diff options
author | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2018-09-20 09:00:17 +0000 |
---|---|---|
committer | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2018-09-20 09:00:17 +0000 |
commit | cd53b7f54efb22c6bf52cab1fbf95805033ca018 (patch) | |
tree | 4816566361325bafbe968b99655e1dd6d21959ae /llvm/lib/Transforms/Scalar/SCCP.cpp | |
parent | eb7f60201cb348223d3feec20638b3b084804a26 (diff) | |
download | bcm5719-llvm-cd53b7f54efb22c6bf52cab1fbf95805033ca018.tar.gz bcm5719-llvm-cd53b7f54efb22c6bf52cab1fbf95805033ca018.zip |
[IPSCCP] Fix a problem with removing labels in a switch with undef condition
Summary:
Before removing basic blocks that ipsccp has considered as dead
all uses of the basic block label must be removed. That is done
by calling ConstantFoldTerminator on the users. An exception
is when the branch condition is an undef value. In such
scenarios ipsccp is using some internal assumptions regarding
which edge in the control flow that should remain, while
ConstantFoldTerminator don't know how to fold the terminator.
The problem addressed here is related to ConstantFoldTerminator's
ability to rewrite a 'switch' into a conditional 'br'. In such
situations ConstantFoldTerminator returns true indicating that
the terminator has been rewritten. However, ipsccp treated the
true value as if the edge to the dead basic block had been
removed. So the code for resolving an undef branch condition
did not trigger, and we ended up with assertion that there were
uses remaining when deleting the basic block.
The solution is to resolve indeterminate branches before the
call to ConstantFoldTerminator.
Reviewers: efriedma, fhahn, davide
Reviewed By: fhahn
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D52232
llvm-svn: 342632
Diffstat (limited to 'llvm/lib/Transforms/Scalar/SCCP.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/SCCP.cpp | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index adb70f3c257..d024e03b80a 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1888,6 +1888,42 @@ static void findReturnsToZap(Function &F, } } +// Update the condition for terminators that are branching on indeterminate +// values, forcing them to use a specific edge. +static void forceIndeterminateEdge(Instruction* I, SCCPSolver &Solver) { + BasicBlock *Dest = nullptr; + Constant *C = nullptr; + if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) { + if (!isa<ConstantInt>(SI->getCondition())) { + // Indeterminate switch; use first case value. + Dest = SI->case_begin()->getCaseSuccessor(); + C = SI->case_begin()->getCaseValue(); + } + } else if (BranchInst *BI = dyn_cast<BranchInst>(I)) { + if (!isa<ConstantInt>(BI->getCondition())) { + // Indeterminate branch; use false. + Dest = BI->getSuccessor(1); + C = ConstantInt::getFalse(BI->getContext()); + } + } else if (IndirectBrInst *IBR = dyn_cast<IndirectBrInst>(I)) { + if (!isa<BlockAddress>(IBR->getAddress()->stripPointerCasts())) { + // Indeterminate indirectbr; use successor 0. + Dest = IBR->getSuccessor(0); + C = BlockAddress::get(IBR->getSuccessor(0)); + } + } else { + llvm_unreachable("Unexpected terminator instruction"); + } + if (C) { + assert(Solver.isEdgeFeasible(I->getParent(), Dest) && + "Didn't find feasible edge?"); + (void)Dest; + + I->setOperand(0, C); + } +} + + bool llvm::runIPSCCP( Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI, function_ref<std::unique_ptr<PredicateInfo>(Function &)> getPredicateInfo) { @@ -2017,32 +2053,10 @@ bool llvm::runIPSCCP( // Ignore blockaddress users; BasicBlock's dtor will handle them. if (!I) continue; + // If we have forced an edge for an indeterminate value, then force the + // terminator to fold to that edge. + forceIndeterminateEdge(I, Solver); bool Folded = ConstantFoldTerminator(I->getParent()); - if (!Folded) { - // If the branch can't be folded, we must have forced an edge - // for an indeterminate value. Force the terminator to fold - // to that edge. - Constant *C; - BasicBlock *Dest; - if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) { - Dest = SI->case_begin()->getCaseSuccessor(); - C = SI->case_begin()->getCaseValue(); - } else if (BranchInst *BI = dyn_cast<BranchInst>(I)) { - Dest = BI->getSuccessor(1); - C = ConstantInt::getFalse(BI->getContext()); - } else if (IndirectBrInst *IBR = dyn_cast<IndirectBrInst>(I)) { - Dest = IBR->getSuccessor(0); - C = BlockAddress::get(IBR->getSuccessor(0)); - } else { - llvm_unreachable("Unexpected terminator instruction"); - } - assert(Solver.isEdgeFeasible(I->getParent(), Dest) && - "Didn't find feasible edge?"); - (void)Dest; - - I->setOperand(0, C); - Folded = ConstantFoldTerminator(I->getParent()); - } assert(Folded && "Expect TermInst on constantint or blockaddress to be folded"); (void) Folded; |