]> granicus.if.org Git - llvm/commitdiff
[GlobalISel][AArch64] Use fmov for G_FCONSTANT when possible
authorJessica Paquette <jpaquette@apple.com>
Wed, 1 May 2019 22:39:43 +0000 (22:39 +0000)
committerJessica Paquette <jpaquette@apple.com>
Wed, 1 May 2019 22:39:43 +0000 (22:39 +0000)
This adds support for using fmov rather than a standard mov to materialize
G_FCONSTANT when it's safe to do so.

Update arm64-fast-isel-materialize.ll and select-constant.mir to show that the
selection is correct.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359734 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64InstructionSelector.cpp
test/CodeGen/AArch64/GlobalISel/select-constant.mir
test/CodeGen/AArch64/arm64-fast-isel-materialize.ll

index ae668ddac4001a3622d38495a434521a2774ad48..76bbd9489afc950e0f8822be3dc4f17e6cf8fe76 100644 (file)
@@ -118,6 +118,12 @@ private:
                                      unsigned 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;
+
   ComplexRendererFns selectArithImmed(MachineOperand &Root) const;
 
   ComplexRendererFns selectAddrModeUnscaled(MachineOperand &Root,
@@ -1178,14 +1184,18 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
     const unsigned MovOpc =
         DefSize == 32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
 
-    I.setDesc(TII.get(MovOpc));
-
     if (isFP) {
+      // Either emit a FMOV, or emit a copy to emit a normal mov.
       const TargetRegisterClass &GPRRC =
           DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
       const TargetRegisterClass &FPRRC =
           DefSize == 32 ? AArch64::FPR32RegClass : AArch64::FPR64RegClass;
 
+      // Can we use a FMOV instruction to represent the immediate?
+      if (emitFMovForFConstant(I, MRI))
+        return true;
+
+      // Nope. Emit a copy and use a normal mov instead.
       const unsigned DefGPRReg = MRI.createVirtualRegister(&GPRRC);
       MachineOperand &RegOp = I.getOperand(0);
       RegOp.setReg(DefGPRReg);
@@ -1209,6 +1219,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
       I.getOperand(1).ChangeToImmediate(Val);
     }
 
+    I.setDesc(TII.get(MovOpc));
     constrainSelectedInstRegOperands(I, TII, TRI, RBI);
     return true;
   }
@@ -2716,6 +2727,39 @@ 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;
+}
+
 bool AArch64InstructionSelector::tryOptVectorDup(MachineInstr &I) const {
   // Try to match a vector splat operation into a dup instruction.
   // We're looking for this pattern:
index e046aa290c138c645e2f90ae83b5f252c1237046..234957a8f8e5b202011ed6d7f61b096bcdde16b5 100644 (file)
@@ -55,9 +55,8 @@ registers:
 body:             |
   bb.0:
     ; CHECK-LABEL: name: fconst_s32
-    ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 1080033280
-    ; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY [[MOVi32imm]]
-    ; CHECK: $s0 = COPY [[COPY]]
+    ; CHECK: [[FMOVSi:%[0-9]+]]:fpr32 = FMOVSi 12
+    ; CHECK: $s0 = COPY [[FMOVSi]]
     %0(s32) = G_FCONSTANT float 3.5
     $s0 = COPY %0(s32)
 ...
@@ -72,9 +71,8 @@ registers:
 body:             |
   bb.0:
     ; CHECK-LABEL: name: fconst_s64
-    ; CHECK: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm 4607182418800017408
-    ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY [[MOVi64imm]]
-    ; CHECK: $d0 = COPY [[COPY]]
+    ; CHECK: [[FMOVDi:%[0-9]+]]:fpr64 = FMOVDi 112
+    ; CHECK: $d0 = COPY [[FMOVDi]]
     %0(s64) = G_FCONSTANT double 1.0
     $d0 = COPY %0(s64)
 ...
index 234731cfa2425bd710878c0649875325f71c26ec..3a8a31be152cd9fc17a6ac4f2b721e3e29280c58 100644 (file)
@@ -1,27 +1,38 @@
 ; RUN: llc -O0 -fast-isel -fast-isel-abort=1 -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
+; RUN: llc -O0 -global-isel -fast-isel-abort=2 -pass-remarks-missed=gisel* -verify-machineinstrs -mtriple=arm64-apple-darwin %s -o - 2>&1 | FileCheck %s --check-prefixes=GISEL,FALLBACK
+
+; FALLBACK-NOT: remark:
 
 ; Materialize using fmov
 define float @fmov_float1() {
 ; CHECK-LABEL: fmov_float1
 ; CHECK:       fmov s0, #1.25000000
+; GISEL-LABEL: fmov_float1
+; GISEL:       fmov s0, #1.25000000
   ret float 1.250000e+00
 }
 
 define float @fmov_float2() {
 ; CHECK-LABEL: fmov_float2
 ; CHECK:       fmov s0, wzr
+; GISEL-LABEL: fmov_float2
+; GISEL:       fmov s0, wzr
   ret float 0.0e+00
 }
 
 define double @fmov_double1() {
 ; CHECK-LABEL: fmov_double1
 ; CHECK:       fmov d0, #1.25000000
+; GISEL-LABEL: fmov_double1
+; GISEL:       fmov d0, #1.25000000
   ret double 1.250000e+00
 }
 
 define double @fmov_double2() {
 ; CHECK-LABEL: fmov_double2
 ; CHECK:       fmov d0, xzr
+; GISEL-LABEL: fmov_double2
+; GISEL:       fmov d0, xzr
   ret double 0.0e+00
 }