summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp13
-rw-r--r--llvm/test/CodeGen/PowerPC/fastcc_stacksize.ll141
2 files changed, 152 insertions, 2 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 00dcb0db6b4..38e77bb0192 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -5467,6 +5467,11 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
// arguments that will be in registers.
unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
+ // Avoid allocating parameter area for fastcc functions if all the arguments
+ // can be passed in the registers.
+ if (CallConv == CallingConv::Fast)
+ HasParameterArea = false;
+
// Add up all the space actually used.
for (unsigned i = 0; i != NumOps; ++i) {
ISD::ArgFlagsTy Flags = Outs[i].Flags;
@@ -5477,9 +5482,11 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
continue;
if (CallConv == CallingConv::Fast) {
- if (Flags.isByVal())
+ if (Flags.isByVal()) {
NumGPRsUsed += (Flags.getByValSize()+7)/8;
- else
+ if (NumGPRsUsed > NumGPRs)
+ HasParameterArea = true;
+ } else {
switch (ArgVT.getSimpleVT().SimpleTy) {
default: llvm_unreachable("Unexpected ValueType for argument!");
case MVT::i1:
@@ -5516,6 +5523,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
continue;
break;
}
+ HasParameterArea = true;
+ }
}
/* Respect alignment of argument on the stack. */
diff --git a/llvm/test/CodeGen/PowerPC/fastcc_stacksize.ll b/llvm/test/CodeGen/PowerPC/fastcc_stacksize.ll
new file mode 100644
index 00000000000..e2921f6c17b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/fastcc_stacksize.ll
@@ -0,0 +1,141 @@
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+
+; Paramater Save Area is not needed if number of parameter does not exceed
+; number of registers
+; ------------------------------------------------------------------------------
+
+; Max number of GPR is 8
+define linkonce_odr void
+ @WithoutParamArea(i8* %a, i32 signext %b) align 2 {
+entry:
+ call fastcc void @fastccFunc(i32 signext 1)
+ ret void
+
+; CHECK-LABEL: WithoutParamArea
+; CHECK: stdu 1, -32(1)
+; CHECK: blr
+}
+declare fastcc void @fastccFunc(i32 signext %level) unnamed_addr
+
+; No need for Parameter Save Area if only 8 GPRs is needed.
+define linkonce_odr void @WithoutParamArea2(i8* %a, i32 signext %b) align 2 {
+entry:
+ call fastcc void @eightArgs(i32 signext 1, i32 signext 2, i32 signext 3,
+ i32 signext 4, i32 signext 5, i32 signext 6,
+ i32 signext 7, i32 signext 8)
+ ret void
+
+; CHECK-LABEL: WithoutParamArea2
+; CHECK: stdu 1, -32(1)
+; CHECK: blr
+}
+
+declare fastcc void
+ @eightArgs(i32 signext %level, i32 signext %level2, i32 signext %level3,
+ i32 signext %level4, i32 signext %level5, i32 signext %level6,
+ i32 signext %level7, i32 signext %level8) unnamed_addr
+
+; No need for Parameter Save Area for calls that utiliizes 8 GPR and 2 FPR.
+define linkonce_odr void @WithoutParamArea3(i8* %a, i32 signext %b) align 2 {
+entry:
+ call fastcc void
+ @mixedArgs(i32 signext 1, float 1.0, i32 signext 2, float 2.0,
+ i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6,
+ i32 signext 7, i32 signext 8) ret void
+ ret void
+
+; CHECK-LABEL : WithoutParamArea3
+; CHECK: stdu 1, -32(1)
+; CHECK: blr
+}
+
+declare fastcc void
+ @mixedArgs(i32 signext %level, float %levelf1, i32 signext %level2,
+ float %levelf2, i32 signext %level3, i32 signext %level4,
+ i32 signext %level5, i32 signext %level6, i32 signext %level7,
+ i32 signext %level8) unnamed_addr
+
+; Pass by value usage requiring less GPR then available
+%"myClass::Mem" = type { i8, i8, i16, i32, i32, i32, i64 }
+
+define internal fastcc void @CallPassByValue(%"myClass::Mem"* %E) align 2 {
+entry:
+ call fastcc void @PassByValue(%"myClass::Mem"* byval nonnull align 8 undef);
+ ret void
+
+; CHECK-LABEL : PassByValue
+; CHECK: stdu 1, -32(1)
+; CHECK: blr
+}
+
+declare dso_local fastcc void
+ @PassByValue(%"myClass::Mem"* byval nocapture readonly align 8) align 2
+
+; Verify Paramater Save Area is allocated if parameter exceed the number that
+; can be passed via registers
+; ------------------------------------------------------------------------------
+
+; Max number of GPR is 8
+define linkonce_odr void @WithParamArea(i8 * %a, i32 signext %b) align 2 {
+entry:
+ call fastcc void @nineArgs(i32 signext 1, i32 signext 2, i32 signext 3,
+ i32 signext 4, i32 signext 5, i32 signext 6,
+ i32 signext 7, i32 signext 8, i32 signext 9)
+ ret void
+
+; CHECK-LABEL: WithParamArea
+; CHECK: stdu 1, -96(1)
+; CHECK: blr
+}
+
+declare fastcc void @nineArgs(i32 signext %level, i32 signext %level2,
+ i32 signext %level3, i32 signext %level4, i32 signext %level5,
+ i32 signext %level6, i32 signext %level7, i32 signext %level8,
+ i32 signext %level9) unnamed_addr
+
+; Max number of FPR for parameter passing is 13
+define linkonce_odr void @WithParamArea2(i8* %a, i32 signext %b) align 2 {
+entry:
+ call fastcc void @funcW14FloatArgs(float 1.0, float 2.0, float 3.0,
+ float 4.0, float 5.0, float 6.0, float 7.0, float 8.0, float 1.0,
+ float 2.0, float 3.0, float 4.0, float 5.0, float 14.0)
+ ret void
+
+; CHECK-LABEL: WithParamArea2
+; CHECK: stdu 1, -96(1)
+; CHECK: blr
+}
+
+declare fastcc void
+ @funcW14FloatArgs(float %level, float %level2, float %level3,
+ float %level4, float %level5, float %level6,
+ float %level7, float %level8, float %level9,
+ float %level10, float %level11, float %level12,
+ float %level13, float %level14);
+
+
+; Pass by value usage requires more GPR then available
+%"myClass::MemA" = type { i8, i8, i16, i32, i32, i32, i64 }
+%"myClass::MemB" = type { i32*, i32, i32, %"myClass::MemB"** }
+%"myClass::MemC" = type { %"myClass::MemD"*, %"myClass::MemC"*, i64 }
+%"myClass::MemD" = type { %"myClass::MemB"*, %"myClass::MemC"*, i8, i8, i16,
+ i32 }
+%"myStruct::MemF" = type { i32, %"myClass::MemA"*, %"myClass::MemA"*, i64, i64 }
+%"myClass::MemK" = type { i32, %"myClass::MemD"*, %"myClass::MemD"*, i64, i32,
+ i64, i8, i32, %"myStruct::MemF",
+ i8, %"myClass::MemA"* }
+
+define internal fastcc void @AggMemExprEmitter(%"myClass::MemK"* %E) align 2 {
+entry:
+ call fastcc void @MemExprEmitterInitialization(%"myClass::MemK" *
+ byval nonnull align 8 undef);
+ ret void
+
+; CHECK-LABEL : AggMemExprEmitter
+; CHECK: stdu 1, -144(1)
+; CHECK: blr
+}
+
+declare dso_local fastcc void
+ @MemExprEmitterInitialization(%"myClass::MemK" *
+ byval nocapture readonly align 8) align 2
OpenPOWER on IntegriCloud