forked from OSchip/llvm-project
[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. llvm-svn: 359734
This commit is contained in:
parent
50721b27c4
commit
a3843fe6f4
|
@ -118,6 +118,12 @@ private:
|
||||||
unsigned VecReg, unsigned LaneIdx,
|
unsigned VecReg, unsigned LaneIdx,
|
||||||
MachineIRBuilder &MIRBuilder) const;
|
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 selectArithImmed(MachineOperand &Root) const;
|
||||||
|
|
||||||
ComplexRendererFns selectAddrModeUnscaled(MachineOperand &Root,
|
ComplexRendererFns selectAddrModeUnscaled(MachineOperand &Root,
|
||||||
|
@ -1178,14 +1184,18 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
|
||||||
const unsigned MovOpc =
|
const unsigned MovOpc =
|
||||||
DefSize == 32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
|
DefSize == 32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
|
||||||
|
|
||||||
I.setDesc(TII.get(MovOpc));
|
|
||||||
|
|
||||||
if (isFP) {
|
if (isFP) {
|
||||||
|
// Either emit a FMOV, or emit a copy to emit a normal mov.
|
||||||
const TargetRegisterClass &GPRRC =
|
const TargetRegisterClass &GPRRC =
|
||||||
DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
|
DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
|
||||||
const TargetRegisterClass &FPRRC =
|
const TargetRegisterClass &FPRRC =
|
||||||
DefSize == 32 ? AArch64::FPR32RegClass : AArch64::FPR64RegClass;
|
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);
|
const unsigned DefGPRReg = MRI.createVirtualRegister(&GPRRC);
|
||||||
MachineOperand &RegOp = I.getOperand(0);
|
MachineOperand &RegOp = I.getOperand(0);
|
||||||
RegOp.setReg(DefGPRReg);
|
RegOp.setReg(DefGPRReg);
|
||||||
|
@ -1209,6 +1219,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
|
||||||
I.getOperand(1).ChangeToImmediate(Val);
|
I.getOperand(1).ChangeToImmediate(Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
I.setDesc(TII.get(MovOpc));
|
||||||
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
|
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2716,6 +2727,39 @@ MachineInstr *AArch64InstructionSelector::emitVectorConcat(
|
||||||
return &*InsElt;
|
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 {
|
bool AArch64InstructionSelector::tryOptVectorDup(MachineInstr &I) const {
|
||||||
// Try to match a vector splat operation into a dup instruction.
|
// Try to match a vector splat operation into a dup instruction.
|
||||||
// We're looking for this pattern:
|
// We're looking for this pattern:
|
||||||
|
|
|
@ -55,9 +55,8 @@ registers:
|
||||||
body: |
|
body: |
|
||||||
bb.0:
|
bb.0:
|
||||||
; CHECK-LABEL: name: fconst_s32
|
; CHECK-LABEL: name: fconst_s32
|
||||||
; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 1080033280
|
; CHECK: [[FMOVSi:%[0-9]+]]:fpr32 = FMOVSi 12
|
||||||
; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY [[MOVi32imm]]
|
; CHECK: $s0 = COPY [[FMOVSi]]
|
||||||
; CHECK: $s0 = COPY [[COPY]]
|
|
||||||
%0(s32) = G_FCONSTANT float 3.5
|
%0(s32) = G_FCONSTANT float 3.5
|
||||||
$s0 = COPY %0(s32)
|
$s0 = COPY %0(s32)
|
||||||
...
|
...
|
||||||
|
@ -72,9 +71,8 @@ registers:
|
||||||
body: |
|
body: |
|
||||||
bb.0:
|
bb.0:
|
||||||
; CHECK-LABEL: name: fconst_s64
|
; CHECK-LABEL: name: fconst_s64
|
||||||
; CHECK: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm 4607182418800017408
|
; CHECK: [[FMOVDi:%[0-9]+]]:fpr64 = FMOVDi 112
|
||||||
; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY [[MOVi64imm]]
|
; CHECK: $d0 = COPY [[FMOVDi]]
|
||||||
; CHECK: $d0 = COPY [[COPY]]
|
|
||||||
%0(s64) = G_FCONSTANT double 1.0
|
%0(s64) = G_FCONSTANT double 1.0
|
||||||
$d0 = COPY %0(s64)
|
$d0 = COPY %0(s64)
|
||||||
...
|
...
|
||||||
|
|
|
@ -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 -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
|
; Materialize using fmov
|
||||||
define float @fmov_float1() {
|
define float @fmov_float1() {
|
||||||
; CHECK-LABEL: fmov_float1
|
; CHECK-LABEL: fmov_float1
|
||||||
; CHECK: fmov s0, #1.25000000
|
; CHECK: fmov s0, #1.25000000
|
||||||
|
; GISEL-LABEL: fmov_float1
|
||||||
|
; GISEL: fmov s0, #1.25000000
|
||||||
ret float 1.250000e+00
|
ret float 1.250000e+00
|
||||||
}
|
}
|
||||||
|
|
||||||
define float @fmov_float2() {
|
define float @fmov_float2() {
|
||||||
; CHECK-LABEL: fmov_float2
|
; CHECK-LABEL: fmov_float2
|
||||||
; CHECK: fmov s0, wzr
|
; CHECK: fmov s0, wzr
|
||||||
|
; GISEL-LABEL: fmov_float2
|
||||||
|
; GISEL: fmov s0, wzr
|
||||||
ret float 0.0e+00
|
ret float 0.0e+00
|
||||||
}
|
}
|
||||||
|
|
||||||
define double @fmov_double1() {
|
define double @fmov_double1() {
|
||||||
; CHECK-LABEL: fmov_double1
|
; CHECK-LABEL: fmov_double1
|
||||||
; CHECK: fmov d0, #1.25000000
|
; CHECK: fmov d0, #1.25000000
|
||||||
|
; GISEL-LABEL: fmov_double1
|
||||||
|
; GISEL: fmov d0, #1.25000000
|
||||||
ret double 1.250000e+00
|
ret double 1.250000e+00
|
||||||
}
|
}
|
||||||
|
|
||||||
define double @fmov_double2() {
|
define double @fmov_double2() {
|
||||||
; CHECK-LABEL: fmov_double2
|
; CHECK-LABEL: fmov_double2
|
||||||
; CHECK: fmov d0, xzr
|
; CHECK: fmov d0, xzr
|
||||||
|
; GISEL-LABEL: fmov_double2
|
||||||
|
; GISEL: fmov d0, xzr
|
||||||
ret double 0.0e+00
|
ret double 0.0e+00
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue