From 5e983188417d0cf30c046a89cd40068c4a659894 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Thu, 23 Feb 2017 13:25:43 +0000 Subject: [PATCH] [ARM] GlobalISel: Lower call parameters in regs Add support for lowering calls with parameters than can fit into regs. Use the same ValueHandler that we used for function returns, but rename it to match its new, extended purpose. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295971 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMCallLowering.cpp | 54 +++++++++---- .../ARM/GlobalISel/arm-irtranslator.ll | 77 +++++++++++++++++++ 2 files changed, 116 insertions(+), 15 deletions(-) diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp index 64e870cd1f0..7ba859921c2 100644 --- a/lib/Target/ARM/ARMCallLowering.cpp +++ b/lib/Target/ARM/ARMCallLowering.cpp @@ -48,10 +48,12 @@ static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI, } namespace { -struct FuncReturnHandler : public CallLowering::ValueHandler { - FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, - MachineInstrBuilder &MIB, CCAssignFn *AssignFn) - : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {} +/// Helper class for values going out through an ABI boundary (used for handling +/// function return values and call parameters). +struct OutgoingValueHandler : public CallLowering::ValueHandler { + OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder &MIB, CCAssignFn *AssignFn) + : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {} unsigned getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO) override { @@ -155,7 +157,7 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); - FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn); + OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn); return handleAssignments(MIRBuilder, SplitVTs, RetHandler); } @@ -227,7 +229,7 @@ struct FormalArgHandler : public CallLowering::ValueHandler { MIRBuilder.buildCopy(ValVReg, PhysReg); } - unsigned assignCustomValue(const llvm::ARMCallLowering::ArgInfo &Arg, + unsigned assignCustomValue(const ARMCallLowering::ArgInfo &Arg, ArrayRef VAs) override { CCValAssign VA = VAs[0]; assert(VA.needsCustom() && "Value doesn't need custom handling"); @@ -309,16 +311,15 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const MachineOperand &Callee, const ArgInfo &OrigRet, ArrayRef OrigArgs) const { - const MachineFunction &MF = MIRBuilder.getMF(); + MachineFunction &MF = MIRBuilder.getMF(); + const auto &TLI = *getTLI(); + const auto &DL = MF.getDataLayout(); const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + MachineRegisterInfo &MRI = MF.getRegInfo(); if (MF.getSubtarget().genLongCalls()) return false; - // FIXME: Support calling functions with arguments. - if (OrigArgs.size() > 0) - return false; - // FIXME: Support calling functions with return types. if (!OrigRet.Ty->isVoidTy()) return false; @@ -327,10 +328,33 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, .addImm(0) .add(predOps(ARMCC::AL)); - MIRBuilder.buildInstr(ARM::BLX) - .add(Callee) - // FIXME: Don't hardcode the calling conv here... - .addRegMask(TRI->getCallPreservedMask(MF, CallingConv::ARM_AAPCS)); + // FIXME: This is the calling convention of the caller - we should use the + // calling convention of the callee instead. + auto CallConv = MF.getFunction()->getCallingConv(); + + // Create the call instruction so we can add the implicit uses of arg + // registers, but don't insert it yet. + auto MIB = MIRBuilder.buildInstrNoInsert(ARM::BLX).add(Callee).addRegMask( + TRI->getCallPreservedMask(MF, CallConv)); + + SmallVector ArgInfos; + for (auto Arg : OrigArgs) { + if (!isSupportedType(DL, TLI, Arg.Ty)) + return false; + + if (!Arg.IsFixed) + return false; + + splitToValueTypes(Arg, ArgInfos, DL, MRI); + } + + auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false); + OutgoingValueHandler ArgHandler(MIRBuilder, MRI, MIB, ArgAssignFn); + if (!handleAssignments(MIRBuilder, ArgInfos, ArgHandler)) + return false; + + // Now we can add the actual call instruction to the correct basic block. + MIRBuilder.insertInstr(MIB); MIRBuilder.buildInstr(ARM::ADJCALLSTACKUP) .addImm(0) diff --git a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index 28bbda4dc8e..4e81316f9a0 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -358,3 +358,80 @@ entry: notail call arm_aapcscc void @call_target() ret void } + +declare arm_aapcscc void @simple_params_target(i32, i32*) + +define arm_aapcscc void @test_call_simple_params(i32 *%a, i32 %b) { +; CHECK-LABEL: name: test_call_simple_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 +; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp +entry: + notail call arm_aapcscc void @simple_params_target(i32 %b, i32 *%a) + ret void +} + +declare arm_aapcscc void @ext_target(i8 signext, i8 zeroext, i16 signext, i16 zeroext) + +define arm_aapcscc void @test_call_ext_params(i8 %a, i16 %b) { +; CHECK-LABEL: name: test_call_ext_params +; CHECK-DAG: [[AVREG:%[0-9]+]](s8) = COPY %r0 +; CHECK-DAG: [[BVREG:%[0-9]+]](s16) = COPY %r1 +; CHECK: ADJCALLSTACKDOWN 0, 14, _, implicit-def %sp, implicit %sp +; CHECK-DAG: [[SEXTA:%[0-9]+]](s32) = G_SEXT [[AVREG]](s8) +; CHECK-DAG: %r0 = COPY [[SEXTA]] +; CHECK-DAG: [[ZEXTA:%[0-9]+]](s32) = G_ZEXT [[AVREG]](s8) +; CHECK-DAG: %r1 = COPY [[ZEXTA]] +; CHECK-DAG: [[SEXTB:%[0-9]+]](s32) = G_SEXT [[BVREG]](s16) +; CHECK-DAG: %r2 = COPY [[SEXTB]] +; CHECK-DAG: [[ZEXTB:%[0-9]+]](s32) = G_ZEXT [[BVREG]](s16) +; CHECK-DAG: %r3 = COPY [[ZEXTB]] +; CHECK: BLX @ext_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3 +; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp +entry: + notail call arm_aapcscc void @ext_target(i8 signext %a, i8 zeroext %a, i16 signext %b, i16 zeroext %b) + ret void +} + +declare arm_aapcs_vfpcc void @vfpcc_fp_target(float, double) + +define arm_aapcs_vfpcc void @test_call_vfpcc_fp_params(double %a, float %b) { +; CHECK-LABEL: name: test_call_vfpcc_fp_params +; CHECK-DAG: [[AVREG:%[0-9]+]](s64) = COPY %d0 +; CHECK-DAG: [[BVREG:%[0-9]+]](s32) = COPY %s2 +; CHECK: ADJCALLSTACKDOWN 0, 14, _, implicit-def %sp, implicit %sp +; CHECK-DAG: %s0 = COPY [[BVREG]] +; CHECK-DAG: %d1 = COPY [[AVREG]] +; CHECK: BLX @vfpcc_fp_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %s0, implicit %d1 +; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp +entry: + notail call arm_aapcs_vfpcc void @vfpcc_fp_target(float %b, double %a) + ret void +} + +declare arm_aapcscc void @aapcscc_fp_target(float, double) + +define arm_aapcscc void @test_call_aapcs_fp_params(double %a, float %b) { +; CHECK-LABEL: name: test_call_aapcs_fp_params +; CHECK-DAG: [[A1:%[0-9]+]](s32) = COPY %r0 +; CHECK-DAG: [[A2:%[0-9]+]](s32) = COPY %r1 +; 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-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: BLX @aapcscc_fp_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r2, implicit %r3 +; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp +entry: + notail call arm_aapcscc void @aapcscc_fp_target(float %b, double %a) + ret void +}