diff options
-rw-r--r-- | llvm/lib/Target/PowerPC/PPC.td | 2 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCSubtarget.h | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/PowerPC/longcall.ll | 26 |
5 files changed, 41 insertions, 1 deletions
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td index b40b530f4c5..ac1c3060046 100644 --- a/llvm/lib/Target/PowerPC/PPC.td +++ b/llvm/lib/Target/PowerPC/PPC.td @@ -136,6 +136,8 @@ def FeatureInvariantFunctionDescriptors : SubtargetFeature<"invariant-function-descriptors", "HasInvariantFunctionDescriptors", "true", "Assume function descriptors are invariant">; +def FeatureLongCall : SubtargetFeature<"longcall", "UseLongCalls", "true", + "Always use indirect calls">; def FeatureHTM : SubtargetFeature<"htm", "HasHTM", "true", "Enable Hardware Transactional Memory instructions">; def FeatureMFTB : SubtargetFeature<"", "FeatureMFTB", "true", diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index f895b06ac68..09887c3e4d1 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -4695,7 +4695,9 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, ImmutableCallSite *CS = CLI.CS; if (isTailCall) { - if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) + if (Subtarget.useLongCalls() && !(CS && CS->isMustTailCall())) + isTailCall = false; + else if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) isTailCall = IsEligibleForTailCallOptimization_64SVR4(Callee, CallConv, CS, isVarArg, Outs, Ins, DAG); @@ -4725,6 +4727,13 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, report_fatal_error("failed to perform tail call elimination on a call " "site marked musttail"); + // When long calls (i.e. indirect calls) are always used, calls are always + // made via function pointer. If we have a function name, first translate it + // into a pointer. + if (Subtarget.useLongCalls() && isa<GlobalAddressSDNode>(Callee) && + !isTailCall) + Callee = LowerGlobalAddress(Callee, DAG); + if (Subtarget.isSVR4ABI()) { if (Subtarget.isPPC64()) return LowerCall_64SVR4(Chain, Callee, CallConv, isVarArg, diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 603f0fccc7c..19570735295 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -105,6 +105,7 @@ void PPCSubtarget::initializeEnvironment() { HasFusion = false; HasFloat128 = false; IsISA3_0 = false; + UseLongCalls = false; HasPOPCNTD = POPCNTD_Unavailable; } diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h index 9fe286a3b7a..f58c7c10c8b 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -132,6 +132,7 @@ protected: bool HasFusion; bool HasFloat128; bool IsISA3_0; + bool UseLongCalls; POPCNTDKind HasPOPCNTD; @@ -275,6 +276,7 @@ public: bool hasFusion() const { return HasFusion; } bool hasFloat128() const { return HasFloat128; } bool isISA3_0() const { return IsISA3_0; } + bool useLongCalls() const { return UseLongCalls; } POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; } diff --git a/llvm/test/CodeGen/PowerPC/longcall.ll b/llvm/test/CodeGen/PowerPC/longcall.ll new file mode 100644 index 00000000000..9645ca8d31f --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/longcall.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +; Function Attrs: nounwind +define void @bar() local_unnamed_addr #0 { +entry: + tail call void @foo() #1 + ret void + +; CHECK-LABEL: @bar +; CHECK: ld [[FD:[0-9]+]], .LC0@toc@l({{[0-9]+}}) +; CHECK: ld [[ADDR:[0-9]+]], 0([[FD]]) +; CHECK: mtctr [[ADDR]] +; CHECK: bctrl +; CHECK-NOT: bl foo +; CHECK: blr +} + +; CHECK: .tc foo + +declare void @foo() local_unnamed_addr + +attributes #0 = { nounwind "target-cpu"="ppc64" "target-features"="+longcall" } +attributes #1 = { nounwind } + |