mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-19 14:44:39 +00:00
[BOLT] Align BranchInfo and FuncBranchData in DataAggregator::recordTrace
`DataAggregator::recordTrace` serves two purposes: - Attaching LBR fallthrough ("trace") information to CFG (`getBranchInfo`), which eventually gets emitted as YAML profile. - Populating vector of offsets that gets added to `FuncBranchData`, which eventually gets emitted as fdata profile. `recordTrace` is invoked from `getFallthroughsInTrace` which checks its return status and passes on the collected vector of offsets to `doTrace`. However, if a malformed trace is passed to `recordTrace` it might partially attach the profile to CFG and exit with false, not propagating the vector of offsets to `doTrace`. This leads to a difference between fdata and yaml profile collected from the same binary and the same perf file. (Skylake LBR errata might produce such malformed traces where the last entry is duplicated, resulting in invalid fallthrough path between the last two entries). There are two ways to handle this mismatch: conservative (aligned with fdata), or aggressive (aligned with yaml). Conservative approach would discard the trace entirely, buffering the CFG updates until all fallthroughs are confirmed. Aggressive approach would apply CFG updates and return the matching fallthroughs in the vector even if the trace is invalid (doesn't correspond to a valid fallthrough path). I chose to go with the former (conservative/fdata) approach which produces more accurate profile. We can't rely on pre-filtering such traces early (in LBR sample processing) as DataAggregator is used for both perf samples and pre-aggregated perf information which loses branch stack information. Test Plan: https://github.com/rafaelauler/bolt-tests/pull/22 Reviewed By: #bolt, rafauler Differential Revision: https://reviews.llvm.org/D151614
This commit is contained in:
parent
fef23e8d87
commit
bce889c8df
@ -199,10 +199,10 @@ private:
|
||||
/// execution order.
|
||||
///
|
||||
/// Return true if the trace is valid, false otherwise.
|
||||
bool recordTrace(
|
||||
BinaryFunction &BF, const LBREntry &First, const LBREntry &Second,
|
||||
uint64_t Count = 1,
|
||||
SmallVector<std::pair<uint64_t, uint64_t>, 16> *Branches = nullptr) const;
|
||||
bool
|
||||
recordTrace(BinaryFunction &BF, const LBREntry &First, const LBREntry &Second,
|
||||
uint64_t Count,
|
||||
SmallVector<std::pair<uint64_t, uint64_t>, 16> &Branches) const;
|
||||
|
||||
/// Return a vector of offsets corresponding to a trace in a function
|
||||
/// (see recordTrace() above).
|
||||
|
@ -838,11 +838,9 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
|
||||
}
|
||||
|
||||
bool DataAggregator::recordTrace(
|
||||
BinaryFunction &BF,
|
||||
const LBREntry &FirstLBR,
|
||||
const LBREntry &SecondLBR,
|
||||
BinaryFunction &BF, const LBREntry &FirstLBR, const LBREntry &SecondLBR,
|
||||
uint64_t Count,
|
||||
SmallVector<std::pair<uint64_t, uint64_t>, 16> *Branches) const {
|
||||
SmallVector<std::pair<uint64_t, uint64_t>, 16> &Branches) const {
|
||||
BinaryContext &BC = BF.getBinaryContext();
|
||||
|
||||
if (!BF.isSimple())
|
||||
@ -902,24 +900,27 @@ bool DataAggregator::recordTrace(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Record fall-through jumps
|
||||
BinaryBasicBlock::BinaryBranchInfo &BI = BB->getBranchInfo(*NextBB);
|
||||
BI.Count += Count;
|
||||
const MCInst *Instr = BB->getLastNonPseudoInstr();
|
||||
uint64_t Offset = 0;
|
||||
if (Instr)
|
||||
Offset = BC.MIB->getOffsetWithDefault(*Instr, 0);
|
||||
else
|
||||
Offset = BB->getOffset();
|
||||
|
||||
if (Branches) {
|
||||
const MCInst *Instr = BB->getLastNonPseudoInstr();
|
||||
uint64_t Offset = 0;
|
||||
if (Instr)
|
||||
Offset = BC.MIB->getOffsetWithDefault(*Instr, 0);
|
||||
else
|
||||
Offset = BB->getOffset();
|
||||
|
||||
Branches->emplace_back(Offset, NextBB->getOffset());
|
||||
}
|
||||
Branches.emplace_back(Offset, NextBB->getOffset());
|
||||
|
||||
BB = NextBB;
|
||||
}
|
||||
|
||||
// Record fall-through jumps
|
||||
for (const auto &[FromOffset, ToOffset] : Branches) {
|
||||
BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(FromOffset);
|
||||
BinaryBasicBlock *ToBB = BF.getBasicBlockAtOffset(ToOffset);
|
||||
assert(FromBB && ToBB);
|
||||
BinaryBasicBlock::BinaryBranchInfo &BI = FromBB->getBranchInfo(*ToBB);
|
||||
BI.Count += Count;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -930,7 +931,7 @@ DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
|
||||
uint64_t Count) const {
|
||||
SmallVector<std::pair<uint64_t, uint64_t>, 16> Res;
|
||||
|
||||
if (!recordTrace(BF, FirstLBR, SecondLBR, Count, &Res))
|
||||
if (!recordTrace(BF, FirstLBR, SecondLBR, Count, Res))
|
||||
return std::nullopt;
|
||||
|
||||
return Res;
|
||||
|
Loading…
x
Reference in New Issue
Block a user