Skip to content

Commit 547d87f

Browse files
committed
Add a UniqueAddressUses utility.
Analyze and classify the leaf uses of unique storage. Storage that has a unique set of roots within this function includes alloc_stack, alloc_box, exclusive argument, and global variables. All access to the storage within this function is derived from these roots. Gather the kinds of uses that are typically relevant to algorithms: - loads (including copies out of, not including inout args) - stores (including copies into and inout args) - destroys (of the entire aggregate) - debugUses (only populated when preserveDebugInfo == false)
1 parent 0836b6a commit 547d87f

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

include/swift/SIL/MemAccessUtils.h

+39
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,45 @@ bool visitAccessPathUses(AccessUseVisitor &visitor, AccessPath accessPath,
13241324

13251325
} // end namespace swift
13261326

1327+
//===----------------------------------------------------------------------===//
1328+
// MARK: UniqueAddressUses
1329+
//===----------------------------------------------------------------------===//
1330+
1331+
namespace swift {
1332+
1333+
/// Analyze and classify the leaf uses of unique storage.
1334+
///
1335+
/// Storage that has a unique set of roots within this function includes
1336+
/// alloc_stack, alloc_box, exclusive argument, and global variables. All access
1337+
/// to the storage within this function is derived from these roots.
1338+
///
1339+
/// Gather the kinds of uses that are typically relevant to algorithms:
1340+
/// - loads (including copies out of, not including inout args)
1341+
/// - stores (including copies into and inout args)
1342+
/// - destroys (of the entire aggregate)
1343+
/// - debugUses (only populated when preserveDebugInfo == false)
1344+
/// - unknownUses (e.g. address_to_pointer, box escape)
1345+
struct UniqueStorageUseVisitor {
1346+
static bool findUses(UniqueStorageUseVisitor &visitor);
1347+
1348+
SILFunction *function;
1349+
AccessStorage storage;
1350+
1351+
UniqueStorageUseVisitor(AccessStorage storage, SILFunction *function)
1352+
: function(function), storage(storage) {}
1353+
1354+
virtual ~UniqueStorageUseVisitor() = default;
1355+
1356+
virtual bool visitLoad(Operand *use) = 0;
1357+
virtual bool visitStore(Operand *use) = 0;
1358+
virtual bool visitDestroy(Operand *use) = 0;
1359+
virtual bool visitDealloc(Operand *use) = 0;
1360+
virtual bool visitDebugUse(Operand *use) = 0;
1361+
virtual bool visitUnknownUse(Operand *use) = 0;
1362+
};
1363+
1364+
} // namespace swift
1365+
13271366
//===----------------------------------------------------------------------===//
13281367
// MARK: Helper API for specific formal access patterns
13291368
//===----------------------------------------------------------------------===//

lib/SIL/Utils/MemAccessUtils.cpp

+104
Original file line numberDiff line numberDiff line change
@@ -1923,6 +1923,110 @@ bool AccessPath::collectUses(SmallVectorImpl<Operand *> &uses,
19231923
return visitAccessPathUses(collector, *this, function);
19241924
}
19251925

1926+
//===----------------------------------------------------------------------===//
1927+
// MARK: UniqueStorageUseVisitor
1928+
//===----------------------------------------------------------------------===//
1929+
1930+
struct GatherUniqueStorageUses : public AccessUseVisitor {
1931+
UniqueStorageUseVisitor &visitor;
1932+
1933+
GatherUniqueStorageUses(UniqueStorageUseVisitor &visitor)
1934+
: AccessUseVisitor(AccessUseType::Overlapping,
1935+
NestedAccessType::IgnoreAccessBegin),
1936+
visitor(visitor) {}
1937+
1938+
bool visitUse(Operand *use, AccessUseType useTy) override;
1939+
};
1940+
1941+
bool UniqueStorageUseVisitor::findUses(UniqueStorageUseVisitor &visitor) {
1942+
assert(visitor.storage.isUniquelyIdentified());
1943+
1944+
GatherUniqueStorageUses gather(visitor);
1945+
return visitAccessStorageUses(gather, visitor.storage, visitor.function);
1946+
}
1947+
1948+
bool GatherUniqueStorageUses::visitUse(Operand *use, AccessUseType useTy) {
1949+
unsigned operIdx = use->getOperandNumber();
1950+
auto *user = use->getUser();
1951+
assert(!user->isTypeDependentOperand(*use));
1952+
1953+
// TODO: handle non-escaping partial-applies just like a full apply. The
1954+
// address uses are the points where the partial apply is invoked.
1955+
if (FullApplySite apply = FullApplySite::isa(user)) {
1956+
switch (apply.getArgumentConvention(*use)) {
1957+
case SILArgumentConvention::Indirect_Inout:
1958+
case SILArgumentConvention::Indirect_InoutAliasable:
1959+
case SILArgumentConvention::Indirect_Out:
1960+
visitor.visitStore(use);
1961+
break;
1962+
case SILArgumentConvention::Indirect_In_Guaranteed:
1963+
case SILArgumentConvention::Indirect_In:
1964+
case SILArgumentConvention::Indirect_In_Constant:
1965+
visitor.visitLoad(use);
1966+
break;
1967+
case SILArgumentConvention::Direct_Unowned:
1968+
case SILArgumentConvention::Direct_Owned:
1969+
case SILArgumentConvention::Direct_Guaranteed:
1970+
// most likely an escape of a box
1971+
visitor.visitUnknownUse(use);
1972+
break;
1973+
}
1974+
return true;
1975+
}
1976+
switch (user->getKind()) {
1977+
case SILInstructionKind::DestroyAddrInst:
1978+
case SILInstructionKind::DestroyValueInst:
1979+
if (useTy == AccessUseType::Exact) {
1980+
visitor.visitDestroy(use);
1981+
return true;
1982+
}
1983+
visitor.visitUnknownUse(use);
1984+
return true;
1985+
1986+
case SILInstructionKind::DebugValueInst:
1987+
visitor.visitDebugUse(use);
1988+
return true;
1989+
1990+
case SILInstructionKind::LoadInst:
1991+
case SILInstructionKind::LoadWeakInst:
1992+
case SILInstructionKind::LoadUnownedInst:
1993+
case SILInstructionKind::ExistentialMetatypeInst:
1994+
visitor.visitLoad(use);
1995+
return true;
1996+
1997+
case SILInstructionKind::StoreInst:
1998+
case SILInstructionKind::StoreWeakInst:
1999+
case SILInstructionKind::StoreUnownedInst:
2000+
if (operIdx == CopyLikeInstruction::Dest) {
2001+
visitor.visitStore(use);
2002+
return true;
2003+
}
2004+
break;
2005+
2006+
case SILInstructionKind::InjectEnumAddrInst:
2007+
visitor.visitStore(use);
2008+
return true;
2009+
2010+
case SILInstructionKind::CopyAddrInst:
2011+
if (operIdx == CopyLikeInstruction::Dest) {
2012+
visitor.visitStore(use);
2013+
return true;
2014+
}
2015+
assert(operIdx == CopyLikeInstruction::Src);
2016+
visitor.visitLoad(use);
2017+
return true;
2018+
2019+
case SILInstructionKind::DeallocStackInst:
2020+
visitor.visitDealloc(use);
2021+
return true;
2022+
2023+
default:
2024+
break;
2025+
}
2026+
visitor.visitUnknownUse(use);
2027+
return true;
2028+
}
2029+
19262030
//===----------------------------------------------------------------------===//
19272031
// MARK: Helper API for specific formal access patterns
19282032
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)