Skip to content

Commit 71b012e

Browse files
authored
Merge pull request #23190 from atrick/cleanup-accessopts
Cleanup/fix AccessEnforcementOpts
2 parents 168c4f9 + 462df6c commit 71b012e

File tree

4 files changed

+546
-553
lines changed

4 files changed

+546
-553
lines changed

include/swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h

Lines changed: 114 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ template <> struct DenseMapInfo<swift::StorageAccessInfo> {
122122
}
123123

124124
namespace swift {
125-
/// The per-function result of AccessedStorageAnalysis.
126-
///
125+
using AccessedStorageSet = llvm::SmallDenseSet<StorageAccessInfo, 8>;
126+
127127
/// Records each unique AccessedStorage in a set of StorageAccessInfo
128128
/// objects. Hashing and equality only sees the AccesedStorage data. The
129129
/// additional StorageAccessInfo bits are recorded as results of this analysis.
@@ -133,28 +133,32 @@ namespace swift {
133133
/// results, either because the call graph is unknown or the access sets are too
134134
/// large. It does not imply that all accesses have Unidentified
135135
/// AccessedStorage, which is never allowed for class or global access.
136-
class FunctionAccessedStorage {
137-
using AccessedStorageSet = llvm::SmallDenseSet<StorageAccessInfo, 8>;
138-
136+
class AccessedStorageResult {
139137
AccessedStorageSet storageAccessSet;
140138
Optional<SILAccessKind> unidentifiedAccess;
141139

142140
public:
143-
FunctionAccessedStorage() {}
141+
AccessedStorageResult() {}
144142

145143
// ---------------------------------------------------------------------------
146144
// Accessing the results.
147145

146+
const AccessedStorageSet &getStorageSet() const { return storageAccessSet; }
147+
148+
bool isEmpty() const {
149+
return storageAccessSet.empty() && !unidentifiedAccess;
150+
}
151+
148152
bool hasUnidentifiedAccess() const { return unidentifiedAccess != None; }
149153

150154
/// Return true if the analysis has determined all accesses of otherStorage
151155
/// have the [no_nested_conflict] flag set.
152156
///
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
154158
/// given storage is uniquely identified.
155159
bool hasNoNestedConflict(const AccessedStorage &otherStorage) const;
156160

157-
/// Does any of the accesses represented by this FunctionAccessedStorage
161+
/// Does any of the accesses represented by this AccessedStorageResult
158162
/// object conflict with the given access kind and storage.
159163
bool mayConflictWith(SILAccessKind otherAccessKind,
160164
const AccessedStorage &otherStorage) const;
@@ -181,6 +185,97 @@ class FunctionAccessedStorage {
181185
unidentifiedAccess = SILAccessKind::Modify;
182186
}
183187

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+
184279
/// Summarize the given function's effects using this FunctionAccessedStorage
185280
/// object.
186281
//
@@ -201,12 +296,14 @@ class FunctionAccessedStorage {
201296
///
202297
/// TODO: Summarize ArraySemanticsCall accesses.
203298
bool summarizeCall(FullApplySite fullApply) {
204-
assert(storageAccessSet.empty() && "expected uninitialized results.");
299+
assert(accessResult.isEmpty() && "expected uninitialized results.");
205300
return false;
206301
}
207302

208303
/// 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+
}
210307

211308
/// Merge the effects represented in calleeAccess into this
212309
/// FunctionAccessedStorage object. calleeAccess must correspond to at least
@@ -217,31 +314,19 @@ class FunctionAccessedStorage {
217314
/// The full caller-side effects at a call site can be obtained with
218315
/// AccessedStorageAnalysis::getCallSiteEffects().
219316
bool mergeFromApply(const FunctionAccessedStorage &calleeAccess,
220-
FullApplySite fullApply);
317+
FullApplySite fullApply) {
318+
return accessResult.mergeFromApply(calleeAccess.accessResult, fullApply);
319+
}
221320

222321
/// Analyze the side-effects of a single SIL instruction \p I.
223322
/// Visited callees are added to \p BottomUpOrder until \p RecursionDepth
224323
/// 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);
235326
}
236327

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(); }
245330
};
246331

247332
/// Summarizes the dynamic accesses performed within a function and its

0 commit comments

Comments
 (0)