From d50e9e2566479301e687fc81e16dab7e3c2b50ea Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sat, 26 Jun 2010 12:53:31 +0000 Subject: [PATCH] Fix PR7328: when turning a tail recursion into a loop, need to preserve the returned value after the tail call if it differs from other return values. The optimal thing to do would be to introduce a phi node for the return value, but for the moment just fix the miscompile. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106947 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/TailRecursionElimination.cpp | 12 ++++++------ .../2010-06-26-MultipleReturnValues.ll | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp index 42f4a5f71d0..97e53e23d2a 100644 --- a/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -270,16 +270,16 @@ static bool isDynamicConstant(Value *V, CallInst *CI, ReturnInst *RI) { } // getCommonReturnValue - Check to see if the function containing the specified -// return instruction and tail call consistently returns the same -// runtime-constant value at all exit points. If so, return the returned value. +// tail call consistently returns the same runtime-constant value at all exit +// points except for IgnoreRI. If so, return the returned value. // -static Value *getCommonReturnValue(ReturnInst *TheRI, CallInst *CI) { - Function *F = TheRI->getParent()->getParent(); +static Value *getCommonReturnValue(ReturnInst *IgnoreRI, CallInst *CI) { + Function *F = CI->getParent()->getParent(); Value *ReturnedValue = 0; for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI) if (ReturnInst *RI = dyn_cast(BBI->getTerminator())) - if (RI != TheRI) { + if (RI != IgnoreRI) { Value *RetOp = RI->getOperand(0); // We can only perform this transformation if the value returned is @@ -404,7 +404,7 @@ bool TailCallElim::ProcessReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry, if (Ret->getNumOperands() == 1 && Ret->getReturnValue() != CI && !isa(Ret->getReturnValue()) && AccumulatorRecursionEliminationInitVal == 0 && - !getCommonReturnValue(Ret, CI)) + !getCommonReturnValue(0, CI)) return false; // OK! We can transform this tail call. If this is the first one found, diff --git a/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll b/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll new file mode 100644 index 00000000000..f39476f7daf --- /dev/null +++ b/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -tailcallelim -S | FileCheck %s +; PR7328 +define i32 @foo(i32 %x) { +; CHECK: define i32 @foo +entry: + %cond = icmp ugt i32 %x, 0 ; [#uses=1] + br i1 %cond, label %return, label %body + +body: ; preds = %entry + %y = add i32 %x, 1 ; [#uses=1] + %tmp = call i32 @foo(i32 %y) ; [#uses=0] + ret i32 0 +; CHECK: ret i32 0 + +return: ; preds = %entry + ret i32 1 +} -- 2.34.1