forked from OSchip/llvm-project
[SimplifyCFG] SUCCESS! Teach createUnreachableSwitchDefault() to preserve DomTree
This pretty much concludes patch series for updating SimplifyCFG to preserve DomTree. All 318 dedicated `-simplifycfg` tests now pass with `-simplifycfg-require-and-preserve-domtree=1`. There are a few leftovers that apparently don't have good test coverage. I do not yet know what gaps in test coverage will the wider-scale testing reveal, but the default flip might be close.
This commit is contained in:
parent
e1440d43bc
commit
831636b0e6
|
@ -4783,15 +4783,29 @@ static bool CasesAreContiguous(SmallVectorImpl<ConstantInt *> &Cases) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void createUnreachableSwitchDefault(SwitchInst *Switch) {
|
||||
static void createUnreachableSwitchDefault(SwitchInst *Switch,
|
||||
DomTreeUpdater *DTU) {
|
||||
LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
|
||||
auto *BB = Switch->getParent();
|
||||
BasicBlock *NewDefaultBlock =
|
||||
SplitBlockPredecessors(Switch->getDefaultDest(), Switch->getParent(), "");
|
||||
SplitBlockPredecessors(Switch->getDefaultDest(), Switch->getParent(), "",
|
||||
DTU ? &DTU->getDomTree() : nullptr);
|
||||
auto *OrigDefaultBlock = Switch->getDefaultDest();
|
||||
Switch->setDefaultDest(&*NewDefaultBlock);
|
||||
SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front());
|
||||
if (DTU)
|
||||
DTU->applyUpdatesPermissive(
|
||||
{{DominatorTree::Delete, BB, OrigDefaultBlock},
|
||||
{DominatorTree::Insert, BB, &*NewDefaultBlock}});
|
||||
SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front(),
|
||||
DTU ? &DTU->getDomTree() : nullptr);
|
||||
SmallVector<DominatorTree::UpdateType, 2> Updates;
|
||||
for (auto *Successor : successors(NewDefaultBlock))
|
||||
Updates.push_back({DominatorTree::Delete, NewDefaultBlock, Successor});
|
||||
auto *NewTerminator = NewDefaultBlock->getTerminator();
|
||||
new UnreachableInst(Switch->getContext(), NewTerminator);
|
||||
EraseTerminatorAndDCECond(NewTerminator);
|
||||
if (DTU)
|
||||
DTU->applyUpdatesPermissive(Updates);
|
||||
}
|
||||
|
||||
/// Turn a switch with two reachable destinations into an integer range
|
||||
|
@ -4803,6 +4817,8 @@ bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,
|
|||
bool HasDefault =
|
||||
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
|
||||
|
||||
auto *BB = SI->getParent();
|
||||
|
||||
// Partition the cases into two sets with different destinations.
|
||||
BasicBlock *DestA = HasDefault ? SI->getDefaultDest() : nullptr;
|
||||
BasicBlock *DestB = nullptr;
|
||||
|
@ -4906,11 +4922,17 @@ bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,
|
|||
// Clean up the default block - it may have phis or other instructions before
|
||||
// the unreachable terminator.
|
||||
if (!HasDefault)
|
||||
createUnreachableSwitchDefault(SI);
|
||||
createUnreachableSwitchDefault(SI, DTU);
|
||||
|
||||
auto *UnreachableDefault = SI->getDefaultDest();
|
||||
|
||||
// Drop the switch.
|
||||
SI->eraseFromParent();
|
||||
|
||||
if (!HasDefault && DTU)
|
||||
DTU->applyUpdatesPermissive(
|
||||
{{DominatorTree::Delete, BB, UnreachableDefault}});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4957,7 +4979,7 @@ static bool eliminateDeadSwitchCases(SwitchInst *SI, DomTreeUpdater *DTU,
|
|||
if (HasDefault && DeadCases.empty() &&
|
||||
NumUnknownBits < 64 /* avoid overflow */ &&
|
||||
SI->getNumCases() == (1ULL << NumUnknownBits)) {
|
||||
createUnreachableSwitchDefault(SI);
|
||||
createUnreachableSwitchDefault(SI, /*DTU=*/nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt %s -simplifycfg -S | FileCheck %s
|
||||
; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
|
||||
declare i32 @f(i32)
|
||||
|
||||
|
|
Loading…
Reference in New Issue