Skip to content

Commit 9aef8e0

Browse files
committed
unified checkReturn and checkUncondJump, logging
Created using spr 1.3.4
1 parent 734e5b0 commit 9aef8e0

File tree

2 files changed

+46
-37
lines changed

2 files changed

+46
-37
lines changed

bolt/include/bolt/Profile/DataAggregator.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class DataAggregator : public DataReader {
137137
std::vector<std::pair<Trace, TakenBranchInfo>> Traces;
138138
/// Pre-populated addresses of returns, coming from pre-aggregated data or
139139
/// disassembly. Used to disambiguate call-continuation fall-throughs.
140-
std::unordered_set<uint64_t> Returns;
140+
std::unordered_map<uint64_t, bool> Returns;
141141
std::unordered_map<uint64_t, uint64_t> BasicSamples;
142142
std::vector<PerfMemSample> MemSamples;
143143

@@ -514,6 +514,38 @@ class DataAggregator : public DataReader {
514514
void printBasicSamplesDiagnostics(uint64_t OutOfRangeSamples) const;
515515
void printBranchStacksDiagnostics(uint64_t IgnoredSamples) const;
516516

517+
template <typename T>
518+
std::optional<T>
519+
testInstructionAt(const uint64_t Addr,
520+
std::function<T(const MCInst &)> Callback) const {
521+
BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr);
522+
if (!Func)
523+
return std::nullopt;
524+
const uint64_t Offset = Addr - Func->getAddress();
525+
if (Func->hasInstructions()) {
526+
if (auto *MI = Func->getInstructionAtOffset(Offset))
527+
return Callback(*MI);
528+
} else {
529+
if (auto MI = Func->disassembleInstructionAtOffset(Offset))
530+
return Callback(*MI);
531+
}
532+
return std::nullopt;
533+
}
534+
535+
template <typename T>
536+
std::optional<T> testAndSet(const uint64_t Addr,
537+
std::function<T(const MCInst &)> Callback,
538+
std::unordered_map<uint64_t, T> &Map) {
539+
auto It = Map.find(Addr);
540+
if (It != Map.end())
541+
return It->second;
542+
if (std::optional<T> Res = testInstructionAt<T>(Addr, Callback)) {
543+
Map.emplace(Addr, *Res);
544+
return *Res;
545+
}
546+
return std::nullopt;
547+
}
548+
517549
public:
518550
/// If perf.data was collected without build ids, the buildid-list may contain
519551
/// incomplete entries. Return true if the buffer containing

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -546,23 +546,10 @@ void DataAggregator::imputeFallThroughs() {
546546
// Helper map with whether the instruction is a call/ret/unconditional branch
547547
std::unordered_map<uint64_t, bool> IsUncondJumpMap;
548548
auto checkUncondJump = [&](const uint64_t Addr) {
549-
auto isUncondJump = [&](auto MI) {
550-
return MI && BC->MIB->IsUnconditionalJump(*MI);
549+
auto isUncondJump = [&](const MCInst &MI) -> bool {
550+
return BC->MIB->IsUnconditionalJump(MI);
551551
};
552-
auto It = IsUncondJumpMap.find(Addr);
553-
if (It != IsUncondJumpMap.end())
554-
return It->second;
555-
BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr);
556-
if (!Func)
557-
return false;
558-
const uint64_t Offset = Addr - Func->getAddress();
559-
if (Func->hasInstructions()
560-
? isUncondJump(Func->getInstructionAtOffset(Offset))
561-
: isUncondJump(Func->disassembleInstructionAtOffset(Offset))) {
562-
IsUncondJumpMap.emplace(Addr, true);
563-
return true;
564-
}
565-
return false;
552+
return testAndSet<bool>(Addr, isUncondJump, IsUncondJumpMap).value_or(true);
566553
};
567554

568555
for (auto &[Trace, Info] : Traces) {
@@ -574,7 +561,8 @@ void DataAggregator::imputeFallThroughs() {
574561
? AggregateFallthroughSize / AggregateCount
575562
: !checkUncondJump(Trace.From);
576563
Trace.To = Trace.From + InferredBytes;
577-
outs() << "Inferred " << Trace << " " << InferredBytes << '\n';
564+
LLVM_DEBUG(dbgs() << "imputed " << Trace << " (" << InferredBytes
565+
<< " bytes)\n");
578566
++InferredTraces;
579567
} else {
580568
if (CurrentBranch != PrevBranch)
@@ -585,7 +573,8 @@ void DataAggregator::imputeFallThroughs() {
585573
}
586574
PrevBranch = CurrentBranch;
587575
}
588-
outs() << "Inferred " << InferredTraces << " traces\n";
576+
if (opts::Verbosity >= 1)
577+
outs() << "BOLT-INFO: imputed " << InferredTraces << " traces\n";
589578
}
590579

591580
Error DataAggregator::preprocessProfile(BinaryContext &BC) {
@@ -804,22 +793,10 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
804793
}
805794

806795
bool DataAggregator::checkReturn(uint64_t Addr) {
807-
auto isReturn = [&](auto MI) { return MI && BC->MIB->isReturn(*MI); };
808-
if (llvm::is_contained(Returns, Addr))
809-
return true;
810-
811-
BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr);
812-
if (!Func)
813-
return false;
814-
815-
const uint64_t Offset = Addr - Func->getAddress();
816-
if (Func->hasInstructions()
817-
? isReturn(Func->getInstructionAtOffset(Offset))
818-
: isReturn(Func->disassembleInstructionAtOffset(Offset))) {
819-
Returns.emplace(Addr);
820-
return true;
821-
}
822-
return false;
796+
auto isReturn = [&](const MCInst &MI) -> bool {
797+
return BC->MIB->isReturn(MI);
798+
};
799+
return testAndSet<bool>(Addr, isReturn, Returns).value_or(false);
823800
}
824801

825802
bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
@@ -1409,7 +1386,7 @@ std::error_code DataAggregator::parseAggregatedLBREntry() {
14091386
if (!Addr[0]->Offset)
14101387
Addr[0]->Offset = Trace::FT_EXTERNAL_RETURN;
14111388
else
1412-
Returns.emplace(Addr[0]->Offset);
1389+
Returns.emplace(Addr[0]->Offset, true);
14131390
}
14141391

14151392
/// Record a trace.
@@ -1670,7 +1647,7 @@ void DataAggregator::processBranchEvents() {
16701647
NamedRegionTimer T("processBranch", "Processing branch events",
16711648
TimerGroupName, TimerGroupDesc, opts::TimeAggregator);
16721649

1673-
Returns.emplace(Trace::FT_EXTERNAL_RETURN);
1650+
Returns.emplace(Trace::FT_EXTERNAL_RETURN, true);
16741651
for (const auto &[Trace, Info] : Traces) {
16751652
bool IsReturn = checkReturn(Trace.Branch);
16761653
// Ignore returns.

0 commit comments

Comments
 (0)