Skip to content

[SHT_LLVM_BB_ADDR_MAP] Adds pretty printing of BFI and BPI for PGO Analysis Map in tools. #82292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,6 @@ class BlockFrequencyInfoImplBase {
}
};

void printBlockFreqImpl(raw_ostream &OS, BlockFrequency EntryFreq,
BlockFrequency Freq);

namespace bfi_detail {

template <class BlockT> struct TypeMap {};
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Support/BlockFrequency.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace llvm {

class raw_ostream;
class BranchProbability;

// This class represents Block Frequency as a 64-bit value.
Expand Down Expand Up @@ -119,6 +120,9 @@ class BlockFrequency {
}
};

void printRelativeBlockFreq(raw_ostream &OS, BlockFrequency EntryFreq,
BlockFrequency Freq);

} // namespace llvm

#endif
2 changes: 1 addition & 1 deletion llvm/lib/Analysis/BlockFrequencyInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
}

Expand Down
15 changes: 0 additions & 15 deletions llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 << "<invalid BFI>";
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());
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
}

Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Support/BlockFrequency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -45,3 +47,18 @@ std::optional<BlockFrequency> 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 << "<invalid BFI>";
return;
}
ScaledNumber<uint64_t> Block(Freq.getFrequency(), 0);
ScaledNumber<uint64_t> Entry(EntryFreq.getFrequency(), 0);
OS << Block / Entry;
}
56 changes: 38 additions & 18 deletions llvm/test/tools/llvm-objdump/X86/elf-pgoanalysismap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -98,18 +100,28 @@ Symbols:
Section: .text.foo
Value: 0x0

# ENTRYCOUNT-BLOCKFREQ: <foo>:
# ENTRYCOUNT-BLOCKFREQ: <BB3> (Entry count: 1000, Frequency: 1000):
# ENTRYCOUNT-BLOCKFREQ: <BB1> (Frequency: 133):
# ENTRYCOUNT-BLOCKFREQ: <BB2> (Frequency: 18):
# ENTRYCOUNT-BLOCKFREQ: <BB5> (Frequency: 1000):
# ENTRYCOUNT-BLOCKFREQ:<foo>:
# ENTRYCOUNT-BLOCKFREQ:<BB3> (Entry count: 1000, Frequency: 1000):
# ENTRYCOUNT-BLOCKFREQ:<BB1> (Frequency: 133):
# ENTRYCOUNT-BLOCKFREQ:<BB2> (Frequency: 18):
# ENTRYCOUNT-BLOCKFREQ:<BB5> (Frequency: 1000):

# ENTRYCOUNT-BLOCKFREQ-PRETTY:<foo>:
# ENTRYCOUNT-BLOCKFREQ-PRETTY:<BB3> (Entry count: 1000, Frequency: 1.0):
# ENTRYCOUNT-BLOCKFREQ-PRETTY:<BB1> (Frequency: 0.133):
# ENTRYCOUNT-BLOCKFREQ-PRETTY:<BB2> (Frequency: 0.018):
# ENTRYCOUNT-BLOCKFREQ-PRETTY:<BB5> (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:
Expand Down Expand Up @@ -154,30 +166,38 @@ 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:
- Name: foo
Section: .text.foo
Value: 0x0

# ENTRY-FREQ-PROB: <foo>:
# ENTRY-FREQ-PROB: <BB3> (Entry count: 1000, Frequency: 1000, Successors: BB1:22222222, BB2:33333333, BB3:aaaaaaaa):
# ENTRY-FREQ-PROB: <BB1> (Frequency: 133, Successors: BB2:11111111, BB3:eeeeeeee):
# ENTRY-FREQ-PROB: <BB2> (Frequency: 18, Successors: BB3:ffffffff):
# ENTRY-FREQ-PROB: <BB5> (Frequency: 1000):
# ENTRY-FREQ-PROB:<foo>:
# ENTRY-FREQ-PROB:<BB3> (Entry count: 1000, Frequency: 1000, Successors: BB1:10000000, BB2:15000000, BB3:50000000):
# ENTRY-FREQ-PROB:<BB1> (Frequency: 133, Successors: BB2:10000000, BB3:70000000):
# ENTRY-FREQ-PROB:<BB2> (Frequency: 18, Successors: BB3:80000000):
# ENTRY-FREQ-PROB:<BB5> (Frequency: 1000):

# ENTRY-FREQ-PROB-PRETTY:<foo>:
# ENTRY-FREQ-PROB-PRETTY:<BB3> (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:<BB1> (Frequency: 0.133, Successors: BB2:[0x10000000 / 0x80000000 = 12.50%], BB3:[0x70000000 / 0x80000000 = 87.50%]):
# ENTRY-FREQ-PROB-PRETTY:<BB2> (Frequency: 0.018, Successors: BB3:[0x80000000 / 0x80000000 = 100.00%]):
# ENTRY-FREQ-PROB-PRETTY:<BB5> (Frequency: 1.0):

# MISSING-SYMBOLIZE-OPERANDS: warning: --symbolize-operands must be enabled for --pretty-pgo-analysis-map to have an effect
22 changes: 15 additions & 7 deletions llvm/test/tools/llvm-readobj/ELF/bb-addr-map-pgo-analysis-map.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

## 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 %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 %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefixes=CHECK,PRETTY
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same coomment as above re. --strict-whitespace etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readobj, full line matching and strict whitespace is less needed since the structure formatting is done by ScopedPrinters, rather than manual like objdump. The braces and bracket are good enough to validate the fields are printed in the right spot and then trust the spacing is accurate from ScopedPrinters tests. There is a warning that we test for which throws off a full line match since it contains the readobj absolute path which varies by host test machine.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The braces and bracket are good enough to validate the fields are printed in the right spot and then trust the spacing is accurate from ScopedPrinters tests.

In this context, I'm actually more interested in checking that there isn't anything on the line that is unexpected (e.g. garbage data etc). --match-full-lines on its own would probably suffice in this case.

There is a warning that we test for which throws off a full line match since it contains the readobj absolute path which varies by host test machine.

FWIW, this is easily dealt with by adding {{.*}} to the start of the check for the warning.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion, I added match-full-lines to these tests.

# 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 -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.
Expand Down Expand Up @@ -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: }
Expand Down Expand Up @@ -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: }
Expand All @@ -104,6 +110,8 @@

# 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: ]
Expand Down Expand Up @@ -192,7 +200,7 @@ Sections:
- BBFreq: 100
Successors:
- ID: 2
BrProb: 0xFFFFFFFF
BrProb: 0x80000000
- BBFreq: 100
Successors: []
- FuncEntryCount: 8888
Expand Down
29 changes: 22 additions & 7 deletions llvm/tools/llvm-objdump/llvm-objdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 << ", ";
}
Expand All @@ -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());
});
}
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)});
}
}

Expand Down Expand Up @@ -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);
Expand Down
Loading