Skip to content

Commit c43d043

Browse files
authored
[BOLT] Create .text.warm for 3-way splitting (#73863)
This commit explicitly adds a warm code section, .text.warm, when -split-functions -split-strategy=cdsplit is used. This replaces the previous approach of using .text.cold.0 as warm and .text.cold.1 as cold in 3-way function splitting. NFC.
1 parent 3cf1909 commit c43d043

File tree

6 files changed

+57
-17
lines changed

6 files changed

+57
-17
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,11 @@ class BinaryContext {
614614
/// Indicates if the function ordering of the binary is finalized.
615615
bool HasFinalizedFunctionOrder{false};
616616

617+
/// Indicates if a separate .text.warm section is needed that contains
618+
/// function fragments with
619+
/// FunctionFragment::getFragmentNum() == FragmentNum::warm()
620+
bool HasWarmSection{false};
621+
617622
/// Is the binary always loaded at a fixed address. Shared objects and
618623
/// position-independent executables (PIEs) are examples of binaries that
619624
/// will have HasFixedLoadAddress set to false.
@@ -930,6 +935,8 @@ class BinaryContext {
930935

931936
const char *getMainCodeSectionName() const { return ".text"; }
932937

938+
const char *getWarmCodeSectionName() const { return ".text.warm"; }
939+
933940
const char *getColdCodeSectionName() const { return ".text.cold"; }
934941

935942
const char *getHotTextMoverSectionName() const { return ".text.mover"; }

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,8 @@ class BinaryFunction {
12361236
return SmallString<32>(CodeSectionName);
12371237
if (Fragment == FragmentNum::cold())
12381238
return SmallString<32>(ColdCodeSectionName);
1239+
if (BC.HasWarmSection && Fragment == FragmentNum::warm())
1240+
return SmallString<32>(BC.getWarmCodeSectionName());
12391241
return formatv("{0}.{1}", ColdCodeSectionName, Fragment.get() - 1);
12401242
}
12411243

bolt/include/bolt/Core/FunctionLayout.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class FragmentNum {
6363

6464
static constexpr FragmentNum main() { return FragmentNum(0); }
6565
static constexpr FragmentNum cold() { return FragmentNum(1); }
66+
static constexpr FragmentNum warm() { return FragmentNum(2); }
6667
};
6768

6869
/// A freestanding subset of contiguous blocks of a function.

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,10 @@ void BinaryEmitter::emitFunctions() {
287287

288288
// Mark the end of hot text.
289289
if (opts::HotText) {
290-
Streamer.switchSection(BC.getTextSection());
290+
if (BC.HasWarmSection)
291+
Streamer.switchSection(BC.getCodeSection(BC.getWarmCodeSectionName()));
292+
else
293+
Streamer.switchSection(BC.getTextSection());
291294
Streamer.emitLabel(BC.getHotTextEndSymbol());
292295
}
293296
}

bolt/lib/Passes/SplitFunctions.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,15 @@ struct SplitCacheDirected final : public SplitStrategy {
160160
// Assign fragments based on the computed best split index.
161161
// All basic blocks with index up to the best split index become hot.
162162
// All remaining blocks are warm / cold depending on if count is
163-
// greater than 0 or not.
164-
FragmentNum Main(0);
165-
FragmentNum Cold(1);
166-
FragmentNum Warm(2);
163+
// greater than zero or not.
167164
for (size_t Index = 0; Index < BlockOrder.size(); Index++) {
168165
BinaryBasicBlock *BB = BlockOrder[Index];
169166
if (Index <= BestSplitIndex)
170-
BB->setFragmentNum(Main);
167+
BB->setFragmentNum(FragmentNum::main());
171168
else
172-
BB->setFragmentNum(BB->getKnownExecutionCount() > 0 ? Warm : Cold);
169+
BB->setFragmentNum(BB->getKnownExecutionCount() > 0
170+
? FragmentNum::warm()
171+
: FragmentNum::cold());
173172
}
174173
}
175174

@@ -313,6 +312,7 @@ void SplitFunctions::runOnFunctions(BinaryContext &BC) {
313312
else
314313
Strategy = std::make_unique<SplitProfile2>();
315314
opts::AggressiveSplitting = true;
315+
BC.HasWarmSection = true;
316316
break;
317317
case SplitFunctionsStrategy::Profile2:
318318
Strategy = std::make_unique<SplitProfile2>();

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,11 +3478,21 @@ std::vector<BinarySection *> RewriteInstance::getCodeSections() {
34783478
if (B->getName() == BC->getHotTextMoverSectionName())
34793479
return false;
34803480

3481-
// Depending on the option, put main text at the beginning or at the end.
3482-
if (opts::HotFunctionsAtEnd)
3483-
return B->getName() == BC->getMainCodeSectionName();
3484-
else
3485-
return A->getName() == BC->getMainCodeSectionName();
3481+
// Depending on opts::HotFunctionsAtEnd, place main and warm sections in
3482+
// order.
3483+
if (opts::HotFunctionsAtEnd) {
3484+
if (B->getName() == BC->getMainCodeSectionName())
3485+
return true;
3486+
if (A->getName() == BC->getMainCodeSectionName())
3487+
return false;
3488+
return (B->getName() == BC->getWarmCodeSectionName());
3489+
} else {
3490+
if (A->getName() == BC->getMainCodeSectionName())
3491+
return true;
3492+
if (B->getName() == BC->getMainCodeSectionName())
3493+
return false;
3494+
return (A->getName() == BC->getWarmCodeSectionName());
3495+
}
34863496
};
34873497

34883498
// Determine the order of sections.
@@ -3524,6 +3534,9 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
35243534

35253535
// Allocate sections starting at a given Address.
35263536
auto allocateAt = [&](uint64_t Address) {
3537+
const char *LastNonColdSectionName = BC->HasWarmSection
3538+
? BC->getWarmCodeSectionName()
3539+
: BC->getMainCodeSectionName();
35273540
for (BinarySection *Section : CodeSections) {
35283541
Address = alignTo(Address, Section->getAlignment());
35293542
Section->setOutputAddress(Address);
@@ -3532,13 +3545,13 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
35323545
// Hugify: Additional huge page from right side due to
35333546
// weird ASLR mapping addresses (4KB aligned)
35343547
if (opts::Hugify && !BC->HasFixedLoadAddress &&
3535-
Section->getName() == BC->getMainCodeSectionName())
3548+
Section->getName() == LastNonColdSectionName)
35363549
Address = alignTo(Address, Section->getAlignment());
35373550
}
35383551

35393552
// Make sure we allocate enough space for huge pages.
35403553
ErrorOr<BinarySection &> TextSection =
3541-
BC->getUniqueSectionByName(BC->getMainCodeSectionName());
3554+
BC->getUniqueSectionByName(LastNonColdSectionName);
35423555
if (opts::HotText && TextSection && TextSection->hasValidSectionID()) {
35433556
uint64_t HotTextEnd =
35443557
TextSection->getOutputAddress() + TextSection->getOutputSize();
@@ -4396,6 +4409,21 @@ void RewriteInstance::updateELFSymbolTable(
43964409
return NewIndex;
43974410
};
43984411

4412+
// Get the extra symbol name of a split fragment; used in addExtraSymbols.
4413+
auto getSplitSymbolName = [&](const FunctionFragment &FF,
4414+
const ELFSymTy &FunctionSymbol) {
4415+
SmallString<256> SymbolName;
4416+
if (BC->HasWarmSection)
4417+
SymbolName =
4418+
formatv("{0}.{1}", cantFail(FunctionSymbol.getName(StringSection)),
4419+
FF.getFragmentNum() == FragmentNum::warm() ? "warm" : "cold");
4420+
else
4421+
SymbolName = formatv("{0}.cold.{1}",
4422+
cantFail(FunctionSymbol.getName(StringSection)),
4423+
FF.getFragmentNum().get() - 1);
4424+
return SymbolName;
4425+
};
4426+
43994427
// Add extra symbols for the function.
44004428
//
44014429
// Note that addExtraSymbols() could be called multiple times for the same
@@ -4423,9 +4451,8 @@ void RewriteInstance::updateELFSymbolTable(
44234451
Function.getLayout().getSplitFragments()) {
44244452
if (FF.getAddress()) {
44254453
ELFSymTy NewColdSym = FunctionSymbol;
4426-
const SmallString<256> SymbolName = formatv(
4427-
"{0}.cold.{1}", cantFail(FunctionSymbol.getName(StringSection)),
4428-
FF.getFragmentNum().get() - 1);
4454+
const SmallString<256> SymbolName =
4455+
getSplitSymbolName(FF, FunctionSymbol);
44294456
NewColdSym.st_name = AddToStrTab(SymbolName);
44304457
NewColdSym.st_shndx =
44314458
Function.getCodeSection(FF.getFragmentNum())->getIndex();

0 commit comments

Comments
 (0)