summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/SCCP.cpp
diff options
context:
space:
mode:
authorBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2018-09-20 09:00:17 +0000
committerBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2018-09-20 09:00:17 +0000
commitcd53b7f54efb22c6bf52cab1fbf95805033ca018 (patch)
tree4816566361325bafbe968b99655e1dd6d21959ae /llvm/lib/Transforms/Scalar/SCCP.cpp
parenteb7f60201cb348223d3feec20638b3b084804a26 (diff)
downloadbcm5719-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.cpp64
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;
OpenPOWER on IntegriCloud