[llvm] 95d3fd9 - [RISCV] Refactor how we create separate instructions for F and Zfinx. NFC

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 16 11:23:07 PDT 2023


Author: Craig Topper
Date: 2023-06-16T11:22:44-07:00
New Revision: 95d3fd9a91376e0ef60c4e7599b4d224ac6f0e6f

URL: https://github.com/llvm/llvm-project/commit/95d3fd9a91376e0ef60c4e7599b4d224ac6f0e6f
DIFF: https://github.com/llvm/llvm-project/commit/95d3fd9a91376e0ef60c4e7599b4d224ac6f0e6f.diff

LOG: [RISCV] Refactor how we create separate instructions for F and Zfinx. NFC

Previously we had a ExtInfo_rr class that was instantiated for
every combination of types that can appear together along with
their predicates, suffixes, and decoder namespace.

This patch replaces this with a new ExtInfo class that contains
predicates, suffix, namespace, and the f16, f32, and f64 DAGOperands
implied by the predicates. The DAGOperand can be unset if
the predicate is not enough to distinquish it.

At every instruction instantiation we know whether the operands
are GPR, f16, f32, or f64 and can ask the ExtInfo for the relevant
DAGOperand.

The foreach loops of ExtInfo have been moved out of the classes to
be at the top level of the 3 files. This allows the file to pick
the f16/f32/f64 DAGOperand per instruction and pass it down to the
classes separately from the ExtInfo. The ExtInfo still needs to be
passed down to get suffix, predicates, and decoder namespace.

Reviewed By: sunshaoce

Differential Revision: https://reviews.llvm.org/D152948

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVInstrInfoD.td
    llvm/lib/Target/RISCV/RISCVInstrInfoF.td
    llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
index 80132c92f78cb..f2099a4652a59 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
@@ -54,41 +54,15 @@ def FPR64IN32X : RegisterOperand<GPRPF64> {
   let ParserMatchClass = GPRPF64AsFPR;
 }
 
-def DExt       : ExtInfo<0, [HasStdExtD]>;
-def ZdinxExt   : ExtInfo<1, [HasStdExtZdinx, IsRV64]>;
-def Zdinx32Ext : ExtInfo<2, [HasStdExtZdinx, IsRV32]>;
-
-def D       : ExtInfo_r<DExt,       FPR64>;
-def D_INX   : ExtInfo_r<ZdinxExt,   FPR64INX>;
-def D_IN32X : ExtInfo_r<Zdinx32Ext, FPR64IN32X>;
-
-def DD       : ExtInfo_rr<DExt,       FPR64,      FPR64>;
-def DD_INX   : ExtInfo_rr<ZdinxExt,   FPR64INX,   FPR64INX>;
-def DD_IN32X : ExtInfo_rr<Zdinx32Ext, FPR64IN32X, FPR64IN32X>;
-def DF       : ExtInfo_rr<DExt,       FPR64,      FPR32>;
-def DF_INX   : ExtInfo_rr<ZdinxExt,   FPR64INX,   FPR32INX>;
-def DF_IN32X : ExtInfo_rr<Zdinx32Ext, FPR64IN32X, FPR32INX>;
-def DX       : ExtInfo_rr<DExt,       FPR64,      GPR>;
-def DX_INX   : ExtInfo_rr<ZdinxExt,   FPR64INX,   GPR>;
-def DX_IN32X : ExtInfo_rr<Zdinx32Ext, FPR64IN32X, GPR>;
-def FD       : ExtInfo_rr<DExt,       FPR32,      FPR64>;
-def FD_INX   : ExtInfo_rr<ZdinxExt,   FPR32INX,   FPR64INX>;
-def FD_IN32X : ExtInfo_rr<Zdinx32Ext, FPR32INX,   FPR64IN32X>;
-def XD       : ExtInfo_rr<DExt,       GPR,        FPR64>;
-def XD_INX   : ExtInfo_rr<ZdinxExt,   GPR,        FPR64INX>;
-def XD_IN32X : ExtInfo_rr<Zdinx32Ext, GPR,        FPR64IN32X>;
-
-defvar DINX    = [D,     D_INX,  D_IN32X];
-defvar DDINX   = [DD,    DD_INX, DD_IN32X];
-defvar DXINX   = [DX,    DX_INX, DX_IN32X];
-defvar DFINX   = [DF,    DF_INX, DF_IN32X];
-defvar FDINX   = [FD,    FD_INX, FD_IN32X];
-defvar XDINX   = [XD,    XD_INX, XD_IN32X];
-
-// Lists without the IN32X classes that aren't needed for some RV64-only 
-// instructions.
-defvar DXINXRV64  = [DX,    DX_INX];
-defvar XDINXRV64  = [XD,    XD_INX];
+def DExt       : ExtInfo<"", "", [HasStdExtD], FPR64, FPR32, FPR64, ?>;
+
+def ZdinxExt   : ExtInfo<"_INX", "RVZfinx", [HasStdExtZdinx, IsRV64],
+                         FPR64INX, FPR32INX, FPR64INX, ?>;
+def Zdinx32Ext : ExtInfo<"_IN32X", "RV32Zdinx", [HasStdExtZdinx, IsRV32],
+                         FPR64IN32X, FPR32INX, FPR64IN32X, ?>;
+
+defvar DExts     = [DExt, ZdinxExt, Zdinx32Ext];
+defvar DExtsRV64 = [DExt, ZdinxExt];
 
 //===----------------------------------------------------------------------===//
 // Instructions
@@ -103,84 +77,100 @@ def FLD : FPLoad_r<0b011, "fld", FPR64, WriteFLD64>;
 def FSD : FPStore_r<0b011, "fsd", FPR64, WriteFST64>;
 } // Predicates = [HasStdExtD]
 
