Skip to content

[BOLT] Use deterministic xxh3 for computing BF/BB hashes #72542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bolt/lib/Core/BinaryFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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(
Expand Down
9 changes: 0 additions & 9 deletions bolt/lib/Core/HashUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 9 additions & 6 deletions bolt/lib/Profile/StaleProfileMatching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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.
Expand All @@ -257,15 +258,15 @@ 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;
for (BinaryBasicBlock *PredBB : BB->predecessors()) {
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.
Expand Down Expand Up @@ -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(
Expand Down
18 changes: 9 additions & 9 deletions bolt/test/X86/Inputs/blarge_profile_stale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 } ]
...
2 changes: 1 addition & 1 deletion bolt/test/X86/pre-aggregated-perf.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 29 additions & 3 deletions bolt/test/X86/reader-stale-yaml.test
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
# 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 \
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add REQUIRES: asserts for debug logging checks

# 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
Expand All @@ -28,6 +38,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)
Expand All @@ -48,7 +59,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
Expand All @@ -58,6 +83,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)
Expand Down