13
13
#ifndef SWIFT_SILANALYSIS_ALIASANALYSIS_H
14
14
#define SWIFT_SILANALYSIS_ALIASANALYSIS_H
15
15
16
+ #include " swift/Basic/ValueEnumerator.h"
16
17
#include " swift/SIL/SILInstruction.h"
17
18
#include " swift/SILAnalysis/Analysis.h"
18
19
#include " swift/SILAnalysis/SideEffectAnalysis.h"
19
20
#include " llvm/ADT/DenseMap.h"
20
21
22
+ namespace {
23
+ // / A cache for AliasAnalysis.
24
+ // / This struct represents the argument list to the method 'alias'.
25
+ // / The two SILValue pointers are mapped to size_t indices because we need
26
+ // / an efficient way to invalidate them (the mechanism is described below).
27
+ // / The Type arguments are translated to void* because their
28
+ // / underlying storage is opaque pointers that never goes away.
29
+ struct AliasKeyTy {
30
+ // The SILValue pair:
31
+ size_t V1, V2;
32
+ unsigned ResultNo1, ResultNo2;
33
+ // The TBAAType pair:
34
+ void *T1, *T2;
35
+ };
36
+ }
37
+
21
38
namespace swift {
22
39
23
40
class SILValue ;
@@ -69,6 +86,16 @@ class AliasAnalysis : public SILAnalysis {
69
86
// / never change.
70
87
llvm::DenseMap<TBAACacheKey, bool > TypesMayAliasCache;
71
88
89
+ // / AliasAnalysis value cache.
90
+ // / The alias() method uses this map to cache queries.
91
+ llvm::DenseMap<AliasKeyTy, AliasResult> AliasCache;
92
+
93
+ // / The AliasAnalysis cache can't directly map a pair of ValueBase pointers
94
+ // / to alias results because we'd like to be able to remove deleted pointers
95
+ // / without having to scan the whole map. So, instead of storing pointers
96
+ // / we map pointers to indices and store the indices.
97
+ ValueEnumerator<ValueBase*> ValueBaseToIndex;
98
+
72
99
using MemoryBehavior = SILInstruction::MemoryBehavior;
73
100
74
101
AliasResult aliasAddressProjection (SILValue V1, SILValue V2,
@@ -83,7 +110,12 @@ class AliasAnalysis : public SILAnalysis {
83
110
bool typesMayAlias (SILType T1, SILType T2);
84
111
85
112
86
- virtual void handleDeleteNotification (ValueBase *I) override { }
113
+ virtual void handleDeleteNotification (ValueBase *I) override {
114
+ // The pointer I is going away. We can't scan the whole cache and remove
115
+ // all of the occurrences of the pointer. Instead we remove the pointer
116
+ // from the cache the translates pointers to indices.
117
+ ValueBaseToIndex.invalidateValue (I);
118
+ }
87
119
88
120
public:
89
121
AliasAnalysis (SILModule *M) :
@@ -172,14 +204,22 @@ class AliasAnalysis : public SILAnalysis {
172
204
return MemoryBehavior::MayHaveSideEffects == B;
173
205
}
174
206
175
- virtual void invalidate (SILAnalysis::InvalidationKind K) override { }
207
+ // / Encodes the alias query as a AliasKeyTy.
208
+ // / The parameters to this function are identical to the parameters of alias()
209
+ // / and this method serializes them into a key for the alias analysis cache.
210
+ AliasKeyTy toAliasKey (SILValue V1, SILValue V2, SILType Type1, SILType Type2);
211
+
212
+ virtual void invalidate (SILAnalysis::InvalidationKind K) override {
213
+ AliasCache.clear ();
214
+ }
176
215
177
216
virtual void invalidate (SILFunction *,
178
217
SILAnalysis::InvalidationKind K) override {
179
218
invalidate (K);
180
219
}
181
220
};
182
221
222
+
183
223
llvm::raw_ostream &operator <<(llvm::raw_ostream &OS,
184
224
AliasAnalysis::AliasResult R);
185
225
@@ -193,4 +233,34 @@ bool isLetPointer(SILValue V);
193
233
194
234
} // end namespace swift
195
235
236
+ namespace llvm {
237
+ template <> struct llvm ::DenseMapInfo<AliasKeyTy> {
238
+ static inline AliasKeyTy getEmptyKey () {
239
+ return {0 , 0 , 0 , 0 , nullptr , nullptr };
240
+ }
241
+ static inline AliasKeyTy getTombstoneKey () {
242
+ auto Allone = std::numeric_limits<size_t >::max ();
243
+ return {Allone, Allone, 0xff , 0xff , nullptr , nullptr };
244
+ }
245
+ static unsigned getHashValue (const AliasKeyTy Val) {
246
+ unsigned H = 0 ;
247
+ H ^= DenseMapInfo<size_t >::getHashValue (Val.V1 );
248
+ H ^= DenseMapInfo<size_t >::getHashValue (Val.V2 );
249
+ H ^= DenseMapInfo<unsigned >::getHashValue (Val.ResultNo1 );
250
+ H ^= DenseMapInfo<unsigned >::getHashValue (Val.ResultNo2 );
251
+ H ^= DenseMapInfo<void *>::getHashValue (Val.T1 );
252
+ H ^= DenseMapInfo<void *>::getHashValue (Val.T2 );
253
+ return H;
254
+ }
255
+ static bool isEqual (const AliasKeyTy LHS, const AliasKeyTy RHS) {
256
+ return LHS.V1 == RHS.V1 &&
257
+ LHS.V2 == RHS.V2 &&
258
+ LHS.ResultNo1 == RHS.ResultNo1 &&
259
+ LHS.ResultNo2 == RHS.ResultNo2 &&
260
+ LHS.T1 == RHS.T1 &&
261
+ LHS.T2 == RHS.T2 ;
262
+ }
263
+ };
264
+ }
265
+
196
266
#endif
0 commit comments