-let SchedRW = [WriteFMA64, ReadFMA64, ReadFMA64, ReadFMA64] in {
-defm FMADD_D  : FPFMA_rrr_frm_m<OPC_MADD,  0b01, "fmadd.d",  DINX>;
-defm FMSUB_D  : FPFMA_rrr_frm_m<OPC_MSUB,  0b01, "fmsub.d",  DINX>;
-defm FNMSUB_D : FPFMA_rrr_frm_m<OPC_NMSUB, 0b01, "fnmsub.d", DINX>;
-defm FNMADD_D : FPFMA_rrr_frm_m<OPC_NMADD, 0b01, "fnmadd.d", DINX>;
-}
-
-let SchedRW = [WriteFAdd64, ReadFAdd64, ReadFAdd64] in {
-defm FADD_D : FPALU_rr_frm_m<0b0000001, "fadd.d", DINX, /*Commutable*/1>;
-defm FSUB_D : FPALU_rr_frm_m<0b0000101, "fsub.d", DINX>;
-}
-let SchedRW = [WriteFMul64, ReadFMul64, ReadFMul64] in
-defm FMUL_D : FPALU_rr_frm_m<0b0001001, "fmul.d", DINX, /*Commutable*/1>;
-
-let SchedRW = [WriteFDiv64, ReadFDiv64, ReadFDiv64] in
-defm FDIV_D : FPALU_rr_frm_m<0b0001101, "fdiv.d", DINX>;
-
-defm FSQRT_D : FPUnaryOp_r_frm_m<0b0101101, 0b00000, DDINX, "fsqrt.d">,
-               Sched<[WriteFSqrt64, ReadFSqrt64]>;
-
-let SchedRW = [WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64],
-    mayRaiseFPException = 0 in {
-defm FSGNJ_D  : FPALU_rr_m<0b0010001, 0b000, "fsgnj.d",  DINX>;
-defm FSGNJN_D : FPALU_rr_m<0b0010001, 0b001, "fsgnjn.d", DINX>;
-defm FSGNJX_D : FPALU_rr_m<0b0010001, 0b010, "fsgnjx.d", DINX>;
-}
-
-let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in {
-defm FMIN_D   : FPALU_rr_m<0b0010101, 0b000, "fmin.d", DINX, /*Commutable*/1>;
-defm FMAX_D   : FPALU_rr_m<0b0010101, 0b001, "fmax.d", DINX, /*Commutable*/1>;
-}
-
-defm FCVT_S_D : FPUnaryOp_r_frm_m<0b0100000, 0b00001, FDINX, "fcvt.s.d">,
-                Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]>;
-
-defm FCVT_D_S : FPUnaryOp_r_m<0b0100001, 0b00000, 0b000, DFINX, "fcvt.d.s">,
-                Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]>;
-
-let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in {
-defm FEQ_D : FPCmp_rr_m<0b1010001, 0b010, "feq.d", DINX, /*Commutable*/1>;
-defm FLT_D : FPCmp_rr_m<0b1010001, 0b001, "flt.d", DINX>;
-defm FLE_D : FPCmp_rr_m<0b1010001, 0b000, "fle.d", DINX>;
-}
+foreach Ext = DExts in {
+  let SchedRW = [WriteFMA64, ReadFMA64, ReadFMA64, ReadFMA64] in {
+    defm FMADD_D  : FPFMA_rrr_frm_m<OPC_MADD,  0b01, "fmadd.d",  Ext>;
+    defm FMSUB_D  : FPFMA_rrr_frm_m<OPC_MSUB,  0b01, "fmsub.d",  Ext>;
+    defm FNMSUB_D : FPFMA_rrr_frm_m<OPC_NMSUB, 0b01, "fnmsub.d", Ext>;
+    defm FNMADD_D : FPFMA_rrr_frm_m<OPC_NMADD, 0b01, "fnmadd.d", Ext>;
+  }
+
+  let SchedRW = [WriteFAdd64, ReadFAdd64, ReadFAdd64] in {
+    defm FADD_D : FPALU_rr_frm_m<0b0000001, "fadd.d", Ext, /*Commutable*/1>;
+    defm FSUB_D : FPALU_rr_frm_m<0b0000101, "fsub.d", Ext>;
+  }
+  let SchedRW = [WriteFMul64, ReadFMul64, ReadFMul64] in
+  defm FMUL_D : FPALU_rr_frm_m<0b0001001, "fmul.d", Ext, /*Commutable*/1>;
+
+  let SchedRW = [WriteFDiv64, ReadFDiv64, ReadFDiv64] in
+  defm FDIV_D : FPALU_rr_frm_m<0b0001101, "fdiv.d", Ext>;
+
+  defm FSQRT_D : FPUnaryOp_r_frm_m<0b0101101, 0b00000, Ext, Ext.PrimaryTy,
+                                   Ext.PrimaryTy, "fsqrt.d">,
+                 Sched<[WriteFSqrt64, ReadFSqrt64]>;
+
+  let SchedRW = [WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64],
+      mayRaiseFPException = 0 in {
+    defm FSGNJ_D  : FPALU_rr_m<0b0010001, 0b000, "fsgnj.d",  Ext>;
+    defm FSGNJN_D : FPALU_rr_m<0b0010001, 0b001, "fsgnjn.d", Ext>;
+    defm FSGNJX_D : FPALU_rr_m<0b0010001, 0b010, "fsgnjx.d", Ext>;
+  }
+
+  let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in {
+    defm FMIN_D   : FPALU_rr_m<0b0010101, 0b000, "fmin.d", Ext, /*Commutable*/1>;
+    defm FMAX_D   : FPALU_rr_m<0b0010101, 0b001, "fmax.d", Ext, /*Commutable*/1>;
+  }
+
+  defm FCVT_S_D : FPUnaryOp_r_frm_m<0b0100000, 0b00001, Ext, Ext.F32Ty,
+                                    Ext.PrimaryTy, "fcvt.s.d">,
+                  Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]>;
+
+  defm FCVT_D_S : FPUnaryOp_r_m<0b0100001, 0b00000, 0b000, Ext, Ext.PrimaryTy,
+                                Ext.F32Ty, "fcvt.d.s">,
+                  Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]>;
+
+  let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in {
+    defm FEQ_D : FPCmp_rr_m<0b1010001, 0b010, "feq.d", Ext, /*Commutable*/1>;
+    defm FLT_D : FPCmp_rr_m<0b1010001, 0b001, "flt.d", Ext>;
+    defm FLE_D : FPCmp_rr_m<0b1010001, 0b000, "fle.d", Ext>;
+  }
+
+  let mayRaiseFPException = 0 in
+  defm FCLASS_D : FPUnaryOp_r_m<0b1110001, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,
+                                "fclass.d">,
+                  Sched<[WriteFClass64, ReadFClass64]>;
+
+  let IsSignExtendingOpW = 1 in
+  defm FCVT_W_D : FPUnaryOp_r_frm_m<0b1100001, 0b00000, Ext, GPR, Ext.PrimaryTy,
+                                    "fcvt.w.d">,
+                 Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
 
-let mayRaiseFPException = 0 in
-defm FCLASS_D : FPUnaryOp_r_m<0b1110001, 0b00000, 0b001, XDINX, "fclass.d">,
-                Sched<[WriteFClass64, ReadFClass64]>;
+  let IsSignExtendingOpW = 1 in
+  defm FCVT_WU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00001, Ext, GPR, Ext.PrimaryTy,
+                                     "fcvt.wu.d">,
+                   Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
 
-let IsSignExtendingOpW = 1 in
-defm FCVT_W_D : FPUnaryOp_r_frm_m<0b1100001, 0b00000, XDINX, "fcvt.w.d">,
-               Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
+  defm FCVT_D_W : FPUnaryOp_r_m<0b1101001, 0b00000, 0b000, Ext, Ext.PrimaryTy, GPR,
+                                "fcvt.d.w">,
+                  Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
 
-let IsSignExtendingOpW = 1 in
-defm FCVT_WU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00001, XDINX, "fcvt.wu.d">,
-                 Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
+  defm FCVT_D_WU : FPUnaryOp_r_m<0b1101001, 0b00001, 0b000, Ext, Ext.PrimaryTy, GPR,
+                                 "fcvt.d.wu">,
+                   Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
+} // foreach Ext = DExts
 
