[llvm] [PGO][NFC] Make CFGMST debug dump order deterministic (PR #200835)

Yaxun Liu via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 30 08:18:45 PDT 2026


https://github.com/yxsamliu updated https://github.com/llvm/llvm-project/pull/200835

>From 58dbfeadbf5f5ba6f649be91d4ca8dce32e1a733 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  | 34 ++++++++++++++++---
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h b/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
index 6b93b6cb83b4e..caab53dfb5819 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
@@ -15,6 +15,7 @@
 #define LLVM_TRANSFORMS_INSTRUMENTATION_CFGMST_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
@@ -286,12 +287,37 @@ 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());
+
+#ifndef NDEBUG
+    SmallDenseSet<uint32_t, 16> SeenIndices;
+    for (const auto &P : SortedBBInfos)
+      assert(SeenIndices.insert(P.second->Index).second &&
+             "BBInfo indices should be unique");
+#endif
+
+    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