@@ -157,19 +157,38 @@ SILBasicBlock *SILBuilder::splitBlockForFallthrough() {
157
157
return NewBB;
158
158
}
159
159
160
+ static bool setAccessToDeinit (BeginAccessInst *beginAccess) {
161
+ // It's possible that AllocBoxToStack could catch some cases that
162
+ // AccessEnforcementSelection does not promote to [static]. Ultimately, this
163
+ // should be an assert, but only after we the two passes can be fixes to share
164
+ // a common analysis.
165
+ if (beginAccess->getEnforcement () == SILAccessEnforcement::Dynamic)
166
+ return false ;
167
+
168
+ beginAccess->setAccessKind (SILAccessKind::Deinit);
169
+ return true ;
170
+ }
171
+
160
172
PointerUnion<CopyAddrInst *, DestroyAddrInst *>
161
173
SILBuilder::emitDestroyAddr (SILLocation Loc, SILValue Operand) {
162
174
// Check to see if the instruction immediately before the insertion point is a
163
175
// copy_addr from the specified operand. If so, we can fold this into the
164
176
// copy_addr as a take.
177
+ BeginAccessInst *beginAccess = nullptr ;
165
178
auto I = getInsertionPoint (), BBStart = getInsertionBB ()->begin ();
166
179
while (I != BBStart) {
167
180
auto *Inst = &*--I;
168
181
169
182
if (auto CA = dyn_cast<CopyAddrInst>(Inst)) {
170
- if (CA->getSrc () == Operand && !CA->isTakeOfSrc ()) {
171
- CA->setIsTakeOfSrc (IsTake);
172
- return CA;
183
+ if (!CA->isTakeOfSrc ()) {
184
+ if (CA->getSrc () == Operand && !CA->isTakeOfSrc ()) {
185
+ CA->setIsTakeOfSrc (IsTake);
186
+ return CA;
187
+ }
188
+ if (CA->getSrc () == beginAccess && setAccessToDeinit (beginAccess)) {
189
+ CA->setIsTakeOfSrc (IsTake);
190
+ return CA;
191
+ }
173
192
}
174
193
}
175
194
@@ -178,6 +197,15 @@ SILBuilder::emitDestroyAddr(SILLocation Loc, SILValue Operand) {
178
197
if (isa<DeallocStackInst>(Inst))
179
198
continue ;
180
199
200
+ // An end_access of the same address may be able to be rewritten as a
201
+ // [deinit] access.
202
+ if (auto endAccess = dyn_cast<EndAccessInst>(Inst)) {
203
+ if (endAccess->getSource () == Operand) {
204
+ beginAccess = endAccess->getBeginAccess ();
205
+ continue ;
206
+ }
207
+ }
208
+
181
209
// This code doesn't try to prove tricky validity constraints about whether
182
210
// it is safe to push the destroy_addr past interesting instructions.
183
211
if (Inst->mayHaveSideEffects ())
0 commit comments