Skip to content

Commit 9672375

Browse files
committed
Revert "[StructuralHash] Refactor (#112621)"
This reverts commit b667d16.
1 parent b667d16 commit 9672375

File tree

4 files changed

+63
-100
lines changed

4 files changed

+63
-100
lines changed

llvm/include/llvm/IR/StructuralHash.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,27 @@
1414
#ifndef LLVM_IR_STRUCTURALHASH_H
1515
#define LLVM_IR_STRUCTURALHASH_H
1616

17-
#include "llvm/ADT/StableHashing.h"
1817
#include <cstdint>
1918

2019
namespace llvm {
2120

2221
class Function;
2322
class Module;
2423

24+
using IRHash = uint64_t;
25+
2526
/// Returns a hash of the function \p F.
2627
/// \param F The function to hash.
2728
/// \param DetailedHash Whether or not to encode additional information in the
2829
/// hash. The additional information added into the hash when this flag is set
2930
/// to true includes instruction and operand type information.
30-
stable_hash StructuralHash(const Function &F, bool DetailedHash = false);
31+
IRHash StructuralHash(const Function &F, bool DetailedHash = false);
3132

3233
/// Returns a hash of the module \p M by hashing all functions and global
3334
/// variables contained within. \param M The module to hash. \param DetailedHash
3435
/// Whether or not to encode additional information in the function hashes that
3536
/// composed the module hash.
36-
stable_hash StructuralHash(const Module &M, bool DetailedHash = false);
37+
IRHash StructuralHash(const Module &M, bool DetailedHash = false);
3738

3839
} // end namespace llvm
3940

llvm/lib/IR/StructuralHash.cpp

