Skip to content

Commit 36d3311

Browse files
committed
DeadObjectElimination: enable removal of dead alloc_stack locations which contain a non-payload resilient enum case
If the enum does not have a payload, i.e. there is no init_enum_data_addr involved, we can remove the alloc_stack (if there is no read from it).
1 parent 6a18fb8 commit 36d3311

File tree

2 files changed

+46
-20
lines changed

2 files changed

+46
-20
lines changed

lib/SILOptimizer/Transforms/DeadObjectElimination.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ removeInstructions(ArrayRef<SILInstruction*> UsersToRemove) {
193193

194194
/// Returns false if Inst is an instruction that would require us to keep the
195195
/// alloc_ref alive.
196-
static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
196+
static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts,
197+
bool onlyAcceptTrivialStores) {
197198
if (isa<SetDeallocatingInst>(Inst) || isa<FixLifetimeInst>(Inst))
198199
return true;
199200

@@ -204,6 +205,24 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
204205
isa<DeallocPartialRefInst>(Inst))
205206
return acceptRefCountInsts;
206207

208+
if (isa<InjectEnumAddrInst>(Inst))
209+
return true;
210+
211+
// We know that the destructor has no side effects so we can remove the
212+
// deallocation instruction too.
213+
if (isa<DeallocationInst>(Inst) || isa<AllocationInst>(Inst))
214+
return true;
215+
216+
// Much like deallocation, destroy addr is safe.
217+
if (isa<DestroyAddrInst>(Inst))
218+
return true;
219+
220+
// The only store instructions which is guaranteed to store a trivial value
221+
// is an inject_enum_addr witout a payload (i.e. without init_enum_data_addr).
222+
// There can also be a 'store [trivial]', but we don't handle that yet.
223+
if (onlyAcceptTrivialStores)
224+
return false;
225+
207226
// If we see a store here, we have already checked that we are storing into
208227
// the pointer before we added it to the worklist, so we can skip it.
209228
if (isa<StoreInst>(Inst))
@@ -215,15 +234,6 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
215234
!isa<TermInst>(Inst))
216235
return true;
217236

218-
// We know that the destructor has no side effects so we can remove the
219-
// deallocation instruction too.
220-
if (isa<DeallocationInst>(Inst))
221-
return true;
222-
223-
// Much like deallocation, destroy addr is safe.
224-
if (isa<DestroyAddrInst>(Inst))
225-
return true;
226-
227237
// Otherwise we do not know how to handle this instruction. Be conservative
228238
// and don't zap it.
229239
return false;
@@ -233,7 +243,7 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
233243
/// zapping it completely.
234244
static bool
235245
hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
236-
bool acceptRefCountInsts) {
246+
bool acceptRefCountInsts, bool onlyAcceptTrivialStores) {
237247
SmallVector<SILInstruction *, 16> Worklist;
238248
Worklist.push_back(AllocRef);
239249

@@ -252,7 +262,7 @@ hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
252262
}
253263

254264
// If we can't zap this instruction... bail...
255-
if (!canZapInstruction(I, acceptRefCountInsts)) {
265+
if (!canZapInstruction(I, acceptRefCountInsts, onlyAcceptTrivialStores)) {
256266
LLVM_DEBUG(llvm::dbgs() << " Found instruction we can't zap...\n");
257267
return true;
258268
}
@@ -701,7 +711,8 @@ bool DeadObjectElimination::processAllocRef(AllocRefInst *ARI) {
701711
// escape, then we can completely remove the use graph of this alloc_ref.
702712
UserList UsersToRemove;
703713
if (hasUnremovableUsers(ARI, UsersToRemove,
704-
/*acceptRefCountInsts=*/ !HasSideEffects)) {
714+
/*acceptRefCountInsts=*/ !HasSideEffects,
715+
/*onlyAcceptTrivialStores*/false)) {
705716
LLVM_DEBUG(llvm::dbgs() << " Found a use that cannot be zapped...\n");
706717
return false;
707718
}
@@ -716,12 +727,11 @@ bool DeadObjectElimination::processAllocRef(AllocRefInst *ARI) {
716727
}
717728

718729
bool DeadObjectElimination::processAllocStack(AllocStackInst *ASI) {
719-
// Trivial types don't have destructors. Let's try to zap this AllocStackInst.
720-
if (!ASI->getElementType().isTrivial(ASI->getModule()))
721-
return false;
722-
730+
// Trivial types don't have destructors.
731+
bool isTrivialType = ASI->getElementType().isTrivial(ASI->getModule());
723732
UserList UsersToRemove;
724-
if (hasUnremovableUsers(ASI, UsersToRemove, /*acceptRefCountInsts=*/ true)) {
733+
if (hasUnremovableUsers(ASI, UsersToRemove, /*acceptRefCountInsts=*/ true,
734+
/*onlyAcceptTrivialStores*/!isTrivialType)) {
725735
LLVM_DEBUG(llvm::dbgs() << " Found a use that cannot be zapped...\n");
726736
return false;
727737
}

test/SILOptimizer/dead_alloc_elim.sil

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,9 @@ sil @non_trivial_destructor_objc_destructor : $@convention(thin) () -> () {
325325
}
326326

327327
// CHECK-LABEL: sil @non_trivial_destructor_on_stack : $@convention(thin) () -> () {
328-
// CHECK: alloc_stack
329-
// CHECK: return
328+
// CHECK: bb0:
329+
// CHECK-NEXT: %0 = tuple ()
330+
// CHECK-NEXT: return %0
330331
sil @non_trivial_destructor_on_stack : $@convention(thin) () -> () {
331332
%0 = alloc_stack $NonTrivialDestructor
332333
dealloc_stack %0 : $*NonTrivialDestructor
@@ -358,3 +359,18 @@ sil @trivial_destructor_may_trap : $@convention(thin) () -> () {
358359
%4 = tuple()
359360
return %4 : $()
360361
}
362+
363+
// CHECK-LABEL: sil @remove_dead_enum_stackloc
364+
// CHECK: bb0:
365+
// CHECK-NEXT: %0 = tuple ()
366+
// CHECK-NEXT: return %0
367+
sil @remove_dead_enum_stackloc : $@convention(thin) () -> () {
368+
bb0:
369+
%0 = alloc_stack $FloatingPointRoundingRule
370+
inject_enum_addr %0 : $*FloatingPointRoundingRule, #FloatingPointRoundingRule.toNearestOrEven!enumelt
371+
destroy_addr %0 : $*FloatingPointRoundingRule
372+
dealloc_stack %0 : $*FloatingPointRoundingRule
373+
%1 = tuple ()
374+
return %1 : $()
375+
}
376+

0 commit comments

Comments
 (0)