[llvm] r358063 - [ARM GlobalISel] Select G_FCONSTANT for VFP3

Diana Picus via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 02:14:32 PDT 2019


Author: rovka
Date: Wed Apr 10 02:14:32 2019
New Revision: 358063

URL: http://llvm.org/viewvc/llvm-project?rev=358063&view=rev
Log:
[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.

Modified:
    llvm/trunk/lib/Target/ARM/ARMInstrVFP.td
    llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp
    llvm/trunk/test/CodeGen/ARM/GlobalISel/select-fp-const.mir

Modified: llvm/trunk/lib/Target/ARM/ARMInstrVFP.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrVFP.td?rev=358063&r1=358062&r2=358063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrVFP.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrVFP.td Wed Apr 10 02:14:32 2019
@@ -52,28 +52,50 @@ def vfp_f16imm : Operand<f16>,
   let ParserMatchClass = FPImmOperand;
 }
 
-def vfp_f32imm : Operand<f32>,
-                 PatLeaf<(f32 fpimm), [{
-      return ARM_AM::getFP32Imm(N->getValueAPF()) != -1;
-    }], SDNodeXForm<fpimm, [{
+def vfp_f32imm_xform : SDNodeXForm<fpimm, [{
       APFloat InVal = N->getValueAPF();
       uint32_t enc = ARM_AM::getFP32Imm(InVal);
       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
-    }]>> {
+    }]>;
+
+def gi_vfp_f32imm : GICustomOperandRenderer<"renderVFPF32Imm">,
+                    GISDNodeXFormEquiv<vfp_f32imm_xform>;
+
+def vfp_f32imm : Operand<f32>,
+                 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<f64>,
-                 PatLeaf<(f64 fpimm), [{
-      return ARM_AM::getFP64Imm(N->getValueAPF()) != -1;
-    }], SDNodeXForm<fpimm, [{
+def vfp_f64imm_xform : SDNodeXForm<fpimm, [{
       APFloat InVal = N->getValueAPF();
       uint32_t enc = ARM_AM::getFP64Imm(InVal);
       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
-    }]>> {
+    }]>;
+
+def gi_vfp_f64imm : GICustomOperandRenderer<"renderVFPF64Imm">,
+                    GISDNodeXFormEquiv<vfp_f64imm_xform>;
+
+def vfp_f64imm : Operand<f64>,
+                 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), [{

Modified: llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp?rev=358063&r1=358062&r2=358063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp Wed Apr 10 02:14:32 2019
@@ -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
   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!");

Modified: llvm/trunk/test/CodeGen/ARM/GlobalISel/select-fp-const.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/GlobalISel/select-fp-const.mir?rev=358063&r1=358062&r2=358063&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/GlobalISel/select-fp-const.mir (original)
+++ llvm/trunk/test/CodeGen/ARM/GlobalISel/select-fp-const.mir Wed Apr 10 02:14:32 2019
@@ -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




More information about the llvm-commits mailing list