[llvm] f5d5a7d - [AArch64][GlobalISel] Import FMOV patterns rather than manually selecting it

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 26 16:27:46 PST 2021


Author: Jessica Paquette
Date: 2021-02-26T16:27:39-08:00
New Revision: f5d5a7d7eac74e157c613c11945387b8846c18d1

URL: https://github.com/llvm/llvm-project/commit/f5d5a7d7eac74e157c613c11945387b8846c18d1
DIFF: https://github.com/llvm/llvm-project/commit/f5d5a7d7eac74e157c613c11945387b8846c18d1.diff

LOG: [AArch64][GlobalISel] Import FMOV patterns rather than manually selecting it

There are existing patterns for FMOVHi, FMOVSi, and FMOVDi in
AArch64InstrFormats.td.

Importing these allows us to remove the manual selection code for FMOV.

It also allows us to select FMOVHi for non-zero constants when we have full
fp-16 support.

Refactor some of the code in AArch64InstrFormats.td so that we can create
equivalent custom renderers in GlobalISel.

Differential Revision: https://reviews.llvm.org/D97511

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64InstrFormats.td
    llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
    llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index c8545643bdc9..938bd6663773 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -1155,36 +1155,44 @@ def gi_arith_extended_reg32to64_i64 :
     GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
 
 // Floating-point immediate.
-def fpimm16 : Operand<f16>,
-              FPImmLeaf<f16, [{
-      return AArch64_AM::getFP16Imm(Imm) != -1;
-    }], SDNodeXForm<fpimm, [{
+
+def fpimm16XForm : SDNodeXForm<fpimm, [{
       APFloat InVal = N->getValueAPF();
       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
-    }]>> {
+    }]>;
+
+def fpimm32XForm : SDNodeXForm<fpimm, [{
+      APFloat InVal = N->getValueAPF();
+      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
+      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
+    }]>;
+
+def fpimm64XForm : SDNodeXForm<fpimm, [{
+      APFloat InVal = N->getValueAPF();
+      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
+      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
+    }]>;
+
+def fpimm16 : Operand<f16>,
+              FPImmLeaf<f16, [{
+      return AArch64_AM::getFP16Imm(Imm) != -1;
+    }], fpimm16XForm> {
   let ParserMatchClass = FPImmOperand;
   let PrintMethod = "printFPImmOperand";
 }
+
 def fpimm32 : Operand<f32>,
               FPImmLeaf<f32, [{
       return AArch64_AM::getFP32Imm(Imm) != -1;
-    }], SDNodeXForm<fpimm, [{
-      APFloat InVal = N->getValueAPF();
-      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
-      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
-    }]>> {
+    }], fpimm32XForm> {
   let ParserMatchClass = FPImmOperand;
   let PrintMethod = "printFPImmOperand";
 }
 def fpimm64 : Operand<f64>,
               FPImmLeaf<f64, [{
       return AArch64_AM::getFP64Imm(Imm) != -1;
-    }], SDNodeXForm<fpimm, [{
-      APFloat InVal = N->getValueAPF();
-      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
-      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
-    }]>> {
+    }], fpimm64XForm> {
   let ParserMatchClass = FPImmOperand;
   let PrintMethod = "printFPImmOperand";
 }
@@ -1198,6 +1206,13 @@ def fpimm0 : FPImmLeaf<fAny, [{
   return Imm.isExactlyValue(+0.0);
 }]>;
 
+def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
+  GISDNodeXFormEquiv<fpimm16XForm>;
+def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
+  GISDNodeXFormEquiv<fpimm32XForm>;
+def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
+  GISDNodeXFormEquiv<fpimm64XForm>;
+
 // Vector lane operands
 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
   let Name = NamePrefix # "IndexRange" # Min # "_" # Max;

diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 61748e70d66f..727b329d22ab 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -244,12 +244,6 @@ class AArch64InstructionSelector : public InstructionSelector {
                                      Register VecReg, unsigned LaneIdx,
                                      MachineIRBuilder &MIRBuilder) const;
 
-  /// Helper function for selecting G_FCONSTANT. If the G_FCONSTANT can be
-  /// materialized using a FMOV instruction, then update MI and return it.
-  /// Otherwise, do nothing and return a nullptr.
-  MachineInstr *emitFMovForFConstant(MachineInstr &MI,
-                                     MachineRegisterInfo &MRI) const;
-
   /// Emit a CSet for an integer compare.
   ///
   /// \p DefReg and \p SrcReg are expected to be 32-bit scalar registers.
@@ -393,6 +387,12 @@ class AArch64InstructionSelector : public InstructionSelector {
                           int OpIdx = -1) const;
   void renderLogicalImm64(MachineInstrBuilder &MIB, const MachineInstr &I,
                           int OpIdx = -1) const;
