diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -1187,6 +1187,7 @@ CCAssignFn *ccAssignFnForCall(CallingConv::ID CC, bool Return, bool IsVarArg) const; + bool supportsTailCallFor(const CallBase *CB) const; private: struct ReuseLoadInfo { diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -5640,6 +5640,34 @@ DAG, InVals); } +bool PPCTargetLowering::supportsTailCallFor(const CallBase *CB) const { + CallingConv::ID CalleeCC = CB->getCallingConv(); + const Function *CallerFunc = CB->getCaller(); + CallingConv::ID CallerCC = CallerFunc->getCallingConv(); + const Function *CalleeFunc = CB->getCalledFunction(); + if (!CalleeFunc) + return false; + const GlobalValue *CalleeGV = dyn_cast(CalleeFunc); + + SmallVector Outs; + SmallVector Ins; + bool IsByValArg = false; + + GetReturnInfo(CalleeCC, CalleeFunc->getReturnType(), + CalleeFunc->getAttributes(), Outs, *this, + CalleeFunc->getParent()->getDataLayout()); + + for (const Argument &Arg : CalleeFunc->args()) + if (Arg.hasAttribute(Attribute::ByVal) || + Arg.hasAttribute(Attribute::InAlloca) || + Arg.hasAttribute(Attribute::Preallocated)) + IsByValArg = true; + + return isEligibleForTCO(CalleeGV, CalleeCC, CallerCC, CB, + CalleeFunc->isVarArg(), Outs, Ins, IsByValArg, + CallerFunc, false /*isCalleeExternalSymbol*/); +} + bool PPCTargetLowering::isEligibleForTCO( const GlobalValue *CalleeGV, CallingConv::ID CalleeCC, CallingConv::ID CallerCC, const CallBase *CB, bool isVarArg, diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -1078,17 +1078,5 @@ } bool PPCTTIImpl::supportsTailCallFor(const CallBase *CB) const { - // Subtargets using PC-Relative addressing supported. - if (ST->isUsingPCRelativeCalls()) - return true; - - const Function *Callee = CB->getCalledFunction(); - // Indirect calls and variadic argument functions not supported. - if (!Callee || Callee->isVarArg()) - return false; - - const Function *Caller = CB->getCaller(); - // Support if we can share TOC base. - return ST->getTargetMachine().shouldAssumeDSOLocal(*Caller->getParent(), - Callee); + return TLI->supportsTailCallFor(CB); } diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail-ppc64le.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail-ppc64le.ll --- a/llvm/test/Transforms/Coroutines/coro-split-musttail-ppc64le.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail-ppc64le.ll @@ -3,7 +3,14 @@ ; RUN: -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 | FileCheck %s ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S \ ; RUN: -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr10 --code-model=medium \ -; RUN: | FileCheck %s --check-prefix=CHECK-PCREL +; RUN: | FileCheck %s +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S \ +; RUN: -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr10 --code-model=medium -mattr=+longcall \ +; RUN: | FileCheck %s +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S \ +; RUN: -mtriple=powerpc-- | FileCheck %s +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S \ +; RUN: -mtriple=ppc32-- | FileCheck %s define void @f() #0 { entry: @@ -45,12 +52,6 @@ ; CHECK: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) ; CHECK-NEXT: call fastcc void %[[addr2]](ptr null) -; Verify that ppc target using PC-Relative addressing in the resume part resume call is marked with musttail. -; CHECK-PCREL-LABEL: @f.resume( -; CHECK-PCREL: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0) -; CHECK-PCREL-NEXT: musttail call fastcc void %[[addr2]](ptr null) -; CHECK-PCREL-NEXT: ret void - declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1 declare i1 @llvm.coro.alloc(token) #2 declare i64 @llvm.coro.size.i64() #3