Skip to content

Commit b6adebc

Browse files
committed
[𝘀𝗽𝗿] changes to main this commit is based on
Created using spr 1.3.4 [skip ci]
1 parent 6ffefbb commit b6adebc

File tree

7 files changed

+273
-68
lines changed

7 files changed

+273
-68
lines changed

bolt/docs/BAT.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Functions table:
5454
| table |
5555
| |
5656
| Secondary entry |
57-
| points |
57+
| points and LPs |
5858
|------------------|
5959
6060
```
@@ -80,7 +80,7 @@ Hot indices are delta encoded, implicitly starting at zero.
8080
| `HotIndex` | Delta, ULEB128 | Index of corresponding hot function in hot functions table | Cold |
8181
| `FuncHash` | 8b | Function hash for input function | Hot |
8282
| `NumBlocks` | ULEB128 | Number of basic blocks in the original function | Hot |
83-
| `NumSecEntryPoints` | ULEB128 | Number of secondary entry points in the original function | Hot |
83+
| `NumSecEntryPoints` | ULEB128 | Number of secondary entry points and landing pads in the original function | Hot |
8484
| `ColdInputSkew` | ULEB128 | Skew to apply to all input offsets | Cold |
8585
| `NumEntries` | ULEB128 | Number of address translation entries for a function | Both |
8686
| `EqualElems` | ULEB128 | Number of equal offsets in the beginning of a function | Both |
@@ -116,7 +116,11 @@ input basic block mapping.
116116

117117
### Secondary Entry Points table
118118
The table is emitted for hot fragments only. It contains `NumSecEntryPoints`
119-
offsets denoting secondary entry points, delta encoded, implicitly starting at zero.
119+
offsets denoting secondary entry points and landing pads, delta encoded,
120+
implicitly starting at zero.
120121
| Entry | Encoding | Description |
121122
| ----- | -------- | ----------- |
122-
| `SecEntryPoint` | Delta, ULEB128 | Secondary entry point offset |
123+
| `SecEntryPoint` | Delta, ULEB128 | Secondary entry point offset with `LPENTRY` LSB bit |
124+
125+
`LPENTRY` bit denotes whether a given offset is a landing pad block. If not set,
126+
the offset is a secondary entry point.

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,10 @@ class BinaryFunction {
908908
return BB && BB->getOffset() == Offset ? BB : nullptr;
909909
}
910910

911+
const BinaryBasicBlock *getBasicBlockAtOffset(uint64_t Offset) const {
912+
return const_cast<BinaryFunction *>(this)->getBasicBlockAtOffset(Offset);
913+
}
914+
911915
/// Retrieve the landing pad BB associated with invoke instruction \p Invoke
912916
/// that is in \p BB. Return nullptr if none exists
913917
BinaryBasicBlock *getLandingPadBBFor(const BinaryBasicBlock &BB,

bolt/include/bolt/Profile/BoltAddressTranslation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ class BoltAddressTranslation {
182182
/// translation map entry
183183
const static uint32_t BRANCHENTRY = 0x1;
184184

185+
/// Identifies a landing pad in secondary entry point map entry.
186+
const static uint32_t LPENTRY = 0x1;
187+
185188
public:
186189
/// Map basic block input offset to a basic block index and hash pair.
187190
class BBHashMapTy {

bolt/include/bolt/Profile/DataAggregator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ class DataAggregator : public DataReader {
266266
uint64_t Mispreds);
267267

268268
/// Register a \p Branch.
269-
bool doBranch(uint64_t From, uint64_t To, uint64_t Count, uint64_t Mispreds);
269+
bool doBranch(uint64_t From, uint64_t To, uint64_t Count, uint64_t Mispreds,
270+
bool IsPreagg);
270271

271272
/// Register a trace between two LBR entries supplied in execution order.
272273
bool doTrace(const LBREntry &First, const LBREntry &Second,

bolt/lib/Profile/BoltAddressTranslation.cpp

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,16 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
8686
if (Function.isIgnored() || (!BC.HasRelocations && !Function.isSimple()))
8787
continue;
8888

89-
uint32_t NumSecondaryEntryPoints = 0;
90-
Function.forEachEntryPoint([&](uint64_t Offset, const MCSymbol *) {
91-
if (!Offset)
92-
return true;
93-
++NumSecondaryEntryPoints;
94-
SecondaryEntryPointsMap[OutputAddress].push_back(Offset);
95-
return true;
96-
});
97-
9889
LLVM_DEBUG(dbgs() << "Function name: " << Function.getPrintName() << "\n");
9990
LLVM_DEBUG(dbgs() << " Address reference: 0x"
10091
<< Twine::utohexstr(Function.getOutputAddress()) << "\n");
10192
LLVM_DEBUG(dbgs() << formatv(" Hash: {0:x}\n", getBFHash(InputAddress)));
102-
LLVM_DEBUG(dbgs() << " Secondary Entry Points: " << NumSecondaryEntryPoints
103-
<< '\n');
93+
LLVM_DEBUG({
94+
uint32_t NumSecondaryEntryPoints = 0;
95+
if (SecondaryEntryPointsMap.count(InputAddress))
96+
NumSecondaryEntryPoints = SecondaryEntryPointsMap[InputAddress].size();
97+
dbgs() << " Secondary Entry Points: " << NumSecondaryEntryPoints << '\n';
98+
});
10499

105100
MapTy Map;
106101
for (const BinaryBasicBlock *const BB :
@@ -206,10 +201,9 @@ void BoltAddressTranslation::writeMaps(uint64_t &PrevAddress, raw_ostream &OS) {
206201
<< Twine::utohexstr(Address) << ".\n");
207202
encodeULEB128(Address - PrevAddress, OS);
208203
PrevAddress = Address;
209-
const uint32_t NumSecondaryEntryPoints =
210-
SecondaryEntryPointsMap.count(Address)
211-
? SecondaryEntryPointsMap[Address].size()
212-
: 0;
204+
uint32_t NumSecondaryEntryPoints = 0;
205+
if (SecondaryEntryPointsMap.count(HotInputAddress))
206+
NumSecondaryEntryPoints = SecondaryEntryPointsMap[HotInputAddress].size();
213207
uint32_t Skew = 0;
214208
if (Cold) {
215209
auto HotEntryIt = llvm::lower_bound(HotFuncs, ColdPartSource[Address]);
@@ -281,7 +275,7 @@ void BoltAddressTranslation::writeMaps(uint64_t &PrevAddress, raw_ostream &OS) {
281275
if (!Cold && NumSecondaryEntryPoints) {
282276
LLVM_DEBUG(dbgs() << "Secondary entry points: ");
283277
// Secondary entry point offsets, delta-encoded
284-
for (uint32_t Offset : SecondaryEntryPointsMap[Address]) {
278+
for (uint32_t Offset : SecondaryEntryPointsMap[HotInputAddress]) {
285279
encodeULEB128(Offset - PrevOffset, OS);
286280
LLVM_DEBUG(dbgs() << formatv("{0:x} ", Offset));
287281
PrevOffset = Offset;
@@ -469,8 +463,12 @@ void BoltAddressTranslation::dump(raw_ostream &OS) const {
469463
const std::vector<uint32_t> &SecondaryEntryPoints =
470464
SecondaryEntryPointsIt->second;
471465
OS << SecondaryEntryPoints.size() << " secondary entry points:\n";
472-
for (uint32_t EntryPointOffset : SecondaryEntryPoints)
473-
OS << formatv("{0:x}\n", EntryPointOffset);
466+
for (uint32_t EntryPointOffset : SecondaryEntryPoints) {
467+
OS << formatv("{0:x}", EntryPointOffset >> 1);
468+
if (EntryPointOffset & LPENTRY)
469+
OS << " (lp)";
470+
OS << '\n';
471+
}
474472
}
475473
OS << "\n";
476474
}
@@ -582,14 +580,21 @@ void BoltAddressTranslation::saveMetadata(BinaryContext &BC) {
582580
// changed
583581
if (BF.isIgnored() || (!BC.HasRelocations && !BF.isSimple()))
584582
continue;
583+
const uint64_t FuncAddress = BF.getAddress();
585584
// Prepare function and block hashes
586-
FuncHashes.addEntry(BF.getAddress(), BF.computeHash());
585+
FuncHashes.addEntry(FuncAddress, BF.computeHash());
587586
BF.computeBlockHashes();
588-
BBHashMapTy &BBHashMap = getBBHashMap(BF.getAddress());
587+
BBHashMapTy &BBHashMap = getBBHashMap(FuncAddress);
588+
std::vector<uint32_t> SecondaryEntryPoints;
589589
// Set BF/BB metadata
590-
for (const BinaryBasicBlock &BB : BF)
590+
for (const BinaryBasicBlock &BB : BF) {
591591
BBHashMap.addEntry(BB.getInputOffset(), BB.getIndex(), BB.getHash());
592-
NumBasicBlocksMap.emplace(BF.getAddress(), BF.size());
592+
bool IsLandingPad = BB.isLandingPad();
593+
if (IsLandingPad || BF.getSecondaryEntryPointSymbol(BB))
594+
SecondaryEntryPoints.emplace_back(BB.getOffset() << 1 | IsLandingPad);
595+
}
596+
SecondaryEntryPointsMap.emplace(FuncAddress, SecondaryEntryPoints);
597+
NumBasicBlocksMap.emplace(FuncAddress, BF.size());
593598
}
594599
}
595600

@@ -599,13 +604,20 @@ BoltAddressTranslation::getSecondaryEntryPointId(uint64_t Address,
599604
auto FunctionIt = SecondaryEntryPointsMap.find(Address);
600605
if (FunctionIt == SecondaryEntryPointsMap.end())
601606
return 0;
602-
const std::vector<uint32_t> &Offsets = FunctionIt->second;
603-
auto OffsetIt = std::find(Offsets.begin(), Offsets.end(), Offset);
604-
if (OffsetIt == Offsets.end())
605-
return 0;
606-
// Adding one here because main entry point is not stored in BAT, and
607-
// enumeration for secondary entry points starts with 1.
608-
return OffsetIt - Offsets.begin() + 1;
607+
unsigned EntryPoints = 0;
608+
// Note we need to scan the vector to get the entry point id because it
609+
// contains both entry points and landing pads.
610+
for (uint32_t Off : FunctionIt->second) {
611+
// Skip landing pads.
612+
if (Off & LPENTRY)
613+
continue;
614+
// Adding one here because main entry point is not stored in BAT, and
615+
// enumeration for secondary entry points starts with 1.
616+
if (Off >> 1 == Offset)
617+
return EntryPoints + 1;
618+
++EntryPoints;
619+
}
620+
return 0;
609621
}
610622

611623
std::pair<const BinaryFunction *, unsigned>

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -778,42 +778,75 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
778778
}
779779

780780
bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
781-
uint64_t Mispreds) {
782-
bool IsReturn = false;
783-
auto handleAddress = [&](uint64_t &Addr, bool IsFrom) -> BinaryFunction * {
784-
if (BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr)) {
785-
Addr -= Func->getAddress();
786-
if (IsFrom) {
787-
auto checkReturn = [&](auto MaybeInst) {
788-
IsReturn = MaybeInst && BC->MIB->isReturn(*MaybeInst);
789-
};
790-
if (Func->hasInstructions())
791-
checkReturn(Func->getInstructionAtOffset(Addr));
792-
else
793-
checkReturn(Func->disassembleInstructionAtOffset(Addr));
794-
}
781+
uint64_t Mispreds, bool IsPreagg) {
782+
// Returns whether \p Offset in \p Func contains a return instruction.
783+
auto checkReturn = [&](const BinaryFunction &Func, const uint64_t Offset) {
784+
auto isReturn = [&](auto MI) { return MI && BC->MIB->isReturn(*MI); };
785+
return Func.hasInstructions()
786+
? isReturn(Func.getInstructionAtOffset(Offset))
787+
: isReturn(Func.disassembleInstructionAtOffset(Offset));
788+
};
795789

796-
if (BAT)
797-
Addr = BAT->translate(Func->getAddress(), Addr, IsFrom);
790+
// Returns whether \p Offset in \p Func may be a call continuation excluding
791+
// entry points and landing pads.
792+
auto checkCallCont = [&](const BinaryFunction &Func, const uint64_t Offset) {
793+
// No call continuation at a function start.
794+
if (!Offset)
795+
return false;
796+
797+
// FIXME: support BAT case where the function might be in empty state
798+
// (split fragments declared non-simple).
799+
if (!Func.hasCFG())
800+
return false;
801+
802+
// The offset should not be an entry point or a landing pad.
803+
const BinaryBasicBlock *ContBB = Func.getBasicBlockAtOffset(Offset);
804+
return ContBB && !ContBB->isEntryPoint() && !ContBB->isLandingPad();
805+
};
798806

799-
if (BinaryFunction *ParentFunc = getBATParentFunction(*Func)) {
800-
Func = ParentFunc;
801-
if (IsFrom)
802-
NumColdSamples += Count;
803-
}
807+
// Mutates \p Addr to an offset into the containing function, performing BAT
808+
// offset translation and parent lookup.
809+
//
810+
// Returns the containing function (or BAT parent) and whether the address
811+
// corresponds to a return (if \p IsFrom) or a call continuation (otherwise).
812+
auto handleAddress = [&](uint64_t &Addr, bool IsFrom) {
813+
BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr);
814+
if (!Func)
815+
return std::pair{Func, false};
804816

805-
return Func;
806-
}
807-
return nullptr;
817+
Addr -= Func->getAddress();
818+
819+
bool IsRetOrCallCont =
820+
IsFrom ? checkReturn(*Func, Addr) : checkCallCont(*Func, Addr);
821+
822+
if (BAT)
823+
Addr = BAT->translate(Func->getAddress(), Addr, IsFrom);
824+
825+
BinaryFunction *ParentFunc = getBATParentFunction(*Func);
826+
if (!ParentFunc)
827+
return std::pair{Func, IsRetOrCallCont};
828+
829+
if (IsFrom)
830+
NumColdSamples += Count;
831+
832+
return std::pair{ParentFunc, IsRetOrCallCont};
808833
};
809834

810-
BinaryFunction *FromFunc = handleAddress(From, /*IsFrom=*/true);
835+
uint64_t ToOrig = To;
836+
auto [FromFunc, IsReturn] = handleAddress(From, /*IsFrom=*/true);
837+
auto [ToFunc, IsCallCont] = handleAddress(To, /*IsFrom=*/false);
838+
if (!FromFunc && !ToFunc)
839+
return false;
840+
841+
// Record call to continuation trace.
842+
if (IsPreagg && FromFunc != ToFunc && (IsReturn || IsCallCont)) {
843+
LBREntry First{ToOrig - 1, ToOrig - 1, false};
844+
LBREntry Second{ToOrig, ToOrig, false};
845+
return doTrace(First, Second, Count);
846+
}
811847
// Ignore returns.
812848
if (IsReturn)
813849
return true;
814-
BinaryFunction *ToFunc = handleAddress(To, /*IsFrom=*/false);
815-
if (!FromFunc && !ToFunc)
816-
return false;
817850

818851
// Treat recursive control transfers as inter-branches.
819852
if (FromFunc == ToFunc && To != 0) {
@@ -830,10 +863,19 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
830863
BinaryFunction *ToFunc = getBinaryFunctionContainingAddress(Second.From);
831864
if (!FromFunc || !ToFunc) {
832865
LLVM_DEBUG({
833-
dbgs() << "Out of range trace starting in " << FromFunc->getPrintName()
834-
<< formatv(" @ {0:x}", First.To - FromFunc->getAddress())
835-
<< " and ending in " << ToFunc->getPrintName()
836-
<< formatv(" @ {0:x}\n", Second.From - ToFunc->getAddress());
866+
dbgs() << "Out of range trace starting in ";
867+
if (FromFunc)
868+
dbgs() << formatv("{0} @ {1:x}", *FromFunc,
869+
First.To - FromFunc->getAddress());
870+
else
871+
dbgs() << Twine::utohexstr(First.To);
872+
dbgs() << " and ending in ";
873+
if (ToFunc)
874+
dbgs() << formatv("{0} @ {1:x}", *ToFunc,
875+
Second.From - ToFunc->getAddress());
876+
else
877+
dbgs() << Twine::utohexstr(Second.From);
878+
dbgs() << '\n';
837879
});
838880
NumLongRangeTraces += Count;
839881
return false;
@@ -1620,7 +1662,8 @@ void DataAggregator::processBranchEvents() {
16201662
for (const auto &AggrLBR : BranchLBRs) {
16211663
const Trace &Loc = AggrLBR.first;
16221664
const TakenBranchInfo &Info = AggrLBR.second;
1623-
doBranch(Loc.From, Loc.To, Info.TakenCount, Info.MispredCount);
1665+
doBranch(Loc.From, Loc.To, Info.TakenCount, Info.MispredCount,
1666+
/*IsPreagg*/ false);
16241667
}
16251668
}
16261669

@@ -1781,7 +1824,7 @@ void DataAggregator::processPreAggregated() {
17811824
switch (AggrEntry.EntryType) {
17821825
case AggregatedLBREntry::BRANCH:
17831826
doBranch(AggrEntry.From.Offset, AggrEntry.To.Offset, AggrEntry.Count,
1784-
AggrEntry.Mispreds);
1827+
AggrEntry.Mispreds, /*IsPreagg=*/true);
17851828
break;
17861829
case AggregatedLBREntry::FT:
17871830
case AggregatedLBREntry::FT_EXTERNAL_ORIGIN: {

0 commit comments

Comments
 (0)