forked from OSchip/llvm-project
[ARM GlobalISel] Select G_FCONSTANT for VFP3
Make it possible to TableGen code for FCONSTS and FCONSTD. We need to make two changes to the TableGen descriptions of vfp_f32imm and vfp_f64imm respectively: * add GISelPredicateCode to check that the immediate fits in 8 bits; * extract the SDNodeXForms into separate definitions and create a GISDNodeXFormEquiv and a custom renderer function for each of them. There's a lot of boilerplate to get the actual value of the immediate, but it basically just boils down to calling ARM_AM::getFP32Imm or ARM_AM::getFP64Imm. llvm-svn: 358063
This commit is contained in:
parent
3533ad6801
commit
b6e83b98f9
|
@ -52,28 +52,50 @@ def vfp_f16imm : Operand<f16>,
|
|||
let ParserMatchClass = FPImmOperand;
|
||||
}
|
||||
|
||||
def vfp_f32imm : Operand<f32>,
|
||||
PatLeaf<(f32 fpimm), [{
|
||||
return ARM_AM::getFP32Imm(N->getValueAPF()) != -1;
|
||||
}], SDNodeXForm<fpimm, [{
|
||||
def vfp_f32imm_xform : SDNodeXForm<fpimm, [{
|
||||
APFloat InVal = N->getValueAPF();
|
||||
uint32_t enc = ARM_AM::getFP32Imm(InVal);
|
||||
return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
|
||||
}]>> {
|
||||
}]>;
|
||||
|
||||
def gi_vfp_f32imm : GICustomOperandRenderer<"renderVFPF32Imm">,
|
||||
GISDNodeXFormEquiv<vfp_f32imm_xform>;
|
||||
|
||||
def vfp_f32imm : Operand<f32>,
|
||||
PatLeaf<(f32 fpimm), [{
|
||||
return ARM_AM::getFP32Imm(N->getValueAPF()) != -1;
|
||||
}], vfp_f32imm_xform> {
|
||||
let PrintMethod = "printFPImmOperand";
|
||||
let ParserMatchClass = FPImmOperand;
|
||||
let GISelPredicateCode = [{
|
||||
const auto &MO = MI.getOperand(1);
|
||||
if (!MO.isFPImm())
|
||||
return false;
|
||||
return ARM_AM::getFP32Imm(MO.getFPImm()->getValueAPF()) != -1;
|
||||
}];
|
||||
}
|
||||
|
||||
def vfp_f64imm_xform : SDNodeXForm<fpimm, [{
|
||||
APFloat InVal = N->getValueAPF();
|
||||
uint32_t enc = ARM_AM::getFP64Imm(InVal);
|
||||
return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def gi_vfp_f64imm : GICustomOperandRenderer<"renderVFPF64Imm">,
|
||||
GISDNodeXFormEquiv<vfp_f64imm_xform>;
|
||||
|
||||
def vfp_f64imm : Operand<f64>,
|
||||
PatLeaf<(f64 fpimm), [{
|
||||
return ARM_AM::getFP64Imm(N->getValueAPF()) != -1;
|
||||
}], SDNodeXForm<fpimm, [{
|
||||
APFloat InVal = N->getValueAPF();
|
||||
uint32_t enc = ARM_AM::getFP64Imm(InVal);
|
||||
return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
|
||||
}]>> {
|
||||
}], vfp_f64imm_xform> {
|
||||
let PrintMethod = "printFPImmOperand";
|
||||
let ParserMatchClass = FPImmOperand;
|
||||
let GISelPredicateCode = [{
|
||||
const auto &MO = MI.getOperand(1);
|
||||
if (!MO.isFPImm())
|
||||
return false;
|
||||
return ARM_AM::getFP64Imm(MO.getFPImm()->getValueAPF()) != -1;
|
||||
}];
|
||||
}
|
||||
|
||||
def alignedload16 : PatFrag<(ops node:$ptr), (load node:$ptr), [{
|
||||
|
|
|
@ -137,6 +137,9 @@ private:
|
|||
unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
|
||||
unsigned Size) const;
|
||||
|
||||
void renderVFPF32Imm(MachineInstrBuilder &New, const MachineInstr &Old) const;
|
||||
void renderVFPF64Imm(MachineInstrBuilder &New, const MachineInstr &Old) const;
|
||||
|
||||
#define GET_GLOBALISEL_PREDICATES_DECL
|
||||
#include "ARMGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_PREDICATES_DECL
|
||||
|
@ -804,6 +807,30 @@ bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
|
|||
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
|
||||
}
|
||||
|
||||
void ARMInstructionSelector::renderVFPF32Imm(
|
||||
MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const {
|
||||
assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
|
||||
"Expected G_FCONSTANT");
|
||||
|
||||
APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
|
||||
uint32_t FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
|
||||
assert(FPImmEncoding != -1 && "Invalid immediate value");
|
||||
|
||||
NewInstBuilder.addImm(FPImmEncoding);
|
||||
}
|
||||
|
||||
void ARMInstructionSelector::renderVFPF64Imm(
|
||||
MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const {
|
||||
assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
|
||||
"Expected G_FCONSTANT");
|
||||
|
||||
APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
|
||||
uint64_t FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
|
||||
assert(FPImmEncoding != -1 && "Invalid immediate value");
|
||||
|
||||
NewInstBuilder.addImm(FPImmEncoding);
|
||||
}
|
||||
|
||||
bool ARMInstructionSelector::select(MachineInstr &I,
|
||||
CodeGenCoverage &CoverageInfo) const {
|
||||
assert(I.getParent() && "Instruction should be in a basic block!");
|
||||
|
|
|
@ -81,11 +81,12 @@ selected: false
|
|||
registers:
|
||||
- { id: 0, class: gprb }
|
||||
- { id: 1, class: fprb }
|
||||
# CHECK: constants:
|
||||
# CHECK-NEXT: id: 0
|
||||
# CHECK-NEXT: value: 'float -2.000000e+00'
|
||||
# CHECK-NEXT: alignment: 4
|
||||
# CHECK-NEXT: isTargetSpecific: false
|
||||
# VFP3: constants: []
|
||||
# VFP2: constants:
|
||||
# VFP2-NEXT: id: 0
|
||||
# VFP2-NEXT: value: 'float -2.000000e+00'
|
||||
# VFP2-NEXT: alignment: 4
|
||||
# VFP2-NEXT: isTargetSpecific: false
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $r0
|
||||
|
@ -94,7 +95,8 @@ body: |
|
|||
; CHECK: [[PTR:%[0-9]+]]:gpr = COPY $r0
|
||||
|
||||
%1(s32) = G_FCONSTANT float -2.0
|
||||
; CHECK: [[VREG:%[0-9]+]]:spr = VLDRS %const.0, 0, 14, $noreg :: (load 4 from constant-pool)
|
||||
; VFP3: [[VREG:%[0-9]+]]:spr = FCONSTS 128, 14, $noreg
|
||||
; VFP2: [[VREG:%[0-9]+]]:spr = VLDRS %const.0, 0, 14, $noreg :: (load 4 from constant-pool)
|
||||
|
||||
G_STORE %1(s32), %0 :: (store 4)
|
||||
; CHECK: VSTRS [[VREG]], [[PTR]], 0, 14, $noreg
|
||||
|
@ -112,11 +114,12 @@ selected: false
|
|||
registers:
|
||||
- { id: 0, class: gprb }
|
||||
- { id: 1, class: fprb }
|
||||
# CHECK: constants:
|
||||
# CHECK-NEXT: id: 0
|
||||
# CHECK-NEXT: value: double 5.000000e-01
|
||||
# CHECK-NEXT: alignment: 8
|
||||
# CHECK-NEXT: isTargetSpecific: false
|
||||
# VFP3: constants: []
|
||||
# VFP2: constants:
|
||||
# VFP2-NEXT: id: 0
|
||||
# VFP2-NEXT: value: double 5.000000e-01
|
||||
# VFP2-NEXT: alignment: 8
|
||||
# VFP2-NEXT: isTargetSpecific: false
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $r0
|
||||
|
@ -125,7 +128,8 @@ body: |
|
|||
; CHECK: [[PTR:%[0-9]+]]:gpr = COPY $r0
|
||||
|
||||
%1(s64) = G_FCONSTANT double 5.0e-1
|
||||
; CHECK: [[VREG:%[0-9]+]]:dpr = VLDRD %const.0, 0, 14, $noreg :: (load 8 from constant-pool)
|
||||
; VFP3: [[VREG:%[0-9]+]]:dpr = FCONSTD 96, 14, $noreg
|
||||
; VFP2: [[VREG:%[0-9]+]]:dpr = VLDRD %const.0, 0, 14, $noreg :: (load 8 from constant-pool)
|
||||
|
||||
G_STORE %1(s64), %0 :: (store 8)
|
||||
; CHECK: VSTRD [[VREG]], [[PTR]], 0, 14, $noreg
|
||||
|
|
Loading…
Reference in New Issue