@@ -177,13 +177,22 @@ static DestructorEffects doesDestructorHaveSideEffects(AllocRefInstBase *ARI) {
177
177
assert (RefInst->getNumOperands () == 1 &&
178
178
" Make sure RefInst only has one argument." );
179
179
LLVM_DEBUG (llvm::dbgs () << " SAFE! Ref count operation on "
180
- " Self.\n " );
180
+ " Self.\n " );
181
+ continue ;
182
+ }
183
+ LLVM_DEBUG (llvm::dbgs () << " UNSAFE! Ref count operation "
184
+ " not on self.\n " );
185
+ return DestructorEffects::Unknown;
186
+ }
187
+ if (auto *destroy = dyn_cast<DestroyValueInst>(&I)) {
188
+ if (stripCasts (destroy->getOperand ()) == Self) {
189
+ LLVM_DEBUG (llvm::dbgs () << " SAFE! Ref count operation on "
190
+ " Self.\n " );
181
191
continue ;
182
- } else {
183
- LLVM_DEBUG (llvm::dbgs () << " UNSAFE! Ref count operation "
184
- " not on self.\n " );
185
- return DestructorEffects::Unknown;
186
192
}
193
+ LLVM_DEBUG (llvm::dbgs () << " UNSAFE! Ref count operation "
194
+ " not on self.\n " );
195
+ return DestructorEffects::Unknown;
187
196
}
188
197
189
198
// dealloc_stack can be ignored.
@@ -246,7 +255,15 @@ static DestructorEffects doesDestructorHaveSideEffects(AllocRefInstBase *ARI) {
246
255
// / alloc_ref alive.
247
256
static bool canZapInstruction (SILInstruction *Inst, bool acceptRefCountInsts,
248
257
bool onlyAcceptTrivialStores) {
249
- if (isa<SetDeallocatingInst>(Inst) || isa<FixLifetimeInst>(Inst))
258
+ if (isa<DestroyValueInst>(Inst)) {
259
+ return acceptRefCountInsts;
260
+ }
261
+ if (isa<CopyValueInst>(Inst) || isa<BeginBorrowInst>(Inst) ||
262
+ isa<MoveValueInst>(Inst)) {
263
+ return true ;
264
+ }
265
+ if (isa<SetDeallocatingInst>(Inst) || isa<FixLifetimeInst>(Inst) ||
266
+ isa<EndBorrowInst>(Inst))
250
267
return true ;
251
268
252
269
// It is ok to eliminate various retains/releases. We are either removing
@@ -384,6 +401,7 @@ hasUnremovableUsers(SILInstruction *allocation, UserList *Users,
384
401
LLVM_DEBUG (llvm::dbgs () << " Analyzing Use Graph." );
385
402
386
403
SmallVector<RefElementAddrInst *, 8 > refElementAddrs;
404
+
387
405
BuiltinInst *destroyArray = nullptr ;
388
406
auto *allocRef = dyn_cast<AllocRefInstBase>(allocation);
389
407
@@ -397,11 +415,10 @@ hasUnremovableUsers(SILInstruction *allocation, UserList *Users,
397
415
if (Users && !Users->insert (I)) {
398
416
LLVM_DEBUG (llvm::dbgs () << " Already seen skipping...\n " );
399
417
continue ;
400
- }
401
- if (auto *rea = dyn_cast<RefElementAddrInst>(I)) {
418
+ } else if (auto *rea = dyn_cast<RefElementAddrInst>(I)) {
402
419
if (rea != allocation && !rea->getType ().isTrivial (*rea->getFunction ()))
403
420
refElementAddrs.push_back (rea);
404
- } else if (allocRef && Users && isDestroyArray (I)) {
421
+ } else if (allocRef && isDestroyArray (I)) {
405
422
if (destroyArray)
406
423
return true ;
407
424
destroyArray = cast<BuiltinInst>(I);
@@ -434,20 +451,20 @@ hasUnremovableUsers(SILInstruction *allocation, UserList *Users,
434
451
}
435
452
}
436
453
437
- // In OSSA, we don't have to do this check. We can always accept a
438
- // destroyArray and insert the compensating destroys right at the store
439
- // instructions .
440
- if (destroyArray)
441
- return !onlyStoresToTailObjects (destroyArray, *Users, allocRef);
442
-
443
- // In non-OSSA we cannot reliably track the lifetime of non-trivial stored
444
- // properties. Removing the dead alloc_ref might leak a property value.
445
- // TODO: in OSSA we can replace stores to properties with a destroy_value.
446
- for (RefElementAddrInst *rea : refElementAddrs) {
447
- // Re-run the check with not accepting non-trivial stores.
448
- if ( hasUnremovableUsers (rea, nullptr , acceptRefCountInsts,
449
- /* onlyAcceptTrivialStores */ true ))
450
- return true ;
454
+ if (!allocation-> getFunction ()-> hasOwnership ()) {
455
+ // In non-ossa, if we found a destroy array builtin that destroys the tail
456
+ // elements, ensure all stores are to the taile elems .
457
+ if (destroyArray) {
458
+ return !onlyStoresToTailObjects (destroyArray, *Users, allocRef);
459
+ }
460
+ // In non-OSSA we cannot reliably track the lifetime of non-trivial stored
461
+ // properties. Removing the dead alloc_ref might leak a property value.
462
+ for (RefElementAddrInst *rea : refElementAddrs) {
463
+ // Re-run the check with not accepting non-trivial stores.
464
+ if ( hasUnremovableUsers (rea, nullptr , acceptRefCountInsts,
465
+ /* onlyAcceptTrivialStores */ true ))
466
+ return true ;
467
+ }
451
468
}
452
469
453
470
return false ;
@@ -820,21 +837,35 @@ bool DeadObjectElimination::processAllocRef(AllocRefInstBase *ARI) {
820
837
return false ;
821
838
}
822
839
823
- // Find the instruction which releases the object's tail elements.
824
- SILInstruction *releaseOfTailElems = nullptr ;
825
- for (SILInstruction *user : UsersToRemove) {
826
- if (isDestroyArray (user) ||
827
- (destructorEffects == DestructorEffects::DestroysTailElems &&
828
- isa<RefCountingInst>(user) && user->mayRelease ())) {
829
- // Bail if we find multiple such instructions.
830
- if (releaseOfTailElems)
840
+ if (!ARI->getFunction ()->hasOwnership ()) {
841
+ // Find the instruction which releases the object's tail elements.
842
+ SILInstruction *releaseOfTailElems = nullptr ;
843
+ for (SILInstruction *user : UsersToRemove) {
844
+ if (isDestroyArray (user) ||
845
+ (destructorEffects == DestructorEffects::DestroysTailElems &&
846
+ isa<RefCountingInst>(user) && user->mayRelease ())) {
847
+ // Bail if we find multiple such instructions.
848
+ if (releaseOfTailElems)
849
+ return false ;
850
+ releaseOfTailElems = user;
851
+ }
852
+ }
853
+ if (releaseOfTailElems) {
854
+ if (!insertCompensatingReleases (releaseOfTailElems, UsersToRemove)) {
831
855
return false ;
832
- releaseOfTailElems = user;
856
+ }
833
857
}
834
858
}
835
- if (releaseOfTailElems) {
836
- if (!insertCompensatingReleases (releaseOfTailElems, UsersToRemove)) {
837
- return false ;
859
+
860
+ if (ARI->getFunction ()->hasOwnership ()) {
861
+ for (auto *user : UsersToRemove) {
862
+ auto *store = dyn_cast<StoreInst>(user);
863
+ if (!store ||
864
+ store->getOwnershipQualifier () == StoreOwnershipQualifier::Trivial) {
865
+ continue ;
866
+ }
867
+ SILBuilderWithScope (store).createDestroyValue (store->getLoc (),
868
+ store->getSrc ());
838
869
}
839
870
}
840
871
0 commit comments