Skip to content

Commit db29f20

Browse files
authored
[BOLT] Ignore returns in DataAggregator
Returns are ignored in perf/pre-aggregated/fdata profile reader (see DataReader::convertBranchData). They are also omitted in YAMLProfileWriter by virtue of not having the profile attached to them in the reader, and YAMLProfileWriter converting the profile attached to BinaryFunctions. Thus, return profile is universally ignored across all profile types except BAT YAML. To make returns ignored for YAML produced in BAT mode, we can: 1) ignore them in YAMLProfileReader, 2) omit them from YAML profile in profile conversion/writing. The first option is prone to profile staleness issue, where the profiled binary doesn't match the one to be optimized, and thus returns in the profile can no longer be reliably detected (as we don't distinguish them from calls in the profile). The second option is robust to staleness but requires disassembling the branch source instruction. Test Plan: Updated bolt-address-translation-yaml.test Reviewers: rafaelauler, dcci, ayermolo, maksfb Reviewed By: maksfb Pull Request: #90807
1 parent a6b6237 commit db29f20

File tree

4 files changed

+33
-2
lines changed

4 files changed

+33
-2
lines changed

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,8 @@ class BinaryFunction {
930930
return const_cast<BinaryFunction *>(this)->getInstructionAtOffset(Offset);
931931
}
932932

933+
std::optional<MCInst> disassembleInstructionAtOffset(uint64_t Offset) const;
934+
933935
/// Return offset for the first instruction. If there is data at the
934936
/// beginning of a function then offset of the first instruction could
935937
/// be different from 0

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,21 @@ void BinaryFunction::handleAArch64IndirectCall(MCInst &Instruction,
11671167
}
11681168
}
11691169

1170+
std::optional<MCInst>
1171+
BinaryFunction::disassembleInstructionAtOffset(uint64_t Offset) const {
1172+
assert(CurrentState == State::Empty && "Function should not be disassembled");
1173+
assert(Offset < MaxSize && "Invalid offset");
1174+
ErrorOr<ArrayRef<unsigned char>> FunctionData = getData();
1175+
assert(FunctionData && "Cannot get function as data");
1176+
MCInst Instr;
1177+
uint64_t InstrSize = 0;
1178+
const uint64_t InstrAddress = getAddress() + Offset;
1179+
if (BC.DisAsm->getInstruction(Instr, InstrSize, FunctionData->slice(Offset),
1180+
InstrAddress, nulls()))
1181+
return Instr;
1182+
return std::nullopt;
1183+
}
1184+
11701185
Error BinaryFunction::disassemble() {
11711186
NamedRegionTimer T("disassemble", "Disassemble function", "buildfuncs",
11721187
"Build Binary Functions", opts::TimeBuild);

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,9 +773,19 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
773773

774774
bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
775775
uint64_t Mispreds) {
776+
bool IsReturn = false;
776777
auto handleAddress = [&](uint64_t &Addr, bool IsFrom) -> BinaryFunction * {
777778
if (BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr)) {
778779
Addr -= Func->getAddress();
780+
if (IsFrom) {
781+
auto checkReturn = [&](auto MaybeInst) {
782+
IsReturn = MaybeInst && BC->MIB->isReturn(*MaybeInst);
783+
};
784+
if (Func->hasInstructions())
785+
checkReturn(Func->getInstructionAtOffset(Addr));
786+
else
787+
checkReturn(Func->disassembleInstructionAtOffset(Addr));
788+
}
779789

780790
if (BAT)
781791
Addr = BAT->translate(Func->getAddress(), Addr, IsFrom);
@@ -792,6 +802,9 @@ bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
792802
};
793803

794804
BinaryFunction *FromFunc = handleAddress(From, /*IsFrom=*/true);
805+
// Ignore returns.
806+
if (IsReturn)
807+
return true;
795808
BinaryFunction *ToFunc = handleAddress(To, /*IsFrom=*/false);
796809
if (!FromFunc && !ToFunc)
797810
return false;

bolt/test/X86/bolt-address-translation-yaml.test

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ RUN: llvm-bolt %t.exe -data %t.fdata -w %t.yaml-fdata -o /dev/null
1313
RUN: FileCheck --input-file %t.yaml-fdata --check-prefix YAML-BAT-CHECK %s
1414

1515
# Test resulting YAML profile with the original binary (no-stale mode)
16-
RUN: llvm-bolt %t.exe -data %t.yaml -o %t.null -dyno-stats \
16+
RUN: llvm-bolt %t.exe -data %t.yaml -o %t.null -dyno-stats 2>&1 \
1717
RUN: | FileCheck --check-prefix CHECK-BOLT-YAML %s
1818

1919
WRITE-BAT-CHECK: BOLT-INFO: Wrote 5 BAT maps
@@ -63,7 +63,8 @@ YAML-BAT-CHECK-NEXT: blocks:
6363
YAML-BAT-CHECK: - bid: 1
6464
YAML-BAT-CHECK-NEXT: insns: [[#]]
6565
YAML-BAT-CHECK-NEXT: hash: 0xD70DC695320E0010
66-
YAML-BAT-CHECK-NEXT: succ: {{.*}} { bid: 2, cnt: [[#]] }
66+
YAML-BAT-CHECK-NEXT: succ: {{.*}} { bid: 2, cnt: [[#]]
6767

6868
CHECK-BOLT-YAML: pre-processing profile using YAML profile reader
6969
CHECK-BOLT-YAML-NEXT: 5 out of 16 functions in the binary (31.2%) have non-empty execution profile
70+
CHECK-BOLT-YAML-NOT: invalid (possibly stale) profile

0 commit comments

Comments
 (0)