@@ -251,21 +251,24 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts,
251251// / Analyze the use graph of AllocRef for any uses that would prevent us from
252252// / zapping it completely.
253253static bool
254- hasUnremovableUsers (SILInstruction *AllocRef, UserList & Users,
254+ hasUnremovableUsers (SILInstruction *AllocRef, UserList * Users,
255255 bool acceptRefCountInsts, bool onlyAcceptTrivialStores) {
256256 SmallVector<SILInstruction *, 16 > Worklist;
257257 Worklist.push_back (AllocRef);
258258
259259 LLVM_DEBUG (llvm::dbgs () << " Analyzing Use Graph." );
260260
261+ SmallVector<RefElementAddrInst *, 8 > refElementAddrs;
262+ bool deallocationMaybeInlined = false ;
263+
261264 while (!Worklist.empty ()) {
262265 SILInstruction *I = Worklist.pop_back_val ();
263266
264267 LLVM_DEBUG (llvm::dbgs () << " Visiting: " << *I);
265268
266269 // Insert the instruction into our InvolvedInstructions set. If we have
267270 // already seen it, then don't reprocess all of the uses.
268- if (!Users. insert (I)) {
271+ if (Users && !Users-> insert (I)) {
269272 LLVM_DEBUG (llvm::dbgs () << " Already seen skipping...\n " );
270273 continue ;
271274 }
@@ -276,6 +279,13 @@ hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
276279 return true ;
277280 }
278281
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+
279289 // At this point, we can remove the instruction as long as all of its users
280290 // can be removed as well. Scan its users and add them to the worklist for
281291 // recursive processing.
@@ -299,6 +309,20 @@ hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
299309 }
300310 }
301311
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+
302326 return false ;
303327}
304328
@@ -736,7 +760,7 @@ bool DeadObjectElimination::processAllocRef(AllocRefInst *ARI) {
736760 // Our destructor has no side effects, so if we can prove that no loads
737761 // escape, then we can completely remove the use graph of this alloc_ref.
738762 UserList UsersToRemove;
739- if (hasUnremovableUsers (ARI, UsersToRemove,
763+ if (hasUnremovableUsers (ARI, & UsersToRemove,
740764 /* acceptRefCountInsts=*/ !HasSideEffects,
741765 /* onlyAcceptTrivialStores*/ false )) {
742766 LLVM_DEBUG (llvm::dbgs () << " Found a use that cannot be zapped...\n " );
@@ -756,7 +780,7 @@ bool DeadObjectElimination::processAllocStack(AllocStackInst *ASI) {
756780 // Trivial types don't have destructors.
757781 bool isTrivialType = ASI->getElementType ().isTrivial (*ASI->getFunction ());
758782 UserList UsersToRemove;
759- if (hasUnremovableUsers (ASI, UsersToRemove, /* acceptRefCountInsts=*/ true ,
783+ if (hasUnremovableUsers (ASI, & UsersToRemove, /* acceptRefCountInsts=*/ true ,
760784 /* onlyAcceptTrivialStores*/ !isTrivialType)) {
761785 LLVM_DEBUG (llvm::dbgs () << " Found a use that cannot be zapped...\n " );
762786 return false ;
@@ -773,7 +797,7 @@ bool DeadObjectElimination::processAllocStack(AllocStackInst *ASI) {
773797
774798bool DeadObjectElimination::processKeyPath (KeyPathInst *KPI) {
775799 UserList UsersToRemove;
776- if (hasUnremovableUsers (KPI, UsersToRemove, /* acceptRefCountInsts=*/ true ,
800+ if (hasUnremovableUsers (KPI, & UsersToRemove, /* acceptRefCountInsts=*/ true ,
777801 /* onlyAcceptTrivialStores*/ false )) {
778802 LLVM_DEBUG (llvm::dbgs () << " Found a use that cannot be zapped...\n " );
779803 return false ;
0 commit comments