@@ -51,6 +51,43 @@ visitAutoreleasePoolCall(ValueBase *V) {
51
51
return DataflowResult (RCStateTransitionDataflowResultKind::NoEffects);
52
52
}
53
53
54
+ // private helper method since C++ does not have extensions... *sigh*.
55
+ //
56
+ // TODO: This needs a better name.
57
+ template <class ARCState >
58
+ static bool isKnownSafe (BottomUpDataflowRCStateVisitor<ARCState> *State,
59
+ SILInstruction *I, SILValue Op) {
60
+ // If we are running with 'frozen' owned arg releases, check if we have a
61
+ // frozen use in the side table. If so, this release must be known safe.
62
+ if (State->FreezeOwnedArgEpilogueReleases )
63
+ if (auto *OwnedRelease =
64
+ State->EpilogueReleaseMatcher .getSingleReleaseForArgument (Op))
65
+ if (I != OwnedRelease)
66
+ return true ;
67
+
68
+ // A guaranteed function argument is guaranteed to outlive the function we are
69
+ // processing. So bottom up for such a parameter, we are always known safe.
70
+ if (auto *Arg = dyn_cast<SILArgument>(Op)) {
71
+ if (Arg->isFunctionArg () &&
72
+ Arg->hasConvention (SILArgumentConvention::Direct_Guaranteed)) {
73
+ return true ;
74
+ }
75
+ }
76
+
77
+ // If Op is a load from an in_guaranteed parameter, it is guaranteed as well.
78
+ if (auto *LI = dyn_cast<LoadInst>(Op)) {
79
+ SILValue RCIdentity = State->RCFI ->getRCIdentityRoot (LI->getOperand ());
80
+ if (auto *Arg = dyn_cast<SILArgument>(RCIdentity)) {
81
+ if (Arg->isFunctionArg () &&
82
+ Arg->hasConvention (SILArgumentConvention::Indirect_In_Guaranteed)) {
83
+ return true ;
84
+ }
85
+ }
86
+ }
87
+
88
+ return false ;
89
+ }
90
+
54
91
template <class ARCState >
55
92
typename BottomUpDataflowRCStateVisitor<ARCState>::DataflowResult
56
93
BottomUpDataflowRCStateVisitor<ARCState>::visitStrongDecrement(ValueBase *V) {
@@ -70,23 +107,8 @@ BottomUpDataflowRCStateVisitor<ARCState>::visitStrongDecrement(ValueBase *V) {
70
107
BottomUpRefCountState &State = DataflowState.getBottomUpRefCountState (Op);
71
108
bool NestingDetected = State.initWithMutatorInst (SetFactory.get (I), RCFI);
72
109
73
- // If we are running with 'frozen' owned arg releases, check if we have a
74
- // frozen use in the side table. If so, this release must be known safe.
75
- if (FreezeOwnedArgEpilogueReleases) {
76
- if (auto *OwnedRelease = EpilogueReleaseMatcher.getSingleReleaseForArgument (Op)) {
77
- if (I != OwnedRelease) {
78
- State.updateKnownSafe (true );
79
- }
80
- }
81
- }
82
-
83
- // A guaranteed function argument is guaranteed to outlive the function we are
84
- // processing. So bottom up for such a parameter, we are always known safe.
85
- if (auto *Arg = dyn_cast<SILArgument>(Op)) {
86
- if (Arg->isFunctionArg () &&
87
- Arg->hasConvention (SILArgumentConvention::Direct_Guaranteed)) {
88
- State.updateKnownSafe (true );
89
- }
110
+ if (isKnownSafe (this , I, Op)) {
111
+ State.updateKnownSafe (true );
90
112
}
91
113
92
114
DEBUG (llvm::dbgs () << " REF COUNT DECREMENT! Known Safe: "
0 commit comments