From 4d78bde1910fea8061398f4011089ee71e4aa609 Mon Sep 17 00:00:00 2001 From: Micah Weston Date: Tue, 31 Oct 2023 21:42:27 -0400 Subject: [PATCH 1/3] Implements llvm-readobj handling without tests yet. Adds tests for llvm-readobj PGOBBAddrMap. Updates readobj for the redesign with PGOAnalysisMap Updates tests after moving PGO analyses to after each function. Updates readobj with bitfield features. --- .../ELF/pgo-bb-addr-map-relocatable.test | 210 ++++++++++++++++++ .../llvm-readobj/ELF/pgo-bb-addr-map.test | 205 +++++++++++++++++ llvm/tools/llvm-readobj/ELFDumper.cpp | 45 +++- llvm/tools/llvm-readobj/ObjDumper.h | 2 +- llvm/tools/llvm-readobj/Opts.td | 1 + llvm/tools/llvm-readobj/llvm-readobj.cpp | 6 +- 6 files changed, 458 insertions(+), 11 deletions(-) create mode 100644 llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test create mode 100644 llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test diff --git a/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test b/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test new file mode 100644 index 0000000000000..7a8844b49d443 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test @@ -0,0 +1,210 @@ +## This test checks how we handle the --pgo-analysis-map option on relocatable +## object files. + +## Fails on windows (https://github.com/llvm/llvm-project/issues/60013). +# UNSUPPORTED: system-windows + +# RUN: yaml2obj %s -o %t1.o +# RUN: llvm-readobj %t1.o --pgo-analysis-map | FileCheck %s + +# CHECK: BBAddrMap [ +# CHECK-NEXT: Function { +# CHECK-NEXT: At: 0x0 +# CHECK-NEXT: Name: +# CHECK-NEXT: EntryCount: 89 +# CHECK-NEXT: BB entries [ +# CHECK-NEXT: { +# CHECK-NEXT: ID: 0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0xF +# CHECK-NEXT: HasReturn: Yes +# CHECK-NEXT: HasTailCall: No +# CHECK-NEXT: IsEHPad: No +# CHECK-NEXT: CanFallThrough: No +# CHECK-NEXT: HasIndirectBranch: No +# CHECK-NEXT: Frequency: 90 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: Function { +# CHECK-NEXT: At: 0x10 +# CHECK-NEXT: Name: +# CHECK-NEXT: BB entries [ +# CHECK-NEXT: { +# CHECK-NEXT: ID: 0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0x11 +# CHECK-NEXT: HasReturn: No +# CHECK-NEXT: HasTailCall: No +# CHECK-NEXT: IsEHPad: No +# CHECK-NEXT: CanFallThrough: Yes +# CHECK-NEXT: HasIndirectBranch: No +# CHECK-NEXT: Frequency: 123 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .llvm_bb_addr_map + Type: SHT_LLVM_BB_ADDR_MAP + Link: .text + Entries: + - Version: 2 + Feature: 0x3 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0xF + Metadata: 0x1 + - Version: 2 + Feature: 0x2 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0x11 + Metadata: 0x8 + PGOAnalyses: + - FuncEntryCount: 89 + PGOBBEntries: + - BBFreq: 90 + - PGOBBEntries: + - BBFreq: 123 + - Name: .rela.llvm_bb_addr_map + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + Info: .llvm_bb_addr_map + Relocations: + - Offset: 0x2 + Symbol: .text + Type: R_X86_64_64 + - Offset: 0x13 + Symbol: .text + Type: R_X86_64_64 + Addend: 16 +Symbols: + - Name: a + Section: .text + Value: 0x0 + - Name: c + Section: .text + Value: 0x10 + - Name: .text + Type: STT_SECTION + Section: .text + +## Check that we get a warning if we expect a relocation and it is not present. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .llvm_bb_addr_map + Type: SHT_LLVM_BB_ADDR_MAP + Link: .text + Entries: + - Version: 2 + Feature: 0x7 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0xF + Metadata: 0x1 + PGOAnalyses: + - FuncEntryCount: 2 + PGOBBEntries: + - BBFreq: 2 + - Name: .rela.llvm_bb_addr_map + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Info: .llvm_bb_addr_map + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .rela.llvm_bb_addr_map + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Info: 0xFF + +# RUN: yaml2obj %s --docnum=3 -o %t4.o +# RUN: llvm-readobj %t4.o --pgo-analysis-map 2>&1 | FileCheck %s --check-prefix=NO-RELOCATED-SECTION -DFILE=%t4.o + +# NO-RELOCATED-SECTION: warning: '[[FILE]]': failed to get SHT_LLVM_BB_ADDR_MAP section(s): SHT_RELA section with index 1: failed to get a relocated section: invalid section index: 255 + +## Check that if we have an ET_DYN file with a .rela.dyn section, we don't get +## a warning about a missing relocation section and can get the baddrmap data. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.dyn + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + - Name: .llvm_bb_addr_map + Type: SHT_LLVM_BB_ADDR_MAP + Flags: [ SHF_LINK_ORDER ] + Entries: + - Version: 2 + Feature: 0x7 + Address: 0xF + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0xF + Metadata: 0x1 + PGOAnalyses: + - FuncEntryCount: 100 + PGOBBEntries: + - BBFreq: 100 + Successors: [] + +# RUN: yaml2obj %s --docnum=4 -o %t5.o +# RUN: llvm-readobj %t5.o --pgo-analysis-map | FileCheck %s --check-prefix=ET-DYN-NO-WARNING -DFILE=%t5.o + +# ET-DYN-NO-WARNING: BBAddrMap [ +# ET-DYN-NO-WARNING-NEXT: Function { +# ET-DYN-NO-WARNING-NEXT: At: 0xF +# ET-DYN-NO-WARNING-NEXT: Name: +# ET-DYN-NO-WARNING-NEXT: EntryCount: 100 +# ET-DYN-NO-WARNING-NEXT: BB entries [ +# ET-DYN-NO-WARNING-NEXT: { +# ET-DYN-NO-WARNING-NEXT: ID: 0 +# ET-DYN-NO-WARNING-NEXT: Offset: 0x0 +# ET-DYN-NO-WARNING-NEXT: Size: 0xF +# ET-DYN-NO-WARNING-NEXT: HasReturn: Yes +# ET-DYN-NO-WARNING-NEXT: HasTailCall: No +# ET-DYN-NO-WARNING-NEXT: IsEHPad: No +# ET-DYN-NO-WARNING-NEXT: CanFallThrough: No +# ET-DYN-NO-WARNING-NEXT: HasIndirectBranch: No +# ET-DYN-NO-WARNING-NEXT: Frequency: 100 +# ET-DYN-NO-WARNING-NEXT: Successors [ +# ET-DYN-NO-WARNING-NEXT: ] +# ET-DYN-NO-WARNING-NEXT: } +# ET-DYN-NO-WARNING-NEXT: ] +# ET-DYN-NO-WARNING-NEXT: } +# ET-DYN-NO-WARNING-NEXT: ] diff --git a/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test new file mode 100644 index 0000000000000..05ae473010815 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test @@ -0,0 +1,205 @@ +## This test checks how we handle the --pgo-analysis-map option. + +## Fails on windows (https://github.com/llvm/llvm-project/issues/60013). +# UNSUPPORTED: system-windows + +## Check 64-bit: +# RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o +# RUN: llvm-readobj %t1.x64.o --pgo-analysis-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefix=CHECK +# RUN: llvm-readelf %t1.x64.o --pgo-analysis-map | FileCheck %s --check-prefix=GNU + +## Check 64-bit: +# RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.v1.x64.o +# RUN: llvm-readobj %t1.v1.x64.o --pgo-analysis-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.v1.x64.o --check-prefix=CHECK + +## Check 32-bit: +# RUN: yaml2obj --docnum=1 %s -DBITS=32 -o %t1.x32.o +# RUN: llvm-readobj %t1.x32.o --pgo-analysis-map 2>&1 | FileCheck -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefix=CHECK +# RUN: llvm-readelf %t1.x32.o --pgo-analysis-map | FileCheck %s --check-prefix=GNU + +## Check that a malformed section can be handled. +# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DSIZE=6 -o %t2.o +# RUN: llvm-readobj %t2.o --pgo-analysis-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED + +## Check that invalid metadata can be handled. +# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DMETADATA=0xF000002 -o %t3.o +# RUN: llvm-readobj %t3.o --pgo-analysis-map 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALIDMD + +# CHECK: BBAddrMap [ +# CHECK-NEXT: Function { +# CHECK-NEXT: At: [[ADDR]] +# CHECK-NEXT: warning: '[[FILE]]': could not identify function symbol for address ([[ADDR]]) in SHT_LLVM_BB_ADDR_MAP section with index 3 +# CHECK-NEXT: Name: +# CHECK-NEXT: EntryCount: 100 +# CHECK-NEXT: BB entries [ +# CHECK-NEXT: { +# CHECK-NEXT: ID: 0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0x1 +# CHECK-NEXT: HasReturn: No +# CHECK-NEXT: HasTailCall: Yes +# CHECK-NEXT: IsEHPad: No +# CHECK-NEXT: CanFallThrough: No +# CHECK-NEXT: HasIndirectBranch: No +# CHECK-NEXT: Frequency: 100 +# CHECK-NEXT: Successors [ +# CHECK-NEXT: { +# CHECK-NEXT: ID: 2 +# CHECK-NEXT: Probability: 0xFFFFFFFF +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: { +# CHECK-NEXT: ID: 2 +# CHECK-NEXT: Offset: 0x4 +# CHECK-NEXT: Size: 0x4 +# CHECK-NEXT: HasReturn: Yes +# CHECK-NEXT: HasTailCall: No +# CHECK-NEXT: IsEHPad: Yes +# CHECK-NEXT: CanFallThrough: No +# CHECK-NEXT: HasIndirectBranch: Yes +# CHECK-NEXT: Frequency: 100 +# CHECK-NEXT: Successors [ +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: Function { +# CHECK-NEXT: At: 0x22222 +# CHECK-NEXT: Name: foo +# CHECK-NEXT: EntryCount: 8888 +# CHECK-NEXT: BB entries [ +# CHECK-NEXT: { +# CHECK-NEXT: ID: 4 +# CHECK-NEXT: Offset: 0x6 +# CHECK-NEXT: Size: 0x7 +# CHECK-NEXT: HasReturn: No +# CHECK-NEXT: HasTailCall: No +# CHECK-NEXT: IsEHPad: No +# CHECK-NEXT: CanFallThrough: Yes +# CHECK-NEXT: HasIndirectBranch: No +# CHECK-NEXT: Frequency: 9000 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# GNU: GNUStyle::printBBAddrMaps not implemented + +# TRUNCATED: BBAddrMap [ +# TRUNCATED-NEXT: warning: '[[FILE]]': unable to dump SHT_LLVM_BB_ADDR_MAP section with index 3: unable to decode LEB128 at offset [[OFFSET]]: malformed uleb128, extends past end +# TRUNCATED-NEXT: ] +## Check that the other valid section is properly dumped. +# TRUNCATED-NEXT: BBAddrMap [ +# TRUNCATED-NEXT: Function { +# TRUNCATED-NEXT: At: 0x33333 +# TRUNCATED-NEXT: Name: bar +# TRUNCATED-NEXT: EntryCount: 89 +# TRUNCATED-NEXT: BB entries [ +# TRUNCATED-NEXT: { +# TRUNCATED-NEXT: ID: 6 +# TRUNCATED-NEXT: Offset: 0x9 +# TRUNCATED-NEXT: Size: 0xA +# TRUNCATED-NEXT: HasReturn: Yes +# TRUNCATED-NEXT: HasTailCall: Yes +# TRUNCATED-NEXT: IsEHPad: No +# TRUNCATED-NEXT: CanFallThrough: Yes +# TRUNCATED-NEXT: HasIndirectBranch: Yes +# TRUNCATED-NEXT: } +# TRUNCATED-NEXT: { +# TRUNCATED-NEXT: ID: 7 +# TRUNCATED-NEXT: Offset: 0x1F +# TRUNCATED-NEXT: Size: 0xD +# TRUNCATED-NEXT: HasReturn: No +# TRUNCATED-NEXT: HasTailCall: Yes +# TRUNCATED-NEXT: IsEHPad: Yes +# TRUNCATED-NEXT: CanFallThrough: Yes +# TRUNCATED-NEXT: HasIndirectBranch: No +# TRUNCATED-NEXT: } +# TRUNCATED-NEXT: ] +# TRUNCATED-NEXT: } +# TRUNCATED-NEXT: ] + +# INVALIDMD: BBAddrMap [ +# INVALIDMD-NEXT: warning: '[[FILE]]': unable to dump SHT_LLVM_BB_ADDR_MAP section with index 3: invalid encoding for BBEntry::Metadata: 0xf000002 + +--- !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: 0x7 + Address: [[ADDR=0x11111]] + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0x1 + Metadata: [[METADATA=0x2]] + - ID: 2 + AddressOffset: 0x3 + Size: 0x4 + Metadata: 0x15 + - Version: 2 + Feature: 0x3 + Address: 0x22222 + BBEntries: + - ID: 4 + AddressOffset: 0x6 + Size: 0x7 + Metadata: 0x8 + PGOAnalyses: + - FuncEntryCount: 100 + PGOBBEntries: + - BBFreq: 100 + Successors: + - ID: 2 + BrProb: 0xFFFFFFFF + - BBFreq: 100 + Successors: [] + - FuncEntryCount: 8888 + PGOBBEntries: + - BBFreq: 9000 + - Name: dummy_section + Type: SHT_PROGBITS + Size: 16 + - Name: '.llvm_bb_addr_map (1)' + Type: SHT_LLVM_BB_ADDR_MAP + Link: .text.bar + Entries: + - Version: 2 + Feature: 0x1 + Address: 0x33333 + BBEntries: + - ID: 6 + AddressOffset: 0x9 + Size: 0xa + Metadata: 0x1b + - ID: 7 + AddressOffset: 0xc + Size: 0xd + Metadata: 0xe + PGOAnalyses: + - FuncEntryCount: 89 +Symbols: + - Name: foo + Section: .text + Type: STT_FUNC + Value: 0x22222 + - Name: bar + Section: .text.bar + Type: STT_FUNC + Value: 0x33333 + diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index f369a63add114..3b32d98052777 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -593,7 +593,7 @@ template class GNUELFDumper : public ELFDumper { void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printCGProfile() override; - void printBBAddrMaps() override; + void printBBAddrMaps(bool IncludePGOAnalysis = false) override; void printAddrsig() override; void printNotes() override; void printELFLinkerOptions() override; @@ -704,7 +704,7 @@ template class LLVMELFDumper : public ELFDumper { void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printCGProfile() override; - void printBBAddrMaps() override; + void printBBAddrMaps(bool IncludePGOAnalysis = false) override; void printAddrsig() override; void printNotes() override; void printELFLinkerOptions() override; @@ -739,6 +739,8 @@ template class LLVMELFDumper : public ELFDumper { void printMipsABIFlags() override; virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const; + template void printAddrMaps(); + protected: virtual std::string getGroupSectionHeaderName() const; void printSymbolOtherField(const Elf_Sym &Symbol) const; @@ -5070,7 +5072,8 @@ template void GNUELFDumper::printCGProfile() { OS << "GNUStyle::printCGProfile not implemented\n"; } -template void GNUELFDumper::printBBAddrMaps() { +template +void GNUELFDumper::printBBAddrMaps(bool IncludePGOAnalysis) { OS << "GNUStyle::printBBAddrMaps not implemented\n"; } @@ -7541,7 +7544,8 @@ template void LLVMELFDumper::printCGProfile() { } } -template void LLVMELFDumper::printBBAddrMaps() { +template +void LLVMELFDumper::printBBAddrMaps(bool IncludePGOAnalysis) { bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL; using Elf_Shdr = typename ELFT::Shdr; auto IsMatch = [](const Elf_Shdr &Sec) -> bool { @@ -7567,14 +7571,16 @@ template void LLVMELFDumper::printBBAddrMaps() { this->describe(*Sec)); continue; } - Expected> BBAddrMapOrErr = - this->Obj.decodeBBAddrMap(*Sec, RelocSec); + std::vector PGOAnalysis; + Expected> BBAddrMapOrErr = this->Obj.decodeBBAddrMap( + *Sec, RelocSec, IncludePGOAnalysis ? &PGOAnalysis : nullptr); if (!BBAddrMapOrErr) { this->reportUniqueWarning("unable to dump " + this->describe(*Sec) + ": " + toString(BBAddrMapOrErr.takeError())); continue; } - for (const BBAddrMap &AM : *BBAddrMapOrErr) { + for (const auto &[Idx, AM] : llvm::enumerate(*BBAddrMapOrErr)) { + const auto *PAM = IncludePGOAnalysis ? &PGOAnalysis[Idx] : nullptr; DictScope D(W, "Function"); W.printHex("At", AM.Addr); SmallVector FuncSymIndex = @@ -7587,9 +7593,14 @@ template void LLVMELFDumper::printBBAddrMaps() { else FuncName = this->getStaticSymbolName(FuncSymIndex.front()); W.printString("Name", FuncName); + if (IncludePGOAnalysis && PAM->FeatEnable.FuncEntryCount) + W.printNumber("EntryCount", PAM->FuncEntryCount); + bool IncludePGOBBData = + IncludePGOAnalysis && PAM->BBEntries.size() == AM.BBEntries.size(); ListScope L(W, "BB entries"); - for (const BBAddrMap::BBEntry &BBE : AM.BBEntries) { + for (const auto &[BIdx, BBE] : llvm::enumerate(AM.BBEntries)) { + const auto *PBBE = IncludePGOBBData ? &PAM->BBEntries[BIdx] : nullptr; DictScope L(W); W.printNumber("ID", BBE.ID); W.printHex("Offset", BBE.Offset); @@ -7599,6 +7610,24 @@ template void LLVMELFDumper::printBBAddrMaps() { W.printBoolean("IsEHPad", BBE.isEHPad()); W.printBoolean("CanFallThrough", BBE.canFallThrough()); W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch()); + + /// FIXME: currently we just emit the raw frequency, it may be better to + /// provide an option to scale it by the first entry frequence using + /// BlockFrequency::Scaled64 number + if (IncludePGOBBData && PAM->FeatEnable.BBFreq) + W.printNumber("Frequency", PBBE->BlockFreq.getFrequency()); + + if (IncludePGOBBData && PAM->FeatEnable.BrProb) { + ListScope L(W, "Successors"); + for (const auto &Succ : PBBE->Successors) { + DictScope L(W); + W.printNumber("ID", Succ.ID); + /// FIXME: currently we just emit the raw numerator of the probably, + /// it may be better to provide an option to emit it as a percentage + /// or other prettied representation + W.printHex("Probability", Succ.Prob.getNumerator()); + } + } } } } diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 1d679453581bc..082aba80841c6 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -129,7 +129,7 @@ class ObjDumper { virtual void printGroupSections() {} virtual void printHashHistograms() {} virtual void printCGProfile() {} - virtual void printBBAddrMaps() {} + virtual void printBBAddrMaps(bool IncludePGOAnalysis = false) {} virtual void printAddrsig() {} virtual void printNotes() {} virtual void printELFLinkerOptions() {} diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index e2d93c6ec229e..a981fac2f2f36 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -29,6 +29,7 @@ def extra_sym_info : FF<"extra-sym-info", "Display extra information when showin def file_header : FF<"file-header", "Display file header">; def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">; defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"">; +def pgo_analysis_map : FF<"pgo-analysis-map", "Display the BB address map section with PGO data included">; def pretty_print : FF<"pretty-print", "Pretty print JSON output">; def relocs : FF<"relocs", "Display the relocation entries in the file">; def section_data : FF<"section-data", "Display section data for each section shown. This option has no effect for GNU style output">; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index f9d605d35244b..4dcab4ce5c9f7 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -95,6 +95,7 @@ static bool Addrsig; static bool All; static bool ArchSpecificInfo; static bool BBAddrMap; +static bool PGOAnalysisMap; bool ExpandRelocs; static bool CGProfile; bool Demangle; @@ -211,6 +212,7 @@ static void parseOptions(const opt::InputArgList &Args) { opts::All = Args.hasArg(OPT_all); opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific); opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map); + opts::PGOAnalysisMap = Args.hasArg(OPT_pgo_analysis_map); opts::CGProfile = Args.hasArg(OPT_cg_profile); opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false); opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries); @@ -463,8 +465,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, Dumper->printHashHistograms(); if (opts::CGProfile) Dumper->printCGProfile(); - if (opts::BBAddrMap) - Dumper->printBBAddrMaps(); + if (opts::BBAddrMap || opts::PGOAnalysisMap) + Dumper->printBBAddrMaps(opts::PGOAnalysisMap); if (opts::Addrsig) Dumper->printAddrsig(); if (opts::Notes) From c036ea8331dce425d05515ed06073b520ba7e3ce Mon Sep 17 00:00:00 2001 From: Micah Weston Date: Thu, 25 Jan 2024 18:20:38 -0500 Subject: [PATCH 2/3] Updates to pgo-analysis-map and always prints. --- ...test => bb-addr-map-pgo-analysis-map.test} | 60 +++-- .../ELF/pgo-bb-addr-map-relocatable.test | 210 ------------------ llvm/tools/llvm-readobj/ELFDumper.cpp | 96 ++++---- llvm/tools/llvm-readobj/ObjDumper.h | 2 +- llvm/tools/llvm-readobj/Opts.td | 1 - llvm/tools/llvm-readobj/llvm-readobj.cpp | 6 +- 6 files changed, 92 insertions(+), 283 deletions(-) rename llvm/test/tools/llvm-readobj/ELF/{pgo-bb-addr-map.test => bb-addr-map-pgo-analysis-map.test} (75%) delete mode 100644 llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test diff --git a/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test similarity index 75% rename from llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test rename to llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test index 05ae473010815..fad2cca1990a4 100644 --- a/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map.test +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test @@ -1,36 +1,35 @@ -## This test checks how we handle the --pgo-analysis-map option. +## This test checks how we handle PGO Analysis Map in --bb-addr-map. ## Fails on windows (https://github.com/llvm/llvm-project/issues/60013). # UNSUPPORTED: system-windows ## Check 64-bit: # RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o -# RUN: llvm-readobj %t1.x64.o --pgo-analysis-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefix=CHECK -# RUN: llvm-readelf %t1.x64.o --pgo-analysis-map | FileCheck %s --check-prefix=GNU +# RUN: llvm-readobj %t1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefix=CHECK +# RUN: llvm-readelf %t1.x64.o --bb-addr-map | FileCheck %s --check-prefix=GNU ## Check 64-bit: # RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.v1.x64.o -# RUN: llvm-readobj %t1.v1.x64.o --pgo-analysis-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.v1.x64.o --check-prefix=CHECK +# RUN: llvm-readobj %t1.v1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.v1.x64.o --check-prefix=CHECK ## Check 32-bit: # RUN: yaml2obj --docnum=1 %s -DBITS=32 -o %t1.x32.o -# RUN: llvm-readobj %t1.x32.o --pgo-analysis-map 2>&1 | FileCheck -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefix=CHECK -# RUN: llvm-readelf %t1.x32.o --pgo-analysis-map | FileCheck %s --check-prefix=GNU +# RUN: llvm-readobj %t1.x32.o --bb-addr-map 2>&1 | FileCheck -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefix=CHECK +# RUN: llvm-readelf %t1.x32.o --bb-addr-map | FileCheck %s --check-prefix=GNU ## Check that a malformed section can be handled. # RUN: yaml2obj --docnum=1 %s -DBITS=32 -DSIZE=6 -o %t2.o -# RUN: llvm-readobj %t2.o --pgo-analysis-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED +# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED ## Check that invalid metadata can be handled. # RUN: yaml2obj --docnum=1 %s -DBITS=32 -DMETADATA=0xF000002 -o %t3.o -# RUN: llvm-readobj %t3.o --pgo-analysis-map 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALIDMD +# RUN: llvm-readobj %t3.o --bb-addr-map 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALIDMD # CHECK: BBAddrMap [ # CHECK-NEXT: Function { # CHECK-NEXT: At: [[ADDR]] # CHECK-NEXT: warning: '[[FILE]]': could not identify function symbol for address ([[ADDR]]) in SHT_LLVM_BB_ADDR_MAP section with index 3 # CHECK-NEXT: Name: -# CHECK-NEXT: EntryCount: 100 # CHECK-NEXT: BB entries [ # CHECK-NEXT: { # CHECK-NEXT: ID: 0 @@ -41,13 +40,6 @@ # CHECK-NEXT: IsEHPad: No # CHECK-NEXT: CanFallThrough: No # CHECK-NEXT: HasIndirectBranch: No -# CHECK-NEXT: Frequency: 100 -# CHECK-NEXT: Successors [ -# CHECK-NEXT: { -# CHECK-NEXT: ID: 2 -# CHECK-NEXT: Probability: 0xFFFFFFFF -# CHECK-NEXT: } -# CHECK-NEXT: ] # CHECK-NEXT: } # CHECK-NEXT: { # CHECK-NEXT: ID: 2 @@ -58,16 +50,31 @@ # CHECK-NEXT: IsEHPad: Yes # CHECK-NEXT: CanFallThrough: No # CHECK-NEXT: HasIndirectBranch: Yes -# CHECK-NEXT: Frequency: 100 -# CHECK-NEXT: Successors [ -# CHECK-NEXT: ] # CHECK-NEXT: } # CHECK-NEXT: ] +# CHECK-NEXT: PGO analyses { +# CHECK-NEXT: FuncEntryCount: 100 +# CHECK-NEXT: PGO BB entries [ +# CHECK-NEXT: { +# CHECK-NEXT: Frequency: 100 +# CHECK-NEXT: Successors [ +# CHECK-NEXT: { +# CHECK-NEXT: ID: 2 +# CHECK-NEXT: Probability: 0xFFFFFFFF +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: { +# CHECK-NEXT: Frequency: 100 +# CHECK-NEXT: Successors [ +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } # CHECK-NEXT: } # CHECK-NEXT: Function { # CHECK-NEXT: At: 0x22222 # CHECK-NEXT: Name: foo -# CHECK-NEXT: EntryCount: 8888 # CHECK-NEXT: BB entries [ # CHECK-NEXT: { # CHECK-NEXT: ID: 4 @@ -78,9 +85,16 @@ # CHECK-NEXT: IsEHPad: No # CHECK-NEXT: CanFallThrough: Yes # CHECK-NEXT: HasIndirectBranch: No -# CHECK-NEXT: Frequency: 9000 # CHECK-NEXT: } # CHECK-NEXT: ] +# CHECK-NEXT: PGO analyses { +# CHECK-NEXT: FuncEntryCount: 8888 +# CHECK-NEXT: PGO BB entries [ +# CHECK-NEXT: { +# CHECK-NEXT: Frequency: 9000 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } # CHECK-NEXT: } # CHECK-NEXT: ] @@ -94,7 +108,6 @@ # TRUNCATED-NEXT: Function { # TRUNCATED-NEXT: At: 0x33333 # TRUNCATED-NEXT: Name: bar -# TRUNCATED-NEXT: EntryCount: 89 # TRUNCATED-NEXT: BB entries [ # TRUNCATED-NEXT: { # TRUNCATED-NEXT: ID: 6 @@ -117,6 +130,9 @@ # TRUNCATED-NEXT: HasIndirectBranch: No # TRUNCATED-NEXT: } # TRUNCATED-NEXT: ] +# TRUNCATED-NEXT: PGO analyses { +# TRUNCATED-NEXT: FuncEntryCount: 89 +# TRUNCATED-NEXT: } # TRUNCATED-NEXT: } # TRUNCATED-NEXT: ] diff --git a/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test b/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test deleted file mode 100644 index 7a8844b49d443..0000000000000 --- a/llvm/test/tools/llvm-readobj/ELF/pgo-bb-addr-map-relocatable.test +++ /dev/null @@ -1,210 +0,0 @@ -## This test checks how we handle the --pgo-analysis-map option on relocatable -## object files. - -## Fails on windows (https://github.com/llvm/llvm-project/issues/60013). -# UNSUPPORTED: system-windows - -# RUN: yaml2obj %s -o %t1.o -# RUN: llvm-readobj %t1.o --pgo-analysis-map | FileCheck %s - -# CHECK: BBAddrMap [ -# CHECK-NEXT: Function { -# CHECK-NEXT: At: 0x0 -# CHECK-NEXT: Name: -# CHECK-NEXT: EntryCount: 89 -# CHECK-NEXT: BB entries [ -# CHECK-NEXT: { -# CHECK-NEXT: ID: 0 -# CHECK-NEXT: Offset: 0x0 -# CHECK-NEXT: Size: 0xF -# CHECK-NEXT: HasReturn: Yes -# CHECK-NEXT: HasTailCall: No -# CHECK-NEXT: IsEHPad: No -# CHECK-NEXT: CanFallThrough: No -# CHECK-NEXT: HasIndirectBranch: No -# CHECK-NEXT: Frequency: 90 -# CHECK-NEXT: } -# CHECK-NEXT: ] -# CHECK-NEXT: } -# CHECK-NEXT: Function { -# CHECK-NEXT: At: 0x10 -# CHECK-NEXT: Name: -# CHECK-NEXT: BB entries [ -# CHECK-NEXT: { -# CHECK-NEXT: ID: 0 -# CHECK-NEXT: Offset: 0x0 -# CHECK-NEXT: Size: 0x11 -# CHECK-NEXT: HasReturn: No -# CHECK-NEXT: HasTailCall: No -# CHECK-NEXT: IsEHPad: No -# CHECK-NEXT: CanFallThrough: Yes -# CHECK-NEXT: HasIndirectBranch: No -# CHECK-NEXT: Frequency: 123 -# CHECK-NEXT: } -# CHECK-NEXT: ] -# CHECK-NEXT: } -# CHECK-NEXT: ] - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - - Name: .llvm_bb_addr_map - Type: SHT_LLVM_BB_ADDR_MAP - Link: .text - Entries: - - Version: 2 - Feature: 0x3 - BBEntries: - - ID: 0 - AddressOffset: 0x0 - Size: 0xF - Metadata: 0x1 - - Version: 2 - Feature: 0x2 - BBEntries: - - ID: 0 - AddressOffset: 0x0 - Size: 0x11 - Metadata: 0x8 - PGOAnalyses: - - FuncEntryCount: 89 - PGOBBEntries: - - BBFreq: 90 - - PGOBBEntries: - - BBFreq: 123 - - Name: .rela.llvm_bb_addr_map - Type: SHT_RELA - Flags: [ SHF_INFO_LINK ] - Link: .symtab - Info: .llvm_bb_addr_map - Relocations: - - Offset: 0x2 - Symbol: .text - Type: R_X86_64_64 - - Offset: 0x13 - Symbol: .text - Type: R_X86_64_64 - Addend: 16 -Symbols: - - Name: a - Section: .text - Value: 0x0 - - Name: c - Section: .text - Value: 0x10 - - Name: .text - Type: STT_SECTION - Section: .text - -## Check that we get a warning if we expect a relocation and it is not present. - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - - Name: .llvm_bb_addr_map - Type: SHT_LLVM_BB_ADDR_MAP - Link: .text - Entries: - - Version: 2 - Feature: 0x7 - BBEntries: - - ID: 0 - AddressOffset: 0x0 - Size: 0xF - Metadata: 0x1 - PGOAnalyses: - - FuncEntryCount: 2 - PGOBBEntries: - - BBFreq: 2 - - Name: .rela.llvm_bb_addr_map - Type: SHT_RELA - Flags: [ SHF_INFO_LINK ] - Info: .llvm_bb_addr_map - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .rela.llvm_bb_addr_map - Type: SHT_RELA - Flags: [ SHF_INFO_LINK ] - Info: 0xFF - -# RUN: yaml2obj %s --docnum=3 -o %t4.o -# RUN: llvm-readobj %t4.o --pgo-analysis-map 2>&1 | FileCheck %s --check-prefix=NO-RELOCATED-SECTION -DFILE=%t4.o - -# NO-RELOCATED-SECTION: warning: '[[FILE]]': failed to get SHT_LLVM_BB_ADDR_MAP section(s): SHT_RELA section with index 1: failed to get a relocated section: invalid section index: 255 - -## Check that if we have an ET_DYN file with a .rela.dyn section, we don't get -## a warning about a missing relocation section and can get the baddrmap data. - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_DYN - Machine: EM_X86_64 -Sections: - - Name: .rela.dyn - Type: SHT_RELA - Flags: [ SHF_ALLOC ] - - Name: .llvm_bb_addr_map - Type: SHT_LLVM_BB_ADDR_MAP - Flags: [ SHF_LINK_ORDER ] - Entries: - - Version: 2 - Feature: 0x7 - Address: 0xF - BBEntries: - - ID: 0 - AddressOffset: 0x0 - Size: 0xF - Metadata: 0x1 - PGOAnalyses: - - FuncEntryCount: 100 - PGOBBEntries: - - BBFreq: 100 - Successors: [] - -# RUN: yaml2obj %s --docnum=4 -o %t5.o -# RUN: llvm-readobj %t5.o --pgo-analysis-map | FileCheck %s --check-prefix=ET-DYN-NO-WARNING -DFILE=%t5.o - -# ET-DYN-NO-WARNING: BBAddrMap [ -# ET-DYN-NO-WARNING-NEXT: Function { -# ET-DYN-NO-WARNING-NEXT: At: 0xF -# ET-DYN-NO-WARNING-NEXT: Name: -# ET-DYN-NO-WARNING-NEXT: EntryCount: 100 -# ET-DYN-NO-WARNING-NEXT: BB entries [ -# ET-DYN-NO-WARNING-NEXT: { -# ET-DYN-NO-WARNING-NEXT: ID: 0 -# ET-DYN-NO-WARNING-NEXT: Offset: 0x0 -# ET-DYN-NO-WARNING-NEXT: Size: 0xF -# ET-DYN-NO-WARNING-NEXT: HasReturn: Yes -# ET-DYN-NO-WARNING-NEXT: HasTailCall: No -# ET-DYN-NO-WARNING-NEXT: IsEHPad: No -# ET-DYN-NO-WARNING-NEXT: CanFallThrough: No -# ET-DYN-NO-WARNING-NEXT: HasIndirectBranch: No -# ET-DYN-NO-WARNING-NEXT: Frequency: 100 -# ET-DYN-NO-WARNING-NEXT: Successors [ -# ET-DYN-NO-WARNING-NEXT: ] -# ET-DYN-NO-WARNING-NEXT: } -# ET-DYN-NO-WARNING-NEXT: ] -# ET-DYN-NO-WARNING-NEXT: } -# ET-DYN-NO-WARNING-NEXT: ] diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 3b32d98052777..4bf4640f1a4ca 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -593,7 +593,7 @@ template class GNUELFDumper : public ELFDumper { void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printCGProfile() override; - void printBBAddrMaps(bool IncludePGOAnalysis = false) override; + void printBBAddrMaps() override; void printAddrsig() override; void printNotes() override; void printELFLinkerOptions() override; @@ -704,7 +704,7 @@ template class LLVMELFDumper : public ELFDumper { void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printCGProfile() override; - void printBBAddrMaps(bool IncludePGOAnalysis = false) override; + void printBBAddrMaps() override; void printAddrsig() override; void printNotes() override; void printELFLinkerOptions() override; @@ -739,8 +739,6 @@ template class LLVMELFDumper : public ELFDumper { void printMipsABIFlags() override; virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const; - template void printAddrMaps(); - protected: virtual std::string getGroupSectionHeaderName() const; void printSymbolOtherField(const Elf_Sym &Symbol) const; @@ -5072,8 +5070,7 @@ template void GNUELFDumper::printCGProfile() { OS << "GNUStyle::printCGProfile not implemented\n"; } -template -void GNUELFDumper::printBBAddrMaps(bool IncludePGOAnalysis) { +template void GNUELFDumper::printBBAddrMaps() { OS << "GNUStyle::printBBAddrMaps not implemented\n"; } @@ -7544,8 +7541,7 @@ template void LLVMELFDumper::printCGProfile() { } } -template -void LLVMELFDumper::printBBAddrMaps(bool IncludePGOAnalysis) { +template void LLVMELFDumper::printBBAddrMaps() { bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL; using Elf_Shdr = typename ELFT::Shdr; auto IsMatch = [](const Elf_Shdr &Sec) -> bool { @@ -7571,16 +7567,15 @@ void LLVMELFDumper::printBBAddrMaps(bool IncludePGOAnalysis) { this->describe(*Sec)); continue; } - std::vector PGOAnalysis; - Expected> BBAddrMapOrErr = this->Obj.decodeBBAddrMap( - *Sec, RelocSec, IncludePGOAnalysis ? &PGOAnalysis : nullptr); + std::vector PGOAnalyses; + Expected> BBAddrMapOrErr = + this->Obj.decodeBBAddrMap(*Sec, RelocSec, &PGOAnalyses); if (!BBAddrMapOrErr) { this->reportUniqueWarning("unable to dump " + this->describe(*Sec) + ": " + toString(BBAddrMapOrErr.takeError())); continue; } - for (const auto &[Idx, AM] : llvm::enumerate(*BBAddrMapOrErr)) { - const auto *PAM = IncludePGOAnalysis ? &PGOAnalysis[Idx] : nullptr; + for (const auto &[AM, PAM] : zip_equal(*BBAddrMapOrErr, PGOAnalyses)) { DictScope D(W, "Function"); W.printHex("At", AM.Addr); SmallVector FuncSymIndex = @@ -7593,39 +7588,50 @@ void LLVMELFDumper::printBBAddrMaps(bool IncludePGOAnalysis) { else FuncName = this->getStaticSymbolName(FuncSymIndex.front()); W.printString("Name", FuncName); - if (IncludePGOAnalysis && PAM->FeatEnable.FuncEntryCount) - W.printNumber("EntryCount", PAM->FuncEntryCount); - - bool IncludePGOBBData = - IncludePGOAnalysis && PAM->BBEntries.size() == AM.BBEntries.size(); - ListScope L(W, "BB entries"); - for (const auto &[BIdx, BBE] : llvm::enumerate(AM.BBEntries)) { - const auto *PBBE = IncludePGOBBData ? &PAM->BBEntries[BIdx] : nullptr; - DictScope L(W); - W.printNumber("ID", BBE.ID); - W.printHex("Offset", BBE.Offset); - W.printHex("Size", BBE.Size); - W.printBoolean("HasReturn", BBE.hasReturn()); - W.printBoolean("HasTailCall", BBE.hasTailCall()); - W.printBoolean("IsEHPad", BBE.isEHPad()); - W.printBoolean("CanFallThrough", BBE.canFallThrough()); - W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch()); - - /// FIXME: currently we just emit the raw frequency, it may be better to - /// provide an option to scale it by the first entry frequence using - /// BlockFrequency::Scaled64 number - if (IncludePGOBBData && PAM->FeatEnable.BBFreq) - W.printNumber("Frequency", PBBE->BlockFreq.getFrequency()); - - if (IncludePGOBBData && PAM->FeatEnable.BrProb) { - ListScope L(W, "Successors"); - for (const auto &Succ : PBBE->Successors) { + + { + ListScope L(W, "BB entries"); + for (const BBAddrMap::BBEntry &BBE : AM.BBEntries) { + DictScope L(W); + W.printNumber("ID", BBE.ID); + W.printHex("Offset", BBE.Offset); + W.printHex("Size", BBE.Size); + W.printBoolean("HasReturn", BBE.hasReturn()); + W.printBoolean("HasTailCall", BBE.hasTailCall()); + W.printBoolean("IsEHPad", BBE.isEHPad()); + W.printBoolean("CanFallThrough", BBE.canFallThrough()); + W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch()); + } + } + + if (PAM.FeatEnable.anyEnabled()) { + DictScope PD(W, "PGO analyses"); + + if (PAM.FeatEnable.FuncEntryCount) + W.printNumber("FuncEntryCount", PAM.FuncEntryCount); + + if (PAM.FeatEnable.BBFreq || PAM.FeatEnable.BrProb) { + ListScope L(W, "PGO BB entries"); + for (const PGOAnalysisMap::PGOBBEntry &PBBE : PAM.BBEntries) { DictScope L(W); - W.printNumber("ID", Succ.ID); - /// FIXME: currently we just emit the raw numerator of the probably, - /// it may be better to provide an option to emit it as a percentage - /// or other prettied representation - W.printHex("Probability", Succ.Prob.getNumerator()); + + /// FIXME: currently we just emit the raw frequency, it may be + /// better to provide an option to scale it by the first entry + /// frequence using BlockFrequency::Scaled64 number + if (PAM.FeatEnable.BBFreq) + W.printNumber("Frequency", PBBE.BlockFreq.getFrequency()); + + if (PAM.FeatEnable.BrProb) { + ListScope L(W, "Successors"); + for (const auto &Succ : PBBE.Successors) { + DictScope L(W); + W.printNumber("ID", Succ.ID); + /// FIXME: currently we just emit the raw numerator of the + /// probably, it may be better to provide an option to emit it + /// as a percentage or other prettied representation + W.printHex("Probability", Succ.Prob.getNumerator()); + } + } } } } diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 082aba80841c6..1d679453581bc 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -129,7 +129,7 @@ class ObjDumper { virtual void printGroupSections() {} virtual void printHashHistograms() {} virtual void printCGProfile() {} - virtual void printBBAddrMaps(bool IncludePGOAnalysis = false) {} + virtual void printBBAddrMaps() {} virtual void printAddrsig() {} virtual void printNotes() {} virtual void printELFLinkerOptions() {} diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index a981fac2f2f36..e2d93c6ec229e 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -29,7 +29,6 @@ def extra_sym_info : FF<"extra-sym-info", "Display extra information when showin def file_header : FF<"file-header", "Display file header">; def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">; defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"">; -def pgo_analysis_map : FF<"pgo-analysis-map", "Display the BB address map section with PGO data included">; def pretty_print : FF<"pretty-print", "Pretty print JSON output">; def relocs : FF<"relocs", "Display the relocation entries in the file">; def section_data : FF<"section-data", "Display section data for each section shown. This option has no effect for GNU style output">; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index 4dcab4ce5c9f7..f9d605d35244b 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -95,7 +95,6 @@ static bool Addrsig; static bool All; static bool ArchSpecificInfo; static bool BBAddrMap; -static bool PGOAnalysisMap; bool ExpandRelocs; static bool CGProfile; bool Demangle; @@ -212,7 +211,6 @@ static void parseOptions(const opt::InputArgList &Args) { opts::All = Args.hasArg(OPT_all); opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific); opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map); - opts::PGOAnalysisMap = Args.hasArg(OPT_pgo_analysis_map); opts::CGProfile = Args.hasArg(OPT_cg_profile); opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false); opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries); @@ -465,8 +463,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, Dumper->printHashHistograms(); if (opts::CGProfile) Dumper->printCGProfile(); - if (opts::BBAddrMap || opts::PGOAnalysisMap) - Dumper->printBBAddrMaps(opts::PGOAnalysisMap); + if (opts::BBAddrMap) + Dumper->printBBAddrMaps(); if (opts::Addrsig) Dumper->printAddrsig(); if (opts::Notes) From 71a258ccd0000d070bf1c18d554963b733dbd0ba Mon Sep 17 00:00:00 2001 From: Micah Weston Date: Mon, 29 Jan 2024 15:24:18 -0500 Subject: [PATCH 3/3] Updates test based on feedback. --- .../ELF/bb-addr-map-pgo-analysis-map.test | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test index fad2cca1990a4..91b3d7e3902e3 100644 --- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test @@ -1,29 +1,23 @@ -## This test checks how we handle PGO Analysis Map in --bb-addr-map. - -## Fails on windows (https://github.com/llvm/llvm-project/issues/60013). -# UNSUPPORTED: system-windows +## This test checks how llvm-readobj prints the PGO Analysis Map with the +## --bb-addr-map option. ## Check 64-bit: -# RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o +# RUN: yaml2obj %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o # RUN: llvm-readobj %t1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefix=CHECK # RUN: llvm-readelf %t1.x64.o --bb-addr-map | FileCheck %s --check-prefix=GNU -## Check 64-bit: -# RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.v1.x64.o -# RUN: llvm-readobj %t1.v1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.v1.x64.o --check-prefix=CHECK - ## Check 32-bit: -# RUN: yaml2obj --docnum=1 %s -DBITS=32 -o %t1.x32.o +# RUN: yaml2obj %s -DBITS=32 -o %t1.x32.o # RUN: llvm-readobj %t1.x32.o --bb-addr-map 2>&1 | FileCheck -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefix=CHECK # RUN: llvm-readelf %t1.x32.o --bb-addr-map | FileCheck %s --check-prefix=GNU ## Check that a malformed section can be handled. -# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DSIZE=6 -o %t2.o -# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED +# RUN: yaml2obj %s -DBITS=32 -DSIZE=24 -o %t2.o +# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000018 -DFILE=%t2.o --check-prefix=TRUNCATED -## Check that invalid metadata can be handled. -# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DMETADATA=0xF000002 -o %t3.o -# RUN: llvm-readobj %t3.o --bb-addr-map 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALIDMD +## Check that missing features can be handled. +# RUN: yaml2obj %s -DBITS=32 -DFEATURE=0x2 -o %t3.o +# RUN: llvm-readobj %t3.o --bb-addr-map 2>&1 | FileCheck %s -DFILE=%t3.o --check-prefix=INVALIDFT # CHECK: BBAddrMap [ # CHECK-NEXT: Function { @@ -136,8 +130,7 @@ # TRUNCATED-NEXT: } # TRUNCATED-NEXT: ] -# INVALIDMD: BBAddrMap [ -# INVALIDMD-NEXT: warning: '[[FILE]]': unable to dump SHT_LLVM_BB_ADDR_MAP section with index 3: invalid encoding for BBEntry::Metadata: 0xf000002 +# INVALIDFT: warning: '[[FILE]]': unable to dump SHT_LLVM_BB_ADDR_MAP section with index 5: unable to decode LEB128 at offset 0x00000010: malformed uleb128, extends past end --- !ELF FileHeader: @@ -163,7 +156,7 @@ Sections: - ID: 0 AddressOffset: 0x0 Size: 0x1 - Metadata: [[METADATA=0x2]] + Metadata: 0x2 - ID: 2 AddressOffset: 0x3 Size: 0x4 @@ -196,7 +189,7 @@ Sections: Link: .text.bar Entries: - Version: 2 - Feature: 0x1 + Feature: [[FEATURE=0x1]] Address: 0x33333 BBEntries: - ID: 6