From 8c8976533c6010161541b2060e06fe0b9389d748 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Wed, 10 Apr 2019 09:14:32 +0000 Subject: [PATCH] [ARM GlobalISel] Select G_FCONSTANT for VFP3 Make it possible to TableGen code for FCONSTS and FCONSTD. We need to make two changes to the TableGen descriptions of vfp_f32imm and vfp_f64imm respectively: * add GISelPredicateCode to check that the immediate fits in 8 bits; * extract the SDNodeXForms into separate definitions and create a GISDNodeXFormEquiv and a custom renderer function for each of them. There's a lot of boilerplate to get the actual value of the immediate, but it basically just boils down to calling ARM_AM::getFP32Imm or ARM_AM::getFP64Imm. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358063 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrVFP.td | 42 +++++++++++++++++++------ lib/Target/ARM/ARMInstructionSelector.cpp | 27 ++++++++++++++++ test/CodeGen/ARM/GlobalISel/select-fp-const.mir | 28 ++++++++++------- 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 7871b18ae93..4478fce6ef9 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -52,28 +52,50 @@ def vfp_f16imm : Operand, let ParserMatchClass = FPImmOperand; } -def vfp_f32imm : Operand, - PatLeaf<(f32 fpimm), [{ - return ARM_AM::getFP32Imm(N->getValueAPF()) != -1; - }], SDNodeXFormgetValueAPF(); uint32_t enc = ARM_AM::getFP32Imm(InVal); return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); - }]>> { + }]>; + +def gi_vfp_f32imm : GICustomOperandRenderer<"renderVFPF32Imm">, + GISDNodeXFormEquiv; + +def vfp_f32imm : Operand, + PatLeaf<(f32 fpimm), [{ + return ARM_AM::getFP32Imm(N->getValueAPF()) != -1; + }], vfp_f32imm_xform> { let PrintMethod = "printFPImmOperand"; let ParserMatchClass = FPImmOperand; + let GISelPredicateCode = [{ + const auto &MO = MI.getOperand(1); + if (!MO.isFPImm()) + return false; + return ARM_AM::getFP32Imm(MO.getFPImm()->getValueAPF()) != -1; + }]; } -def vfp_f64imm : Operand, - PatLeaf<(f64 fpimm), [{ - return ARM_AM::getFP64Imm(N->getValueAPF()) != -1; - }], SDNodeXFormgetValueAPF(); uint32_t enc = ARM_AM::getFP64Imm(InVal); return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32); - }]>> { + }]>; + +def gi_vfp_f64imm : GICustomOperandRenderer<"renderVFPF64Imm">, + GISDNodeXFormEquiv; + +def vfp_f64imm : Operand, + PatLeaf<(f64 fpimm), [{ + return ARM_AM::getFP64Imm(N->getValueAPF()) != -1; + }], vfp_f64imm_xform> { let PrintMethod = "printFPImmOperand"; let ParserMatchClass = FPImmOperand; + let GISelPredicateCode = [{ + const auto &MO = MI.getOperand(1); + if (!MO.isFPImm()) + return false; + return ARM_AM::getFP64Imm(MO.getFPImm()->getValueAPF()) != -1; + }]; } def alignedload16 : PatFrag<(ops node:$ptr), (load node:$ptr), [{ diff --git a/lib/Target/ARM/ARMInstructionSelector.cpp b/lib/Target/ARM/ARMInstructionSelector.cpp index 0f56504d06b..c7bead914b6 100644 --- a/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/lib/Target/ARM/ARMInstructionSelector.cpp @@ -137,6 +137,9 @@ private: unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank, unsigned Size) const; + void renderVFPF32Imm(MachineInstrBuilder &New, const MachineInstr &Old) const; + void renderVFPF64Imm(MachineInstrBuilder &New, const MachineInstr &Old) const; + #define GET_GLOBALISEL_PREDICATES_DECL #include "ARMGenGlobalISel.inc" #undef GET_GLOBALISEL_PREDICATES_DECL @@ -804,6 +807,30 @@ bool ARMInstructionSelector::selectShift(unsigned ShiftOpc, return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } +void ARMInstructionSelector::renderVFPF32Imm( + MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const { + assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT && + "Expected G_FCONSTANT"); + + APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF(); + uint32_t FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue); + assert(FPImmEncoding != -1 && "Invalid immediate value"); + + NewInstBuilder.addImm(FPImmEncoding); +} + +void ARMInstructionSelector::renderVFPF64Imm( + MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const { + assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT && + "Expected G_FCONSTANT"); + + APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF(); + uint64_t FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue); + assert(FPImmEncoding != -1 && "Invalid immediate value"); + + NewInstBuilder.addImm(FPImmEncoding); +} + bool ARMInstructionSelector::select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const { assert(I.getParent() && "Instruction should be in a basic block!"); diff --git a/test/CodeGen/ARM/GlobalISel/select-fp-const.mir b/test/CodeGen/ARM/GlobalISel/select-fp-const.mir index 8eac01dacf4..6629f24f697 100644 --- a/test/CodeGen/ARM/GlobalISel/select-fp-const.mir +++ b/test/CodeGen/ARM/GlobalISel/select-fp-const.mir @@ -81,11 +81,12 @@ selected: false registers: - { id: 0, class: gprb } - { id: 1, class: fprb } -# CHECK: constants: -# CHECK-NEXT: id: 0 -# CHECK-NEXT: value: 'float -2.000000e+00' -# CHECK-NEXT: alignment: 4 -# CHECK-NEXT: isTargetSpecific: false +# VFP3: constants: [] +# VFP2: constants: +# VFP2-NEXT: id: 0 +# VFP2-NEXT: value: 'float -2.000000e+00' +# VFP2-NEXT: alignment: 4 +# VFP2-NEXT: isTargetSpecific: false body: | bb.0: liveins: $r0 @@ -94,7 +95,8 @@ body: | ; CHECK: [[PTR:%[0-9]+]]:gpr = COPY $r0 %1(s32) = G_FCONSTANT float -2.0 - ; CHECK: [[VREG:%[0-9]+]]:spr = VLDRS %const.0, 0, 14, $noreg :: (load 4 from constant-pool) + ; VFP3: [[VREG:%[0-9]+]]:spr = FCONSTS 128, 14, $noreg + ; VFP2: [[VREG:%[0-9]+]]:spr = VLDRS %const.0, 0, 14, $noreg :: (load 4 from constant-pool) G_STORE %1(s32), %0 :: (store 4) ; CHECK: VSTRS [[VREG]], [[PTR]], 0, 14, $noreg @@ -112,11 +114,12 @@ selected: false registers: - { id: 0, class: gprb } - { id: 1, class: fprb } -# CHECK: constants: -# CHECK-NEXT: id: 0 -# CHECK-NEXT: value: double 5.000000e-01 -# CHECK-NEXT: alignment: 8 -# CHECK-NEXT: isTargetSpecific: false +# VFP3: constants: [] +# VFP2: constants: +# VFP2-NEXT: id: 0 +# VFP2-NEXT: value: double 5.000000e-01 +# VFP2-NEXT: alignment: 8 +# VFP2-NEXT: isTargetSpecific: false body: | bb.0: liveins: $r0 @@ -125,7 +128,8 @@ body: | ; CHECK: [[PTR:%[0-9]+]]:gpr = COPY $r0 %1(s64) = G_FCONSTANT double 5.0e-1 - ; CHECK: [[VREG:%[0-9]+]]:dpr = VLDRD %const.0, 0, 14, $noreg :: (load 8 from constant-pool) + ; VFP3: [[VREG:%[0-9]+]]:dpr = FCONSTD 96, 14, $noreg + ; VFP2: [[VREG:%[0-9]+]]:dpr = VLDRD %const.0, 0, 14, $noreg :: (load 8 from constant-pool) G_STORE %1(s64), %0 :: (store 8) ; CHECK: VSTRD [[VREG]], [[PTR]], 0, 14, $noreg -- 2.11.0