@@ -251,21 +251,24 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts,
251
251
// / Analyze the use graph of AllocRef for any uses that would prevent us from
252
252
// / zapping it completely.
253
253
static bool
254
- hasUnremovableUsers (SILInstruction *AllocRef, UserList & Users,
254
+ hasUnremovableUsers (SILInstruction *AllocRef, UserList * Users,
255
255
bool acceptRefCountInsts, bool onlyAcceptTrivialStores) {
256
256
SmallVector<SILInstruction *, 16 > Worklist;
257
257
Worklist.push_back (AllocRef);
258
258
259
259
LLVM_DEBUG (llvm::dbgs () << " Analyzing Use Graph." );
260
260
261
+ SmallVector<RefElementAddrInst *, 8 > refElementAddrs;
262
+ bool deallocationMaybeInlined = false ;
263
+
261
264
while (!Worklist.empty ()) {
262
265
SILInstruction *I = Worklist.pop_back_val ();
263
266
264
267
LLVM_DEBUG (llvm::dbgs () << " Visiting: " << *I);
265
268
266
269
// Insert the instruction into our InvolvedInstructions set. If we have
267
270
// already seen it, then don't reprocess all of the uses.
268
- if (!Users. insert (I)) {
271
+ if (Users && !Users-> insert (I)) {
269
272
LLVM_DEBUG (llvm::dbgs () << " Already seen skipping...\n " );
270
273
continue ;
271
274
}
@@ -276,6 +279,13 @@ hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
276
279
return true ;
277
280
}
278
281
282
+ if (auto *rea = dyn_cast<RefElementAddrInst>(I)) {
283
+ if (!rea->getType ().isTrivial (*rea->getFunction ()))
284
+ refElementAddrs.push_back (rea);
285
+ } else if (isa<SetDeallocatingInst>(I)) {
286
+ deallocationMaybeInlined = true ;
287
+ }
288
+
279
289
// At this point, we can remove the instruction as long as all of its users
280
290
// can be removed as well. Scan its users and add them to the worklist for
281
291
// recursive processing.
@@ -299,6 +309,20 @@ hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
299
309
}
300
310
}
301
311
312
+ if (deallocationMaybeInlined) {
313
+ // The alloc_ref is not destructed by a strong_release which is calling the
314
+ // deallocator (destroying all stored properties).
315
+ // In non-OSSA we cannot reliably track the lifetime of non-trivial stored
316
+ // properties. Removing the dead alloc_ref might leak a property value.
317
+ // TODO: in OSSA we can replace stores to properties with a destroy_value.
318
+ for (RefElementAddrInst *rea : refElementAddrs) {
319
+ // Re-run the check with not accepting non-trivial stores.
320
+ if (hasUnremovableUsers (rea, nullptr , acceptRefCountInsts,
321
+ /* onlyAcceptTrivialStores*/ true ))
322
+ return true ;
323
+ }
324
+ }
325
+
302
326
return false ;
303
327
}
304
328
@@ -736,7 +760,7 @@ bool DeadObjectElimination::processAllocRef(AllocRefInst *ARI) {
736
760
// Our destructor has no side effects, so if we can prove that no loads
737
761
// escape, then we can completely remove the use graph of this alloc_ref.
738
762
UserList UsersToRemove;
739
- if (hasUnremovableUsers (ARI, UsersToRemove,
763
+ if (hasUnremovableUsers (ARI, & UsersToRemove,
740
764
/* acceptRefCountInsts=*/ !HasSideEffects,
741
765
/* onlyAcceptTrivialStores*/ false )) {
742
766
LLVM_DEBUG (llvm::dbgs () << " Found a use that cannot be zapped...\n " );
@@ -756,7 +780,7 @@ bool DeadObjectElimination::processAllocStack(AllocStackInst *ASI) {
756
780
// Trivial types don't have destructors.
757
781
bool isTrivialType = ASI->getElementType ().isTrivial (*ASI->getFunction ());
758
782
UserList UsersToRemove;
759
- if (hasUnremovableUsers (ASI, UsersToRemove, /* acceptRefCountInsts=*/ true ,
783
+ if (hasUnremovableUsers (ASI, & UsersToRemove, /* acceptRefCountInsts=*/ true ,
760
784
/* onlyAcceptTrivialStores*/ !isTrivialType)) {
761
785
LLVM_DEBUG (llvm::dbgs () << " Found a use that cannot be zapped...\n " );
762
786
return false ;
@@ -773,7 +797,7 @@ bool DeadObjectElimination::processAllocStack(AllocStackInst *ASI) {
773
797
774
798
bool DeadObjectElimination::processKeyPath (KeyPathInst *KPI) {
775
799
UserList UsersToRemove;
776
- if (hasUnremovableUsers (KPI, UsersToRemove, /* acceptRefCountInsts=*/ true ,
800
+ if (hasUnremovableUsers (KPI, & UsersToRemove, /* acceptRefCountInsts=*/ true ,
777
801
/* onlyAcceptTrivialStores*/ false )) {
778
802
LLVM_DEBUG (llvm::dbgs () << " Found a use that cannot be zapped...\n " );
779
803
return false ;
0 commit comments