@@ -24,93 +24,61 @@ namespace {
24
24
// by the MergeFunctions pass.
25
25
26
26
class StructuralHashImpl {
27
- stable_hash Hash = 4 ;
27
+ uint64_t Hash = 4 ;
28
28
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); }
36
30
37
31
// This will produce different values on 32-bit and 64-bit systens as
38
32
// hash_combine returns a size_t. However, this is only used for
39
33
// detailed hashing which, in-tree, only needs to distinguish between
40
34
// 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));
44
37
}
45
38
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 ());
49
41
if (ValueType->isIntegerTy ())
50
- Hashes.emplace_back (ValueType->getIntegerBitWidth ());
51
- return stable_hash_combine (Hashes);
42
+ hash (ValueType->getIntegerBitWidth ());
52
43
}
53
44
54
45
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)) {
66
60
// Hashing the name will be deterministic as LLVM's hashing infrastructure
67
61
// has explicit support for hashing strings and will not simply hash
68
62
// the pointer.
69
- Hashes. emplace_back ( hashArbitaryType (Func->getName () ));
63
+ hashArbitaryType (Func->getName ());
70
64
}
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);
87
65
}
88
66
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 ());
99
69
100
70
if (!DetailedHash)
101
- return stable_hash_combine (Hashes) ;
71
+ return ;
102
72
103
- Hashes. emplace_back ( hashType (Inst.getType () ));
73
+ hashType (Inst.getType ());
104
74
105
75
// Handle additional properties of specific instructions that cause
106
76
// semantic differences in the IR.
107
77
if (const auto *ComparisonInstruction = dyn_cast<CmpInst>(&Inst))
108
- Hashes. emplace_back (ComparisonInstruction->getPredicate ());
78
+ hash (ComparisonInstruction->getPredicate ());
109
79
110
80
for (const auto &Op : Inst.operands ())
111
- Hashes.emplace_back (hashOperand (Op));
112
-
113
- return stable_hash_combine (Hashes);
81
+ updateOperand (Op);
114
82
}
115
83
116
84
// A function hash is calculated by considering only the number of arguments
@@ -129,17 +97,15 @@ class StructuralHashImpl {
129
97
// expensive checks for pass modification status). When modifying this
130
98
// function, most changes should be gated behind an option and enabled
131
99
// selectively.
132
- void update (const Function &F) {
100
+ void update (const Function &F, bool DetailedHash ) {
133
101
// Declarations don't affect analyses.
134
102
if (F.isDeclaration ())
135
103
return ;
136
104
137
- SmallVector<stable_hash> Hashes;
138
- Hashes.emplace_back (Hash);
139
- Hashes.emplace_back (FunctionHeaderHash);
105
+ hash (0x62642d6b6b2d6b72 ); // Function header
140
106
141
- Hashes. emplace_back (F.isVarArg ());
142
- Hashes. emplace_back (F.arg_size ());
107
+ hash (F.isVarArg ());
108
+ hash (F.arg_size ());
143
109
144
110
SmallVector<const BasicBlock *, 8 > BBs;
145
111
SmallPtrSet<const BasicBlock *, 16 > VisitedBBs;
@@ -152,17 +118,17 @@ class StructuralHashImpl {
152
118
while (!BBs.empty ()) {
153
119
const BasicBlock *BB = BBs.pop_back_val ();
154
120
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 );
156
125
for (auto &Inst : *BB)
157
- Hashes. emplace_back ( hashInstruction ( Inst) );
126
+ updateInstruction ( Inst, DetailedHash );
158
127
159
128
for (const BasicBlock *Succ : successors (BB))
160
129
if (VisitedBBs.insert (Succ).second )
161
130
BBs.push_back (Succ);
162
131
}
163
-
164
- // Update the combined hash in place.
165
- Hash = stable_hash_combine (Hashes);
166
132
}
167
133
168
134
void update (const GlobalVariable &GV) {
@@ -171,35 +137,30 @@ class StructuralHashImpl {
171
137
// we ignore anything with the `.llvm` prefix
172
138
if (GV.isDeclaration () || GV.getName ().starts_with (" llvm." ))
173
139
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 ());
181
142
}
182
143
183
- void update (const Module &M) {
144
+ void update (const Module &M, bool DetailedHash ) {
184
145
for (const GlobalVariable &GV : M.globals ())
185
146
update (GV);
186
147
for (const Function &F : M)
187
- update (F);
148
+ update (F, DetailedHash );
188
149
}
189
150
190
151
uint64_t getHash () const { return Hash; }
191
152
};
192
153
193
154
} // namespace
194
155
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 );
198
159
return H.getHash ();
199
160
}
200
161
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 );
204
165
return H.getHash ();
205
166
}
0 commit comments