1//===- IntrinsicsRISCVXsf.td - SiFive intrinsics -----------*- 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 defines all of the SiFive vendor intrinsics for RISC-V.
10//
11//===----------------------------------------------------------------------===//
12
13class VCIXSuffix<string range> {
14  list<string> suffix = !cond(!eq(range, "c"): ["e8mf8", "e8mf4", "e8mf2", "e8m1", "e8m2", "e8m4", "e8m8"],
15                              !eq(range, "s"): ["e16mf4", "e16mf2", "e16m1", "e16m2", "e16m4", "e16m8"],
16                              !eq(range, "i"): ["e32mf2", "e32m1", "e32m2", "e32m4", "e32m8"],
17                              !eq(range, "l"): ["e64m1", "e64m2", "e64m4", "e64m8"]);
18}
19
20let TargetPrefix = "riscv" in {
21  // Output: (vector_out) or ()
22  // Input: (bit<27-26>, bit<24-20>, scalar_in, vl) or
23  //        (bit<27-26>, bit<24-20>, bit<11-7>, scalar_in, vl)
24  class RISCVSFCustomVC_X<bit HasDst, bit HasSE, bit ImmScalar>
25        : Intrinsic<!if(HasDst, [llvm_anyvector_ty], []),
26                    !listconcat(!if(HasDst, [llvm_anyint_ty, LLVMMatchType<1>],
27                                            [llvm_anyint_ty, LLVMMatchType<0>, LLVMMatchType<0>]),
28                                [llvm_any_ty, llvm_anyint_ty]),
29                    !listconcat([IntrNoMem, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>],    // bit<27-26> and bit<24-20>
30                                !if(HasDst, [], [ImmArg<ArgIndex<2>>]),                   // Vd or bit<11-7>
31                                !if(ImmScalar, !if(HasDst, [ImmArg<ArgIndex<2>>],
32                                                           [ImmArg<ArgIndex<3>>]), []),   // ScalarOperand
33                                !if(HasSE, [IntrHasSideEffects], []))>,
34          RISCVVIntrinsic {
35    let ScalarOperand = !cond(ImmScalar: NoScalarOperand,
36                              HasDst: 2,
37                              true: 3);
38    let VLOperand = !if(HasDst, 3, 4);
39  }
40  // Output: (vector_out) or ()
41  // Input: (bit<27-26>, vector_in, vector_in/scalar_in, vl) or
42  //        (bit<27-26>, bit<11-7>, vector_in, vector_in/scalar_in, vl)
43  class RISCVSFCustomVC_XV<bit HasDst, bit HasSE, bit ImmScalar>
44        : Intrinsic<!if(HasDst, [llvm_anyvector_ty], []),
45                    !listconcat(!if(HasDst, [llvm_anyint_ty, llvm_anyvector_ty],
46                                            [llvm_anyint_ty, LLVMMatchType<0>, llvm_anyvector_ty]),
47                                [llvm_any_ty, llvm_anyint_ty]),
48                    !listconcat([IntrNoMem, ImmArg<ArgIndex<0>>],                        // bit<27-26>
49                                !if(HasDst, [], [ImmArg<ArgIndex<1>>]),                  // Vd or bit<11-7>
50                                !if(ImmScalar, !if(HasDst, [ImmArg<ArgIndex<2>>],
51                                                           [ImmArg<ArgIndex<3>>]), []),  // ScalarOperand
52                                !if(HasSE, [IntrHasSideEffects], []))>,
53          RISCVVIntrinsic {
54    let ScalarOperand = !cond(ImmScalar: NoScalarOperand,
55                              HasDst: 2,
56                              true: 3);
57    let VLOperand = !if(HasDst, 3, 4);
58  }
59  // Output: (vector_out) or ()
60  // Input: (bit<27-26>, passthru, vector_in, vector_in/scalar_in, vl) or
61  //        (bit<27-26>, vector_in, vector_in, vector_in/scalar_in, vl)
62  class RISCVSFCustomVC_XVV<bit HasDst, bit HasSE, bit ImmScalar>
63        : Intrinsic<!if(HasDst, [llvm_anyvector_ty], []),
64                    !listconcat(!if(HasDst, [llvm_anyint_ty, llvm_anyvector_ty, llvm_anyvector_ty],
65                                            [llvm_anyint_ty, llvm_anyvector_ty, llvm_anyvector_ty]),
66                                [llvm_any_ty, llvm_anyint_ty]),
67                    !listconcat([IntrNoMem, ImmArg<ArgIndex<0>>],                        // bit<27-26>
68                                !if(ImmScalar, [ImmArg<ArgIndex<3>>], []),               // ScalarOperand
69                                !if(HasSE, [IntrHasSideEffects], []))>,
70          RISCVVIntrinsic {
71    let ScalarOperand = !if(ImmScalar, NoScalarOperand, 3);
72    let VLOperand = 4;
73  }
74  // Output: (wvector_out) or ()
75  // Input: (bit<27-26>, passthru, vector_in, vector_in/scalar_in, vl) or
76  //        (bit<27-26>, wvector_in, vector_in, vector_in/scalar_in, vl)
77  class RISCVSFCustomVC_XVW<bit HasDst, bit HasSE, bit ImmScalar>
78        : Intrinsic<!if(HasDst, [llvm_anyvector_ty], []),
79                    !listconcat(!if(HasDst, [llvm_anyint_ty, llvm_anyvector_ty, llvm_anyvector_ty],
80                                            [llvm_anyint_ty, llvm_anyvector_ty, llvm_anyvector_ty]),
81                                [llvm_any_ty, llvm_anyint_ty]),
82                    !listconcat([IntrNoMem, ImmArg<ArgIndex<0>>],                        // bit<27-26>
83                                !if(ImmScalar, [ImmArg<ArgIndex<3>>], []),               // ScalarOperand
84                                !if(HasSE, [IntrHasSideEffects], []))>,
85          RISCVVIntrinsic {
86    let ScalarOperand = !if(ImmScalar, NoScalarOperand, 3);
87    let VLOperand = 4;
88  }
89
90  multiclass RISCVSFCustomVC_X<list<string> type> {
91    foreach t = type in {
92      defvar ImmScalar = !eq(t, "i");
93      defvar range = ["c", "s", "i", "l"];
94      foreach r = range in {
95        foreach s = VCIXSuffix<r>.suffix in {
96          def "int_riscv_sf_vc_" # t # "_se_" # s : RISCVSFCustomVC_X<HasDst=0, HasSE=1, ImmScalar=ImmScalar>;
97        }
98      }
99      def "int_riscv_sf_vc_v_" # t # "_se" : RISCVSFCustomVC_X<HasDst=1, HasSE=1, ImmScalar=ImmScalar>;
100      def "int_riscv_sf_vc_v_" # t         : RISCVSFCustomVC_X<HasDst=1, HasSE=0, ImmScalar=ImmScalar>;
101    }
102  }
103
104  multiclass RISCVSFCustomVC_XV<list<string> type> {
105    foreach t = type in {
106      defvar ImmScalar = !eq(t, "i");
107      def "int_riscv_sf_vc_" # t # "v_se"   : RISCVSFCustomVC_XV<HasDst=0, HasSE=1, ImmScalar=ImmScalar>;
108      def "int_riscv_sf_vc_v_" # t # "v_se" : RISCVSFCustomVC_XV<HasDst=1, HasSE=1, ImmScalar=ImmScalar>;
109      def "int_riscv_sf_vc_v_" # t # "v"    : RISCVSFCustomVC_XV<HasDst=1, HasSE=0, ImmScalar=ImmScalar>;
110    }
111  }
112
113  multiclass RISCVSFCustomVC_XVV<list<string> type> {
114    foreach t = type in {
115      defvar ImmScalar = !eq(t, "i");
116      def "int_riscv_sf_vc_" # t # "vv_se"   : RISCVSFCustomVC_XVV<HasDst=0, HasSE=1, ImmScalar=ImmScalar>;
117      def "int_riscv_sf_vc_v_" # t # "vv_se" : RISCVSFCustomVC_XVV<HasDst=1, HasSE=1, ImmScalar=ImmScalar>;
118      def "int_riscv_sf_vc_v_" # t # "vv"    : RISCVSFCustomVC_XVV<HasDst=1, HasSE=0, ImmScalar=ImmScalar>;
119    }
120  }
121
122  multiclass RISCVSFCustomVC_XVW<list<string> type> {
123    foreach t = type in {
124      defvar ImmScalar = !eq(t, "i");
125      def "int_riscv_sf_vc_" # t # "vw_se"   : RISCVSFCustomVC_XVW<HasDst=0, HasSE=1, ImmScalar=ImmScalar>;
126      def "int_riscv_sf_vc_v_" # t # "vw_se" : RISCVSFCustomVC_XVW<HasDst=1, HasSE=1, ImmScalar=ImmScalar>;
127      def "int_riscv_sf_vc_v_" # t # "vw"    : RISCVSFCustomVC_XVW<HasDst=1, HasSE=0, ImmScalar=ImmScalar>;
128    }
129  }
130
131  class RISCVSFCustomVMACC
132      : DefaultAttrsIntrinsic< [llvm_anyvector_ty],
133                   [LLVMMatchType<0>, llvm_anyvector_ty, llvm_anyvector_ty,
134                    llvm_anyint_ty, LLVMMatchType<3>],
135                   [ImmArg<ArgIndex<4>>, IntrNoMem] >, RISCVVIntrinsic {
136    let VLOperand = 3;
137  }
138
139  // Input: (passthru, vector_in, scalar_in, frm, vl)
140  class RISCVSFCustomVFNRCLIPUnMasked
141        : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
142                    [LLVMMatchType<0>, llvm_anyfloat_ty, LLVMVectorElementType<1>,
143                     llvm_anyint_ty, LLVMMatchType<2>],
144                    [ImmArg<ArgIndex<3>>, IntrNoMem]>, RISCVVIntrinsic {
145    let VLOperand = 4;
146  }
147
148  // Input: (maskedoff, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
149  class RISCVSFCustomVFNRCLIPMasked
150       : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
151                   [LLVMMatchType<0>, llvm_anyfloat_ty, LLVMVectorElementType<1>,
152                    LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty,
153                    LLVMMatchType<2>, LLVMMatchType<2>],
154                   [ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<6>>, IntrNoMem]>, RISCVVIntrinsic {
155    let VLOperand = 5;
156  }
157
158  multiclass RISCVSFCustomVFNRCLIP {
159    def NAME : RISCVSFCustomVFNRCLIPUnMasked;
160    def NAME # "_mask" : RISCVSFCustomVFNRCLIPMasked;
161  }
162
163  defm "" : RISCVSFCustomVC_X<["x", "i"]>;
164  defm "" : RISCVSFCustomVC_XV<["x", "i", "v", "f"]>;
165  defm "" : RISCVSFCustomVC_XVV<["x", "i", "v", "f"]>;
166  defm "" : RISCVSFCustomVC_XVW<["x", "i", "v", "f"]>;
167
168  // XSfvqmaccdod
169  def int_riscv_sf_vqmaccu_2x8x2  : RISCVSFCustomVMACC;
170  def int_riscv_sf_vqmacc_2x8x2   : RISCVSFCustomVMACC;
171  def int_riscv_sf_vqmaccus_2x8x2 : RISCVSFCustomVMACC;
172  def int_riscv_sf_vqmaccsu_2x8x2 : RISCVSFCustomVMACC;
173
174  // XSfvqmaccqoq
175  def int_riscv_sf_vqmaccu_4x8x4  : RISCVSFCustomVMACC;
176  def int_riscv_sf_vqmacc_4x8x4   : RISCVSFCustomVMACC;
177  def int_riscv_sf_vqmaccus_4x8x4 : RISCVSFCustomVMACC;
178  def int_riscv_sf_vqmaccsu_4x8x4 : RISCVSFCustomVMACC;
179
180  // XSfvfwmaccqqq
181  def int_riscv_sf_vfwmacc_4x4x4 : RISCVSFCustomVMACC;
182
183  // XSfvfnrclipxfqf
184  defm int_riscv_sf_vfnrclip_x_f_qf : RISCVSFCustomVFNRCLIP;
185  defm int_riscv_sf_vfnrclip_xu_f_qf : RISCVSFCustomVFNRCLIP;
186} // TargetPrefix = "riscv"
187