Skip to content

Commit 9476fad

Browse files
committed
Preserve CFG until BAT, use it to check call cont landing pads, encode them in secondary entry points table
1 parent d59024b commit 9476fad

File tree

5 files changed

+44
-126
lines changed

5 files changed

+44
-126
lines changed

bolt/docs/BAT.md

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,13 @@ Deleted basic blocks are emitted as having `OutputOffset` equal to the size of
115115
the function. They don't affect address translation and only participate in
116116
input basic block mapping.
117117

118-
### Secondary Entry Points table
118+
### Secondary Entry Points and Call Continuation Landing Pads table
119119
The table is emitted for hot fragments only. It contains `NumSecEntryPoints`
120-
offsets denoting secondary entry points, delta encoded, implicitly starting at zero.
120+
offsets, delta encoded, implicitly starting at zero.
121121
| Entry | Encoding | Description |
122122
| ----- | -------- | ----------- |
123-
| `SecEntryPoint` | Delta, ULEB128 | Secondary entry point offset |
123+
| `OutputOffset` | Delta, ULEB128 | An offset of secondary entry point or a call continuation landing pad\*|
124124

125-
### Call continuation landing pads table
126-
This table contains the addresses of call continuation blocks that are also
127-
landing pads, to aid pre-aggregated profile conversion. The table is optional
128-
for backwards compatibility, but new versions of BOLT will always emit it.
129-
130-
| Entry | Encoding | Description |
131-
| ----- | -------- | ----------- |
132-
| `NumEntries` | ULEB128 | Number of addresses |
133-
| `InputAddress` | Delta, ULEB128 | `NumEntries` input addresses of call continuation landing pad blocks |
134-
135-
Addresses are delta encoded, implicitly starting at zero.
125+
Call continuation landing pads offsets are shifted by the size of the function
126+
for backwards compatibility (treated as entry points past the end of the
127+
function).

