}
case ISD::ConstantFP: {
const APFloat &APF = cast<ConstantFPSDNode>(Node)->getValueAPF();
- if (Subtarget->hasStdExtZfa()) {
- // fli.h requires Zfh, but we might only have Zfhmin.
- if (VT == MVT::f16 && Subtarget->hasStdExtZfh() &&
- RISCVLoadFPImm::getLoadFP16Imm(APF) != -1)
- break;
- if (VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(APF) != -1)
- break;
- if (VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(APF) != -1)
- break;
- }
+ if (static_cast<const RISCVTargetLowering *>(TLI)->isLegalZfaFPImm(APF, VT))
+ break;
bool NegZeroF64 = APF.isNegZero() && VT == MVT::f64;
SDValue Imm;
// td can handle +0.0 already.
if (APF.isPosZero())
return false;
+
+ MVT VT = CFP->getSimpleValueType(0);
+
+ if (static_cast<const RISCVTargetLowering *>(TLI)->isLegalZfaFPImm(APF, VT))
+ return false;
+
MVT XLenVT = Subtarget->getXLenVT();
- if (CFP->getValueType(0) == MVT::f64 && !Subtarget->is64Bit()) {
+ if (VT == MVT::f64 && !Subtarget->is64Bit()) {
assert(APF.isNegZero() && "Unexpected constant.");
return false;
}
return false;
}
+bool RISCVTargetLowering::isLegalZfaFPImm(const APFloat &Imm, EVT VT) const {
+ if (!Subtarget.hasStdExtZfa() || !VT.isSimple())
+ return false;
+
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ return false;
+ case MVT::f16:
+ return (Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh()) &&
+ RISCVLoadFPImm::getLoadFP16Imm(Imm) != -1;
+ case MVT::f32:
+ return RISCVLoadFPImm::getLoadFP32Imm(Imm) != -1;
+ case MVT::f64:
+ assert(Subtarget.hasStdExtD() && "Expect D extension");
+ return RISCVLoadFPImm::getLoadFP64Imm(Imm) != -1;
+ }
+}
+
bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const {
if (VT == MVT::f16 && !Subtarget.hasStdExtZfhOrZfhmin())
if (VT == MVT::f64 && !Subtarget.hasStdExtD())
return false;
- if (Subtarget.hasStdExtZfa()) {
- // fli.h requires Zfh, but we might only have Zfhmin.
- if (VT == MVT::f16 && Subtarget.hasStdExtZfh() &&
- RISCVLoadFPImm::getLoadFP16Imm(Imm) != -1)
- return true;
- if (VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(Imm) != -1)
- return true;
- if (VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(Imm) != -1)
- return true;
- }
+ if (isLegalZfaFPImm(Imm, VT))
+ return true;
// Cannot create a 64 bit floating-point immediate value for rv32.
if (Subtarget.getXLen() < VT.getScalarSizeInBits()) {
SmallVectorImpl<Use *> &Ops) const override;
bool shouldScalarizeBinop(SDValue VecOp) const override;
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
+ bool isLegalZfaFPImm(const APFloat &Imm, EVT VT) const;
bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+zfh,+experimental-zfa,+experimental-zvfh,+v -target-abi ilp32d -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK
+; RUN: llc -mtriple=riscv64 -mattr=+zfh,+experimental-zfa,+experimental-zvfh,+v -target-abi lp64d -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK
+
+define <vscale x 8 x half> @vsplat_f16_0p625() {
+; CHECK-LABEL: vsplat_f16_0p625:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fli.h ft0, 0.625
+; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma
+; CHECK-NEXT: vfmv.v.f v8, ft0
+; CHECK-NEXT: ret
+ %head = insertelement <vscale x 8 x half> poison, half 0.625, i32 0
+ %splat = shufflevector <vscale x 8 x half> %head, <vscale x 8 x half> poison, <vscale x 8 x i32> zeroinitializer
+ ret <vscale x 8 x half> %splat
+}
+
+define <vscale x 8 x float> @vsplat_f32_0p75() {
+; CHECK-LABEL: vsplat_f32_0p75:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fli.s ft0, 0.75
+; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma
+; CHECK-NEXT: vfmv.v.f v8, ft0
+; CHECK-NEXT: ret
+ %head = insertelement <vscale x 8 x float> poison, float 0.75, i32 0
+ %splat = shufflevector <vscale x 8 x float> %head, <vscale x 8 x float> poison, <vscale x 8 x i32> zeroinitializer
+ ret <vscale x 8 x float> %splat
+}
+
+define <vscale x 8 x double> @vsplat_f64_neg1() {
+; CHECK-LABEL: vsplat_f64_neg1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fli.d ft0, -1.0
+; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma
+; CHECK-NEXT: vfmv.v.f v8, ft0
+; CHECK-NEXT: ret
+ %head = insertelement <vscale x 8 x double> poison, double -1.0, i32 0
+ %splat = shufflevector <vscale x 8 x double> %head, <vscale x 8 x double> poison, <vscale x 8 x i32> zeroinitializer
+ ret <vscale x 8 x double> %splat
+}