diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -92,6 +92,8 @@ addRegisterClass(MVT::f32, &RISCV::FPR32RegClass); if (Subtarget.hasStdExtD()) addRegisterClass(MVT::f64, &RISCV::FPR64RegClass); + if (Subtarget.hasStdExtZfinx()) + addRegisterClass(MVT::f32, &RISCV::GPRF32RegClass); static const MVT::SimpleValueType BoolVecVTs[] = { MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1, @@ -379,7 +381,7 @@ setOperationAction(ISD::FPOWI, MVT::i32, Custom); } - if (Subtarget.hasStdExtF()) { + if (Subtarget.hasStdExtF() || Subtarget.hasStdExtZfinx()) { for (auto NT : FPLegalNodeTypes) setOperationAction(NT, MVT::f32, Legal); for (auto CC : FPCCToExpand) @@ -1345,7 +1347,7 @@ // FIXME: Change to Zfhmin once f16 becomes a legal type with Zfhmin. if (VT == MVT::f16 && !Subtarget.hasStdExtZfh()) return false; - if (VT == MVT::f32 && !Subtarget.hasStdExtF()) + if (VT == MVT::f32 && !Subtarget.hasStdExtF() && !Subtarget.hasStdExtZfinx()) return false; if (VT == MVT::f64 && !Subtarget.hasStdExtD()) return false; @@ -1354,7 +1356,8 @@ bool RISCVTargetLowering::hasBitPreservingFPLogic(EVT VT) const { return (VT == MVT::f16 && Subtarget.hasStdExtZfh()) || - (VT == MVT::f32 && Subtarget.hasStdExtF()) || + (VT == MVT::f32 && + (Subtarget.hasStdExtF() || Subtarget.hasStdExtZfinx())) || (VT == MVT::f64 && Subtarget.hasStdExtD()); } @@ -11511,7 +11514,7 @@ case MVT::f16: return Subtarget.hasStdExtZfh(); case MVT::f32: - return Subtarget.hasStdExtF(); + return Subtarget.hasStdExtF() || Subtarget.hasStdExtZfinx(); case MVT::f64: return Subtarget.hasStdExtD(); default: diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -461,22 +461,50 @@ def fpimmneg0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(-0.0); }]>; /// Generic pattern classes -class PatSetCC +class PatSetCC : Pat<(OpNode Ty:$rs1, Ty:$rs2, Cond), (Inst $rs1, $rs2)>; +multiclass PatSetCC_m Exts> { + foreach Ext = Exts in + let Predicates = Ext.Predicates in + def Ext.Suffix : PatSetCC(Inst#Ext.Suffix)>; +} class PatFprFpr + DAGOperand RegTy> : Pat<(OpNode RegTy:$rs1, RegTy:$rs2), (Inst $rs1, $rs2)>; +multiclass PatFprFpr_m Exts> { + foreach Ext = Exts in + let Predicates = Ext.Predicates in + def Ext.Suffix : PatFprFpr(Inst#Ext.Suffix), + Ext.Reg>; +} class PatFprFprDynFrm + DAGOperand RegTy> : Pat<(OpNode RegTy:$rs1, RegTy:$rs2), (Inst $rs1, $rs2, 0b111)>; +multiclass PatFprFprDynFrm_m Exts> { + foreach Ext = Exts in + let Predicates = Ext.Predicates in + def Ext.Suffix : PatFprFprDynFrm(Inst#Ext.Suffix), + Ext.Reg>; +} let Predicates = [HasStdExtF] in { - /// Float constants def : Pat<(f32 (fpimm0)), (FMV_W_X X0)>; def : Pat<(f32 (fpimmneg0)), (FSGNJN_S (FMV_W_X X0), (FMV_W_X X0))>; +} // Predicates = [HasStdExtF] + +let Predicates = [HasStdExtZfinx] in { +def : Pat<(f32 (fpimm0)), (COPY (f32 X0))>; +def : Pat<(f32 (fpimmneg0)), (FSGNJN_S_INX (COPY (f32 X0)), (COPY (f32 X0)))>; +} // Predicates = [HasStdExtZfinx] /// Float conversion operations @@ -484,18 +512,28 @@ // are defined later. /// Float arithmetic operations +defm : PatFprFprDynFrm_m; +defm : PatFprFprDynFrm_m; +defm : PatFprFprDynFrm_m; +defm : PatFprFprDynFrm_m; -def : PatFprFprDynFrm; -def : PatFprFprDynFrm; -def : PatFprFprDynFrm; -def : PatFprFprDynFrm; - +let Predicates = [HasStdExtF] in { def : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, 0b111)>; def : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>; def : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>; +} // Predicates = [HasStdExtF] + +let Predicates = [HasStdExtZfinx] in { +def : Pat<(any_fsqrt FPR32INX:$rs1), (FSQRT_S_INX FPR32INX:$rs1, 0b111)>; + +def : Pat<(fneg FPR32INX:$rs1), (FSGNJN_S_INX $rs1, $rs1)>; +def : Pat<(fabs FPR32INX:$rs1), (FSGNJX_S_INX $rs1, $rs1)>; +} // Predicates = [HasStdExtZfinx] + +defm : PatFprFpr_m; -def : PatFprFpr; +let Predicates = [HasStdExtF] in { def : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>; // fmadd: rs1 * rs2 + rs3 @@ -513,20 +551,42 @@ // fnmadd: -rs1 * rs2 - rs3 def : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)), (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; +} // Predicates = [HasStdExtF] + +let Predicates = [HasStdExtZfinx] in { +def : Pat<(fcopysign FPR32INX:$rs1, (fneg FPR32INX:$rs2)), (FSGNJN_S_INX $rs1, $rs2)>; + +// fmadd: rs1 * rs2 + rs3 +def : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3), + (FMADD_S_INX $rs1, $rs2, $rs3, 0b111)>; + +// fmsub: rs1 * rs2 - rs3 +def : Pat<(any_fma FPR32INX:$rs1, FPR32INX:$rs2, (fneg FPR32INX:$rs3)), + (FMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, 0b111)>; + +// fnmsub: -rs1 * rs2 + rs3 +def : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, FPR32INX:$rs3), + (FNMSUB_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, 0b111)>; + +// fnmadd: -rs1 * rs2 - rs3 +def : Pat<(any_fma (fneg FPR32INX:$rs1), FPR32INX:$rs2, (fneg FPR32INX:$rs3)), + (FNMADD_S_INX FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3, 0b111)>; +} // Predicates = [HasStdExtZfinx] // The ratified 20191213 ISA spec defines fmin and fmax in a way that matches // LLVM's fminnum and fmaxnum // . -def : PatFprFpr; -def : PatFprFpr; +defm : PatFprFpr_m; +defm : PatFprFpr_m; /// Setcc // FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for // strict versions of those. // Match non-signaling FEQ_S -def : PatSetCC; -def : PatSetCC; +defm : PatSetCC_m; +defm : PatSetCC_m; +let Predicates = [HasStdExtF] in { def : PatSetCC; def : PatSetCC; def : PatSetCC; @@ -566,7 +626,15 @@ // Moves (no conversion) def : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>; def : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>; +} // Predicates = [HasStdExtF, IsRV32] + +let Predicates = [HasStdExtZfinx, IsRV32] in { +// Moves (no conversion) +def : Pat<(f32 (bitconvert (i32 GPR:$rs1))), (COPY GPR:$rs1)>; +def : Pat<(i32 (bitconvert FPR32INX:$rs1)), (COPY FPR32INX:$rs1)>; +} // Predicates = [HasStdExtZfinx, IsRV32] +let Predicates = [HasStdExtF, IsRV32] in { // float->[u]int. Round-to-zero must be used. def : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; def : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; @@ -592,7 +660,17 @@ def : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>; def : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 FPR32:$src), i32), (FMV_X_W FPR32:$src)>; +} // Predicates = [HasStdExtF, IsRV64] +let Predicates = [HasStdExtZfinx, IsRV64] in { +// Moves (no conversion) +def : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (COPY GPR:$src)>; +def : Pat<(riscv_fmv_x_anyextw_rv64 GPRF32:$src), (COPY GPRF32:$src)>; +def : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 GPRF32:$src), i32), + (COPY GPRF32:$src)>; +} // Predicates = [HasStdExtZfinx, IsRV64] + +let Predicates = [HasStdExtF, IsRV64] in { // Use target specific isd nodes to help us remember the result is sign // extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be // duplicated if it has another user that didn't need the sign_extend. diff --git a/llvm/test/CodeGen/RISCV/float-arith-strict.ll b/llvm/test/CodeGen/RISCV/float-arith-strict.ll --- a/llvm/test/CodeGen/RISCV/float-arith-strict.ll +++ b/llvm/test/CodeGen/RISCV/float-arith-strict.ll @@ -5,6 +5,12 @@ ; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ ; RUN: -disable-strictnode-mutation -target-abi=lp64f \ ; RUN: | FileCheck -check-prefix=RV64IF %s +; RUN: llc -mtriple=riscv32 -mattr=+zfinx -verify-machineinstrs < %s \ +; RUN: -disable-strictnode-mutation -target-abi=ilp32 \ +; RUN: | FileCheck -check-prefix=RV32IZFINX %s +; RUN: llc -mtriple=riscv64 -mattr=+zfinx -verify-machineinstrs < %s \ +; RUN: -disable-strictnode-mutation -target-abi=lp64 \ +; RUN: | FileCheck -check-prefix=RV64IZFINX %s ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: -disable-strictnode-mutation | FileCheck -check-prefix=RV32I %s ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ @@ -21,6 +27,16 @@ ; RV64IF-NEXT: fadd.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fadd_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fadd_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fadd_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -54,6 +70,16 @@ ; RV64IF-NEXT: fsub.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fsub_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fsub.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fsub_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fsub.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fsub_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -87,6 +113,16 @@ ; RV64IF-NEXT: fmul.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmul_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmul.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmul_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmul.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmul_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -120,6 +156,16 @@ ; RV64IF-NEXT: fdiv.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fdiv_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fdiv.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fdiv_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fdiv.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fdiv_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -153,6 +199,16 @@ ; RV64IF-NEXT: fsqrt.s fa0, fa0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fsqrt_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fsqrt.s a0, a0 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fsqrt_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fsqrt.s a0, a0 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fsqrt_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -194,6 +250,24 @@ ; RV64IF-NEXT: addi sp, sp, 16 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmin_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: addi sp, sp, -16 +; RV32IZFINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINX-NEXT: call fminf@plt +; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINX-NEXT: addi sp, sp, 16 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmin_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: addi sp, sp, -16 +; RV64IZFINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IZFINX-NEXT: call fminf@plt +; RV64IZFINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IZFINX-NEXT: addi sp, sp, 16 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmin_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -235,6 +309,24 @@ ; RV64IF-NEXT: addi sp, sp, 16 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmax_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: addi sp, sp, -16 +; RV32IZFINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINX-NEXT: call fmaxf@plt +; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINX-NEXT: addi sp, sp, 16 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmax_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: addi sp, sp, -16 +; RV64IZFINX-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IZFINX-NEXT: call fmaxf@plt +; RV64IZFINX-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IZFINX-NEXT: addi sp, sp, 16 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmax_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -268,6 +360,16 @@ ; RV64IF-NEXT: fmadd.s fa0, fa0, fa1, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmadd_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmadd.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmadd_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmadd.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmadd_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -305,6 +407,18 @@ ; RV64IF-NEXT: fmsub.s fa0, fa0, fa1, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmsub_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fmsub.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmsub_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fmsub.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmsub_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -371,6 +485,20 @@ ; RV64IF-NEXT: fnmadd.s fa0, ft1, fa1, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmadd_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, zero +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fnmadd.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmadd_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, zero +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fnmadd.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmadd_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -451,6 +579,20 @@ ; RV64IF-NEXT: fnmadd.s fa0, ft1, fa0, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmadd_s_2: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a1, a1, zero +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fnmadd.s a0, a1, a0, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmadd_s_2: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a1, a1, zero +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fnmadd.s a0, a1, a0, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmadd_s_2: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -529,6 +671,18 @@ ; RV64IF-NEXT: fnmsub.s fa0, ft0, fa1, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmsub_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, zero +; RV32IZFINX-NEXT: fnmsub.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmsub_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, zero +; RV64IZFINX-NEXT: fnmsub.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmsub_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -591,6 +745,18 @@ ; RV64IF-NEXT: fnmsub.s fa0, ft0, fa0, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmsub_s_2: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a1, a1, zero +; RV32IZFINX-NEXT: fnmsub.s a0, a1, a0, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmsub_s_2: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a1, a1, zero +; RV64IZFINX-NEXT: fnmsub.s a0, a1, a0, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmsub_s_2: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 diff --git a/llvm/test/CodeGen/RISCV/float-arith.ll b/llvm/test/CodeGen/RISCV/float-arith.ll --- a/llvm/test/CodeGen/RISCV/float-arith.ll +++ b/llvm/test/CodeGen/RISCV/float-arith.ll @@ -3,6 +3,10 @@ ; RUN: -target-abi=ilp32f | FileCheck -check-prefix=RV32IF %s ; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ ; RUN: -target-abi=lp64f | FileCheck -check-prefix=RV64IF %s +; RUN: llc -mtriple=riscv32 -mattr=+zfinx -verify-machineinstrs < %s \ +; RUN: -target-abi=ilp32 | FileCheck -check-prefix=RV32IZFINX %s +; RUN: llc -mtriple=riscv64 -mattr=+zfinx -verify-machineinstrs < %s \ +; RUN: -target-abi=lp64 | FileCheck -check-prefix=RV64IZFINX %s ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV32I %s ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ @@ -24,6 +28,16 @@ ; RV64IF-NEXT: fadd.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fadd_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fadd_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fadd_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -56,6 +70,16 @@ ; RV64IF-NEXT: fsub.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fsub_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fsub.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fsub_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fsub.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fsub_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -88,6 +112,16 @@ ; RV64IF-NEXT: fmul.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmul_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmul.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmul_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmul.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmul_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -120,6 +154,16 @@ ; RV64IF-NEXT: fdiv.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fdiv_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fdiv.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fdiv_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fdiv.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fdiv_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -154,6 +198,16 @@ ; RV64IF-NEXT: fsqrt.s fa0, fa0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fsqrt_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fsqrt.s a0, a0 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fsqrt_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fsqrt.s a0, a0 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fsqrt_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -188,6 +242,16 @@ ; RV64IF-NEXT: fsgnj.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fsgnj_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fsgnj.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fsgnj_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fsgnj.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fsgnj_s: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a2, 524288 @@ -226,6 +290,20 @@ ; RV64IF-NEXT: feq.s a0, ft0, ft1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fneg_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, a0 +; RV32IZFINX-NEXT: fneg.s a1, a0 +; RV32IZFINX-NEXT: feq.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fneg_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, a0 +; RV64IZFINX-NEXT: fneg.s a1, a0 +; RV64IZFINX-NEXT: feq.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fneg_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -275,6 +353,18 @@ ; RV64IF-NEXT: fsgnjn.s fa0, fa0, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fsgnjn_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a1, a0, a1 +; RV32IZFINX-NEXT: fsgnjn.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fsgnjn_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a1, a0, a1 +; RV64IZFINX-NEXT: fsgnjn.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fsgnjn_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -335,6 +425,20 @@ ; RV64IF-NEXT: fadd.s fa0, ft1, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fabs_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, a1 +; RV32IZFINX-NEXT: fabs.s a1, a0 +; RV32IZFINX-NEXT: fadd.s a0, a1, a0 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fabs_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, a1 +; RV64IZFINX-NEXT: fabs.s a1, a0 +; RV64IZFINX-NEXT: fadd.s a0, a1, a0 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fabs_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -379,6 +483,16 @@ ; RV64IF-NEXT: fmin.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmin_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmin.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmin_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmin.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmin_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -413,6 +527,16 @@ ; RV64IF-NEXT: fmax.s fa0, fa0, fa1 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmax_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmax.s a0, a0, a1 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmax_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmax.s a0, a0, a1 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmax_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -447,6 +571,16 @@ ; RV64IF-NEXT: fmadd.s fa0, fa0, fa1, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmadd_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmadd.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmadd_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmadd.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmadd_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -483,6 +617,18 @@ ; RV64IF-NEXT: fmsub.s fa0, fa0, fa1, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmsub_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fmsub.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmsub_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fmsub.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmsub_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -549,6 +695,20 @@ ; RV64IF-NEXT: fnmadd.s fa0, ft1, fa1, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmadd_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, zero +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fnmadd.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmadd_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, zero +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fnmadd.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmadd_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -629,6 +789,20 @@ ; RV64IF-NEXT: fnmadd.s fa0, ft1, fa0, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmadd_s_2: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a1, a1, zero +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fnmadd.s a0, a1, a0, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmadd_s_2: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a1, a1, zero +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fnmadd.s a0, a1, a0, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmadd_s_2: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -707,6 +881,18 @@ ; RV64IF-NEXT: fnmsub.s fa0, ft0, fa1, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmsub_s: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, zero +; RV32IZFINX-NEXT: fnmsub.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmsub_s: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, zero +; RV64IZFINX-NEXT: fnmsub.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmsub_s: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -769,6 +955,18 @@ ; RV64IF-NEXT: fnmsub.s fa0, ft0, fa0, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmsub_s_2: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a1, a1, zero +; RV32IZFINX-NEXT: fnmsub.s a0, a1, a0, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmsub_s_2: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a1, a1, zero +; RV64IZFINX-NEXT: fnmsub.s a0, a1, a0, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmsub_s_2: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -829,6 +1027,16 @@ ; RV64IF-NEXT: fmadd.s fa0, fa0, fa1, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmadd_s_contract: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fmadd.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmadd_s_contract: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fmadd.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmadd_s_contract: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -876,6 +1084,18 @@ ; RV64IF-NEXT: fmsub.s fa0, fa0, fa1, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fmsub_s_contract: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fmsub.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fmsub_s_contract: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fmsub.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fmsub_s_contract: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -950,6 +1170,22 @@ ; RV64IF-NEXT: fnmadd.s fa0, ft1, ft2, ft0 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmadd_s_contract: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, zero +; RV32IZFINX-NEXT: fadd.s a1, a1, zero +; RV32IZFINX-NEXT: fadd.s a2, a2, zero +; RV32IZFINX-NEXT: fnmadd.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmadd_s_contract: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, zero +; RV64IZFINX-NEXT: fadd.s a1, a1, zero +; RV64IZFINX-NEXT: fadd.s a2, a2, zero +; RV64IZFINX-NEXT: fnmadd.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmadd_s_contract: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16 @@ -1043,6 +1279,20 @@ ; RV64IF-NEXT: fnmsub.s fa0, ft1, ft0, fa2 ; RV64IF-NEXT: ret ; +; RV32IZFINX-LABEL: fnmsub_s_contract: +; RV32IZFINX: # %bb.0: +; RV32IZFINX-NEXT: fadd.s a0, a0, zero +; RV32IZFINX-NEXT: fadd.s a1, a1, zero +; RV32IZFINX-NEXT: fnmsub.s a0, a0, a1, a2 +; RV32IZFINX-NEXT: ret +; +; RV64IZFINX-LABEL: fnmsub_s_contract: +; RV64IZFINX: # %bb.0: +; RV64IZFINX-NEXT: fadd.s a0, a0, zero +; RV64IZFINX-NEXT: fadd.s a1, a1, zero +; RV64IZFINX-NEXT: fnmsub.s a0, a0, a1, a2 +; RV64IZFINX-NEXT: ret +; ; RV32I-LABEL: fnmsub_s_contract: ; RV32I: # %bb.0: ; RV32I-NEXT: addi sp, sp, -16