Skip to content

Commit f6b32ae

Browse files
committed
Add AccessedStorageWithBase to conviently recover the base's VarDecl
1 parent b272dc5 commit f6b32ae

File tree

4 files changed

+59
-26
lines changed

4 files changed

+59
-26
lines changed

include/swift/SIL/MemAccessUtils.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ class AccessedStorage {
507507
llvm_unreachable("unhandled kind");
508508
}
509509

510-
/// Return trye if the given access is guaranteed to be within a heap object.
510+
/// Return true if the given access is guaranteed to be within a heap object.
511511
bool isObjectAccess() const {
512512
return getKind() == Class || getKind() == Tail;
513513
}
@@ -696,6 +696,28 @@ template <> struct DenseMapInfo<swift::AccessedStorage> {
696696

697697
namespace swift {
698698

699+
/// For convenience, encapsulate and AccessedStorage value along with its
700+
/// accessed base address.
701+
struct AccessedStorageWithBase {
702+
AccessedStorage storage;
703+
// The base of the formal access. For class storage, it is the
704+
// ref_element_addr. For global storage it is the global_addr or initializer
705+
// apply. For other storage, it is the same as accessPath.getRoot().
706+
//
707+
// Base may be invalid for global_addr -> address_to_pointer -> phi patterns.
708+
// FIXME: add a structural requirement to SIL so base is always valid in OSSA.
709+
SILValue base;
710+
711+
AccessedStorageWithBase(AccessedStorage storage, SILValue base)
712+
: storage(storage), base(base) {}
713+
714+
/// Identical to AccessedStorage::compute but preserves the access base.
715+
static AccessedStorageWithBase compute(SILValue sourceAddress);
716+
717+
/// Identical to AccessedStorage::computeInScope but preserves the base.
718+
static AccessedStorageWithBase computeInScope(SILValue sourceAddress);
719+
};
720+
699721
/// Return an AccessedStorage value that identifies formally accessed storage
700722
/// for \p beginAccess, considering any outer access scope as having distinct
701723
/// storage from this access scope. This is useful for exclusivity checking

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -714,16 +714,26 @@ class FindAccessedStorageVisitor
714714

715715
} // end anonymous namespace
716716

717-
AccessedStorage AccessedStorage::compute(SILValue sourceAddress) {
717+
AccessedStorageWithBase
718+
AccessedStorageWithBase::compute(SILValue sourceAddress) {
718719
FindAccessedStorageVisitor visitor(NestedAccessType::IgnoreAccessBegin);
719720
visitor.findStorage(sourceAddress);
720-
return visitor.getStorage();
721+
return {visitor.getStorage(), visitor.getBase()};
721722
}
722723

723-
AccessedStorage AccessedStorage::computeInScope(SILValue sourceAddress) {
724+
AccessedStorageWithBase
725+
AccessedStorageWithBase::computeInScope(SILValue sourceAddress) {
724726
FindAccessedStorageVisitor visitor(NestedAccessType::StopAtAccessBegin);
725727
visitor.findStorage(sourceAddress);
726-
return visitor.getStorage();
728+
return {visitor.getStorage(), visitor.getBase()};
729+
}
730+
731+
AccessedStorage AccessedStorage::compute(SILValue sourceAddress) {
732+
return AccessedStorageWithBase::compute(sourceAddress).storage;
733+
}
734+
735+
AccessedStorage AccessedStorage::computeInScope(SILValue sourceAddress) {
736+
return AccessedStorageWithBase::computeInScope(sourceAddress).storage;
727737
}
728738

729739
//===----------------------------------------------------------------------===//

lib/SIL/Verifier/LoadBorrowInvalidationChecker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,11 @@ bool LoadBorrowNeverInvalidatedAnalysis::
454454
bool LoadBorrowNeverInvalidatedAnalysis::isNeverInvalidated(
455455
LoadBorrowInst *lbi) {
456456

457-
SILValue address = getAccessBegin(lbi->getOperand());
457+
SILValue address = getAccessScope(lbi->getOperand());
458458
if (!address)
459459
return false;
460460

461-
auto storage = findAccessedStorage(address);
461+
auto storage = AccessedStorage::compute(address);
462462
// If we couldn't find an access storage, return that we are assumed to write.
463463
if (!storage) {
464464
llvm::errs() << "Couldn't compute access storage?!\n";

lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,21 @@ using llvm::DenseMap;
6767
using llvm::SmallDenseSet;
6868

6969
// Get the VarDecl that represents the DisjointAccessLocation for the given
70-
// AccessedStorage. Returns nullptr for any storage that can't be partitioned
71-
// into a disjoint location.
70+
// storage and access base. Returns nullptr for any storage that can't be
71+
// partitioned into a disjoint location.
7272
//
73-
// identifyFormalAccess may only return Unidentified storage for a global
74-
// variable access if the global is defined in a different module.
75-
//
76-
// WARNING: Retrieving VarDecl for Class access is not constant time.
77-
const VarDecl *getDisjointAccessLocation(const AccessedStorage &storage) {
73+
// Global storage is expected to be disjoint because identifyFormalAccess may
74+
// only return Unidentified storage for a global variable access if the global
75+
// is defined in a different module.
76+
const VarDecl *
77+
getDisjointAccessLocation(AccessedStorageWithBase storageAndBase) {
78+
auto storage = storageAndBase.storage;
7879
switch (storage.getKind()) {
7980
case AccessedStorage::Global:
80-
// A global variable may return a null decl. These variables are
81-
// implementation details that aren't formally accessed.
82-
return storage.getGlobal()->getDecl();
83-
case AccessedStorage::Class: {
84-
return cast<VarDecl>(storage.getDecl());
85-
}
81+
case AccessedStorage::Class:
82+
// Class and Globals are always a VarDecl, but the global decl may have a
83+
// null value for global_addr -> phi.
84+
return cast_or_null<VarDecl>(storage.getDecl(storageAndBase.base));
8685
case AccessedStorage::Box:
8786
case AccessedStorage::Stack:
8887
case AccessedStorage::Tail:
@@ -169,15 +168,17 @@ void GlobalAccessRemoval::perform() {
169168

170169
void GlobalAccessRemoval::visitInstruction(SILInstruction *I) {
171170
if (auto *BAI = dyn_cast<BeginAccessInst>(I)) {
172-
auto storage = AccessedStorage::compute(BAI->getSource());
173-
const VarDecl *decl = getDisjointAccessLocation(storage);
174-
recordAccess(BAI, decl, storage.getKind(), BAI->hasNoNestedConflict());
171+
auto storageAndBase = AccessedStorageWithBase::compute(BAI->getSource());
172+
const VarDecl *decl = getDisjointAccessLocation(storageAndBase);
173+
recordAccess(BAI, decl, storageAndBase.storage.getKind(),
174+
BAI->hasNoNestedConflict());
175175
return;
176176
}
177177
if (auto *BUAI = dyn_cast<BeginUnpairedAccessInst>(I)) {
178-
auto storage = AccessedStorage::compute(BUAI->getSource());
179-
const VarDecl *decl = getDisjointAccessLocation(storage);
180-
recordAccess(BUAI, decl, storage.getKind(), BUAI->hasNoNestedConflict());
178+
auto storageAndBase = AccessedStorageWithBase::compute(BUAI->getSource());
179+
const VarDecl *decl = getDisjointAccessLocation(storageAndBase);
180+
recordAccess(BUAI, decl, storageAndBase.storage.getKind(),
181+
BUAI->hasNoNestedConflict());
181182
return;
182183
}
183184
if (auto *KPI = dyn_cast<KeyPathInst>(I)) {

0 commit comments

Comments
 (0)