From bb65a8b75f90232b7dc920c32b301e167e8ccea6 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Wed, 8 Feb 2017 13:23:04 +0000 Subject: [PATCH] [ARM] GlobalISel: Add FPR reg bank Add a register bank for floating point values and select simple instructions using them (add, copies from GPR). This assumes that the hardware can cope with a single precision add (VADDS) instruction, so the legalizer will treat G_FADD as legal and the instruction selector will refuse to select if the hardware doesn't support it. In the future we'll want to be more careful about this, and legalize to libcalls if we have to use soft float. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294442 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstructionSelector.cpp | 17 ++++++++- lib/Target/ARM/ARMLegalizerInfo.cpp | 4 ++ lib/Target/ARM/ARMRegisterBankInfo.cpp | 10 ++++- lib/Target/ARM/ARMRegisterBanks.td | 1 + .../ARM/GlobalISel/arm-instruction-select.mir | 37 +++++++++++++++++++ test/CodeGen/ARM/GlobalISel/arm-legalizer.mir | 27 ++++++++++++++ .../ARM/GlobalISel/arm-regbankselect.mir | 28 ++++++++++++++ 7 files changed, 122 insertions(+), 2 deletions(-) diff --git a/lib/Target/ARM/ARMInstructionSelector.cpp b/lib/Target/ARM/ARMInstructionSelector.cpp index 538060d4334..dcdd0e83550 100644 --- a/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/lib/Target/ARM/ARMInstructionSelector.cpp @@ -54,9 +54,17 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, DstSize <= SrcSize)) && "Copy with different width?!"); - assert(RegBank->getID() == ARM::GPRRegBankID && "Unsupported reg bank"); + assert((RegBank->getID() == ARM::GPRRegBankID || + RegBank->getID() == ARM::FPRRegBankID) && + "Unsupported reg bank"); + const TargetRegisterClass *RC = &ARM::GPRRegClass; + if (RegBank->getID() == ARM::FPRRegBankID) { + assert(DstSize == 32 && "Only 32-bit FP values are supported"); + RC = &ARM::SPRRegClass; + } + // No need to constrain SrcReg. It will get constrained when // we hit another of its uses or its defs. // Copies do not have constraints. @@ -177,6 +185,13 @@ bool ARMInstructionSelector::select(MachineInstr &I) const { I.setDesc(TII.get(ARM::ADDrr)); MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); break; + case G_FADD: + if (!TII.getSubtarget().hasVFP2() || + TII.getSubtarget().useNEONForSinglePrecisionFP()) + return false; + I.setDesc(TII.get(ARM::VADDS)); + MIB.add(predOps(ARMCC::AL)); + break; case G_FRAME_INDEX: // Add 0 to the given frame index and hope it will eventually be folded into // the user(s). diff --git a/lib/Target/ARM/ARMLegalizerInfo.cpp b/lib/Target/ARM/ARMLegalizerInfo.cpp index d1276df57b1..af44cbf50f0 100644 --- a/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -48,5 +48,9 @@ ARMLegalizerInfo::ARMLegalizerInfo() { setAction({Op, 1, Ty}, Legal); } + // FIXME: This is a bit sloppy, but for now we'll just rely on the instruction + // selector to complain if it doesn't support floating point. + setAction({G_FADD, s32}, Legal); + computeTables(); } diff --git a/lib/Target/ARM/ARMRegisterBankInfo.cpp b/lib/Target/ARM/ARMRegisterBankInfo.cpp index f65b6787697..dc111069921 100644 --- a/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ b/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -33,9 +33,11 @@ using namespace llvm; namespace llvm { namespace ARM { RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank}; +RegisterBankInfo::PartialMapping FPRPartialMapping{0, 32, FPRRegBank}; RegisterBankInfo::ValueMapping ValueMappings[] = { - {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}}; + {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, + {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}}; } // end namespace arm } // end namespace llvm @@ -82,6 +84,9 @@ const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( case GPRnopcRegClassID: case tGPR_and_tcGPRRegClassID: return getRegBank(ARM::GPRRegBankID); + case SPR_8RegClassID: + case SPRRegClassID: + return getRegBank(ARM::FPRRegBankID); default: llvm_unreachable("Unsupported register kind"); } @@ -115,6 +120,9 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { // the real world we would use different mappings. OperandsMapping = &ARM::ValueMappings[0]; break; + case G_FADD: + OperandsMapping = &ARM::ValueMappings[3]; + break; case G_FRAME_INDEX: OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr}); break; diff --git a/lib/Target/ARM/ARMRegisterBanks.td b/lib/Target/ARM/ARMRegisterBanks.td index a2b3a7943c1..b8e0347ef62 100644 --- a/lib/Target/ARM/ARMRegisterBanks.td +++ b/lib/Target/ARM/ARMRegisterBanks.td @@ -11,3 +11,4 @@ //===----------------------------------------------------------------------===// def GPRRegBank : RegisterBank<"GPRB", [GPR, GPRwithAPSR]>; +def FPRRegBank : RegisterBank<"FPRB", [SPR]>; diff --git a/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir index ab2ddf88ff3..8d18513766d 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir +++ b/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir @@ -9,7 +9,11 @@ define void @test_add_s16() { ret void } define void @test_add_s32() { ret void } + define void @test_fadd_s32() #0 { ret void } + define void @test_load_from_stack() { ret void } + + attributes #0 = { "target-features"="+vfp2" } ... --- name: test_zext_s1 @@ -217,6 +221,39 @@ body: | ; CHECK: BX_RET 14, _, implicit %r0 ... --- +name: test_fadd_s32 +# CHECK-LABEL: name: test_fadd_s32 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: fprb } + - { id: 1, class: fprb } + - { id: 2, class: fprb } +# CHECK: id: 0, class: spr +# CHECK: id: 1, class: spr +# CHECK: id: 2, class: spr +body: | + bb.0: + liveins: %s0, %s1 + + %0(s32) = COPY %s0 + ; CHECK: [[VREGX:%[0-9]+]] = COPY %s0 + + %1(s32) = COPY %s1 + ; CHECK: [[VREGY:%[0-9]+]] = COPY %s1 + + %2(s32) = G_FADD %0, %1 + ; CHECK: [[VREGSUM:%[0-9]+]] = VADDS [[VREGX]], [[VREGY]], 14, _ + + %s0 = COPY %2(s32) + ; CHECK: %s0 = COPY [[VREGSUM]] + + BX_RET 14, _, implicit %s0 + ; CHECK: BX_RET 14, _, implicit %s0 +... +--- name: test_load_from_stack # CHECK-LABEL: name: test_load_from_stack legalized: true diff --git a/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir b/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir index 249a0b03795..f187e886930 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir +++ b/test/CodeGen/ARM/GlobalISel/arm-legalizer.mir @@ -9,6 +9,8 @@ define void @test_load_from_stack() { ret void } define void @test_legal_loads() { ret void } + + define void @test_fadd_s32() { ret void } ... --- name: test_sext_s8 @@ -190,3 +192,28 @@ body: | %5(p0) = G_LOAD %0(p0) BX_RET 14, _ ... +--- +name: test_fadd_s32 +# CHECK-LABEL: name: test_fadd_s32 +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: %r0, %r1 + + %0(s32) = COPY %r0 + %1(s32) = COPY %r1 + %2(s32) = G_FADD %0, %1 + ; G_FADD with s32 is legal, so we should find it unchanged in the output + ; CHECK: {{%[0-9]+}}(s32) = G_FADD {{%[0-9]+, %[0-9]+}} + %r0 = COPY %2(s32) + BX_RET 14, _, implicit %r0 + +... diff --git a/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir b/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir index ba6880f3e43..c66aa3cb937 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir +++ b/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir @@ -6,6 +6,8 @@ define void @test_add_s1() { ret void } define void @test_loads() { ret void } + + define void @test_fadd_s32() { ret void } ... --- name: test_add_s32 @@ -144,3 +146,29 @@ body: | BX_RET 14, _, implicit %r0 ... +--- +name: test_fadd_s32 +# CHECK-LABEL: name: test_fadd_s32 +legalized: true +regBankSelected: false +selected: false +# CHECK: registers: +# CHECK: - { id: 0, class: fprb } +# CHECK: - { id: 1, class: fprb } +# CHECK: - { id: 2, class: fprb } + +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: %r0, %r1 + + %0(s32) = COPY %s0 + %1(s32) = COPY %s1 + %2(s32) = G_FADD %0, %1 + %s0 = COPY %2(s32) + BX_RET 14, _, implicit %r0 + +... -- 2.50.1