Skip to content

Commit d333c0e

Browse files
authored
[BOLT] Extend calculateEmittedSize() for block size calculation (#73076)
This commit modifies BinaryContext::calculateEmittedSize() to update the BinaryBasicBlock::OutputAddressRange of each basic block in the function in place. BinaryBasicBlock::getOutputSize() now gives the emitted size of the basic block.
1 parent 442fef6 commit d333c0e

File tree

4 files changed

+144
-6
lines changed

4 files changed

+144
-6
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,9 @@ class BinaryContext {
12301230
///
12311231
/// Return the pair where the first size is for the main part, and the second
12321232
/// size is for the cold one.
1233+
/// Modify BinaryBasicBlock::OutputAddressRange for each basic block in the
1234+
/// function in place so that BinaryBasicBlock::getOutputSize() gives the
1235+
/// emitted size of the basic block.
12331236
std::pair<size_t, size_t> calculateEmittedSize(BinaryFunction &BF,
12341237
bool FixBranches = true);
12351238

bolt/lib/Core/BinaryContext.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,14 +2331,36 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
23312331
MCAsmLayout Layout(Assembler);
23322332
Assembler.layout(Layout);
23332333

2334+
// Obtain fragment sizes.
2335+
std::vector<uint64_t> FragmentSizes;
2336+
// Main fragment size.
23342337
const uint64_t HotSize =
23352338
Layout.getSymbolOffset(*EndLabel) - Layout.getSymbolOffset(*StartLabel);
2336-
const uint64_t ColdSize =
2337-
std::accumulate(SplitLabels.begin(), SplitLabels.end(), 0ULL,
2338-
[&](const uint64_t Accu, const LabelRange &Labels) {
2339-
return Accu + Layout.getSymbolOffset(*Labels.second) -
2340-
Layout.getSymbolOffset(*Labels.first);
2341-
});
2339+
FragmentSizes.push_back(HotSize);
2340+
// Split fragment sizes.
2341+
uint64_t ColdSize = 0;
2342+
for (const auto &Labels : SplitLabels) {
2343+
uint64_t Size = Layout.getSymbolOffset(*Labels.second) -
2344+
Layout.getSymbolOffset(*Labels.first);
2345+
FragmentSizes.push_back(Size);
2346+
ColdSize += Size;
2347+
}
2348+
2349+
// Populate new start and end offsets of each basic block.
2350+
uint64_t FragmentIndex = 0;
2351+
for (FunctionFragment &FF : BF.getLayout().fragments()) {
2352+
BinaryBasicBlock *PrevBB = nullptr;
2353+
for (BinaryBasicBlock *BB : FF) {
2354+
const uint64_t BBStartOffset = Layout.getSymbolOffset(*(BB->getLabel()));
2355+
BB->setOutputStartAddress(BBStartOffset);
2356+
if (PrevBB)
2357+
PrevBB->setOutputEndAddress(BBStartOffset);
2358+
PrevBB = BB;
2359+
}
2360+
if (PrevBB)
2361+
PrevBB->setOutputEndAddress(FragmentSizes[FragmentIndex]);
2362+
FragmentIndex++;
2363+
}
23422364

23432365
// Clean-up the effect of the code emission.
23442366
for (const MCSymbol &Symbol : Assembler.symbols()) {

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ cl::opt<bool>
108108
cl::desc("try to preserve basic block alignment"),
109109
cl::cat(BoltOptCategory));
110110

111+
static cl::opt<bool> PrintOutputAddressRange(
112+
"print-output-address-range",
113+
cl::desc(
114+
"print output address range for each basic block in the function when"
115+
"BinaryFunction::print is called"),
116+
cl::Hidden, cl::cat(BoltOptCategory));
117+
111118
cl::opt<bool>
112119
PrintDynoStats("dyno-stats",
113120
cl::desc("print execution info based on profile"),
@@ -510,6 +517,11 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
510517
OS << BB->getName() << " (" << BB->size()
511518
<< " instructions, align : " << BB->getAlignment() << ")\n";
512519

520+
if (opts::PrintOutputAddressRange)
521+
OS << formatv(" Output Address Range: [{0:x}, {1:x}) ({2} bytes)\n",
522+
BB->getOutputAddressRange().first,
523+
BB->getOutputAddressRange().second, BB->getOutputSize());
524+
513525
if (isEntryPoint(*BB)) {
514526
if (MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB))
515527
OS << " Secondary Entry Point: " << EntrySymbol->getName() << '\n';
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Test BinaryContext::calculateEmittedSize's functionality to update
2+
# BinaryBasicBlock::OutputAddressRange in place so that the emitted size
3+
# of each basic block is given by BinaryBasicBlock::getOutputSize()
4+
5+
# RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %s -o %t.o
6+
# RUN: link_fdata %s %t.o %t.fdata
7+
# RUN: llvm-strip --strip-unneeded %t.o
8+
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
9+
# RUN: llvm-bolt %t.exe -o %t.bolt --split-functions --split-strategy=all \
10+
# RUN: --print-split --print-only=chain --print-output-address-range \
11+
# RUN: --data=%t.fdata --reorder-blocks=ext-tsp \
12+
# RUN: 2>&1 | FileCheck --check-prefix=SPLITALL %s
13+
# RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %s -o %t.o
14+
# RUN: link_fdata %s %t.o %t.fdata
15+
# RUN: llvm-strip --strip-unneeded %t.o
16+
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
17+
# RUN: llvm-bolt %t.exe -o %t.bolt --split-functions --print-split \
18+
# RUN: --print-only=chain --print-output-address-range \
19+
# RUN: --data=%t.fdata --reorder-blocks=ext-tsp \
20+
# RUN: 2>&1 | FileCheck --check-prefix=SPLITHOTCOLD %s
21+
22+
# SPLITALL: {{^\.LBB00}}
23+
# SPLITALL: Output Address Range: [0x0, 0x12) (18 bytes)
24+
# SPLITALL: {{^\.LFT0}}
25+
# SPLITALL: Output Address Range: [0x0, 0xa) (10 bytes)
26+
# SPLITALL: {{^\.Ltmp1}}
27+
# SPLITALL: Output Address Range: [0x0, 0x2) (2 bytes)
28+
# SPLITALL: {{^\.Ltmp0}}
29+
# SPLITALL: Output Address Range: [0x0, 0x10) (16 bytes)
30+
# SPLITALL: {{^\.Ltmp2}}
31+
# SPLITALL: Output Address Range: [0x0, 0x8) (8 bytes)
32+
# SPLITALL: {{^\.LFT1}}
33+
# SPLITALL: Output Address Range: [0x0, 0x8) (8 bytes)
34+
35+
# SPLITHOTCOLD: {{^\.LBB00}}
36+
# SPLITHOTCOLD: Output Address Range: [0x0, 0x9) (9 bytes)
37+
# SPLITHOTCOLD: {{^\.LFT0}}
38+
# SPLITHOTCOLD: Output Address Range: [0x9, 0xe) (5 bytes)
39+
# SPLITHOTCOLD: {{^\.Ltmp1}}
40+
# SPLITHOTCOLD: Output Address Range: [0xe, 0x10) (2 bytes)
41+
# SPLITHOTCOLD: {{^\.Ltmp0}}
42+
# SPLITHOTCOLD: Output Address Range: [0x10, 0x1b) (11 bytes)
43+
# SPLITHOTCOLD: {{^\.Ltmp2}}
44+
# SPLITHOTCOLD: Output Address Range: [0x1b, 0x20) (5 bytes)
45+
# SPLITHOTCOLD: {{^\.LFT1}}
46+
# SPLITHOTCOLD: Output Address Range: [0x0, 0x8) (8 bytes)
47+
48+
.text
49+
.globl chain
50+
.type chain, @function
51+
chain:
52+
pushq %rbp
53+
movq %rsp, %rbp
54+
cmpl $2, %edi
55+
LLentry_LLchain_start:
56+
jge LLchain_start
57+
# FDATA: 1 chain #LLentry_LLchain_start# 1 chain #LLchain_start# 0 10
58+
# FDATA: 1 chain #LLentry_LLchain_start# 1 chain #LLfast# 0 500
59+
LLfast:
60+
movl $5, %eax
61+
LLfast_LLexit:
62+
jmp LLexit
63+
# FDATA: 1 chain #LLfast_LLexit# 1 chain #LLexit# 0 500
64+
LLchain_start:
65+
movl $10, %eax
66+
LLchain_start_LLchain1:
67+
jge LLchain1
68+
# FDATA: 1 chain #LLchain_start_LLchain1# 1 chain #LLchain1# 0 10
69+
# FDATA: 1 chain #LLchain_start_LLchain1# 1 chain #LLcold# 0 0
70+
LLcold:
71+
addl $1, %eax
72+
LLchain1:
73+
addl $1, %eax
74+
LLchain1_LLexit:
75+
jmp LLexit
76+
# FDATA: 1 chain #LLchain1_LLexit# 1 chain #LLexit# 0 10
77+
LLexit:
78+
popq %rbp
79+
ret
80+
LLchain_end:
81+
.size chain, LLchain_end-chain
82+
83+
84+
.globl main
85+
.type main, @function
86+
main:
87+
pushq %rbp
88+
movq %rsp, %rbp
89+
movl $1, %edi
90+
LLmain_chain1:
91+
call chain
92+
# FDATA: 1 main #LLmain_chain1# 1 chain 0 0 500
93+
movl $4, %edi
94+
LLmain_chain2:
95+
call chain
96+
# FDATA: 1 main #LLmain_chain2# 1 chain 0 0 10
97+
xorl %eax, %eax
98+
popq %rbp
99+
retq
100+
.Lmain_end:
101+
.size main, .Lmain_end-main

0 commit comments

Comments
 (0)