mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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).
This commit is contained in:
@@ -193,7 +193,8 @@ removeInstructions(ArrayRef<SILInstruction*> UsersToRemove) {
|
||||
|
||||
/// Returns false if Inst is an instruction that would require us to keep the
|
||||
/// alloc_ref alive.
|
||||
static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
|
||||
static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts,
|
||||
bool onlyAcceptTrivialStores) {
|
||||
if (isa<SetDeallocatingInst>(Inst) || isa<FixLifetimeInst>(Inst))
|
||||
return true;
|
||||
|
||||
@@ -204,6 +205,24 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
|
||||
isa<DeallocPartialRefInst>(Inst))
|
||||
return acceptRefCountInsts;
|
||||
|
||||
if (isa<InjectEnumAddrInst>(Inst))
|
||||
return true;
|
||||
|
||||
// We know that the destructor has no side effects so we can remove the
|
||||
// deallocation instruction too.
|
||||
if (isa<DeallocationInst>(Inst) || isa<AllocationInst>(Inst))
|
||||
return true;
|
||||
|
||||
// Much like deallocation, destroy addr is safe.
|
||||
if (isa<DestroyAddrInst>(Inst))
|
||||
return true;
|
||||
|
||||
// The only store instructions which is guaranteed to store a trivial value
|
||||
// is an inject_enum_addr witout a payload (i.e. without init_enum_data_addr).
|
||||
// There can also be a 'store [trivial]', but we don't handle that yet.
|
||||
if (onlyAcceptTrivialStores)
|
||||
return false;
|
||||
|
||||
// If we see a store here, we have already checked that we are storing into
|
||||
// the pointer before we added it to the worklist, so we can skip it.
|
||||
if (isa<StoreInst>(Inst))
|
||||
@@ -215,15 +234,6 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
|
||||
!isa<TermInst>(Inst))
|
||||
return true;
|
||||
|
||||
// We know that the destructor has no side effects so we can remove the
|
||||
// deallocation instruction too.
|
||||
if (isa<DeallocationInst>(Inst))
|
||||
return true;
|
||||
|
||||
// Much like deallocation, destroy addr is safe.
|
||||
if (isa<DestroyAddrInst>(Inst))
|
||||
return true;
|
||||
|
||||
// Otherwise we do not know how to handle this instruction. Be conservative
|
||||
// and don't zap it.
|
||||
return false;
|
||||
@@ -233,7 +243,7 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts) {
|
||||
/// zapping it completely.
|
||||
static bool
|
||||
hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
|
||||
bool acceptRefCountInsts) {
|
||||
bool acceptRefCountInsts, bool onlyAcceptTrivialStores) {
|
||||
SmallVector<SILInstruction *, 16> Worklist;
|
||||
Worklist.push_back(AllocRef);
|
||||
|
||||
@@ -252,7 +262,7 @@ hasUnremovableUsers(SILInstruction *AllocRef, UserList &Users,
|
||||
}
|
||||
|
||||
// If we can't zap this instruction... bail...
|
||||
if (!canZapInstruction(I, acceptRefCountInsts)) {
|
||||
if (!canZapInstruction(I, acceptRefCountInsts, onlyAcceptTrivialStores)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " Found instruction we can't zap...\n");
|
||||
return true;
|
||||
}
|
||||
@@ -701,7 +711,8 @@ bool DeadObjectElimination::processAllocRef(AllocRefInst *ARI) {
|
||||
// escape, then we can completely remove the use graph of this alloc_ref.
|
||||
UserList UsersToRemove;
|
||||
if (hasUnremovableUsers(ARI, UsersToRemove,
|
||||
/*acceptRefCountInsts=*/ !HasSideEffects)) {
|
||||
/*acceptRefCountInsts=*/ !HasSideEffects,
|
||||
/*onlyAcceptTrivialStores*/false)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " Found a use that cannot be zapped...\n");
|
||||
return false;
|
||||
}
|
||||
@@ -716,12 +727,11 @@ bool DeadObjectElimination::processAllocRef(AllocRefInst *ARI) {
|
||||
}
|
||||
|
||||
bool DeadObjectElimination::processAllocStack(AllocStackInst *ASI) {
|
||||
// Trivial types don't have destructors. Let's try to zap this AllocStackInst.
|
||||
if (!ASI->getElementType().isTrivial(ASI->getModule()))
|
||||
return false;
|
||||
|
||||
// Trivial types don't have destructors.
|
||||
bool isTrivialType = ASI->getElementType().isTrivial(ASI->getModule());
|
||||
UserList UsersToRemove;
|
||||
if (hasUnremovableUsers(ASI, UsersToRemove, /*acceptRefCountInsts=*/ true)) {
|
||||
if (hasUnremovableUsers(ASI, UsersToRemove, /*acceptRefCountInsts=*/ true,
|
||||
/*onlyAcceptTrivialStores*/!isTrivialType)) {
|
||||
LLVM_DEBUG(llvm::dbgs() << " Found a use that cannot be zapped...\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user