Skip to content

Commit 1b8e0cf

Browse files
authored
[BOLT] Never emit "large" functions (#115974)
"Large" functions are functions that are too big to fit into their original slots after code modifications. CheckLargeFunctions pass is designed to prevent such functions from emission. Extend this pass to work with functions with constant islands. Now that CheckLargeFunctions covers all functions, it guarantees that we will never see such functions after code emission on all platforms (previously it was guaranteed on x86 only). Hence, we can get rid of RewriteInstance extensions that were meant to support "large" functions.
1 parent 6b2de10 commit 1b8e0cf

File tree

5 files changed

+28
-55
lines changed

5 files changed

+28
-55
lines changed

bolt/include/bolt/Core/Exceptions.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,14 @@ class CFIReaderWriter {
4343

4444
/// Generate .eh_frame_hdr from old and new .eh_frame sections.
4545
///
46-
/// Take FDEs from the \p NewEHFrame unless their initial_pc is listed
47-
/// in \p FailedAddresses. All other entries are taken from the
46+
/// Take FDEs from the \p NewEHFrame. All other entries are taken from the
4847
/// \p OldEHFrame.
4948
///
5049
/// \p EHFrameHeaderAddress specifies location of .eh_frame_hdr,
5150
/// and is required for relative addressing used in the section.
52-
std::vector<char>
53-
generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame,
54-
const DWARFDebugFrame &NewEHFrame,
55-
uint64_t EHFrameHeaderAddress,
56-
std::vector<uint64_t> &FailedAddresses) const;
51+
std::vector<char> generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame,
52+
const DWARFDebugFrame &NewEHFrame,
53+
uint64_t EHFrameHeaderAddress) const;
5754

5855
using FDEsMap = std::map<uint64_t, const dwarf::FDE *>;
5956

bolt/include/bolt/Rewrite/RewriteInstance.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -556,14 +556,6 @@ class RewriteInstance {
556556
return ErrOrSection ? &ErrOrSection.get() : nullptr;
557557
}
558558

559-
/// Keep track of functions we fail to write in the binary. We need to avoid
560-
/// rewriting CFI info for these functions.
561-
std::vector<uint64_t> FailedAddresses;
562-
563-
/// Keep track of which functions didn't fit in their original space in the
564-
/// last emission, so that we may either decide to split or not optimize them.
565-
std::set<uint64_t> LargeFunctions;
566-
567559
/// Section header string table.
568560
StringTableBuilder SHStrTab;
569561

bolt/lib/Core/Exceptions.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -665,16 +665,13 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
665665
return true;
666666
}
667667

