summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/PowerPC/PPC.td2
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp11
-rw-r--r--llvm/lib/Target/PowerPC/PPCSubtarget.cpp1
-rw-r--r--llvm/lib/Target/PowerPC/PPCSubtarget.h2
-rw-r--r--llvm/test/CodeGen/PowerPC/longcall.ll26
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 }
+
OpenPOWER on IntegriCloud