[llvm] [PGO][NFC] Make CFGMST debug dump order deterministic (PR #200835)
Yaxun Liu via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 1 07:28:12 PDT 2026
https://github.com/yxsamliu created https://github.com/llvm/llvm-project/pull/200835
The PGO instrumentation pass can print a per-function CFG-MST dump under
-debug-only=pgo-instrumentation. The basic blocks were listed in the
iteration order of a DenseMap keyed by the block pointer, so the same
function could print its blocks in a different order from one run or
machine to the next, even when nothing about the MST actually changed.
That makes the dump hard to diff. For example, two runs of the same build
could print the same blocks in different orders:
run 1: run 2:
BB: entry ... BB: if.else ...
BB: if.then ... BB: entry ...
BB: if.else ... BB: if.then ...
and a plain `diff` would flag every line, hiding any real difference.
Sort the blocks by their assigned MST Index (with the block name as a
stable tiebreaker) before printing, so the dump is reproducible across
runs and platforms. This only affects -debug/dump output; codegen is
unchanged (NFC).
>From bcc2653c6631f918cb5f899f5a7b3f0756bcf8e9 Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Mon, 6 Apr 2026 18:58:11 -0400
Subject: [PATCH] [PGO][NFC] Make CFGMST debug dump order deterministic
The PGO instrumentation pass can print a per-function CFG-MST dump under
-debug-only=pgo-instrumentation. The basic blocks were listed in the
iteration order of a DenseMap keyed by the block pointer, so the same
function could print its blocks in a different order from one run or
machine to the next, even when nothing about the MST actually changed.
That makes the dump hard to diff. For example, two runs of the same build
could print the same blocks in different orders:
run 1: run 2:
BB: entry ... BB: if.else ...
BB: if.then ... BB: entry ...
BB: if.else ... BB: if.then ...
and a plain `diff` would flag every line, hiding any real difference.
Sort the blocks by their assigned MST Index (with the block name as a
stable tiebreaker) before printing, so the dump is reproducible across
runs and platforms. This only affects -debug/dump output; codegen is
unchanged (NFC).
---
.../llvm/Transforms/Instrumentation/CFGMST.h | 26 ++++++++++++++++---
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h b/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
index 6b93b6cb83b4e..efef78eadd31e 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
@@ -286,12 +286,30 @@ template <class Edge, class BBInfo> class CFGMST {
if (!Message.str().empty())
OS << Message << "\n";
OS << " Number of Basic Blocks: " << BBInfos.size() << "\n";
- for (auto &BI : BBInfos) {
- const BasicBlock *BB = BI.first;
+ // Collect and sort BBInfos deterministically by their assigned Index.
+ std::vector<std::pair<const BasicBlock *, const BBInfo *>> SortedBBInfos;
+ SortedBBInfos.reserve(BBInfos.size());
+ for (const auto &BI : BBInfos)
+ SortedBBInfos.emplace_back(BI.first, BI.second.get());
+
+ llvm::sort(SortedBBInfos, [](const auto &A, const auto &B) {
+ // Primary key: BBInfo Index
+ if (A.second->Index != B.second->Index)
+ return A.second->Index < B.second->Index;
+ // Secondary key: name string to keep a stable order even if
+ // indices tie (ties shouldn't happen, but this makes ordering
+ // explicit).
+ StringRef NameA = A.first ? A.first->getName() : StringRef("FakeNode");
+ StringRef NameB = B.first ? B.first->getName() : StringRef("FakeNode");
+ return NameA < NameB;
+ });
+
+ for (const auto &P : SortedBBInfos) {
+ const BasicBlock *BB = P.first;
+ const BBInfo *Info = P.second;
OS << " BB: " << (BB == nullptr ? "FakeNode" : BB->getName()) << " "
- << BI.second->infoString() << "\n";
+ << Info->infoString() << "\n";
}
-
OS << " Number of Edges: " << AllEdges.size()
<< " (*: Instrument, C: CriticalEdge, -: Removed)\n";
uint32_t Count = 0;
More information about the llvm-commits
mailing list