668-
std::vector<char> CFIReaderWriter::generateEHFrameHeader(
669-
const DWARFDebugFrame &OldEHFrame, const DWARFDebugFrame &NewEHFrame,
670-
uint64_t EHFrameHeaderAddress,
671-
std::vector<uint64_t> &FailedAddresses) const {
668+
std::vector<char>
669+
CFIReaderWriter::generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame,
670+
const DWARFDebugFrame &NewEHFrame,
671+
uint64_t EHFrameHeaderAddress) const {
672672
// Common PC -> FDE map to be written into .eh_frame_hdr.
673673
std::map<uint64_t, uint64_t> PCToFDE;
674674

675-
// Presort array for binary search.
676-
llvm::sort(FailedAddresses);
677-
678675
// Initialize PCToFDE using NewEHFrame.
679676
for (dwarf::FrameEntry &Entry : NewEHFrame.entries()) {
680677
const dwarf::FDE *FDE = dyn_cast<dwarf::FDE>(&Entry);
@@ -689,13 +686,7 @@ std::vector<char> CFIReaderWriter::generateEHFrameHeader(
689686
continue;
690687

691688
// Add the address to the map unless we failed to write it.
692-
if (!std::binary_search(FailedAddresses.begin(), FailedAddresses.end(),
693-
FuncAddress)) {
694-
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: FDE for function at 0x"
695-
<< Twine::utohexstr(FuncAddress) << " is at 0x"
696-
<< Twine::utohexstr(FDEAddress) << '\n');
697-
PCToFDE[FuncAddress] = FDEAddress;
698-
}
689+
PCToFDE[FuncAddress] = FDEAddress;
699690
};
700691

701692
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: new .eh_frame contains "

bolt/lib/Passes/BinaryPasses.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,10 +588,18 @@ Error CheckLargeFunctions::runOnFunctions(BinaryContext &BC) {
588588
uint64_t HotSize, ColdSize;
589589
std::tie(HotSize, ColdSize) =
590590
BC.calculateEmittedSize(BF, /*FixBranches=*/false);
591-
if (HotSize > BF.getMaxSize()) {
591+
uint64_t MainFragmentSize = HotSize;
592+
if (BF.hasIslandsInfo()) {
593+
MainFragmentSize +=
594+
offsetToAlignment(BF.getAddress() + MainFragmentSize,
595+
Align(BF.getConstantIslandAlignment()));
596+
MainFragmentSize += BF.estimateConstantIslandSize();
597+
}
598+
if (MainFragmentSize > BF.getMaxSize()) {
592599
if (opts::PrintLargeFunctions)
593-
BC.outs() << "BOLT-INFO: " << BF << " size exceeds allocated space by "
594-
<< (HotSize - BF.getMaxSize()) << " bytes\n";
600+
BC.outs() << "BOLT-INFO: " << BF << " size of " << MainFragmentSize
601+
<< " bytes exceeds allocated space by "
602+
<< (MainFragmentSize - BF.getMaxSize()) << " bytes\n";
595603
BF.setSimple(false);
596604
}
597605
};

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,7 +3807,6 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
38073807
if (!Function.isEmitted())
38083808
continue;
38093809

3810-
bool TooLarge = false;
38113810
ErrorOr<BinarySection &> FuncSection = Function.getCodeSection();
38123811
assert(FuncSection && "cannot find section for function");
38133812
FuncSection->setOutputAddress(Function.getAddress());
@@ -3818,11 +3817,8 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
38183817
MapSection(*FuncSection, Function.getAddress());
38193818
Function.setImageAddress(FuncSection->getAllocAddress());
38203819
Function.setImageSize(FuncSection->getOutputSize());
3821-
if (Function.getImageSize() > Function.getMaxSize()) {
3822-
assert(!BC->isX86() && "Unexpected large function.");
3823-
TooLarge = true;
3824-
FailedAddresses.emplace_back(Function.getAddress());
3825-
}
3820+
assert(Function.getImageSize() <= Function.getMaxSize() &&
3821+
"Unexpected large function");
38263822

38273823
// Map jump tables if updating in-place.
38283824
if (opts::JumpTables == JTS_BASIC) {
@@ -3852,29 +3848,18 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
38523848
assert(ColdSection && "cannot find section for cold part");
38533849
// Cold fragments are aligned at 16 bytes.
38543850
NextAvailableAddress = alignTo(NextAvailableAddress, 16);
3855-
if (TooLarge) {
3856-
// The corresponding FDE will refer to address 0.
3857-
FF.setAddress(0);
3858-
FF.setImageAddress(0);
3859-
FF.setImageSize(0);
3860-
FF.setFileOffset(0);
3861-
} else {
3862-
FF.setAddress(NextAvailableAddress);
3863-
FF.setImageAddress(ColdSection->getAllocAddress());
3864-
FF.setImageSize(ColdSection->getOutputSize());
3865-
FF.setFileOffset(getFileOffsetForAddress(NextAvailableAddress));
3866-
ColdSection->setOutputAddress(FF.getAddress());
3867-
}
3851+
FF.setAddress(NextAvailableAddress);
3852+
FF.setImageAddress(ColdSection->getAllocAddress());
3853+
FF.setImageSize(ColdSection->getOutputSize());
3854+
FF.setFileOffset(getFileOffsetForAddress(NextAvailableAddress));
3855+
ColdSection->setOutputAddress(FF.getAddress());
38683856

38693857
LLVM_DEBUG(
38703858
dbgs() << formatv(
38713859
"BOLT: mapping cold fragment {0:x+} to {1:x+} with size {2:x+}\n",
38723860
FF.getImageAddress(), FF.getAddress(), FF.getImageSize()));
38733861
MapSection(*ColdSection, FF.getAddress());
38743862

3875-
if (TooLarge)
3876-
BC->deregisterSection(*ColdSection);
3877-
38783863
NextAvailableAddress += FF.getImageSize();
38793864
}
38803865

@@ -5814,7 +5799,7 @@ void RewriteInstance::writeEHFrameHeader() {
58145799
getFileOffsetForAddress(NextAvailableAddress);
58155800

58165801
std::vector<char> NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
5817-
RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses);
5802+
RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress);
58185803

58195804
Out->os().seek(EHFrameHdrFileOffset);
58205805
Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size());

0 commit comments

Comments
 (0)