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:
Erik Eckstein
2018-12-07 16:03:32 -08:00
parent 6a18fb8d83
commit 36d3311c9a
2 changed files with 46 additions and 20 deletions

View File

@@ -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;
}