[llvm-commits] [llvm] r86403 - in /llvm/trunk: lib/Target/README.txt lib/Transforms/Scalar/TailRecursionElimination.cpp test/Transforms/TailCallElim/switch.ll
Nick Lewycky
nicholas at mxc.ca
Sat Nov 7 13:10:15 PST 2009
Author: nicholas
Date: Sat Nov 7 15:10:15 2009
New Revision: 86403
URL: http://llvm.org/viewvc/llvm-project?rev=86403&view=rev
Log:
Improve tail call elimination to handle the switch statement.
Added:
llvm/trunk/test/Transforms/TailCallElim/switch.ll
Modified:
llvm/trunk/lib/Target/README.txt
llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
Modified: llvm/trunk/lib/Target/README.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/README.txt?rev=86403&r1=86402&r2=86403&view=diff
==============================================================================
--- llvm/trunk/lib/Target/README.txt (original)
+++ llvm/trunk/lib/Target/README.txt Sat Nov 7 15:10:15 2009
@@ -406,22 +406,6 @@
//===---------------------------------------------------------------------===//
-Tail recursion elimination is not transforming this function, because it is
-returning n, which fails the isDynamicConstant check in the accumulator
-recursion checks.
-
-long long fib(const long long n) {
- switch(n) {
- case 0:
- case 1:
- return n;
- default:
- return fib(n-1) + fib(n-2);
- }
-}
-
-//===---------------------------------------------------------------------===//
-
Tail recursion elimination should handle:
int pow2m1(int n) {
Modified: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp?rev=86403&r1=86402&r2=86403&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Sat Nov 7 15:10:15 2009
@@ -234,7 +234,7 @@
// We currently handle static constants and arguments that are not modified as
// part of the recursion.
//
-static bool isDynamicConstant(Value *V, CallInst *CI) {
+static bool isDynamicConstant(Value *V, CallInst *CI, ReturnInst *RI) {
if (isa<Constant>(V)) return true; // Static constants are always dyn consts
// Check to see if this is an immutable argument, if so, the value
@@ -252,6 +252,15 @@
if (CI->getOperand(ArgNo+1) == Arg)
return true;
}
+
+ // Switch cases are always constant integers. If the value is being switched
+ // on and the return is only reachable from one of its cases, it's
+ // effectively constant.
+ if (BasicBlock *UniquePred = RI->getParent()->getUniquePredecessor())
+ if (SwitchInst *SI = dyn_cast<SwitchInst>(UniquePred->getTerminator()))
+ if (SI->getCondition() == V)
+ return SI->getDefaultDest() != RI->getParent();
+
// Not a constant or immutable argument, we can't safely transform.
return false;
}
@@ -273,7 +282,7 @@
// evaluatable at the start of the initial invocation of the function,
// instead of at the end of the evaluation.
//
- if (!isDynamicConstant(RetOp, CI))
+ if (!isDynamicConstant(RetOp, CI, RI))
return 0;
if (ReturnedValue && RetOp != ReturnedValue)
Added: llvm/trunk/test/Transforms/TailCallElim/switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/switch.ll?rev=86403&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/switch.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/switch.ll Sat Nov 7 15:10:15 2009
@@ -0,0 +1,34 @@
+; RUN: opt %s -tailcallelim -S | FileCheck %s
+
+define i64 @fib(i64 %n) nounwind readnone {
+; CHECK: @fib
+entry:
+; CHECK: tailrecurse:
+; CHECK: %accumulator.tr = phi i64 [ %n, %entry ], [ %3, %bb1 ]
+; CHECK: %n.tr = phi i64 [ %n, %entry ], [ %2, %bb1 ]
+ switch i64 %n, label %bb1 [
+; CHECK: switch i64 %n.tr, label %bb1 [
+ i64 0, label %bb2
+ i64 1, label %bb2
+ ]
+
+bb1:
+; CHECK: bb1:
+ %0 = add i64 %n, -1
+; CHECK: %0 = add i64 %n.tr, -1
+ %1 = tail call i64 @fib(i64 %0) nounwind
+; CHECK: %1 = tail call i64 @fib(i64 %0)
+ %2 = add i64 %n, -2
+; CHECK: %2 = add i64 %n.tr, -2
+ %3 = tail call i64 @fib(i64 %2) nounwind
+; CHECK-NOT: tail call i64 @fib
+ %4 = add nsw i64 %3, %1
+; CHECK: add nsw i64 %accumulator.tr, %1
+ ret i64 %4
+; CHECK: br label %tailrecurse
+
+bb2:
+; CHECK: bb2:
+ ret i64 %n
+; CHECK: ret i64 %accumulator.tr
+}
More information about the llvm-commits
mailing list