-defm FCVT_D_W : FPUnaryOp_r_m<0b1101001, 0b00000, 0b000, DXINX, "fcvt.d.w">,
-                Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
+foreach Ext = DExtsRV64 in {
+  defm FCVT_L_D : FPUnaryOp_r_frm_m<0b1100001, 0b00010, Ext, GPR, Ext.PrimaryTy,
+                                    "fcvt.l.d", [IsRV64]>,
+                  Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
 
-defm FCVT_D_WU : FPUnaryOp_r_m<0b1101001, 0b00001, 0b000, DXINX, "fcvt.d.wu">,
-                 Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
+  defm FCVT_LU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00011, Ext, GPR, Ext.PrimaryTy,
+                                     "fcvt.lu.d", [IsRV64]>,
+                   Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
 
-defm FCVT_L_D : FPUnaryOp_r_frm_m<0b1100001, 0b00010, XDINXRV64, "fcvt.l.d", [IsRV64]>,
-                Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
+  defm FCVT_D_L : FPUnaryOp_r_frm_m<0b1101001, 0b00010, Ext, Ext.PrimaryTy, GPR,
+                                    "fcvt.d.l", [IsRV64]>,
+                  Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
 
-defm FCVT_LU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00011, XDINXRV64, "fcvt.lu.d", [IsRV64]>,
-                 Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
+  defm FCVT_D_LU : FPUnaryOp_r_frm_m<0b1101001, 0b00011, Ext, Ext.PrimaryTy, GPR,
+                                     "fcvt.d.lu", [IsRV64]>,
+                   Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
+} // foreach Ext = DExts64
 
 let Predicates = [HasStdExtD, IsRV64], mayRaiseFPException = 0 in
 def FMV_X_D : FPUnaryOp_r<0b1110001, 0b00000, 0b000, GPR, FPR64, "fmv.x.d">,
               Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>;
 
-defm FCVT_D_L : FPUnaryOp_r_frm_m<0b1101001, 0b00010, DXINXRV64, "fcvt.d.l", [IsRV64]>,
-                Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
-
-defm FCVT_D_LU : FPUnaryOp_r_frm_m<0b1101001, 0b00011, DXINXRV64, "fcvt.d.lu", [IsRV64]>,
-                 Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
-
 let Predicates = [HasStdExtD, IsRV64], mayRaiseFPException = 0 in
 def FMV_D_X : FPUnaryOp_r<0b1111001, 0b00000, 0b000, FPR64, GPR, "fmv.d.x">,
               Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]>;
@@ -274,10 +264,12 @@ def : Pat<(any_fpextend FPR32INX:$rs1), (FCVT_D_S_IN32X FPR32INX:$rs1)>;
 
 /// Float arithmetic operations
 
-defm : PatFprFprDynFrm_m<any_fadd, FADD_D, DINX>;
-defm : PatFprFprDynFrm_m<any_fsub, FSUB_D, DINX>;
-defm : PatFprFprDynFrm_m<any_fmul, FMUL_D, DINX>;
-defm : PatFprFprDynFrm_m<any_fdiv, FDIV_D, DINX>;
+foreach Ext = DExts in {
+  defm : PatFprFprDynFrm_m<any_fadd, FADD_D, Ext>;
+  defm : PatFprFprDynFrm_m<any_fsub, FSUB_D, Ext>;
+  defm : PatFprFprDynFrm_m<any_fmul, FMUL_D, Ext>;
+  defm : PatFprFprDynFrm_m<any_fdiv, FDIV_D, Ext>;
+}
 
 let Predicates = [HasStdExtD] in {
 def : Pat<(any_fsqrt FPR64:$rs1), (FSQRT_D FPR64:$rs1, FRM_DYN)>;
@@ -391,20 +383,24 @@ def : Pat<(fneg (any_fma_nsz FPR64IN32X:$rs1, FPR64IN32X:$rs2, FPR64IN32X:$rs3))
 // The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
 // LLVM's fminnum and fmaxnum.
 // <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
-defm : PatFprFpr_m<fminnum, FMIN_D, DINX>;
-defm : PatFprFpr_m<fmaxnum, FMAX_D, DINX>;
+foreach Ext = DExts in {
+  defm : PatFprFpr_m<fminnum, FMIN_D, Ext>;
+  defm : PatFprFpr_m<fmaxnum, FMAX_D, Ext>;
+}
 
 /// Setcc
 // FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
 // strict versions of those.
 
 // Match non-signaling FEQ_D
-defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_D,            DINX>;
-defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_D,            DINX>;
-defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_D, DINX>;
-defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_D, DINX>;
-defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_D, DINX>;
-defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_D, DINX>;
+foreach Ext = DExts in {
+  defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_D,            Ext>;
+  defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_D,            Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_D, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_D, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_D, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_D, Ext>;
+}
 
 let Predicates = [HasStdExtD] in {
 // Match signaling FEQ_D

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
index 115cd67c4b459..bce4fe2e5ae98 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
@@ -86,51 +86,31 @@ def FPR32INX : RegisterOperand<GPRF32> {
   let DecoderMethod = "DecodeGPRRegisterClass";
 }
 
-// inx = 0 : f, d, zfh, zfhmin
-//     = 1 : zfinx, zdinx, zhinx, zhinxmin
-//     = 2 : zdinx_rv32
-class ExtInfo<bits<2> inx, list<Predicate> pres> {
-  string Suffix = !cond(!eq(inx, 0): "",
-                        !eq(inx, 1): "_INX",
-                        !eq(inx, 2): "_IN32X");
-  list<Predicate> Predicates = pres;
-  string Space = !cond(!eq(inx, 0): "",
-                       !eq(inx, 1): "RVZfinx",
-                       !eq(inx, 2): "RV32Zdinx");
-}
-
-class ExtInfo_r<ExtInfo ext, DAGOperand reg> {
-  string Suffix = ext.Suffix;
-  list<Predicate> Predicates = ext.Predicates;
-  string Space = ext.Space;
-  DAGOperand Reg = reg;
-}
-
-class ExtInfo_rr<ExtInfo ext, DAGOperand rdty, DAGOperand rs1ty> {
-  string Suffix = ext.Suffix;
-  list<Predicate> Predicates = ext.Predicates;
-  string Space = ext.Space;
-  DAGOperand RdTy = rdty;
-  DAGOperand Rs1Ty = rs1ty;
+// Describes a combination of predicates from F/D/Zfh/Zfhmin or
+// Zfinx/Zdinx/Zhinx/Zhinxmin that are applied to scalar FP instruction.
+// Contains the DAGOperand for the primary type for the predicates. The primary
+// type may be unset for combinations of predicates like Zfh+D.
+// Also contains the DAGOperand for f16/f32/f64, instruction suffix, and
+// decoder namespace that go with an instruction given those predicates.
+//
+// The DAGOperand can be unset if the predicates are not enough to define it.
+class ExtInfo<string suffix, string space, list<Predicate> predicates,
+              DAGOperand primaryty, DAGOperand f32ty, DAGOperand f64ty,
+              DAGOperand f16ty> {
+  list<Predicate> Predicates = predicates;
+  string Suffix = suffix;
+  string Space = space;
+  DAGOperand PrimaryTy = primaryty;
+  DAGOperand F16Ty = f16ty;
+  DAGOperand F32Ty = f32ty;
+  DAGOperand F64Ty = f64ty;
 }
 
-def FExt       : ExtInfo<0, [HasStdExtF]>;
-def ZfinxExt   : ExtInfo<1, [HasStdExtZfinx]>;
-
-def F      : ExtInfo_r<FExt,     FPR32>;
-def F_INX  : ExtInfo_r<ZfinxExt, FPR32INX>;
+def FExt       : ExtInfo<"", "", [HasStdExtF], FPR32, FPR32, ?, ?>;
 
-def FF        : ExtInfo_rr<FExt,       FPR32,    FPR32>;
-def FF_INX    : ExtInfo_rr<ZfinxExt,   FPR32INX, FPR32INX>;
-def FX        : ExtInfo_rr<FExt,       FPR32,    GPR>;
-def FX_INX    : ExtInfo_rr<ZfinxExt,   FPR32INX, GPR>;
-def XF        : ExtInfo_rr<FExt,       GPR,      FPR32>;
-def XF_INX    : ExtInfo_rr<ZfinxExt,   GPR,      FPR32INX>;
+def ZfinxExt   : ExtInfo<"_INX", "RVZfinx", [HasStdExtZfinx], FPR32INX, FPR32INX, ?, ?>;
 
-defvar FINX    = [F,     F_INX];
-defvar FFINX   = [FF,    FF_INX];
-defvar FXINX   = [FX,    FX_INX];
-defvar XFINX   = [XF,    XF_INX];
+defvar FExts   = [FExt, ZfinxExt];
 
 // Floating-point rounding mode
 
@@ -177,10 +157,9 @@ class FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr,
                   opcodestr, "$rd, $rs1, $rs2, $rs3$frm">;
 
 multiclass FPFMA_rrr_frm_m<RISCVOpcode opcode, bits<2> funct2,
-                           string opcodestr, list<ExtInfo_r> Exts> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
-    def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.Reg>;
+                           string opcodestr, ExtInfo Ext> {
+  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+  def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.PrimaryTy>;
 }
 
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
@@ -191,10 +170,9 @@ class FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
   let isCommutable = Commutable;
 }
 multiclass FPALU_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
-                      list<ExtInfo_r> Exts, bit Commutable = 0> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
-    def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.Reg, Commutable>;
+                      ExtInfo Ext, bit Commutable = 0> {
+  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+  def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
 }
 
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
@@ -207,10 +185,9 @@ class FPALU_rr_frm<bits<7> funct7, string opcodestr, DAGOperand rty,
   let isCommutable = Commutable;
 }
 multiclass FPALU_rr_frm_m<bits<7> funct7, string opcodestr,
-                          list<ExtInfo_r> Exts, bit Commutable = 0> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
-    def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.Reg, Commutable>;
+                          ExtInfo Ext, bit Commutable = 0> {
+  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+  def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.PrimaryTy, Commutable>;
 }
 
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
@@ -221,11 +198,10 @@ class FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
   let rs2 = rs2val;
 }
 multiclass FPUnaryOp_r_m<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
