[BOLT][NFC] Fix braces usage in Profile

Summary:
Refactor bolt/*/Profile to follow the braces rule for if/else/loop from
[LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html).

(cherry picked from FBD33345741)
This commit is contained in:
Amir Ayupov 2021-12-28 18:29:54 -08:00 committed by Maksim Panchenko
parent 89ceb77997
commit def464aaae
6 changed files with 133 additions and 216 deletions

View File

@ -230,9 +230,8 @@ BoltAddressTranslation::getFallthroughsInTrace(const BinaryFunction &Func,
To -= Func.getAddress(); To -= Func.getAddress();
auto Iter = Maps.find(Func.getAddress()); auto Iter = Maps.find(Func.getAddress());
if (Iter == Maps.end()) { if (Iter == Maps.end())
return NoneType(); return NoneType();
}
const MapTy &Map = Iter->second; const MapTy &Map = Iter->second;
auto FromIter = Map.upper_bound(From); auto FromIter = Map.upper_bound(From);
@ -261,9 +260,8 @@ BoltAddressTranslation::getFallthroughsInTrace(const BinaryFunction &Func,
} }
++Iter; ++Iter;
while (Iter->second & BRANCHENTRY && Iter != ToIter) { while (Iter->second & BRANCHENTRY && Iter != ToIter)
++Iter; ++Iter;
}
if (Iter->second & BRANCHENTRY) if (Iter->second & BRANCHENTRY)
break; break;
Res.emplace_back(Src, Iter->first); Res.emplace_back(Src, Iter->first);

View File

@ -122,17 +122,15 @@ DataAggregator::~DataAggregator() { deleteTempFiles(); }
namespace { namespace {
void deleteTempFile(const std::string &FileName) { void deleteTempFile(const std::string &FileName) {
if (std::error_code Errc = sys::fs::remove(FileName.c_str())) { if (std::error_code Errc = sys::fs::remove(FileName.c_str()))
errs() << "PERF2BOLT: failed to delete temporary file " << FileName errs() << "PERF2BOLT: failed to delete temporary file " << FileName
<< " with error " << Errc.message() << "\n"; << " with error " << Errc.message() << "\n";
}
} }
} }
void DataAggregator::deleteTempFiles() { void DataAggregator::deleteTempFiles() {
for (std::string &FileName : TempFiles) { for (std::string &FileName : TempFiles)
deleteTempFile(FileName); deleteTempFile(FileName);
}
TempFiles.clear(); TempFiles.clear();
} }
@ -155,17 +153,16 @@ void DataAggregator::start() {
findPerfExecutable(); findPerfExecutable();
if (opts::BasicAggregation) { if (opts::BasicAggregation)
launchPerfProcess("events without LBR", launchPerfProcess("events without LBR",
MainEventsPPI, MainEventsPPI,
"script -F pid,event,ip", "script -F pid,event,ip",
/*Wait = */false); /*Wait = */false);
} else { else
launchPerfProcess("branch events", launchPerfProcess("branch events",
MainEventsPPI, MainEventsPPI,
"script -F pid,ip,brstack", "script -F pid,ip,brstack",
/*Wait = */false); /*Wait = */false);
}
// Note: we launch script for mem events regardless of the option, as the // Note: we launch script for mem events regardless of the option, as the
// command fails fairly fast if mem events were not collected. // command fails fairly fast if mem events were not collected.
@ -253,13 +250,12 @@ void DataAggregator::launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
<< "\n"; << "\n";
}); });
if (Wait) { if (Wait)
PPI.PI.ReturnCode = sys::ExecuteAndWait(PerfPath.data(), Argv, PPI.PI.ReturnCode = sys::ExecuteAndWait(PerfPath.data(), Argv,
/*envp*/ llvm::None, Redirects); /*envp*/ llvm::None, Redirects);
} else { else
PPI.PI = sys::ExecuteNoWait(PerfPath.data(), Argv, /*envp*/ llvm::None, PPI.PI = sys::ExecuteNoWait(PerfPath.data(), Argv, /*envp*/ llvm::None,
Redirects); Redirects);
}
free(WritableArgsString); free(WritableArgsString);
} }
@ -307,9 +303,8 @@ void DataAggregator::processFileBuildID(StringRef FileBuildID) {
"is not the same recorded by perf when collecting profiling " "is not the same recorded by perf when collecting profiling "
"data, or there were no samples recorded for the binary. " "data, or there were no samples recorded for the binary. "
"Use -ignore-build-id option to override.\n"; "Use -ignore-build-id option to override.\n";
if (!opts::IgnoreBuildID) { if (!opts::IgnoreBuildID)
abort(); abort();
}
} else if (*FileName != llvm::sys::path::filename(BC->getFilename())) { } else if (*FileName != llvm::sys::path::filename(BC->getFilename())) {
errs() << "PERF2BOLT-WARNING: build-id matched a different file name\n"; errs() << "PERF2BOLT-WARNING: build-id matched a different file name\n";
BuildIDBinaryName = std::string(*FileName); BuildIDBinaryName = std::string(*FileName);
@ -446,10 +441,10 @@ void DataAggregator::filterBinaryMMapInfo() {
<< " for binary \"" << BC->getFilename() << "\"."; << " for binary \"" << BC->getFilename() << "\".";
assert(!BinaryMMapInfo.empty() && "No memory map for matching binary"); assert(!BinaryMMapInfo.empty() && "No memory map for matching binary");
errs() << " Profile for the following process is available:\n"; errs() << " Profile for the following process is available:\n";
for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo) { for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo)
outs() << " " << MMI.second.PID outs() << " " << MMI.second.PID
<< (MMI.second.Forked ? " (forked)\n" : "\n"); << (MMI.second.Forked ? " (forked)\n" : "\n");
}
if (errs().has_colors()) if (errs().has_colors())
errs().resetColor(); errs().resetColor();
@ -529,15 +524,13 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
opts::IgnoreInterruptLBR = false; opts::IgnoreInterruptLBR = false;
} else { } else {
prepareToParse("mmap events", MMapEventsPPI); prepareToParse("mmap events", MMapEventsPPI);
if (parseMMapEvents()) { if (parseMMapEvents())
errs() << "PERF2BOLT: failed to parse mmap events\n"; errs() << "PERF2BOLT: failed to parse mmap events\n";
} }
}
prepareToParse("task events", TaskEventsPPI); prepareToParse("task events", TaskEventsPPI);
if (parseTaskEvents()) { if (parseTaskEvents())
errs() << "PERF2BOLT: failed to parse task events\n"; errs() << "PERF2BOLT: failed to parse task events\n";
}
filterBinaryMMapInfo(); filterBinaryMMapInfo();
prepareToParse("events", MainEventsPPI); prepareToParse("events", MainEventsPPI);
@ -551,15 +544,14 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
} }
if ((!opts::BasicAggregation && parseBranchEvents()) || if ((!opts::BasicAggregation && parseBranchEvents()) ||
(opts::BasicAggregation && parseBasicEvents())) { (opts::BasicAggregation && parseBasicEvents()))
errs() << "PERF2BOLT: failed to parse samples\n"; errs() << "PERF2BOLT: failed to parse samples\n";
}
// We can finish early if the goal is just to generate data for autofdo // We can finish early if the goal is just to generate data for autofdo
if (opts::WriteAutoFDOData) { if (opts::WriteAutoFDOData) {
if (std::error_code EC = writeAutoFDOData(opts::OutputFilename)) { if (std::error_code EC = writeAutoFDOData(opts::OutputFilename))
errs() << "Error writing autofdo data to file: " << EC.message() << "\n"; errs() << "Error writing autofdo data to file: " << EC.message() << "\n";
}
deleteTempFiles(); deleteTempFiles();
exit(0); exit(0);
} }
@ -597,10 +589,9 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
ParsingBuf = FileBuf->getBuffer(); ParsingBuf = FileBuf->getBuffer();
Col = 0; Col = 0;
Line = 1; Line = 1;
if (const std::error_code EC = parseMemEvents()) { if (const std::error_code EC = parseMemEvents())
errs() << "PERF2BOLT: failed to parse memory events: " << EC.message() errs() << "PERF2BOLT: failed to parse memory events: " << EC.message()
<< '\n'; << '\n';
}
deleteTempFiles(); deleteTempFiles();
@ -616,10 +607,9 @@ Error DataAggregator::readProfile(BinaryContext &BC) {
} }
if (opts::AggregateOnly) { if (opts::AggregateOnly) {
if (std::error_code EC = writeAggregatedFile(opts::OutputFilename)) { if (std::error_code EC = writeAggregatedFile(opts::OutputFilename))
report_error("cannot create output data file", EC); report_error("cannot create output data file", EC);
} }
}
return Error::success(); return Error::success();
} }
@ -844,10 +834,9 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
<< FromFunc->getPrintName() << ":" << FromFunc->getPrintName() << ":"
<< Twine::utohexstr(First.To) << " to " << Twine::utohexstr(First.To) << " to "
<< Twine::utohexstr(Second.From) << ".\n"); << Twine::utohexstr(Second.From) << ".\n");
for (const std::pair<uint64_t, uint64_t> &Pair : *FTs) { for (const std::pair<uint64_t, uint64_t> &Pair : *FTs)
doIntraBranch(*FromFunc, Pair.first + FromFunc->getAddress(), doIntraBranch(*FromFunc, Pair.first + FromFunc->getAddress(),
Pair.second + FromFunc->getAddress(), Count, false); Pair.second + FromFunc->getAddress(), Count, false);
}
return true; return true;
} }
@ -885,12 +874,11 @@ bool DataAggregator::recordTrace(
BinaryBasicBlock *PrevBB = BF.BasicBlocksLayout[FromBB->getIndex() - 1]; BinaryBasicBlock *PrevBB = BF.BasicBlocksLayout[FromBB->getIndex() - 1];
if (PrevBB->getSuccessor(FromBB->getLabel())) { if (PrevBB->getSuccessor(FromBB->getLabel())) {
const MCInst *Instr = PrevBB->getLastNonPseudoInstr(); const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
if (Instr && BC.MIB->isCall(*Instr)) { if (Instr && BC.MIB->isCall(*Instr))
FromBB = PrevBB; FromBB = PrevBB;
} else { else
LLVM_DEBUG(dbgs() << "invalid incoming LBR (no call): " << FirstLBR LLVM_DEBUG(dbgs() << "invalid incoming LBR (no call): " << FirstLBR
<< '\n'); << '\n');
}
} else { } else {
LLVM_DEBUG(dbgs() << "invalid incoming LBR: " << FirstLBR << '\n'); LLVM_DEBUG(dbgs() << "invalid incoming LBR: " << FirstLBR << '\n');
} }
@ -899,9 +887,8 @@ bool DataAggregator::recordTrace(
// Fill out information for fall-through edges. The From and To could be // Fill out information for fall-through edges. The From and To could be
// within the same basic block, e.g. when two call instructions are in the // within the same basic block, e.g. when two call instructions are in the
// same block. In this case we skip the processing. // same block. In this case we skip the processing.
if (FromBB == ToBB) { if (FromBB == ToBB)
return true; return true;
}
// Process blocks in the original layout order. // Process blocks in the original layout order.
BinaryBasicBlock *BB = BF.BasicBlocksLayout[FromBB->getIndex()]; BinaryBasicBlock *BB = BF.BasicBlocksLayout[FromBB->getIndex()];
@ -925,11 +912,11 @@ bool DataAggregator::recordTrace(
if (Branches) { if (Branches) {
const MCInst *Instr = BB->getLastNonPseudoInstr(); const MCInst *Instr = BB->getLastNonPseudoInstr();
uint64_t Offset = 0; uint64_t Offset = 0;
if (Instr) { if (Instr)
Offset = BC.MIB->getAnnotationWithDefault<uint32_t>(*Instr, "Offset"); Offset = BC.MIB->getAnnotationWithDefault<uint32_t>(*Instr, "Offset");
} else { else
Offset = BB->getOffset(); Offset = BB->getOffset();
}
Branches->emplace_back(Offset, NextBB->getOffset()); Branches->emplace_back(Offset, NextBB->getOffset());
} }
@ -1039,9 +1026,9 @@ ErrorOr<LBREntry> DataAggregator::parseLBREntry() {
} }
bool DataAggregator::checkAndConsumeFS() { bool DataAggregator::checkAndConsumeFS() {
if (ParsingBuf[0] != FieldSeparator) { if (ParsingBuf[0] != FieldSeparator)
return false; return false;
}
ParsingBuf = ParsingBuf.drop_front(1); ParsingBuf = ParsingBuf.drop_front(1);
Col += 1; Col += 1;
return true; return true;
@ -1128,9 +1115,8 @@ ErrorOr<DataAggregator::PerfBasicSample> DataAggregator::parseBasicSample() {
} }
ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator, true); ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator, true);
if (std::error_code EC = AddrRes.getError()) { if (std::error_code EC = AddrRes.getError())
return EC; return EC;
}
if (!checkAndConsumeNewLine()) { if (!checkAndConsumeNewLine()) {
reportError("expected end of line"); reportError("expected end of line");
@ -1175,9 +1161,8 @@ ErrorOr<DataAggregator::PerfMemSample> DataAggregator::parseMemSample() {
} }
ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator); ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator);
if (std::error_code EC = AddrRes.getError()) { if (std::error_code EC = AddrRes.getError())
return EC; return EC;
}
while (checkAndConsumeFS()) { while (checkAndConsumeFS()) {
} }
@ -1363,11 +1348,10 @@ std::error_code DataAggregator::printLBRHeatMap() {
} }
HM.print(opts::HeatmapFile); HM.print(opts::HeatmapFile);
if (opts::HeatmapFile == "-") { if (opts::HeatmapFile == "-")
HM.printCDF(opts::HeatmapFile); HM.printCDF(opts::HeatmapFile);
} else { else
HM.printCDF(opts::HeatmapFile + ".csv"); HM.printCDF(opts::HeatmapFile + ".csv");
}
return std::error_code(); return std::error_code();
} }
@ -1432,11 +1416,10 @@ std::error_code DataAggregator::parseBranchEvents() {
getBinaryFunctionContainingAddress(TraceFrom); getBinaryFunctionContainingAddress(TraceFrom);
if (TraceBF && TraceBF->containsAddress(TraceTo)) { if (TraceBF && TraceBF->containsAddress(TraceTo)) {
FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)]; FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
if (TraceBF->containsAddress(LBR.From)) { if (TraceBF->containsAddress(LBR.From))
++Info.InternCount; ++Info.InternCount;
} else { else
++Info.ExternCount; ++Info.ExternCount;
}
} else { } else {
if (TraceBF && getBinaryFunctionContainingAddress(TraceTo)) { if (TraceBF && getBinaryFunctionContainingAddress(TraceTo)) {
LLVM_DEBUG(dbgs() LLVM_DEBUG(dbgs()
@ -1497,14 +1480,13 @@ std::error_code DataAggregator::parseBranchEvents() {
auto printColored = [](raw_ostream &OS, float Percent, float T1, float T2) { auto printColored = [](raw_ostream &OS, float Percent, float T1, float T2) {
OS << " ("; OS << " (";
if (OS.has_colors()) { if (OS.has_colors()) {
if (Percent > T2) { if (Percent > T2)
OS.changeColor(raw_ostream::RED); OS.changeColor(raw_ostream::RED);
} else if (Percent > T1) { else if (Percent > T1)
OS.changeColor(raw_ostream::YELLOW); OS.changeColor(raw_ostream::YELLOW);
} else { else
OS.changeColor(raw_ostream::GREEN); OS.changeColor(raw_ostream::GREEN);
} }
}
OS << format("%.1f%%", Percent); OS << format("%.1f%%", Percent);
if (OS.has_colors()) if (OS.has_colors())
OS.resetColor(); OS.resetColor();
@ -1527,12 +1509,11 @@ std::error_code DataAggregator::parseBranchEvents() {
outs() << "PERF2BOLT: " << IgnoredSamples << " samples"; outs() << "PERF2BOLT: " << IgnoredSamples << " samples";
printColored(outs(), PercentIgnored, 20, 50); printColored(outs(), PercentIgnored, 20, 50);
outs() << " were ignored\n"; outs() << " were ignored\n";
if (PercentIgnored > 50.0f) { if (PercentIgnored > 50.0f)
errs() << "PERF2BOLT-WARNING: less than 50% of all recorded samples " errs() << "PERF2BOLT-WARNING: less than 50% of all recorded samples "
"were attributed to the input binary\n"; "were attributed to the input binary\n";
} }
} }
}
outs() << "PERF2BOLT: traces mismatching disassembled function contents: " outs() << "PERF2BOLT: traces mismatching disassembled function contents: "
<< NumInvalidTraces; << NumInvalidTraces;
float Perc = 0.0f; float Perc = 0.0f;
@ -1541,18 +1522,16 @@ std::error_code DataAggregator::parseBranchEvents() {
printColored(outs(), Perc, 5, 10); printColored(outs(), Perc, 5, 10);
} }
outs() << "\n"; outs() << "\n";
if (Perc > 10.0f) { if (Perc > 10.0f)
outs() << "\n !! WARNING !! This high mismatch ratio indicates the input " outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
"binary is probably not the same binary used during profiling " "binary is probably not the same binary used during profiling "
"collection. The generated data may be ineffective for improving " "collection. The generated data may be ineffective for improving "
"performance.\n\n"; "performance.\n\n";
}
outs() << "PERF2BOLT: out of range traces involving unknown regions: " outs() << "PERF2BOLT: out of range traces involving unknown regions: "
<< NumLongRangeTraces; << NumLongRangeTraces;
if (NumTraces > 0) { if (NumTraces > 0)
outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces); outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces);
}
outs() << "\n"; outs() << "\n";
if (NumColdSamples > 0) { if (NumColdSamples > 0) {
@ -1560,13 +1539,12 @@ std::error_code DataAggregator::parseBranchEvents() {
outs() << "PERF2BOLT: " << NumColdSamples outs() << "PERF2BOLT: " << NumColdSamples
<< format(" (%.1f%%)", ColdSamples) << format(" (%.1f%%)", ColdSamples)
<< " samples recorded in cold regions of split functions.\n"; << " samples recorded in cold regions of split functions.\n";
if (ColdSamples > 5.0f) { if (ColdSamples > 5.0f)
outs() outs()
<< "WARNING: The BOLT-processed binary where samples were collected " << "WARNING: The BOLT-processed binary where samples were collected "
"likely used bad data or your service observed a large shift in " "likely used bad data or your service observed a large shift in "
"profile. You may want to audit this.\n"; "profile. You may want to audit this.\n";
} }
}
return std::error_code(); return std::error_code();
} }
@ -1581,9 +1559,8 @@ void DataAggregator::processBranchEvents() {
const FTInfo &Info = AggrLBR.second; const FTInfo &Info = AggrLBR.second;
LBREntry First{Loc.From, Loc.From, false}; LBREntry First{Loc.From, Loc.From, false};
LBREntry Second{Loc.To, Loc.To, false}; LBREntry Second{Loc.To, Loc.To, false};
if (Info.InternCount) { if (Info.InternCount)
doTrace(First, Second, Info.InternCount); doTrace(First, Second, Info.InternCount);
}
if (Info.ExternCount) { if (Info.ExternCount) {
First.From = 0; First.From = 0;
doTrace(First, Second, Info.ExternCount); doTrace(First, Second, Info.ExternCount);
@ -1646,26 +1623,24 @@ void DataAggregator::processBasicEvents() {
outs() << " ("; outs() << " (";
Perc = OutOfRangeSamples * 100.0f / NumSamples; Perc = OutOfRangeSamples * 100.0f / NumSamples;
if (outs().has_colors()) { if (outs().has_colors()) {
if (Perc > 60.0f) { if (Perc > 60.0f)
outs().changeColor(raw_ostream::RED); outs().changeColor(raw_ostream::RED);
} else if (Perc > 40.0f) { else if (Perc > 40.0f)
outs().changeColor(raw_ostream::YELLOW); outs().changeColor(raw_ostream::YELLOW);
} else { else
outs().changeColor(raw_ostream::GREEN); outs().changeColor(raw_ostream::GREEN);
} }
}
outs() << format("%.1f%%", Perc); outs() << format("%.1f%%", Perc);
if (outs().has_colors()) if (outs().has_colors())
outs().resetColor(); outs().resetColor();
outs() << ")"; outs() << ")";
} }
outs() << "\n"; outs() << "\n";
if (Perc > 80.0f) { if (Perc > 80.0f)
outs() << "\n !! WARNING !! This high mismatch ratio indicates the input " outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
"binary is probably not the same binary used during profiling " "binary is probably not the same binary used during profiling "
"collection. The generated data may be ineffective for improving " "collection. The generated data may be ineffective for improving "
"performance.\n\n"; "performance.\n\n";
}
} }
std::error_code DataAggregator::parseMemEvents() { std::error_code DataAggregator::parseMemEvents() {
@ -1784,32 +1759,29 @@ void DataAggregator::processPreAggregated() {
outs() << " ("; outs() << " (";
Perc = NumInvalidTraces * 100.0f / NumTraces; Perc = NumInvalidTraces * 100.0f / NumTraces;
if (outs().has_colors()) { if (outs().has_colors()) {
if (Perc > 10.0f) { if (Perc > 10.0f)
outs().changeColor(raw_ostream::RED); outs().changeColor(raw_ostream::RED);
} else if (Perc > 5.0f) { else if (Perc > 5.0f)
outs().changeColor(raw_ostream::YELLOW); outs().changeColor(raw_ostream::YELLOW);
} else { else
outs().changeColor(raw_ostream::GREEN); outs().changeColor(raw_ostream::GREEN);
} }
}
outs() << format("%.1f%%", Perc); outs() << format("%.1f%%", Perc);
if (outs().has_colors()) if (outs().has_colors())
outs().resetColor(); outs().resetColor();
outs() << ")"; outs() << ")";
} }
outs() << "\n"; outs() << "\n";
if (Perc > 10.0f) { if (Perc > 10.0f)
outs() << "\n !! WARNING !! This high mismatch ratio indicates the input " outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
"binary is probably not the same binary used during profiling " "binary is probably not the same binary used during profiling "
"collection. The generated data may be ineffective for improving " "collection. The generated data may be ineffective for improving "
"performance.\n\n"; "performance.\n\n";
}
outs() << "PERF2BOLT: Out of range traces involving unknown regions: " outs() << "PERF2BOLT: Out of range traces involving unknown regions: "
<< NumLongRangeTraces; << NumLongRangeTraces;
if (NumTraces > 0) { if (NumTraces > 0)
outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces); outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces);
}
outs() << "\n"; outs() << "\n";
} }
@ -1823,9 +1795,8 @@ Optional<int32_t> DataAggregator::parseCommExecEvent() {
StringRef Line = ParsingBuf.substr(0, LineEnd); StringRef Line = ParsingBuf.substr(0, LineEnd);
size_t Pos = Line.find("PERF_RECORD_COMM exec"); size_t Pos = Line.find("PERF_RECORD_COMM exec");
if (Pos == StringRef::npos) { if (Pos == StringRef::npos)
return NoneType(); return NoneType();
}
Line = Line.drop_front(Pos); Line = Line.drop_front(Pos);
// Line: // Line:
@ -1848,9 +1819,8 @@ Optional<uint64_t> parsePerfTime(const StringRef TimeStr) {
uint64_t SecTime; uint64_t SecTime;
uint64_t USecTime; uint64_t USecTime;
if (SecTimeStr.getAsInteger(10, SecTime) || if (SecTimeStr.getAsInteger(10, SecTime) ||
USecTimeStr.getAsInteger(10, USecTime)) { USecTimeStr.getAsInteger(10, USecTime))
return NoneType(); return NoneType();
}
return SecTime * 1000000ULL + USecTime; return SecTime * 1000000ULL + USecTime;
} }
} }
@ -1930,9 +1900,8 @@ DataAggregator::parseMMapEvent() {
const StringRef TimeStr = const StringRef TimeStr =
Line.substr(0, Pos).rsplit(':').first.rsplit(FieldSeparator).second; Line.substr(0, Pos).rsplit(':').first.rsplit(FieldSeparator).second;
if (Optional<uint64_t> TimeRes = parsePerfTime(TimeStr)) { if (Optional<uint64_t> TimeRes = parsePerfTime(TimeStr))
ParsedInfo.Time = *TimeRes; ParsedInfo.Time = *TimeRes;
}
Line = Line.drop_front(Pos); Line = Line.drop_front(Pos);
@ -2012,12 +1981,11 @@ std::error_code DataAggregator::parseMMapEvents() {
LLVM_DEBUG({ LLVM_DEBUG({
dbgs() << "FileName -> mmap info:\n"; dbgs() << "FileName -> mmap info:\n";
for (const std::pair<const StringRef, MMapInfo> &Pair : GlobalMMapInfo) { for (const std::pair<const StringRef, MMapInfo> &Pair : GlobalMMapInfo)
dbgs() << " " << Pair.first << " : " << Pair.second.PID << " [0x" dbgs() << " " << Pair.first << " : " << Pair.second.PID << " [0x"
<< Twine::utohexstr(Pair.second.BaseAddress) << ", " << Twine::utohexstr(Pair.second.BaseAddress) << ", "
<< Twine::utohexstr(Pair.second.Size) << " @ " << Twine::utohexstr(Pair.second.Size) << " @ "
<< Twine::utohexstr(Pair.second.Offset) << "]\n"; << Twine::utohexstr(Pair.second.Offset) << "]\n";
}
}); });
StringRef NameToUse = llvm::sys::path::filename(BC->getFilename()); StringRef NameToUse = llvm::sys::path::filename(BC->getFilename());
@ -2063,9 +2031,8 @@ std::error_code DataAggregator::parseMMapEvents() {
if (!GlobalMMapInfo.empty()) { if (!GlobalMMapInfo.empty()) {
errs() << " Profile for the following binary name(s) is available:\n"; errs() << " Profile for the following binary name(s) is available:\n";
for (auto I = GlobalMMapInfo.begin(), IE = GlobalMMapInfo.end(); I != IE; for (auto I = GlobalMMapInfo.begin(), IE = GlobalMMapInfo.end(); I != IE;
I = GlobalMMapInfo.upper_bound(I->first)) { I = GlobalMMapInfo.upper_bound(I->first))
errs() << " " << I->first << '\n'; errs() << " " << I->first << '\n';
}
errs() << "Please rename the input binary.\n"; errs() << "Please rename the input binary.\n";
} else { } else {
errs() << " Failed to extract any binary name from a profile.\n"; errs() << " Failed to extract any binary name from a profile.\n";
@ -2088,9 +2055,8 @@ std::error_code DataAggregator::parseTaskEvents() {
if (Optional<int32_t> CommInfo = parseCommExecEvent()) { if (Optional<int32_t> CommInfo = parseCommExecEvent()) {
// Remove forked child that ran execve // Remove forked child that ran execve
auto MMapInfoIter = BinaryMMapInfo.find(*CommInfo); auto MMapInfoIter = BinaryMMapInfo.find(*CommInfo);
if (MMapInfoIter != BinaryMMapInfo.end() && MMapInfoIter->second.Forked) { if (MMapInfoIter != BinaryMMapInfo.end() && MMapInfoIter->second.Forked)
BinaryMMapInfo.erase(MMapInfoIter); BinaryMMapInfo.erase(MMapInfoIter);
}
consumeRestOfLine(); consumeRestOfLine();
continue; continue;
} }
@ -2122,11 +2088,10 @@ std::error_code DataAggregator::parseTaskEvents() {
<< BinaryMMapInfo.size() << " PID(s)\n"; << BinaryMMapInfo.size() << " PID(s)\n";
LLVM_DEBUG({ LLVM_DEBUG({
for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo) { for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo)
outs() << " " << MMI.second.PID << (MMI.second.Forked ? " (forked)" : "") outs() << " " << MMI.second.PID << (MMI.second.Forked ? " (forked)" : "")
<< ": (0x" << Twine::utohexstr(MMI.second.BaseAddress) << ": 0x" << ": (0x" << Twine::utohexstr(MMI.second.BaseAddress) << ": 0x"
<< Twine::utohexstr(MMI.second.Size) << ")\n"; << Twine::utohexstr(MMI.second.Size) << ")\n";
}
}); });
return std::error_code(); return std::error_code();
@ -2187,9 +2152,8 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const {
OutFile << "boltedcollection\n"; OutFile << "boltedcollection\n";
if (opts::BasicAggregation) { if (opts::BasicAggregation) {
OutFile << "no_lbr"; OutFile << "no_lbr";
for (const StringMapEntry<NoneType> &Entry : EventNames) { for (const StringMapEntry<NoneType> &Entry : EventNames)
OutFile << " " << Entry.getKey(); OutFile << " " << Entry.getKey();
}
OutFile << "\n"; OutFile << "\n";
for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) { for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) {
@ -2246,9 +2210,8 @@ void DataAggregator::dump(const LBREntry &LBR) const {
void DataAggregator::dump(const PerfBranchSample &Sample) const { void DataAggregator::dump(const PerfBranchSample &Sample) const {
Diag << "Sample LBR entries: " << Sample.LBR.size() << "\n"; Diag << "Sample LBR entries: " << Sample.LBR.size() << "\n";
for (const LBREntry &LBR : Sample.LBR) { for (const LBREntry &LBR : Sample.LBR)
dump(LBR); dump(LBR);
}
} }
void DataAggregator::dump(const PerfMemSample &Sample) const { void DataAggregator::dump(const PerfMemSample &Sample) const {

View File

@ -42,23 +42,21 @@ namespace bolt {
Optional<StringRef> getLTOCommonName(const StringRef Name) { Optional<StringRef> getLTOCommonName(const StringRef Name) {
size_t LTOSuffixPos = Name.find(".lto_priv."); size_t LTOSuffixPos = Name.find(".lto_priv.");
if (LTOSuffixPos != StringRef::npos) { if (LTOSuffixPos != StringRef::npos)
return Name.substr(0, LTOSuffixPos + 10); return Name.substr(0, LTOSuffixPos + 10);
} else if ((LTOSuffixPos = Name.find(".constprop.")) != StringRef::npos) { if ((LTOSuffixPos = Name.find(".constprop.")) != StringRef::npos)
return Name.substr(0, LTOSuffixPos + 11); return Name.substr(0, LTOSuffixPos + 11);
} else {
return NoneType(); return NoneType();
}
} }
namespace { namespace {
/// Return true if the function name can change across compilations. /// Return true if the function name can change across compilations.
bool hasVolatileName(const BinaryFunction &BF) { bool hasVolatileName(const BinaryFunction &BF) {
for (const StringRef Name : BF.getNames()) { for (const StringRef Name : BF.getNames())
if (getLTOCommonName(Name)) if (getLTOCommonName(Name))
return true; return true;
}
return false; return false;
} }
@ -134,9 +132,8 @@ uint64_t FuncSampleData::getSamples(uint64_t Start, uint64_t End) const {
uint64_t Result = 0; uint64_t Result = 0;
for (auto I = std::lower_bound(Data.begin(), Data.end(), Start, Compare()), for (auto I = std::lower_bound(Data.begin(), Data.end(), Start, Compare()),
E = std::lower_bound(Data.begin(), Data.end(), End, Compare()); E = std::lower_bound(Data.begin(), Data.end(), End, Compare());
I != E; ++I) { I != E; ++I)
Result += I->Hits; Result += I->Hits;
}
return Result; return Result;
} }
@ -206,10 +203,10 @@ void BranchInfo::print(raw_ostream &OS) const {
ErrorOr<const BranchInfo &> FuncBranchData::getBranch(uint64_t From, ErrorOr<const BranchInfo &> FuncBranchData::getBranch(uint64_t From,
uint64_t To) const { uint64_t To) const {
for (const BranchInfo &I : Data) { for (const BranchInfo &I : Data)
if (I.From.Offset == From && I.To.Offset == To && I.From.Name == I.To.Name) if (I.From.Offset == From && I.To.Offset == To && I.From.Name == I.To.Name)
return I; return I;
}
return make_error_code(llvm::errc::invalid_argument); return make_error_code(llvm::errc::invalid_argument);
} }
@ -226,10 +223,10 @@ FuncBranchData::getDirectCallBranch(uint64_t From) const {
} }
}; };
auto Range = std::equal_range(Data.begin(), Data.end(), From, Compare()); auto Range = std::equal_range(Data.begin(), Data.end(), From, Compare());
for (auto I = Range.first; I != Range.second; ++I) { for (auto I = Range.first; I != Range.second; ++I)
if (I->From.Name != I->To.Name) if (I->From.Name != I->To.Name)
return *I; return *I;
}
return make_error_code(llvm::errc::invalid_argument); return make_error_code(llvm::errc::invalid_argument);
} }
@ -255,18 +252,15 @@ void FuncMemData::update(const Location &Offset, const Location &Addr) {
} }
Error DataReader::preprocessProfile(BinaryContext &BC) { Error DataReader::preprocessProfile(BinaryContext &BC) {
if (std::error_code EC = parseInput()) { if (std::error_code EC = parseInput())
return errorCodeToError(EC); return errorCodeToError(EC);
}
if (opts::DumpData) { if (opts::DumpData)
dump(); dump();
}
if (collectedInBoltedBinary()) { if (collectedInBoltedBinary())
outs() << "BOLT-INFO: profile collection done on a binary already " outs() << "BOLT-INFO: profile collection done on a binary already "
"processed by BOLT\n"; "processed by BOLT\n";
}
for (auto &BFI : BC.getBinaryFunctions()) { for (auto &BFI : BC.getBinaryFunctions()) {
BinaryFunction &Function = BFI.second; BinaryFunction &Function = BFI.second;
@ -308,18 +302,16 @@ Error DataReader::readProfilePreCFG(BinaryContext &BC) {
BC.MIB->getOrCreateAnnotationAs<MemoryAccessProfile>( BC.MIB->getOrCreateAnnotationAs<MemoryAccessProfile>(
II->second, "MemoryAccessProfile"); II->second, "MemoryAccessProfile");
BinaryData *BD = nullptr; BinaryData *BD = nullptr;
if (MI.Addr.IsSymbol) { if (MI.Addr.IsSymbol)
BD = BC.getBinaryDataByName(MI.Addr.Name); BD = BC.getBinaryDataByName(MI.Addr.Name);
}
MemAccessProfile.AddressAccessInfo.push_back( MemAccessProfile.AddressAccessInfo.push_back(
{BD, MI.Addr.Offset, MI.Count}); {BD, MI.Addr.Offset, MI.Count});
auto NextII = std::next(II); auto NextII = std::next(II);
if (NextII == Function.Instructions.end()) { if (NextII == Function.Instructions.end())
MemAccessProfile.NextInstrOffset = Function.getSize(); MemAccessProfile.NextInstrOffset = Function.getSize();
} else { else
MemAccessProfile.NextInstrOffset = II->first; MemAccessProfile.NextInstrOffset = II->first;
} }
}
Function.HasMemoryProfile = true; Function.HasMemoryProfile = true;
} }
@ -350,13 +342,11 @@ std::error_code DataReader::parseInput() {
} }
FileBuf = std::move(MB.get()); FileBuf = std::move(MB.get());
ParsingBuf = FileBuf->getBuffer(); ParsingBuf = FileBuf->getBuffer();
if (std::error_code EC = parse()) { if (std::error_code EC = parse())
return EC; return EC;
} if (!ParsingBuf.empty())
if (!ParsingBuf.empty()) {
Diag << "WARNING: invalid profile data detected at line " << Line Diag << "WARNING: invalid profile data detected at line " << Line
<< ". Possibly corrupted profile.\n"; << ". Possibly corrupted profile.\n";
}
buildLTONameMaps(); buildLTONameMaps();
@ -401,9 +391,8 @@ void DataReader::readProfile(BinaryFunction &BF) {
uint64_t MismatchedBranches = 0; uint64_t MismatchedBranches = 0;
for (const BranchInfo &BI : FBD->Data) { for (const BranchInfo &BI : FBD->Data) {
if (BI.From.Name != BI.To.Name) { if (BI.From.Name != BI.To.Name)
continue; continue;
}
if (!recordBranch(BF, BI.From.Offset, BI.To.Offset, BI.Branches, if (!recordBranch(BF, BI.From.Offset, BI.To.Offset, BI.Branches,
BI.Mispreds)) { BI.Mispreds)) {
@ -523,9 +512,8 @@ float DataReader::evaluateProfileData(BinaryFunction &BF,
// Until we define a minimal profile, we consider an empty branch data to be // Until we define a minimal profile, we consider an empty branch data to be
// a valid profile. It could happen to a function without branches when we // a valid profile. It could happen to a function without branches when we
// still have an EntryData for the execution count. // still have an EntryData for the execution count.
if (BranchData.Data.empty()) { if (BranchData.Data.empty())
return 1.0f; return 1.0f;
}
uint64_t NumMatchedBranches = 0; uint64_t NumMatchedBranches = 0;
for (const BranchInfo &BI : BranchData.Data) { for (const BranchInfo &BI : BranchData.Data) {
@ -549,10 +537,9 @@ float DataReader::evaluateProfileData(BinaryFunction &BF,
if (Instr && BC.MIB->isPrefix(*Instr)) if (Instr && BC.MIB->isPrefix(*Instr))
Instr = BF.getInstructionAtOffset(BI.From.Offset + 1); Instr = BF.getInstructionAtOffset(BI.From.Offset + 1);
if (Instr && (BC.MIB->isCall(*Instr) || BC.MIB->isBranch(*Instr) || if (Instr && (BC.MIB->isCall(*Instr) || BC.MIB->isBranch(*Instr) ||
BC.MIB->isReturn(*Instr))) { BC.MIB->isReturn(*Instr)))
IsValid = true; IsValid = true;
} }
}
if (IsValid) { if (IsValid) {
++NumMatchedBranches; ++NumMatchedBranches;
@ -567,12 +554,11 @@ float DataReader::evaluateProfileData(BinaryFunction &BF,
} }
const float MatchRatio = (float)NumMatchedBranches / BranchData.Data.size(); const float MatchRatio = (float)NumMatchedBranches / BranchData.Data.size();
if (opts::Verbosity >= 2 && NumMatchedBranches < BranchData.Data.size()) { if (opts::Verbosity >= 2 && NumMatchedBranches < BranchData.Data.size())
errs() << "BOLT-WARNING: profile branches match only " errs() << "BOLT-WARNING: profile branches match only "
<< format("%.1f%%", MatchRatio * 100.0f) << " (" << format("%.1f%%", MatchRatio * 100.0f) << " ("
<< NumMatchedBranches << '/' << BranchData.Data.size() << NumMatchedBranches << '/' << BranchData.Data.size()
<< ") for function " << BF << '\n'; << ") for function " << BF << '\n';
}
return MatchRatio; return MatchRatio;
} }
@ -592,11 +578,11 @@ void DataReader::readSampleData(BinaryFunction &BF) {
if (NagUser) { if (NagUser) {
outs() outs()
<< "BOLT-INFO: operating with basic samples profiling data (no LBR).\n"; << "BOLT-INFO: operating with basic samples profiling data (no LBR).\n";
if (NormalizeByInsnCount) { if (NormalizeByInsnCount)
outs() << "BOLT-INFO: normalizing samples by instruction count.\n"; outs() << "BOLT-INFO: normalizing samples by instruction count.\n";
} else if (NormalizeByCalls) { else if (NormalizeByCalls)
outs() << "BOLT-INFO: normalizing samples by branches.\n"; outs() << "BOLT-INFO: normalizing samples by branches.\n";
}
NagUser = false; NagUser = false;
} }
uint64_t LastOffset = BF.getSize(); uint64_t LastOffset = BF.getSize();
@ -608,9 +594,9 @@ void DataReader::readSampleData(BinaryFunction &BF) {
// later need to normalize numbers // later need to normalize numbers
uint64_t NumSamples = uint64_t NumSamples =
SampleDataOrErr->getSamples(CurOffset, LastOffset) * 1000; SampleDataOrErr->getSamples(CurOffset, LastOffset) * 1000;
if (NormalizeByInsnCount && I->second->getNumNonPseudos()) if (NormalizeByInsnCount && I->second->getNumNonPseudos()) {
NumSamples /= I->second->getNumNonPseudos(); NumSamples /= I->second->getNumNonPseudos();
else if (NormalizeByCalls) { } else if (NormalizeByCalls) {
uint32_t NumCalls = I->second->getNumCalls(); uint32_t NumCalls = I->second->getNumCalls();
NumSamples /= NumCalls + 1; NumSamples /= NumCalls + 1;
} }
@ -655,11 +641,10 @@ void DataReader::convertBranchData(BinaryFunction &BF) const {
continue; continue;
auto setOrUpdateAnnotation = [&](StringRef Name, uint64_t Count) { auto setOrUpdateAnnotation = [&](StringRef Name, uint64_t Count) {
if (opts::Verbosity >= 1 && BC.MIB->hasAnnotation(*Instr, Name)) { if (opts::Verbosity >= 1 && BC.MIB->hasAnnotation(*Instr, Name))
errs() << "BOLT-WARNING: duplicate " << Name << " info for offset 0x" errs() << "BOLT-WARNING: duplicate " << Name << " info for offset 0x"
<< Twine::utohexstr(BI.From.Offset) << " in function " << BF << Twine::utohexstr(BI.From.Offset) << " in function " << BF
<< '\n'; << '\n';
}
auto &Value = BC.MIB->getOrCreateAnnotationAs<uint64_t>(*Instr, Name); auto &Value = BC.MIB->getOrCreateAnnotationAs<uint64_t>(*Instr, Name);
Value += Count; Value += Count;
}; };
@ -670,10 +655,9 @@ void DataReader::convertBranchData(BinaryFunction &BF) const {
*Instr, "CallProfile"); *Instr, "CallProfile");
MCSymbol *CalleeSymbol = nullptr; MCSymbol *CalleeSymbol = nullptr;
if (BI.To.IsSymbol) { if (BI.To.IsSymbol) {
if (BinaryData *BD = BC.getBinaryDataByName(BI.To.Name)) { if (BinaryData *BD = BC.getBinaryDataByName(BI.To.Name))
CalleeSymbol = BD->getSymbol(); CalleeSymbol = BD->getSymbol();
} }
}
CSP.emplace_back(CalleeSymbol, BI.Branches, BI.Mispreds); CSP.emplace_back(CalleeSymbol, BI.Branches, BI.Mispreds);
} else if (BC.MIB->getConditionalTailCall(*Instr)) { } else if (BC.MIB->getConditionalTailCall(*Instr)) {
setOrUpdateAnnotation("CTCTakenCount", BI.Branches); setOrUpdateAnnotation("CTCTakenCount", BI.Branches);
@ -701,20 +685,18 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
// BBs as a result of optimizations. In that case, a branch between these // BBs as a result of optimizations. In that case, a branch between these
// two will be recorded as a branch from A going to A in the source address // two will be recorded as a branch from A going to A in the source address
// space. Keep processing. // space. Keep processing.
if (From == To) { if (From == To)
return true; return true;
}
// Return from a tail call. // Return from a tail call.
if (FromBB->succ_size() == 0) if (FromBB->succ_size() == 0)
return true; return true;
// Very rarely we will see ignored branches. Do a linear check. // Very rarely we will see ignored branches. Do a linear check.
for (std::pair<uint32_t, uint32_t> &Branch : BF.IgnoredBranches) { for (std::pair<uint32_t, uint32_t> &Branch : BF.IgnoredBranches)
if (Branch == if (Branch ==
std::make_pair(static_cast<uint32_t>(From), static_cast<uint32_t>(To))) std::make_pair(static_cast<uint32_t>(From), static_cast<uint32_t>(To)))
return true; return true;
}
bool OffsetMatches = !!(To == ToBB->getOffset()); bool OffsetMatches = !!(To == ToBB->getOffset());
if (!OffsetMatches) { if (!OffsetMatches) {
@ -742,9 +724,8 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
BC.MIB->getAnnotationWithDefault<uint32_t>(*LastInstr, "Offset"); BC.MIB->getAnnotationWithDefault<uint32_t>(*LastInstr, "Offset");
// With old .fdata we are getting FT branches for "jcc,jmp" sequences. // With old .fdata we are getting FT branches for "jcc,jmp" sequences.
if (To == LastInstrOffset && BC.MIB->isUnconditionalBranch(*LastInstr)) { if (To == LastInstrOffset && BC.MIB->isUnconditionalBranch(*LastInstr))
return true; return true;
}
if (To <= LastInstrOffset) { if (To <= LastInstrOffset) {
LLVM_DEBUG(dbgs() << "branch recorded into the middle of the block" LLVM_DEBUG(dbgs() << "branch recorded into the middle of the block"
@ -1163,15 +1144,13 @@ std::error_code DataReader::parseInNoLBRMode() {
I->getValue().Data.emplace_back(std::move(MI)); I->getValue().Data.emplace_back(std::move(MI));
} }
for (StringMapEntry<FuncSampleData> &FuncSamples : NamesToSamples) { for (StringMapEntry<FuncSampleData> &FuncSamples : NamesToSamples)
std::stable_sort(FuncSamples.second.Data.begin(), std::stable_sort(FuncSamples.second.Data.begin(),
FuncSamples.second.Data.end()); FuncSamples.second.Data.end());
}
for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents) { for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents)
std::stable_sort(MemEvents.second.Data.begin(), std::stable_sort(MemEvents.second.Data.begin(),
MemEvents.second.Data.end()); MemEvents.second.Data.end());
}
return std::error_code(); return std::error_code();
} }
@ -1266,15 +1245,13 @@ std::error_code DataReader::parse() {
I->getValue().Data.emplace_back(std::move(MI)); I->getValue().Data.emplace_back(std::move(MI));
} }
for (StringMapEntry<FuncBranchData> &FuncBranches : NamesToBranches) { for (StringMapEntry<FuncBranchData> &FuncBranches : NamesToBranches)
std::stable_sort(FuncBranches.second.Data.begin(), std::stable_sort(FuncBranches.second.Data.begin(),
FuncBranches.second.Data.end()); FuncBranches.second.Data.end());
}
for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents) { for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents)
std::stable_sort(MemEvents.second.Data.begin(), std::stable_sort(MemEvents.second.Data.begin(),
MemEvents.second.Data.end()); MemEvents.second.Data.end());
}
return std::error_code(); return std::error_code();
} }
@ -1343,11 +1320,10 @@ std::vector<decltype(MapTy::MapEntryTy::second) *> fetchMapEntriesRegex(
} }
} else { } else {
auto I = Map.find(Name); auto I = Map.find(Name);
if (I != Map.end()) { if (I != Map.end())
return {&I->getValue()}; return {&I->getValue()};
} }
} }
}
return AllData; return AllData;
} }
@ -1419,16 +1395,14 @@ bool DataReader::hasLocalsWithFileName() const {
void DataReader::dump() const { void DataReader::dump() const {
for (const StringMapEntry<FuncBranchData> &Func : NamesToBranches) { for (const StringMapEntry<FuncBranchData> &Func : NamesToBranches) {
Diag << Func.getKey() << " branches:\n"; Diag << Func.getKey() << " branches:\n";
for (const BranchInfo &BI : Func.getValue().Data) { for (const BranchInfo &BI : Func.getValue().Data)
Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " " Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " "
<< BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n"; << BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n";
}
Diag << Func.getKey() << " entry points:\n"; Diag << Func.getKey() << " entry points:\n";
for (const BranchInfo &BI : Func.getValue().EntryData) { for (const BranchInfo &BI : Func.getValue().EntryData)
Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " " Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " "
<< BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n"; << BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n";
} }
}
for (auto I = EventNames.begin(), E = EventNames.end(); I != E; ++I) { for (auto I = EventNames.begin(), E = EventNames.end(); I != E; ++I) {
StringRef Event = I->getKey(); StringRef Event = I->getKey();
@ -1436,20 +1410,18 @@ void DataReader::dump() const {
} }
for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) { for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) {
Diag << Func.getKey() << " samples:\n"; Diag << Func.getKey() << " samples:\n";
for (const SampleInfo &SI : Func.getValue().Data) { for (const SampleInfo &SI : Func.getValue().Data)
Diag << SI.Loc.Name << " " << SI.Loc.Offset << " " << SI.Hits << "\n"; Diag << SI.Loc.Name << " " << SI.Loc.Offset << " " << SI.Hits << "\n";
} }
}
for (const StringMapEntry<FuncMemData> &Func : NamesToMemEvents) { for (const StringMapEntry<FuncMemData> &Func : NamesToMemEvents) {
Diag << "Memory events for " << Func.getValue().Name; Diag << "Memory events for " << Func.getValue().Name;
Location LastOffset(0); Location LastOffset(0);
for (const MemInfo &MI : Func.getValue().Data) { for (const MemInfo &MI : Func.getValue().Data) {
if (MI.Offset == LastOffset) { if (MI.Offset == LastOffset)
Diag << ", " << MI.Addr << "/" << MI.Count; Diag << ", " << MI.Addr << "/" << MI.Count;
} else { else
Diag << "\n" << MI.Offset << ": " << MI.Addr << "/" << MI.Count; Diag << "\n" << MI.Offset << ": " << MI.Addr << "/" << MI.Count;
}
LastOffset = MI.Offset; LastOffset = MI.Offset;
} }
Diag << "\n"; Diag << "\n";

View File

@ -41,9 +41,8 @@ void Heatmap::registerAddressRange(uint64_t StartAddress, uint64_t EndAddress,
} }
for (uint64_t Bucket = StartAddress / BucketSize; for (uint64_t Bucket = StartAddress / BucketSize;
Bucket <= EndAddress / BucketSize; ++Bucket) { Bucket <= EndAddress / BucketSize; ++Bucket)
Map[Bucket] += Count; Map[Bucket] += Count;
}
} }
void Heatmap::print(StringRef FileName) const { void Heatmap::print(StringRef FileName) const {
@ -72,9 +71,8 @@ void Heatmap::print(raw_ostream &OS) const {
// Calculate the max value for scaling. // Calculate the max value for scaling.
uint64_t MaxValue = 0; uint64_t MaxValue = 0;
for (const std::pair<const uint64_t, uint64_t> &Entry : Map) { for (const std::pair<const uint64_t, uint64_t> &Entry : Map)
MaxValue = std::max<uint64_t>(MaxValue, Entry.second); MaxValue = std::max<uint64_t>(MaxValue, Entry.second);
}
// Print start of the line and fill it with an empty space right before // Print start of the line and fill it with an empty space right before
// the Address. // the Address.
@ -89,9 +87,8 @@ void Heatmap::print(raw_ostream &OS) const {
if (Empty) if (Empty)
Address = LineAddress + BytesPerLine; Address = LineAddress + BytesPerLine;
for (uint64_t Fill = LineAddress; Fill < Address; Fill += BucketSize) { for (uint64_t Fill = LineAddress; Fill < Address; Fill += BucketSize)
OS << FillChar; OS << FillChar;
}
}; };
// Finish line after \p Address was printed. // Finish line after \p Address was printed.
@ -151,11 +148,11 @@ void Heatmap::print(raw_ostream &OS) const {
break; break;
} }
} }
if (Value <= Range[0]) { if (Value <= Range[0])
OS << 'o'; OS << 'o';
} else { else
OS << 'O'; OS << 'O';
}
if (ResetColor) if (ResetColor)
changeColor(DefaultColor); changeColor(DefaultColor);
}; };
@ -200,11 +197,10 @@ void Heatmap::print(raw_ostream &OS) const {
const std::pair<const uint64_t, uint64_t> &Entry = *MI; const std::pair<const uint64_t, uint64_t> &Entry = *MI;
uint64_t Address = Entry.first * BucketSize; uint64_t Address = Entry.first * BucketSize;
if (PrevAddress) { if (PrevAddress)
fillRange(PrevAddress, Address); fillRange(PrevAddress, Address);
} else { else
startLine(Address); startLine(Address);
}
printValue(Entry.second); printValue(Entry.second);

View File

@ -53,18 +53,15 @@ void YAMLProfileReader::buildNameMaps(
if (Pos != StringRef::npos) if (Pos != StringRef::npos)
Name = Name.substr(0, Pos); Name = Name.substr(0, Pos);
ProfileNameToProfile[Name] = &YamlBF; ProfileNameToProfile[Name] = &YamlBF;
if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) { if (const Optional<StringRef> CommonName = getLTOCommonName(Name))
LTOCommonNameMap[*CommonName].push_back(&YamlBF); LTOCommonNameMap[*CommonName].push_back(&YamlBF);
} }
}
for (auto &BFI : Functions) { for (auto &BFI : Functions) {
const BinaryFunction &Function = BFI.second; const BinaryFunction &Function = BFI.second;
for (StringRef Name : Function.getNames()) { for (StringRef Name : Function.getNames())
if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) { if (const Optional<StringRef> CommonName = getLTOCommonName(Name))
LTOCommonNameFunctionMap[*CommonName].insert(&Function); LTOCommonNameFunctionMap[*CommonName].insert(&Function);
} }
}
}
} }
bool YAMLProfileReader::hasLocalsWithFileName() const { bool YAMLProfileReader::hasLocalsWithFileName() const {
@ -123,11 +120,11 @@ bool YAMLProfileReader::parseFunctionProfile(
continue; continue;
} }
uint64_t NumSamples = YamlBB.EventCount * 1000; uint64_t NumSamples = YamlBB.EventCount * 1000;
if (NormalizeByInsnCount && BB.getNumNonPseudos()) { if (NormalizeByInsnCount && BB.getNumNonPseudos())
NumSamples /= BB.getNumNonPseudos(); NumSamples /= BB.getNumNonPseudos();
} else if (NormalizeByCalls) { else if (NormalizeByCalls)
NumSamples /= BB.getNumCalls() + 1; NumSamples /= BB.getNumCalls() + 1;
}
BB.setExecutionCount(NumSamples); BB.setExecutionCount(NumSamples);
if (BB.isEntryPoint()) if (BB.isEntryPoint())
FunctionExecutionCount += NumSamples; FunctionExecutionCount += NumSamples;
@ -142,9 +139,9 @@ bool YAMLProfileReader::parseFunctionProfile(
: nullptr; : nullptr;
bool IsFunction = Callee ? true : false; bool IsFunction = Callee ? true : false;
MCSymbol *CalleeSymbol = nullptr; MCSymbol *CalleeSymbol = nullptr;
if (IsFunction) { if (IsFunction)
CalleeSymbol = Callee->getSymbolForEntryID(YamlCSI.EntryDiscriminator); CalleeSymbol = Callee->getSymbolForEntryID(YamlCSI.EntryDiscriminator);
}
BF.getAllCallSites().emplace_back(CalleeSymbol, YamlCSI.Count, BF.getAllCallSites().emplace_back(CalleeSymbol, YamlCSI.Count,
YamlCSI.Mispreds, YamlCSI.Offset); YamlCSI.Mispreds, YamlCSI.Offset);
@ -221,10 +218,9 @@ bool YAMLProfileReader::parseFunctionProfile(
} }
// If basic block profile wasn't read it should be 0. // If basic block profile wasn't read it should be 0.
for (BinaryBasicBlock &BB : BF) { for (BinaryBasicBlock &BB : BF)
if (BB.getExecutionCount() == BinaryBasicBlock::COUNT_NO_PROFILE) if (BB.getExecutionCount() == BinaryBasicBlock::COUNT_NO_PROFILE)
BB.setExecutionCount(0); BB.setExecutionCount(0);
}
if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) { if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) {
BF.setExecutionCount(FunctionExecutionCount); BF.setExecutionCount(FunctionExecutionCount);
@ -236,11 +232,10 @@ bool YAMLProfileReader::parseFunctionProfile(
if (ProfileMatched) if (ProfileMatched)
BF.markProfiled(YamlBP.Header.Flags); BF.markProfiled(YamlBP.Header.Flags);
if (!ProfileMatched && opts::Verbosity >= 1) { if (!ProfileMatched && opts::Verbosity >= 1)
errs() << "BOLT-WARNING: " << MismatchedBlocks << " blocks, " errs() << "BOLT-WARNING: " << MismatchedBlocks << " blocks, "
<< MismatchedCalls << " calls, and " << MismatchedEdges << MismatchedCalls << " calls, and " << MismatchedEdges
<< " edges in profile did not match function " << BF << '\n'; << " edges in profile did not match function " << BF << '\n';
}
return ProfileMatched; return ProfileMatched;
} }
@ -263,16 +258,15 @@ Error YAMLProfileReader::preprocessProfile(BinaryContext &BC) {
} }
// Sanity check. // Sanity check.
if (YamlBP.Header.Version != 1) { if (YamlBP.Header.Version != 1)
return make_error<StringError>( return make_error<StringError>(
Twine("cannot read profile : unsupported version"), Twine("cannot read profile : unsupported version"),
inconvertibleErrorCode()); inconvertibleErrorCode());
}
if (YamlBP.Header.EventNames.find(',') != StringRef::npos) { if (YamlBP.Header.EventNames.find(',') != StringRef::npos)
return make_error<StringError>( return make_error<StringError>(
Twine("multiple events in profile are not supported"), Twine("multiple events in profile are not supported"),
inconvertibleErrorCode()); inconvertibleErrorCode());
}
// Match profile to function based on a function name. // Match profile to function based on a function name.
buildNameMaps(BC.getBinaryFunctions()); buildNameMaps(BC.getBinaryFunctions());
@ -298,11 +292,10 @@ bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) {
if (ProfileNameToProfile.find(Name) != ProfileNameToProfile.end()) if (ProfileNameToProfile.find(Name) != ProfileNameToProfile.end())
return true; return true;
if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) { if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) {
if (LTOCommonNameMap.find(*CommonName) != LTOCommonNameMap.end()) { if (LTOCommonNameMap.find(*CommonName) != LTOCommonNameMap.end())
return true; return true;
} }
} }
}
return false; return false;
} }
@ -336,9 +329,9 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
for (StringRef FunctionName : Function.getNames()) { for (StringRef FunctionName : Function.getNames()) {
auto PI = ProfileNameToProfile.find(FunctionName); auto PI = ProfileNameToProfile.find(FunctionName);
if (PI == ProfileNameToProfile.end()) { if (PI == ProfileNameToProfile.end())
continue; continue;
}
yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue(); yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue();
if (profileMatches(YamlBF, Function)) if (profileMatches(YamlBF, Function))
matchProfileToFunction(YamlBF, Function); matchProfileToFunction(YamlBF, Function);
@ -394,12 +387,10 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
} }
} }
for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) { for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions)
if (!YamlBF.Used && opts::Verbosity >= 1) { if (!YamlBF.Used && opts::Verbosity >= 1)
errs() << "BOLT-WARNING: profile ignored for function " << YamlBF.Name errs() << "BOLT-WARNING: profile ignored for function " << YamlBF.Name
<< '\n'; << '\n';
}
}
// Set for parseFunctionProfile(). // Set for parseFunctionProfile().
NormalizeByInsnCount = usesEvent("cycles") || usesEvent("instructions"); NormalizeByInsnCount = usesEvent("cycles") || usesEvent("instructions");
@ -412,12 +403,11 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
++NumUnused; ++NumUnused;
continue; continue;
} }
if (BinaryFunction *BF = YamlProfileToFunction[YamlBF.Id]) { if (BinaryFunction *BF = YamlProfileToFunction[YamlBF.Id])
parseFunctionProfile(*BF, YamlBF); parseFunctionProfile(*BF, YamlBF);
} else { else
++NumUnused; ++NumUnused;
} }
}
BC.setNumUnusedProfiledObjects(NumUnused); BC.setNumUnusedProfiledObjects(NumUnused);

