mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[ARM] GlobalISel: Lower i32 and fp call parameters on the stack
Lower i32, float and double parameters that need to live on the stack. This boils down to creating some G_GEPs starting from the stack pointer and storing the values there. During the process we also keep track of the stack size and use the final value in the ADJCALLSTACKDOWN/UP instructions. We currently assert for smaller types, since they usually require extensions. They will be handled in a separate patch. llvm-svn: 296473
This commit is contained in:
parent
9f47d8e6fa
commit
c958dc921b
@ -53,11 +53,27 @@ namespace {
|
||||
struct OutgoingValueHandler : public CallLowering::ValueHandler {
|
||||
OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
||||
MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
|
||||
: ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
|
||||
: ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB), StackSize(0) {}
|
||||
|
||||
unsigned getStackAddress(uint64_t Size, int64_t Offset,
|
||||
MachinePointerInfo &MPO) override {
|
||||
llvm_unreachable("Don't know how to get a stack address yet");
|
||||
// FIXME: Support smaller sizes (which may require extensions).
|
||||
assert((Size == 4 || Size == 8) && "Unsupported size");
|
||||
|
||||
LLT p0 = LLT::pointer(0, 32);
|
||||
LLT s32 = LLT::scalar(32);
|
||||
unsigned SPReg = MRI.createGenericVirtualRegister(p0);
|
||||
MIRBuilder.buildCopy(SPReg, ARM::SP);
|
||||
|
||||
unsigned OffsetReg = MRI.createGenericVirtualRegister(s32);
|
||||
MIRBuilder.buildConstant(OffsetReg, Offset);
|
||||
|
||||
unsigned AddrReg = MRI.createGenericVirtualRegister(p0);
|
||||
MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg);
|
||||
|
||||
MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
|
||||
StackSize = std::max(StackSize, Size + Offset);
|
||||
return AddrReg;
|
||||
}
|
||||
|
||||
void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
|
||||
@ -75,7 +91,12 @@ struct OutgoingValueHandler : public CallLowering::ValueHandler {
|
||||
|
||||
void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
|
||||
MachinePointerInfo &MPO, CCValAssign &VA) override {
|
||||
llvm_unreachable("Don't know how to assign a value to an address yet");
|
||||
// FIXME: Support smaller sizes (which may require extensions).
|
||||
assert((Size == 4 || Size == 8) && "Unsupported size");
|
||||
|
||||
auto MMO = MIRBuilder.getMF().getMachineMemOperand(
|
||||
MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0);
|
||||
MIRBuilder.buildStore(ValVReg, Addr, *MMO);
|
||||
}
|
||||
|
||||
unsigned assignCustomValue(const CallLowering::ArgInfo &Arg,
|
||||
@ -110,6 +131,7 @@ struct OutgoingValueHandler : public CallLowering::ValueHandler {
|
||||
}
|
||||
|
||||
MachineInstrBuilder &MIB;
|
||||
uint64_t StackSize;
|
||||
};
|
||||
} // End anonymous namespace.
|
||||
|
||||
@ -352,9 +374,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
|
||||
if (MF.getSubtarget<ARMSubtarget>().genLongCalls())
|
||||
return false;
|
||||
|
||||
MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN)
|
||||
.addImm(0)
|
||||
.add(predOps(ARMCC::AL));
|
||||
auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN);
|
||||
|
||||
// FIXME: This is the calling convention of the caller - we should use the
|
||||
// calling convention of the callee instead.
|
||||
@ -397,8 +417,12 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
|
||||
return false;
|
||||
}
|
||||
|
||||
// We now know the size of the stack - update the ADJCALLSTACKDOWN
|
||||
// accordingly.
|
||||
CallSeqStart.addImm(ArgHandler.StackSize).add(predOps(ARMCC::AL));
|
||||
|
||||
MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP)
|
||||
.addImm(0)
|
||||
.addImm(ArgHandler.StackSize)
|
||||
.addImm(0)
|
||||
.add(predOps(ARMCC::AL));
|
||||
|
||||
|
@ -359,22 +359,51 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare arm_aapcscc i32* @simple_params_target(i32, i32*)
|
||||
declare arm_aapcscc i32* @simple_reg_params_target(i32, i32*)
|
||||
|
||||
define arm_aapcscc i32* @test_call_simple_params(i32 *%a, i32 %b) {
|
||||
; CHECK-LABEL: name: test_call_simple_params
|
||||
define arm_aapcscc i32* @test_call_simple_reg_params(i32 *%a, i32 %b) {
|
||||
; CHECK-LABEL: name: test_call_simple_reg_params
|
||||
; CHECK-DAG: [[AVREG:%[0-9]+]](p0) = COPY %r0
|
||||
; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %r1
|
||||
; CHECK: ADJCALLSTACKDOWN 0, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK-DAG: %r0 = COPY [[BVREG]]
|
||||
; CHECK-DAG: %r1 = COPY [[AVREG]]
|
||||
; CHECK: BLX @simple_params_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0
|
||||
; CHECK: BLX @simple_reg_params_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0
|
||||
; CHECK: [[RVREG:%[0-9]+]](p0) = COPY %r0
|
||||
; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK: %r0 = COPY [[RVREG]]
|
||||
; CHECK: BX_RET 14, _, implicit %r0
|
||||
entry:
|
||||
%r = notail call arm_aapcscc i32 *@simple_params_target(i32 %b, i32 *%a)
|
||||
%r = notail call arm_aapcscc i32 *@simple_reg_params_target(i32 %b, i32 *%a)
|
||||
ret i32 *%r
|
||||
}
|
||||
|
||||
declare arm_aapcscc i32* @simple_stack_params_target(i32, i32*, i32, i32*, i32, i32*)
|
||||
|
||||
define arm_aapcscc i32* @test_call_simple_stack_params(i32 *%a, i32 %b) {
|
||||
; CHECK-LABEL: name: test_call_simple_stack_params
|
||||
; CHECK-DAG: [[AVREG:%[0-9]+]](p0) = COPY %r0
|
||||
; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %r1
|
||||
; CHECK: ADJCALLSTACKDOWN 8, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK-DAG: %r0 = COPY [[BVREG]]
|
||||
; CHECK-DAG: %r1 = COPY [[AVREG]]
|
||||
; CHECK-DAG: %r2 = COPY [[BVREG]]
|
||||
; CHECK-DAG: %r3 = COPY [[AVREG]]
|
||||
; CHECK: [[SP1:%[0-9]+]](p0) = COPY %sp
|
||||
; CHECK: [[OFF1:%[0-9]+]](s32) = G_CONSTANT i32 0
|
||||
; CHECK: [[FI1:%[0-9]+]](p0) = G_GEP [[SP1]], [[OFF1]](s32)
|
||||
; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0)
|
||||
; CHECK: [[SP2:%[0-9]+]](p0) = COPY %sp
|
||||
; CHECK: [[OFF2:%[0-9]+]](s32) = G_CONSTANT i32 4
|
||||
; CHECK: [[FI2:%[0-9]+]](p0) = G_GEP [[SP2]], [[OFF2]](s32)
|
||||
; CHECK: G_STORE [[AVREG]](p0), [[FI2]](p0)
|
||||
; CHECK: BLX @simple_stack_params_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0
|
||||
; CHECK: [[RVREG:%[0-9]+]](p0) = COPY %r0
|
||||
; CHECK: ADJCALLSTACKUP 8, 0, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK: %r0 = COPY [[RVREG]]
|
||||
; CHECK: BX_RET 14, _, implicit %r0
|
||||
entry:
|
||||
%r = notail call arm_aapcscc i32 *@simple_stack_params_target(i32 %b, i32 *%a, i32 %b, i32 *%a, i32 %b, i32 *%a)
|
||||
ret i32 *%r
|
||||
}
|
||||
|
||||
@ -423,7 +452,7 @@ entry:
|
||||
ret double %r
|
||||
}
|
||||
|
||||
declare arm_aapcscc double @aapcscc_fp_target(float, double)
|
||||
declare arm_aapcscc double @aapcscc_fp_target(float, double, float, double)
|
||||
|
||||
define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) {
|
||||
; CHECK-LABEL: name: test_call_aapcs_fp_params
|
||||
@ -432,19 +461,27 @@ define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) {
|
||||
; LITTLE-DAG: [[AVREG:%[0-9]+]](s64) = G_SEQUENCE [[A1]](s32), 0, [[A2]](s32), 32
|
||||
; BIG-DAG: [[AVREG:%[0-9]+]](s64) = G_SEQUENCE [[A2]](s32), 0, [[A1]](s32), 32
|
||||
; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %r2
|
||||
; CHECK: ADJCALLSTACKDOWN 0, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK: ADJCALLSTACKDOWN 16, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK-DAG: %r0 = COPY [[BVREG]]
|
||||
; CHECK-DAG: [[A1:%[0-9]+]](s32), [[A2:%[0-9]+]](s32) = G_EXTRACT [[AVREG]](s64), 0, 32
|
||||
; LITTLE-DAG: %r2 = COPY [[A1]]
|
||||
; LITTLE-DAG: %r3 = COPY [[A2]]
|
||||
; BIG-DAG: %r2 = COPY [[A2]]
|
||||
; BIG-DAG: %r3 = COPY [[A1]]
|
||||
; CHECK: [[SP1:%[0-9]+]](p0) = COPY %sp
|
||||
; CHECK: [[OFF1:%[0-9]+]](s32) = G_CONSTANT i32 0
|
||||
; CHECK: [[FI1:%[0-9]+]](p0) = G_GEP [[SP1]], [[OFF1]](s32)
|
||||
; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0)
|
||||
; CHECK: [[SP2:%[0-9]+]](p0) = COPY %sp
|
||||
; CHECK: [[OFF2:%[0-9]+]](s32) = G_CONSTANT i32 8
|
||||
; CHECK: [[FI2:%[0-9]+]](p0) = G_GEP [[SP2]], [[OFF2]](s32)
|
||||
; CHECK: G_STORE [[AVREG]](s64), [[FI2]](p0)
|
||||
; CHECK: BLX @aapcscc_fp_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1
|
||||
; CHECK-DAG: [[R1:%[0-9]+]](s32) = COPY %r0
|
||||
; CHECK-DAG: [[R2:%[0-9]+]](s32) = COPY %r1
|
||||
; LITTLE: [[RVREG:%[0-9]+]](s64) = G_SEQUENCE [[R1]](s32), 0, [[R2]](s32), 32
|
||||
; BIG: [[RVREG:%[0-9]+]](s64) = G_SEQUENCE [[R2]](s32), 0, [[R1]](s32), 32
|
||||
; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK: ADJCALLSTACKUP 16, 0, 14, _, implicit-def %sp, implicit %sp
|
||||
; CHECK: [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32) = G_EXTRACT [[RVREG]](s64), 0, 32
|
||||
; LITTLE-DAG: %r0 = COPY [[R1]]
|
||||
; LITTLE-DAG: %r1 = COPY [[R2]]
|
||||
@ -452,6 +489,6 @@ define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) {
|
||||
; BIG-DAG: %r1 = COPY [[R1]]
|
||||
; CHECK: BX_RET 14, _, implicit %r0, implicit %r1
|
||||
entry:
|
||||
%r = notail call arm_aapcscc double @aapcscc_fp_target(float %b, double %a)
|
||||
%r = notail call arm_aapcscc double @aapcscc_fp_target(float %b, double %a, float %b, double %a)
|
||||
ret double %r
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user