[llvm] [RISCV] Refactor the MC layer SiFive VCIX classes. (PR #180433)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 8 19:11:25 PST 2026


================
@@ -49,124 +72,141 @@ def tsimm5 : RISCVOp, TImmLeaf<XLenVT, [{return isInt<5>(Imm);}]> {
   let OperandType = "OPERAND_SIMM5";
 }
 
-class SwapVCIXIns<dag funct6, dag rd, dag rs2, dag rs1, bit swap> {
-  dag Ins = !con(funct6, !if(swap, rs2, rd), !if(swap, rd, rs2), rs1);
+class VCIXInfo<VCIXType type, VCIXRs1Info rs1info, bit HaveOutputDst> {
+  bit HasOutput = HaveOutputDst;
+  VCIXRs1Info Rs1 = rs1info;
+  defvar suffix = rs1info.Prefix # type.Suffix;
+
+  string OpcodeStr = !if(HaveOutputDst, "sf.vc.v." # suffix,
+                                        "sf.vc." # suffix);
+  bits<4> Funct6_hi4 = type.Val;
+  bits<3> Funct3 = rs1info.Funct3;
+
+  // TyRd is VR when there's an output or vd is a source operand, otherwise uimm5
+  defvar TyRd = !if(!or(HaveOutputDst, type.VdIsSource), VR, uimm5);
+
+  // TyRs2 is uimm5 when vs2 is an immediate, otherwise VR
+  defvar TyRs2 = !if(type.Vs2IsImmediate, uimm5, VR);
+
+  dag Outs = !cond(!not(HaveOutputDst): (outs),
+                   type.VdIsSource:     (outs TyRd:$vd_wb),
+                   true:                (outs TyRd:$vd));
+
+  // Vd operand: omitted from ins when HaveOutputDst and not a source operand
+  defvar VdOp = !if(!and(HaveOutputDst, !not(type.VdIsSource)),
+                    (ins), (ins TyRd:$vd));
+
+  // Vs2 operand
+  defvar Vs2Op = (ins TyRs2:$vs2);
+
+  // Build Ins DAG: swap vd and vs2 order when vs2 is an immediate
+  dag Ins = !if(type.Vs2IsImmediate,
+                !con(rs1info.Funct6Op, Vs2Op, VdOp, rs1info.Op),
+                !con(rs1info.Funct6Op, VdOp, Vs2Op, rs1info.Op));
+
+  string ArgStr = !if(type.Vs2IsImmediate,
+                      rs1info.Funct6Name # ", $vs2, $vd, " # rs1info.Name,
+                      rs1info.Funct6Name # ", $vd, $vs2, " # rs1info.Name);
+
+  string Constraints = !if(!and(HaveOutputDst, type.VdIsSource),
+                           "$vd = $vd_wb", "");
+
+  RISCVVConstraint RVVConstraint = !if(!and(HaveOutputDst, type.IsWidening),
+                                       !if(rs1info.IsVR, VCIXVS2VS1, VCIXVS2),
+                                       NoConstraint);
 }
 
-class RVInstVCCustom2<bits<4> funct6_hi4, bits<3> funct3, dag outs, dag ins,
-                      string opcodestr, string argstr>
-    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
-  bits<5> rs2;
-  bits<5> rs1;
-  bits<5> rd;
-  bits<2> funct6_lo2;
-  bit vm;
+// Common base class for VCIX instructions
+class RVInstVCCustom2Base<VCIXInfo info>
+    : RVInst<info.Outs, info.Ins, info.OpcodeStr, info.ArgStr, [], InstFormatR> {
+  bits<5> vs2;
+  bits<5> vd;
 
-  let Inst{31-28} = funct6_hi4;
-  let Inst{27-26} = funct6_lo2;
-  let Inst{25} = vm;
-  let Inst{24-20} = rs2;
-  let Inst{19-15} = rs1;
-  let Inst{14-12} = funct3;
-  let Inst{11-7} = rd;
+  let Inst{31-28} = info.Funct6_hi4;
+  let Inst{25} = !not(info.HasOutput);
+  let Inst{24-20} = vs2;
+  let Inst{14-12} = info.Funct3;
+  let Inst{11-7} = vd;
   let Inst{6-0} = OPC_CUSTOM_2.Value;
 
   let Uses = [VL, VTYPE];
-  let RVVConstraint = NoConstraint;
+  let Constraints = info.Constraints;
+  let RVVConstraint = info.RVVConstraint;
   let ElementsDependOn = EltDepsVLMask;
   let ReadsPastVL = 1;
 }
 
-class RVInstVCFCustom2<bits<4> funct6_hi4, bits<3> funct3, dag outs, dag ins,
-                       string opcodestr, string argstr>
-    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
-  bits<5> rs2;
+// VCIX instructions with GPR rs1 operand
+class RVInstVCCustom2_X<VCIXInfo info> : RVInstVCCustom2Base<info> {
   bits<5> rs1;
-  bits<5> rd;
-  bit funct6_lo1;
-  bit vm;
+  bits<2> funct6_lo2;
 
-  let Inst{31-28} = funct6_hi4;
-  let Inst{27} = 1;
-  let Inst{26} = funct6_lo1;
-  let Inst{25} = vm;
-  let Inst{24-20} = rs2;
+  let Inst{27-26} = funct6_lo2;
   let Inst{19-15} = rs1;
-  let Inst{14-12} = funct3;
-  let Inst{11-7} = rd;
-  let Inst{6-0} = OPC_CUSTOM_2.Value;
+}
 
-  let Uses = [VL, VTYPE];
-  let RVVConstraint = NoConstraint;
-  let ElementsDependOn = EltDepsVLMask;
-  let ReadsPastVL = 1;
+// VCIX instructions with VR vs1 operand
+class RVInstVCCustom2_V<VCIXInfo info> : RVInstVCCustom2Base<info> {
+  bits<5> vs1;
+  bits<2> funct6_lo2;
+
+  let Inst{27-26} = funct6_lo2;
+  let Inst{19-15} = vs1;
 }
 
-class VCIXInfo<string suffix, VCIXType type, DAGOperand TyRd,
-               DAGOperand TyRs2, DAGOperand TyRs1, bit HaveOutputDst> {
-  string OpcodeStr = !if(HaveOutputDst, "sf.vc.v." # suffix,
-                                        "sf.vc." # suffix);
-  bits<4> Funct6_hi4 = type.Val;
-  bits<3> Funct3 = !cond(!eq(TyRs1, VR):    0b000,
-                         !eq(TyRs1, GPR):   0b100,
-                         !eq(TyRs1, FPR32): 0b101,
-                         !eq(TyRs1, simm5): 0b011);
-  dag Outs = !if(!not(HaveOutputDst), (outs),
-                 !if(!or(!eq(type, VCIX_XVV), !eq(type, VCIX_XVW)),
-                     (outs TyRd:$rd_wb), (outs TyRd:$rd)));
-  dag Ins = SwapVCIXIns<!if(!ne(TyRs1, FPR32), (ins uimm2:$funct6_lo2),
-                                               (ins uimm1:$funct6_lo1)),
-                        !if(!and(HaveOutputDst, !or(!eq(type, VCIX_X),
-                                                    !eq(type, VCIX_XV))),
-                            (ins), (ins TyRd:$rd)),
-                        (ins TyRs2:$rs2),
-                        (ins TyRs1:$rs1),
-                        !if(!eq(type, VCIX_X), 1, 0)>.Ins;
-  string Prototype = !if(!eq(type, VCIX_X), "$funct6_lo2, $rs2, $rd, $rs1",
-                         !if(!ne(TyRs1, FPR32), "$funct6_lo2, $rd, $rs2, $rs1",
-                                                "$funct6_lo1, $rd, $rs2, $rs1"));
-  string Constraints = !if(!not(HaveOutputDst), "",
-                           !if(!or(!eq(type, VCIX_XVV),
-                                   !eq(type, VCIX_XVW)), "$rd = $rd_wb", ""));
-  RISCVVConstraint RVVConstraint = !if(!or(!not(HaveOutputDst),
-                                           !ne(type, VCIX_XVW)), NoConstraint,
-                                       !if(!eq(TyRs1, VR), VCIXVS2VS1, VCIXVS2));
-}
-
-class CustomSiFiveVCIX<VCIXInfo info>
-  : RVInstVCCustom2<info.Funct6_hi4, info.Funct3, info.Outs,
-                    info.Ins, info.OpcodeStr, info.Prototype> {
-  let Constraints = info.Constraints;
-  let RVVConstraint = info.RVVConstraint;
+// VCIX instructions with immediate operand
+class RVInstVCCustom2_I<VCIXInfo info> : RVInstVCCustom2Base<info> {
+  bits<5> imm;
+  bits<2> funct6_lo2;
+
+  let Inst{27-26} = funct6_lo2;
+  let Inst{19-15} = imm;
 }
 
-class CustomSiFiveVCIF<VCIXInfo info>
-  : RVInstVCFCustom2<info.Funct6_hi4, info.Funct3, info.Outs,
-                     info.Ins, info.OpcodeStr, info.Prototype> {
-  let Constraints = info.Constraints;
-  let RVVConstraint = info.RVVConstraint;
+// VCIX instructions with FPR rs1 operand
+class RVInstVCFCustom2_F<VCIXInfo info> : RVInstVCCustom2Base<info> {
+  bits<5> rs1;
+  bit funct6_lo1;
+
+  let Inst{27} = 1;
+  let Inst{26} = funct6_lo1;
+  let Inst{19-15} = rs1;
 }
 
-multiclass CustomSiFiveVCIXorVCIF<string suffix, VCIXType type,
-                                  DAGOperand TyRd, DAGOperand TyRs2,
-                                  DAGOperand TyRs1, bit HaveOutputDst> {
-  defvar info = VCIXInfo<suffix, type, TyRd, TyRs2, TyRs1, HaveOutputDst>;
+multiclass CustomSiFiveVCIXorVCIF<VCIXInfo info> {
+  defvar TyRs1 = info.Rs1.Ty;
   if !eq(TyRs1, FPR32) then {
-    def NAME : CustomSiFiveVCIF<info>;
+    def NAME : RVInstVCFCustom2_F<info>;
+  } else if !eq(TyRs1, GPR) then {
+    def NAME : RVInstVCCustom2_X<info>;
+  } else if !eq(TyRs1, VR) then {
+    def NAME : RVInstVCCustom2_V<info>;
   } else {
-    def NAME : CustomSiFiveVCIX<info>;
+    def NAME : RVInstVCCustom2_I<info>;
   }
 }
 
-multiclass CustomSiFiveVCIX<string suffix, VCIXType type,
-                            DAGOperand InTyRd, DAGOperand InTyRs2,
-                            DAGOperand InTyRs1> {
-  let vm = 1 in
-  defm SF_VC_ # NAME   : CustomSiFiveVCIXorVCIF<suffix, type, InTyRd, InTyRs2,
-                                             InTyRs1, 0>;
-  let vm = 0 in
-  defm SF_VC_V_ # NAME : CustomSiFiveVCIXorVCIF<suffix, type, VR, InTyRs2,
-                                             InTyRs1, 1>;
+multiclass CustomSiFiveVCIX<VCIXType type, VCIXRs1Info rs1> {
+  defm SF_VC_ # NAME   : CustomSiFiveVCIXorVCIF<VCIXInfo<type, rs1, HaveOutputDst=0>>;
+  defm SF_VC_V_ # NAME : CustomSiFiveVCIXorVCIF<VCIXInfo<type, rs1, HaveOutputDst=1>>;
+}
+
+let Predicates = [HasVendorXSfvcp], mayLoad = 0, mayStore = 0,
+    hasSideEffects = 1, hasNoSchedulingInfo = 1, DecoderNamespace = "XSfvector" in {
+  defm X   : CustomSiFiveVCIX<VCIX_X,   VCIX_GPR>,   Sched<[]>;
----------------
topperc wrote:

Yeah. I agree that's confusing. I'll fix it.

https://github.com/llvm/llvm-project/pull/180433


More information about the llvm-commits mailing list