Skip to content

Commit 935b946

Browse files
authored
[BOLT] Process cross references between ignored functions in BAT mode (llvm#92484)
To align YAML and fdata profiles produced in BAT mode, lift two restrictions applied in non-relocation mode when BAT is present: 1) register secondary entry points from ignored functions, 2) treat functions with secondary entry points as simple. This allows constructing CFG for non-simple functions in non-relocation mode and emitting YAML profile for them, which can then be used for optimizations in relocation mode. Test Plan: added test ignored-interprocedural-reference.s
1 parent a6d97de commit 935b946

File tree

6 files changed

+62
-2
lines changed

6 files changed

+62
-2
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,9 @@ class BinaryContext {
677677
/// have an origin file name available.
678678
bool HasSymbolsWithFileName{false};
679679

680+
/// Does the binary have BAT section.
681+
bool HasBATSection{false};
682+
680683
/// Sum of execution count of all functions
681684
uint64_t SumExecutionCount{0};
682685

bolt/lib/Core/BinaryContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,9 @@ void BinaryContext::processInterproceduralReferences() {
13221322
InterproceduralReferences) {
13231323
BinaryFunction &Function = *It.first;
13241324
uint64_t Address = It.second;
1325-
if (!Address || Function.isIgnored())
1325+
// Process interprocedural references from ignored functions in BAT mode
1326+
// (non-simple in non-relocation mode) to properly register entry points
1327+
if (!Address || (Function.isIgnored() && !HasBATSection))
13261328
continue;
13271329

13281330
BinaryFunction *TargetFunction =

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,8 @@ void BinaryFunction::postProcessEntryPoints() {
16661666
// In non-relocation mode there's potentially an external undetectable
16671667
// reference to the entry point and hence we cannot move this entry
16681668
// point. Optimizing without moving could be difficult.
1669-
if (!BC.HasRelocations)
1669+
// In BAT mode, register any known entry points for CFG construction.
1670+
if (!BC.HasRelocations && !BC.HasBATSection)
16701671
setSimple(false);
16711672

16721673
const uint32_t Offset = KV.first;

bolt/lib/Profile/YAMLProfileWriter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ const BinaryFunction *YAMLProfileWriter::setCSIDestination(
3939
BC.getFunctionForSymbol(Symbol, &EntryID)) {
4040
if (BAT && BAT->isBATFunction(Callee->getAddress()))
4141
std::tie(Callee, EntryID) = BAT->translateSymbol(BC, *Symbol, Offset);
42+
else if (const BinaryBasicBlock *BB =
43+
Callee->getBasicBlockContainingOffset(Offset))
44+
BC.getFunctionForSymbol(Callee->getSecondaryEntryPointSymbol(*BB),
45+
&EntryID);
4246
CSI.DestId = Callee->getFunctionNumber();
4347
CSI.EntryDiscriminator = EntryID;
4448
return Callee;

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,6 +1988,7 @@ Error RewriteInstance::readSpecialSections() {
19881988

19891989
if (ErrorOr<BinarySection &> BATSec =
19901990
BC->getUniqueSectionByName(BoltAddressTranslation::SECTION_NAME)) {
1991+
BC->HasBATSection = true;
19911992
// Do not read BAT when plotting a heatmap
19921993
if (!opts::HeatmapMode) {
19931994
if (std::error_code EC = BAT->parse(BC->outs(), BATSec->getContents())) {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# This reproduces a bug with not processing interprocedural references from
2+
# ignored functions.
3+
4+
# REQUIRES: system-linux
5+
6+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
7+
# RUN: %clang %cflags %t.o -o %t.exe -nostdlib -Wl,-q
8+
# RUN: llvm-bolt %t.exe -o %t.out --enable-bat -funcs=main
9+
# RUN: link_fdata %s %t.out %t.preagg PREAGG
10+
# RUN: perf2bolt %t.out -p %t.preagg --pa -o %t.fdata -w %t.yaml
11+
# RUN: FileCheck %s --input-file=%t.fdata --check-prefix=CHECK-FDATA
12+
# RUN: FileCheck %s --input-file=%t.yaml --check-prefix=CHECK-YAML
13+
14+
# CHECK-FDATA: 1 main 0 1 foo a 1 1
15+
# CHECK-YAML: name: main
16+
# CHECK-YAML: calls: {{.*}} disc: 1
17+
18+
# PREAGG: B #main# #foo_secondary# 1 1
19+
# main calls foo at valid instruction offset past nops that are to be stripped.
20+
.globl main
21+
main:
22+
.cfi_startproc
23+
call foo_secondary
24+
ret
25+
.cfi_endproc
26+
.size main,.-main
27+
28+
# Placeholder cold fragment to force main to be ignored in non-relocation mode.
29+
.globl main.cold
30+
main.cold:
31+
.cfi_startproc
32+
ud2
33+
.cfi_endproc
34+
.size main.cold,.-main.cold
35+
36+
# foo is set up to contain a valid instruction at called offset, and trapping
37+
# instructions past that.
38+
.globl foo
39+
foo:
40+
.cfi_startproc
41+
.nops 10
42+
.globl foo_secondary
43+
foo_secondary:
44+
ret
45+
.rept 20
46+
int3
47+
.endr
48+
.cfi_endproc
49+
.size foo,.-foo

0 commit comments

Comments
 (0)