[llvm] [BOLT] Use deterministic xxh3 for computing BF/BB hashes (PR #72542)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 27 14:45:45 PST 2023


https://github.com/spupyrev updated https://github.com/llvm/llvm-project/pull/72542

>From acfbb45bd5527623feceaeac07272a5301c46b8a Mon Sep 17 00:00:00 2001
From: spupyrev <spupyrev at fb.com>
Date: Thu, 16 Nov 2023 06:42:36 -0800
Subject: [PATCH 1/2] [BOLT] Use deterministic xxh3 for computing BF/BB hashes

---
 bolt/lib/Core/BinaryFunction.cpp              |  3 +-
 bolt/lib/Core/HashUtilities.cpp               |  9 ------
 bolt/lib/Profile/StaleProfileMatching.cpp     | 15 +++++----
 .../test/X86/Inputs/blarge_profile_stale.yaml | 18 +++++------
 bolt/test/X86/pre-aggregated-perf.test        |  2 +-
 bolt/test/X86/reader-stale-yaml.test          | 31 +++++++++++++++++--
 6 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 30c34a82c32d720..3b0a2314dc1d252 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -40,6 +40,7 @@
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Timer.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/xxhash.h"
 #include <functional>
 #include <limits>
 #include <numeric>
@@ -3636,7 +3637,7 @@ size_t BinaryFunction::computeHash(bool UseDFS,
   for (const BinaryBasicBlock *BB : Order)
     HashString.append(hashBlock(BC, *BB, OperandHashFunc));
 
-  return Hash = std::hash<std::string>{}(HashString);
+  return Hash = llvm::xxh3_64bits(HashString);
 }
 
 void BinaryFunction::insertBasicBlocks(
diff --git a/bolt/lib/Core/HashUtilities.cpp b/bolt/lib/Core/HashUtilities.cpp
index 6c7570dcc44e87b..d40159b2e216d90 100644
--- a/bolt/lib/Core/HashUtilities.cpp
+++ b/bolt/lib/Core/HashUtilities.cpp
@@ -18,15 +18,6 @@
 namespace llvm {
 namespace bolt {
 
-/// Hashing a 64-bit integer to a 16-bit one.
-uint16_t hash_64_to_16(const uint64_t Hash) {
-  uint16_t Res = (uint16_t)(Hash & 0xFFFF);
-  Res ^= (uint16_t)((Hash >> 16) & 0xFFFF);
-  Res ^= (uint16_t)((Hash >> 32) & 0xFFFF);
-  Res ^= (uint16_t)((Hash >> 48) & 0xFFFF);
-  return Res;
-}
-
 std::string hashInteger(uint64_t Value) {
   std::string HashString;
   if (Value == 0)
diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp
index d00bf87ffc8ad87..6fb6f380f71eecd 100644
--- a/bolt/lib/Profile/StaleProfileMatching.cpp
+++ b/bolt/lib/Profile/StaleProfileMatching.cpp
@@ -30,6 +30,7 @@
 #include "llvm/ADT/Bitfields.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/xxhash.h"
 #include "llvm/Transforms/Utils/SampleProfileInference.h"
 
 #include <queue>
@@ -240,12 +241,12 @@ void BinaryFunction::computeBlockHashes() const {
     // Hashing complete instructions.
     std::string InstrHashStr = hashBlock(
         BC, *BB, [&](const MCOperand &Op) { return hashInstOperand(BC, Op); });
-    uint64_t InstrHash = std::hash<std::string>{}(InstrHashStr);
-    BlendedHashes[I].InstrHash = (uint16_t)hash_value(InstrHash);
+    uint64_t InstrHash = llvm::xxh3_64bits(InstrHashStr);
+    BlendedHashes[I].InstrHash = (uint16_t)InstrHash;
     // Hashing opcodes.
     std::string OpcodeHashStr = hashBlockLoose(BC, *BB);
-    OpcodeHashes[I] = std::hash<std::string>{}(OpcodeHashStr);
-    BlendedHashes[I].OpcodeHash = (uint16_t)hash_value(OpcodeHashes[I]);
+    OpcodeHashes[I] = llvm::xxh3_64bits(OpcodeHashStr);
+    BlendedHashes[I].OpcodeHash = (uint16_t)OpcodeHashes[I];
   }
 
   // Initialize neighbor hash.
@@ -257,7 +258,7 @@ void BinaryFunction::computeBlockHashes() const {
       uint64_t SuccHash = OpcodeHashes[SuccBB->getIndex()];
       Hash = hashing::detail::hash_16_bytes(Hash, SuccHash);
     }
-    BlendedHashes[I].SuccHash = (uint8_t)hash_value(Hash);
+    BlendedHashes[I].SuccHash = (uint8_t)Hash;
 
     // Append hashes of predecessors.
     Hash = 0;
@@ -265,7 +266,7 @@ void BinaryFunction::computeBlockHashes() const {
       uint64_t PredHash = OpcodeHashes[PredBB->getIndex()];
       Hash = hashing::detail::hash_16_bytes(Hash, PredHash);
     }
-    BlendedHashes[I].PredHash = (uint8_t)hash_value(Hash);
+    BlendedHashes[I].PredHash = (uint8_t)Hash;
   }
 
   //  Assign hashes.
@@ -405,6 +406,8 @@ void matchWeightsByHashes(BinaryContext &BC,
         ++BC.Stats.NumMatchedBlocks;
         BC.Stats.MatchedSampleCount += YamlBB.ExecCount;
         LLVM_DEBUG(dbgs() << "  exact match\n");
+      } else {
+        LLVM_DEBUG(dbgs() << "  loose match\n");
       }
     } else {
       LLVM_DEBUG(
diff --git a/bolt/test/X86/Inputs/blarge_profile_stale.yaml b/bolt/test/X86/Inputs/blarge_profile_stale.yaml
index f5abaed3da39412..43b75c99656f188 100644
--- a/bolt/test/X86/Inputs/blarge_profile_stale.yaml
+++ b/bolt/test/X86/Inputs/blarge_profile_stale.yaml
@@ -10,33 +10,33 @@ header:
 functions:
   - name:            SolveCubic
     fid:             6
-    hash:            0xC6E9098E973BBE19
+    hash:            0x0000000000000000
     exec:            151
     nblocks:         18
     blocks:
       - bid:             0
         insns:           43
-        hash:            0xed4db287e71c0000
+        hash:            0x4600940a609c0000
         exec:            151
         succ:            [ { bid: 1, cnt: 151, mis: 2 }, { bid: 7, cnt: 0 } ]
       - bid:             1
         insns:           7
-        hash:            0x39330000e4560088
+        hash:            0x167a1f084f130088
         succ:            [ { bid: 13, cnt: 151 }, { bid: 2, cnt: 0 } ]
       - bid:             13
         insns:           26
-        hash:            0xa9700000fe202a7
+        hash:            0xa8d50000f81902a7
         succ:            [ { bid: 3, cnt: 89 }, { bid: 2, cnt: 10 } ]
       - bid:             3
         insns:           9
-        hash:            0x62391dad18a700a0
+        hash:            0xc516000073dc00a0
         succ:            [ { bid: 5, cnt: 151 } ]
       - bid:             5
         insns:           9
-        hash:            0x4d906d19ecec0111
+        hash:            0x6446e1ea500111
   - name:            usqrt
     fid:             7
-    hash:            0x8B62B1F9AD81EA35
+    hash:            0x0000000000000000
     exec:            20
     nblocks:         6
     blocks:
@@ -47,10 +47,10 @@ functions:
         succ:            [ { bid: 1, cnt: 0 } ]
       - bid:             1
         insns:           9
-        hash:            0x27e43a5e10cd0010
+        hash:            0xd70d7a64320e0010
         succ:            [ { bid: 3, cnt: 320, mis: 171 }, { bid: 2, cnt: 0 } ]
       - bid:             3
         insns:           2
-        hash:            0x4db935b6471e0039
+        hash:            0x5c06705524800039
         succ:            [ { bid: 1, cnt: 300, mis: 33 }, { bid: 4, cnt: 20 } ]
 ...
diff --git a/bolt/test/X86/pre-aggregated-perf.test b/bolt/test/X86/pre-aggregated-perf.test
index 720d179d1c6b809..e8c3f64239a27dd 100644
--- a/bolt/test/X86/pre-aggregated-perf.test
+++ b/bolt/test/X86/pre-aggregated-perf.test
@@ -46,7 +46,7 @@ PERF2BOLT: 1 usqrt a 1 usqrt 10 0 22
 
 NEWFORMAT:  - name:            'frame_dummy/1'
 NEWFORMAT:    fid:             3
-NEWFORMAT:    hash:            0x24496F7F9594E89F
+NEWFORMAT:    hash:            0x28C72085C0BD8D37
 NEWFORMAT:    exec:            1
 
 NEWFORMAT:  - name:            usqrt
diff --git a/bolt/test/X86/reader-stale-yaml.test b/bolt/test/X86/reader-stale-yaml.test
index 4127e92b59d3f97..b9715f0cabe33bf 100644
--- a/bolt/test/X86/reader-stale-yaml.test
+++ b/bolt/test/X86/reader-stale-yaml.test
@@ -5,19 +5,28 @@ RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe
 # Testing "usqrt"
 RUN: llvm-bolt %t.exe -o %t.null --b %p/Inputs/blarge_profile_stale.yaml \
 RUN:   --print-cfg --print-only=usqrt --infer-stale-profile=1 \
-RUN:   --profile-ignore-hash=1 --profile-use-dfs=0 2>&1 | FileCheck %s -check-prefix=CHECK1
+RUN:   --profile-ignore-hash=1 --profile-use-dfs=0 --debug-only=bolt-prof 2>&1 | FileCheck %s -check-prefix=CHECK1
 # Testing "SolveCubic"
 RUN: llvm-bolt %t.exe -o %t.null --b %p/Inputs/blarge_profile_stale.yaml \
 RUN:   --print-cfg --print-only=SolveCubic --infer-stale-profile=1 \
-RUN:   --profile-ignore-hash=1 --profile-use-dfs=0 2>&1 | FileCheck %s -check-prefix=CHECK2
+RUN:   --profile-ignore-hash=1 --profile-use-dfs=0 --debug-only=bolt-prof 2>&1 | FileCheck %s -check-prefix=CHECK2
 
 # Function "usqrt" has stale profile, since the number of blocks in the profile
 # (nblocks=6) does not match the size of the CFG in the binary. The entry
 # block (bid=0) has an incorrect (missing) count, which should be inferred by
 # the algorithm.
 
-# Verify that yaml reader works as expected.
+# Verify inference details.
 CHECK1:  pre-processing profile using YAML profile reader
+CHECK1:  applying profile inference for "usqrt"
+CHECK1: Matched yaml block (bid = 0) with hash 1111111111111111 to BB (index = 0) with hash 36007ba1d80c0000
+CHECK1-NEXT: loose match
+CHECK1:  Matched yaml block (bid = 1) with hash d70d7a64320e0010 to BB (index = 1) with hash d70d7a64320e0010
+CHECK1-NEXT: exact match
+CHECK1:  Matched yaml block (bid = 3) with hash 5c06705524800039 to BB (index = 3) with hash 5c06705524800039
+CHECK1-NEXT: exact match
+
+# Verify that yaml reader works as expected.
 CHECK1:    Binary Function "usqrt" after building cfg {
 CHECK1:      State       : CFG constructed
 CHECK1:      Address     : 0x401170
@@ -28,6 +37,7 @@ CHECK1:      BB Count    : 5
 CHECK1:      Exec Count  : 20
 CHECK1:      Branch Count: 640
 CHECK1:    }
+
 # Verify block counts.
 CHECK1:    .LBB01 (4 instructions, align : 1)
 CHECK1:      Successors: .Ltmp[[#BB13:]] (mispreds: 0, count: 20)
@@ -48,7 +58,21 @@ CHECK1:  inferred profile for 2 (100.00% of profiled, 100.00% of stale) function
 # verifies that the inference is able to match two blocks (bid=1 and bid=13)
 # using "loose" hashes and then correctly propagate the counts.
 
+# Verify inference details.
 CHECK2:  pre-processing profile using YAML profile reader
+CHECK2:  applying profile inference for "SolveCubic"
+CHECK2:  Matched yaml block (bid = 0) with hash 4600940a609c0000 to BB (index = 0) with hash 4600940a609c0000
+CHECK2-NEXT:  exact match
+CHECK2:  Matched yaml block (bid = 1) with hash 167a1f084f130088 to BB (index = 1) with hash 167a1f084f130088
+CHECK2-NEXT:  exact match
+CHECK2:  Matched yaml block (bid = 13) with hash a8d50000f81902a7 to BB (index = 13) with hash a8d5aa43f81902a7
+CHECK2-NEXT:  loose match
+CHECK2:  Matched yaml block (bid = 3) with hash c516000073dc00a0 to BB (index = 3) with hash c516b1c973dc00a0
+CHECK2-NEXT:  loose match
+CHECK2:  Matched yaml block (bid = 5) with hash 6446e1ea500111 to BB (index = 5) with hash 6446e1ea500111
+CHECK2-NEXT:  exact match
+
+# Verify that yaml reader works as expected.
 CHECK2:    Binary Function "SolveCubic" after building cfg {
 CHECK2:      State       : CFG constructed
 CHECK2:      Address     : 0x400e00
@@ -58,6 +82,7 @@ CHECK2:      IsSimple    : 1
 CHECK2:      BB Count    : 18
 CHECK2:      Exec Count  : 151
 CHECK2:      Branch Count: 552
+
 # Verify block counts.
 CHECK2:    .LBB00 (43 instructions, align : 1)
 CHECK2:      Successors: .Ltmp[[#BB7:]] (mispreds: 0, count: 0), .LFT[[#BB1:]] (mispreds: 0, count: 151)

>From 9156275225011b2fd67e31deec8891970aedbe1e Mon Sep 17 00:00:00 2001
From: spupyrev <spupyrev at fb.com>
Date: Mon, 27 Nov 2023 11:31:29 -0800
Subject: [PATCH 2/2] added REQUIRES: asserts

---
 bolt/test/X86/reader-stale-yaml.test | 1 +
 1 file changed, 1 insertion(+)

diff --git a/bolt/test/X86/reader-stale-yaml.test b/bolt/test/X86/reader-stale-yaml.test
index b9715f0cabe33bf..ad0945b1493407c 100644
--- a/bolt/test/X86/reader-stale-yaml.test
+++ b/bolt/test/X86/reader-stale-yaml.test
@@ -1,6 +1,7 @@
 # This script checks that YamlProfileReader in llvm-bolt is reading data
 # correctly and stale data is corrected by profile inference.
 
+REQUIRES: asserts
 RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe
 # Testing "usqrt"
 RUN: llvm-bolt %t.exe -o %t.null --b %p/Inputs/blarge_profile_stale.yaml \



More information about the llvm-commits mailing list