-                         list<ExtInfo_rr> Exts, string opcodestr> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
-    def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, Ext.RdTy, Ext.Rs1Ty,
-                                 opcodestr>;
+                         ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
+                         string opcodestr> {
+  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+  def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, rdty, rs1ty, opcodestr>;
 }
 
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
@@ -238,13 +214,12 @@ class FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
   let rs2 = rs2val;
 }
 multiclass FPUnaryOp_r_frm_m<bits<7> funct7, bits<5> rs2val,
-                             list<ExtInfo_rr> Exts, string opcodestr,
-                             list<Predicate> ExtraPreds = []> {
-  foreach Ext = Exts in
-    let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
-        DecoderNamespace = Ext.Space in
-    def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, Ext.RdTy, Ext.Rs1Ty,
-                                     opcodestr>;
+                             ExtInfo Ext, DAGOperand rdty, DAGOperand rs1ty,
+                             string opcodestr, list<Predicate> ExtraPreds = []> {
+  let Predicates = !listconcat(Ext.Predicates, ExtraPreds),
+      DecoderNamespace = Ext.Space in
+  def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, rdty, rs1ty,
+                                   opcodestr>;
 }
 
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
@@ -256,10 +231,9 @@ class FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
   let isCommutable = Commutable;
 }
 multiclass FPCmp_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
-                      list<ExtInfo_r> Exts, bit Commutable = 0> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
-    def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.Reg, Commutable>;
+                      ExtInfo Ext, bit Commutable = 0> {
+  let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+  def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.PrimaryTy, Commutable>;
 }
 
 class PseudoFROUND<DAGOperand Ty>
@@ -285,83 +259,96 @@ def FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;
 def FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>;
 } // Predicates = [HasStdExtF]
 
-let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32] in {
-defm FMADD_S  : FPFMA_rrr_frm_m<OPC_MADD,  0b00, "fmadd.s",  FINX>;
-defm FMSUB_S  : FPFMA_rrr_frm_m<OPC_MSUB,  0b00, "fmsub.s",  FINX>;
-defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", FINX>;
-defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", FINX>;
-}
-
-let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in {
-defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", FINX, /*Commutable*/1>;
-defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", FINX>;
-}
-let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in
-defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", FINX, /*Commutable*/1>;
-
-let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in
-defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", FINX>;
-
-defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, FFINX, "fsqrt.s">,
-               Sched<[WriteFSqrt32, ReadFSqrt32]>;
-
-let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],
-    mayRaiseFPException = 0 in {
-defm FSGNJ_S  : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s",  FINX>;
-defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", FINX>;
-defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", FINX>;
-}
-
-let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
-defm FMIN_S   : FPALU_rr_m<0b0010100, 0b000, "fmin.s", FINX, /*Commutable*/1>;
-defm FMAX_S   : FPALU_rr_m<0b0010100, 0b001, "fmax.s", FINX, /*Commutable*/1>;
-}
-
-let IsSignExtendingOpW = 1 in
-defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, XFINX, "fcvt.w.s">,
-                Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
-
-let IsSignExtendingOpW = 1 in
-defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, XFINX, "fcvt.wu.s">,
-                 Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
+foreach Ext = FExts in {
+  let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32] in {
+    defm FMADD_S  : FPFMA_rrr_frm_m<OPC_MADD,  0b00, "fmadd.s",  Ext>;
+    defm FMSUB_S  : FPFMA_rrr_frm_m<OPC_MSUB,  0b00, "fmsub.s",  Ext>;
+    defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", Ext>;
+    defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", Ext>;
+  }
+
+  let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in {
+    defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, /*Commutable*/1>;
+    defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", Ext>;
+  }
+
+  let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in
+  defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, /*Commutable*/1>;
+
+  let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in
+  defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", Ext>;
+
+  defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, Ext, Ext.PrimaryTy,
+                                   Ext.PrimaryTy, "fsqrt.s">,
+                 Sched<[WriteFSqrt32, ReadFSqrt32]>;
+
+  let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],
+      mayRaiseFPException = 0 in {
+    defm FSGNJ_S  : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s",  Ext>;
+    defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", Ext>;
+    defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", Ext>;
+  }
+
+  let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
+    defm FMIN_S   : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, /*Commutable*/1>;
+    defm FMAX_S   : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, /*Commutable*/1>;
+  }
+
+  let IsSignExtendingOpW = 1 in
+  defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, Ext, GPR, Ext.PrimaryTy,
+                                    "fcvt.w.s">,
+                  Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
+
+  let IsSignExtendingOpW = 1 in
+  defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, Ext, GPR, Ext.PrimaryTy,
+                                     "fcvt.wu.s">,
+                   Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
+
+  let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
+  defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, /*Commutable*/1>;
+  defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", Ext>;
+  defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", Ext>;
+  }
+
+  let mayRaiseFPException = 0 in
+  defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,
+                                "fclass.s">,
+                  Sched<[WriteFClass32, ReadFClass32]>;
+
+  defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, Ext, Ext.PrimaryTy, GPR,
+                                    "fcvt.s.w">,
+                  Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
+
+  defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, Ext, Ext.PrimaryTy, GPR,
+                                     "fcvt.s.wu">,
+                   Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
+
+  defm FCVT_L_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00010, Ext, GPR, Ext.PrimaryTy,
+                                     "fcvt.l.s", [IsRV64]>,
+                   Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
+
+  defm FCVT_LU_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00011, Ext, GPR, Ext.PrimaryTy,
+                                      "fcvt.lu.s", [IsRV64]>,
+                    Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
+
+  defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, Ext, Ext.PrimaryTy, GPR,
+                                    "fcvt.s.l", [IsRV64]>,
+                  Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
+
+  defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, Ext, Ext.PrimaryTy, GPR,
+                                     "fcvt.s.lu", [IsRV64]>,
+                   Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
+} // foreach Ext = FExts
 
 let Predicates = [HasStdExtF], mayRaiseFPException = 0,
     IsSignExtendingOpW = 1 in
 def FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">,
               Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>;
 
