[llvm] Use the Propeller CFG profile in the PGO analysis map if it is available. (PR #163252)
Rahman Lavaee via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 21 09:56:42 PDT 2025
https://github.com/rlavaee updated https://github.com/llvm/llvm-project/pull/163252
>From 0903d669c62d9c168c5a3ac85bbbe59a2d943622 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 17:29:55 +0000
Subject: [PATCH 01/11] Emit the PGO analysis map based on the Propeller
profile.
---
.../CodeGen/BasicBlockSectionsProfileReader.h | 49 ++++++++---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 87 ++++++++++++++-----
.../BasicBlockSectionsProfileReader.cpp | 25 +-----
.../X86/basic-block-sections-pgo-features.ll | 64 ++++++++++++++
4 files changed, 167 insertions(+), 58 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
diff --git a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
index 82dd5feb31dba..3c0e26bad7a5b 100644
--- a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
+++ b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
@@ -42,18 +42,40 @@ struct BBClusterInfo {
unsigned PositionInCluster;
};
+// This represents the CFG profile data for a function.
+struct CFGProfile {
+ // Node counts for each basic block.
+ DenseMap<UniqueBBID, uint64_t> NodeCounts;
+ // Edge counts for each edge, stored as a nested map.
+ DenseMap<UniqueBBID, DenseMap<UniqueBBID, uint64_t>> EdgeCounts;
+
+ // Returns the profile count for the given basic block or zero if it does not
+ // exist.
+ uint64_t getNodeCount(const UniqueBBID &BBID) const {
+ return NodeCounts.lookup(BBID);
+ }
+
+ // Returns the profile count for the edge from `SrcBBID` to `SinkBBID` or
+ // zero if it does not exist.
+ uint64_t getEdgeCount(const UniqueBBID &SrcBBID,
+ const UniqueBBID &SinkBBID) const {
+ auto It = EdgeCounts.find(SrcBBID);
+ if (It == EdgeCounts.end())
+ return 0;
+ return It->second.lookup(SinkBBID);
+ }
+};
+
// This represents the raw input profile for one function.
-struct FunctionPathAndClusterInfo {
+struct FunctionProfile {
// BB Cluster information specified by `UniqueBBID`s.
SmallVector<BBClusterInfo> ClusterInfo;
// Paths to clone. A path a -> b -> c -> d implies cloning b, c, and d along
// the edge a -> b (a is not cloned). The index of the path in this vector
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
- // Node counts for each basic block.
- DenseMap<UniqueBBID, uint64_t> NodeCounts;
- // Edge counts for each edge, stored as a nested map.
- DenseMap<UniqueBBID, DenseMap<UniqueBBID, uint64_t>> EdgeCounts;
+ // CFG profile data.
+ CFGProfile CFG;
};
class BasicBlockSectionsProfileReader {
@@ -81,10 +103,14 @@ class BasicBlockSectionsProfileReader {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;
- // Returns the profile count for the edge from `SrcBBID` to `SinkBBID` in
- // function `FuncName` or zero if it does not exist.
- uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID,
- const UniqueBBID &SinkBBID) const;
+ // Returns a pointer to the CFGProfile for the given function.
+ // Returns nullptr if no profile data is available for the function.
+ const CFGProfile *getFunctionCFGProfile(StringRef FuncName) const {
+ auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
+ if (It == ProgramPathAndClusterInfo.end())
+ return nullptr;
+ return &It->second.CFG;
+ }
private:
StringRef getAliasName(StringRef FuncName) const {
@@ -132,7 +158,7 @@ class BasicBlockSectionsProfileReader {
// for (all or some of) its basic blocks. The cluster information for every
// basic block includes its cluster ID along with the position of the basic
// block in that cluster.
- StringMap<FunctionPathAndClusterInfo> ProgramPathAndClusterInfo;
+ StringMap<FunctionProfile> ProgramPathAndClusterInfo;
// Some functions have alias names. We use this map to find the main alias
// name which appears in ProgramPathAndClusterInfo as a key.
@@ -192,9 +218,6 @@ class BasicBlockSectionsProfileReaderWrapperPass : public ImmutablePass {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;
- uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID,
- const UniqueBBID &DestBBID) const;
-
// Initializes the FunctionNameToDIFilename map for the current module and
// then reads the profile for the matching functions.
bool doInitialization(Module &M) override;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 219bbc9d5cdd4..3544033ead5f5 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -37,6 +37,7 @@
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
@@ -1531,38 +1532,80 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
assert(BBAddrMapVersion >= 2 &&
"PGOAnalysisMap only supports version 2 or later");
+ const BasicBlockSectionsProfileReader *BBSPR = nullptr;
+ if (auto *BBSPRPass =
+ getAnalysisIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>())
+ BBSPR = &BBSPRPass->getBBSPR();
+
+ const CFGProfile *FuncCFGProfile = nullptr;
+ if (BBSPR)
+ FuncCFGProfile = BBSPR->getFunctionCFGProfile(MF.getFunction().getName());
+
if (Features.FuncEntryCount) {
OutStreamer->AddComment("function entry count");
- auto MaybeEntryCount = MF.getFunction().getEntryCount();
- OutStreamer->emitULEB128IntValue(
- MaybeEntryCount ? MaybeEntryCount->getCount() : 0);
+ uint64_t EntryCount = 0;
+ if (FuncCFGProfile) {
+ EntryCount = FuncCFGProfile->getNodeCount(*MF.front().getBBID());
+ } else {
+ auto MaybeEntryCount = MF.getFunction().getEntryCount();
+ EntryCount = MaybeEntryCount ? MaybeEntryCount->getCount() : 0;
+ }
+ OutStreamer->emitULEB128IntValue(EntryCount);
}
- const MachineBlockFrequencyInfo *MBFI =
- Features.BBFreq
- ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
- : nullptr;
- const MachineBranchProbabilityInfo *MBPI =
- Features.BrProb
- ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI()
- : nullptr;
-
- if (Features.BBFreq || Features.BrProb) {
- for (const MachineBasicBlock &MBB : MF) {
- if (Features.BBFreq) {
- OutStreamer->AddComment("basic block frequency");
+
+ if (FuncCFGProfile) {
+ if (Features.BBFreq) {
+ // Basic Block Frequencies from BBSPR NodeCounts.
+ for (const MachineBasicBlock &MBB : MF) {
+ OutStreamer->AddComment("basic block frequency (from BBSPR)");
OutStreamer->emitULEB128IntValue(
- MBFI->getBlockFreq(&MBB).getFrequency());
+ FuncCFGProfile->getNodeCount(*MBB.getBBID()));
}
- if (Features.BrProb) {
- unsigned SuccCount = MBB.succ_size();
+ }
+ if (Features.BrProb) {
+ // Branch Probabilities from BBSPR EdgeCounts.
+ for (const MachineBasicBlock &MBB : MF) {
OutStreamer->AddComment("basic block successor count");
- OutStreamer->emitULEB128IntValue(SuccCount);
+ OutStreamer->emitULEB128IntValue(MBB.succ_size());
for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
OutStreamer->AddComment("successor BB ID");
OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
- OutStreamer->AddComment("successor branch probability");
+ // Emit the numerator of the probability.
+ OutStreamer->AddComment("successor branch probability (from BBSPR)");
OutStreamer->emitULEB128IntValue(
- MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator());
+ FuncCFGProfile->getEdgeCount(*MBB.getBBID(), *SuccMBB->getBBID()));
+ }
+ }
+ }
+ } else {
+ // Fallback to MBFI and MBPI if BBSPR data is not available.
+ const MachineBlockFrequencyInfo *MBFI =
+ Features.BBFreq
+ ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
+ : nullptr;
+ const MachineBranchProbabilityInfo *MBPI =
+ Features.BrProb ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
+ .getMBPI()
+ : nullptr;
+
+ if (Features.BBFreq || Features.BrProb) {
+ for (const MachineBasicBlock &MBB : MF) {
+ if (Features.BBFreq) {
+ OutStreamer->AddComment("basic block frequency");
+ OutStreamer->emitULEB128IntValue(
+ MBFI->getBlockFreq(&MBB).getFrequency());
+ }
+ if (Features.BrProb) {
+ unsigned SuccCount = MBB.succ_size();
+ OutStreamer->AddComment("basic block successor count");
+ OutStreamer->emitULEB128IntValue(SuccCount);
+ for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
+ OutStreamer->AddComment("successor BB ID");
+ OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
+ OutStreamer->AddComment("successor branch probability");
+ OutStreamer->emitULEB128IntValue(
+ MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator());
+ }
}
}
}
diff --git a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
index fbcd614b85d18..71a12e79fdd85 100644
--- a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
@@ -76,21 +76,6 @@ BasicBlockSectionsProfileReader::getClonePathsForFunction(
return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;
}
-uint64_t BasicBlockSectionsProfileReader::getEdgeCount(
- StringRef FuncName, const UniqueBBID &SrcBBID,
- const UniqueBBID &SinkBBID) const {
- auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
- if (It == ProgramPathAndClusterInfo.end())
- return 0;
- auto NodeIt = It->second.EdgeCounts.find(SrcBBID);
- if (NodeIt == It->second.EdgeCounts.end())
- return 0;
- auto EdgeIt = NodeIt->second.find(SinkBBID);
- if (EdgeIt == NodeIt->second.end())
- return 0;
- return EdgeIt->second;
-}
-
// Reads the version 1 basic block sections profile. Profile for each function
// is encoded as follows:
// m <module_name>
@@ -279,10 +264,10 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
Twine("unsigned integer expected: '") + CountStr + "'");
if (i == 0) {
// The first element represents the source and its total count.
- FI->second.NodeCounts[SrcBBID = *BBID] = Count;
+ FI->second.CFG.NodeCounts[SrcBBID = *BBID] = Count;
continue;
}
- FI->second.EdgeCounts[SrcBBID][*BBID] = Count;
+ FI->second.CFG.EdgeCounts[SrcBBID][*BBID] = Count;
}
}
continue;
@@ -487,12 +472,6 @@ BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
return BBSPR.getClonePathsForFunction(FuncName);
}
-uint64_t BasicBlockSectionsProfileReaderWrapperPass::getEdgeCount(
- StringRef FuncName, const UniqueBBID &SrcBBID,
- const UniqueBBID &SinkBBID) const {
- return BBSPR.getEdgeCount(FuncName, SrcBBID, SinkBBID);
-}
-
BasicBlockSectionsProfileReader &
BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
return BBSPR;
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
new file mode 100644
index 0000000000000..e46dba51c716b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
@@ -0,0 +1,64 @@
+; Verify PGO analysis map features with basic block sections profile.
+;
+; RUN: echo 'v1' > %t
+; RUN: echo 'f foo' >> %t
+; RUN: echo 'g 0:1000,1:800,2:200 1:800,3:800 2:200,3:200 3:1000' >> %t
+; RUN: echo 'c 0 1 2' >> %t
+;
+; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -basic-block-address-map -pgo-analysis-map=all | FileCheck %s
+
+define void @foo() nounwind !prof !0 {
+entry:
+ br label %bb1
+
+bb1:
+ br i1 undef, label %bb2, label %bb3, !prof !1
+
+bb2:
+ br label %bb3
+
+bb3:
+ ret void
+}
+
+!0 = !{!"function_entry_count", i64 1500}
+!1 = !{!"branch_weights", i32 1200, i32 300}
+
+; CHECK: .section .text.foo,"ax", at progbits
+; CHECK-LABEL: foo:
+; CHECK: .LBB_END0_0:
+; CHECK-LABEL: .LBB0_1:
+; CHECK: .LBB_END0_1:
+; CHECK-LABEL: .LBB0_2:
+; CHECK: .LBB_END0_2:
+; CHECK-LABEL: foo.cold:
+; CHECK: .LBB_END0_3:
+
+; CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text.foo
+; CHECK-NEXT: .byte 3 # version
+; CHECK-NEXT: .byte 15 # feature
+; CHECK: .quad .Lfunc_begin0 # base address
+; CHECK: .byte 0 # BB id
+; CHECK: .byte 1 # BB id
+; CHECK: .byte 2 # BB id
+; CHECK: .byte 3 # BB id
+
+; PGO Analysis Map
+; CHECK: .ascii "\350\007" # function entry count
+; CHECK-NEXT: .ascii "\350\007" # basic block frequency (from BBSPR)
+; CHECK-NEXT: .ascii "\240\006" # basic block frequency (from BBSPR)
+; CHECK-NEXT: .ascii "\310\001" # basic block frequency (from BBSPR)
+; CHECK-NEXT: .ascii "\350\007" # basic block frequency (from BBSPR)
+; CHECK-NEXT: .byte 1 # basic block successor count
+; CHECK-NEXT: .byte 1 # successor BB ID
+; CHECK-NEXT: .ascii "\240\006" # successor branch probability (from BBSPR)
+; CHECK-NEXT: .byte 2 # basic block successor count
+; CHECK-NEXT: .byte 2 # successor BB ID
+; CHECK-NEXT: .byte 0 # successor branch probability (from BBSPR)
+; CHECK-NEXT: .byte 3 # successor BB ID
+; CHECK-NEXT: .ascii "\240\006" # successor branch probability (from BBSPR)
+; CHECK-NEXT: .byte 1 # basic block successor count
+; CHECK-NEXT: .byte 3 # successor BB ID
+; CHECK-NEXT: .ascii "\310\001" # successor branch probability (from BBSPR)
+; CHECK-NEXT: .byte 0 # basic block successor count
+
>From c22ac4dc0c47c916f3138bdfec2022e6a742644f Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 17:30:07 +0000
Subject: [PATCH 02/11] clang-format.
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3544033ead5f5..f84f15b84f2ba 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1533,8 +1533,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
"PGOAnalysisMap only supports version 2 or later");
const BasicBlockSectionsProfileReader *BBSPR = nullptr;
- if (auto *BBSPRPass =
- getAnalysisIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>())
+ if (auto *BBSPRPass = getAnalysisIfAvailable<
+ BasicBlockSectionsProfileReaderWrapperPass>())
BBSPR = &BBSPRPass->getBBSPR();
const CFGProfile *FuncCFGProfile = nullptr;
@@ -1571,9 +1571,10 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
OutStreamer->AddComment("successor BB ID");
OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
// Emit the numerator of the probability.
- OutStreamer->AddComment("successor branch probability (from BBSPR)");
- OutStreamer->emitULEB128IntValue(
- FuncCFGProfile->getEdgeCount(*MBB.getBBID(), *SuccMBB->getBBID()));
+ OutStreamer->AddComment(
+ "successor branch probability (from BBSPR)");
+ OutStreamer->emitULEB128IntValue(FuncCFGProfile->getEdgeCount(
+ *MBB.getBBID(), *SuccMBB->getBBID()));
}
}
}
@@ -1584,9 +1585,10 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
: nullptr;
const MachineBranchProbabilityInfo *MBPI =
- Features.BrProb ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
- .getMBPI()
- : nullptr;
+ Features.BrProb
+ ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
+ .getMBPI()
+ : nullptr;
if (Features.BBFreq || Features.BrProb) {
for (const MachineBasicBlock &MBB : MF) {
>From d10f3404ebed5887a9f1f80ed861bb0fb31e42bc Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 18:36:27 +0000
Subject: [PATCH 03/11] Refine and extend the test.
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 73 +++++++------------
.../X86/basic-block-sections-pgo-features.ll | 64 +++++++++++-----
2 files changed, 72 insertions(+), 65 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index f84f15b84f2ba..1a770013ec199 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1532,15 +1532,28 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
assert(BBAddrMapVersion >= 2 &&
"PGOAnalysisMap only supports version 2 or later");
+ // We will emit the BBSPR profile data if availale. Otherwise, we fall back
+ // to MBFI and MBPI.
const BasicBlockSectionsProfileReader *BBSPR = nullptr;
if (auto *BBSPRPass = getAnalysisIfAvailable<
BasicBlockSectionsProfileReaderWrapperPass>())
BBSPR = &BBSPRPass->getBBSPR();
+
const CFGProfile *FuncCFGProfile = nullptr;
if (BBSPR)
FuncCFGProfile = BBSPR->getFunctionCFGProfile(MF.getFunction().getName());
+ const MachineBlockFrequencyInfo *MBFI =
+ Features.BBFreq
+ ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
+ : nullptr;
+ const MachineBranchProbabilityInfo *MBPI =
+ Features.BrProb
+ ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
+ .getMBPI()
+ : nullptr;
+
if (Features.FuncEntryCount) {
OutStreamer->AddComment("function entry count");
uint64_t EntryCount = 0;
@@ -1553,65 +1566,31 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
OutStreamer->emitULEB128IntValue(EntryCount);
}
- if (FuncCFGProfile) {
- if (Features.BBFreq) {
- // Basic Block Frequencies from BBSPR NodeCounts.
+ if (Features.BBFreq || Features.BrProb) {
for (const MachineBasicBlock &MBB : MF) {
- OutStreamer->AddComment("basic block frequency (from BBSPR)");
- OutStreamer->emitULEB128IntValue(
- FuncCFGProfile->getNodeCount(*MBB.getBBID()));
+
+ if (Features.BBFreq) {
+ OutStreamer->AddComment("basic block frequency");
+ uint64_t BlockFrequency = FuncCFGProfile ? FuncCFGProfile->getNodeCount(*MBB.getBBID()) : MBFI->getBlockFreq(&MBB).getFrequency();
+ OutStreamer->emitULEB128IntValue(BlockFrequency);
}
- }
if (Features.BrProb) {
- // Branch Probabilities from BBSPR EdgeCounts.
- for (const MachineBasicBlock &MBB : MF) {
OutStreamer->AddComment("basic block successor count");
OutStreamer->emitULEB128IntValue(MBB.succ_size());
for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
OutStreamer->AddComment("successor BB ID");
OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
- // Emit the numerator of the probability.
OutStreamer->AddComment(
- "successor branch probability (from BBSPR)");
- OutStreamer->emitULEB128IntValue(FuncCFGProfile->getEdgeCount(
- *MBB.getBBID(), *SuccMBB->getBBID()));
+ "successor branch probability");
+ // For MPBI, we emit the numerator of the probability. For BBSPR, we
+ // emit the raw edge count.
+ uint64_t EdgeFrequency = FuncCFGProfile ? FuncCFGProfile->getEdgeCount(
+ *MBB.getBBID(), *SuccMBB->getBBID()) : MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator();
+ OutStreamer->emitULEB128IntValue(EdgeFrequency);
}
- }
}
- } else {
- // Fallback to MBFI and MBPI if BBSPR data is not available.
- const MachineBlockFrequencyInfo *MBFI =
- Features.BBFreq
- ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
- : nullptr;
- const MachineBranchProbabilityInfo *MBPI =
- Features.BrProb
- ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
- .getMBPI()
- : nullptr;
-
- if (Features.BBFreq || Features.BrProb) {
- for (const MachineBasicBlock &MBB : MF) {
- if (Features.BBFreq) {
- OutStreamer->AddComment("basic block frequency");
- OutStreamer->emitULEB128IntValue(
- MBFI->getBlockFreq(&MBB).getFrequency());
- }
- if (Features.BrProb) {
- unsigned SuccCount = MBB.succ_size();
- OutStreamer->AddComment("basic block successor count");
- OutStreamer->emitULEB128IntValue(SuccCount);
- for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
- OutStreamer->AddComment("successor BB ID");
- OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
- OutStreamer->AddComment("successor branch probability");
- OutStreamer->emitULEB128IntValue(
- MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator());
- }
- }
- }
}
- }
+ }
}
OutStreamer->popSection();
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
index e46dba51c716b..ff97066659f4d 100644
--- a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
+++ b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
@@ -24,15 +24,7 @@ bb3:
!0 = !{!"function_entry_count", i64 1500}
!1 = !{!"branch_weights", i32 1200, i32 300}
-; CHECK: .section .text.foo,"ax", at progbits
-; CHECK-LABEL: foo:
-; CHECK: .LBB_END0_0:
-; CHECK-LABEL: .LBB0_1:
-; CHECK: .LBB_END0_1:
-; CHECK-LABEL: .LBB0_2:
-; CHECK: .LBB_END0_2:
-; CHECK-LABEL: foo.cold:
-; CHECK: .LBB_END0_3:
+;; Verify that foo gets its PGO map from its Propeller CFG profile.
; CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text.foo
; CHECK-NEXT: .byte 3 # version
@@ -43,22 +35,58 @@ bb3:
; CHECK: .byte 2 # BB id
; CHECK: .byte 3 # BB id
-; PGO Analysis Map
+; PGO Analysis Map for foo
; CHECK: .ascii "\350\007" # function entry count
-; CHECK-NEXT: .ascii "\350\007" # basic block frequency (from BBSPR)
-; CHECK-NEXT: .ascii "\240\006" # basic block frequency (from BBSPR)
-; CHECK-NEXT: .ascii "\310\001" # basic block frequency (from BBSPR)
-; CHECK-NEXT: .ascii "\350\007" # basic block frequency (from BBSPR)
+; CHECK-NEXT: .ascii "\350\007" # basic block frequency
; CHECK-NEXT: .byte 1 # basic block successor count
; CHECK-NEXT: .byte 1 # successor BB ID
-; CHECK-NEXT: .ascii "\240\006" # successor branch probability (from BBSPR)
+; CHECK-NEXT: .ascii "\240\006" # successor branch probability
+; CHECK-NEXT: .ascii "\240\006" # basic block frequency
; CHECK-NEXT: .byte 2 # basic block successor count
; CHECK-NEXT: .byte 2 # successor BB ID
-; CHECK-NEXT: .byte 0 # successor branch probability (from BBSPR)
+; CHECK-NEXT: .byte 0 # successor branch probability
; CHECK-NEXT: .byte 3 # successor BB ID
-; CHECK-NEXT: .ascii "\240\006" # successor branch probability (from BBSPR)
+; CHECK-NEXT: .ascii "\240\006" # successor branch probability
+; CHECK-NEXT: .ascii "\310\001" # basic block frequency
; CHECK-NEXT: .byte 1 # basic block successor count
; CHECK-NEXT: .byte 3 # successor BB ID
-; CHECK-NEXT: .ascii "\310\001" # successor branch probability (from BBSPR)
+; CHECK-NEXT: .ascii "\310\001" # successor branch probability
+; CHECK-NEXT: .ascii "\350\007" # basic block frequency
; CHECK-NEXT: .byte 0 # basic block successor count
+define void @bar() nounwind !prof !2 {
+entry:
+ br i1 undef, label %bb1, label %bb2, !prof !3
+
+bb1:
+ ret void
+
+bb2:
+ ret void
+}
+
+!2 = !{!"function_entry_count", i64 80}
+!3 = !{!"branch_weights", i32 2, i32 78}
+
+;; Verify that we emit the PGO map for bar although it doesn't have Propeller profile.
+
+; CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text.bar
+; CHECK-NEXT: .byte 3 # version
+; CHECK-NEXT: .byte 7 # feature
+; CHECK: .quad .Lfunc_begin1 # function address
+; CHECK: .byte 0 # BB id
+; CHECK: .byte 1 # BB id
+; CHECK: .byte 2 # BB id
+
+; CHECK: .byte 80 # function entry count
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200 " # basic block frequency
+; CHECK-NEXT: .byte 2 # basic block successor count
+; CHECK-NEXT: .byte 1 # successor BB ID
+; CHECK-NEXT: .ascii "\200\200\200\200\004" # successor branch probability
+; CHECK-NEXT: .byte 2 # successor BB ID
+; CHECK-NEXT: .ascii "\200\200\200\200\004" # successor branch probability
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200\020" # basic block frequency
+; CHECK-NEXT: .byte 0 # basic block successor count
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200\020" # basic block frequency
+; CHECK-NEXT: .byte 0 # basic block successor count
+
>From 16814a40874fc25563307ec1ae9a5bfcbd043fd7 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 18:36:43 +0000
Subject: [PATCH 04/11] clang-format.
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 42 +++++++++++-----------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 1a770013ec199..9adc65ee0c1b1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1539,20 +1539,18 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
BasicBlockSectionsProfileReaderWrapperPass>())
BBSPR = &BBSPRPass->getBBSPR();
-
const CFGProfile *FuncCFGProfile = nullptr;
if (BBSPR)
FuncCFGProfile = BBSPR->getFunctionCFGProfile(MF.getFunction().getName());
const MachineBlockFrequencyInfo *MBFI =
- Features.BBFreq
- ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
- : nullptr;
- const MachineBranchProbabilityInfo *MBPI =
- Features.BrProb
- ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
- .getMBPI()
- : nullptr;
+ Features.BBFreq
+ ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
+ : nullptr;
+ const MachineBranchProbabilityInfo *MBPI =
+ Features.BrProb
+ ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI()
+ : nullptr;
if (Features.FuncEntryCount) {
OutStreamer->AddComment("function entry count");
@@ -1566,31 +1564,35 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
OutStreamer->emitULEB128IntValue(EntryCount);
}
- if (Features.BBFreq || Features.BrProb) {
- for (const MachineBasicBlock &MBB : MF) {
+ if (Features.BBFreq || Features.BrProb) {
+ for (const MachineBasicBlock &MBB : MF) {
- if (Features.BBFreq) {
+ if (Features.BBFreq) {
OutStreamer->AddComment("basic block frequency");
- uint64_t BlockFrequency = FuncCFGProfile ? FuncCFGProfile->getNodeCount(*MBB.getBBID()) : MBFI->getBlockFreq(&MBB).getFrequency();
+ uint64_t BlockFrequency =
+ FuncCFGProfile ? FuncCFGProfile->getNodeCount(*MBB.getBBID())
+ : MBFI->getBlockFreq(&MBB).getFrequency();
OutStreamer->emitULEB128IntValue(BlockFrequency);
}
- if (Features.BrProb) {
+ if (Features.BrProb) {
OutStreamer->AddComment("basic block successor count");
OutStreamer->emitULEB128IntValue(MBB.succ_size());
for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
OutStreamer->AddComment("successor BB ID");
OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
- OutStreamer->AddComment(
- "successor branch probability");
+ OutStreamer->AddComment("successor branch probability");
// For MPBI, we emit the numerator of the probability. For BBSPR, we
// emit the raw edge count.
- uint64_t EdgeFrequency = FuncCFGProfile ? FuncCFGProfile->getEdgeCount(
- *MBB.getBBID(), *SuccMBB->getBBID()) : MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator();
+ uint64_t EdgeFrequency =
+ FuncCFGProfile
+ ? FuncCFGProfile->getEdgeCount(*MBB.getBBID(),
+ *SuccMBB->getBBID())
+ : MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator();
OutStreamer->emitULEB128IntValue(EdgeFrequency);
}
- }
- }
}
+ }
+ }
}
OutStreamer->popSection();
>From b02b87aea00564c7e32f4115004c62cd56addea9 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 19:38:48 +0000
Subject: [PATCH 05/11] Fix a test comment.
---
llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
index ff97066659f4d..f535b9f6bd9d2 100644
--- a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
+++ b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
@@ -68,7 +68,7 @@ bb2:
!2 = !{!"function_entry_count", i64 80}
!3 = !{!"branch_weights", i32 2, i32 78}
-;; Verify that we emit the PGO map for bar although it doesn't have Propeller profile.
+;; Verify that we emit the PGO map for bar which doesn't have Propeller profile.
; CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text.bar
; CHECK-NEXT: .byte 3 # version
>From 3362e028bac8aac63c3e0bab3de6f04d996c91f1 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 22:36:44 +0000
Subject: [PATCH 06/11] Add flag to enable using the Propeller profile in PGO
analysis map.
---
.../CodeGen/BasicBlockSectionsProfileReader.h | 12 ++++++-----
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 20 ++++++++++---------
.../BasicBlockSectionsProfileReader.cpp | 5 +++++
.../X86/basic-block-sections-pgo-features.ll | 2 +-
4 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
index 3c0e26bad7a5b..4967365f1bfe5 100644
--- a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
+++ b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
@@ -43,7 +43,7 @@ struct BBClusterInfo {
};
// This represents the CFG profile data for a function.
-struct CFGProfile {
+struct CfgProfile {
// Node counts for each basic block.
DenseMap<UniqueBBID, uint64_t> NodeCounts;
// Edge counts for each edge, stored as a nested map.
@@ -74,8 +74,8 @@ struct FunctionProfile {
// the edge a -> b (a is not cloned). The index of the path in this vector
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
- // CFG profile data.
- CFGProfile CFG;
+ // Cfg profile data (block and edge frequencies).
+ CfgProfile CFG;
};
class BasicBlockSectionsProfileReader {
@@ -103,9 +103,9 @@ class BasicBlockSectionsProfileReader {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;
- // Returns a pointer to the CFGProfile for the given function.
+ // Returns a pointer to the CfgProfile for the given function.
// Returns nullptr if no profile data is available for the function.
- const CFGProfile *getFunctionCFGProfile(StringRef FuncName) const {
+ const CfgProfile *getFunctionCfgProfile(StringRef FuncName) const {
auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
if (It == ProgramPathAndClusterInfo.end())
return nullptr;
@@ -218,6 +218,8 @@ class BasicBlockSectionsProfileReaderWrapperPass : public ImmutablePass {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;
+ const CfgProfile *getFunctionCfgProfile(StringRef FuncName) const;
+
// Initializes the FunctionNameToDIFilename map for the current module and
// then reads the profile for the matching functions.
bool doInitialization(Module &M) override;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 9adc65ee0c1b1..06f57019da40a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -165,6 +165,10 @@ static cl::bits<PGOMapFeaturesEnum> PgoAnalysisMapFeatures(
"Enable extended information within the SHT_LLVM_BB_ADDR_MAP that is "
"extracted from PGO related analysis."));
+static cl::opt<bool> PgoAnalysisMapUsePropellerCfg("pgo-analysis-map-use-propeller-cfg",
+cl::desc("If available, use the Propeller cfg profile in the PGO analysis map."),
+cl::Hidden, cl::init(false));
+
static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
"basic-block-address-map-skip-bb-entries",
cl::desc("Skip emitting basic block entries in the SHT_LLVM_BB_ADDR_MAP "
@@ -474,6 +478,7 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<GCModuleInfo>();
AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
+ AU.addUsedIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>();
}
bool AsmPrinter::doInitialization(Module &M) {
@@ -1532,16 +1537,13 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
assert(BBAddrMapVersion >= 2 &&
"PGOAnalysisMap only supports version 2 or later");
- // We will emit the BBSPR profile data if availale. Otherwise, we fall back
+ // We will emit the BBSPR profile data if requested and availale. Otherwise, we fall back
// to MBFI and MBPI.
- const BasicBlockSectionsProfileReader *BBSPR = nullptr;
- if (auto *BBSPRPass = getAnalysisIfAvailable<
- BasicBlockSectionsProfileReaderWrapperPass>())
- BBSPR = &BBSPRPass->getBBSPR();
-
- const CFGProfile *FuncCFGProfile = nullptr;
- if (BBSPR)
- FuncCFGProfile = BBSPR->getFunctionCFGProfile(MF.getFunction().getName());
+ const CfgProfile *FuncCFGProfile = nullptr;
+ if (PgoAnalysisMapUsePropellerCfg) {
+ if (auto *BBSPR = getAnalysisIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>())
+ FuncCFGProfile = BBSPR->getFunctionCfgProfile(MF.getFunction().getName());
+ }
const MachineBlockFrequencyInfo *MBFI =
Features.BBFreq
diff --git a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
index 71a12e79fdd85..49de0a351b5f5 100644
--- a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
@@ -472,6 +472,11 @@ BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
return BBSPR.getClonePathsForFunction(FuncName);
}
+
+const CfgProfile *BasicBlockSectionsProfileReaderWrapperPass::getFunctionCfgProfile(StringRef FuncName) const {
+ return BBSPR.getFunctionCfgProfile(FuncName);
+}
+
BasicBlockSectionsProfileReader &
BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
return BBSPR;
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
index f535b9f6bd9d2..ee3a24177a466 100644
--- a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
+++ b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
@@ -5,7 +5,7 @@
; RUN: echo 'g 0:1000,1:800,2:200 1:800,3:800 2:200,3:200 3:1000' >> %t
; RUN: echo 'c 0 1 2' >> %t
;
-; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -basic-block-address-map -pgo-analysis-map=all | FileCheck %s
+; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -basic-block-address-map -pgo-analysis-map=all -pgo-analysis-map-use-propeller-cfg | FileCheck %s
define void @foo() nounwind !prof !0 {
entry:
>From d1fc65ba2b54c0f6418412ae1420b73fea85811b Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 22:36:56 +0000
Subject: [PATCH 07/11] clang-format.
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 18 +++++++++++-------
.../BasicBlockSectionsProfileReader.cpp | 5 +++--
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 06f57019da40a..b54a89468afb6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -165,9 +165,11 @@ static cl::bits<PGOMapFeaturesEnum> PgoAnalysisMapFeatures(
"Enable extended information within the SHT_LLVM_BB_ADDR_MAP that is "
"extracted from PGO related analysis."));
-static cl::opt<bool> PgoAnalysisMapUsePropellerCfg("pgo-analysis-map-use-propeller-cfg",
-cl::desc("If available, use the Propeller cfg profile in the PGO analysis map."),
-cl::Hidden, cl::init(false));
+static cl::opt<bool> PgoAnalysisMapUsePropellerCfg(
+ "pgo-analysis-map-use-propeller-cfg",
+ cl::desc(
+ "If available, use the Propeller cfg profile in the PGO analysis map."),
+ cl::Hidden, cl::init(false));
static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
"basic-block-address-map-skip-bb-entries",
@@ -1537,12 +1539,14 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
assert(BBAddrMapVersion >= 2 &&
"PGOAnalysisMap only supports version 2 or later");
- // We will emit the BBSPR profile data if requested and availale. Otherwise, we fall back
- // to MBFI and MBPI.
+ // We will emit the BBSPR profile data if requested and availale. Otherwise,
+ // we fall back to MBFI and MBPI.
const CfgProfile *FuncCFGProfile = nullptr;
if (PgoAnalysisMapUsePropellerCfg) {
- if (auto *BBSPR = getAnalysisIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>())
- FuncCFGProfile = BBSPR->getFunctionCfgProfile(MF.getFunction().getName());
+ if (auto *BBSPR = getAnalysisIfAvailable<
+ BasicBlockSectionsProfileReaderWrapperPass>())
+ FuncCFGProfile =
+ BBSPR->getFunctionCfgProfile(MF.getFunction().getName());
}
const MachineBlockFrequencyInfo *MBFI =
diff --git a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
index 49de0a351b5f5..0fb8f3a1503cd 100644
--- a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
@@ -472,8 +472,9 @@ BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
return BBSPR.getClonePathsForFunction(FuncName);
}
-
-const CfgProfile *BasicBlockSectionsProfileReaderWrapperPass::getFunctionCfgProfile(StringRef FuncName) const {
+const CfgProfile *
+BasicBlockSectionsProfileReaderWrapperPass::getFunctionCfgProfile(
+ StringRef FuncName) const {
return BBSPR.getFunctionCfgProfile(FuncName);
}
>From 497d39e30d3efffd05e631cb5a8ab7717af8ef7e Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 13 Oct 2025 22:52:16 +0000
Subject: [PATCH 08/11] Fix the undefs in test.
---
.../test/CodeGen/X86/basic-block-sections-pgo-features.ll | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
index ee3a24177a466..21ff75a5cd354 100644
--- a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
+++ b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
@@ -7,12 +7,12 @@
;
; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -basic-block-address-map -pgo-analysis-map=all -pgo-analysis-map-use-propeller-cfg | FileCheck %s
-define void @foo() nounwind !prof !0 {
+define void @foo(i1 %cond) nounwind !prof !0 {
entry:
br label %bb1
bb1:
- br i1 undef, label %bb2, label %bb3, !prof !1
+ br i1 %cond, label %bb2, label %bb3, !prof !1
bb2:
br label %bb3
@@ -54,9 +54,9 @@ bb3:
; CHECK-NEXT: .ascii "\350\007" # basic block frequency
; CHECK-NEXT: .byte 0 # basic block successor count
-define void @bar() nounwind !prof !2 {
+define void @bar(i1 %cond) nounwind !prof !2 {
entry:
- br i1 undef, label %bb1, label %bb2, !prof !3
+ br i1 %cond, label %bb1, label %bb2, !prof !3
bb1:
ret void
>From 3ed21186ed6b64f9f88b9790b5ed097de020a124 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Tue, 14 Oct 2025 22:00:16 +0000
Subject: [PATCH 09/11] Change CFG to lower-case Cfg.
---
.../llvm/CodeGen/BasicBlockSectionsProfileReader.h | 6 +++---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 14 +++++++-------
.../CodeGen/BasicBlockSectionsProfileReader.cpp | 10 +++++-----
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
index 4967365f1bfe5..42771fbe18d60 100644
--- a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
+++ b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
@@ -42,7 +42,7 @@ struct BBClusterInfo {
unsigned PositionInCluster;
};
-// This represents the CFG profile data for a function.
+// This represents the cfg profile data for a function.
struct CfgProfile {
// Node counts for each basic block.
DenseMap<UniqueBBID, uint64_t> NodeCounts;
@@ -75,7 +75,7 @@ struct FunctionProfile {
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
// Cfg profile data (block and edge frequencies).
- CfgProfile CFG;
+ CfgProfile Cfg;
};
class BasicBlockSectionsProfileReader {
@@ -109,7 +109,7 @@ class BasicBlockSectionsProfileReader {
auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
if (It == ProgramPathAndClusterInfo.end())
return nullptr;
- return &It->second.CFG;
+ return &It->second.Cfg;
}
private:
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d48af1136e4db..0d748217a1ed9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1542,11 +1542,11 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
// We will emit the BBSPR profile data if requested and availale. Otherwise,
// we fall back to MBFI and MBPI.
- const CfgProfile *FuncCFGProfile = nullptr;
+ const CfgProfile *FuncCfgProfile = nullptr;
if (PgoAnalysisMapUsePropellerCfg) {
if (auto *BBSPR = getAnalysisIfAvailable<
BasicBlockSectionsProfileReaderWrapperPass>())
- FuncCFGProfile =
+ FuncCfgProfile =
BBSPR->getFunctionCfgProfile(MF.getFunction().getName());
}
@@ -1562,8 +1562,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
if (Features.FuncEntryCount) {
OutStreamer->AddComment("function entry count");
uint64_t EntryCount = 0;
- if (FuncCFGProfile) {
- EntryCount = FuncCFGProfile->getNodeCount(*MF.front().getBBID());
+ if (FuncCfgProfile) {
+ EntryCount = FuncCfgProfile->getNodeCount(*MF.front().getBBID());
} else {
auto MaybeEntryCount = MF.getFunction().getEntryCount();
EntryCount = MaybeEntryCount ? MaybeEntryCount->getCount() : 0;
@@ -1577,7 +1577,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
if (Features.BBFreq) {
OutStreamer->AddComment("basic block frequency");
uint64_t BlockFrequency =
- FuncCFGProfile ? FuncCFGProfile->getNodeCount(*MBB.getBBID())
+ FuncCfgProfile ? FuncCfgProfile->getNodeCount(*MBB.getBBID())
: MBFI->getBlockFreq(&MBB).getFrequency();
OutStreamer->emitULEB128IntValue(BlockFrequency);
}
@@ -1591,8 +1591,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
// For MPBI, we emit the numerator of the probability. For BBSPR, we
// emit the raw edge count.
uint64_t EdgeFrequency =
- FuncCFGProfile
- ? FuncCFGProfile->getEdgeCount(*MBB.getBBID(),
+ FuncCfgProfile
+ ? FuncCfgProfile->getEdgeCount(*MBB.getBBID(),
*SuccMBB->getBBID())
: MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator();
OutStreamer->emitULEB128IntValue(EdgeFrequency);
diff --git a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
index 0fb8f3a1503cd..adab0e8956268 100644
--- a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
@@ -100,7 +100,7 @@ BasicBlockSectionsProfileReader::getClonePathsForFunction(
// the edge 1->3. Within the given clusters, each cloned block is identified by
// "<original block id>.<clone id>". For instance, 3.1 represents the first
// clone of block 3. Original blocks are specified just with their block ids. A
-// block cloned multiple times appears with distinct clone ids. The CFG for bar
+// block cloned multiple times appears with distinct clone ids. The Cfg for bar
// is shown below before and after cloning with its final clusters labeled.
//
// f main
@@ -240,12 +240,12 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
}
continue;
}
- case 'g': { // CFG profile specifier.
+ case 'g': { // Cfg profile specifier.
// Skip the profile when we the profile iterator (FI) refers to the
// past-the-end element.
if (FI == ProgramPathAndClusterInfo.end())
continue;
- // For each node, its CFG profile is encoded as
+ // For each node, its Cfg profile is encoded as
// <src>:<count>,<sink_1>:<count_1>,<sink_2>:<count_2>,...
for (auto BasicBlockEdgeProfile : Values) {
if (BasicBlockEdgeProfile.empty())
@@ -264,10 +264,10 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
Twine("unsigned integer expected: '") + CountStr + "'");
if (i == 0) {
// The first element represents the source and its total count.
- FI->second.CFG.NodeCounts[SrcBBID = *BBID] = Count;
+ FI->second.Cfg.NodeCounts[SrcBBID = *BBID] = Count;
continue;
}
- FI->second.CFG.EdgeCounts[SrcBBID][*BBID] = Count;
+ FI->second.Cfg.EdgeCounts[SrcBBID][*BBID] = Count;
}
}
continue;
>From 7e89984eb0b30c38fea2aba5981750a02a4d694a Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Tue, 21 Oct 2025 05:19:29 +0000
Subject: [PATCH 10/11] Emit the Propeller CFG frequencies.
---
.../CodeGen/BasicBlockSectionsProfileReader.h | 18 ++--
llvm/include/llvm/Object/ELFTypes.h | 16 ++--
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 95 +++++++++----------
.../BasicBlockSectionsProfileReader.cpp | 16 +---
.../X86/basic-block-sections-pgo-features.ll | 52 +++++-----
5 files changed, 99 insertions(+), 98 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
index 42771fbe18d60..db21455f160b2 100644
--- a/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
+++ b/llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
@@ -42,8 +42,8 @@ struct BBClusterInfo {
unsigned PositionInCluster;
};
-// This represents the cfg profile data for a function.
-struct CfgProfile {
+// This represents the CFG profile data for a function.
+struct CFGProfile {
// Node counts for each basic block.
DenseMap<UniqueBBID, uint64_t> NodeCounts;
// Edge counts for each edge, stored as a nested map.
@@ -51,7 +51,7 @@ struct CfgProfile {
// Returns the profile count for the given basic block or zero if it does not
// exist.
- uint64_t getNodeCount(const UniqueBBID &BBID) const {
+ uint64_t getBlockCount(const UniqueBBID &BBID) const {
return NodeCounts.lookup(BBID);
}
@@ -74,8 +74,8 @@ struct FunctionProfile {
// the edge a -> b (a is not cloned). The index of the path in this vector
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
- // Cfg profile data (block and edge frequencies).
- CfgProfile Cfg;
+ // CFG profile data.
+ CFGProfile CFG;
};
class BasicBlockSectionsProfileReader {
@@ -103,13 +103,13 @@ class BasicBlockSectionsProfileReader {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;
- // Returns a pointer to the CfgProfile for the given function.
+ // Returns a pointer to the CFGProfile for the given function.
// Returns nullptr if no profile data is available for the function.
- const CfgProfile *getFunctionCfgProfile(StringRef FuncName) const {
+ const CFGProfile *getFunctionCFGProfile(StringRef FuncName) const {
auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
if (It == ProgramPathAndClusterInfo.end())
return nullptr;
- return &It->second.Cfg;
+ return &It->second.CFG;
}
private:
@@ -218,8 +218,6 @@ class BasicBlockSectionsProfileReaderWrapperPass : public ImmutablePass {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;
- const CfgProfile *getFunctionCfgProfile(StringRef FuncName) const;
-
// Initializes the FunctionNameToDIFilename map for the current module and
// then reads the profile for the matching functions.
bool doInitialization(Module &M) override;
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index e9a417d3d4fb3..e6d4552168607 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -834,10 +834,13 @@ struct BBAddrMap {
bool OmitBBEntries : 1;
bool CallsiteEndOffsets : 1;
bool BBHash : 1;
+ bool PropellerCFG : 1;
- bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; }
+ bool hasPGOAnalysis() const {
+ return FuncEntryCount || BBFreq || BrProb || PropellerCFG;
+ }
- bool hasPGOAnalysisBBData() const { return BBFreq || BrProb; }
+ bool hasPGOAnalysisBBData() const { return BBFreq || BrProb || PropellerCFG; }
// Encodes to minimum bit width representation.
uint8_t encode() const {
@@ -847,7 +850,8 @@ struct BBAddrMap {
(static_cast<uint8_t>(MultiBBRange) << 3) |
(static_cast<uint8_t>(OmitBBEntries) << 4) |
(static_cast<uint8_t>(CallsiteEndOffsets) << 5) |
- (static_cast<uint8_t>(BBHash) << 6);
+ (static_cast<uint8_t>(BBHash) << 6) |
+ (static_cast<uint8_t>(PropellerCFG) << 7);
}
// Decodes from minimum bit width representation and validates no
@@ -857,7 +861,7 @@ struct BBAddrMap {
static_cast<bool>(Val & (1 << 0)), static_cast<bool>(Val & (1 << 1)),
static_cast<bool>(Val & (1 << 2)), static_cast<bool>(Val & (1 << 3)),
static_cast<bool>(Val & (1 << 4)), static_cast<bool>(Val & (1 << 5)),
- static_cast<bool>(Val & (1 << 6))};
+ static_cast<bool>(Val & (1 << 6)), static_cast<bool>(Val & (1 << 7))};
if (Feat.encode() != Val)
return createStringError(
std::error_code(), "invalid encoding for BBAddrMap::Features: 0x%x",
@@ -867,10 +871,10 @@ struct BBAddrMap {
bool operator==(const Features &Other) const {
return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange,
- OmitBBEntries, CallsiteEndOffsets, BBHash) ==
+ OmitBBEntries, CallsiteEndOffsets, BBHash, PropellerCFG) ==
std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb,
Other.MultiBBRange, Other.OmitBBEntries,
- Other.CallsiteEndOffsets, Other.BBHash);
+ Other.CallsiteEndOffsets, Other.BBHash, Other.PropellerCFG);
}
};
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0d748217a1ed9..9ffaa53f8755f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -20,7 +20,6 @@
#include "WinException.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -120,6 +119,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VCSRevision.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
@@ -149,6 +149,7 @@ enum class PGOMapFeaturesEnum {
FuncEntryCount,
BBFreq,
BrProb,
+ PropellerCFG,
All,
};
static cl::bits<PGOMapFeaturesEnum> PgoAnalysisMapFeatures(
@@ -160,17 +161,13 @@ static cl::bits<PGOMapFeaturesEnum> PgoAnalysisMapFeatures(
clEnumValN(PGOMapFeaturesEnum::BBFreq, "bb-freq",
"Basic Block Frequency"),
clEnumValN(PGOMapFeaturesEnum::BrProb, "br-prob", "Branch Probability"),
+ clEnumValN(PGOMapFeaturesEnum::PropellerCFG, "propeller-cfg",
+ "Propeller CFG"),
clEnumValN(PGOMapFeaturesEnum::All, "all", "Enable all options")),
cl::desc(
"Enable extended information within the SHT_LLVM_BB_ADDR_MAP that is "
"extracted from PGO related analysis."));
-static cl::opt<bool> PgoAnalysisMapUsePropellerCfg(
- "pgo-analysis-map-use-propeller-cfg",
- cl::desc(
- "If available, use the Propeller cfg profile in the PGO analysis map."),
- cl::Hidden, cl::init(false));
-
static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
"basic-block-address-map-skip-bb-entries",
cl::desc("Skip emitting basic block entries in the SHT_LLVM_BB_ADDR_MAP "
@@ -480,7 +477,6 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<GCModuleInfo>();
AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
- AU.addUsedIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>();
}
bool AsmPrinter::doInitialization(Module &M) {
@@ -1412,7 +1408,7 @@ static uint32_t getBBAddrMapMetadata(const MachineBasicBlock &MBB) {
static llvm::object::BBAddrMap::Features
getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges,
- bool HasCalls) {
+ bool HasCalls, const CFGProfile *FuncCFGProfile) {
// Ensure that the user has not passed in additional options while also
// specifying all or none.
if ((PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::None) ||
@@ -1434,19 +1430,25 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges,
bool BrProbEnabled =
AllFeatures ||
(!NoFeatures && PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::BrProb));
+ bool PropellerCFGEnabled =
+ FuncCFGProfile &&
+ (AllFeatures ||
+ (!NoFeatures &&
+ PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::PropellerCFG)));
if ((BBFreqEnabled || BrProbEnabled) && BBAddrMapSkipEmitBBEntries) {
MF.getFunction().getContext().emitError(
- "BB entries info is required for BBFreq and BrProb "
- "features");
+ "BB entries info is required for BBFreq and BrProb features");
}
+
return {FuncEntryCountEnabled,
BBFreqEnabled,
BrProbEnabled,
MF.hasBBSections() && NumMBBSectionRanges > 1,
static_cast<bool>(BBAddrMapSkipEmitBBEntries),
HasCalls,
- false};
+ false,
+ PropellerCFGEnabled};
}
void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
@@ -1455,6 +1457,14 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
assert(BBAddrMapSection && ".llvm_bb_addr_map section is not initialized.");
bool HasCalls = !CurrentFnCallsiteEndSymbols.empty();
+ const BasicBlockSectionsProfileReader *BBSPR = nullptr;
+ if (auto *BBSPRPass =
+ getAnalysisIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>())
+ BBSPR = &BBSPRPass->getBBSPR();
+ const CFGProfile *FuncCFGProfile = nullptr;
+ if (BBSPR)
+ FuncCFGProfile = BBSPR->getFunctionCFGProfile(MF.getFunction().getName());
+
const MCSymbol *FunctionSymbol = getFunctionBegin();
OutStreamer->pushSection();
@@ -1463,7 +1473,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
uint8_t BBAddrMapVersion = OutStreamer->getContext().getBBAddrMapVersion();
OutStreamer->emitInt8(BBAddrMapVersion);
OutStreamer->AddComment("feature");
- auto Features = getBBAddrMapFeature(MF, MBBSectionRanges.size(), HasCalls);
+ auto Features =
+ getBBAddrMapFeature(MF, MBBSectionRanges.size(), HasCalls, FuncCFGProfile);
OutStreamer->emitInt8(Features.encode());
// Emit BB Information for each basic block in the function.
if (Features.MultiBBRange) {
@@ -1540,16 +1551,12 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
assert(BBAddrMapVersion >= 2 &&
"PGOAnalysisMap only supports version 2 or later");
- // We will emit the BBSPR profile data if requested and availale. Otherwise,
- // we fall back to MBFI and MBPI.
- const CfgProfile *FuncCfgProfile = nullptr;
- if (PgoAnalysisMapUsePropellerCfg) {
- if (auto *BBSPR = getAnalysisIfAvailable<
- BasicBlockSectionsProfileReaderWrapperPass>())
- FuncCfgProfile =
- BBSPR->getFunctionCfgProfile(MF.getFunction().getName());
+ if (Features.FuncEntryCount) {
+ OutStreamer->AddComment("function entry count");
+ auto MaybeEntryCount = MF.getFunction().getEntryCount();
+ OutStreamer->emitULEB128IntValue(
+ MaybeEntryCount ? MaybeEntryCount->getCount() : 0);
}
-
const MachineBlockFrequencyInfo *MBFI =
Features.BBFreq
? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
@@ -1559,43 +1566,33 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI()
: nullptr;
- if (Features.FuncEntryCount) {
- OutStreamer->AddComment("function entry count");
- uint64_t EntryCount = 0;
- if (FuncCfgProfile) {
- EntryCount = FuncCfgProfile->getNodeCount(*MF.front().getBBID());
- } else {
- auto MaybeEntryCount = MF.getFunction().getEntryCount();
- EntryCount = MaybeEntryCount ? MaybeEntryCount->getCount() : 0;
- }
- OutStreamer->emitULEB128IntValue(EntryCount);
- }
-
if (Features.BBFreq || Features.BrProb) {
for (const MachineBasicBlock &MBB : MF) {
-
if (Features.BBFreq) {
OutStreamer->AddComment("basic block frequency");
- uint64_t BlockFrequency =
- FuncCfgProfile ? FuncCfgProfile->getNodeCount(*MBB.getBBID())
- : MBFI->getBlockFreq(&MBB).getFrequency();
- OutStreamer->emitULEB128IntValue(BlockFrequency);
+ OutStreamer->emitULEB128IntValue(
+ MBFI->getBlockFreq(&MBB).getFrequency());
+ if (Features.PropellerCFG) {
+ OutStreamer->AddComment("basic block frequency (propeller)");
+ OutStreamer->emitULEB128IntValue(
+ FuncCFGProfile->getBlockCount(*MBB.getBBID()));
+ }
}
if (Features.BrProb) {
+ unsigned SuccCount = MBB.succ_size();
OutStreamer->AddComment("basic block successor count");
- OutStreamer->emitULEB128IntValue(MBB.succ_size());
+ OutStreamer->emitULEB128IntValue(SuccCount);
for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
OutStreamer->AddComment("successor BB ID");
OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
OutStreamer->AddComment("successor branch probability");
- // For MPBI, we emit the numerator of the probability. For BBSPR, we
- // emit the raw edge count.
- uint64_t EdgeFrequency =
- FuncCfgProfile
- ? FuncCfgProfile->getEdgeCount(*MBB.getBBID(),
- *SuccMBB->getBBID())
- : MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator();
- OutStreamer->emitULEB128IntValue(EdgeFrequency);
+ OutStreamer->emitULEB128IntValue(
+ MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator());
+ if (Features.PropellerCFG) {
+ OutStreamer->AddComment("successor branch frequency (propeller)");
+ OutStreamer->emitULEB128IntValue(FuncCFGProfile->getEdgeCount(
+ *MBB.getBBID(), *SuccMBB->getBBID()));
+ }
}
}
}
@@ -1715,7 +1712,7 @@ static ConstantInt *extractNumericCGTypeId(const Function &F) {
return nullptr;
}
-/// Emits .callgraph section.
+/// Emits .llvm.callgraph section.
void AsmPrinter::emitCallGraphSection(const MachineFunction &MF,
FunctionCallGraphInfo &FuncCGInfo) {
if (!MF.getTarget().Options.EmitCallGraphSection)
diff --git a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
index adab0e8956268..71a12e79fdd85 100644
--- a/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
@@ -100,7 +100,7 @@ BasicBlockSectionsProfileReader::getClonePathsForFunction(
// the edge 1->3. Within the given clusters, each cloned block is identified by
// "<original block id>.<clone id>". For instance, 3.1 represents the first
// clone of block 3. Original blocks are specified just with their block ids. A
-// block cloned multiple times appears with distinct clone ids. The Cfg for bar
+// block cloned multiple times appears with distinct clone ids. The CFG for bar
// is shown below before and after cloning with its final clusters labeled.
//
// f main
@@ -240,12 +240,12 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
}
continue;
}
- case 'g': { // Cfg profile specifier.
+ case 'g': { // CFG profile specifier.
// Skip the profile when we the profile iterator (FI) refers to the
// past-the-end element.
if (FI == ProgramPathAndClusterInfo.end())
continue;
- // For each node, its Cfg profile is encoded as
+ // For each node, its CFG profile is encoded as
// <src>:<count>,<sink_1>:<count_1>,<sink_2>:<count_2>,...
for (auto BasicBlockEdgeProfile : Values) {
if (BasicBlockEdgeProfile.empty())
@@ -264,10 +264,10 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
Twine("unsigned integer expected: '") + CountStr + "'");
if (i == 0) {
// The first element represents the source and its total count.
- FI->second.Cfg.NodeCounts[SrcBBID = *BBID] = Count;
+ FI->second.CFG.NodeCounts[SrcBBID = *BBID] = Count;
continue;
}
- FI->second.Cfg.EdgeCounts[SrcBBID][*BBID] = Count;
+ FI->second.CFG.EdgeCounts[SrcBBID][*BBID] = Count;
}
}
continue;
@@ -472,12 +472,6 @@ BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
return BBSPR.getClonePathsForFunction(FuncName);
}
-const CfgProfile *
-BasicBlockSectionsProfileReaderWrapperPass::getFunctionCfgProfile(
- StringRef FuncName) const {
- return BBSPR.getFunctionCfgProfile(FuncName);
-}
-
BasicBlockSectionsProfileReader &
BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
return BBSPR;
diff --git a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
index 21ff75a5cd354..ad55e86e62e25 100644
--- a/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
+++ b/llvm/test/CodeGen/X86/basic-block-sections-pgo-features.ll
@@ -5,7 +5,7 @@
; RUN: echo 'g 0:1000,1:800,2:200 1:800,3:800 2:200,3:200 3:1000' >> %t
; RUN: echo 'c 0 1 2' >> %t
;
-; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -basic-block-address-map -pgo-analysis-map=all -pgo-analysis-map-use-propeller-cfg | FileCheck %s
+; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -basic-block-address-map -pgo-analysis-map=all | FileCheck %s
define void @foo(i1 %cond) nounwind !prof !0 {
entry:
@@ -24,35 +24,42 @@ bb3:
!0 = !{!"function_entry_count", i64 1500}
!1 = !{!"branch_weights", i32 1200, i32 300}
-;; Verify that foo gets its PGO map from its Propeller CFG profile.
+;; Verify that foo's PGO map contains both IRPGO and Propeller CFG profiles.
; CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text.foo
; CHECK-NEXT: .byte 3 # version
-; CHECK-NEXT: .byte 15 # feature
+; CHECK-NEXT: .byte 143 # feature
; CHECK: .quad .Lfunc_begin0 # base address
; CHECK: .byte 0 # BB id
; CHECK: .byte 1 # BB id
; CHECK: .byte 2 # BB id
; CHECK: .byte 3 # BB id
-; PGO Analysis Map for foo
-; CHECK: .ascii "\350\007" # function entry count
-; CHECK-NEXT: .ascii "\350\007" # basic block frequency
-; CHECK-NEXT: .byte 1 # basic block successor count
-; CHECK-NEXT: .byte 1 # successor BB ID
-; CHECK-NEXT: .ascii "\240\006" # successor branch probability
-; CHECK-NEXT: .ascii "\240\006" # basic block frequency
-; CHECK-NEXT: .byte 2 # basic block successor count
-; CHECK-NEXT: .byte 2 # successor BB ID
-; CHECK-NEXT: .byte 0 # successor branch probability
-; CHECK-NEXT: .byte 3 # successor BB ID
-; CHECK-NEXT: .ascii "\240\006" # successor branch probability
-; CHECK-NEXT: .ascii "\310\001" # basic block frequency
-; CHECK-NEXT: .byte 1 # basic block successor count
-; CHECK-NEXT: .byte 3 # successor BB ID
-; CHECK-NEXT: .ascii "\310\001" # successor branch probability
-; CHECK-NEXT: .ascii "\350\007" # basic block frequency
-; CHECK-NEXT: .byte 0 # basic block successor count
+; CHECK: .ascii "\334\013" # function entry count
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200 " # basic block frequency
+; CHECK-NEXT: .ascii "\350\007" # basic block frequency (propeller)
+; CHECK-NEXT: .byte 1 # basic block successor count
+; CHECK-NEXT: .byte 1 # successor BB ID
+; CHECK-NEXT: .ascii "\200\200\200\200\b" # successor branch probability
+; CHECK-NEXT: .ascii "\240\006" # successor branch frequency (propeller)
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200 " # basic block frequency
+; CHECK-NEXT: .ascii "\240\006" # basic block frequency (propeller)
+; CHECK-NEXT: .byte 2 # basic block successor count
+; CHECK-NEXT: .byte 2 # successor BB ID
+; CHECK-NEXT: .ascii "\200\200\200\200\004" # successor branch probability
+; CHECK-NEXT: .byte 0 # successor branch frequency (propeller)
+; CHECK-NEXT: .byte 3 # successor BB ID
+; CHECK-NEXT: .ascii "\200\200\200\200\004" # successor branch probability
+; CHECK-NEXT: .ascii "\240\006" # successor branch frequency (propeller)
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200\020" # basic block frequency
+; CHECK-NEXT: .ascii "\310\001" # basic block frequency (propeller)
+; CHECK-NEXT: .byte 1 # basic block successor count
+; CHECK-NEXT: .byte 3 # successor BB ID
+; CHECK-NEXT: .ascii "\200\200\200\200\b" # successor branch probability
+; CHECK-NEXT: .ascii "\310\001" # successor branch frequency (propeller)
+; CHECK-NEXT: .ascii "\200\200\200\200\200\200\200 " # basic block frequency
+; CHECK-NEXT: .ascii "\350\007" # basic block frequency (propeller)
+; CHECK-NEXT: .byte 0 # basic block successor count
define void @bar(i1 %cond) nounwind !prof !2 {
entry:
@@ -68,7 +75,8 @@ bb2:
!2 = !{!"function_entry_count", i64 80}
!3 = !{!"branch_weights", i32 2, i32 78}
-;; Verify that we emit the PGO map for bar which doesn't have Propeller profile.
+;; Verify that the PGO map for bar only includes IRPGO data since it doesn't
+;; have Propeller profile.
; CHECK: .section .llvm_bb_addr_map,"o", at llvm_bb_addr_map,.text.bar
; CHECK-NEXT: .byte 3 # version
>From 224933a522067dd829a6f1ea1f8d065275193062 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Tue, 21 Oct 2025 16:56:11 +0000
Subject: [PATCH 11/11] clang-format.
---
llvm/include/llvm/Object/ELFTypes.h | 10 +++++++---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 9 ++++-----
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index e6d4552168607..c35d5066f0bb4 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -840,7 +840,9 @@ struct BBAddrMap {
return FuncEntryCount || BBFreq || BrProb || PropellerCFG;
}
- bool hasPGOAnalysisBBData() const { return BBFreq || BrProb || PropellerCFG; }
+ bool hasPGOAnalysisBBData() const {
+ return BBFreq || BrProb || PropellerCFG;
+ }
// Encodes to minimum bit width representation.
uint8_t encode() const {
@@ -871,10 +873,12 @@ struct BBAddrMap {
bool operator==(const Features &Other) const {
return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange,
- OmitBBEntries, CallsiteEndOffsets, BBHash, PropellerCFG) ==
+ OmitBBEntries, CallsiteEndOffsets, BBHash,
+ PropellerCFG) ==
std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb,
Other.MultiBBRange, Other.OmitBBEntries,
- Other.CallsiteEndOffsets, Other.BBHash, Other.PropellerCFG);
+ Other.CallsiteEndOffsets, Other.BBHash,
+ Other.PropellerCFG);
}
};
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 9ffaa53f8755f..51d66b034b757 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1432,9 +1432,8 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges,
(!NoFeatures && PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::BrProb));
bool PropellerCFGEnabled =
FuncCFGProfile &&
- (AllFeatures ||
- (!NoFeatures &&
- PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::PropellerCFG)));
+ (AllFeatures || (!NoFeatures && PgoAnalysisMapFeatures.isSet(
+ PGOMapFeaturesEnum::PropellerCFG)));
if ((BBFreqEnabled || BrProbEnabled) && BBAddrMapSkipEmitBBEntries) {
MF.getFunction().getContext().emitError(
@@ -1473,8 +1472,8 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
uint8_t BBAddrMapVersion = OutStreamer->getContext().getBBAddrMapVersion();
OutStreamer->emitInt8(BBAddrMapVersion);
OutStreamer->AddComment("feature");
- auto Features =
- getBBAddrMapFeature(MF, MBBSectionRanges.size(), HasCalls, FuncCFGProfile);
+ auto Features = getBBAddrMapFeature(MF, MBBSectionRanges.size(), HasCalls,
+ FuncCFGProfile);
OutStreamer->emitInt8(Features.encode());
// Emit BB Information for each basic block in the function.
if (Features.MultiBBRange) {
More information about the llvm-commits
mailing list