@@ -82,6 +82,20 @@ getSingleUnsafeGuaranteedValueResult(BuiltinInst *BI) {
82
82
return std::make_pair (GuaranteedValue, Token);
83
83
}
84
84
85
+ static bool hasUnsafeGuarantedOperand (SILValue UnsafeGuaranteedValue,
86
+ SILValue UnsafeGuaranteedValueOperand,
87
+ RCIdentityFunctionInfo &RCII,
88
+ SILBasicBlock::iterator ReleaseIt) {
89
+ assert (isa<StrongReleaseInst>(ReleaseIt) ||
90
+ isa<ReleaseValueInst>(ReleaseIt) && " Expecting a release" );
91
+
92
+ auto RCRoot =
93
+ RCII.getRCIdentityRoot (cast<SILInstruction>(ReleaseIt)->getOperand (0 ));
94
+
95
+ return RCRoot == UnsafeGuaranteedValue ||
96
+ RCRoot == UnsafeGuaranteedValueOperand;
97
+ }
98
+
85
99
// / Walk backwards from an unsafeGuaranteedEnd builtin instruction looking for a
86
100
// / release on the reference returned by the matching unsafeGuaranteed builtin
87
101
// / ignoring releases on the way.
@@ -93,35 +107,57 @@ getSingleUnsafeGuaranteedValueResult(BuiltinInst *BI) {
93
107
// / strong_release %6 : $Foo // Ignore.
94
108
// / %12 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $()
95
109
// /
110
+ // / Alternatively, look for the release after the unsafeGuaranteedEnd.
96
111
static SILBasicBlock::iterator findReleaseToMatchUnsafeGuaranteedValue (
97
- SILInstruction *UnsafeGuaranteedEndI, SILValue UnsafeGuaranteedValue,
98
- SILBasicBlock &BB, RCIdentityFunctionInfo &RCIA) {
112
+ SILInstruction *UnsafeGuaranteedEndI, SILInstruction *UnsafeGuaranteedI,
113
+ SILValue UnsafeGuaranteedValue, SILBasicBlock &BB,
114
+ RCIdentityFunctionInfo &RCIA) {
99
115
100
116
auto UnsafeGuaranteedEndIIt = SILBasicBlock::iterator (UnsafeGuaranteedEndI);
101
117
if (UnsafeGuaranteedEndIIt == BB.begin ())
102
118
return BB.end ();
103
119
auto LastReleaseIt = std::prev (UnsafeGuaranteedEndIIt);
104
- auto UnsafeGuaranteedRCIdentityRoot =
105
- RCIA.getRCIdentityRoot (UnsafeGuaranteedValue);
120
+ auto UnsafeGuaranteedRoot = RCIA.getRCIdentityRoot (UnsafeGuaranteedValue);
121
+ auto UnsafeGuaranteedOpdRoot =
122
+ RCIA.getRCIdentityRoot (UnsafeGuaranteedI->getOperand (0 ));
123
+
124
+ // Look before the "unsafeGuaranteedEnd".
106
125
while (LastReleaseIt != BB.begin () &&
107
126
(((isa<StrongReleaseInst>(*LastReleaseIt) ||
108
127
isa<ReleaseValueInst>(*LastReleaseIt)) &&
109
- RCIA.getRCIdentityRoot (LastReleaseIt->getOperand (0 )) !=
110
- UnsafeGuaranteedRCIdentityRoot &&
111
- LastReleaseIt->getOperand (0 ) !=
112
- cast<SILInstruction>(UnsafeGuaranteedValue)->getOperand (0 )) ||
128
+ !hasUnsafeGuarantedOperand (UnsafeGuaranteedRoot,
129
+ UnsafeGuaranteedOpdRoot, RCIA,
130
+ LastReleaseIt)) ||
113
131
!LastReleaseIt->mayHaveSideEffects () ||
114
132
isa<DebugValueInst>(*LastReleaseIt) ||
115
133
isa<DebugValueInst>(*LastReleaseIt)))
116
134
--LastReleaseIt;
135
+ if ((isa<StrongReleaseInst>(*LastReleaseIt) ||
136
+ isa<ReleaseValueInst>(*LastReleaseIt)) &&
137
+ hasUnsafeGuarantedOperand (UnsafeGuaranteedRoot, UnsafeGuaranteedOpdRoot,
138
+ RCIA, LastReleaseIt))
139
+ return LastReleaseIt;
140
+
141
+ // Otherwise, try finding it after the "unsafeGuaranteedEnd".
142
+ LastReleaseIt = std::next (SILBasicBlock::iterator (UnsafeGuaranteedEndI));
143
+ while (LastReleaseIt != BB.end () &&
144
+ (((isa<StrongReleaseInst>(*LastReleaseIt) ||
145
+ isa<ReleaseValueInst>(*LastReleaseIt)) &&
146
+ !hasUnsafeGuarantedOperand (UnsafeGuaranteedRoot,
147
+ UnsafeGuaranteedOpdRoot, RCIA,
148
+ LastReleaseIt)) ||
149
+ !LastReleaseIt->mayHaveSideEffects () ||
150
+ isa<DebugValueInst>(*LastReleaseIt) ||
151
+ isa<DebugValueInst>(*LastReleaseIt)))
152
+ ++LastReleaseIt;
153
+ if (LastReleaseIt == BB.end ())
154
+ return LastReleaseIt;
117
155
if ((!isa<StrongReleaseInst>(*LastReleaseIt) &&
118
156
!isa<ReleaseValueInst>(*LastReleaseIt)) ||
119
- (RCIA.getRCIdentityRoot (LastReleaseIt->getOperand (0 )) !=
120
- UnsafeGuaranteedRCIdentityRoot &&
121
- LastReleaseIt->getOperand (0 ) !=
122
- cast<SILInstruction>(UnsafeGuaranteedValue)->getOperand (0 ))) {
157
+ !hasUnsafeGuarantedOperand (UnsafeGuaranteedRoot, UnsafeGuaranteedOpdRoot,
158
+ RCIA, LastReleaseIt))
123
159
return BB.end ();
124
- }
160
+
125
161
return LastReleaseIt;
126
162
}
127
163
@@ -224,10 +260,10 @@ static bool removeGuaranteedRetainReleasePairs(SILFunction &F,
224
260
// Find the release to match with the unsafeGuaranteedValue.
225
261
auto &UnsafeGuaranteedEndBB = *UnsafeGuaranteedEndI->getParent ();
226
262
auto LastReleaseIt = findReleaseToMatchUnsafeGuaranteedValue (
227
- UnsafeGuaranteedEndI, UnsafeGuaranteedValue, UnsafeGuaranteedEndBB ,
228
- RCIA);
263
+ UnsafeGuaranteedEndI, UnsafeGuaranteedI, UnsafeGuaranteedValue ,
264
+ UnsafeGuaranteedEndBB, RCIA);
229
265
if (LastReleaseIt == UnsafeGuaranteedEndBB.end ()) {
230
- DEBUG (llvm::dbgs () << " no release before unsafeGuaranteedEnd found\n " );
266
+ DEBUG (llvm::dbgs () << " no release before/after unsafeGuaranteedEnd found\n " );
231
267
continue ;
232
268
}
233
269
SILInstruction *LastRelease = &*LastReleaseIt;
0 commit comments