1//===-- RISCVInstrInfoXsf.td - SiFive custom instructions --*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the vendor extensions defined by SiFive.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// XSFVCP extension instructions.
15//===----------------------------------------------------------------------===//
16
17def VCIXVS2    : RISCVVConstraint<VS2Constraint.Value>;
18def VCIXVS2VS1 : RISCVVConstraint<!or(VS2Constraint.Value,
19                                      VS1Constraint.Value)>;
20
21class VCIXType<bits<4> val> {
22  bits<4> Val = val;
23}
24
25def VCIX_X   : VCIXType<0b0000>;
26def VCIX_XV  : VCIXType<0b0010>;
27def VCIX_XVV : VCIXType<0b1010>;
28def VCIX_XVW : VCIXType<0b1111>;
29
30// The payload and tsimm5 operands are all marked as ImmArg in the IR
31// intrinsic and will be target constant, so use TImmLeaf rather than ImmLeaf.
32class PayloadOp<int bitsNum> : RISCVOp, TImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);"> {
33  let ParserMatchClass = UImmAsmOperand<bitsNum>;
34  let DecoderMethod = "decodeUImmOperand<"# bitsNum # ">";
35  let OperandType = "OPERAND_UIMM" # bitsNum;
36}
37
38def payload1 : PayloadOp<1>;
39def payload2 : PayloadOp<2>;
40def payload5 : PayloadOp<5>;
41
42def tsimm5 : Operand<XLenVT>, TImmLeaf<XLenVT, [{return isInt<5>(Imm);}]> {
43  let ParserMatchClass = SImmAsmOperand<5>;
44  let EncoderMethod = "getImmOpValue";
45  let DecoderMethod = "decodeSImmOperand<5>";
46  let MCOperandPredicate = [{
47    int64_t Imm;
48    if (MCOp.evaluateAsConstantImm(Imm))
49      return isInt<5>(Imm);
50    return MCOp.isBareSymbolRef();
51  }];
52}
53
54class SwapVCIXIns<dag funct6, dag rd, dag rs2, dag rs1, bit swap> {
55  dag Ins = !con(funct6, !if(swap, rs2, rd), !if(swap, rd, rs2), rs1);
56}
57
58class RVInstVCCustom2<bits<4> funct6_hi4, bits<3> funct3, dag outs, dag ins,
59                      string opcodestr, string argstr>
60    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
61  bits<5> rs2;
62  bits<5> rs1;
63  bits<5> rd;
64  bits<2> funct6_lo2;
65  bit vm;
66
67  let Inst{31-28} = funct6_hi4;
68  let Inst{27-26} = funct6_lo2;
69  let Inst{25} = vm;
70  let Inst{24-20} = rs2;
71  let Inst{19-15} = rs1;
72  let Inst{14-12} = funct3;
73  let Inst{11-7} = rd;
74  let Inst{6-0} = OPC_CUSTOM_2.Value;
75
76  let Uses = [VTYPE, VL];
77  let RVVConstraint = NoConstraint;
78}
79
80class RVInstVCFCustom2<bits<4> funct6_hi4, bits<3> funct3, dag outs, dag ins,
81                       string opcodestr, string argstr>
82    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
83  bits<5> rs2;
84  bits<5> rs1;
85  bits<5> rd;
86  bit funct6_lo1;
87  bit vm;
88
89  let Inst{31-28} = funct6_hi4;
90  let Inst{27} = 1;
91  let Inst{26} = funct6_lo1;
92  let Inst{25} = vm;
93  let Inst{24-20} = rs2;
94  let Inst{19-15} = rs1;
95  let Inst{14-12} = funct3;
96  let Inst{11-7} = rd;
97  let Inst{6-0} = OPC_CUSTOM_2.Value;
98
99  let Uses = [VTYPE, VL];
100  let RVVConstraint = NoConstraint;
101}
102
103class VCIXInfo<string suffix, VCIXType type, DAGOperand TyRd,
104               DAGOperand TyRs2, DAGOperand TyRs1, bit HaveOutputDst> {
105  string OpcodeStr = !if(HaveOutputDst, "sf.vc.v." # suffix,
106                                        "sf.vc." # suffix);
107  bits<4> Funct6_hi4 = type.Val;
108  bits<3> Funct3 = !cond(!eq(TyRs1, VR):    0b000,
109                         !eq(TyRs1, GPR):   0b100,
110                         !eq(TyRs1, FPR32): 0b101,
111                         !eq(TyRs1, simm5): 0b011);
112  dag Outs = !if(!not(HaveOutputDst), (outs),
113                 !if(!or(!eq(type, VCIX_XVV), !eq(type, VCIX_XVW)),
114                     (outs TyRd:$rd_wb), (outs TyRd:$rd)));
115  dag Ins = SwapVCIXIns<!if(!ne(TyRs1, FPR32), (ins uimm2:$funct6_lo2),
116                                               (ins uimm1:$funct6_lo1)),
117                        !if(!and(HaveOutputDst, !or(!eq(type, VCIX_X),
118                                                    !eq(type, VCIX_XV))),
119                            (ins), (ins TyRd:$rd)),
120                        (ins TyRs2:$rs2),
121                        (ins TyRs1:$rs1),
122                        !if(!eq(type, VCIX_X), 1, 0)>.Ins;
123  string Prototype = !if(!eq(type, VCIX_X), "$funct6_lo2, $rs2, $rd, $rs1",
124                         !if(!ne(TyRs1, FPR32), "$funct6_lo2, $rd, $rs2, $rs1",
125                                                "$funct6_lo1, $rd, $rs2, $rs1"));
126  string Constraints = !if(!not(HaveOutputDst), "",
127                           !if(!or(!eq(type, VCIX_XVV),
128                                   !eq(type, VCIX_XVW)), "$rd = $rd_wb", ""));
129  RISCVVConstraint RVVConstraint = !if(!or(!not(HaveOutputDst),
130                                           !ne(type, VCIX_XVW)), NoConstraint,
131                                       !if(!eq(TyRs1, VR), VCIXVS2VS1, VCIXVS2));
132}
133
134class CustomSiFiveVCIX<VCIXInfo info>
135  : RVInstVCCustom2<info.Funct6_hi4, info.Funct3, info.Outs,
136                    info.Ins, info.OpcodeStr, info.Prototype> {
137  let Constraints = info.Constraints;
138  let RVVConstraint = info.RVVConstraint;
139}
140
141class CustomSiFiveVCIF<VCIXInfo info>
142  : RVInstVCFCustom2<info.Funct6_hi4, info.Funct3, info.Outs,
143                     info.Ins, info.OpcodeStr, info.Prototype> {
144  let Constraints = info.Constraints;
145  let RVVConstraint = info.RVVConstraint;
146}
147
148multiclass CustomSiFiveVCIXorVCIF<string suffix, VCIXType type,
149                                  DAGOperand TyRd, DAGOperand TyRs2,
150                                  DAGOperand TyRs1, bit HaveOutputDst> {
151  defvar info = VCIXInfo<suffix, type, TyRd, TyRs2, TyRs1, HaveOutputDst>;
152  if !eq(TyRs1, FPR32) then {
153    def NAME : CustomSiFiveVCIF<info>;
154  } else {
155    def NAME : CustomSiFiveVCIX<info>;
156  }
157}
158
159multiclass CustomSiFiveVCIX<string suffix, VCIXType type,
160                            DAGOperand InTyRd, DAGOperand InTyRs2,
161                            DAGOperand InTyRs1> {
162  let vm = 1 in
163  defm VC_ # NAME   : CustomSiFiveVCIXorVCIF<suffix, type, InTyRd, InTyRs2,
164                                             InTyRs1, 0>;
165  let vm = 0 in
166  defm VC_V_ # NAME : CustomSiFiveVCIXorVCIF<suffix, type, VR, InTyRs2,
167                                             InTyRs1, 1>;
168}
169
170let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
171class CustomSiFiveVMACC<bits<6> funct6, RISCVVFormat opv, string opcodestr>
172    : RVInstVCCustom2<funct6{5-2}, opv.Value, (outs VR:$rd), (ins VR:$rs1, VR:$rs2),
173                      opcodestr, "$rd, $rs1, $rs2"> {
174  let vm = 1;
175  let funct6_lo2 = funct6{1-0};
176}
177}
178
179class CustomSiFiveVFNRCLIP<bits<6> funct6, RISCVVFormat opv, string opcodestr>
180    : VALUVF<funct6, opv, opcodestr> {
181  let Inst{6-0} = OPC_CUSTOM_2.Value;
182}
183
184let Predicates = [HasVendorXSfvcp], mayLoad = 0, mayStore = 0,
185    hasSideEffects = 1, hasNoSchedulingInfo = 1, DecoderNamespace = "XSfvcp" in {
186  defm X   : CustomSiFiveVCIX<"x",   VCIX_X,   uimm5, uimm5, GPR>,   Sched<[]>;
187  defm I   : CustomSiFiveVCIX<"i",   VCIX_X,   uimm5, uimm5, simm5>, Sched<[]>;
188  defm XV  : CustomSiFiveVCIX<"xv",  VCIX_XV,  uimm5, VR,    GPR>,   Sched<[]>;
189  defm IV  : CustomSiFiveVCIX<"iv",  VCIX_XV,  uimm5, VR,    simm5>, Sched<[]>;
190  defm VV  : CustomSiFiveVCIX<"vv",  VCIX_XV,  uimm5, VR,    VR>,    Sched<[]>;
191  defm FV  : CustomSiFiveVCIX<"fv",  VCIX_XV,  uimm5, VR,    FPR32>, Sched<[]>;
192  defm XVV : CustomSiFiveVCIX<"xvv", VCIX_XVV, VR,    VR,    GPR>,   Sched<[]>;
193  defm IVV : CustomSiFiveVCIX<"ivv", VCIX_XVV, VR,    VR,    simm5>, Sched<[]>;
194  defm VVV : CustomSiFiveVCIX<"vvv", VCIX_XVV, VR,    VR,    VR>,    Sched<[]>;
195  defm FVV : CustomSiFiveVCIX<"fvv", VCIX_XVV, VR,    VR,    FPR32>, Sched<[]>;
196  defm XVW : CustomSiFiveVCIX<"xvw", VCIX_XVW, VR,    VR,    GPR>,   Sched<[]>;
197  defm IVW : CustomSiFiveVCIX<"ivw", VCIX_XVW, VR,    VR,    simm5>, Sched<[]>;
198  defm VVW : CustomSiFiveVCIX<"vvw", VCIX_XVW, VR,    VR,    VR>,    Sched<[]>;
199  defm FVW : CustomSiFiveVCIX<"fvw", VCIX_XVW, VR,    VR,    FPR32>, Sched<[]>;
200}
201
202let Predicates = [HasVendorXSfvqmaccdod], DecoderNamespace = "XSfvqmaccdod" in {
203  def VQMACCU_2x8x2  : CustomSiFiveVMACC<0b101100, OPMVV, "sf.vqmaccu.2x8x2">;
204  def VQMACC_2x8x2   : CustomSiFiveVMACC<0b101101, OPMVV, "sf.vqmacc.2x8x2">;
205  def VQMACCUS_2x8x2 : CustomSiFiveVMACC<0b101110, OPMVV, "sf.vqmaccus.2x8x2">;
206  def VQMACCSU_2x8x2 : CustomSiFiveVMACC<0b101111, OPMVV, "sf.vqmaccsu.2x8x2">;
207}
208
209let Predicates = [HasVendorXSfvqmaccqoq], DecoderNamespace = "XSfvqmaccqoq" in {
210  def VQMACCU_4x8x4  : CustomSiFiveVMACC<0b111100, OPMVV, "sf.vqmaccu.4x8x4">;
211  def VQMACC_4x8x4   : CustomSiFiveVMACC<0b111101, OPMVV, "sf.vqmacc.4x8x4">;
212  def VQMACCUS_4x8x4 : CustomSiFiveVMACC<0b111110, OPMVV, "sf.vqmaccus.4x8x4">;
213  def VQMACCSU_4x8x4 : CustomSiFiveVMACC<0b111111, OPMVV, "sf.vqmaccsu.4x8x4">;
214}
215
216let Predicates = [HasVendorXSfvfwmaccqqq], DecoderNamespace = "XSfvfwmaccqqq" in {
217  def VFWMACC_4x4x4 : CustomSiFiveVMACC<0b111100, OPFVV, "sf.vfwmacc.4x4x4">;
218}
219
220let Predicates = [HasVendorXSfvfnrclipxfqf], DecoderNamespace = "XSfvfnrclipxfqf" in {
221  def VFNRCLIP_XU_F_QF : CustomSiFiveVFNRCLIP<0b100010, OPFVF, "sf.vfnrclip.xu.f.qf">;
222  def VFNRCLIP_X_F_QF : CustomSiFiveVFNRCLIP<0b100011, OPFVF, "sf.vfnrclip.x.f.qf">;
223}
224class VPseudoVC_X<Operand OpClass, DAGOperand RS1Class,
225                  bit HasSideEffect = 1> :
226      Pseudo<(outs),
227             (ins OpClass:$op1, payload5:$rs2, payload5:$rd, RS1Class:$r1,
228                  AVL:$vl, ixlenimm:$sew), []>,
229      RISCVVPseudo {
230  let mayLoad = 0;
231  let mayStore = 0;
232  let HasVLOp = 1;
233  let HasSEWOp = 1;
234  let hasSideEffects = HasSideEffect;
235  let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
236}
237
238class VPseudoVC_XV<Operand OpClass, VReg RS2Class, DAGOperand RS1Class,
239                   bit HasSideEffect = 1> :
240      Pseudo<(outs),
241             (ins OpClass:$op1, payload5:$rd, RS2Class:$rs2, RS1Class:$r1,
242                  AVL:$vl, ixlenimm:$sew), []>,
243      RISCVVPseudo {
244  let mayLoad = 0;
245  let mayStore = 0;
246  let HasVLOp = 1;
247  let HasSEWOp = 1;
248  let hasSideEffects = HasSideEffect;
249  let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
250}
251
252class VPseudoVC_XVV<Operand OpClass, VReg RDClass, VReg RS2Class,
253                    DAGOperand RS1Class, bit HasSideEffect = 1> :
254      Pseudo<(outs),
255             (ins OpClass:$op1, RDClass:$rd, RS2Class:$rs2, RS1Class:$r1,
256                  AVL:$vl, ixlenimm:$sew), []>,
257      RISCVVPseudo {
258  let mayLoad = 0;
259  let mayStore = 0;
260  let HasVLOp = 1;
261  let HasSEWOp = 1;
262  let hasSideEffects = HasSideEffect;
263  let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
264}
265
266class VPseudoVC_V_X<Operand OpClass, VReg RDClass, DAGOperand RS1Class,
267                    bit HasSideEffect = 1> :
268      Pseudo<(outs RDClass:$rd),
269             (ins OpClass:$op1, payload5:$rs2, RS1Class:$r1,
270                  AVL:$vl, ixlenimm:$sew), []>,
271      RISCVVPseudo {
272  let mayLoad = 0;
273  let mayStore = 0;
274  let HasVLOp = 1;
275  let HasSEWOp = 1;
276  let hasSideEffects = HasSideEffect;
277  let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
278}
279
280class VPseudoVC_V_XV<Operand OpClass, VReg RDClass, VReg RS2Class,
281                     DAGOperand RS1Class, bit HasSideEffect = 1> :
282      Pseudo<(outs RDClass:$rd),
283             (ins OpClass:$op1, RS2Class:$rs2, RS1Class:$r1,
284                  AVL:$vl, ixlenimm:$sew), []>,
285      RISCVVPseudo {
286  let mayLoad = 0;
287  let mayStore = 0;
288  let HasVLOp = 1;
289  let HasSEWOp = 1;
290  let hasSideEffects = HasSideEffect;
291  let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
292}
293
294class VPseudoVC_V_XVV<Operand OpClass, VReg RDClass, VReg RS2Class,
295                      DAGOperand RS1Class, bit HasSideEffect = 1> :
296      Pseudo<(outs RDClass:$rd),
297             (ins OpClass:$op1, RDClass:$rs3, RS2Class:$rs2, RS1Class:$r1,
298                  AVL:$vl, ixlenimm:$sew), []>,
299      RISCVVPseudo {
300  let mayLoad = 0;
301  let mayStore = 0;
302  let HasVLOp = 1;
303  let HasSEWOp = 1;
304  let hasSideEffects = HasSideEffect;
305  let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
306}
307
308multiclass VPseudoVC_X<LMULInfo m, DAGOperand RS1Class,
309                       Operand OpClass = payload2> {
310  let VLMul = m.value in {
311    def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_X<OpClass, RS1Class>;
312    def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_X<OpClass, m.vrclass, RS1Class>;
313    def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_X<OpClass, m.vrclass, RS1Class, 0>;
314  }
315}
316
317multiclass VPseudoVC_XV<LMULInfo m, DAGOperand RS1Class,
318                        Operand OpClass = payload2> {
319  let VLMul = m.value in {
320    def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_XV<OpClass, m.vrclass, RS1Class>;
321    def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_XV<OpClass, m.vrclass, m.vrclass, RS1Class>;
322    def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_XV<OpClass, m.vrclass, m.vrclass, RS1Class, 0>;
323  }
324}
325
326multiclass VPseudoVC_XVV<LMULInfo m, DAGOperand RS1Class,
327                         Operand OpClass = payload2> {
328  let VLMul = m.value in {
329    def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_XVV<OpClass, m.vrclass, m.vrclass, RS1Class>;
330    def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_XVV<OpClass, m.vrclass, m.vrclass, RS1Class>;
331    def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_XVV<OpClass, m.vrclass, m.vrclass, RS1Class, 0>;
332  }
333}
334
335multiclass VPseudoVC_XVW<LMULInfo m, DAGOperand RS1Class,
336                         Operand OpClass = payload2> {
337  let VLMul = m.value in {
338    def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_XVV<OpClass, m.wvrclass, m.vrclass, RS1Class>;
339    let Constraints = "@earlyclobber $rd, $rd = $rs3" in {
340      def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_XVV<OpClass, m.wvrclass, m.vrclass, RS1Class>;
341      def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_XVV<OpClass, m.wvrclass, m.vrclass, RS1Class, 0>;
342    }
343  }
344}
345
346multiclass VPseudoSiFiveVMACC<string mx, VReg vd_type, VReg vs2_type,
347                              string Constraint = ""> {
348  def "Pseudo" # NAME # "_" # mx
349      : VPseudoTernaryNoMaskWithPolicy<vd_type, V_M1.vrclass, vs2_type, Constraint>;
350}
351
352multiclass VPseudoSiFiveVQMACCDOD<string Constraint = ""> {
353  foreach m = MxListVF8 in
354    let VLMul = m.value in
355    defm NAME : VPseudoSiFiveVMACC<m.MX, m.vrclass, m.vrclass, Constraint>;
356}
357
358multiclass VPseudoSiFiveVQMACCQOQ<string Constraint = ""> {
359  foreach m = [V_MF2, V_M1, V_M2, V_M4] in
360    let VLMul = m.value in
361    defm NAME : VPseudoSiFiveVMACC<m.MX, m.wvrclass, m.vrclass, Constraint>;
362}
363
364multiclass VPseudoSiFiveVFWMACC<string Constraint = ""> {
365  foreach m = MxListVF2 in
366    let VLMul = m.value in
367    defm NAME : VPseudoSiFiveVMACC<m.MX, m.wvrclass, m.vrclass, Constraint>;
368}
369
370multiclass VPseudoSiFiveVFNRCLIP<string Constraint = "@earlyclobber $rd"> {
371  foreach i = 0-4 in
372    let hasSideEffects = 0 in
373      defm "Pseudo" # NAME : VPseudoBinaryRoundingMode<MxListW[i].vrclass,
374                                                       MxListVF4[i].vrclass,
375                                                       FPR32, MxListW[i],
376                                                       Constraint, /*sew*/0,
377                                                       UsesVXRM=0>;
378}
379
380let Predicates = [HasVendorXSfvcp] in {
381  foreach m = MxList in {
382    defm X : VPseudoVC_X<m, GPR>;
383    defm I : VPseudoVC_X<m, tsimm5>;
384    defm XV : VPseudoVC_XV<m, GPR>;
385    defm IV : VPseudoVC_XV<m, tsimm5>;
386    defm VV : VPseudoVC_XV<m, m.vrclass>;
387    defm XVV : VPseudoVC_XVV<m, GPR>;
388    defm IVV : VPseudoVC_XVV<m, tsimm5>;
389    defm VVV : VPseudoVC_XVV<m, m.vrclass>;
390  }
391  foreach f = FPList in {
392    foreach m = f.MxList in {
393    defm f.FX # "V" : VPseudoVC_XV<m, f.fprclass, payload1>;
394    defm f.FX # "VV" : VPseudoVC_XVV<m, f.fprclass, payload1>;
395    }
396  }
397  foreach m = MxListW in {
398    defm XVW : VPseudoVC_XVW<m, GPR>;
399    defm IVW : VPseudoVC_XVW<m, tsimm5>;
400    defm VVW : VPseudoVC_XVW<m, m.vrclass>;
401  }
402  foreach f = FPListW in {
403    foreach m = f.MxList in
404    defm f.FX # "VW" : VPseudoVC_XVW<m, f.fprclass, payload1>;
405  }
406}
407
408let Predicates = [HasVendorXSfvqmaccdod] in {
409  defm VQMACCU_2x8x2  : VPseudoSiFiveVQMACCDOD;
410  defm VQMACC_2x8x2   : VPseudoSiFiveVQMACCDOD;
411  defm VQMACCUS_2x8x2 : VPseudoSiFiveVQMACCDOD;
412  defm VQMACCSU_2x8x2 : VPseudoSiFiveVQMACCDOD;
413}
414
415let Predicates = [HasVendorXSfvqmaccqoq] in {
416  defm VQMACCU_4x8x4  : VPseudoSiFiveVQMACCQOQ;
417  defm VQMACC_4x8x4   : VPseudoSiFiveVQMACCQOQ;
418  defm VQMACCUS_4x8x4 : VPseudoSiFiveVQMACCQOQ;
419  defm VQMACCSU_4x8x4 : VPseudoSiFiveVQMACCQOQ;
420}
421
422let Predicates = [HasVendorXSfvfwmaccqqq] in {
423  defm VFWMACC_4x4x4 : VPseudoSiFiveVFWMACC;
424}
425
426let Predicates = [HasVendorXSfvfnrclipxfqf] in {
427  defm VFNRCLIP_XU_F_QF : VPseudoSiFiveVFNRCLIP;
428  defm VFNRCLIP_X_F_QF : VPseudoSiFiveVFNRCLIP;
429}
430
431class VPatVC_OP4<string intrinsic_name,
432                 string inst,
433                 ValueType op2_type,
434                 ValueType op3_type,
435                 ValueType op4_type,
436                 int sew,
437                 DAGOperand op2_kind,
438                 DAGOperand op3_kind,
439                 DAGOperand op4_kind,
440                 Operand op1_kind = payload2> :
441  Pat<(!cast<Intrinsic>(intrinsic_name)
442       (XLenVT   op1_kind:$op1),
443       (op2_type op2_kind:$op2),
444       (op3_type op3_kind:$op3),
445       (op4_type op4_kind:$op4),
446       VLOpFrag),
447      (!cast<Instruction>(inst)
448       (XLenVT   op1_kind:$op1),
449       (op2_type op2_kind:$op2),
450       (op3_type op3_kind:$op3),
451       (op4_type op4_kind:$op4),
452       GPR:$vl, sew)>;
453
454class VPatVC_V_OP4<string intrinsic_name,
455                   string inst,
456                   ValueType result_type,
457                   ValueType op2_type,
458                   ValueType op3_type,
459                   ValueType op4_type,
460                   int sew,
461                   DAGOperand op2_kind,
462                   DAGOperand op3_kind,
463                   DAGOperand op4_kind,
464                   Operand op1_kind = payload2> :
465  Pat<(result_type (!cast<Intrinsic>(intrinsic_name)
466                    (XLenVT   op1_kind:$op1),
467                    (op2_type op2_kind:$op2),
468                    (op3_type op3_kind:$op3),
469                    (op4_type op4_kind:$op4),
470                    VLOpFrag)),
471                   (!cast<Instruction>(inst)
472                    (XLenVT   op1_kind:$op1),
473                    (op2_type op2_kind:$op2),
474                    (op3_type op3_kind:$op3),
475                    (op4_type op4_kind:$op4),
476                    GPR:$vl, sew)>;
477
478class VPatVC_V_OP3<string intrinsic_name,
479                   string inst,
480                   ValueType result_type,
481                   ValueType op2_type,
482                   ValueType op3_type,
483                   int sew,
484                   DAGOperand op2_kind,
485                   DAGOperand op3_kind,
486                   Operand op1_kind = payload2> :
487  Pat<(result_type (!cast<Intrinsic>(intrinsic_name)
488                    (XLenVT   op1_kind:$op1),
489                    (op2_type op2_kind:$op2),
490                    (op3_type op3_kind:$op3),
491                    VLOpFrag)),
492                   (!cast<Instruction>(inst)
493                    (XLenVT   op1_kind:$op1),
494                    (op2_type op2_kind:$op2),
495                    (op3_type op3_kind:$op3),
496                    GPR:$vl, sew)>;
497
498multiclass VPatVC_X<string intrinsic_suffix, string instruction_suffix,
499                    VTypeInfo vti, ValueType type, DAGOperand kind> {
500  def : VPatVC_OP4<"int_riscv_sf_vc_" # intrinsic_suffix # "_se_e" # vti.SEW # !tolower(vti.LMul.MX),
501                   "PseudoVC_" # instruction_suffix # "_SE_" # vti.LMul.MX,
502                   XLenVT, XLenVT, type, vti.Log2SEW,
503                   payload5, payload5, kind>;
504  def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix # "_se",
505                     "PseudoVC_V_" # instruction_suffix # "_SE_" # vti.LMul.MX,
506                     vti.Vector, XLenVT, type, vti.Log2SEW,
507                     payload5, kind>;
508  def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix,
509                     "PseudoVC_V_" # instruction_suffix # "_" # vti.LMul.MX,
510                     vti.Vector, XLenVT, type, vti.Log2SEW,
511                     payload5, kind>;
512}
513
514multiclass VPatVC_XV<string intrinsic_suffix, string instruction_suffix,
515                     VTypeInfo vti, ValueType type, DAGOperand kind,
516                     Operand op1_kind = payload2> {
517  def : VPatVC_OP4<"int_riscv_sf_vc_" # intrinsic_suffix # "_se",
518                   "PseudoVC_" # instruction_suffix # "_SE_" # vti.LMul.MX,
519                   XLenVT, vti.Vector, type, vti.Log2SEW,
520                   payload5, vti.RegClass, kind, op1_kind>;
521  def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix # "_se",
522                     "PseudoVC_V_" # instruction_suffix # "_SE_" # vti.LMul.MX,
523                     vti.Vector, vti.Vector, type, vti.Log2SEW,
524                     vti.RegClass, kind, op1_kind>;
525  def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix,
526                     "PseudoVC_V_" # instruction_suffix # "_" # vti.LMul.MX,
527                     vti.Vector, vti.Vector, type, vti.Log2SEW,
528                     vti.RegClass, kind, op1_kind>;
529}
530
531multiclass VPatVC_XVV<string intrinsic_suffix, string instruction_suffix,
532                      VTypeInfo wti, VTypeInfo vti, ValueType type, DAGOperand kind,
533                      Operand op1_kind = payload2> {
534  def : VPatVC_OP4<"int_riscv_sf_vc_" # intrinsic_suffix # "_se",
535                   "PseudoVC_" # instruction_suffix # "_SE_" # vti.LMul.MX,
536                   wti.Vector, vti.Vector, type, vti.Log2SEW,
537                   wti.RegClass, vti.RegClass, kind, op1_kind>;
538  def : VPatVC_V_OP4<"int_riscv_sf_vc_v_" # intrinsic_suffix # "_se",
539                     "PseudoVC_V_" # instruction_suffix # "_SE_" # vti.LMul.MX,
540                     wti.Vector, wti.Vector, vti.Vector, type, vti.Log2SEW,
541                     wti.RegClass, vti.RegClass, kind, op1_kind>;
542  def : VPatVC_V_OP4<"int_riscv_sf_vc_v_" # intrinsic_suffix,
543                     "PseudoVC_V_" # instruction_suffix # "_" # vti.LMul.MX,
544                     wti.Vector, wti.Vector, vti.Vector, type, vti.Log2SEW,
545                     wti.RegClass, vti.RegClass, kind, op1_kind>;
546}
547
548class GetFTypeInfo<int Sew> {
549  ValueType Scalar = !cond(!eq(Sew, 16) : f16,
550                           !eq(Sew, 32) : f32,
551                           !eq(Sew, 64) : f64);
552  RegisterClass ScalarRegClass = !cond(!eq(Sew, 16) : FPR16,
553                                       !eq(Sew, 32) : FPR32,
554                                       !eq(Sew, 64) : FPR64);
555
556  string ScalarSuffix = !cond(!eq(Scalar, f16) : "FPR16",
557                              !eq(Scalar, f32) : "FPR32",
558                              !eq(Scalar, f64) : "FPR64");
559}
560
561multiclass VPatVMACC<string intrinsic, string instruction, string kind,
562                     list<VTypeInfoToWide> info_pairs, ValueType vec_m1> {
563  foreach pair = info_pairs in {
564    defvar VdInfo = pair.Wti;
565    defvar Vs2Info = pair.Vti;
566    let Predicates = [HasVInstructions] in
567    def : VPatTernaryNoMaskWithPolicy<"int_riscv_sf_" # intrinsic,
568                                      "Pseudo" # instruction, kind, VdInfo.Vector,
569                                      vec_m1, Vs2Info.Vector,
570                                      Vs2Info.Log2SEW, Vs2Info.LMul,
571                                      VdInfo.RegClass, VR, Vs2Info.RegClass>;
572  }
573}
574
575defset list<VTypeInfoToWide> VQMACCDODInfoPairs = {
576  def : VTypeInfoToWide<VI8M1, VI32M1>;
577  def : VTypeInfoToWide<VI8M2, VI32M2>;
578  def : VTypeInfoToWide<VI8M4, VI32M4>;
579  def : VTypeInfoToWide<VI8M8, VI32M8>;
580}
581
582defset list<VTypeInfoToWide> VQMACCQOQInfoPairs = {
583  def : VTypeInfoToWide<VI8MF2, VI32M1>;
584  def : VTypeInfoToWide<VI8M1, VI32M2>;
585  def : VTypeInfoToWide<VI8M2, VI32M4>;
586  def : VTypeInfoToWide<VI8M4, VI32M8>;
587}
588
589multiclass VPatVQMACCDOD<string intrinsic, string instruction, string kind>
590    : VPatVMACC<intrinsic, instruction, kind, VQMACCDODInfoPairs, vint8m1_t>;
591
592multiclass VPatVQMACCQOQ<string intrinsic, string instruction, string kind>
593    : VPatVMACC<intrinsic, instruction, kind, VQMACCQOQInfoPairs, vint8m1_t>;
594
595multiclass VPatVFWMACC<string intrinsic, string instruction, string kind>
596    : VPatVMACC<intrinsic, instruction, kind, AllWidenableBFloatToFloatVectors,
597                vbfloat16m1_t>;
598
599defset list<VTypeInfoToWide> VFNRCLIPInfoPairs = {
600  def : VTypeInfoToWide<VI8MF8, VF32MF2>;
601  def : VTypeInfoToWide<VI8MF4, VF32M1>;
602  def : VTypeInfoToWide<VI8MF2, VF32M2>;
603  def : VTypeInfoToWide<VI8M1,  VF32M4>;
604  def : VTypeInfoToWide<VI8M2,  VF32M8>;
605}
606
607multiclass VPatVFNRCLIP<string intrinsic, string instruction> {
608  foreach pair = VFNRCLIPInfoPairs in {
609    defvar Vti = pair.Vti;
610    defvar Wti = pair.Wti;
611    defm : VPatBinaryRoundingMode<"int_riscv_sf_" # intrinsic,
612                                  "Pseudo" # instruction # "_" # Vti.LMul.MX,
613                                  Vti.Vector, Wti.Vector, Wti.Scalar, Vti.Mask,
614                                  Vti.Log2SEW, Vti.RegClass,
615                                  Wti.RegClass, Wti.ScalarRegClass>;
616  }
617}
618
619let Predicates = [HasVendorXSfvcp] in {
620  foreach vti = AllIntegerVectors in {
621    defm : VPatVC_X<"x", "X", vti, XLenVT, GPR>;
622    defm : VPatVC_X<"i", "I", vti, XLenVT, tsimm5>;
623    defm : VPatVC_XV<"xv", "XV", vti, XLenVT, GPR>;
624    defm : VPatVC_XV<"iv", "IV", vti, XLenVT, tsimm5>;
625    defm : VPatVC_XV<"vv", "VV", vti, vti.Vector, vti.RegClass>;
626    defm : VPatVC_XVV<"xvv", "XVV", vti, vti, XLenVT, GPR>;
627    defm : VPatVC_XVV<"ivv", "IVV", vti, vti, XLenVT, tsimm5>;
628    defm : VPatVC_XVV<"vvv", "VVV", vti, vti, vti.Vector, vti.RegClass>;
629
630    if !ne(vti.SEW, 8) then {
631      defvar finfo = GetFTypeInfo<vti.SEW>;
632      defm : VPatVC_XV<"fv", finfo.ScalarSuffix # "V", vti, finfo.Scalar,
633                       finfo.ScalarRegClass, payload1>;
634      defm : VPatVC_XVV<"fvv", finfo.ScalarSuffix # "VV", vti, vti, finfo.Scalar,
635                        finfo.ScalarRegClass, payload1>;
636    }
637  }
638  foreach VtiToWti = AllWidenableIntVectors in {
639    defvar vti = VtiToWti.Vti;
640    defvar wti = VtiToWti.Wti;
641    defvar iinfo = GetIntVTypeInfo<vti>.Vti;
642    defm : VPatVC_XVV<"xvw", "XVW", wti, vti, iinfo.Scalar, iinfo.ScalarRegClass>;
643    defm : VPatVC_XVV<"ivw", "IVW", wti, vti, XLenVT, tsimm5>;
644    defm : VPatVC_XVV<"vvw", "VVW", wti, vti, vti.Vector, vti.RegClass>;
645
646    if !ne(vti.SEW, 8) then {
647      defvar finfo = GetFTypeInfo<vti.SEW>;
648      defm : VPatVC_XVV<"fvw", finfo.ScalarSuffix # "VW", wti, vti, finfo.Scalar,
649                        finfo.ScalarRegClass, payload1>;
650    }
651  }
652}
653
654let Predicates = [HasVendorXSfvqmaccdod] in {
655  defm : VPatVQMACCDOD<"vqmaccu_2x8x2", "VQMACCU", "2x8x2">;
656  defm : VPatVQMACCDOD<"vqmacc_2x8x2", "VQMACC", "2x8x2">;
657  defm : VPatVQMACCDOD<"vqmaccus_2x8x2", "VQMACCUS", "2x8x2">;
658  defm : VPatVQMACCDOD<"vqmaccsu_2x8x2", "VQMACCSU", "2x8x2">;
659}
660
661let Predicates = [HasVendorXSfvqmaccqoq] in {
662  defm : VPatVQMACCQOQ<"vqmaccu_4x8x4", "VQMACCU", "4x8x4">;
663  defm : VPatVQMACCQOQ<"vqmacc_4x8x4", "VQMACC", "4x8x4">;
664  defm : VPatVQMACCQOQ<"vqmaccus_4x8x4", "VQMACCUS", "4x8x4">;
665  defm : VPatVQMACCQOQ<"vqmaccsu_4x8x4", "VQMACCSU", "4x8x4">;
666}
667
668let Predicates = [HasVendorXSfvfwmaccqqq] in {
669  defm : VPatVFWMACC<"vfwmacc_4x4x4", "VFWMACC", "4x4x4">;
670}
671
672let Predicates = [HasVendorXSfvfnrclipxfqf] in {
673  defm : VPatVFNRCLIP<"vfnrclip_xu_f_qf", "VFNRCLIP_XU_F_QF">;
674  defm : VPatVFNRCLIP<"vfnrclip_x_f_qf", "VFNRCLIP_X_F_QF">;
675}
676