Skip to content

Commit

Permalink
[PowerPC] Reduce stack frame for fastcc functions by only allocating …
Browse files Browse the repository at this point in the history
…parameter save area when needed

Current implementation always allocates the parameter save area conservatively
for fastcc functions. There is no reason to allocate the parameter save area if
all the parameters can be passed via registers.

Differential Revision: https://reviews.llvm.org/D42602

llvm-svn: 325581
  • Loading branch information
lei137 committed Feb 20, 2018
1 parent b404fae commit dfd4155
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 2 deletions.
13 changes: 11 additions & 2 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Expand Up @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -5516,6 +5523,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
continue;
break;
}
HasParameterArea = true;
}
}

/* Respect alignment of argument on the stack. */
Expand Down
141 changes: 141 additions & 0 deletions 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

0 comments on commit dfd4155

Please sign in to comment.