bolt/include/bolt/Profile/BoltAddressTranslation.h

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,12 @@ class BoltAddressTranslation {
143143
/// Write the serialized address translation table for a function.
144144
template <bool Cold> void writeMaps(uint64_t &PrevAddress, raw_ostream &OS);
145145

146-
/// Write call continuation landing pad addresses.
147-
void writeCallContLandingPads(raw_ostream &OS);
148-
149146
/// Read the serialized address translation table for a function.
150147
/// Return a parse error if failed.
151148
template <bool Cold>
152149
void parseMaps(uint64_t &PrevAddress, DataExtractor &DE, uint64_t &Offset,
153150
Error &Err);
154151

155-
156-
/// Read the table with call continuation landing pad offsets.
157-
void parseCallContLandingPads(DataExtractor &DE, uint64_t &Offset,
158-
Error &Err);
159-
160152
/// Returns the bitmask with set bits corresponding to indices of BRANCHENTRY
161153
/// entries in function address translation map.
162154
APInt calculateBranchEntriesBitMask(MapTy &Map, size_t EqualElems) const;
@@ -176,14 +168,6 @@ class BoltAddressTranslation {
176168
/// Map a function to its secondary entry points vector
177169
std::unordered_map<uint64_t, std::vector<uint32_t>> SecondaryEntryPointsMap;
178170

179-
/// Vector with call continuation landing pads input addresses (pre-BOLT
180-
/// binary).
181-
std::vector<uint64_t> CallContLandingPadAddrs;
182-
183-
/// Return a secondary entry point ID for a function located at \p Address and
184-
/// \p Offset within that function.
185-
unsigned getSecondaryEntryPointId(uint64_t Address, uint32_t Offset) const;
186-
187171
/// Links outlined cold bocks to their original function
188172
std::map<uint64_t, uint64_t> ColdPartSource;
189173

@@ -195,13 +179,9 @@ class BoltAddressTranslation {
195179
const static uint32_t BRANCHENTRY = 0x1;
196180

197181
public:
198-
/// Returns whether a given \p Offset is a secondary entry point in function
199-
/// with address \p Address.
200-
bool isSecondaryEntry(uint64_t Address, uint32_t Offset) const;
201-
202-
/// Returns whether a given \p Offset is a call continuation landing pad in
203-
/// function with address \p Address.
204-
bool isCallContinuationLandingPad(uint64_t Address, uint32_t Offset) const;
182+
/// Return a secondary entry point ID for a function located at \p Address and
183+
/// \p Offset within that function.
184+
unsigned getSecondaryEntryPointId(uint64_t Address, uint32_t Offset) const;
205185

206186
/// Map basic block input offset to a basic block index and hash pair.
207187
class BBHashMapTy {

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ void BinaryEmitter::emitFunctions() {
257257
Streamer.setAllowAutoPadding(OriginalAllowAutoPadding);
258258

259259
if (Emitted)
260-
Function->setEmitted(/*KeepCFG=*/opts::PrintCacheMetrics);
260+
Function->setEmitted(/*KeepCFG=*/opts::PrintCacheMetrics ||
261+
opts::EnableBAT);
261262
}
262263
};
263264

bolt/lib/Profile/BoltAddressTranslation.cpp

Lines changed: 28 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,28 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
8787
continue;
8888

8989
uint32_t NumSecondaryEntryPoints = 0;
90-
Function.forEachEntryPoint([&](uint64_t Offset, const MCSymbol *) {
91-
if (!Offset)
92-
return true;
90+
for (const BinaryBasicBlock &BB : llvm::drop_begin(Function)) {
91+
if (BB.isEntryPoint()) {
92+
++NumSecondaryEntryPoints;
93+
SecondaryEntryPointsMap[OutputAddress].push_back(BB.getOffset());
94+
continue;
95+
}
96+
// Add call continuation landing pads, offset by function size
97+
if (!BB.isLandingPad())
98+
continue;
99+
const BinaryBasicBlock *PrevBB =
100+
Function.getLayout().getBlock(BB.getIndex() - 1);
101+
if (!PrevBB->isSuccessor(&BB))
102+
continue;
103+
const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
104+
if (!Instr || !BC.MIB->isCall(*Instr))
105+
continue;
93106
++NumSecondaryEntryPoints;
94-
SecondaryEntryPointsMap[OutputAddress].push_back(Offset);
95-
return true;
96-
});
107+
SecondaryEntryPointsMap[OutputAddress].push_back(
108+
Function.getOutputSize() + BB.getOffset());
109+
}
110+
if (NumSecondaryEntryPoints)
111+
llvm::sort(SecondaryEntryPointsMap[OutputAddress]);
97112

98113
LLVM_DEBUG(dbgs() << "Function name: " << Function.getPrintName() << "\n");
99114
LLVM_DEBUG(dbgs() << " Address reference: 0x"
@@ -145,7 +160,6 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
145160
uint64_t PrevAddress = 0;
146161
writeMaps</*Cold=*/false>(PrevAddress, OS);
147162
writeMaps</*Cold=*/true>(PrevAddress, OS);
148-
writeCallContLandingPads(OS);
149163

150164
BC.outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n";
151165
BC.outs() << "BOLT-INFO: Wrote " << FuncHashes.getNumFunctions()
@@ -292,15 +306,6 @@ void BoltAddressTranslation::writeMaps(uint64_t &PrevAddress, raw_ostream &OS) {
292306
}
293307
}
294308

295-
void BoltAddressTranslation::writeCallContLandingPads(raw_ostream &OS) {
296-
encodeULEB128(CallContLandingPadAddrs.size(), OS);
297-
uint64_t PrevAddress = 0;
298-
for (const uint64_t Address : CallContLandingPadAddrs) {
299-
encodeULEB128(Address - PrevAddress, OS);
300-
PrevAddress = Address;
301-
}
302-
}
303-
304309
std::error_code BoltAddressTranslation::parse(raw_ostream &OS, StringRef Buf) {
305310
DataExtractor DE = DataExtractor(Buf, true, 8);
306311
uint64_t Offset = 0;
@@ -325,8 +330,6 @@ std::error_code BoltAddressTranslation::parse(raw_ostream &OS, StringRef Buf) {
325330
parseMaps</*Cold=*/false>(PrevAddress, DE, Offset, Err);
326331
parseMaps</*Cold=*/true>(PrevAddress, DE, Offset, Err);
327332
OS << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n";
328-
if (Offset < Buf.size())
329-
parseCallContLandingPads(DE, Offset, Err);
330333
return errorToErrorCode(std::move(Err));
331334
}
332335

@@ -446,21 +449,6 @@ void BoltAddressTranslation::parseMaps(uint64_t &PrevAddress, DataExtractor &DE,
446449
}
447450
}
448451

449-
void BoltAddressTranslation::parseCallContLandingPads(DataExtractor &DE,
450-
uint64_t &Offset,
451-
Error &Err) {
452-
const uint32_t NumEntries = DE.getULEB128(&Offset, &Err);
453-
LLVM_DEBUG(dbgs() << "Parsing " << NumEntries
454-
<< " call continuation landing pad entries\n");
455-
CallContLandingPadAddrs.reserve(NumEntries);
456-
uint64_t PrevAddress = 0;
457-
for (uint32_t I = 0; I < NumEntries; ++I) {
458-
const uint64_t Address = PrevAddress + DE.getULEB128(&Offset, &Err);
459-
CallContLandingPadAddrs.emplace_back(Address);
460-
PrevAddress = Address;
461-
}
462-
}
463-
464452
void BoltAddressTranslation::dump(raw_ostream &OS) const {
465453
const size_t NumTables = Maps.size();
466454
OS << "BAT tables for " << NumTables << " functions:\n";
@@ -609,25 +597,14 @@ void BoltAddressTranslation::saveMetadata(BinaryContext &BC) {
609597
// changed
610598
if (BF.isIgnored() || (!BC.HasRelocations && !BF.isSimple()))
611599
continue;
612-
const uint64_t FuncAddress = BF.getAddress();
613600
// Prepare function and block hashes
614-
FuncHashes.addEntry(FuncAddress, BF.computeHash());
601+
FuncHashes.addEntry(BF.getAddress(), BF.computeHash());
615602
BF.computeBlockHashes();
616-
BBHashMapTy &BBHashMap = getBBHashMap(FuncAddress);
603+
BBHashMapTy &BBHashMap = getBBHashMap(BF.getAddress());
617604
// Set BF/BB metadata
618-
for (const BinaryBasicBlock &BB : BF) {
619-
const uint32_t BlockOffset = BB.getInputOffset();
620-
BBHashMap.addEntry(BlockOffset, BB.getIndex(), BB.getHash());
621-
// Set CallContLandingPads
622-
if (!BB.isEntryPoint() && BB.isLandingPad()) {
623-
const BinaryBasicBlock *PrevBB =
624-
BF.getLayout().getBlock(BB.getIndex() - 1);
625-
const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
626-
if (Instr && BC.MIB->isCall(*Instr))
627-
CallContLandingPadAddrs.emplace_back(FuncAddress + BlockOffset);
628-
}
629-
}
630-
NumBasicBlocksMap.emplace(FuncAddress, BF.size());
605+
for (const BinaryBasicBlock &BB : BF)
606+
BBHashMap.addEntry(BB.getInputOffset(), BB.getIndex(), BB.getHash());
607+
NumBasicBlocksMap.emplace(BF.getAddress(), BF.size());
631608
}
632609
}
633610

@@ -638,8 +615,8 @@ BoltAddressTranslation::getSecondaryEntryPointId(uint64_t Address,
638615
if (FunctionIt == SecondaryEntryPointsMap.end())
639616
return 0;
640617
const std::vector<uint32_t> &Offsets = FunctionIt->second;
641-
auto OffsetIt = std::find(Offsets.begin(), Offsets.end(), Offset);
642-
if (OffsetIt == Offsets.end())
618+
auto OffsetIt = llvm::lower_bound(FunctionIt->second, Offset);
619+
if (OffsetIt == Offsets.end() || *OffsetIt != Offset)
643620
return 0;
644621
// Adding one here because main entry point is not stored in BAT, and
645622
// enumeration for secondary entry points starts with 1.
@@ -675,30 +652,5 @@ BoltAddressTranslation::translateSymbol(const BinaryContext &BC,
675652
return std::pair(ParentBF, SecondaryEntryId);
676653
}
677654

678-
bool BoltAddressTranslation::isSecondaryEntry(uint64_t OutputAddress,
679-
uint32_t Offset) const {
680-
const uint64_t InputOffset =
681-
translate(OutputAddress, Offset, /*IsBranchSrc*/ false);
682-
683-
const uint64_t HotAddress = fetchParentAddress(OutputAddress);
684-
auto MapsIter = Maps.find(HotAddress ? HotAddress : OutputAddress);
685-
if (MapsIter == Maps.end())
686-
return false;
687-
688-
const uint64_t InputAddress = MapsIter->second.begin()->second;
689-
690-
auto FunctionIt = SecondaryEntryPointsMap.find(Address);
691-
if (FunctionIt == SecondaryEntryPointsMap.end())
692-
return false;
693-
const std::vector<uint32_t> &Offsets = FunctionIt->second;
694-
uint64_t InputOffset = translate(OutputAddress, Offset, /*IsBranchSrc*/ false);
695-
auto OffsetIt = llvm::lower_bound(Offsets, InputOffset << 1);
696-
return OffsetIt != Offsets.end() && *OffsetIt >> 1 == InputOffset;
697-
}
698-
699-
bool BoltAddressTranslation::isCallContinuationLandingPad(
700-
uint64_t Address, uint32_t Offset) const {
701-
}
702-
703655
} // namespace bolt
704656
} // namespace llvm

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -809,18 +809,11 @@ bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
809809
return false;
810810

811811
if (!Func.hasCFG()) {
812-
if (!BAT)
813-
return false;
814-
const uint64_t FuncAddress = Func.getAddress();
815-
const BinaryData *BD =
816-
BC->getBinaryDataAtAddress(FuncAddress + Offset);
817-
unsigned EntryID = 0;
818-
if (BD && BD->getSymbol())
819-
EntryID = BAT->translateSymbol(*BC, *BD->getSymbol(), 0).second;
820-
const MCSymbol &Symbol =
821-
const auto [Function, EntryID] = BAT->translateSymbol(BC,
822-
return BAT && !(BAT->isSecondaryEntry(FuncAddress, Offset) ||
823-
BAT->isCallContinuationLandingPad(FuncAddress, Offset));
812+
const uint64_t Address = Func.getAddress();
813+
// Check if offset is a secondary entry point or a call continuation
814+
// landing pad (offset shifted by function size).
815+
return BAT && !BAT->getSecondaryEntryPointId(Address, Offset) &&
816+
!BAT->getSecondaryEntryPointId(Address, Func.getSize() + Offset);
824817
}
825818

826819
// The offset should not be an entry point or a landing pad.

0 commit comments

Comments
 (0)