Lines changed: 47 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -24,93 +24,61 @@ namespace {
2424
// by the MergeFunctions pass.
2525

2626
class StructuralHashImpl {
27-
stable_hash Hash = 4;
27+
uint64_t Hash = 4;
2828

29-
bool DetailedHash;
30-
31-
// This random value acts as a block header, as otherwise the partition of
32-
// opcodes into BBs wouldn't affect the hash, only the order of the opcodes.
33-
static constexpr stable_hash BlockHeaderHash = 45798;
34-
static constexpr stable_hash FunctionHeaderHash = 0x62642d6b6b2d6b72;
35-
static constexpr stable_hash GlobalHeaderHash = 23456;
29+
void hash(uint64_t V) { Hash = hashing::detail::hash_16_bytes(Hash, V); }
3630

3731
// This will produce different values on 32-bit and 64-bit systens as
3832
// hash_combine returns a size_t. However, this is only used for
3933
// detailed hashing which, in-tree, only needs to distinguish between
4034
// differences in functions.
41-
// TODO: This is not stable.
42-
template <typename T> stable_hash hashArbitaryType(const T &V) {
43-
return hash_combine(V);
35+
template <typename T> void hashArbitaryType(const T &V) {
36+
hash(hash_combine(V));
4437
}
4538

46-
stable_hash hashType(Type *ValueType) {
47-
SmallVector<stable_hash> Hashes;
48-
Hashes.emplace_back(ValueType->getTypeID());
39+
void hashType(Type *ValueType) {
40+
hash(ValueType->getTypeID());
4941
if (ValueType->isIntegerTy())
50-
Hashes.emplace_back(ValueType->getIntegerBitWidth());
51-
return stable_hash_combine(Hashes);
42+
hash(ValueType->getIntegerBitWidth());
5243
}
5344

5445
public:
55-
StructuralHashImpl() = delete;
56-
explicit StructuralHashImpl(bool DetailedHash) : DetailedHash(DetailedHash) {}
57-
58-
stable_hash hashConstant(Constant *C) {
59-
SmallVector<stable_hash> Hashes;
60-
// TODO: hashArbitaryType() is not stable.
61-
if (ConstantInt *ConstInt = dyn_cast<ConstantInt>(C)) {
62-
Hashes.emplace_back(hashArbitaryType(ConstInt->getValue()));
63-
} else if (ConstantFP *ConstFP = dyn_cast<ConstantFP>(C)) {
64-
Hashes.emplace_back(hashArbitaryType(ConstFP->getValue()));
65-
} else if (Function *Func = dyn_cast<Function>(C)) {
46+
StructuralHashImpl() = default;
47+
48+
void updateOperand(Value *Operand) {
49+
hashType(Operand->getType());
50+
51+
// The cases enumerated below are not exhaustive and are only aimed to
52+
// get decent coverage over the function.
53+
if (ConstantInt *ConstInt = dyn_cast<ConstantInt>(Operand)) {
54+
hashArbitaryType(ConstInt->getValue());
55+
} else if (ConstantFP *ConstFP = dyn_cast<ConstantFP>(Operand)) {
56+
hashArbitaryType(ConstFP->getValue());
57+
} else if (Argument *Arg = dyn_cast<Argument>(Operand)) {
58+
hash(Arg->getArgNo());
59+
} else if (Function *Func = dyn_cast<Function>(Operand)) {
6660
// Hashing the name will be deterministic as LLVM's hashing infrastructure
6761
// has explicit support for hashing strings and will not simply hash
6862
// the pointer.
69-
Hashes.emplace_back(hashArbitaryType(Func->getName()));
63+
hashArbitaryType(Func->getName());
7064
}
71-
72-
return stable_hash_combine(Hashes);
73-
}
74-
75-
stable_hash hashValue(Value *V) {
76-
// Check constant and return its hash.
77-
Constant *C = dyn_cast<Constant>(V);
78-
if (C)
79-
return hashConstant(C);
80-
81-
// Hash argument number.
82-
SmallVector<stable_hash> Hashes;
83-
if (Argument *Arg = dyn_cast<Argument>(V))
84-
Hashes.emplace_back(Arg->getArgNo());
85-
86-
return stable_hash_combine(Hashes);
8765
}
8866

89-
stable_hash hashOperand(Value *Operand) {
90-
SmallVector<stable_hash> Hashes;
91-
Hashes.emplace_back(hashType(Operand->getType()));
92-
Hashes.emplace_back(hashValue(Operand));
93-
return stable_hash_combine(Hashes);
94-
}
95-
96-
stable_hash hashInstruction(const Instruction &Inst) {
97-
SmallVector<stable_hash> Hashes;
98-
Hashes.emplace_back(Inst.getOpcode());
67+
void updateInstruction(const Instruction &Inst, bool DetailedHash) {
68+
hash(Inst.getOpcode());
9969

10070
if (!DetailedHash)
101-
return stable_hash_combine(Hashes);
71+
return;
10272

103-
Hashes.emplace_back(hashType(Inst.getType()));
73+
hashType(Inst.getType());
10474

10575
// Handle additional properties of specific instructions that cause
10676
// semantic differences in the IR.
10777
if (const auto *ComparisonInstruction = dyn_cast<CmpInst>(&Inst))
108-
Hashes.emplace_back(ComparisonInstruction->getPredicate());
78+
hash(ComparisonInstruction->getPredicate());
10979

11080
for (const auto &Op : Inst.operands())
111-
Hashes.emplace_back(hashOperand(Op));
112-
113-
return stable_hash_combine(Hashes);
81+
updateOperand(Op);
11482
}
11583

11684
// A function hash is calculated by considering only the number of arguments
@@ -129,17 +97,15 @@ class StructuralHashImpl {
12997
// expensive checks for pass modification status). When modifying this
13098
// function, most changes should be gated behind an option and enabled
13199
// selectively.
132-
void update(const Function &F) {
100+
void update(const Function &F, bool DetailedHash) {
133101
// Declarations don't affect analyses.
134102
if (F.isDeclaration())
135103
return;
136104

137-
SmallVector<stable_hash> Hashes;
138-
Hashes.emplace_back(Hash);
139-
Hashes.emplace_back(FunctionHeaderHash);
105+
hash(0x62642d6b6b2d6b72); // Function header
140106

141-
Hashes.emplace_back(F.isVarArg());
142-
Hashes.emplace_back(F.arg_size());
107+
hash(F.isVarArg());
108+
hash(F.arg_size());
143109

144110
SmallVector<const BasicBlock *, 8> BBs;
145111
SmallPtrSet<const BasicBlock *, 16> VisitedBBs;
@@ -152,17 +118,17 @@ class StructuralHashImpl {
152118
while (!BBs.empty()) {
153119
const BasicBlock *BB = BBs.pop_back_val();
154120

155-
Hashes.emplace_back(BlockHeaderHash);
121+
// This random value acts as a block header, as otherwise the partition of
122+
// opcodes into BBs wouldn't affect the hash, only the order of the
123+
// opcodes
124+
hash(45798);
156125
for (auto &Inst : *BB)
157-
Hashes.emplace_back(hashInstruction(Inst));
126+
updateInstruction(Inst, DetailedHash);
158127

159128
for (const BasicBlock *Succ : successors(BB))
160129
if (VisitedBBs.insert(Succ).second)
161130
BBs.push_back(Succ);
162131
}
163-
164-
// Update the combined hash in place.
165-
Hash = stable_hash_combine(Hashes);
166132
}
167133

168134
void update(const GlobalVariable &GV) {
@@ -171,35 +137,30 @@ class StructuralHashImpl {
171137
// we ignore anything with the `.llvm` prefix
172138
if (GV.isDeclaration() || GV.getName().starts_with("llvm."))
173139
return;
174-
SmallVector<stable_hash> Hashes;
175-
Hashes.emplace_back(Hash);
176-
Hashes.emplace_back(GlobalHeaderHash);
177-
Hashes.emplace_back(GV.getValueType()->getTypeID());
178-
179-
// Update the combined hash in place.
180-
Hash = stable_hash_combine(Hashes);
140+
hash(23456); // Global header
141+
hash(GV.getValueType()->getTypeID());
181142
}
182143

183-
void update(const Module &M) {
144+
void update(const Module &M, bool DetailedHash) {
184145
for (const GlobalVariable &GV : M.globals())
185146
update(GV);
186147
for (const Function &F : M)
187-
update(F);
148+
update(F, DetailedHash);
188149
}
189150

190151
uint64_t getHash() const { return Hash; }
191152
};
192153

193154
} // namespace
194155

195-
stable_hash llvm::StructuralHash(const Function &F, bool DetailedHash) {
196-
StructuralHashImpl H(DetailedHash);
197-
H.update(F);
156+
IRHash llvm::StructuralHash(const Function &F, bool DetailedHash) {
157+
StructuralHashImpl H;
158+
H.update(F, DetailedHash);
198159
return H.getHash();
199160
}
200161

201-
stable_hash llvm::StructuralHash(const Module &M, bool DetailedHash) {
202-
StructuralHashImpl H(DetailedHash);
203-
H.update(M);
162+
IRHash llvm::StructuralHash(const Module &M, bool DetailedHash) {
163+
StructuralHashImpl H;
164+
H.update(M, DetailedHash);
204165
return H.getHash();
205166
}

llvm/lib/Transforms/IPO/MergeFunctions.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,14 @@ namespace {
172172

173173
class FunctionNode {
174174
mutable AssertingVH<Function> F;
175-
stable_hash Hash;
175+
IRHash Hash;
176176

177177
public:
178178
// Note the hash is recalculated potentially multiple times, but it is cheap.
179179
FunctionNode(Function *F) : F(F), Hash(StructuralHash(*F)) {}
180180

181181
Function *getFunc() const { return F; }
182-
stable_hash getHash() const { return Hash; }
182+
IRHash getHash() const { return Hash; }
183183

184184
/// Replace the reference to the function F by the function G, assuming their
185185
/// implementations are equal.
@@ -420,7 +420,7 @@ bool MergeFunctions::runOnModule(Module &M) {
420420

421421
// All functions in the module, ordered by hash. Functions with a unique
422422
// hash value are easily eliminated.
423-
std::vector<std::pair<stable_hash, Function *>> HashedFuncs;
423+
std::vector<std::pair<IRHash, Function *>> HashedFuncs;
424424
for (Function &Func : M) {
425425
if (isEligibleForMerging(Func)) {
426426
HashedFuncs.push_back({StructuralHash(Func), &Func});

llvm/test/Transforms/MergeFunc/call-and-invoke-with-ranges.ll

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,6 @@ lpad:
6363
resume { ptr, i32 } zeroinitializer
6464
}
6565

66-
define i8 @call_with_same_range() {
67-
; CHECK-LABEL: @call_with_same_range
68-
; CHECK: tail call i8 @call_with_range
69-
bitcast i8 0 to i8
70-
%out = call i8 @dummy(), !range !0
71-
ret i8 %out
72-
}
73-
7466
define i8 @invoke_with_same_range() personality ptr undef {
7567
; CHECK-LABEL: @invoke_with_same_range()
7668
; CHECK: tail call i8 @invoke_with_range()
@@ -84,6 +76,15 @@ lpad:
8476
resume { ptr, i32 } zeroinitializer
8577
}
8678

79+
define i8 @call_with_same_range() {
80+
; CHECK-LABEL: @call_with_same_range
81+
; CHECK: tail call i8 @call_with_range
82+
bitcast i8 0 to i8
83+
%out = call i8 @dummy(), !range !0
84+
ret i8 %out
85+
}
86+
87+
8788
declare i8 @dummy();
8889
declare i32 @__gxx_personality_v0(...)
8990

0 commit comments

Comments
 (0)