diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 0f8c73f81cfa6..87e4dbe448091 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -830,6 +830,7 @@ struct BBAddrMap { bool BBFreq : 1; bool BrProb : 1; bool MultiBBRange : 1; + bool OmitBBEntries : 1; bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; } @@ -840,7 +841,8 @@ struct BBAddrMap { return (static_cast(FuncEntryCount) << 0) | (static_cast(BBFreq) << 1) | (static_cast(BrProb) << 2) | - (static_cast(MultiBBRange) << 3); + (static_cast(MultiBBRange) << 3) | + (static_cast(OmitBBEntries) << 4); } // Decodes from minimum bit width representation and validates no @@ -848,7 +850,8 @@ struct BBAddrMap { static Expected decode(uint8_t Val) { Features Feat{ static_cast(Val & (1 << 0)), static_cast(Val & (1 << 1)), - static_cast(Val & (1 << 2)), static_cast(Val & (1 << 3))}; + static_cast(Val & (1 << 2)), static_cast(Val & (1 << 3)), + static_cast(Val & (1 << 4))}; if (Feat.encode() != Val) return createStringError( std::error_code(), "invalid encoding for BBAddrMap::Features: 0x%x", @@ -857,9 +860,10 @@ struct BBAddrMap { } bool operator==(const Features &Other) const { - return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange) == + return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange, + OmitBBEntries) == std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb, - Other.MultiBBRange); + Other.MultiBBRange, Other.OmitBBEntries); } }; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 1d24fa44a5cea..256384728eeda 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -161,6 +161,13 @@ static cl::bits PgoAnalysisMapFeatures( "Enable extended information within the SHT_LLVM_BB_ADDR_MAP that is " "extracted from PGO related analysis.")); +static cl::opt BBAddrMapSkipEmitBBEntries( + "basic-block-address-map-skip-bb-entries", + cl::desc("Skip emitting basic block entries in the SHT_LLVM_BB_ADDR_MAP " + "section. It's used to save binary size when BB entries are " + "unnecessary for some PGOAnalysisMap features."), + cl::Hidden, cl::init(false)); + static cl::opt EmitJumpTableSizesSection( "emit-jump-table-sizes-section", cl::desc("Emit a section containing jump table addresses and sizes"), @@ -1411,8 +1418,15 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges) { bool BrProbEnabled = AllFeatures || (!NoFeatures && PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::BrProb)); + + if ((BBFreqEnabled || BrProbEnabled) && BBAddrMapSkipEmitBBEntries) { + MF.getFunction().getContext().emitError( + "BB entries info is required for BBFreq and BrProb " + "features"); + } return {FuncEntryCountEnabled, BBFreqEnabled, BrProbEnabled, - MF.hasBBSections() && NumMBBSectionRanges > 1}; + MF.hasBBSections() && NumMBBSectionRanges > 1, + static_cast(BBAddrMapSkipEmitBBEntries)}; } void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { @@ -1469,24 +1483,28 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { OutStreamer->emitULEB128IntValue(MBBSectionNumBlocks[MBB.getSectionID()]); PrevMBBEndSymbol = MBBSymbol; } - // TODO: Remove this check when version 1 is deprecated. - if (BBAddrMapVersion > 1) { - OutStreamer->AddComment("BB id"); - // Emit the BB ID for this basic block. - // We only emit BaseID since CloneID is unset for - // -basic-block-adress-map. - // TODO: Emit the full BBID when labels and sections can be mixed - // together. - OutStreamer->emitULEB128IntValue(MBB.getBBID()->BaseID); + + if (!Features.OmitBBEntries) { + // TODO: Remove this check when version 1 is deprecated. + if (BBAddrMapVersion > 1) { + OutStreamer->AddComment("BB id"); + // Emit the BB ID for this basic block. + // We only emit BaseID since CloneID is unset for + // -basic-block-adress-map. + // TODO: Emit the full BBID when labels and sections can be mixed + // together. + OutStreamer->emitULEB128IntValue(MBB.getBBID()->BaseID); + } + // Emit the basic block offset relative to the end of the previous block. + // This is zero unless the block is padded due to alignment. + emitLabelDifferenceAsULEB128(MBBSymbol, PrevMBBEndSymbol); + // Emit the basic block size. When BBs have alignments, their size cannot + // always be computed from their offsets. + emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol); + // Emit the Metadata. + OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB)); } - // Emit the basic block offset relative to the end of the previous block. - // This is zero unless the block is padded due to alignment. - emitLabelDifferenceAsULEB128(MBBSymbol, PrevMBBEndSymbol); - // Emit the basic block size. When BBs have alignments, their size cannot - // always be computed from their offsets. - emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol); - // Emit the Metadata. - OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB)); + PrevMBBEndSymbol = MBB.getEndSymbol(); } diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 545a672c05c8a..b6d0699ee4fe0 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -851,29 +851,31 @@ decodeBBAddrMapImpl(const ELFFile &EF, NumBlocksInBBRange = readULEB128As(Data, Cur, ULEBSizeErr); } std::vector BBEntries; - for (uint32_t BlockIndex = 0; !MetadataDecodeErr && !ULEBSizeErr && Cur && - (BlockIndex < NumBlocksInBBRange); - ++BlockIndex) { - uint32_t ID = Version >= 2 - ? readULEB128As(Data, Cur, ULEBSizeErr) - : BlockIndex; - uint32_t Offset = readULEB128As(Data, Cur, ULEBSizeErr); - uint32_t Size = readULEB128As(Data, Cur, ULEBSizeErr); - uint32_t MD = readULEB128As(Data, Cur, ULEBSizeErr); - if (Version >= 1) { - // Offset is calculated relative to the end of the previous BB. - Offset += PrevBBEndOffset; - PrevBBEndOffset = Offset + Size; - } - Expected MetadataOrErr = - BBAddrMap::BBEntry::Metadata::decode(MD); - if (!MetadataOrErr) { - MetadataDecodeErr = MetadataOrErr.takeError(); - break; + if (!FeatEnable.OmitBBEntries) { + for (uint32_t BlockIndex = 0; !MetadataDecodeErr && !ULEBSizeErr && + Cur && (BlockIndex < NumBlocksInBBRange); + ++BlockIndex) { + uint32_t ID = Version >= 2 + ? readULEB128As(Data, Cur, ULEBSizeErr) + : BlockIndex; + uint32_t Offset = readULEB128As(Data, Cur, ULEBSizeErr); + uint32_t Size = readULEB128As(Data, Cur, ULEBSizeErr); + uint32_t MD = readULEB128As(Data, Cur, ULEBSizeErr); + if (Version >= 1) { + // Offset is calculated relative to the end of the previous BB. + Offset += PrevBBEndOffset; + PrevBBEndOffset = Offset + Size; + } + Expected MetadataOrErr = + BBAddrMap::BBEntry::Metadata::decode(MD); + if (!MetadataOrErr) { + MetadataDecodeErr = MetadataOrErr.takeError(); + break; + } + BBEntries.push_back({ID, Offset, Size, *MetadataOrErr}); } - BBEntries.push_back({ID, Offset, Size, *MetadataOrErr}); + TotalNumBlocks += BBEntries.size(); } - TotalNumBlocks += BBEntries.size(); BBRangeEntries.push_back({RangeBaseAddress, std::move(BBEntries)}); } FunctionEntries.push_back({std::move(BBRangeEntries)}); diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index bf19e81933cab..1b0b07e2dcc2b 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1500,7 +1500,7 @@ void ELFState::writeSectionContent( BBR.NumBlocks.value_or(BBR.BBEntries ? BBR.BBEntries->size() : 0); SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks); // Write all BBEntries in this BBRange. - if (!BBR.BBEntries) + if (!BBR.BBEntries || FeatureOrErr->OmitBBEntries) continue; for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) { ++TotalNumBlocks; diff --git a/llvm/test/CodeGen/X86/basic-block-address-map-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-address-map-pgo-features.ll index fca5aa046b03b..63779727ec72c 100644 --- a/llvm/test/CodeGen/X86/basic-block-address-map-pgo-features.ll +++ b/llvm/test/CodeGen/X86/basic-block-address-map-pgo-features.ll @@ -11,6 +11,10 @@ ; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true -basic-block-address-map -pgo-analysis-map=bb-freq | FileCheck %s --check-prefixes=CHECK,PGO-BBF,BBF-ONLY ; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true -basic-block-address-map -pgo-analysis-map=br-prob | FileCheck %s --check-prefixes=CHECK,PGO-BRP,BRP-ONLY +; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true -basic-block-address-map -pgo-analysis-map=func-entry-count -basic-block-address-map-skip-bb-entries | FileCheck %s --check-prefixes=SKIP-BB-ENTRIES +; RUN: not llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true -basic-block-address-map -pgo-analysis-map=bb-freq -basic-block-address-map-skip-bb-entries 2>&1 | FileCheck %s --check-prefixes=SKIP-BB-ENTRIES-ERROR +; RUN: not llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true -basic-block-address-map -pgo-analysis-map=br-prob -basic-block-address-map-skip-bb-entries 2>&1 | FileCheck %s --check-prefixes=SKIP-BB-ENTRIES-ERROR + ;; Verify that we emit an error if we try and specify values in addition to all/none ; RUN: not llc < %s -mtriple=x86_64 -basic-block-address-map -pgo-analysis-map=all,bb-freq ; RUN: not llc < %s -mtriple=x86_64 -basic-block-address-map -pgo-analysis-map=none,bb-freq @@ -134,3 +138,10 @@ declare i32 @__gxx_personality_v0(...) ; PGO-BRP-NEXT: .byte 5 # successor BB ID ; PGO-BRP-NEXT: .ascii "\200\200\200\200\b" # successor branch probability +; SKIP-BB-ENTRIES: .byte 17 # feature +; SKIP-BB-ENTRIES-NEXT: .quad .Lfunc_begin0 # function address +; SKIP-BB-ENTRIES-NEXT: .byte 6 # number of basic blocks +; SKIP-BB-ENTRIES-NEXT: .byte 100 # function entry count +; SKIP-BB-ENTRIES-NOT: # BB id + +; SKIP-BB-ENTRIES-ERROR: error: BB entries info is required for BBFreq and BrProb features diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-skip-bb-entries.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-skip-bb-entries.test new file mode 100644 index 0000000000000..44d718fa366cc --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-skip-bb-entries.test @@ -0,0 +1,89 @@ +## This test checks how llvm-readobj prints skipped BB entries (-basic-block-address-map-skip-emit-bb-entries). + +## Check 64-bit: +# RUN: yaml2obj %s -DBITS=64 -o %t1.x64.o +# RUN: llvm-readobj %t1.x64.o --bb-addr-map 2>&1 | FileCheck --match-full-lines %s -DFILE=%t1.x64.o + +## Check 32-bit: +# RUN: yaml2obj %s -DBITS=32 -o %t1.x32.o +# RUN: llvm-readobj %t1.x32.o --bb-addr-map 2>&1 | FileCheck --match-full-lines %s -DFILE=%t1.x32.o + +# CHECK: BBAddrMap [ +# CHECK-NEXT: Function { +# CHECK-NEXT: At: 0x11111 +# CHECK-NEXT: Name: foo +# CHECK-NEXT: BB Ranges [ +# CHECK-NEXT: { +# CHECK-NEXT: Base Address: 0x11111 +# CHECK-NEXT: BB Entries [ +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: PGO analyses { +# CHECK-NEXT: FuncEntryCount: 100 +# CHECK-NEXT: PGO BB entries [ +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT:] +# CHECK-NEXT:BBAddrMap [ +# CHECK-NEXT: Function { +# CHECK-NEXT: At: 0x33333 +# CHECK-NEXT: Name: bar +# CHECK-NEXT: BB Ranges [ +# CHECK-NEXT: { +# CHECK-NEXT: Base Address: 0x33333 +# CHECK-NEXT: BB Entries [ +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: PGO analyses { +# CHECK-NEXT: FuncEntryCount: 89 +# CHECK-NEXT: PGO BB entries [ +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT:] + +--- !ELF +FileHeader: + Class: ELFCLASS[[BITS]] + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC] + - Name: .text.bar + Type: SHT_PROGBITS + Flags: [SHF_ALLOC] + - Name: .llvm_bb_addr_map + Type: SHT_LLVM_BB_ADDR_MAP + ShSize: [[SIZE=]] + Link: .text + Entries: + - Version: 2 + Feature: 0x17 + BBRanges: + - BaseAddress: 0x11111 + PGOAnalyses: + - FuncEntryCount: 100 + - Name: '.llvm_bb_addr_map2' + Type: SHT_LLVM_BB_ADDR_MAP + Link: .text.bar + Entries: + - Version: 2 + Feature: 0x17 + BBRanges: + - BaseAddress: 0x33333 + PGOAnalyses: + - FuncEntryCount: 89 +Symbols: + - Name: foo + Section: .text + Type: STT_FUNC + Value: 0x11111 + - Name: bar + Section: .text.bar + Type: STT_FUNC + Value: 0x33333 diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml index 4dfaf60be3c0e..a4cb572e6d993 100644 --- a/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml +++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map-pgo-analysis-map.yaml @@ -66,7 +66,7 @@ Sections: ## Check that yaml2obj generates a warning when we use unsupported feature. # RUN: yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=INVALID-FEATURE -# INVALID-FEATURE: warning: invalid encoding for BBAddrMap::Features: 0xff +# INVALID-FEATURE: warning: invalid encoding for BBAddrMap::Features: 0xf0 --- !ELF FileHeader: @@ -79,5 +79,4 @@ Sections: Entries: - Version: 2 ## Specify unsupported feature - Feature: 0xFF - + Feature: 0xF0 diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp index c13dc0e3fab89..2a0921690914b 100644 --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -1148,11 +1148,11 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { BBAddrMap E1 = { {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}}; - PGOAnalysisMap P1 = {892, {}, {true, false, false, false}}; + PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false}}; BBAddrMap E2 = { {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}}; PGOAnalysisMap P2 = { - {}, {{BlockFrequency(343), {}}}, {false, true, false, false}}; + {}, {{BlockFrequency(343), {}}}, {false, true, false, false, false}}; BBAddrMap E3 = {{{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}, {1, 0x3, 0x3, {false, false, true, false, false}}, @@ -1163,7 +1163,7 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { {2, BranchProbability::getRaw(0xeeee'eeee)}}}, {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}}, {{}, {}}}, - {false, false, true, false}}; + {false, false, true, false, false}}; BBAddrMap E4 = {{{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}, {1, 0x4, 0x4, {false, false, false, false, false}}, @@ -1180,10 +1180,10 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { {3, BranchProbability::getRaw(0xeeee'eeee)}}}, {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}}, {BlockFrequency(1000), {}}}, - {true, true, true, false}}; + {true, true, true, false, false}}; BBAddrMap E5 = { {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}}; - PGOAnalysisMap P5 = {{}, {}, {false, false, false, false}}; + PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false}}; BBAddrMap E6 = { {{0x66666, {{0, 0x0, 0x6, {false, true, true, false, false}}, @@ -1195,7 +1195,7 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { {2, BranchProbability::getRaw(0xcccc'cccc)}}}, {{}, {{2, BranchProbability::getRaw(0x8888'8888)}}}, {{}, {}}}, - {false, false, true, true}}; + {false, false, true, true, false}}; std::vector Section0BBAddrMaps = {E4, E5, E6}; std::vector Section1BBAddrMaps = {E3}; diff --git a/llvm/unittests/Object/ELFTypesTest.cpp b/llvm/unittests/Object/ELFTypesTest.cpp index f04d45cf0983c..13130dde80ef1 100644 --- a/llvm/unittests/Object/ELFTypesTest.cpp +++ b/llvm/unittests/Object/ELFTypesTest.cpp @@ -102,15 +102,15 @@ static_assert( TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { const std::array Decoded = { - {{false, false, false, false}, - {true, false, false, false}, - {false, true, false, false}, - {false, false, true, false}, - {false, false, false, true}, - {true, true, false, false}, - {false, true, true, false}, - {false, true, true, true}, - {true, true, true, true}}}; + {{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 Encoded = { {0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111}}; for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) @@ -125,9 +125,9 @@ TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { TEST(ELFTypesTest, BBAddrMapFeaturesInvalidEncodingTest) { const std::array Errors = { - "invalid encoding for BBAddrMap::Features: 0x10", - "invalid encoding for BBAddrMap::Features: 0xff"}; - const std::array Values = {{0b10000, 0b1111'1111}}; + "invalid encoding for BBAddrMap::Features: 0x20", + "invalid encoding for BBAddrMap::Features: 0xf0"}; + const std::array Values = {{0b10'0000, 0b1111'0000}}; for (const auto &[Val, Error] : llvm::zip(Values, Errors)) { EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(), FailedWithMessage(Error));