[llvm] [CodeGen] Fix non-determinism in MachineBlockHashInfo hashes (PR #192826)

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 19 11:09:28 PDT 2026


https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/192826

>From 7de6ee285c3a165772683994b92e63e1d9b1a90e Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sat, 18 Apr 2026 21:44:41 -0700
Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
 =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7

[skip ci]
---
 .../CodeGen/BasicBlockMatchingAndInference.cpp  |  4 ++--
 llvm/lib/CodeGen/MachineBlockHashInfo.cpp       | 17 +++++++++--------
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/CodeGen/BasicBlockMatchingAndInference.cpp b/llvm/lib/CodeGen/BasicBlockMatchingAndInference.cpp
index bba4c4a220d9e..d956bd475c9e6 100644
--- a/llvm/lib/CodeGen/BasicBlockMatchingAndInference.cpp
+++ b/llvm/lib/CodeGen/BasicBlockMatchingAndInference.cpp
@@ -19,12 +19,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/BasicBlockMatchingAndInference.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
 #include "llvm/CodeGen/MachineBlockHashInfo.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/InitializePasses.h"
 #include <llvm/Support/CommandLine.h>
-#include <unordered_map>
 
 using namespace llvm;
 
@@ -70,7 +70,7 @@ class StaleMatcher {
 
 private:
   using HashBlockPairType = std::pair<BlendedBlockHash, MachineBasicBlock *>;
-  std::unordered_map<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks;
+  DenseMap<uint16_t, std::vector<HashBlockPairType>> OpHashToBlocks;
 };
 
 INITIALIZE_PASS_BEGIN(BasicBlockMatchingAndInference,
diff --git a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
index 73dfc7c62a95c..3aa3823731396 100644
--- a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
+++ b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
@@ -17,7 +17,7 @@
 
 using namespace llvm;
 
-uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) {
+static uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) {
   uint64_t Hash = 0;
   for (const MachineInstr &MI : MBB) {
     if (MI.isMetaInstruction() || MI.isTerminator())
@@ -34,7 +34,7 @@ uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) {
 }
 
 /// Fold a 64-bit integer to a 16-bit one.
-uint16_t fold_64_to_16(const uint64_t Value) {
+static uint16_t fold_64_to_16(const uint64_t Value) {
   uint16_t Res = static_cast<uint16_t>(Value);
   Res ^= static_cast<uint16_t>(Value >> 16);
   Res ^= static_cast<uint16_t>(Value >> 32);
@@ -66,18 +66,19 @@ bool MachineBlockHashInfo::runOnMachineFunction(MachineFunction &F) {
   uint16_t Offset = 0;
   // Initialize hash components
   for (const MachineBasicBlock &MBB : F) {
+    auto &HashInfo = HashInfos[&MBB];
     // offset of the machine basic block
-    HashInfos[&MBB].Offset = Offset;
-    Offset += MBB.size();
+    HashInfo.Offset = Offset + MBB.size();
     // Hashing opcodes
-    HashInfos[&MBB].OpcodeHash = hashBlock(MBB, /*HashOperands=*/false);
+    HashInfo.OpcodeHash = hashBlock(MBB, /*HashOperands=*/false);
     // Hash complete instructions
-    HashInfos[&MBB].InstrHash = hashBlock(MBB, /*HashOperands=*/true);
+    HashInfo.InstrHash = hashBlock(MBB, /*HashOperands=*/true);
   }
 
   // Initialize neighbor hash
   for (const MachineBasicBlock &MBB : F) {
-    uint64_t Hash = HashInfos[&MBB].OpcodeHash;
+    auto &HashInfo = HashInfos[&MBB];
+    uint64_t Hash = HashInfo.OpcodeHash;
     // Append hashes of successors
     for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
       uint64_t SuccHash = HashInfos[SuccMBB].OpcodeHash;
@@ -88,7 +89,7 @@ bool MachineBlockHashInfo::runOnMachineFunction(MachineFunction &F) {
       uint64_t PredHash = HashInfos[PredMBB].OpcodeHash;
       Hash = hashing::detail::hash_16_bytes(Hash, PredHash);
     }
-    HashInfos[&MBB].NeighborHash = Hash;
+    HashInfo.NeighborHash = Hash;
   }
 
   // Assign hashes

>From 4c11ef77e835061eb2a12c93f3f81904ee9829dd Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sun, 19 Apr 2026 00:16:50 -0700
Subject: [PATCH 2/4] fix

Created using spr 1.3.7
---
 llvm/lib/CodeGen/MachineBlockHashInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
index 804986dac6ad2..2ad31d4fd87a8 100644
--- a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
+++ b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
@@ -43,7 +43,7 @@ static uint64_t hashValue(const APInt &I) {
   return hashValue(ArrayRef(I.getRawData(), I.getNumWords()));
 }
 
-template <typename T> static uint64_t ignoreValue(const T *I) { return 1; }
+template <typename T> static uint64_t ignoreValue(const T *) { return 1; }
 
 static uint64_t hashCombine() { return 0; }
 

>From 1980cac4b3a5cc3fb712ea626ed29f0397593d88 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sun, 19 Apr 2026 00:28:27 -0700
Subject: [PATCH 3/4] include

Created using spr 1.3.7
---
 llvm/lib/CodeGen/MachineBlockHashInfo.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
index 2ad31d4fd87a8..b72a1a57b6435 100644
--- a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
+++ b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Target/TargetMachine.h"
 

>From 15021a2c8383592bb1f04e999a35c1c7b9a1624a Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sun, 19 Apr 2026 11:09:10 -0700
Subject: [PATCH 4/4] stableHashValue

Created using spr 1.3.7
---
 llvm/lib/CodeGen/MachineBlockHashInfo.cpp | 103 +---------------------
 1 file changed, 3 insertions(+), 100 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
index b72a1a57b6435..c0dd4968f05b6 100644
--- a/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
+++ b/llvm/lib/CodeGen/MachineBlockHashInfo.cpp
@@ -11,111 +11,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/MachineBlockHashInfo.h"
-#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/Passes.h"
-#include "llvm/IR/Constants.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Target/TargetMachine.h"
 
 using namespace llvm;
 
-template <typename T>
-std::enable_if_t<is_integral_or_enum<T>::value, uint64_t>
-hashValue(const T &Val) {
-  return static_cast<uint64_t>(Val);
-}
-
-static uint64_t hashValue(StringRef S) {
-  uint64_t Hash = 0;
-  for (char C : S)
-    Hash = hashing::detail::hash_16_bytes(Hash, C);
-  return Hash;
-}
-
-template <typename T> uint64_t hashValue(ArrayRef<T> A) {
-  uint64_t Hash = 0;
-  for (const auto &C : A)
-    Hash = hashing::detail::hash_16_bytes(Hash, C);
-  return Hash;
-}
-
-static uint64_t hashValue(const APInt &I) {
-  return hashValue(ArrayRef(I.getRawData(), I.getNumWords()));
-}
-
-template <typename T> static uint64_t ignoreValue(const T *) { return 1; }
-
-static uint64_t hashCombine() { return 0; }
-
-template <typename T, typename... Ts>
-uint64_t hashCombine(const T &Hash, const Ts &...Args) {
-  return hashing::detail::hash_16_bytes(hashValue(Hash), hashCombine(Args...));
-}
-
-// Similar to hash_code llvm::hash_value(const MachineOperand &MO) but stable.
-static uint64_t hashOperand(const MachineOperand &MO) {
-  switch (MO.getType()) {
-  case MachineOperand::MO_Register:
-    // Register operands don't have target flags.
-    return hashCombine(MO.getType(), MO.getReg().id(), MO.getSubReg(),
-                       MO.isDef());
-  case MachineOperand::MO_Immediate:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getImm());
-  case MachineOperand::MO_CImmediate:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       MO.getCImm()->getValue());
-  case MachineOperand::MO_FPImmediate:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       MO.getFPImm()->getValue().bitcastToAPInt());
-  case MachineOperand::MO_MachineBasicBlock:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       ignoreValue(MO.getMBB()));
-  case MachineOperand::MO_FrameIndex:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getIndex());
-  case MachineOperand::MO_ConstantPoolIndex:
-  case MachineOperand::MO_TargetIndex:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getIndex(),
-                       MO.getOffset());
-  case MachineOperand::MO_JumpTableIndex:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getIndex());
-  case MachineOperand::MO_ExternalSymbol:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getOffset(),
-                       StringRef(MO.getSymbolName()));
-  case MachineOperand::MO_GlobalAddress:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       ignoreValue(MO.getGlobal()), MO.getOffset());
-  case MachineOperand::MO_BlockAddress:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       ignoreValue(MO.getBlockAddress()), MO.getOffset());
-  case MachineOperand::MO_RegisterMask:
-  case MachineOperand::MO_RegisterLiveOut:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       ignoreValue(MO.getRegMask()));
-  case MachineOperand::MO_Metadata:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       ignoreValue(MO.getMetadata()));
-  case MachineOperand::MO_MCSymbol:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       ignoreValue(MO.getMCSymbol()));
-  case MachineOperand::MO_DbgInstrRef:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       MO.getInstrRefInstrIndex(), MO.getInstrRefOpIndex());
-  case MachineOperand::MO_CFIIndex:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex());
-  case MachineOperand::MO_IntrinsicID:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID());
-  case MachineOperand::MO_Predicate:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getPredicate());
-  case MachineOperand::MO_ShuffleMask:
-    return hashCombine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask());
-  case MachineOperand::MO_LaneMask:
-    return hashCombine(MO.getType(), MO.getTargetFlags(),
-                       MO.getLaneMask().getAsInteger());
-  }
-  llvm_unreachable("Invalid machine operand type");
-}
-
 static uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) {
   uint64_t Hash = 0;
   for (const MachineInstr &MI : MBB) {
@@ -124,8 +27,8 @@ static uint64_t hashBlock(const MachineBasicBlock &MBB, bool HashOperands) {
     Hash = hashing::detail::hash_16_bytes(Hash, MI.getOpcode());
     if (HashOperands) {
       for (unsigned i = 0; i < MI.getNumOperands(); i++) {
-        Hash =
-            hashing::detail::hash_16_bytes(Hash, hashOperand(MI.getOperand(i)));
+        Hash = hashing::detail::hash_16_bytes(
+            Hash, stableHashValue(MI.getOperand(i)));
       }
     }
   }



More information about the llvm-commits mailing list