Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -4397,13 +4397,18 @@ static bool areCallingConvEligibleForTCO_64SVR4(CallingConv::ID CallerCC, CallingConv::ID CalleeCC) { - // Tail or Sibling call optimization (TCO/SCO) needs callee and caller to - // have the same calling convention. - if (CallerCC != CalleeCC) + // tail calls are possible with fastcc and ccc. + auto isTailCallableCC = [] (CallingConv::ID CC){ + return CC == CallingConv::C || CC == CallingConv::Fast; + }; + if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC)) return false; - // Tail or Sibling calls can be done with fastcc/ccc. - return (CallerCC == CallingConv::Fast || CallerCC == CallingConv::C); + // We can safely tail call both fastcc and ccc callees from a c calling + // convention caller. If the caller is fastcc, we may have less stack space + // then a non-fastcc caller with the same signature so disable tail-calls in + // that case. + return CallerCC == CallingConv::C || CallerCC == CalleeCC; } bool @@ -4438,6 +4443,12 @@ if (any_of(Outs, [](const ISD::OutputArg& OA) { return OA.Flags.isByVal(); })) return false; + // If callee and caller use different calling conventions, we cannot pass + // parameters on stack since offsets for the parameter area may be different. + if (Caller->getCallingConv() != CalleeCC && + needStackSlotPassParameters(Subtarget, Outs)) + return false; + // No TCO/SCO on indirect call because Caller have to restore its TOC if (!isFunctionGlobalAddress(Callee) && !isa(Callee)) Index: test/CodeGen/PowerPC/duplicate-returns-for-tailcall.ll =================================================================== --- test/CodeGen/PowerPC/duplicate-returns-for-tailcall.ll +++ test/CodeGen/PowerPC/duplicate-returns-for-tailcall.ll @@ -42,10 +42,10 @@ if.then6: ; preds = %if.end4 %call7 = tail call fastcc signext i32 @call3(i32 signext %a, i32 signext %b, i32 signext %c) br label %return -; No duplication here because the calling convention mismatch means we won't tail-call +; tail calling a fastcc function from a ccc function is supported. ; CHECK_LABEL: if.then13: -; CHECK: tail call fastcc signext i32 @call3 -; CHECK-NEXT: br +; CHECK: %[[T2:[a-zA-Z0-9]+]] = tail call fastcc signext i32 @call3 +; CHECK-NEXT: ret i32 %[[T2]] return: ; preds = %if.end4, %if.then6, %if.then2, %if.then %retval.0 = phi i32 [ %call, %if.then ], [ %call3, %if.then2 ], [ %call7, %if.then6 ], [ %c, %if.end4 ] Index: test/CodeGen/PowerPC/ppc64-sibcall.ll =================================================================== --- test/CodeGen/PowerPC/ppc64-sibcall.ll +++ test/CodeGen/PowerPC/ppc64-sibcall.ll @@ -41,6 +41,15 @@ ; CHECK-SCO: b callee_64_64_copy } +define internal fastcc void @callee_64_64_copy_fastcc([8 x i64] %a, [8 x i64] %b) #0 { ret void } +define void @caller_64_64_copy_ccc([8 x i64] %a, [8 x i64] %b) #1 { + tail call fastcc void @callee_64_64_copy_fastcc([8 x i64] %a, [8 x i64] %b) + ret void + +; CHECK-SCO-LABEL: caller_64_64_copy_ccc: +; CHECK-SCO: bl callee_64_64_copy_fastcc +} + define void @caller_64_64_reorder_copy([8 x i64] %a, [8 x i64] %b) #1 { tail call void @callee_64_64_copy([8 x i64] %b, [8 x i64] %a) ret void