We can only eliminate dealloc_stack in an unreachable block if we can eliminate all dealloc_stack instructions in the block

This commit is contained in:
Arnold Schwaighofer
2019-01-17 14:45:46 -08:00
parent 614006e3cb
commit b6f91292bf

View File

@@ -1843,6 +1843,26 @@ bool SimplifyCFG::simplifySwitchValueBlock(SwitchValueInst *SVI) {
return simplifyTermWithIdenticalDestBlocks(ThisBB);
}
bool onlyContainsRefcountAndDeallocStackInst(
SILBasicBlock::reverse_iterator I, SILBasicBlock::reverse_iterator End) {
while (I != End) {
auto MaybeDead = I++;
switch (MaybeDead->getKind()) {
// These technically have side effects, but not ones that matter
// in a block that we shouldn't really reach...
case SILInstructionKind::StrongRetainInst:
case SILInstructionKind::StrongReleaseInst:
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::ReleaseValueInst:
case SILInstructionKind::DeallocStackInst:
break;
default:
return false;
}
}
return true;
}
/// simplifyUnreachableBlock - Simplify blocks ending with unreachable by
/// removing instructions that are safe to delete backwards until we
/// hit an instruction we cannot delete.
@@ -1853,6 +1873,8 @@ bool SimplifyCFG::simplifyUnreachableBlock(UnreachableInst *UI) {
auto End = BB->rend();
SmallVector<SILInstruction *, 8> DeadInstrs;
bool canIgnoreRestOfBlock = false;
// Walk backwards deleting instructions that should be safe to delete
// in a block that ends with unreachable.
while (I != End) {
@@ -1865,12 +1887,20 @@ bool SimplifyCFG::simplifyUnreachableBlock(UnreachableInst *UI) {
case SILInstructionKind::StrongReleaseInst:
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::ReleaseValueInst:
case SILInstructionKind::DeallocStackInst:
break;
// We can only ignore a dealloc_stack instruction if we can ignore all
// instructions in the block.
case SILInstructionKind::DeallocStackInst: {
if (canIgnoreRestOfBlock ||
onlyContainsRefcountAndDeallocStackInst(MaybeDead, End)) {
canIgnoreRestOfBlock = true;
break;
}
LLVM_FALLTHROUGH;
}
default:
if (MaybeDead->mayHaveSideEffects()) {
if (Changed)
if (Changed)
for (auto Dead : DeadInstrs)
Dead->eraseFromParent();
return Changed;