From 86809ccdaddf48a87ed772bc01464812caaf4baf Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 3 Feb 2010 03:28:02 +0000 Subject: Allow all types of callee's to be tail called. But avoid automatic tailcall if the callee is a result of bitcast to avoid losing necessary zext / sext etc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95195 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 13 ++++++++---- lib/Target/X86/X86ISelLowering.cpp | 18 +---------------- test/CodeGen/X86/tailcall2.ll | 25 ++++++++++++++++++++++++ test/CodeGen/X86/tailcallfp2.ll | 6 +++--- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 284b984..495418d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4197,8 +4197,9 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { /// /// This function only tests target-independent requirements. static bool -isInTailCallPosition(const Instruction *I, Attributes CalleeRetAttr, +isInTailCallPosition(CallSite CS, Attributes CalleeRetAttr, const TargetLowering &TLI) { + const Instruction *I = CS.getInstruction(); const BasicBlock *ExitBB = I->getParent(); const TerminatorInst *Term = ExitBB->getTerminator(); const ReturnInst *Ret = dyn_cast(Term); @@ -4207,6 +4208,12 @@ isInTailCallPosition(const Instruction *I, Attributes CalleeRetAttr, // The block must end in a return statement or an unreachable. if (!Ret && !isa(Term)) return false; + // Unless we are explicitly forcing tailcall optimization do not tailcall if + // the called function is bitcast'ed. The analysis may not be entirely + // accurate. + if (!PerformTailCallOpt && isa(CS.getCalledValue())) + return false; + // If I will have a chain, make sure no other instruction that will have a // chain interposes between I and the return. if (I->mayHaveSideEffects() || I->mayReadFromMemory() || @@ -4348,9 +4355,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, // Check if target-independent constraints permit a tail call here. // Target-dependent constraints are checked within TLI.LowerCallTo. if (isTailCall && - !isInTailCallPosition(CS.getInstruction(), - CS.getAttributes().getRetAttributes(), - TLI)) + !isInTailCallPosition(CS, CS.getAttributes().getRetAttributes(), TLI)) isTailCall = false; std::pair Result = diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6f710ec..9d6b5a3 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2269,7 +2269,6 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, return false; } - // Look for obvious safe cases to perform tail call optimization that does not // requite ABI changes. This is what gcc calls sibcall. @@ -2324,22 +2323,7 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, } } - // If the caller does not return a value, then this is obviously safe. - // This is one case where it's safe to perform this optimization even - // if the return types do not match. - const Type *CallerRetTy = CallerF->getReturnType(); - if (CallerRetTy->isVoidTy()) - return true; - - // If the return types match, then it's safe. - // Don't tail call optimize recursive call. - GlobalAddressSDNode *G = dyn_cast(Callee); - if (!G) return false; // FIXME: common external symbols? - if (const Function *CalleeF = dyn_cast(G->getGlobal())) { - const Type *CalleeRetTy = CalleeF->getReturnType(); - return CallerRetTy == CalleeRetTy; - } - return false; + return true; } FastISel * diff --git a/test/CodeGen/X86/tailcall2.ll b/test/CodeGen/X86/tailcall2.ll index e41e3da..81419dc 100644 --- a/test/CodeGen/X86/tailcall2.ll +++ b/test/CodeGen/X86/tailcall2.ll @@ -102,3 +102,28 @@ entry: } declare i32 @bar2(i32, i32, i32) + +define signext i16 @t8() nounwind ssp { +entry: +; 32: t8: +; 32: jmp {{_?}}bar3 + +; 64: t8: +; 64: jmp {{_?}}bar3 + %0 = tail call signext i16 @bar3() nounwind ; [#uses=1] + ret i16 %0 +} + +declare signext i16 @bar3() + +define signext i16 @t9(i32 (i32)* nocapture %x) nounwind ssp { +entry: +; 32: t9: +; 32: call * + +; 64: t9: +; 64: callq * + %0 = bitcast i32 (i32)* %x to i16 (i32)* + %1 = tail call signext i16 %0(i32 0) nounwind + ret i16 %1 +} diff --git a/test/CodeGen/X86/tailcallfp2.ll b/test/CodeGen/X86/tailcallfp2.ll index be4f96c..3841f51 100644 --- a/test/CodeGen/X86/tailcallfp2.ll +++ b/test/CodeGen/X86/tailcallfp2.ll @@ -2,7 +2,7 @@ declare i32 @putchar(i32) -define fastcc i32 @checktail(i32 %x, i32* %f, i32 %g) { +define fastcc i32 @checktail(i32 %x, i32* %f, i32 %g) nounwind { %tmp1 = icmp sgt i32 %x, 0 br i1 %tmp1, label %if-then, label %if-else @@ -18,8 +18,8 @@ if-else: } -define i32 @main() { +define i32 @main() nounwind { %f = bitcast i32 (i32, i32*, i32)* @checktail to i32* %res = tail call fastcc i32 @checktail( i32 10, i32* %f,i32 10) ret i32 %res -} \ No newline at end of file +} -- cgit v1.1