+  void renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI,
+                     int OpIdx = -1) const;
+  void renderFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI,
+                     int OpIdx = -1) const;
+  void renderFPImm64(MachineInstrBuilder &MIB, const MachineInstr &MI,
+                     int OpIdx = -1) const;
 
   // Materialize a GlobalValue or BlockAddress using a movz+movk sequence.
   void materializeLargeCMVal(MachineInstr &I, const Value *V,
@@ -2425,10 +2425,6 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
                         : (DefSize == 64 ? AArch64::FPR64RegClass 
                                          : AArch64::FPR128RegClass);
 
-      // Can we use a FMOV instruction to represent the immediate?
-      if (emitFMovForFConstant(I, MRI))
-        return true;
-
       // For 64b values, emit a constant pool load instead.
       if (DefSize == 64 || DefSize == 128) {
         auto *FPImm = I.getOperand(1).getFPImm();
@@ -4387,39 +4383,6 @@ MachineInstr *AArch64InstructionSelector::emitVectorConcat(
   return &*InsElt;
 }
 
-MachineInstr *AArch64InstructionSelector::emitFMovForFConstant(
-    MachineInstr &I, MachineRegisterInfo &MRI) const {
-  assert(I.getOpcode() == TargetOpcode::G_FCONSTANT &&
-         "Expected a G_FCONSTANT!");
-  MachineOperand &ImmOp = I.getOperand(1);
-  unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
-
-  // Only handle 32 and 64 bit defs for now.
-  if (DefSize != 32 && DefSize != 64)
-    return nullptr;
-
-  // Don't handle null values using FMOV.
-  if (ImmOp.getFPImm()->isNullValue())
-    return nullptr;
-
-  // Get the immediate representation for the FMOV.
-  const APFloat &ImmValAPF = ImmOp.getFPImm()->getValueAPF();
-  int Imm = DefSize == 32 ? AArch64_AM::getFP32Imm(ImmValAPF)
-                          : AArch64_AM::getFP64Imm(ImmValAPF);
-
-  // If this is -1, it means the immediate can't be represented as the requested
-  // floating point value. Bail.
-  if (Imm == -1)
-    return nullptr;
-
-  // Update MI to represent the new FMOV instruction, constrain it, and return.
-  ImmOp.ChangeToImmediate(Imm);
-  unsigned MovOpc = DefSize == 32 ? AArch64::FMOVSi : AArch64::FMOVDi;
-  I.setDesc(TII.get(MovOpc));
-  constrainSelectedInstRegOperands(I, TII, TRI, RBI);
-  return &I;
-}
-
 MachineInstr *
 AArch64InstructionSelector::emitCSetForICMP(Register DefReg, unsigned Pred,
                                             MachineIRBuilder &MIRBuilder,
@@ -5965,6 +5928,33 @@ void AArch64InstructionSelector::renderLogicalImm64(
   MIB.addImm(Enc);
 }
 
+void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB,
+                                               const MachineInstr &MI,
+                                               int OpIdx) const {
+  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
+         "Expected G_FCONSTANT");
+  MIB.addImm(
+      AArch64_AM::getFP16Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
+}
+
+void AArch64InstructionSelector::renderFPImm32(MachineInstrBuilder &MIB,
+                                               const MachineInstr &MI,
+                                               int OpIdx) const {
+  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
+         "Expected G_FCONSTANT");
+  MIB.addImm(
+      AArch64_AM::getFP32Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
+}
+
+void AArch64InstructionSelector::renderFPImm64(MachineInstrBuilder &MIB,
+                                               const MachineInstr &MI,
+                                               int OpIdx) const {
+  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
+         "Expected G_FCONSTANT");
+  MIB.addImm(
+      AArch64_AM::getFP64Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
+}
+
 bool AArch64InstructionSelector::isLoadStoreOfNumBytes(
     const MachineInstr &MI, unsigned NumBytes) const {
   if (!MI.mayLoadOrStore())

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir
index 59ee5bbef75c..f7ad8fa0121e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-fp16-fconstant.mir
@@ -15,3 +15,18 @@ body:             |
     %0:fpr(s16) = G_FCONSTANT half 0.0
     $h0 = COPY %0(s16)
     RET_ReallyLR implicit $h0
+...
+---
+name:            one
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    ; CHECK-LABEL: name: one
+    ; CHECK: [[FMOVHi:%[0-9]+]]:fpr16 = FMOVHi 112
+    ; CHECK: $h0 = COPY [[FMOVHi]]
+    ; CHECK: RET_ReallyLR implicit $h0
+    %0:fpr(s16) = G_FCONSTANT half 1.0
+    $h0 = COPY %0(s16)
+    RET_ReallyLR implicit $h0


        


More information about the llvm-commits mailing list