diff options
Diffstat (limited to 'llvm')
3 files changed, 61 insertions, 8 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index ae668ddac40..76bbd9489af 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -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: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-constant.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-constant.mir index e046aa290c1..234957a8f8e 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-constant.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-constant.mir @@ -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)  ... diff --git a/llvm/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll b/llvm/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll index 234731cfa24..3a8a31be152 100644 --- a/llvm/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll +++ b/llvm/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll @@ -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  }  | 

