diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst index 959452a74b23e..7f8def756c696 100644 --- a/llvm/docs/CommandGuide/llvm-objdump.rst +++ b/llvm/docs/CommandGuide/llvm-objdump.rst @@ -271,7 +271,12 @@ OPTIONS When printing a PC-relative global symbol reference, print it as an offset from the leading symbol. - When a bb-address-map section is present (i.e., the object file is built with ``-fbasic-block-sections=labels``), labels are retrieved from that section instead. + When a bb-address-map section is present (i.e., the object file is built with + ``-fbasic-block-sections=labels``), labels are retrieved from that section + instead. If a pgo-analysis-map is present alongside the bb-address-map, any + available analyses are printed after the relevant block label. By default, + any analysis with a special representation (i.e. BlockFrequency, + BranchProbability, etc) are printed as raw hex values. Only works with PowerPC objects or X86 linked images. @@ -291,6 +296,15 @@ OPTIONS cmp eax, dword ptr jge +.. option:: --pretty-pgo-analysis-map + + When using :option:`--symbolize-operands` with bb-address-map and + pgo-analysis-map, print analyses using the same format as their analysis + passes would. An example of pretty format would be printing block frequencies + relative to the entry block, the same as BFI. + + Only works when :option:`--symbolize-operands` is enabled. + .. option:: --triple= Target triple to disassemble for, see ``--version`` for available targets. diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst index cb9232ef5e560..7e4093c9fcfe1 100644 --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -159,6 +159,17 @@ The following options are implemented only for the ELF file format. Display the contents of the basic block address map section(s), which contain the address of each function, along with the relative offset of each basic block. + When pgo analysis maps are present, all analyses are printed as their raw + value. + +.. option:: --pretty-pgo-analysis-map + + When pgo analysis maps are present in the basic block address map section(s), + analyses with special formats (i.e. BlockFrequency, BranchProbability, etc) + are printed using the same format as their respective analysis pass. + + Requires :option:`--bb-addr-map` to have an effect. + .. option:: --demangle, -C Display demangled symbol names in the output. diff --git a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 8acb75e872541..4aa922635c374 100644 --- a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -539,9 +539,6 @@ class BlockFrequencyInfoImplBase { } }; -void printBlockFreqImpl(raw_ostream &OS, BlockFrequency EntryFreq, - BlockFrequency Freq); - namespace bfi_detail { template struct TypeMap {}; diff --git a/llvm/include/llvm/Support/BlockFrequency.h b/llvm/include/llvm/Support/BlockFrequency.h index 8b172ee486aab..aeab99615a951 100644 --- a/llvm/include/llvm/Support/BlockFrequency.h +++ b/llvm/include/llvm/Support/BlockFrequency.h @@ -19,6 +19,7 @@ namespace llvm { +class raw_ostream; class BranchProbability; // This class represents Block Frequency as a 64-bit value. @@ -119,6 +120,9 @@ class BlockFrequency { } }; +void printRelativeBlockFreq(raw_ostream &OS, BlockFrequency EntryFreq, + BlockFrequency Freq); + } // namespace llvm #endif diff --git a/llvm/lib/Analysis/BlockFrequencyInfo.cpp b/llvm/lib/Analysis/BlockFrequencyInfo.cpp index 96c9bfa0e372c..ebad8388cbe41 100644 --- a/llvm/lib/Analysis/BlockFrequencyInfo.cpp +++ b/llvm/lib/Analysis/BlockFrequencyInfo.cpp @@ -284,7 +284,7 @@ void BlockFrequencyInfo::verifyMatch(BlockFrequencyInfo &Other) const { Printable llvm::printBlockFreq(const BlockFrequencyInfo &BFI, BlockFrequency Freq) { return Printable([&BFI, Freq](raw_ostream &OS) { - printBlockFreqImpl(OS, BFI.getEntryFreq(), Freq); + printRelativeBlockFreq(OS, BFI.getEntryFreq(), Freq); }); } diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp index ae08d56ef098a..9f6e53ba15b6a 100644 --- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp +++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp @@ -634,21 +634,6 @@ BlockFrequencyInfoImplBase::getLoopName(const LoopData &Loop) const { return getBlockName(Loop.getHeader()) + (Loop.isIrreducible() ? "**" : "*"); } -void llvm::printBlockFreqImpl(raw_ostream &OS, BlockFrequency EntryFreq, - BlockFrequency Freq) { - if (Freq == BlockFrequency(0)) { - OS << "0"; - return; - } - if (EntryFreq == BlockFrequency(0)) { - OS << ""; - return; - } - Scaled64 Block(Freq.getFrequency(), 0); - Scaled64 Entry(EntryFreq.getFrequency(), 0); - OS << Block / Entry; -} - void IrreducibleGraph::addNodesInLoop(const BFIBase::LoopData &OuterLoop) { Start = OuterLoop.getHeader(); Nodes.reserve(OuterLoop.Nodes.size()); diff --git a/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp b/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp index 7ee72e2144263..cbebdd87398e4 100644 --- a/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp +++ b/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp @@ -280,7 +280,7 @@ BlockFrequency MachineBlockFrequencyInfo::getEntryFreq() const { Printable llvm::printBlockFreq(const MachineBlockFrequencyInfo &MBFI, BlockFrequency Freq) { return Printable([&MBFI, Freq](raw_ostream &OS) { - printBlockFreqImpl(OS, MBFI.getEntryFreq(), Freq); + printRelativeBlockFreq(OS, MBFI.getEntryFreq(), Freq); }); } diff --git a/llvm/lib/Support/BlockFrequency.cpp b/llvm/lib/Support/BlockFrequency.cpp index 329f1e12cdc29..7d5498e7cb997 100644 --- a/llvm/lib/Support/BlockFrequency.cpp +++ b/llvm/lib/Support/BlockFrequency.cpp @@ -13,6 +13,8 @@ #include "llvm/Support/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/ScaledNumber.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -45,3 +47,18 @@ std::optional BlockFrequency::mul(uint64_t Factor) const { return {}; return BlockFrequency(ResultFrequency); } + +void llvm::printRelativeBlockFreq(raw_ostream &OS, BlockFrequency EntryFreq, + BlockFrequency Freq) { + if (Freq == BlockFrequency(0)) { + OS << "0"; + return; + } + if (EntryFreq == BlockFrequency(0)) { + OS << ""; + return; + } + ScaledNumber Block(Freq.getFrequency(), 0); + ScaledNumber Entry(EntryFreq.getFrequency(), 0); + OS << Block / Entry; +} diff --git a/llvm/test/tools/llvm-objdump/X86/elf-pgoanalysismap.yaml b/llvm/test/tools/llvm-objdump/X86/elf-pgoanalysismap.yaml index 732fab3e2a378..4d1e5408d86d4 100644 --- a/llvm/test/tools/llvm-objdump/X86/elf-pgoanalysismap.yaml +++ b/llvm/test/tools/llvm-objdump/X86/elf-pgoanalysismap.yaml @@ -47,7 +47,9 @@ Symbols: # RUN: yaml2obj %s --docnum=2 -o %t2 # RUN: llvm-objdump %t2 -d --symbolize-operands --no-show-raw-insn --no-leading-addr | \ -# RUN: FileCheck %s --check-prefix=ENTRYCOUNT-BLOCKFREQ +# RUN: FileCheck --match-full-lines --strict-whitespace %s --check-prefix=ENTRYCOUNT-BLOCKFREQ +# RUN: llvm-objdump %t2 -d --symbolize-operands --pretty-pgo-analysis-map --no-show-raw-insn --no-leading-addr | \ +# RUN: FileCheck --match-full-lines --strict-whitespace %s --check-prefix=ENTRYCOUNT-BLOCKFREQ-PRETTY --- !ELF FileHeader: @@ -98,18 +100,28 @@ Symbols: Section: .text.foo Value: 0x0 -# ENTRYCOUNT-BLOCKFREQ: : -# ENTRYCOUNT-BLOCKFREQ: (Entry count: 1000, Frequency: 1000): -# ENTRYCOUNT-BLOCKFREQ: (Frequency: 133): -# ENTRYCOUNT-BLOCKFREQ: (Frequency: 18): -# ENTRYCOUNT-BLOCKFREQ: (Frequency: 1000): +# ENTRYCOUNT-BLOCKFREQ:: +# ENTRYCOUNT-BLOCKFREQ: (Entry count: 1000, Frequency: 1000): +# ENTRYCOUNT-BLOCKFREQ: (Frequency: 133): +# ENTRYCOUNT-BLOCKFREQ: (Frequency: 18): +# ENTRYCOUNT-BLOCKFREQ: (Frequency: 1000): + +# ENTRYCOUNT-BLOCKFREQ-PRETTY:: +# ENTRYCOUNT-BLOCKFREQ-PRETTY: (Entry count: 1000, Frequency: 1.0): +# ENTRYCOUNT-BLOCKFREQ-PRETTY: (Frequency: 0.133): +# ENTRYCOUNT-BLOCKFREQ-PRETTY: (Frequency: 0.018): +# ENTRYCOUNT-BLOCKFREQ-PRETTY: (Frequency: 1.0): ## Check the case where we have entry points, block frequency, and branch ## proabability information. # RUN: yaml2obj %s --docnum=3 -o %t3 # RUN: llvm-objdump %t3 -d --symbolize-operands --no-show-raw-insn --no-leading-addr | \ -# RUN: FileCheck %s --check-prefix=ENTRY-FREQ-PROB +# RUN: FileCheck --match-full-lines --strict-whitespace %s --check-prefix=ENTRY-FREQ-PROB +# RUN: llvm-objdump %t3 -d --symbolize-operands --pretty-pgo-analysis-map --no-show-raw-insn --no-leading-addr | \ +# RUN: FileCheck --match-full-lines --strict-whitespace %s --check-prefix=ENTRY-FREQ-PROB-PRETTY +# RUN: llvm-objdump %t3 -d --pretty-pgo-analysis-map --no-show-raw-insn --no-leading-addr 2>&1 | \ +# RUN: FileCheck %s --check-prefix=MISSING-SYMBOLIZE-OPERANDS --- !ELF FileHeader: @@ -154,21 +166,21 @@ Sections: - BBFreq: 1000 Successors: - ID: 1 - BrProb: 0x22222222 + BrProb: 0x10000000 - ID: 2 - BrProb: 0x33333333 + BrProb: 0x15000000 - ID: 3 - BrProb: 0xaaaaaaaa + BrProb: 0x50000000 - BBFreq: 133 Successors: - ID: 2 - BrProb: 0x11111111 + BrProb: 0x10000000 - ID: 3 - BrProb: 0xeeeeeeee + BrProb: 0x70000000 - BBFreq: 18 Successors: - ID: 3 - BrProb: 0xffffffff + BrProb: 0x80000000 - BBFreq: 1000 Successors: [] Symbols: @@ -176,8 +188,16 @@ Symbols: Section: .text.foo Value: 0x0 -# ENTRY-FREQ-PROB: : -# ENTRY-FREQ-PROB: (Entry count: 1000, Frequency: 1000, Successors: BB1:22222222, BB2:33333333, BB3:aaaaaaaa): -# ENTRY-FREQ-PROB: (Frequency: 133, Successors: BB2:11111111, BB3:eeeeeeee): -# ENTRY-FREQ-PROB: (Frequency: 18, Successors: BB3:ffffffff): -# ENTRY-FREQ-PROB: (Frequency: 1000): +# ENTRY-FREQ-PROB:: +# ENTRY-FREQ-PROB: (Entry count: 1000, Frequency: 1000, Successors: BB1:10000000, BB2:15000000, BB3:50000000): +# ENTRY-FREQ-PROB: (Frequency: 133, Successors: BB2:10000000, BB3:70000000): +# ENTRY-FREQ-PROB: (Frequency: 18, Successors: BB3:80000000): +# ENTRY-FREQ-PROB: (Frequency: 1000): + +# ENTRY-FREQ-PROB-PRETTY:: +# ENTRY-FREQ-PROB-PRETTY: (Entry count: 1000, Frequency: 1.0, Successors: BB1:[0x10000000 / 0x80000000 = 12.50%], BB2:[0x15000000 / 0x80000000 = 16.41%], BB3:[0x50000000 / 0x80000000 = 62.50%]): +# ENTRY-FREQ-PROB-PRETTY: (Frequency: 0.133, Successors: BB2:[0x10000000 / 0x80000000 = 12.50%], BB3:[0x70000000 / 0x80000000 = 87.50%]): +# ENTRY-FREQ-PROB-PRETTY: (Frequency: 0.018, Successors: BB3:[0x80000000 / 0x80000000 = 100.00%]): +# ENTRY-FREQ-PROB-PRETTY: (Frequency: 1.0): + +# MISSING-SYMBOLIZE-OPERANDS: warning: --symbolize-operands must be enabled for --pretty-pgo-analysis-map to have an effect 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 e5a9400c670c0..5faafd4d83b2f 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 @@ -3,17 +3,19 @@ ## Check 64-bit: # 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-readobj %t1.x64.o --bb-addr-map 2>&1 | FileCheck --match-full-lines %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefixes=CHECK,RAW +# RUN: llvm-readobj %t1.x64.o --bb-addr-map --pretty-pgo-analysis-map 2>&1 | FileCheck --match-full-lines %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefixes=CHECK,PRETTY # RUN: llvm-readelf %t1.x64.o --bb-addr-map | FileCheck %s --check-prefix=GNU +# RUN: llvm-readobj %t1.x64.o --pretty-pgo-analysis-map 2>&1 | FileCheck %s --check-prefix=PRETTY-NO-BAM ## Check 32-bit: # 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-readobj %t1.x32.o --bb-addr-map 2>&1 | FileCheck --match-full-lines -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefixes=CHECK,RAW # RUN: llvm-readelf %t1.x32.o --bb-addr-map | FileCheck %s --check-prefix=GNU ## Check that a malformed section can be handled. # 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 +# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck --match-full-lines %s -DOFFSET=0x00000018 -DFILE=%t2.o --check-prefix=TRUNCATED ## Check that missing features can be handled. # RUN: yaml2obj %s -DBITS=32 -DFEATURE=0x2 -o %t3.o @@ -22,7 +24,7 @@ # 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: {{.*}}: 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: BB Ranges [ # CHECK-NEXT: { @@ -55,16 +57,19 @@ # CHECK-NEXT: FuncEntryCount: 100 # CHECK-NEXT: PGO BB entries [ # CHECK-NEXT: { -# CHECK-NEXT: Frequency: 100 +# RAW-NEXT: Frequency: 100 +# PRETTY-NEXT: Frequency: 1.0 # CHECK-NEXT: Successors [ # CHECK-NEXT: { # CHECK-NEXT: ID: 2 -# CHECK-NEXT: Probability: 0xFFFFFFFF +# RAW-NEXT: Probability: 0x80000000 +# PRETTY-NEXT: Probability: 0x80000000 / 0x80000000 = 100.00% # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } # CHECK-NEXT: { -# CHECK-NEXT: Frequency: 100 +# RAW-NEXT: Frequency: 100 +# PRETTY-NEXT: Frequency: 1.0 # CHECK-NEXT: Successors [ # CHECK-NEXT: ] # CHECK-NEXT: } @@ -95,7 +100,8 @@ # CHECK-NEXT: FuncEntryCount: 8888 # CHECK-NEXT: PGO BB entries [ # CHECK-NEXT: { -# CHECK-NEXT: Frequency: 9000 +# RAW-NEXT: Frequency: 9000 +# PRETTY-NEXT: Frequency: 1.0 # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } @@ -104,8 +110,10 @@ # GNU: GNUStyle::printBBAddrMaps not implemented +# PRETTY-NO-BAM: warning: --bb-addr-map must be enabled for --pretty-pgo-analysis-map to have an effect + # 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: {{.*}}: 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 [ @@ -192,7 +200,7 @@ Sections: - BBFreq: 100 Successors: - ID: 2 - BrProb: 0xFFFFFFFF + BrProb: 0x80000000 - BBFreq: 100 Successors: [] - FuncEntryCount: 8888 diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td index c1dec5ced89d3..c3764c6e97534 100644 --- a/llvm/tools/llvm-objdump/ObjdumpOpts.td +++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td @@ -210,6 +210,10 @@ def : Flag<["-"], "t">, Alias, HelpText<"Alias for --syms">; def symbolize_operands : Flag<["--"], "symbolize-operands">, HelpText<"Symbolize instruction operands when disassembling">; +def pretty_pgo_analysis_map : Flag<["--"], "pretty-pgo-analysis-map">, + HelpText<"Display PGO analysis values with " + "formatting rather than raw numbers">; + def dynamic_syms : Flag<["--"], "dynamic-syms">, HelpText<"Display the contents of the dynamic symbol table">; def : Flag<["-"], "T">, Alias, diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 948a5d74e1ab2..78cf67b1e630b 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -188,8 +188,10 @@ class BBAddrMapFunctionEntry { const BBAddrMap &getAddrMap() const { return AddrMap; } // Returns the PGO string associated with the entry of index `PGOBBEntryIndex` - // in `PGOMap`. - std::string constructPGOLabelString(size_t PGOBBEntryIndex) const { + // in `PGOMap`. If PrettyPGOAnalysis is true, prints BFI as relative frequency + // and BPI as percentage. Otherwise raw values are displayed. + std::string constructPGOLabelString(size_t PGOBBEntryIndex, + bool PrettyPGOAnalysis) const { if (!PGOMap.FeatEnable.hasPGOAnalysis()) return ""; std::string PGOString; @@ -211,7 +213,12 @@ class BBAddrMapFunctionEntry { PGOMap.BBEntries[PGOBBEntryIndex]; if (PGOMap.FeatEnable.BBFreq) { - PGOSS << "Frequency: " << Twine(PGOBBEntry.BlockFreq.getFrequency()); + PGOSS << "Frequency: "; + if (PrettyPGOAnalysis) + printRelativeBlockFreq(PGOSS, PGOMap.BBEntries.front().BlockFreq, + PGOBBEntry.BlockFreq); + else + PGOSS << Twine(PGOBBEntry.BlockFreq.getFrequency()); if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) { PGOSS << ", "; } @@ -220,9 +227,12 @@ class BBAddrMapFunctionEntry { PGOSS << "Successors: "; interleaveComma( PGOBBEntry.Successors, PGOSS, - [&PGOSS](const PGOAnalysisMap::PGOBBEntry::SuccessorEntry &SE) { + [&](const PGOAnalysisMap::PGOBBEntry::SuccessorEntry &SE) { PGOSS << "BB" << SE.ID << ":"; - PGOSS.write_hex(SE.Prob.getNumerator()); + if (PrettyPGOAnalysis) + PGOSS << "[" << SE.Prob << "]"; + else + PGOSS.write_hex(SE.Prob.getNumerator()); }); } } @@ -331,6 +341,7 @@ static bool HasStopAddressFlag; bool objdump::SymbolTable; static bool SymbolizeOperands; +static bool PrettyPGOAnalysisMap; static bool DynamicSymbolTable; std::string objdump::TripleName; bool objdump::UnwindInfo; @@ -1410,8 +1421,8 @@ static void collectBBAddrMapLabels( std::string LabelString = ("BB" + Twine(BBEntry.ID)).str(); Labels[BBAddress].push_back( - {LabelString, - FunctionMap->constructPGOLabelString(NumBBEntriesBeforeRange + I)}); + {LabelString, FunctionMap->constructPGOLabelString( + NumBBEntriesBeforeRange + I, PrettyPGOAnalysisMap)}); } } @@ -3473,6 +3484,10 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) { HasStopAddressFlag = InputArgs.hasArg(OBJDUMP_stop_address_EQ); SymbolTable = InputArgs.hasArg(OBJDUMP_syms); SymbolizeOperands = InputArgs.hasArg(OBJDUMP_symbolize_operands); + PrettyPGOAnalysisMap = InputArgs.hasArg(OBJDUMP_pretty_pgo_analysis_map); + if (PrettyPGOAnalysisMap && !SymbolizeOperands) + reportCmdLineWarning("--symbolize-operands must be enabled for " + "--pretty-pgo-analysis-map to have an effect"); DynamicSymbolTable = InputArgs.hasArg(OBJDUMP_dynamic_syms); TripleName = InputArgs.getLastArgValue(OBJDUMP_triple_EQ).str(); UnwindInfo = InputArgs.hasArg(OBJDUMP_unwind_info); diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 50ea63e87a43b..33ee6055b9b4d 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 PrettyPGOAnalysis) 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 PrettyPGOAnalysis) override; void printAddrsig() override; void printNotes() override; void printELFLinkerOptions() override; @@ -5031,7 +5031,8 @@ template void GNUELFDumper::printCGProfile() { OS << "GNUStyle::printCGProfile not implemented\n"; } -template void GNUELFDumper::printBBAddrMaps() { +template +void GNUELFDumper::printBBAddrMaps(bool /*PrettyPGOAnalysis*/) { OS << "GNUStyle::printBBAddrMaps not implemented\n"; } @@ -7521,7 +7522,8 @@ template void LLVMELFDumper::printCGProfile() { } } -template void LLVMELFDumper::printBBAddrMaps() { +template +void LLVMELFDumper::printBBAddrMaps(bool PrettyPGOAnalysis) { bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL; using Elf_Shdr = typename ELFT::Shdr; auto IsMatch = [](const Elf_Shdr &Sec) -> bool { @@ -7600,21 +7602,28 @@ template void LLVMELFDumper::printBBAddrMaps() { for (const PGOAnalysisMap::PGOBBEntry &PBBE : PAM.BBEntries) { DictScope L(W); - /// 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.BBFreq) { + if (PrettyPGOAnalysis) { + std::string BlockFreqStr; + raw_string_ostream SS(BlockFreqStr); + printRelativeBlockFreq(SS, PAM.BBEntries.front().BlockFreq, + PBBE.BlockFreq); + W.printString("Frequency", BlockFreqStr); + } else { + 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()); + if (PrettyPGOAnalysis) { + W.printObject("Probability", Succ.Prob); + } else { + W.printHex("Probability", Succ.Prob.getNumerator()); + } } } } diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 1d679453581bc..ae51019fa30bb 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -129,7 +129,9 @@ class ObjDumper { virtual void printGroupSections() {} virtual void printHashHistograms() {} virtual void printCGProfile() {} - virtual void printBBAddrMaps() {} + // If PrettyPGOAnalysis is true, prints BFI as relative frequency and BPI as + // percentage. Otherwise raw values are displayed. + virtual void printBBAddrMaps(bool PrettyPGOAnalysis) {} 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..765a43fdef7ce 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -19,6 +19,7 @@ def all : FF<"all", "Equivalent to setting: --file-header, --program-headers, -- "--section-groups and --histogram">; def arch_specific : FF<"arch-specific", "Display architecture-specific information">; def bb_addr_map : FF<"bb-addr-map", "Display the BB address map section">; +def pretty_pgo_analysis_map : FF<"pretty-pgo-analysis-map", "Display PGO analysis values with formatting rather than raw numbers">; def cg_profile : FF<"cg-profile", "Display call graph profile section">; defm demangle : BB<"demangle", "Demangle symbol names", "Do not demangle symbol names (default)">; def dependent_libraries : FF<"dependent-libraries", "Display the dependent libraries section">; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index f9d605d35244b..43e976d106ead 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 PrettyPGOAnalysisMap; bool ExpandRelocs; static bool CGProfile; bool Demangle; @@ -211,6 +212,11 @@ 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::PrettyPGOAnalysisMap = Args.hasArg(OPT_pretty_pgo_analysis_map); + if (opts::PrettyPGOAnalysisMap && !opts::BBAddrMap) + WithColor::warning(errs(), ToolName) + << "--bb-addr-map must be enabled for --pretty-pgo-analysis-map to " + "have an effect\n"; opts::CGProfile = Args.hasArg(OPT_cg_profile); opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false); opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries); @@ -464,7 +470,7 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, if (opts::CGProfile) Dumper->printCGProfile(); if (opts::BBAddrMap) - Dumper->printBBAddrMaps(); + Dumper->printBBAddrMaps(opts::PrettyPGOAnalysisMap); if (opts::Addrsig) Dumper->printAddrsig(); if (opts::Notes)