aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2022-04-26 12:41:41 +0100
committerFlorian Hahn <flo@fhahn.com>2022-04-26 12:41:41 +0100
commit857c612d899f271402470d4026d2e3be1dce53a4 (patch)
treea4a740480b150c9c4cff671c4df7881f326b1370 /llvm/lib
parent5b3ca24a35e91bf9c19af856e7f92c69b17f989e (diff)
downloadllvm-857c612d899f271402470d4026d2e3be1dce53a4.zip
llvm-857c612d899f271402470d4026d2e3be1dce53a4.tar.gz
llvm-857c612d899f271402470d4026d2e3be1dce53a4.tar.bz2
[IPSCCP] Support unfeasible default dests for switch.
At the moment, unfeasible default destinations are not handled properly in removeNonFeasibleEdges. So far, only unfeasible cases are removed, but later code expects unreachable blocks to have no predecessors. This is causing the crash reported in PR49573. If the default destination is unfeasible it won't be executed. Create a new unreachable block on demand and use that as default destination. Note that at the moment this only is relevant for cases where resolvedUndefsIn marks the first case as executable. Regular switch handling has a FIXME/TODO to support determining whether the default case is feasible or not. Fixes #48917. Differential Revision: https://reviews.llvm.org/D113497
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Scalar/SCCP.cpp23
1 files changed, 21 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp
index d96a1a2..26c4ca1 100644
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp
@@ -336,7 +336,8 @@ static void findReturnsToZap(Function &F,
}
static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
- DomTreeUpdater &DTU) {
+ DomTreeUpdater &DTU,
+ BasicBlock *&NewUnreachableBB) {
SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors;
bool HasNonFeasibleEdges = false;
for (BasicBlock *Succ : successors(BB)) {
@@ -379,6 +380,23 @@ static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
} else if (FeasibleSuccessors.size() > 1) {
SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI));
SmallVector<DominatorTree::UpdateType, 8> Updates;
+
+ // If the default destination is unfeasible it will never be taken. Replace
+ // it with a new block with a single Unreachable instruction.
+ BasicBlock *DefaultDest = SI->getDefaultDest();
+ if (!FeasibleSuccessors.contains(DefaultDest)) {
+ if (!NewUnreachableBB) {
+ NewUnreachableBB =
+ BasicBlock::Create(DefaultDest->getContext(), "default.unreachable",
+ DefaultDest->getParent(), DefaultDest);
+ new UnreachableInst(DefaultDest->getContext(), NewUnreachableBB);
+ }
+
+ SI->setDefaultDest(NewUnreachableBB);
+ Updates.push_back({DominatorTree::Delete, BB, DefaultDest});
+ Updates.push_back({DominatorTree::Insert, BB, NewUnreachableBB});
+ }
+
for (auto CI = SI->case_begin(); CI != SI->case_end();) {
if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) {
++CI;
@@ -526,8 +544,9 @@ bool llvm::runIPSCCP(
NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHI(),
/*PreserveLCSSA=*/false, &DTU);
+ BasicBlock *NewUnreachableBB = nullptr;
for (BasicBlock &BB : F)
- MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU);
+ MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU, NewUnreachableBB);
for (BasicBlock *DeadBB : BlocksToErase)
if (!DeadBB->hasAddressTaken())