[llvm] r359734 - [GlobalISel][AArch64] Use fmov for G_FCONSTANT when possible
Jessica Paquette via llvm-commits
llvm-commits at lists.llvm.org
Wed May 1 15:39:43 PDT 2019
Author: paquette
Date: Wed May 1 15:39:43 2019
New Revision: 359734
URL: http://llvm.org/viewvc/llvm-project?rev=359734&view=rev
Log:
[GlobalISel][AArch64] Use fmov for G_FCONSTANT when possible
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.
Modified:
llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-constant.mir
llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=359734&r1=359733&r2=359734&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Wed May 1 15:39:43 2019
@@ -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(
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(
I.getOperand(1).ChangeToImmediate(Val);
}
+ I.setDesc(TII.get(MovOpc));
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
return true;
}
@@ -2716,6 +2727,39 @@ MachineInstr *AArch64InstructionSelector
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:
Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-constant.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-constant.mir?rev=359734&r1=359733&r2=359734&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-constant.mir (original)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-constant.mir Wed May 1 15:39:43 2019
@@ -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)
...
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll?rev=359734&r1=359733&r2=359734&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-materialize.ll Wed May 1 15:39:43 2019
@@ -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
}
More information about the llvm-commits
mailing list