summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikael Holmen <mikael.holmen@ericsson.com>2018-08-28 12:40:11 +0000
committerMikael Holmen <mikael.holmen@ericsson.com>2018-08-28 12:40:11 +0000
commit4d652c4ce75f4de60054de79f9f3fdee4cc1806f (patch)
tree7656a41a651722cc8953af07d692a1b3d924cf07
parentb7e10182cec42162e22bc483931be689b50371f4 (diff)
downloadbcm5719-llvm-4d652c4ce75f4de60054de79f9f3fdee4cc1806f.tar.gz
bcm5719-llvm-4d652c4ce75f4de60054de79f9f3fdee4cc1806f.zip
[CloneFunction] Constant fold terminators before checking single predecessor
Summary: This fixes PR31105. There is code trying to delete dead code that does so by e.g. checking if the single predecessor of a block is the block itself. That check fails on a block like this bb: br i1 undef, label %bb, label %bb since that has two (identical) predecessors. However, after the check for dead blocks there is a call to ConstantFoldTerminator on the basic block, and that call simplifies the block to bb: br label %bb Therefore we now do the call to ConstantFoldTerminator before the check if the block is dead, so it can realize that it really is. The original behavior lead to the block not being removed, but it was simplified as above, and then we did a call to Dest->replaceAllUsesWith(&*I); with old and new being equal, and an assertion triggered. Reviewers: chandlerc, fhahn Reviewed By: fhahn Subscribers: eraman, llvm-commits Differential Revision: https://reviews.llvm.org/D51280 llvm-svn: 340820
-rw-r--r--llvm/lib/Transforms/Utils/CloneFunction.cpp23
-rw-r--r--llvm/test/Transforms/Inline/infinite-loop-two-predecessors.ll32
2 files changed, 48 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 4a51424a4da..a9257a8c670 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -636,6 +636,22 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB])->getIterator();
Function::iterator I = Begin;
while (I != NewFunc->end()) {
+ // We need to simplify conditional branches and switches with a constant
+ // operand. We try to prune these out when cloning, but if the
+ // simplification required looking through PHI nodes, those are only
+ // available after forming the full basic block. That may leave some here,
+ // and we still want to prune the dead code as early as possible.
+ //
+ // Do the folding before we check if the block is dead since we want code
+ // like
+ // bb:
+ // br i1 undef, label %bb, label %bb
+ // to be simplified to
+ // bb:
+ // br label %bb
+ // before we call I->getSinglePredecessor().
+ ConstantFoldTerminator(&*I);
+
// Check if this block has become dead during inlining or other
// simplifications. Note that the first block will appear dead, as it has
// not yet been wired up properly.
@@ -646,13 +662,6 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
continue;
}
- // We need to simplify conditional branches and switches with a constant
- // operand. We try to prune these out when cloning, but if the
- // simplification required looking through PHI nodes, those are only
- // available after forming the full basic block. That may leave some here,
- // and we still want to prune the dead code as early as possible.
- ConstantFoldTerminator(&*I);
-
BranchInst *BI = dyn_cast<BranchInst>(I->getTerminator());
if (!BI || BI->isConditional()) { ++I; continue; }
diff --git a/llvm/test/Transforms/Inline/infinite-loop-two-predecessors.ll b/llvm/test/Transforms/Inline/infinite-loop-two-predecessors.ll
new file mode 100644
index 00000000000..aa07315eb08
--- /dev/null
+++ b/llvm/test/Transforms/Inline/infinite-loop-two-predecessors.ll
@@ -0,0 +1,32 @@
+; RUN: opt -S -o - %s -inline | FileCheck %s
+
+define void @f1() {
+bb.0:
+ br i1 false, label %bb.2, label %bb.1
+
+bb.1: ; preds = %bb.0
+ br label %bb.2
+
+bb.2: ; preds = %bb.0, %bb.1
+ %tmp0 = phi i1 [ true, %bb.1 ], [ false, %bb.0 ]
+ br i1 %tmp0, label %bb.4, label %bb.3
+
+bb.3: ; preds = %bb.3, %bb.3
+ br i1 undef, label %bb.3, label %bb.3
+
+bb.4: ; preds = %bb.2
+ ret void
+}
+
+define void @f2() {
+bb.0:
+ call void @f1()
+ ret void
+}
+
+; f1 should be inlined into f2 and simplified/collapsed to nothing.
+
+; CHECK-LABEL: define void @f2() {
+; CHECK-NEXT: bb.0:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
OpenPOWER on IntegriCloud