aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/TailRecursionElimination.cpp9
-rw-r--r--test/Transforms/TailCallElim/inf-recursion.ll10
2 files changed, 19 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp
index 497b81f..7eb47dd 100644
--- a/lib/Transforms/Scalar/TailRecursionElimination.cpp
+++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp
@@ -302,6 +302,15 @@ bool TailCallElim::ProcessReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry,
if (&BB->front() == Ret) // Make sure there is something before the ret...
return false;
+
+ // If the return is in the entry block, then making this transformation would
+ // turn infinite recursion into an infinite loop. This transformation is ok
+ // in theory, but breaks some code like:
+ // double fabs(double f) { return __builtin_fabs(f); } // a 'fabs' call
+ // disable this xform in this case, because the code generator will lower the
+ // call to fabs into inline code.
+ if (BB == &F->getEntryBlock())
+ return false;
// Scan backwards from the return, checking to see if there is a tail call in
// this block. If so, set CI to it.
diff --git a/test/Transforms/TailCallElim/inf-recursion.ll b/test/Transforms/TailCallElim/inf-recursion.ll
new file mode 100644
index 0000000..d346171
--- /dev/null
+++ b/test/Transforms/TailCallElim/inf-recursion.ll
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | opt -tailcallelim | grep call
+; Don't turn this into an infinite loop, this is probably the implementation
+; of fabs and we expect the codegen to lower fabs.
+
+define double @fabs(double %f) {
+entry:
+ %tmp2 = call double @fabs( double %f ) ; <double> [#uses=1]
+ ret double %tmp2
+}
+