[llvm-commits] [llvm] r101468 - in /llvm/trunk: lib/Transforms/Scalar/TailRecursionElimination.cpp test/Transforms/TailCallElim/inf-recursion.ll

Dan Gohman gohman at apple.com
Fri Apr 16 08:57:50 PDT 2010


Author: djg
Date: Fri Apr 16 10:57:50 2010
New Revision: 101468

URL: http://llvm.org/viewvc/llvm-project?rev=101468&view=rev
Log:
Refine the detection of seemingly infinitely recursive calls where the
callee is expected to be expanded to something else by codegen, so that
normal infinitely recursive calls are still transformed.

Modified:
    llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
    llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll

Modified: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp?rev=101468&r1=101467&r2=101468&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Fri Apr 16 10:57:50 2010
@@ -59,6 +59,8 @@
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/InlineCost.h"
+#include "llvm/Support/CallSite.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/ADT/Statistic.h"
 using namespace llvm;
@@ -328,15 +330,6 @@
   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.
   CallInst *CI;
@@ -356,6 +349,25 @@
   if (CI->isTailCall() && CannotTailCallElimCallsMarkedTail)
     return false;
 
+  // As a special case, detect code like this:
+  //   double fabs(double f) { return __builtin_fabs(f); } // a 'fabs' call
+  // and disable this xform in this case, because the code generator will
+  // lower the call to fabs into inline code.
+  if (BB == &F->getEntryBlock() && 
+      &BB->front() == CI && &*++BB->begin() == Ret &&
+      callIsSmall(F)) {
+    // A single-block function with just a call and a return. Check that
+    // the arguments match.
+    CallSite::arg_iterator I = CallSite(CI).arg_begin(),
+                           E = CallSite(CI).arg_end();
+    Function::arg_iterator FI = F->arg_begin(),
+                           FE = F->arg_end();
+    for (; I != E && FI != FE; ++I, ++FI)
+      if (*I != &*FI) break;
+    if (I == E && FI == FE)
+      return false;
+  }
+
   // If we are introducing accumulator recursion to eliminate associative
   // operations after the call instruction, this variable contains the initial
   // value for the accumulator.  If this value is set, we actually perform

Modified: llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll?rev=101468&r1=101467&r2=101468&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll (original)
+++ llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll Fri Apr 16 10:57:50 2010
@@ -1,6 +1,10 @@
-; RUN: opt < %s -tailcallelim -S | grep call
+; RUN: opt < %s -tailcallelim -S | FileCheck %s
+
 ; Don't turn this into an infinite loop, this is probably the implementation
 ; of fabs and we expect the codegen to lower fabs.
+; CHECK: @fabs(double %f)
+; CHECK: call
+; CHECK: ret
 
 define double @fabs(double %f) {
 entry:
@@ -8,3 +12,23 @@
         ret double %tmp2
 }
 
+; Do turn other calls into infinite loops though.
+
+; CHECK: define double @foo
+; CHECK-NOT: call
+; CHECK: }
+define double @foo(double %f) {
+        %t= call double @foo(double %f)
+        ret double %t
+}
+
+; CHECK: define float @fabsf
+; CHECK-NOT: call
+; CHECK: }
+define float @fabsf(float %f) {
+        %t= call float @fabsf(float 2.0)
+        ret float %t
+}
+
+declare float @fabsf(float %f)
+declare x86_fp80 @fabsl(x86_fp80 %f)





More information about the llvm-commits mailing list