summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-04-06 17:21:31 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-04-06 17:21:31 +0000
commit9ceebb7e92e980340d199b550e3a2110c80ea871 (patch)
treeb04f5a1d3e691facff502a9feb782c8ca2b64623
parentbe2df1675df492092b6355803709a62296ad73aa (diff)
downloadexternal_llvm-9ceebb7e92e980340d199b550e3a2110c80ea871.zip
external_llvm-9ceebb7e92e980340d199b550e3a2110c80ea871.tar.gz
external_llvm-9ceebb7e92e980340d199b550e3a2110c80ea871.tar.bz2
Sink the collection of return instructions until after *all*
simplification has been performed. This is a bit less efficient (requires another ilist walk of the basic blocks) but shouldn't matter in practice. More importantly, it's just too much work to keep track of all the various ways the return instructions can be mutated while simplifying them. This fixes yet another crasher, reported by Daniel Dunbar. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154179 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Utils/CloneFunction.cpp16
-rw-r--r--test/Transforms/Inline/inline_cleanup.ll37
2 files changed, 46 insertions, 7 deletions
diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp
index 423f47d..20052a4 100644
--- a/lib/Transforms/Utils/CloneFunction.cpp
+++ b/lib/Transforms/Utils/CloneFunction.cpp
@@ -532,13 +532,6 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
// and we still want to prune the dead code as early as possible.
ConstantFoldTerminator(I);
- // Track all of the newly-inserted returns.
- if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator())) {
- Returns.push_back(RI);
- ++I;
- continue;
- }
-
BranchInst *BI = dyn_cast<BranchInst>(I->getTerminator());
if (!BI || BI->isConditional()) { ++I; continue; }
@@ -566,4 +559,13 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
// Do not increment I, iteratively merge all things this block branches to.
}
+
+ // Make a final pass over the basic blocks from theh old function to gather
+ // any return instructions which survived folding. We have to do this here
+ // because we can iteratively remove and merge returns above.
+ for (Function::iterator I = cast<BasicBlock>(VMap[&OldFunc->getEntryBlock()]),
+ E = NewFunc->end();
+ I != E; ++I)
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator()))
+ Returns.push_back(RI);
}
diff --git a/test/Transforms/Inline/inline_cleanup.ll b/test/Transforms/Inline/inline_cleanup.ll
index ee73b0e..3898aa7 100644
--- a/test/Transforms/Inline/inline_cleanup.ll
+++ b/test/Transforms/Inline/inline_cleanup.ll
@@ -174,3 +174,40 @@ entry:
call void @PR12470_inner(i16 signext 1)
ret void
}
+
+define void @crasher_inner() nounwind uwtable {
+entry:
+ br i1 false, label %for.end28, label %for.body6
+
+for.body6:
+ br i1 undef, label %for.body6, label %for.cond12.for.inc26_crit_edge
+
+for.cond12.for.inc26_crit_edge:
+ br label %for.body6.1
+
+for.end28:
+ ret void
+
+for.body6.1:
+ br i1 undef, label %for.body6.1, label %for.cond12.for.inc26_crit_edge.1
+
+for.cond12.for.inc26_crit_edge.1:
+ br label %for.body6.2
+
+for.body6.2:
+ br i1 undef, label %for.body6.2, label %for.cond12.for.inc26_crit_edge.2
+
+for.cond12.for.inc26_crit_edge.2:
+ br label %for.end28
+}
+
+define void @crasher_outer() {
+; CHECK: @crasher_outer
+; CHECK-NOT: call
+; CHECK: ret void
+; CHECK-NOT: ret
+; CHECK: }
+entry:
+ tail call void @crasher_inner()
+ ret void
+}