-let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
-defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", FINX, /*Commutable*/1>;
-defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", FINX>;
-defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", FINX>;
-}
-
-let mayRaiseFPException = 0 in
-defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, XFINX, "fclass.s">,
-                Sched<[WriteFClass32, ReadFClass32]>;
-
-defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, FXINX, "fcvt.s.w">,
-                Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
-
-defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, FXINX, "fcvt.s.wu">,
-                 Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
-
 let Predicates = [HasStdExtF], mayRaiseFPException = 0 in
 def FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">,
               Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>;
 
-defm FCVT_L_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00010, XFINX, "fcvt.l.s", [IsRV64]>,
-                 Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
-
-defm FCVT_LU_S  : FPUnaryOp_r_frm_m<0b1100000, 0b00011, XFINX, "fcvt.lu.s", [IsRV64]>,
-                  Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
-
-defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, FXINX, "fcvt.s.l", [IsRV64]>,
-                Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
-
-defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, FXINX, "fcvt.s.lu", [IsRV64]>,
-                 Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
-
 //===----------------------------------------------------------------------===//
 // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
 //===----------------------------------------------------------------------===//
@@ -452,34 +439,31 @@ class PatSetCC<DAGOperand Ty, SDPatternOperator OpNode, CondCode Cond,
                RVInst Inst>
     : Pat<(OpNode Ty:$rs1, Ty:$rs2, Cond), (Inst $rs1, $rs2)>;
 multiclass PatSetCC_m<SDPatternOperator OpNode, CondCode Cond,
