@@ -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