@@ -53,17 +53,17 @@ class ObjectProjection {
53
53
}
54
54
};
55
55
56
- // / Represents the identity of a storage location being accessed.
56
+ // / Represents the identity of a storage object being accessed.
57
57
// /
58
58
// / AccessedStorage may be one of several kinds of "identified" storage
59
- // / locations , or may be valid, but Unidentified storage. An identified location
59
+ // / objects , or may be valid, but Unidentified storage. An identified object
60
60
// / is known to identify the base of the accessed storage, whether that is a
61
61
// / SILValue that produces the base address, or a variable
62
62
// / declaration. "Uniquely identified" storage refers to identified storage that
63
63
// / cannot be aliased. For example, local allocations are uniquely identified,
64
64
// / while global variables and class properties are not. Unidentified storage is
65
65
// / associated with a SILValue that produces the accessed address but has not
66
- // / been determined to be the base of a storage location . It may, for example,
66
+ // / been determined to be the base of a storage object . It may, for example,
67
67
// / be a SILPHIArgument.
68
68
// /
69
69
// / An invalid AccessedStorage object is marked Unidentified and contains an
@@ -72,19 +72,19 @@ class ObjectProjection {
72
72
// / SILVerification could allow the optimizer to aggressively assert that
73
73
// / AccessedStorage is always valid.
74
74
// /
75
- // / Note that the SILValue that represents a storage location is not
75
+ // / Note that the SILValue that represents a storage object is not
76
76
// / necessarilly an address type. It may instead be a SILBoxType.
77
77
// /
78
- // / AccessedStorage hashing and comparison is used to determine when two
79
- // / 'begin_access' instructions access the same or disjoint underlying
80
- // / locations .
78
+ // / AccessedStorage hashing and comparison (via DenseMapInfo) is used to
79
+ // / determine when two 'begin_access' instructions access the same or disjoint
80
+ // / underlying objects .
81
81
// /
82
- // / Equality guarantees that two AccessStorage values refer to the same
83
- // / memory if both values are valid.
82
+ // / `DenseMapInfo::isEqual()` guarantees that two AccessStorage values refer to
83
+ // / the same memory if both values are valid.
84
84
// /
85
- // / Inequality does not guarantee that two identified AccessStorage values
86
- // / distinct. Inequality does guarantee that two *uniquely* identified
87
- // / AccessStorage values are distinct.
85
+ // / `!DenseMapInfo::isEqual()` does not guarantee that two identified
86
+ // / AccessStorage values are distinct. Inequality does, however, guarantee that
87
+ // / two *uniquely* identified AccessStorage values are distinct.
88
88
class AccessedStorage {
89
89
public:
90
90
// / Enumerate over all valid begin_access bases. Clients can use a covered
@@ -111,26 +111,42 @@ class AccessedStorage {
111
111
// with the fields used within this class as a common prefix.
112
112
//
113
113
// This allows passes to embed analysis flags, and reserves enough space to
114
- // embed a unique access index.
114
+ // embed a unique index.
115
+ //
116
+ // AccessedStorageAnalysis defines an StorageAccessInfo object that maps each
117
+ // storage object within a function to its unique storage index and summary
118
+ // information of that storage object.
119
+ //
120
+ // AccessEnforcementOpts defines an AccessEnforcementOptsInfo object that maps
121
+ // each begin_access to its storage object, unique access index, and summary
122
+ // info for that access.
115
123
union {
116
124
uint64_t OpaqueBits;
117
- SWIFT_INLINE_BITFIELD_BASE (AccessedStorage, bitmax (NumKindBits, 8 ), Kind
118
- : bitmax (NumKindBits, 8 ));
125
+ SWIFT_INLINE_BITFIELD_BASE (AccessedStorage, bitmax (NumKindBits, 8 ),
126
+ Kind : bitmax (NumKindBits, 8 ));
119
127
120
- // Define bits for use in the AccessEnforcementOpts pass. Reserve the high
121
- // bit for a seenNestedConflict flag, which is the result of pass-specific
122
- // analysis. The remaning bits are sufficient to index all
128
+ // Define bits for use in AccessedStorageAnalysis. Each identified storage
129
+ // object is mapped to one instance of this subclass.
130
+ SWIFT_INLINE_BITFIELD_FULL (StorageAccessInfo, AccessedStorage,
131
+ 64 - NumAccessedStorageBits,
132
+ accessKind : NumSILAccessKindBits,
133
+ noNestedConflict : 1 ,
134
+ storageIndex : 64 - (NumAccessedStorageBits
135
+ + NumSILAccessKindBits
136
+ + 1 ));
137
+
138
+ // Define bits for use in the AccessEnforcementOpts pass. Each begin_access
139
+ // in the function is mapped to one instance of this subclass. Reserve a
140
+ // bit for a seenNestedConflict flag, which is the per-begin-access result
141
+ // of pass-specific analysis. The remaning bits are sufficient to index all
123
142
// begin_[unpaired_]access instructions.
124
143
//
125
- // `AccessEnforcementOpts` does not need to be a defined class. This macro
126
- // simply defines the pass-specific name "AccessEnforcementOptsBitfield".
127
- //
128
- // `AccessedStorage` identifies the AccessedStoredBitfield defined above,
144
+ // `AccessedStorage` refers to the AccessedStorageBitfield defined above,
129
145
// setting aside enough bits for common data.
130
146
SWIFT_INLINE_BITFIELD_FULL (AccessEnforcementOptsInfo, AccessedStorage,
131
147
64 - NumAccessedStorageBits,
132
- beginAccessIndex : 63 - NumAccessedStorageBits ,
133
- seenNestedConflict : 1 );
148
+ seenNestedConflict : 1 ,
149
+ beginAccessIndex : 63 - NumAccessedStorageBits );
134
150
} Bits;
135
151
136
152
private:
@@ -156,7 +172,7 @@ class AccessedStorage {
156
172
initKind (Class);
157
173
}
158
174
159
- // Return true if this is a valid storage location .
175
+ // Return true if this is a valid storage object .
160
176
operator bool () const { return getKind () != Unidentified || value; }
161
177
162
178
Kind getKind () const { return static_cast <Kind>(Bits.AccessedStorage .Kind ); }
@@ -205,6 +221,20 @@ class AccessedStorage {
205
221
}
206
222
}
207
223
224
+ bool isLocal () const {
225
+ switch (getKind ()) {
226
+ case Box:
227
+ case Stack:
228
+ return true ;
229
+ case Global:
230
+ case Class:
231
+ case Argument:
232
+ case Nested:
233
+ case Unidentified:
234
+ return false ;
235
+ }
236
+ }
237
+
208
238
bool isUniquelyIdentified () const {
209
239
switch (getKind ()) {
210
240
case Box:
@@ -231,6 +261,13 @@ class AccessedStorage {
231
261
232
262
void print (raw_ostream &os) const ;
233
263
void dump () const ;
264
+
265
+ private:
266
+ // Disable direct comparison because we allow subclassing with bitfields.
267
+ // Currently, we use DenseMapInfo to unique storage, which defines key
268
+ // equalilty only in terms of the base AccessedStorage class bits.
269
+ bool operator ==(const AccessedStorage &) const = delete ;
270
+ bool operator !=(const AccessedStorage &) const = delete ;
234
271
};
235
272
} // end namespace swift
236
273
@@ -300,9 +337,9 @@ namespace swift {
300
337
// / memory, return an AccessedStorage object that identifies the formal access.
301
338
// /
302
339
// / The returned AccessedStorage represents the best attempt to find the base of
303
- // / the storage location being accessed at `sourceAddr`. This may be a fully
340
+ // / the storage object being accessed at `sourceAddr`. This may be a fully
304
341
// / identified storage base of known kind, or a valid but Unidentified storage
305
- // / location , such as a SILPHIArgument.
342
+ // / object , such as a SILPHIArgument.
306
343
// /
307
344
// / This may return an invalid storage object if the address producer is not
308
345
// / recognized by a whitelist of recognizable access patterns. The result must
@@ -347,6 +384,14 @@ bool isPossibleFormalAccessBase(const AccessedStorage &storage, SILFunction *F);
347
384
void visitAccessedAddress (SILInstruction *I,
348
385
llvm::function_ref<void (Operand *)> visitor);
349
386
387
+ // / Perform a RAUW operation on begin_access with it's own source operand.
388
+ // / Then erase the begin_access and all associated end_access instructions.
389
+ // / Return an iterator to the following instruction.
390
+ // /
391
+ // / The caller should use this iterator rather than assuming that the
392
+ // / instruction following this begin_access was not also erased.
393
+ SILBasicBlock::iterator removeBeginAccess (BeginAccessInst *beginAccess);
394
+
350
395
} // end namespace swift
351
396
352
397
#endif
0 commit comments