Skip to content

Commit 81c0d09

Browse files
authored
Merge pull request #36046 from atrick/fix-escape
Fix EscapeAnalysis::mayReleaseContent
2 parents 28f8d9e + f6624e3 commit 81c0d09

File tree

8 files changed

+522
-84
lines changed

8 files changed

+522
-84
lines changed

include/swift/SILOptimizer/Analysis/EscapeAnalysis.h

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,8 +989,13 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
989989
/// The allocator for the connection graphs in Function2ConGraph.
990990
llvm::SpecificBumpPtrAllocator<FunctionInfo> Allocator;
991991

992+
// TODO: Use per-function caches, at least for Resilient types, to use Maximal
993+
// expansion.
994+
992995
/// Cache for isPointer().
993996
PointerKindCache pointerKindCache;
997+
/// Cache for checking the aggregate pointerness of class properties.
998+
PointerKindCache classPropertiesKindCache;
994999

9951000
SILModule *M;
9961001

@@ -1014,6 +1019,12 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
10141019

10151020
PointerKind findCachedPointerKind(SILType Ty, const SILFunction &F) const;
10161021

1022+
PointerKind findClassPropertiesPointerKind(SILType Ty,
1023+
const SILFunction &F) const;
1024+
1025+
PointerKind findCachedClassPropertiesKind(SILType Ty,
1026+
const SILFunction &F) const;
1027+
10171028
// Returns true if the type \p Ty must be a reference or must transitively
10181029
// contain a reference and no other pointer or address type.
10191030
bool hasReferenceOnly(SILType Ty, const SILFunction &F) const {
@@ -1114,6 +1125,10 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
11141125
bool canEscapeToUsePoint(SILValue value, SILInstruction *usePoint,
11151126
ConnectionGraph *conGraph);
11161127

1128+
/// Common implementation for mayReleaseReferenceContent and
1129+
/// mayReleaseAddressContent.
1130+
bool mayReleaseContent(SILValue releasedPtr, SILValue liveAddress);
1131+
11171132
friend struct ::CGForDotView;
11181133

11191134
public:
@@ -1163,8 +1178,38 @@ class EscapeAnalysis : public BottomUpIPAnalysis {
11631178
bool canEscapeTo(SILValue V, DestroyValueInst *DVI);
11641179

11651180
/// Return true if \p releasedReference deinitialization may release memory
1166-
/// pointed to by \p accessedAddress.
1167-
bool mayReleaseContent(SILValue releasedReference, SILValue accessedAddress);
1181+
/// pointed to by \p liveAddress.
1182+
///
1183+
/// This determines whether a direct release of \p releasedReference, such as
1184+
/// destroy_value or strong_release may release memory pointed to by \p
1185+
/// liveAddress. It can also be used to determine whether passing a
1186+
/// reference-type call argument may release \p liveAddress.
1187+
///
1188+
/// This does not distinguish between a call that releases \p
1189+
/// releasedReference directly, vs. a call that releases one of indirect
1190+
/// references.The side effects of releasing any object reachable from \p
1191+
/// releasedReference are a strict subset of the side effects of directly
1192+
/// releasing the parent reference.
1193+
bool mayReleaseReferenceContent(SILValue releasedReference,
1194+
SILValue liveAddress) {
1195+
assert(!releasedReference->getType().isAddress() &&
1196+
"expected a potentially nontrivial value, not an address");
1197+
return mayReleaseContent(releasedReference, liveAddress);
1198+
}
1199+
1200+
/// Return true if accessing memory at \p accessedAddress may release memory
1201+
/// pointed to by \p liveAddress.
1202+
///
1203+
/// This makes sense for determining whether accessing indirect call argument
1204+
/// \p accessedAddress may release memory pointed to by \p liveAddress.
1205+
///
1206+
/// "Access" to the memory can be any release of a reference pointed to by \p
1207+
/// accessedAddress, so '@in' and '@inout' are handled the same.
1208+
bool mayReleaseAddressContent(SILValue accessedAddress,
1209+
SILValue liveAddress) {
1210+
assert(accessedAddress->getType().isAddress() && "expected an address");
1211+
return mayReleaseContent(accessedAddress, liveAddress);
1212+
}
11681213

11691214
/// Returns true if the pointers \p V1 and \p V2 can possibly point to the
11701215
/// same memory.

lib/SILOptimizer/Analysis/AliasAnalysis.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -723,8 +723,18 @@ bool AliasAnalysis::canApplyDecrementRefCount(FullApplySite FAS, SILValue Ptr) {
723723
if (ArgEffect.mayRelease()) {
724724
// The function may release this argument, so check if the pointer can
725725
// escape to it.
726-
if (EA->mayReleaseContent(FAS.getArgument(Idx), Ptr))
727-
return true;
726+
auto arg = FAS.getArgument(Idx);
727+
if (arg->getType().isAddress()) {
728+
// Handle indirect argument as if they are a release to any references
729+
// pointed to by the argument's address.
730+
if (EA->mayReleaseAddressContent(arg, Ptr))
731+
return true;
732+
} else {
733+
// Handle direct arguments as if they are a direct release of the
734+
// reference (just like a destroy_value).
735+
if (EA->mayReleaseReferenceContent(arg, Ptr))
736+
return true;
737+
}
728738
}
729739
}
730740
return false;
@@ -740,12 +750,18 @@ bool AliasAnalysis::canBuiltinDecrementRefCount(BuiltinInst *BI, SILValue Ptr) {
740750
continue;
741751

742752
// A builtin can only release an object if it can escape to one of the
743-
// builtin's arguments. 'EscapeAnalysis::mayReleaseContent()' expects 'Arg'
744-
// to be an owned reference and disallows addresses. Conservatively handle
745-
// address type arguments as and conservatively treat all other values
746-
// potential owned references.
747-
if (Arg->getType().isAddress() || EA->mayReleaseContent(Arg, Ptr))
748-
return true;
753+
// builtin's arguments.
754+
if (Arg->getType().isAddress()) {
755+
// Handle indirect argument as if they are a release to any references
756+
// pointed to by the argument's address.
757+
if (EA->mayReleaseAddressContent(Arg, Ptr))
758+
return true;
759+
} else {
760+
// Handle direct arguments as if they are a direct release of the
761+
// reference (just like a destroy_value).
762+
if (EA->mayReleaseReferenceContent(Arg, Ptr))
763+
return true;
764+
}
749765
}
750766
return false;
751767
}
@@ -788,7 +804,7 @@ bool AliasAnalysis::mayValueReleaseInterfereWithInstruction(
788804
// accessedPointer. Access to any objects beyond the first released refcounted
789805
// object are irrelevant--they must already have sufficient refcount that they
790806
// won't be released when releasing Ptr.
791-
return EA->mayReleaseContent(releasedReference, accessedPointer);
807+
return EA->mayReleaseReferenceContent(releasedReference, accessedPointer);
792808
}
793809

794810
void AliasAnalysis::initialize(SILPassManager *PM) {

0 commit comments

Comments
 (0)