View File

@ -68,10 +68,9 @@ void convert(const BinaryFunction &BF,
CSI.EntryDiscriminator = 0; CSI.EntryDiscriminator = 0;
if (CSP.Symbol) { if (CSP.Symbol) {
const BinaryFunction *Callee = BC.getFunctionForSymbol(CSP.Symbol); const BinaryFunction *Callee = BC.getFunctionForSymbol(CSP.Symbol);
if (Callee) { if (Callee)
CSI.DestId = Callee->getFunctionNumber(); CSI.DestId = Callee->getFunctionNumber();
} }
}
CSI.Count = CSP.Count; CSI.Count = CSP.Count;
CSI.Mispreds = CSP.Mispreds; CSI.Mispreds = CSP.Mispreds;
YamlBB.CallSites.push_back(CSI); YamlBB.CallSites.push_back(CSI);
@ -115,9 +114,8 @@ void convert(const BinaryFunction &BF,
!(BB->isLandingPad() && BB->getKnownExecutionCount() != 0)) { !(BB->isLandingPad() && BB->getKnownExecutionCount() != 0)) {
uint64_t SuccessorExecCount = 0; uint64_t SuccessorExecCount = 0;
for (const BinaryBasicBlock::BinaryBranchInfo &BranchInfo : for (const BinaryBasicBlock::BinaryBranchInfo &BranchInfo :
BB->branch_info()) { BB->branch_info())
SuccessorExecCount += BranchInfo.Count; SuccessorExecCount += BranchInfo.Count;
}
if (!SuccessorExecCount) if (!SuccessorExecCount)
continue; continue;
} }
@ -175,9 +173,9 @@ std::error_code YAMLProfileWriter::writeProfile(const RewriteInstance &RI) {
const BinaryFunction &BF = BFI.second; const BinaryFunction &BF = BFI.second;
if (BF.hasProfile() && !BF.empty()) { if (BF.hasProfile() && !BF.empty()) {
assert(BF.getProfileFlags() != BinaryFunction::PF_NONE); assert(BF.getProfileFlags() != BinaryFunction::PF_NONE);
if (ProfileFlags == BinaryFunction::PF_NONE) { if (ProfileFlags == BinaryFunction::PF_NONE)
ProfileFlags = BF.getProfileFlags(); ProfileFlags = BF.getProfileFlags();
}
assert(BF.getProfileFlags() == ProfileFlags && assert(BF.getProfileFlags() == ProfileFlags &&
"expected consistent profile flags across all functions"); "expected consistent profile flags across all functions");
} }