mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 04:09:45 +00:00
Add support for a preserve_most calling convention to the AArch64 backend.
This change adds a support for a preserve_most calling convention to the AArch64 backend, similar to how it was done for X86-64. There is also a subsequent patch on top of this one to add a tail-calls support for this calling convention. Differential Revision: http://reviews.llvm.org/D18016 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263092 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d449fa84ed
commit
c461035332
@ -310,3 +310,7 @@ def CSR_AArch64_AllRegs
|
||||
(sequence "Q%u", 0, 31))>;
|
||||
|
||||
def CSR_AArch64_NoRegs : CalleeSavedRegs<(add)>;
|
||||
|
||||
def CSR_AArch64_RT_MostRegs : CalleeSavedRegs<(add CSR_AArch64_AAPCS,
|
||||
(sequence "X%u", 9, 15))>;
|
||||
|
||||
|
@ -723,10 +723,13 @@ static void computeCalleeSaveRegisterPairs(
|
||||
|
||||
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
CallingConv::ID CC = MF.getFunction()->getCallingConv();
|
||||
unsigned Count = CSI.size();
|
||||
(void)CC;
|
||||
// MachO's compact unwind format relies on all registers being stored in
|
||||
// pairs.
|
||||
assert((!MF.getSubtarget<AArch64Subtarget>().isTargetMachO() ||
|
||||
CC == CallingConv::PreserveMost ||
|
||||
(Count & 1) == 0) &&
|
||||
"Odd number of callee-saved regs to spill!");
|
||||
unsigned Offset = AFI->getCalleeSavedStackSize();
|
||||
@ -760,6 +763,7 @@ static void computeCalleeSaveRegisterPairs(
|
||||
// MachO's compact unwind format relies on all registers being stored in
|
||||
// adjacent register pairs.
|
||||
assert((!MF.getSubtarget<AArch64Subtarget>().isTargetMachO() ||
|
||||
CC == CallingConv::PreserveMost ||
|
||||
(RPI.isPaired() &&
|
||||
((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) ||
|
||||
RPI.Reg1 + 1 == RPI.Reg2))) &&
|
||||
|
@ -2455,6 +2455,7 @@ CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC,
|
||||
return CC_AArch64_GHC;
|
||||
case CallingConv::C:
|
||||
case CallingConv::Fast:
|
||||
case CallingConv::PreserveMost:
|
||||
if (!Subtarget->isTargetDarwin())
|
||||
return CC_AArch64_AAPCS;
|
||||
return IsVarArg ? CC_AArch64_DarwinPCS_VarArg : CC_AArch64_DarwinPCS;
|
||||
@ -2942,7 +2943,8 @@ bool AArch64TargetLowering::DoesCalleeRestoreStack(CallingConv::ID CallCC,
|
||||
}
|
||||
|
||||
bool AArch64TargetLowering::IsTailCallConvention(CallingConv::ID CallCC) const {
|
||||
return CallCC == CallingConv::Fast;
|
||||
return CallCC == CallingConv::Fast ||
|
||||
CallCC == CallingConv::PreserveMost;
|
||||
}
|
||||
|
||||
/// LowerCall - Lower a call to a callseq_start + CALL + callseq_end chain,
|
||||
|
@ -51,6 +51,8 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
return MF->getInfo<AArch64FunctionInfo>()->isSplitCSR() ?
|
||||
CSR_AArch64_CXX_TLS_Darwin_PE_SaveList :
|
||||
CSR_AArch64_CXX_TLS_Darwin_SaveList;
|
||||
if (MF->getFunction()->getCallingConv() == CallingConv::PreserveMost)
|
||||
return CSR_AArch64_RT_MostRegs_SaveList;
|
||||
else
|
||||
return CSR_AArch64_AAPCS_SaveList;
|
||||
}
|
||||
@ -74,6 +76,8 @@ AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
||||
return CSR_AArch64_AllRegs_RegMask;
|
||||
if (CC == CallingConv::CXX_FAST_TLS)
|
||||
return CSR_AArch64_CXX_TLS_Darwin_RegMask;
|
||||
if (CC == CallingConv::PreserveMost)
|
||||
return CSR_AArch64_RT_MostRegs_RegMask;
|
||||
else
|
||||
return CSR_AArch64_AAPCS_RegMask;
|
||||
}
|
||||
|
@ -1378,6 +1378,8 @@ ARMTargetLowering::getEffectiveCallingConv(CallingConv::ID CC,
|
||||
case CallingConv::ARM_APCS:
|
||||
case CallingConv::GHC:
|
||||
return CC;
|
||||
case CallingConv::PreserveMost:
|
||||
return CallingConv::PreserveMost;
|
||||
case CallingConv::ARM_AAPCS_VFP:
|
||||
return isVarArg ? CallingConv::ARM_AAPCS : CallingConv::ARM_AAPCS_VFP;
|
||||
case CallingConv::C:
|
||||
@ -1420,6 +1422,8 @@ CCAssignFn *ARMTargetLowering::CCAssignFnForNode(CallingConv::ID CC,
|
||||
return (Return ? RetFastCC_ARM_APCS : FastCC_ARM_APCS);
|
||||
case CallingConv::GHC:
|
||||
return (Return ? RetCC_ARM_APCS : CC_ARM_APCS_GHC);
|
||||
case CallingConv::PreserveMost:
|
||||
return (Return ? RetCC_ARM_AAPCS : CC_ARM_AAPCS);
|
||||
}
|
||||
}
|
||||
|
||||
|
40
test/CodeGen/AArch64/preserve_mostcc.ll
Normal file
40
test/CodeGen/AArch64/preserve_mostcc.ll
Normal file
@ -0,0 +1,40 @@
|
||||
; RUN: llc < %s -mtriple=arm64-apple-ios-8.0.0 | FileCheck %s
|
||||
|
||||
declare void @standard_cc_func()
|
||||
declare preserve_mostcc void @preserve_mostcc_func()
|
||||
|
||||
; Registers r9-r15 should be saved before the call of a function
|
||||
; with a standard calling convention.
|
||||
define preserve_mostcc void @preserve_mostcc1() nounwind {
|
||||
entry:
|
||||
;CHECK-LABEL: preserve_mostcc1
|
||||
;CHECK-NOT: stp
|
||||
;CHECK-NOT: str
|
||||
;CHECK: str x15
|
||||
;CHECK-NEXT: stp x14, x13,
|
||||
;CHECK-NEXT: stp x12, x11,
|
||||
;CHECK-NEXT: stp x10, x9,
|
||||
;CHECK: bl _standard_cc_func
|
||||
call void @standard_cc_func()
|
||||
;CHECK: ldp x10, x9,
|
||||
;CHECK-NEXT: ldp x12, x11,
|
||||
;CHECK-NEXT: ldp x14, x13,
|
||||
;CHECK-NEXT: ldr x15
|
||||
ret void
|
||||
}
|
||||
|
||||
; Registers r9-r15 don't need to be saved if one
|
||||
; function with preserve_mostcc calling convention calls another
|
||||
; function with preserve_mostcc calling convention, because the
|
||||
; callee wil save these registers anyways.
|
||||
define preserve_mostcc void @preserve_mostcc2() nounwind {
|
||||
entry:
|
||||
;CHECK-LABEL: preserve_mostcc2
|
||||
;CHECK-NOT: x14
|
||||
;CHECK: stp x29, x30,
|
||||
;CHECK-NOT: x14
|
||||
;CHECK: bl _preserve_mostcc_func
|
||||
call preserve_mostcc void @preserve_mostcc_func()
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user