diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 5a26e2fc31458..e9a417d3d4fb3 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -833,6 +833,7 @@ struct BBAddrMap { bool MultiBBRange : 1; bool OmitBBEntries : 1; bool CallsiteEndOffsets : 1; + bool BBHash : 1; bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; } @@ -845,7 +846,8 @@ struct BBAddrMap { (static_cast(BrProb) << 2) | (static_cast(MultiBBRange) << 3) | (static_cast(OmitBBEntries) << 4) | - (static_cast(CallsiteEndOffsets) << 5); + (static_cast(CallsiteEndOffsets) << 5) | + (static_cast(BBHash) << 6); } // Decodes from minimum bit width representation and validates no @@ -854,7 +856,8 @@ struct BBAddrMap { 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 << 4)), static_cast(Val & (1 << 5))}; + static_cast(Val & (1 << 4)), static_cast(Val & (1 << 5)), + static_cast(Val & (1 << 6))}; if (Feat.encode() != Val) return createStringError( std::error_code(), "invalid encoding for BBAddrMap::Features: 0x%x", @@ -864,10 +867,10 @@ struct BBAddrMap { bool operator==(const Features &Other) const { return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange, - OmitBBEntries, CallsiteEndOffsets) == + OmitBBEntries, CallsiteEndOffsets, BBHash) == std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb, Other.MultiBBRange, Other.OmitBBEntries, - Other.CallsiteEndOffsets); + Other.CallsiteEndOffsets, Other.BBHash); } }; @@ -920,17 +923,19 @@ struct BBAddrMap { false}; // Metdata for this basic block. // Offsets of end of call instructions, relative to the basic block start. SmallVector CallsiteEndOffsets; + uint64_t Hash = 0; // Hash for this basic block. BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD, - SmallVector CallsiteEndOffsets) + SmallVector CallsiteEndOffsets, uint64_t Hash) : ID(ID), Offset(Offset), Size(Size), MD(MD), - CallsiteEndOffsets(std::move(CallsiteEndOffsets)) {} + CallsiteEndOffsets(std::move(CallsiteEndOffsets)), Hash(Hash) {} UniqueBBID getID() const { return {ID, 0}; } bool operator==(const BBEntry &Other) const { return ID == Other.ID && Offset == Other.Offset && Size == Other.Size && - MD == Other.MD && CallsiteEndOffsets == Other.CallsiteEndOffsets; + MD == Other.MD && CallsiteEndOffsets == Other.CallsiteEndOffsets && + Hash == Other.Hash; } bool hasReturn() const { return MD.HasReturn; } diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index c90591d009dcd..a7c7c7c436dc2 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -163,6 +163,7 @@ struct BBAddrMapEntry { llvm::yaml::Hex64 Size; llvm::yaml::Hex64 Metadata; std::optional> CallsiteEndOffsets; + std::optional Hash; }; uint8_t Version; llvm::yaml::Hex8 Feature; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 219bbc9d5cdd4..05fffe9d97e98 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1437,7 +1437,8 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges, BrProbEnabled, MF.hasBBSections() && NumMBBSectionRanges > 1, static_cast(BBAddrMapSkipEmitBBEntries), - HasCalls}; + HasCalls, + false}; } void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 53699ce0d4fcf..f256e7b56591b 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -837,7 +837,7 @@ decodeBBAddrMapImpl(const ELFFile &EF, Version = Data.getU8(Cur); if (!Cur) break; - if (Version < 2 || Version > 3) + if (Version < 2 || Version > 4) return createError("unsupported SHT_LLVM_BB_ADDR_MAP version: " + Twine(static_cast(Version))); Feature = Data.getU8(Cur); // Feature byte @@ -852,6 +852,11 @@ decodeBBAddrMapImpl(const ELFFile &EF, "callsite offsets feature is enabled: version = " + Twine(static_cast(Version)) + " feature = " + Twine(static_cast(Feature))); + if (FeatEnable.BBHash && Version < 4) + return createError("version should be >= 4 for SHT_LLVM_BB_ADDR_MAP when " + "basic block hash feature is enabled: version = " + + Twine(static_cast(Version)) + + " feature = " + Twine(static_cast(Feature))); uint32_t NumBlocksInBBRange = 0; uint32_t NumBBRanges = 1; typename ELFFile::uintX_t RangeBaseAddress = 0; @@ -907,6 +912,7 @@ decodeBBAddrMapImpl(const ELFFile &EF, uint32_t Size = readULEB128As(Data, Cur, ULEBSizeErr) + LastCallsiteEndOffset; uint32_t MD = readULEB128As(Data, Cur, ULEBSizeErr); + uint64_t Hash = FeatEnable.BBHash ? Data.getU64(Cur) : 0; Expected MetadataOrErr = BBAddrMap::BBEntry::Metadata::decode(MD); if (!MetadataOrErr) { @@ -914,7 +920,7 @@ decodeBBAddrMapImpl(const ELFFile &EF, break; } BBEntries.push_back({ID, Offset + PrevBBEndOffset, Size, - *MetadataOrErr, CallsiteEndOffsets}); + *MetadataOrErr, CallsiteEndOffsets, Hash}); PrevBBEndOffset += Offset + Size; } TotalNumBlocks += BBEntries.size(); diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index faeeab32f5ad2..8b75fbe8291f0 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1465,7 +1465,7 @@ void ELFState::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 > 3) + if (E.Version > 4) WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: " << static_cast(E.Version) << "; encoding using the most recent version"; @@ -1526,6 +1526,12 @@ void ELFState::writeSectionContent( } SHeader.sh_size += CBA.writeULEB128(BBE.Size); SHeader.sh_size += CBA.writeULEB128(BBE.Metadata); + if (FeatureOrErr->BBHash || BBE.Hash.has_value()) { + uint64_t Hash = + BBE.Hash.has_value() ? BBE.Hash.value() : llvm::yaml::Hex64(0); + CBA.write(Hash, ELFT::Endianness); + SHeader.sh_size += 8; + } } } if (!PGOAnalyses) diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index d9cce1eb7641d..421d6603c08c3 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1887,6 +1887,7 @@ void MappingTraits::mapping( IO.mapRequired("Size", E.Size); IO.mapRequired("Metadata", E.Metadata); IO.mapOptional("CallsiteEndOffsets", E.CallsiteEndOffsets); + IO.mapOptional("Hash", E.Hash); } void MappingTraits::mapping( diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test index fd1492fa091a8..bcffd402d36a0 100644 --- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test @@ -34,6 +34,7 @@ # CHECK-NEXT: { # CHECK-NEXT: ID: 0 # CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Hash: 0x0 # CHECK-NEXT: Size: 0x1 # CHECK-NEXT: HasReturn: No # CHECK-NEXT: HasTailCall: Yes @@ -50,6 +51,7 @@ # CHECK-NEXT: ID: 2 # CHECK-NEXT: Offset: 0x3 # CHECK-NEXT: Callsite End Offsets: [1, 3] +# CHECK-NEXT: Hash: 0x123 # CHECK-NEXT: Size: 0x7 # CHECK-NEXT: HasReturn: Yes # CHECK-NEXT: HasTailCall: No @@ -144,8 +146,8 @@ Sections: ShSize: [[SIZE=]] Link: .text Entries: - - Version: 3 - Feature: 0x28 + - Version: 4 + Feature: 0x68 BBRanges: - BaseAddress: [[ADDR=0x11111]] BBEntries: @@ -160,6 +162,7 @@ Sections: Size: 0x4 Metadata: 0x15 CallsiteEndOffsets: [ 0x1 , 0x2 ] + Hash: 0x123 - Version: 2 BBRanges: - BaseAddress: 0x22222 diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml index dc14025689b60..7a22efe2d0f70 100644 --- a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml +++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml @@ -162,6 +162,92 @@ Sections: BBRanges: - BaseAddress: 0x20 +## Check that obj2yaml can dump basic block hash in the .llvm_bb_addr_map section. + +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: obj2yaml %t4 | FileCheck %s --check-prefix=BBHASH + +# BBHASH: --- !ELF +# BBHASH-NEXT: FileHeader: +# BBHASH-NEXT: Class: ELFCLASS64 +# BBHASH-NEXT: Data: ELFDATA2LSB +# BBHASH-NEXT: Type: ET_EXEC +# BBHASH-NEXT: Sections: +# BBHASH-NEXT: - Name: .llvm_bb_addr_map +# BBHASH-NEXT: Type: SHT_LLVM_BB_ADDR_MAP +# BBHASH-NEXT: Entries: +# BBHASH-NEXT: - Version: 4 +# BBHASH-NEXT: Feature: 0x40 +# BBHASH-NEXT: BBRanges: +# BBHASH-NEXT: - BBEntries: +# BBHASH-NEXT: - ID: 0 +# BBHASH-NEXT: AddressOffset: 0x1 +# BBHASH-NEXT: Size: 0x2 +# BBHASH-NEXT: Metadata: 0x3 +# BBHASH-NEXT: Hash: 0x1 +# BBHASH-NEXT: - ID: 2 +# BBHASH-NEXT: AddressOffset: 0x4 +# BBHASH-NEXT: Size: 0x5 +# BBHASH-NEXT: Metadata: 0x6 +# BBHASH-NEXT: Hash: 0x2 +# BBHASH-NEXT: - ID: 4 +# BBHASH-NEXT: AddressOffset: 0xFFFFFFFFFFFFFFF7 +# BBHASH-NEXT: Size: 0xFFFFFFFFFFFFFFF8 +# BBHASH-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9 +# BBHASH-NEXT: Hash: 0x3 +# BBHASH-NEXT: - Version: 4 +# BBHASH-NEXT: Feature: 0x68 +# BBHASH-NEXT: BBRanges: +# BBHASH-NEXT: - BaseAddress: 0xFFFFFFFFFFFFFF20 +# BBHASH-NEXT: BBEntries: +# BBHASH-NEXT: - ID: 6 +# BBHASH-NEXT: AddressOffset: 0xA +# BBHASH-NEXT: Size: 0xB +# BBHASH-NEXT: Metadata: 0xC +# BBHASH-NEXT: CallsiteEndOffsets: [ 0x1, 0x2 ] +# BBHASH-NEXT: Hash: 0x123 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .llvm_bb_addr_map + Type: SHT_LLVM_BB_ADDR_MAP + Entries: + - Version: 4 + Feature: 0x40 + BBRanges: + - BaseAddress: 0x0 + BBEntries: + - ID: 0 + AddressOffset: 0x1 + Size: 0x2 + Metadata: 0x3 + Hash: 0x1 + - ID: 2 + AddressOffset: 0x4 + Size: 0x5 + Metadata: 0x6 + Hash: 0x2 + - ID: 4 + AddressOffset: 0xFFFFFFFFFFFFFFF7 + Size: 0xFFFFFFFFFFFFFFF8 + Metadata: 0xFFFFFFFFFFFFFFF9 + Hash: 0x3 + - Version: 4 + Feature: 0x68 + BBRanges: + - BaseAddress: 0xFFFFFFFFFFFFFF20 + BBEntries: + - ID: 6 + AddressOffset: 0xA + Size: 0xB + Metadata: 0xC + CallsiteEndOffsets: [ 0x1, 0x2 ] + Hash: 0x123 + ## Check that obj2yaml uses the "Content" tag to describe an .llvm_bb_addr_map section ## when it can't extract the entries, for example, when the section is truncated, or ## when an invalid 'NumBlocks' or 'NumBBRanges` field is specified. diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml index 418f90ff8bafe..339e419b39458 100644 --- a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml +++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml @@ -72,6 +72,13 @@ # CHECK-NEXT: 0000: 03202000 00000000 0000010E 01000203 # CHECK-NEXT: ) +# Case 10: Specify basic block hash. +# CHECK: Name: .llvm_bb_addr_map (1) +# CHECK: SectionData ( +# CHECK-NEXT: 0000: 04602000 00000000 0000010E 01000203 +# CHECK-NEXT: 0010: 23010000 00000000 +# CHECK-NEXT: ) + --- !ELF FileHeader: @@ -176,6 +183,22 @@ Sections: Metadata: 0x00000003 CallsiteEndOffsets: [] +## 10) We can produce a SHT_LLVM_BB_ADDR_MAP section with basic block hash. + - Name: '.llvm_bb_addr_map (10)' + Type: SHT_LLVM_BB_ADDR_MAP + Entries: + - Version: 4 + Feature: 0x60 + BBRanges: + - BaseAddress: 0x0000000000000020 + BBEntries: + - ID: 14 + AddressOffset: 0x00000001 + Size: 0x00000002 + Metadata: 0x00000003 + CallsiteEndOffsets: [] + Hash: 0x123 + ## 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 @@ -197,7 +220,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: 4; encoding using the most recent version +# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 5; encoding using the most recent version --- !ELF FileHeader: @@ -209,4 +232,4 @@ Sections: Type: SHT_LLVM_BB_ADDR_MAP Entries: ## Specify unsupported version - - Version: 4 + - Version: 5 diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index ab93316907cc6..9c9b2dd79e686 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -8155,6 +8155,8 @@ void LLVMELFDumper::printBBAddrMaps(bool PrettyPGOAnalysis) { W.printHex("Offset", BBE.Offset); if (!BBE.CallsiteEndOffsets.empty()) W.printList("Callsite End Offsets", BBE.CallsiteEndOffsets); + if (PAM.FeatEnable.BBHash) + W.printHex("Hash", BBE.Hash); W.printHex("Size", BBE.Size); W.printBoolean("HasReturn", BBE.hasReturn()); W.printBoolean("HasTailCall", BBE.hasTailCall()); diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index ef4552f734736..68e18f6c79202 100644 --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -900,7 +900,7 @@ ELFDumper::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 > 3) + if (Cur && Version > 4) return createStringError( errc::invalid_argument, "invalid SHT_LLVM_BB_ADDR_MAP section version: " + @@ -946,8 +946,11 @@ ELFDumper::dumpBBAddrMapSection(const Elf_Shdr *Shdr) { } uint64_t Size = Data.getULEB128(Cur); uint64_t Metadata = Data.getULEB128(Cur); + std::optional Hash; + if (FeatureOrErr->BBHash) + Hash = Data.getU64(Cur); BBEntries.push_back( - {ID, Offset, Size, Metadata, std::move(CallsiteEndOffsets)}); + {ID, Offset, Size, Metadata, std::move(CallsiteEndOffsets), Hash}); } TotalNumBlocks += BBEntries.size(); BBRanges.push_back({BaseAddress, /*NumBlocks=*/{}, BBEntries}); diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp index 17d9f5076b73f..d6a3ca53b2154 100644 --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -531,7 +531,7 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) { // Check that we can detect unsupported versions. SmallString<128> UnsupportedVersionYamlString(CommonYamlString); UnsupportedVersionYamlString += R"( - - Version: 4 + - Version: 5 BBRanges: - BaseAddress: 0x11111 BBEntries: @@ -543,7 +543,7 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) { { SCOPED_TRACE("unsupported version"); DoCheck(UnsupportedVersionYamlString, - "unsupported SHT_LLVM_BB_ADDR_MAP version: 4"); + "unsupported SHT_LLVM_BB_ADDR_MAP version: 5"); } SmallString<128> ZeroBBRangesYamlString(CommonYamlString); @@ -761,14 +761,14 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) { BBAddrMap E1 = { {{0x11111, - {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}}}}}}; + {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}, 0}}}}}; 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}, {}, 0}}}, + {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}, 0}}}}}; BBAddrMap E3 = { - {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}}}}}}; + {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0}}}}}; BBAddrMap E4 = { - {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}}}}}}; + {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0}}}}}; std::vector Section0BBAddrMaps = {E4}; std::vector Section1BBAddrMaps = {E3}; @@ -988,6 +988,123 @@ TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) { } } +// Test for the ELFObjectFile::readBBAddrMap API with BBHash. +TEST(ELFObjectFileTest, ReadBBHash) { + StringRef CommonYamlString(R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .llvm_bb_addr_map_1 + Type: SHT_LLVM_BB_ADDR_MAP + Link: 1 + Entries: + - Version: 4 + Feature: 0x60 + BBRanges: + - BaseAddress: 0x11111 + BBEntries: + - ID: 1 + AddressOffset: 0x0 + Size: 0x1 + Metadata: 0x2 + CallsiteEndOffsets: [ 0x1 , 0x1 ] + Hash: 0x1 + - Name: .llvm_bb_addr_map_2 + Type: SHT_LLVM_BB_ADDR_MAP + Link: 1 + Entries: + - Version: 4 + Feature: 0x48 + BBRanges: + - BaseAddress: 0x22222 + BBEntries: + - ID: 2 + AddressOffset: 0x0 + Size: 0x2 + Metadata: 0x4 + Hash: 0x2 + - BaseAddress: 0xFFFFF + BBEntries: + - ID: 15 + AddressOffset: 0xF0 + Size: 0xF1 + Metadata: 0x1F + Hash: 0xF + - Name: .llvm_bb_addr_map_3 + Type: SHT_LLVM_BB_ADDR_MAP + Link: 2 + Entries: + - Version: 4 + Feature: 0x40 + BBRanges: + - BaseAddress: 0x33333 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0x3 + Metadata: 0x6 + Hash: 0x3 + - Name: .llvm_bb_addr_map_4 + Type: SHT_LLVM_BB_ADDR_MAP + # Link: 0 (by default, can be overriden) + Entries: + - Version: 4 + Feature: 0x40 + BBRanges: + - BaseAddress: 0x44444 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0x4 + Metadata: 0x18 + Hash: 0x4 +)"); + + BBAddrMap E1 = { + {{0x11111, + {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}, 0x1}}}}}; + BBAddrMap E2 = { + {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0x2}}}, + {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}, 0xF}}}}}; + BBAddrMap E3 = { + {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0x3}}}}}; + BBAddrMap E4 = { + {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0x4}}}}}; + + std::vector Section0BBAddrMaps = {E4}; + std::vector Section1BBAddrMaps = {E3}; + std::vector Section2BBAddrMaps = {E1, E2}; + std::vector AllBBAddrMaps = {E1, E2, E3, E4}; + + auto DoCheckSucceeds = [&](StringRef YamlString, + std::optional TextSectionIndex, + std::vector ExpectedResult) { + SCOPED_TRACE("for TextSectionIndex: " + + (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + + " and object yaml:\n" + YamlString); + SmallString<0> Storage; + Expected> ElfOrErr = + toBinary(Storage, YamlString); + ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); + + Expected BBAddrMapSecOrErr = + ElfOrErr->getELFFile().getSection(1); + ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); + auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); + ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); + EXPECT_EQ(*BBAddrMaps, ExpectedResult); + }; + + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, + AllBBAddrMaps); + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps); + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps); + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps); +} + // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap. TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { StringRef CommonYamlString(R"( @@ -1159,29 +1276,32 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { )"); BBAddrMap E1 = { - {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}}}}}}; - PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false, false}}; + {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}, 0}}}}}; + PGOAnalysisMap P1 = { + 892, {}, {true, false, false, false, false, false, false}}; BBAddrMap E2 = { - {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}}; + {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}}}; 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}, {}}}}}}; + {false, true, false, false, false, false, false}}; + BBAddrMap E3 = { + {{0x33333, + {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0}, + {1, 0x3, 0x3, {false, false, true, false, false}, {}, 0}, + {2, 0x6, 0x3, {false, false, false, false, false}, {}, 0}}}}}; PGOAnalysisMap P3 = {{}, {{{}, {{1, BranchProbability::getRaw(0x1111'1111)}, {2, BranchProbability::getRaw(0xeeee'eeee)}}}, {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}}, {{}, {}}}, - {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}, {}}}}}}; + {false, false, true, false, false, false, false}}; + BBAddrMap E4 = { + {{0x44444, + {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0}, + {1, 0x4, 0x4, {false, false, false, false, false}, {}, 0}, + {2, 0x8, 0x4, {false, false, false, false, false}, {}, 0}, + {3, 0xc, 0x4, {false, false, false, false, false}, {}, 0}}}}}; PGOAnalysisMap P4 = { 1000, {{BlockFrequency(1000), @@ -1193,22 +1313,24 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { {3, BranchProbability::getRaw(0xeeee'eeee)}}}, {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}}, {BlockFrequency(1000), {}}}, - {true, true, true, false, false, false}}; + {true, true, true, false, false, false, false}}; BBAddrMap E5 = { - {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}}; - PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false, false}}; + {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}}}; + PGOAnalysisMap P5 = { + {}, {}, {false, 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}, {}, 0}, + {1, 0x6, 0x6, {false, false, true, false, false}, {}, 0}}}, + {0x666661, + {{2, 0x0, 0x6, {false, false, false, false, false}, {}, 0}}}}}; PGOAnalysisMap P6 = {{}, {{{}, {{1, BranchProbability::getRaw(0x2222'2222)}, {2, BranchProbability::getRaw(0xcccc'cccc)}}}, {{}, {{2, BranchProbability::getRaw(0x8888'8888)}}}, {{}, {}}}, - {false, false, true, true, false, false}}; + {false, false, true, true, false, false, 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 f88931b5f544c..1765e15003963 100644 --- a/llvm/unittests/Object/ELFTypesTest.cpp +++ b/llvm/unittests/Object/ELFTypesTest.cpp @@ -101,21 +101,22 @@ static_assert( "PGOAnalysisMap should use the same type for basic block ID as BBAddrMap"); TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { - const std::array 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 Encoded = {{0b0000, 0b0001, 0b0010, 0b0100, - 0b1000, 0b0011, 0b0110, 0b1110, - 0b1111, 0b1'0000, 0b10'0000}}; + const std::array Decoded = { + {{false, false, false, false, false, false, false}, + {true, false, false, false, false, false, false}, + {false, true, false, false, false, false, false}, + {false, false, true, false, false, false, false}, + {false, false, false, true, false, false, false}, + {true, true, false, false, false, false, false}, + {false, true, true, false, false, false, false}, + {false, true, true, true, false, false, false}, + {true, true, true, true, false, false, false}, + {false, false, false, false, true, false, false}, + {false, false, false, false, false, true, false}, + {false, false, false, false, false, false, true}}}; + const std::array Encoded = { + {0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111, + 0b1'0000, 0b10'0000, 0b100'0000}}; for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) EXPECT_EQ(Feat.encode(), EncodedVal); for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) { @@ -128,9 +129,9 @@ TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { TEST(ELFTypesTest, BBAddrMapFeaturesInvalidEncodingTest) { const std::array Errors = { - "invalid encoding for BBAddrMap::Features: 0x40", + "invalid encoding for BBAddrMap::Features: 0x80", "invalid encoding for BBAddrMap::Features: 0xf0"}; - const std::array Values = {{0b100'0000, 0b1111'0000}}; + const std::array Values = {{0b1000'0000, 0b1111'0000}}; for (const auto &[Val, Error] : llvm::zip(Values, Errors)) { EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(), FailedWithMessage(Error));