-                      RVInst Inst, list<ExtInfo_r> Exts> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates in
-    def Ext.Suffix : PatSetCC<Ext.Reg, OpNode, Cond,
-                              !cast<RVInst>(Inst#Ext.Suffix)>;
+                      RVInst Inst, ExtInfo Ext> {
+  let Predicates = Ext.Predicates in
+  def Ext.Suffix : PatSetCC<Ext.PrimaryTy, OpNode, Cond,
+                            !cast<RVInst>(Inst#Ext.Suffix)>;
 }
 
 class PatFprFpr<SDPatternOperator OpNode, RVInstR Inst,
                 DAGOperand RegTy>
     : Pat<(OpNode RegTy:$rs1, RegTy:$rs2), (Inst $rs1, $rs2)>;
 multiclass PatFprFpr_m<SDPatternOperator OpNode, RVInstR Inst,
-                       list<ExtInfo_r> Exts> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates in
-    def Ext.Suffix : PatFprFpr<OpNode, !cast<RVInstR>(Inst#Ext.Suffix),
-                               Ext.Reg>;
+                       ExtInfo Ext> {
+  let Predicates = Ext.Predicates in
+  def Ext.Suffix : PatFprFpr<OpNode, !cast<RVInstR>(Inst#Ext.Suffix),
+                             Ext.PrimaryTy>;
 }
 
 class PatFprFprDynFrm<SDPatternOperator OpNode, RVInstRFrm Inst,
                       DAGOperand RegTy>
     : Pat<(OpNode RegTy:$rs1, RegTy:$rs2), (Inst $rs1, $rs2, FRM_DYN)>;
 multiclass PatFprFprDynFrm_m<SDPatternOperator OpNode, RVInstRFrm Inst,
-                             list<ExtInfo_r> Exts> {
-  foreach Ext = Exts in
-    let Predicates = Ext.Predicates in
-    def Ext.Suffix : PatFprFprDynFrm<OpNode,
-                                     !cast<RVInstRFrm>(Inst#Ext.Suffix),
-                                     Ext.Reg>;
+                             ExtInfo Ext> {
+  let Predicates = Ext.Predicates in
+  def Ext.Suffix : PatFprFprDynFrm<OpNode,
+                                   !cast<RVInstRFrm>(Inst#Ext.Suffix),
+                                   Ext.PrimaryTy>;
 }
 
 /// Float conversion operations
@@ -488,10 +472,12 @@ multiclass PatFprFprDynFrm_m<SDPatternOperator OpNode, RVInstRFrm Inst,
 // are defined later.
 
 /// Float arithmetic operations
-defm : PatFprFprDynFrm_m<any_fadd, FADD_S, FINX>;
-defm : PatFprFprDynFrm_m<any_fsub, FSUB_S, FINX>;
-defm : PatFprFprDynFrm_m<any_fmul, FMUL_S, FINX>;
-defm : PatFprFprDynFrm_m<any_fdiv, FDIV_S, FINX>;
+foreach Ext = FExts in {
+  defm : PatFprFprDynFrm_m<any_fadd, FADD_S, Ext>;
+  defm : PatFprFprDynFrm_m<any_fsub, FSUB_S, Ext>;
+  defm : PatFprFprDynFrm_m<any_fmul, FMUL_S, Ext>;
+  defm : PatFprFprDynFrm_m<any_fdiv, FDIV_S, Ext>;
+}
 
 let Predicates = [HasStdExtF] in {
 def : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, FRM_DYN)>;
@@ -511,7 +497,8 @@ def : Pat<(fabs FPR32INX:$rs1), (FSGNJX_S_INX $rs1, $rs1)>;
 def : Pat<(riscv_fpclass FPR32INX:$rs1), (FCLASS_S_INX $rs1)>;
 } // Predicates = [HasStdExtZfinx]
 
-defm : PatFprFpr_m<fcopysign, FSGNJ_S, FINX>;
+foreach Ext = FExts in
+defm : PatFprFpr_m<fcopysign, FSGNJ_S, Ext>;
 
 let Predicates = [HasStdExtF] in {
 def : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>;
@@ -564,20 +551,24 @@ def : Pat<(fneg (any_fma_nsz FPR32INX:$rs1, FPR32INX:$rs2, FPR32INX:$rs3)),
 // The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
 // LLVM's fminnum and fmaxnum
 // <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
-defm : PatFprFpr_m<fminnum, FMIN_S, FINX>;
-defm : PatFprFpr_m<fmaxnum, FMAX_S, FINX>;
+foreach Ext = FExts in {
+  defm : PatFprFpr_m<fminnum, FMIN_S, Ext>;
+  defm : PatFprFpr_m<fmaxnum, FMAX_S, Ext>;
+}
 
 /// Setcc
 // FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
 // strict versions of those.
 
 // Match non-signaling FEQ_S
-defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_S,            FINX>;
-defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_S,            FINX>;
-defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_S, FINX>;
-defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_S, FINX>;
-defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_S, FINX>;
-defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_S, FINX>;
+foreach Ext = FExts in {
+  defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_S,            Ext>;
+  defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_S,            Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_S, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_S, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_S, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_S, Ext>;
+}
 
 let Predicates = [HasStdExtF] in {
 // Match signaling FEQ_S
@@ -609,10 +600,12 @@ def : Pat<(strict_fsetccs FPR32INX:$rs1, FPR32INX:$rs1, SETOEQ),
           (FLE_S_INX $rs1, $rs1)>;
 } // Predicates = [HasStdExtZfinx]
 
-defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_S, FINX>;
-defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_S, FINX>;
-defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_S, FINX>;
-defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_S, FINX>;
+foreach Ext = FExts in {
+  defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_S, Ext>;
+  defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_S, Ext>;
+  defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_S, Ext>;
+  defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_S, Ext>;
+}
 
 let Predicates = [HasStdExtF] in {
 defm Select_FPR32 : SelectCC_GPR_rrirr<FPR32>;

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
index a21fc148d9bd9..5d02043c8c19d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
@@ -38,45 +38,38 @@ def FPR16INX : RegisterOperand<GPRF16> {
   let DecoderMethod = "DecodeGPRRegisterClass";
 }
 
-def ZfhExt             : ExtInfo<0, [HasStdExtZfh]>;
-def ZfhminExt          : ExtInfo<0, [HasStdExtZfhOrZfhmin]>;
-def ZhinxExt           : ExtInfo<1, [HasStdExtZhinx]>;
-def ZhinxminExt        : ExtInfo<1, [HasStdExtZhinxOrZhinxmin]>;
-
-def ZfhminDExt         : ExtInfo<0, [HasStdExtZfhOrZfhmin,     HasStdExtD]>;
-def ZhinxminZdinxExt   : ExtInfo<1, [HasStdExtZhinxOrZhinxmin, HasStdExtZdinx, IsRV64]>;
-def ZhinxminZdinx32Ext : ExtInfo<2, [HasStdExtZhinxOrZhinxmin, HasStdExtZdinx, IsRV32]>;
-
-def H     : ExtInfo_r<ZfhExt,     FPR16>;
-def H_INX : ExtInfo_r<ZhinxExt, FPR16INX>;
-
-def HH          : ExtInfo_rr<ZfhExt,             FPR16,      FPR16>;
-def HH_INX      : ExtInfo_rr<ZhinxExt,           FPR16INX,   FPR16INX>;
-def XH          : ExtInfo_rr<ZfhExt,             GPR,        FPR16>;
-def XH_INX      : ExtInfo_rr<ZhinxExt,           GPR,        FPR16INX>;
-def HX          : ExtInfo_rr<ZfhExt,             FPR16,      GPR>;
-def HX_INX      : ExtInfo_rr<ZhinxExt,           FPR16INX,   GPR>;
-def HFmin       : ExtInfo_rr<ZfhminExt,          FPR16,      FPR32>;
-def HF_INXmin   : ExtInfo_rr<ZhinxminExt,        FPR16INX,   FPR32INX>;
-def HF_INX      : ExtInfo_rr<ZhinxExt,           FPR16INX,   FPR32INX>;
-def FHmin       : ExtInfo_rr<ZfhminExt,          FPR32,      FPR16>;
-def FH_INXmin   : ExtInfo_rr<ZhinxminExt,        FPR32INX,   FPR16INX>;
-def FH_INX      : ExtInfo_rr<ZhinxExt,           FPR32INX,   FPR16INX>;
-def DHmin       : ExtInfo_rr<ZfhminDExt,         FPR64,      FPR16>;
-def DH_INXmin   : ExtInfo_rr<ZhinxminZdinxExt,   FPR64INX,   FPR16INX>;
-def DH_INX32min : ExtInfo_rr<ZhinxminZdinx32Ext, FPR64IN32X, FPR16INX>;
-def HDmin       : ExtInfo_rr<ZfhminDExt,         FPR16,      FPR64>;
-def HD_INXmin   : ExtInfo_rr<ZhinxminZdinxExt,   FPR16INX,   FPR64INX>;
-def HD_INX32min : ExtInfo_rr<ZhinxminZdinx32Ext, FPR16INX,   FPR64IN32X>;
-
-defvar HINX     = [H,     H_INX];
-defvar HHINX    = [HH,    HH_INX];
-defvar XHINX    = [XH,    XH_INX];
-defvar HXINX    = [HX,    HX_INX];
-defvar HFINXmin = [HFmin, HF_INXmin];
-defvar FHINXmin = [FHmin, FH_INXmin];
-defvar DHINXmin = [DHmin, DH_INXmin, DH_INX32min];
-defvar HDINXmin = [HDmin, HD_INXmin, HD_INX32min];
+def ZfhExt     : ExtInfo<"", "", [HasStdExtZfh],
+                         FPR16, FPR32, ?, FPR16>;
+def ZfhminExt  : ExtInfo<"", "", [HasStdExtZfhOrZfhmin],
+                         FPR16, FPR32, ?, FPR16>;
+def ZfhDExt    : ExtInfo<"", "", [HasStdExtZfh, HasStdExtD],
+                         ?, FPR32, FPR64, FPR16>;
+def ZfhminDExt : ExtInfo<"", "", [HasStdExtZfhOrZfhmin, HasStdExtD],
+                         ?, FPR32, FPR64, FPR16>;
+
+def ZhinxExt            : ExtInfo<"_INX", "RVZfinx",
+                                  [HasStdExtZhinx],
+                                  FPR16INX, FPR32INX, ?, FPR16INX>;
+def ZhinxminExt         : ExtInfo<"_INX", "RVZfinx",
+                                  [HasStdExtZhinxOrZhinxmin],
+                                  FPR16INX, FPR32INX, ?, FPR16INX>;
+def ZhinxZdinxExt       : ExtInfo<"_INX", "RVZfinx",
+                                  [HasStdExtZhinx, HasStdExtZdinx, IsRV64],
+                                  ?, FPR32INX, FPR64INX, FPR16INX>;
+def ZhinxminZdinxExt    : ExtInfo<"_INX", "RVZfinx",
+                                  [HasStdExtZhinxOrZhinxmin, HasStdExtZdinx, IsRV64],
+                                  ?, FPR32INX, FPR64INX, FPR16INX>;
+def ZhinxZdinx32Ext     : ExtInfo<"_IN32X", "RV32Zdinx",
+                                  [HasStdExtZhinx, HasStdExtZdinx, IsRV32],
+                                  ?, FPR32INX, FPR64IN32X, FPR16INX >;
+def ZhinxminZdinx32Ext  : ExtInfo<"_IN32X", "RV32Zdinx",
+                                  [HasStdExtZhinxOrZhinxmin, HasStdExtZdinx, IsRV32],
+                                  ?, FPR32INX, FPR64IN32X, FPR16INX>;
+
+defvar ZfhExts = [ZfhExt, ZhinxExt];
+defvar ZfhminExts = [ZfhminExt, ZhinxminExt];
+defvar ZfhDExts = [ZfhDExt, ZhinxZdinxExt, ZhinxZdinx32Ext];
+defvar ZfhminDExts = [ZfhminDExt, ZhinxminZdinxExt, ZhinxminZdinx32Ext];
 
 //===----------------------------------------------------------------------===//
 // Instructions
@@ -91,57 +84,68 @@ def FLH : FPLoad_r<0b001, "flh", FPR16, WriteFLD16>;
 def FSH : FPStore_r<0b001, "fsh", FPR16, WriteFST16>;
 } // Predicates = [HasHalfFPLoadStoreMove]
 
-let SchedRW = [WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16] in {
-defm FMADD_H  : FPFMA_rrr_frm_m<OPC_MADD,  0b10, "fmadd.h",  HINX>;
-defm FMSUB_H  : FPFMA_rrr_frm_m<OPC_MSUB,  0b10, "fmsub.h",  HINX>;
-defm FNMSUB_H : FPFMA_rrr_frm_m<OPC_NMSUB, 0b10, "fnmsub.h", HINX>;
-defm FNMADD_H : FPFMA_rrr_frm_m<OPC_NMADD, 0b10, "fnmadd.h", HINX>;
-}
-
-let SchedRW = [WriteFAdd16, ReadFAdd16, ReadFAdd16] in {
-defm FADD_H : FPALU_rr_frm_m<0b0000010, "fadd.h", HINX, /*Commutable*/1>;
-defm FSUB_H : FPALU_rr_frm_m<0b0000110, "fsub.h", HINX>;
-}
-let SchedRW = [WriteFMul16, ReadFMul16, ReadFMul16] in
-defm FMUL_H : FPALU_rr_frm_m<0b0001010, "fmul.h", HINX, /*Commutable*/1>;
-
-let SchedRW = [WriteFDiv16, ReadFDiv16, ReadFDiv16] in
-defm FDIV_H : FPALU_rr_frm_m<0b0001110, "fdiv.h", HINX>;
-
-defm FSQRT_H : FPUnaryOp_r_frm_m<0b0101110, 0b00000, HHINX, "fsqrt.h">,
-               Sched<[WriteFSqrt16, ReadFSqrt16]>;
-
-let SchedRW = [WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16],
-    mayRaiseFPException = 0 in {
-defm FSGNJ_H  : FPALU_rr_m<0b0010010, 0b000, "fsgnj.h",  HINX>;
-defm FSGNJN_H : FPALU_rr_m<0b0010010, 0b001, "fsgnjn.h", HINX>;
-defm FSGNJX_H : FPALU_rr_m<0b0010010, 0b010, "fsgnjx.h", HINX>;
-}
-
-let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in {
-defm FMIN_H   : FPALU_rr_m<0b0010110, 0b000, "fmin.h", HINX, /*Commutable*/1>;
-defm FMAX_H   : FPALU_rr_m<0b0010110, 0b001, "fmax.h", HINX, /*Commutable*/1>;
-}
-
-let IsSignExtendingOpW = 1 in
-defm FCVT_W_H : FPUnaryOp_r_frm_m<0b1100010, 0b00000, XHINX, "fcvt.w.h">,
-                Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
-
-let IsSignExtendingOpW = 1 in
-defm FCVT_WU_H : FPUnaryOp_r_frm_m<0b1100010, 0b00001, XHINX, "fcvt.wu.h">,
-                 Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
-
-defm FCVT_H_W : FPUnaryOp_r_frm_m<0b1101010, 0b00000, HXINX, "fcvt.h.w">,
-                Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
-
-defm FCVT_H_WU : FPUnaryOp_r_frm_m<0b1101010, 0b00001, HXINX, "fcvt.h.wu">,
-                 Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
-
-defm FCVT_H_S : FPUnaryOp_r_frm_m<0b0100010, 0b00000, HFINXmin, "fcvt.h.s">,
-                Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]>;
-
-defm FCVT_S_H : FPUnaryOp_r_m<0b0100000, 0b00010, 0b000, FHINXmin, "fcvt.s.h">,
-               Sched<[WriteFCvtF16ToF32, ReadFCvtF16ToF32]>;
+foreach Ext = ZfhExts in {
+  let SchedRW = [WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16] in {
+    defm FMADD_H  : FPFMA_rrr_frm_m<OPC_MADD,  0b10, "fmadd.h",  Ext>;
+    defm FMSUB_H  : FPFMA_rrr_frm_m<OPC_MSUB,  0b10, "fmsub.h",  Ext>;
+    defm FNMSUB_H : FPFMA_rrr_frm_m<OPC_NMSUB, 0b10, "fnmsub.h", Ext>;
+    defm FNMADD_H : FPFMA_rrr_frm_m<OPC_NMADD, 0b10, "fnmadd.h", Ext>;
+  }
+
+  let SchedRW = [WriteFAdd16, ReadFAdd16, ReadFAdd16] in {
+    defm FADD_H : FPALU_rr_frm_m<0b0000010, "fadd.h", Ext, /*Commutable*/1>;
+    defm FSUB_H : FPALU_rr_frm_m<0b0000110, "fsub.h", Ext>;
+  }
+  let SchedRW = [WriteFMul16, ReadFMul16, ReadFMul16] in
+  defm FMUL_H : FPALU_rr_frm_m<0b0001010, "fmul.h", Ext, /*Commutable*/1>;
+
+  let SchedRW = [WriteFDiv16, ReadFDiv16, ReadFDiv16] in
+  defm FDIV_H : FPALU_rr_frm_m<0b0001110, "fdiv.h", Ext>;
+
+  defm FSQRT_H : FPUnaryOp_r_frm_m<0b0101110, 0b00000, Ext, Ext.PrimaryTy,
+                                   Ext.PrimaryTy, "fsqrt.h">,
+                 Sched<[WriteFSqrt16, ReadFSqrt16]>;
+
+  let SchedRW = [WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16],
+      mayRaiseFPException = 0 in {
+    defm FSGNJ_H  : FPALU_rr_m<0b0010010, 0b000, "fsgnj.h",  Ext>;
+    defm FSGNJN_H : FPALU_rr_m<0b0010010, 0b001, "fsgnjn.h", Ext>;
+    defm FSGNJX_H : FPALU_rr_m<0b0010010, 0b010, "fsgnjx.h", Ext>;
+  }
+
+  let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in {
+    defm FMIN_H   : FPALU_rr_m<0b0010110, 0b000, "fmin.h", Ext, /*Commutable*/1>;
+    defm FMAX_H   : FPALU_rr_m<0b0010110, 0b001, "fmax.h", Ext, /*Commutable*/1>;
+  }
+
+  let IsSignExtendingOpW = 1 in
+  defm FCVT_W_H : FPUnaryOp_r_frm_m<0b1100010, 0b00000, Ext, GPR, Ext.PrimaryTy,
+                                    "fcvt.w.h">,
+                  Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
+
+  let IsSignExtendingOpW = 1 in
+  defm FCVT_WU_H : FPUnaryOp_r_frm_m<0b1100010, 0b00001, Ext, GPR, Ext.PrimaryTy,
+                                     "fcvt.wu.h">,
+                   Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
+
+  defm FCVT_H_W : FPUnaryOp_r_frm_m<0b1101010, 0b00000, Ext, Ext.PrimaryTy, GPR,
+                                    "fcvt.h.w">,
+                  Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
+
+  defm FCVT_H_WU : FPUnaryOp_r_frm_m<0b1101010, 0b00001, Ext, Ext.PrimaryTy, GPR,
+                                     "fcvt.h.wu">,
+                   Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
+} // foreach Ext = ZfhExts
+
+foreach Ext = ZfhminExts in {
+  defm FCVT_H_S : FPUnaryOp_r_frm_m<0b0100010, 0b00000, Ext, Ext.PrimaryTy,
+                                    Ext.F32Ty, "fcvt.h.s">,
+                  Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]>;
+
+  defm FCVT_S_H : FPUnaryOp_r_m<0b0100000, 0b00010, 0b000, Ext, Ext.F32Ty,
+                                Ext.PrimaryTy, "fcvt.s.h">,
+                 Sched<[WriteFCvtF16ToF32, ReadFCvtF16ToF32]>;
+} // foreach Ext = ZfhminExts
 
 let Predicates = [HasHalfFPLoadStoreMove] in {
 let mayRaiseFPException = 0, IsSignExtendingOpW = 1 in
@@ -153,33 +157,44 @@ def FMV_H_X : FPUnaryOp_r<0b1111010, 0b00000, 0b000, FPR16, GPR, "fmv.h.x">,
               Sched<[WriteFMovI16ToF16, ReadFMovI16ToF16]>;
 } // Predicates = [HasHalfFPLoadStoreMove]
 
-let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in {
-defm FEQ_H : FPCmp_rr_m<0b1010010, 0b010, "feq.h", HINX, /*Commutable*/1>;
-defm FLT_H : FPCmp_rr_m<0b1010010, 0b001, "flt.h", HINX>;
-defm FLE_H : FPCmp_rr_m<0b1010010, 0b000, "fle.h", HINX>;
-}
-
-let mayRaiseFPException = 0 in
-defm FCLASS_H : FPUnaryOp_r_m<0b1110010, 0b00000, 0b001, XHINX, "fclass.h">,
-                Sched<[WriteFClass16, ReadFClass16]>;
-
-defm FCVT_L_H  : FPUnaryOp_r_frm_m<0b1100010, 0b00010, XHINX, "fcvt.l.h", [IsRV64]>,
-                 Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
-
-defm FCVT_LU_H  : FPUnaryOp_r_frm_m<0b1100010, 0b00011, XHINX, "fcvt.lu.h", [IsRV64]>,
-                  Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
-
-defm FCVT_H_L : FPUnaryOp_r_frm_m<0b1101010, 0b00010, HXINX, "fcvt.h.l", [IsRV64]>,
-                Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
-
-defm FCVT_H_LU : FPUnaryOp_r_frm_m<0b1101010, 0b00011, HXINX, "fcvt.h.lu", [IsRV64]>,
-                 Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
-
-defm FCVT_H_D : FPUnaryOp_r_frm_m<0b0100010, 0b00001, HDINXmin, "fcvt.h.d">,
-                Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]>;
-
-defm FCVT_D_H : FPUnaryOp_r_m<0b0100001, 0b00010, 0b000, DHINXmin, "fcvt.d.h">,
-                Sched<[WriteFCvtF16ToF64, ReadFCvtF16ToF64]>;
+foreach Ext = ZfhExts in {
+  let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in {
+    defm FEQ_H : FPCmp_rr_m<0b1010010, 0b010, "feq.h", Ext, /*Commutable*/1>;
+    defm FLT_H : FPCmp_rr_m<0b1010010, 0b001, "flt.h", Ext>;
+    defm FLE_H : FPCmp_rr_m<0b1010010, 0b000, "fle.h", Ext>;
+  }
+
+  let mayRaiseFPException = 0 in
+  defm FCLASS_H : FPUnaryOp_r_m<0b1110010, 0b00000, 0b001, Ext, GPR, Ext.PrimaryTy,
+                                "fclass.h">,
+                  Sched<[WriteFClass16, ReadFClass16]>;
+
+  defm FCVT_L_H  : FPUnaryOp_r_frm_m<0b1100010, 0b00010, Ext, GPR, Ext.PrimaryTy,
+                                     "fcvt.l.h", [IsRV64]>,
+                   Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
+
+  defm FCVT_LU_H  : FPUnaryOp_r_frm_m<0b1100010, 0b00011, Ext, GPR, Ext.PrimaryTy,
+                                      "fcvt.lu.h", [IsRV64]>,
+                    Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
+
+  defm FCVT_H_L : FPUnaryOp_r_frm_m<0b1101010, 0b00010, Ext, Ext.PrimaryTy, GPR,
+                                    "fcvt.h.l", [IsRV64]>,
+                  Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
+
+  defm FCVT_H_LU : FPUnaryOp_r_frm_m<0b1101010, 0b00011, Ext, Ext.PrimaryTy, GPR,
+                                     "fcvt.h.lu", [IsRV64]>,
+                   Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
+} // foreach Ext = ZfhExts
+
+foreach Ext = ZfhminDExts in {
+  defm FCVT_H_D : FPUnaryOp_r_frm_m<0b0100010, 0b00001, Ext, Ext.F16Ty,
+                                   Ext.F64Ty, "fcvt.h.d">,
+                  Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]>;
+
+  defm FCVT_D_H : FPUnaryOp_r_m<0b0100001, 0b00010, 0b000, Ext, Ext.F64Ty,
+                                Ext.F16Ty, "fcvt.d.h">,
+                  Sched<[WriteFCvtF16ToF64, ReadFCvtF16ToF64]>;
+} // foreach Ext = ZfhminDExts
 
 //===----------------------------------------------------------------------===//
 // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
@@ -330,20 +345,24 @@ def : Pat<(fneg (any_fma_nsz FPR16INX:$rs1, FPR16INX:$rs2, FPR16INX:$rs3)),
 // The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
 // LLVM's fminnum and fmaxnum
 // <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
-defm : PatFprFpr_m<fminnum, FMIN_H, HINX>;
-defm : PatFprFpr_m<fmaxnum, FMAX_H, HINX>;
+foreach Ext = ZfhExts in {
+  defm : PatFprFpr_m<fminnum, FMIN_H, Ext>;
+  defm : PatFprFpr_m<fmaxnum, FMAX_H, Ext>;
+}
 
 /// Setcc
 // FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
 // strict versions of those.
 
 // Match non-signaling FEQ_D
-defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_H,            HINX>;
-defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_H,            HINX>;
-defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_H, HINX>;
-defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_H, HINX>;
-defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_H, HINX>;
-defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_H, HINX>;
+foreach Ext = ZfhExts in {
+  defm : PatSetCC_m<any_fsetcc,    SETEQ,  FEQ_H,            Ext>;
+  defm : PatSetCC_m<any_fsetcc,    SETOEQ, FEQ_H,            Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETLT,  PseudoQuietFLT_H, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_H, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETLE,  PseudoQuietFLE_H, Ext>;
+  defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_H, Ext>;
+}
 
 let Predicates = [HasStdExtZfh] in {
 // Match signaling FEQ_H
@@ -375,10 +394,12 @@ def : Pat<(strict_fsetccs FPR16INX:$rs1, FPR16INX:$rs1, SETOEQ),
           (FLE_H_INX $rs1, $rs1)>;
 } // Predicates = [HasStdExtZhinx]
 
-defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_H, HINX>;
-defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_H, HINX>;
-defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_H, HINX>;
-defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_H, HINX>;
+foreach Ext = ZfhExts in {
+  defm : PatSetCC_m<any_fsetccs, SETLT,  FLT_H, Ext>;
+  defm : PatSetCC_m<any_fsetccs, SETOLT, FLT_H, Ext>;
+  defm : PatSetCC_m<any_fsetccs, SETLE,  FLE_H, Ext>;
+  defm : PatSetCC_m<any_fsetccs, SETOLE, FLE_H, Ext>;
+}
 
 let Predicates = [HasStdExtZfh] in {
 defm Select_FPR16 : SelectCC_GPR_rrirr<FPR16>;


        


More information about the llvm-commits mailing list