[SHT_LLVM_BB_ADDR_MAP] Encode and decode callsite offsets in a newly-introduced SHT_LLVM_BB_ADDR_MAP version. (#144426)
Recently, we have been looking at some optimizations targeting individual calls. In particular, we plan to extend the address mapping technique to map to individual callsites. For example, in this piece of code for a basic blocks: ``` <BB>: 1200: lea 0x1(%rcx), %rdx 1204: callq foo 1209: cmpq 0x10, %rdx 120d: ja L1 ``` We want to emit 0x9 as the call site offset for `callq foo` (the offset from the block entry to right after the call), so that we know if a sampled address is before the call or after. This PR implements the decode/encode/emit capability. The Codegen change will be implemented in a later PR.
This commit is contained in:
@@ -831,6 +831,7 @@ struct BBAddrMap {
|
||||
bool BrProb : 1;
|
||||
bool MultiBBRange : 1;
|
||||
bool OmitBBEntries : 1;
|
||||
bool CallsiteOffsets : 1;
|
||||
|
||||
bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; }
|
||||
|
||||
@@ -842,7 +843,8 @@ struct BBAddrMap {
|
||||
(static_cast<uint8_t>(BBFreq) << 1) |
|
||||
(static_cast<uint8_t>(BrProb) << 2) |
|
||||
(static_cast<uint8_t>(MultiBBRange) << 3) |
|
||||
(static_cast<uint8_t>(OmitBBEntries) << 4);
|
||||
(static_cast<uint8_t>(OmitBBEntries) << 4) |
|
||||
(static_cast<uint8_t>(CallsiteOffsets) << 5);
|
||||
}
|
||||
|
||||
// Decodes from minimum bit width representation and validates no
|
||||
@@ -851,7 +853,7 @@ struct BBAddrMap {
|
||||
Features Feat{
|
||||
static_cast<bool>(Val & (1 << 0)), static_cast<bool>(Val & (1 << 1)),
|
||||
static_cast<bool>(Val & (1 << 2)), static_cast<bool>(Val & (1 << 3)),
|
||||
static_cast<bool>(Val & (1 << 4))};
|
||||
static_cast<bool>(Val & (1 << 4)), static_cast<bool>(Val & (1 << 5))};
|
||||
if (Feat.encode() != Val)
|
||||
return createStringError(
|
||||
std::error_code(), "invalid encoding for BBAddrMap::Features: 0x%x",
|
||||
@@ -861,9 +863,10 @@ struct BBAddrMap {
|
||||
|
||||
bool operator==(const Features &Other) const {
|
||||
return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange,
|
||||
OmitBBEntries) ==
|
||||
OmitBBEntries, CallsiteOffsets) ==
|
||||
std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb,
|
||||
Other.MultiBBRange, Other.OmitBBEntries);
|
||||
Other.MultiBBRange, Other.OmitBBEntries,
|
||||
Other.CallsiteOffsets);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -914,13 +917,18 @@ struct BBAddrMap {
|
||||
uint32_t Size = 0; // Size of the basic block.
|
||||
Metadata MD = {false, false, false, false,
|
||||
false}; // Metdata for this basic block.
|
||||
// Offsets of callsites (end of call instructions), relative to the basic
|
||||
// block start.
|
||||
SmallVector<uint32_t, 1> CallsiteOffsets;
|
||||
|
||||
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD)
|
||||
: ID(ID), Offset(Offset), Size(Size), MD(MD){};
|
||||
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD,
|
||||
SmallVector<uint32_t, 1> CallsiteOffsets)
|
||||
: ID(ID), Offset(Offset), Size(Size), MD(MD),
|
||||
CallsiteOffsets(std::move(CallsiteOffsets)) {}
|
||||
|
||||
bool operator==(const BBEntry &Other) const {
|
||||
return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
|
||||
MD == Other.MD;
|
||||
MD == Other.MD && CallsiteOffsets == Other.CallsiteOffsets;
|
||||
}
|
||||
|
||||
bool hasReturn() const { return MD.HasReturn; }
|
||||
|
||||
@@ -162,6 +162,7 @@ struct BBAddrMapEntry {
|
||||
llvm::yaml::Hex64 AddressOffset;
|
||||
llvm::yaml::Hex64 Size;
|
||||
llvm::yaml::Hex64 Metadata;
|
||||
std::optional<std::vector<llvm::yaml::Hex64>> CallsiteOffsets;
|
||||
};
|
||||
uint8_t Version;
|
||||
llvm::yaml::Hex8 Feature;
|
||||
@@ -180,6 +181,20 @@ struct BBAddrMapEntry {
|
||||
return 0;
|
||||
return BBRanges->front().BaseAddress;
|
||||
}
|
||||
|
||||
// Returns if any BB entries have non-empty callsite offsets.
|
||||
bool hasAnyCallsiteOffsets() const {
|
||||
if (!BBRanges)
|
||||
return false;
|
||||
for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *BBRanges) {
|
||||
if (!BBR.BBEntries)
|
||||
continue;
|
||||
for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries)
|
||||
if (BBE.CallsiteOffsets && !BBE.CallsiteOffsets->empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct PGOAnalysisMapEntry {
|
||||
|
||||
@@ -1426,9 +1426,12 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges) {
|
||||
"BB entries info is required for BBFreq and BrProb "
|
||||
"features");
|
||||
}
|
||||
return {FuncEntryCountEnabled, BBFreqEnabled, BrProbEnabled,
|
||||
return {FuncEntryCountEnabled,
|
||||
BBFreqEnabled,
|
||||
BrProbEnabled,
|
||||
MF.hasBBSections() && NumMBBSectionRanges > 1,
|
||||
static_cast<bool>(BBAddrMapSkipEmitBBEntries)};
|
||||
static_cast<bool>(BBAddrMapSkipEmitBBEntries),
|
||||
false};
|
||||
}
|
||||
|
||||
void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
|
||||
|
||||
@@ -837,7 +837,7 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
|
||||
Version = Data.getU8(Cur);
|
||||
if (!Cur)
|
||||
break;
|
||||
if (Version > 2)
|
||||
if (Version > 3)
|
||||
return createError("unsupported SHT_LLVM_BB_ADDR_MAP version: " +
|
||||
Twine(static_cast<int>(Version)));
|
||||
Feature = Data.getU8(Cur); // Feature byte
|
||||
@@ -847,12 +847,18 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
|
||||
if (!FeatEnableOrErr)
|
||||
return FeatEnableOrErr.takeError();
|
||||
FeatEnable = *FeatEnableOrErr;
|
||||
if (Feature != 0 && Version < 2 && Cur)
|
||||
if (FeatEnable.hasPGOAnalysis() && Version < 2)
|
||||
return createError(
|
||||
"version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when "
|
||||
"PGO features are enabled: version = " +
|
||||
Twine(static_cast<int>(Version)) +
|
||||
" feature = " + Twine(static_cast<int>(Feature)));
|
||||
if (FeatEnable.CallsiteOffsets && Version < 3)
|
||||
return createError(
|
||||
"version should be >= 3 for SHT_LLVM_BB_ADDR_MAP when "
|
||||
"callsite offsets feature is enabled: version = " +
|
||||
Twine(static_cast<int>(Version)) +
|
||||
" feature = " + Twine(static_cast<int>(Feature)));
|
||||
}
|
||||
uint32_t NumBlocksInBBRange = 0;
|
||||
uint32_t NumBBRanges = 1;
|
||||
@@ -893,7 +899,23 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
|
||||
? readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr)
|
||||
: BlockIndex;
|
||||
uint32_t Offset = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
|
||||
uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
|
||||
// Read the callsite offsets.
|
||||
uint32_t LastCallsiteOffset = 0;
|
||||
SmallVector<uint32_t, 1> CallsiteOffsets;
|
||||
if (FeatEnable.CallsiteOffsets) {
|
||||
uint32_t NumCallsites =
|
||||
readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
|
||||
CallsiteOffsets.reserve(NumCallsites);
|
||||
for (uint32_t CallsiteIndex = 0;
|
||||
!ULEBSizeErr && Cur && (CallsiteIndex < NumCallsites);
|
||||
++CallsiteIndex) {
|
||||
LastCallsiteOffset +=
|
||||
readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
|
||||
CallsiteOffsets.push_back(LastCallsiteOffset);
|
||||
}
|
||||
}
|
||||
uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr) +
|
||||
LastCallsiteOffset;
|
||||
uint32_t MD = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
|
||||
if (Version >= 1) {
|
||||
// Offset is calculated relative to the end of the previous BB.
|
||||
@@ -906,7 +928,8 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
|
||||
MetadataDecodeErr = MetadataOrErr.takeError();
|
||||
break;
|
||||
}
|
||||
BBEntries.push_back({ID, Offset, Size, *MetadataOrErr});
|
||||
BBEntries.push_back(
|
||||
{ID, Offset, Size, *MetadataOrErr, CallsiteOffsets});
|
||||
}
|
||||
TotalNumBlocks += BBEntries.size();
|
||||
}
|
||||
|
||||
@@ -1452,7 +1452,7 @@ void ELFState<ELFT>::writeSectionContent(
|
||||
for (const auto &[Idx, E] : llvm::enumerate(*Section.Entries)) {
|
||||
// Write version and feature values.
|
||||
if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP) {
|
||||
if (E.Version > 2)
|
||||
if (E.Version > 3)
|
||||
WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: "
|
||||
<< static_cast<int>(E.Version)
|
||||
<< "; encoding using the most recent version";
|
||||
@@ -1483,6 +1483,8 @@ void ELFState<ELFT>::writeSectionContent(
|
||||
if (!E.BBRanges)
|
||||
continue;
|
||||
uint64_t TotalNumBlocks = 0;
|
||||
bool EmitCallsiteOffsets =
|
||||
FeatureOrErr->CallsiteOffsets || E.hasAnyCallsiteOffsets();
|
||||
for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) {
|
||||
// Write the base address of the range.
|
||||
CBA.write<uintX_t>(BBR.BaseAddress, ELFT::Endianness);
|
||||
@@ -1500,6 +1502,15 @@ void ELFState<ELFT>::writeSectionContent(
|
||||
if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP && E.Version > 1)
|
||||
SHeader.sh_size += CBA.writeULEB128(BBE.ID);
|
||||
SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset);
|
||||
if (EmitCallsiteOffsets) {
|
||||
size_t NumCallsiteOffsets =
|
||||
BBE.CallsiteOffsets ? BBE.CallsiteOffsets->size() : 0;
|
||||
SHeader.sh_size += CBA.writeULEB128(NumCallsiteOffsets);
|
||||
if (BBE.CallsiteOffsets) {
|
||||
for (uint32_t Offset : *BBE.CallsiteOffsets)
|
||||
SHeader.sh_size += CBA.writeULEB128(Offset);
|
||||
}
|
||||
}
|
||||
SHeader.sh_size += CBA.writeULEB128(BBE.Size);
|
||||
SHeader.sh_size += CBA.writeULEB128(BBE.Metadata);
|
||||
}
|
||||
|
||||
@@ -1883,6 +1883,7 @@ void MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry>::mapping(
|
||||
IO.mapRequired("AddressOffset", E.AddressOffset);
|
||||
IO.mapRequired("Size", E.Size);
|
||||
IO.mapRequired("Metadata", E.Metadata);
|
||||
IO.mapOptional("CallsiteOffsets", E.CallsiteOffsets);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::PGOAnalysisMapEntry>::mapping(
|
||||
|
||||
@@ -49,7 +49,8 @@
|
||||
# CHECK-NEXT: {
|
||||
# CHECK-NEXT: ID: 2
|
||||
# CHECK-NEXT: Offset: 0x3
|
||||
# CHECK-NEXT: Size: 0x4
|
||||
# CHECK-NEXT: Callsite Offsets: [1, 3]
|
||||
# CHECK-NEXT: Size: 0x7
|
||||
# CHECK-NEXT: HasReturn: Yes
|
||||
# CHECK-NEXT: HasTailCall: No
|
||||
# CHECK-NEXT: IsEHPad: Yes
|
||||
@@ -75,7 +76,7 @@
|
||||
# CHECK-NEXT: HasTailCall: No
|
||||
# CHECK-NEXT: IsEHPad: No
|
||||
# CHECK-NEXT: CanFallThrough: Yes
|
||||
# CHECK-NEXT: HasIndirectBranch: No
|
||||
# CHECK-NEXT: HasIndirectBranch: No
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: }
|
||||
@@ -143,8 +144,8 @@ Sections:
|
||||
ShSize: [[SIZE=<none>]]
|
||||
Link: .text
|
||||
Entries:
|
||||
- Version: 2
|
||||
Feature: 0x8
|
||||
- Version: 3
|
||||
Feature: 0x28
|
||||
BBRanges:
|
||||
- BaseAddress: [[ADDR=0x11111]]
|
||||
BBEntries:
|
||||
@@ -158,6 +159,7 @@ Sections:
|
||||
AddressOffset: 0x3
|
||||
Size: 0x4
|
||||
Metadata: 0x15
|
||||
CallsiteOffsets: [ 0x1 , 0x2 ]
|
||||
- Version: 2
|
||||
BBRanges:
|
||||
- BaseAddress: 0x22222
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# VALID-NEXT: - Name: .llvm_bb_addr_map
|
||||
# VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
|
||||
# VALID-NEXT: Entries:
|
||||
# VALID-NEXT: - Version: 2
|
||||
# VALID-NEXT: - Version: 3
|
||||
# VALID-NEXT: BBRanges:
|
||||
## The 'BaseAddress' field is omitted when it's zero.
|
||||
# VALID-NEXT: - BBEntries:
|
||||
@@ -30,15 +30,16 @@
|
||||
# VALID-NEXT: AddressOffset: 0xFFFFFFFFFFFFFFF7
|
||||
# VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8
|
||||
# VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9
|
||||
# VALID-NEXT: - Version: 2
|
||||
# VALID-NEXT: Feature: 0x8
|
||||
# VALID-NEXT: - Version: 3
|
||||
# VALID-NEXT: Feature: 0x28
|
||||
# VALID-NEXT: BBRanges:
|
||||
# VALID-NEXT: - BaseAddress: 0xFFFFFFFFFFFFFF20
|
||||
# VALID-NEXT: BBEntries:
|
||||
# VALID-NEXT: - ID: 6
|
||||
# VALID-NEXT: AddressOffset: 0xA
|
||||
# VALID-NEXT: Size: 0xB
|
||||
# VALID-NEXT: Metadata: 0xC
|
||||
# VALID-NEXT: - ID: 6
|
||||
# VALID-NEXT: AddressOffset: 0xA
|
||||
# VALID-NEXT: Size: 0xB
|
||||
# VALID-NEXT: Metadata: 0xC
|
||||
# VALID-NEXT: CallsiteOffsets: [ 0x1, 0x2 ]
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
@@ -50,7 +51,7 @@ Sections:
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
ShSize: [[SIZE=<none>]]
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
Feature: 0x0
|
||||
BBRanges:
|
||||
- BaseAddress: 0x0
|
||||
@@ -67,17 +68,18 @@ Sections:
|
||||
AddressOffset: 0xFFFFFFFFFFFFFFF7
|
||||
Size: 0xFFFFFFFFFFFFFFF8
|
||||
Metadata: 0xFFFFFFFFFFFFFFF9
|
||||
- Version: 2
|
||||
Feature: 0x8
|
||||
- Version: 3
|
||||
Feature: 0x28
|
||||
NumBBRanges: [[NUMBBRANGES=<none>]]
|
||||
BBRanges:
|
||||
- BaseAddress: 0xFFFFFFFFFFFFFF20
|
||||
NumBlocks: [[NUMBLOCKS=<none>]]
|
||||
BBEntries:
|
||||
- ID: 6
|
||||
AddressOffset: 0xA
|
||||
Size: 0xB
|
||||
Metadata: 0xC
|
||||
- ID: 6
|
||||
AddressOffset: 0xA
|
||||
Size: 0xB
|
||||
Metadata: 0xC
|
||||
CallsiteOffsets: [ 0x1, 0x2 ]
|
||||
|
||||
## Check obj2yaml can dump empty .llvm_bb_addr_map sections.
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
# Case 4: Specify Entries.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 02002000 00000000 0000010B 010203
|
||||
# CHECK-NEXT: 0000: 03002000 00000000 0000010B 01020102
|
||||
# CHECK-NEXT: 0010: 0203
|
||||
# CHECK-NEXT: )
|
||||
|
||||
# Case 5: Specify Entries and omit the Address field.
|
||||
@@ -44,28 +45,32 @@
|
||||
# CHECK: Address:
|
||||
# CHECK-SAME: {{^ 0x0$}}
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 02000000 00000000 0000010C 010203
|
||||
# CHECK-NEXT: 0000: 03000000 00000000 0000010C 010203
|
||||
# CHECK-NEXT: )
|
||||
|
||||
# Case 6: Override the NumBlocks field.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 02002000 00000000 0000020D 010203
|
||||
# CHECK-NEXT: 0000: 03002000 00000000 0000020D 010203
|
||||
# CHECK-NEXT: )
|
||||
|
||||
# Case 7: Specify empty BBRanges.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 020000
|
||||
# CHECK-NEXT: 0000: 030000
|
||||
# CHECK-NEXT: )
|
||||
|
||||
# Case 8: Specify empty BBRanges with multi-bb-range.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 020800
|
||||
# CHECK-NEXT: 0000: 030800
|
||||
# CHECK-NEXT: )
|
||||
|
||||
|
||||
# Case 9: Specify empty CallsiteOffsets.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 03202000 00000000 0000010E 01000203
|
||||
# CHECK-NEXT: )
|
||||
|
||||
|
||||
--- !ELF
|
||||
@@ -100,7 +105,7 @@ Sections:
|
||||
- Name: '.llvm_bb_addr_map (4)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
BBRanges:
|
||||
- BaseAddress: 0x0000000000000020
|
||||
BBEntries:
|
||||
@@ -108,13 +113,14 @@ Sections:
|
||||
AddressOffset: 0x00000001
|
||||
Size: 0x00000002
|
||||
Metadata: 0x00000003
|
||||
CallsiteOffsets: [0x1, 0x2]
|
||||
|
||||
## 5) When specifying the description with Entries, the 'Address' field will be
|
||||
## zero when omitted.
|
||||
- Name: '.llvm_bb_addr_map (5)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
BBRanges:
|
||||
- BBEntries:
|
||||
- ID: 12
|
||||
@@ -127,7 +133,7 @@ Sections:
|
||||
- Name: '.llvm_bb_addr_map (6)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
BBRanges:
|
||||
- BaseAddress: 0x0000000000000020
|
||||
NumBlocks: 2
|
||||
@@ -142,7 +148,7 @@ Sections:
|
||||
- Name: '.llvm_bb_addr_map (7)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
BBRanges: []
|
||||
|
||||
## 8) We can produce a SHT_LLVM_BB_ADDR_MAP section from a multi-bb-range
|
||||
@@ -150,10 +156,26 @@ Sections:
|
||||
- Name: '.llvm_bb_addr_map (8)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
Feature: 0x8
|
||||
BBRanges: []
|
||||
|
||||
## 9) We can produce a SHT_LLVM_BB_ADDR_MAP section from a description
|
||||
## with empty callsite offsets.
|
||||
- Name: '.llvm_bb_addr_map (9)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Version: 3
|
||||
Feature: 0x20
|
||||
BBRanges:
|
||||
- BaseAddress: 0x0000000000000020
|
||||
BBEntries:
|
||||
- ID: 14
|
||||
AddressOffset: 0x00000001
|
||||
Size: 0x00000002
|
||||
Metadata: 0x00000003
|
||||
CallsiteOffsets: []
|
||||
|
||||
## Check we can't use Entries at the same time as either Content or Size.
|
||||
# RUN: not yaml2obj --docnum=2 -DCONTENT="00" %s 2>&1 | FileCheck %s --check-prefix=INVALID
|
||||
# RUN: not yaml2obj --docnum=2 -DSIZE="0" %s 2>&1 | FileCheck %s --check-prefix=INVALID
|
||||
@@ -175,7 +197,7 @@ Sections:
|
||||
|
||||
## Check that yaml2obj generates a warning when we use unsupported versions.
|
||||
# RUN: yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=INVALID-VERSION
|
||||
# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 3; encoding using the most recent version
|
||||
# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 4; encoding using the most recent version
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
@@ -187,4 +209,4 @@ Sections:
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
## Specify unsupported version
|
||||
- Version: 3
|
||||
- Version: 4
|
||||
|
||||
@@ -7879,6 +7879,8 @@ void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) {
|
||||
DictScope BBED(W);
|
||||
W.printNumber("ID", BBE.ID);
|
||||
W.printHex("Offset", BBE.Offset);
|
||||
if (!BBE.CallsiteOffsets.empty())
|
||||
W.printList("Callsite Offsets", BBE.CallsiteOffsets);
|
||||
W.printHex("Size", BBE.Size);
|
||||
W.printBoolean("HasReturn", BBE.hasReturn());
|
||||
W.printBoolean("HasTailCall", BBE.hasTailCall());
|
||||
|
||||
@@ -899,7 +899,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
|
||||
while (Cur && Cur.tell() < Content.size()) {
|
||||
if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
|
||||
Version = Data.getU8(Cur);
|
||||
if (Cur && Version > 2)
|
||||
if (Cur && Version > 3)
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"invalid SHT_LLVM_BB_ADDR_MAP section version: " +
|
||||
@@ -934,9 +934,19 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
|
||||
++BlockIndex) {
|
||||
uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex;
|
||||
uint64_t Offset = Data.getULEB128(Cur);
|
||||
std::optional<std::vector<llvm::yaml::Hex64>> CallsiteOffsets;
|
||||
if (FeatureOrErr->CallsiteOffsets) {
|
||||
uint32_t NumCallsites = Data.getULEB128(Cur);
|
||||
CallsiteOffsets = std::vector<llvm::yaml::Hex64>(NumCallsites, 0);
|
||||
for (uint32_t CallsiteIndex = 0; Cur && CallsiteIndex < NumCallsites;
|
||||
++CallsiteIndex) {
|
||||
(*CallsiteOffsets)[CallsiteIndex] = Data.getULEB128(Cur);
|
||||
}
|
||||
}
|
||||
uint64_t Size = Data.getULEB128(Cur);
|
||||
uint64_t Metadata = Data.getULEB128(Cur);
|
||||
BBEntries.push_back({ID, Offset, Size, Metadata});
|
||||
BBEntries.push_back(
|
||||
{ID, Offset, Size, Metadata, std::move(CallsiteOffsets)});
|
||||
}
|
||||
TotalNumBlocks += BBEntries.size();
|
||||
BBRanges.push_back({BaseAddress, /*NumBlocks=*/{}, BBEntries});
|
||||
|
||||
@@ -531,7 +531,7 @@ Sections:
|
||||
// Check that we can detect unsupported versions.
|
||||
SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
|
||||
UnsupportedVersionYamlString += R"(
|
||||
- Version: 3
|
||||
- Version: 4
|
||||
BBRanges:
|
||||
- BaseAddress: 0x11111
|
||||
BBEntries:
|
||||
@@ -543,12 +543,12 @@ Sections:
|
||||
{
|
||||
SCOPED_TRACE("unsupported version");
|
||||
DoCheck(UnsupportedVersionYamlString,
|
||||
"unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
|
||||
"unsupported SHT_LLVM_BB_ADDR_MAP version: 4");
|
||||
}
|
||||
|
||||
SmallString<128> ZeroBBRangesYamlString(CommonYamlString);
|
||||
ZeroBBRangesYamlString += R"(
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
Feature: 0x8
|
||||
BBRanges: []
|
||||
)";
|
||||
@@ -561,7 +561,7 @@ Sections:
|
||||
|
||||
SmallString<128> CommonVersionedYamlString(CommonYamlString);
|
||||
CommonVersionedYamlString += R"(
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
BBRanges:
|
||||
- BaseAddress: 0x11111
|
||||
BBEntries:
|
||||
@@ -669,6 +669,26 @@ Sections:
|
||||
)";
|
||||
DoCheck(OverLimitNumBBRanges,
|
||||
"ULEB128 value at offset 0x2 exceeds UINT32_MAX (0x100000000)");
|
||||
|
||||
// Check that we can detect unsupported version for callsite offsets.
|
||||
SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString);
|
||||
UnsupportedLowVersionYamlString += R"(
|
||||
- Version: 2
|
||||
Feature: 0x20
|
||||
BBRanges:
|
||||
- BBEntries:
|
||||
- AddressOffset: 0x0
|
||||
Size: 0x1
|
||||
Metadata: 0x2
|
||||
CallsiteOffsets: [ 0x1 ]
|
||||
)";
|
||||
|
||||
{
|
||||
SCOPED_TRACE("unsupported version");
|
||||
DoCheck(UnsupportedLowVersionYamlString,
|
||||
"version should be >= 3 for SHT_LLVM_BB_ADDR_MAP when callsite"
|
||||
" offsets feature is enabled: version = 2 feature = 32");
|
||||
}
|
||||
}
|
||||
|
||||
// Test for the ELFObjectFile::readBBAddrMap API.
|
||||
@@ -684,19 +704,21 @@ Sections:
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Link: 1
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
Feature: 0x20
|
||||
BBRanges:
|
||||
- BaseAddress: 0x11111
|
||||
BBEntries:
|
||||
- ID: 1
|
||||
AddressOffset: 0x0
|
||||
Size: 0x1
|
||||
Metadata: 0x2
|
||||
- ID: 1
|
||||
AddressOffset: 0x0
|
||||
Size: 0x1
|
||||
Metadata: 0x2
|
||||
CallsiteOffsets: [ 0x1 , 0x1 ]
|
||||
- Name: .llvm_bb_addr_map_2
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Link: 1
|
||||
Entries:
|
||||
- Version: 2
|
||||
- Version: 3
|
||||
Feature: 0x8
|
||||
BBRanges:
|
||||
- BaseAddress: 0x22222
|
||||
@@ -738,14 +760,15 @@ Sections:
|
||||
)");
|
||||
|
||||
BBAddrMap E1 = {
|
||||
{{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}};
|
||||
{{0x11111,
|
||||
{{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}}}}}};
|
||||
BBAddrMap E2 = {
|
||||
{{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}},
|
||||
{0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}}}}}};
|
||||
{{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}},
|
||||
{0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}}}}}};
|
||||
BBAddrMap E3 = {
|
||||
{{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}}}};
|
||||
{{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}}}}}};
|
||||
BBAddrMap E4 = {
|
||||
{{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}}}};
|
||||
{{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}}}}}};
|
||||
|
||||
std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
|
||||
std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
|
||||
@@ -1137,28 +1160,29 @@ Sections:
|
||||
)");
|
||||
|
||||
BBAddrMap E1 = {
|
||||
{{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}};
|
||||
PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false}};
|
||||
{{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}}}}}};
|
||||
PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false, false}};
|
||||
BBAddrMap E2 = {
|
||||
{{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}};
|
||||
PGOAnalysisMap P2 = {
|
||||
{}, {{BlockFrequency(343), {}}}, {false, true, false, false, false}};
|
||||
{{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}};
|
||||
PGOAnalysisMap P2 = {{},
|
||||
{{BlockFrequency(343), {}}},
|
||||
{false, true, false, false, false, false}};
|
||||
BBAddrMap E3 = {{{0x33333,
|
||||
{{0, 0x0, 0x3, {false, true, true, false, false}},
|
||||
{1, 0x3, 0x3, {false, false, true, false, false}},
|
||||
{2, 0x6, 0x3, {false, false, false, false, false}}}}}};
|
||||
{{0, 0x0, 0x3, {false, true, true, false, false}, {}},
|
||||
{1, 0x3, 0x3, {false, false, true, false, false}, {}},
|
||||
{2, 0x6, 0x3, {false, false, false, false, false}, {}}}}}};
|
||||
PGOAnalysisMap P3 = {{},
|
||||
{{{},
|
||||
{{1, BranchProbability::getRaw(0x1111'1111)},
|
||||
{2, BranchProbability::getRaw(0xeeee'eeee)}}},
|
||||
{{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}},
|
||||
{{}, {}}},
|
||||
{false, false, true, false, false}};
|
||||
{false, false, true, false, false, false}};
|
||||
BBAddrMap E4 = {{{0x44444,
|
||||
{{0, 0x0, 0x4, {false, false, false, true, true}},
|
||||
{1, 0x4, 0x4, {false, false, false, false, false}},
|
||||
{2, 0x8, 0x4, {false, false, false, false, false}},
|
||||
{3, 0xc, 0x4, {false, false, false, false, false}}}}}};
|
||||
{{0, 0x0, 0x4, {false, false, false, true, true}, {}},
|
||||
{1, 0x4, 0x4, {false, false, false, false, false}, {}},
|
||||
{2, 0x8, 0x4, {false, false, false, false, false}, {}},
|
||||
{3, 0xc, 0x4, {false, false, false, false, false}, {}}}}}};
|
||||
PGOAnalysisMap P4 = {
|
||||
1000,
|
||||
{{BlockFrequency(1000),
|
||||
@@ -1170,22 +1194,22 @@ Sections:
|
||||
{3, BranchProbability::getRaw(0xeeee'eeee)}}},
|
||||
{BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}},
|
||||
{BlockFrequency(1000), {}}},
|
||||
{true, true, true, false, false}};
|
||||
{true, true, true, false, false, false}};
|
||||
BBAddrMap E5 = {
|
||||
{{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}};
|
||||
PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false}};
|
||||
{{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}};
|
||||
PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false, false}};
|
||||
BBAddrMap E6 = {
|
||||
{{0x66666,
|
||||
{{0, 0x0, 0x6, {false, true, true, false, false}},
|
||||
{1, 0x6, 0x6, {false, false, true, false, false}}}},
|
||||
{0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}}}}}};
|
||||
{{0, 0x0, 0x6, {false, true, true, false, false}, {}},
|
||||
{1, 0x6, 0x6, {false, false, true, false, false}, {}}}},
|
||||
{0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}, {}}}}}};
|
||||
PGOAnalysisMap P6 = {{},
|
||||
{{{},
|
||||
{{1, BranchProbability::getRaw(0x2222'2222)},
|
||||
{2, BranchProbability::getRaw(0xcccc'cccc)}}},
|
||||
{{}, {{2, BranchProbability::getRaw(0x8888'8888)}}},
|
||||
{{}, {}}},
|
||||
{false, false, true, true, false}};
|
||||
{false, false, true, true, false, false}};
|
||||
|
||||
std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5, E6};
|
||||
std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
|
||||
|
||||
@@ -101,18 +101,21 @@ static_assert(
|
||||
"PGOAnalysisMap should use the same type for basic block ID as BBAddrMap");
|
||||
|
||||
TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) {
|
||||
const std::array<BBAddrMap::Features, 9> Decoded = {
|
||||
{{false, false, false, false, false},
|
||||
{true, false, false, false, false},
|
||||
{false, true, false, false, false},
|
||||
{false, false, true, false, false},
|
||||
{false, false, false, true, false},
|
||||
{true, true, false, false, false},
|
||||
{false, true, true, false, false},
|
||||
{false, true, true, true, false},
|
||||
{true, true, true, true, false}}};
|
||||
const std::array<uint8_t, 9> Encoded = {
|
||||
{0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111}};
|
||||
const std::array<BBAddrMap::Features, 11> Decoded = {
|
||||
{{false, false, false, false, false, false},
|
||||
{true, false, false, false, false, false},
|
||||
{false, true, false, false, false, false},
|
||||
{false, false, true, false, false, false},
|
||||
{false, false, false, true, false, false},
|
||||
{true, true, false, false, false, false},
|
||||
{false, true, true, false, false, false},
|
||||
{false, true, true, true, false, false},
|
||||
{true, true, true, true, false, false},
|
||||
{false, false, false, false, true, false},
|
||||
{false, false, false, false, false, true}}};
|
||||
const std::array<uint8_t, 11> Encoded = {{0b0000, 0b0001, 0b0010, 0b0100,
|
||||
0b1000, 0b0011, 0b0110, 0b1110,
|
||||
0b1111, 0b1'0000, 0b10'0000}};
|
||||
for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded))
|
||||
EXPECT_EQ(Feat.encode(), EncodedVal);
|
||||
for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) {
|
||||
@@ -125,9 +128,9 @@ TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) {
|
||||
|
||||
TEST(ELFTypesTest, BBAddrMapFeaturesInvalidEncodingTest) {
|
||||
const std::array<std::string, 2> Errors = {
|
||||
"invalid encoding for BBAddrMap::Features: 0x20",
|
||||
"invalid encoding for BBAddrMap::Features: 0x40",
|
||||
"invalid encoding for BBAddrMap::Features: 0xf0"};
|
||||
const std::array<uint8_t, 2> Values = {{0b10'0000, 0b1111'0000}};
|
||||
const std::array<uint8_t, 2> Values = {{0b100'0000, 0b1111'0000}};
|
||||
for (const auto &[Val, Error] : llvm::zip(Values, Errors)) {
|
||||
EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(),
|
||||
FailedWithMessage(Error));
|
||||
|
||||
Reference in New Issue
Block a user