[llvm-commits] [llvm] r108241 - in /llvm/trunk: lib/Transforms/Scalar/TailRecursionElimination.cpp test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll
Duncan Sands
baldrick at free.fr
Tue Jul 13 08:41:41 PDT 2010
Author: baldrick
Date: Tue Jul 13 10:41:41 2010
New Revision: 108241
URL: http://llvm.org/viewvc/llvm-project?rev=108241&view=rev
Log:
Handle the case of a tail recursion in which the tail call is followed
by a return that returns a constant, while elsewhere in the function
another return instruction returns a different constant. This is a
special case of accumulator recursion, so just generalize the existing
logic a bit.
Modified:
llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll
Modified: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp?rev=108241&r1=108240&r2=108241&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Tue Jul 13 10:41:41 2010
@@ -373,7 +373,12 @@
// the call instruction that are both associative and commutative, the initial
// value for the accumulator is placed in this variable. If this value is set
// then we actually perform accumulator recursion elimination instead of
- // simple tail recursion elimination.
+ // simple tail recursion elimination. If the operation is an LLVM instruction
+ // (eg: "add") then it is recorded in AccumulatorRecursionInstr. If not, then
+ // we are handling the case when the return instruction returns a constant C
+ // which is different to the constant returned by other return instructions
+ // (which is recorded in AccumulatorRecursionEliminationInitVal). This is a
+ // special case of accumulator recursion, the operation being "return C".
Value *AccumulatorRecursionEliminationInitVal = 0;
Instruction *AccumulatorRecursionInstr = 0;
@@ -404,8 +409,18 @@
if (Ret->getNumOperands() == 1 && Ret->getReturnValue() != CI &&
!isa<UndefValue>(Ret->getReturnValue()) &&
AccumulatorRecursionEliminationInitVal == 0 &&
- !getCommonReturnValue(0, CI))
- return false;
+ !getCommonReturnValue(0, CI)) {
+ // One case remains that we are able to handle: the current return
+ // instruction returns a constant, and all other return instructions
+ // return a different constant.
+ if (!isDynamicConstant(Ret->getReturnValue(), CI, Ret))
+ return false; // Current return instruction does not return a constant.
+ // Check that all other return instructions return a common constant. If
+ // so, record it in AccumulatorRecursionEliminationInitVal.
+ AccumulatorRecursionEliminationInitVal = getCommonReturnValue(Ret, CI);
+ if (!AccumulatorRecursionEliminationInitVal)
+ return false;
+ }
// OK! We can transform this tail call. If this is the first one found,
// create the new entry block, allowing us to branch back to the old entry.
@@ -465,8 +480,9 @@
if (AccumulatorRecursionEliminationInitVal) {
Instruction *AccRecInstr = AccumulatorRecursionInstr;
// Start by inserting a new PHI node for the accumulator.
- PHINode *AccPN = PHINode::Create(AccRecInstr->getType(), "accumulator.tr",
- OldEntry->begin());
+ PHINode *AccPN =
+ PHINode::Create(AccumulatorRecursionEliminationInitVal->getType(),
+ "accumulator.tr", OldEntry->begin());
// Loop over all of the predecessors of the tail recursion block. For the
// real entry into the function we seed the PHI with the initial value,
@@ -483,14 +499,20 @@
AccPN->addIncoming(AccPN, P);
}
- // Add an incoming argument for the current block, which is computed by our
- // associative and commutative accumulator instruction.
- AccPN->addIncoming(AccRecInstr, BB);
-
- // Next, rewrite the accumulator recursion instruction so that it does not
- // use the result of the call anymore, instead, use the PHI node we just
- // inserted.
- AccRecInstr->setOperand(AccRecInstr->getOperand(0) != CI, AccPN);
+ if (AccRecInstr) {
+ // Add an incoming argument for the current block, which is computed by
+ // our associative and commutative accumulator instruction.
+ AccPN->addIncoming(AccRecInstr, BB);
+
+ // Next, rewrite the accumulator recursion instruction so that it does not
+ // use the result of the call anymore, instead, use the PHI node we just
+ // inserted.
+ AccRecInstr->setOperand(AccRecInstr->getOperand(0) != CI, AccPN);
+ } else {
+ // Add an incoming argument for the current block, which is just the
+ // constant returned by the current return instruction.
+ AccPN->addIncoming(Ret->getReturnValue(), BB);
+ }
// Finally, rewrite any return instructions in the program to return the PHI
// node instead of the "initval" that they do currently. This loop will
Modified: llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll?rev=108241&r1=108240&r2=108241&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll (original)
+++ llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll Tue Jul 13 10:41:41 2010
@@ -1,7 +1,9 @@
; RUN: opt < %s -tailcallelim -S | FileCheck %s
; PR7328
+; PR7506
define i32 @foo(i32 %x) {
; CHECK: define i32 @foo
+; CHECK: %accumulator.tr = phi i32 [ 1, %entry ], [ 0, %body ]
entry:
%cond = icmp ugt i32 %x, 0 ; <i1> [#uses=1]
br i1 %cond, label %return, label %body
@@ -9,8 +11,9 @@
body: ; preds = %entry
%y = add i32 %x, 1 ; <i32> [#uses=1]
%tmp = call i32 @foo(i32 %y) ; <i32> [#uses=0]
+; CHECK-NOT: call
ret i32 0
-; CHECK: ret i32 0
+; CHECK: ret i32 %accumulator.tr
return: ; preds = %entry
ret i32 1
More information about the llvm-commits
mailing list