@@ -122,8 +122,8 @@ template <> struct DenseMapInfo<swift::StorageAccessInfo> {
122
122
}
123
123
124
124
namespace swift {
125
- // / The per-function result of AccessedStorageAnalysis.
126
- // /
125
+ using AccessedStorageSet = llvm::SmallDenseSet<StorageAccessInfo, 8 >;
126
+
127
127
// / Records each unique AccessedStorage in a set of StorageAccessInfo
128
128
// / objects. Hashing and equality only sees the AccesedStorage data. The
129
129
// / additional StorageAccessInfo bits are recorded as results of this analysis.
@@ -133,28 +133,32 @@ namespace swift {
133
133
// / results, either because the call graph is unknown or the access sets are too
134
134
// / large. It does not imply that all accesses have Unidentified
135
135
// / AccessedStorage, which is never allowed for class or global access.
136
- class FunctionAccessedStorage {
137
- using AccessedStorageSet = llvm::SmallDenseSet<StorageAccessInfo, 8 >;
138
-
136
+ class AccessedStorageResult {
139
137
AccessedStorageSet storageAccessSet;
140
138
Optional<SILAccessKind> unidentifiedAccess;
141
139
142
140
public:
143
- FunctionAccessedStorage () {}
141
+ AccessedStorageResult () {}
144
142
145
143
// ---------------------------------------------------------------------------
146
144
// Accessing the results.
147
145
146
+ const AccessedStorageSet &getStorageSet () const { return storageAccessSet; }
147
+
148
+ bool isEmpty () const {
149
+ return storageAccessSet.empty () && !unidentifiedAccess;
150
+ }
151
+
148
152
bool hasUnidentifiedAccess () const { return unidentifiedAccess != None; }
149
153
150
154
// / Return true if the analysis has determined all accesses of otherStorage
151
155
// / have the [no_nested_conflict] flag set.
152
156
// /
153
- // / Only call this if there is no unidentifiedAccess in the function and the
157
+ // / Only call this if there is no unidentifiedAccess in the region and the
154
158
// / given storage is uniquely identified.
155
159
bool hasNoNestedConflict (const AccessedStorage &otherStorage) const ;
156
160
157
- // / Does any of the accesses represented by this FunctionAccessedStorage
161
+ // / Does any of the accesses represented by this AccessedStorageResult
158
162
// / object conflict with the given access kind and storage.
159
163
bool mayConflictWith (SILAccessKind otherAccessKind,
160
164
const AccessedStorage &otherStorage) const ;
@@ -181,6 +185,97 @@ class FunctionAccessedStorage {
181
185
unidentifiedAccess = SILAccessKind::Modify;
182
186
}
183
187
188
+ void setUnidentifiedAccess (SILAccessKind kind) { unidentifiedAccess = kind; }
189
+
190
+ // / Merge effects directly from \p RHS.
191
+ bool mergeFrom (const AccessedStorageResult &other);
192
+
193
+ // / Merge the effects represented in calleeAccess into this
194
+ // / FunctionAccessedStorage object. calleeAccess must correspond to at least
195
+ // / one callee at the apply site `fullApply`. Merging drops any local effects,
196
+ // / and translates parameter effects into effects on the caller-side
197
+ // / arguments.
198
+ // /
199
+ // / The full caller-side effects at a call site can be obtained with
200
+ // / AccessedStorageAnalysis::getCallSiteEffects().
201
+ bool mergeFromApply (const AccessedStorageResult &calleeAccess,
202
+ FullApplySite fullApply);
203
+
204
+ // / Record any access scopes entered by the given single SIL instruction. 'I'
205
+ // / must not be a FullApply; use mergeFromApply instead.
206
+ void analyzeInstruction (SILInstruction *I);
207
+
208
+ void print (raw_ostream &os) const ;
209
+ void dump () const ;
210
+
211
+ protected:
212
+ std::pair<AccessedStorageSet::iterator, bool >
213
+ insertStorageAccess (StorageAccessInfo storageAccess) {
214
+ storageAccess.setStorageIndex (storageAccessSet.size ());
215
+ return storageAccessSet.insert (storageAccess);
216
+ }
217
+
218
+ bool updateUnidentifiedAccess (SILAccessKind accessKind);
219
+
220
+ bool mergeAccesses (const AccessedStorageResult &other,
221
+ std::function<StorageAccessInfo(const StorageAccessInfo &)>
222
+ transformStorage);
223
+
224
+ template <typename B> void visitBeginAccess (B *beginAccess);
225
+ };
226
+ } // namespace swift
227
+
228
+ namespace swift {
229
+ // / The per-function result of AccessedStorageAnalysis.
230
+ class FunctionAccessedStorage {
231
+ AccessedStorageResult accessResult;
232
+
233
+ public:
234
+ FunctionAccessedStorage () {}
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // Accessing the results.
238
+
239
+ const AccessedStorageResult &getResult () const { return accessResult; }
240
+
241
+ bool hasUnidentifiedAccess () const {
242
+ return accessResult.hasUnidentifiedAccess ();
243
+ }
244
+
245
+ // / Return true if the analysis has determined all accesses of otherStorage
246
+ // / have the [no_nested_conflict] flag set.
247
+ // /
248
+ // / Only call this if there is no unidentifiedAccess in the function and the
249
+ // / given storage is uniquely identified.
250
+ bool hasNoNestedConflict (const AccessedStorage &otherStorage) const {
251
+ return accessResult.hasNoNestedConflict (otherStorage);
252
+ }
253
+
254
+ // / Does any of the accesses represented by this FunctionAccessedStorage
255
+ // / object conflict with the given access kind and storage.
256
+ bool mayConflictWith (SILAccessKind otherAccessKind,
257
+ const AccessedStorage &otherStorage) const {
258
+ return accessResult.mayConflictWith (otherAccessKind, otherStorage);
259
+ }
260
+
261
+ // / Raw access to the result for a given AccessedStorage location.
262
+ StorageAccessInfo
263
+ getStorageAccessInfo (const AccessedStorage &otherStorage) const {
264
+ return accessResult.getStorageAccessInfo (otherStorage);
265
+ }
266
+
267
+ // ---------------------------------------------------------------------------
268
+ // Constructing the results.
269
+
270
+ void clear () { accessResult.clear (); }
271
+
272
+ // / Return true if these effects are fully conservative.
273
+ bool hasWorstEffects () { return accessResult.hasWorstEffects (); }
274
+
275
+ // / Sets the most conservative effects, if we don't know anything about the
276
+ // / function.
277
+ void setWorstEffects () { accessResult.setWorstEffects (); }
278
+
184
279
// / Summarize the given function's effects using this FunctionAccessedStorage
185
280
// / object.
186
281
//
@@ -201,12 +296,14 @@ class FunctionAccessedStorage {
201
296
// /
202
297
// / TODO: Summarize ArraySemanticsCall accesses.
203
298
bool summarizeCall (FullApplySite fullApply) {
204
- assert (storageAccessSet. empty () && " expected uninitialized results." );
299
+ assert (accessResult. isEmpty () && " expected uninitialized results." );
205
300
return false ;
206
301
}
207
302
208
303
// / Merge effects directly from \p RHS.
209
- bool mergeFrom (const FunctionAccessedStorage &RHS);
304
+ bool mergeFrom (const FunctionAccessedStorage &RHS) {
305
+ return accessResult.mergeFrom (RHS.accessResult );
306
+ }
210
307
211
308
// / Merge the effects represented in calleeAccess into this
212
309
// / FunctionAccessedStorage object. calleeAccess must correspond to at least
@@ -217,31 +314,19 @@ class FunctionAccessedStorage {
217
314
// / The full caller-side effects at a call site can be obtained with
218
315
// / AccessedStorageAnalysis::getCallSiteEffects().
219
316
bool mergeFromApply (const FunctionAccessedStorage &calleeAccess,
220
- FullApplySite fullApply);
317
+ FullApplySite fullApply) {
318
+ return accessResult.mergeFromApply (calleeAccess.accessResult , fullApply);
319
+ }
221
320
222
321
// / Analyze the side-effects of a single SIL instruction \p I.
223
322
// / Visited callees are added to \p BottomUpOrder until \p RecursionDepth
224
323
// / reaches MaxRecursionDepth.
225
- void analyzeInstruction (SILInstruction *I);
226
-
227
- void print (raw_ostream &os) const ;
228
- void dump () const ;
229
-
230
- protected:
231
- std::pair<AccessedStorageSet::iterator, bool >
232
- insertStorageAccess (StorageAccessInfo storageAccess) {
233
- storageAccess.setStorageIndex (storageAccessSet.size ());
234
- return storageAccessSet.insert (storageAccess);
324
+ void analyzeInstruction (SILInstruction *I) {
325
+ accessResult.analyzeInstruction (I);
235
326
}
236
327
237
- bool updateUnidentifiedAccess (SILAccessKind accessKind);
238
-
239
- bool mergeAccesses (
240
- const FunctionAccessedStorage &other,
241
- std::function<StorageAccessInfo(const StorageAccessInfo &)>
242
- transformStorage);
243
-
244
- template <typename B> void visitBeginAccess (B *beginAccess);
328
+ void print (raw_ostream &os) const { accessResult.print (os); }
329
+ void dump () const { accessResult.dump (); }
245
330
};
246
331
247
332
// / Summarizes the dynamic accesses performed within a function and its
0 commit comments