xref: /freebsd/contrib/llvm-project/clang/include/clang/Basic/riscv_sifive_vector.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1//==--- riscv_sifive_vector.td - RISC-V SiFive VCIX function list ---------===//
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 the builtins for RISC-V SiFive VCIX. See:
10//
11//     https://sifive.cdn.prismic.io/sifive/c3829e36-8552-41f0-a841-79945784241b_vcix-spec-software.pdf
12//
13//===----------------------------------------------------------------------===//
14
15include "riscv_vector_common.td"
16
17//===----------------------------------------------------------------------===//
18// Instruction definitions
19//===----------------------------------------------------------------------===//
20
21class VCIXSuffix<string range> {
22  list<string> suffix = !cond(!eq(range, "c"): ["8mf8", "8mf4", "8mf2", "8m1", "8m2", "8m4", "8m8"],
23                              !eq(range, "s"): ["16mf4", "16mf2", "16m1", "16m2", "16m4", "16m8"],
24                              !eq(range, "i"): ["32mf2", "32m1", "32m2", "32m4", "32m8"],
25                              !eq(range, "l"): ["64m1", "64m2", "64m4", "64m8"]);
26}
27
28class VCIXBuiltinSet<string name, string IR_name, string suffix,
29                     string prototype, string type_range,
30                     list<int> intrinsic_types>
31    : RVVBuiltin<suffix, prototype, type_range> {
32  let Name = name;
33  let OverloadedName = name;
34  let IRName = IR_name;
35  let HasMasked = false;
36  let IntrinsicTypes = intrinsic_types;
37}
38
39multiclass VCIXBuiltinSet<string name, string IR_name, string suffix,
40                          string prototype, string type_range,
41                          list<int> intrinsic_types> {
42  if !find(prototype, "0") then {
43    def : VCIXBuiltinSet<name, IR_name, suffix, prototype, type_range, intrinsic_types>;
44  }
45  def : VCIXBuiltinSet<name # "_se", IR_name # "_se", suffix, prototype, type_range, intrinsic_types>;
46}
47
48multiclass RVVVCIXBuiltinSet<list<string> range, string prototype,
49                             list<int> intrinsic_types, bit UseGPR,
50                             string suffix = "Uv"> {
51  foreach r = range in
52    let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")),
53                               ["Xsfvcp", "RV64"], ["Xsfvcp"]) in
54      defm : VCIXBuiltinSet<NAME, NAME, suffix, prototype, r, intrinsic_types>;
55}
56
57multiclass RVVVCIXBuiltinSetWOSuffix<list<string> range, string prototype,
58                                     list<int> intrinsic_types, bit UseGPR> {
59  let Log2LMUL = [0] in
60  defm NAME : RVVVCIXBuiltinSet<range, prototype, intrinsic_types, UseGPR, "">;
61}
62
63let SupportOverloading = false in {
64  defm sf_vc_x  : RVVVCIXBuiltinSetWOSuffix<["c", "s", "i", "l"], "0KzKzKzUeKzKz", [0, 3], UseGPR=1>;
65  defm sf_vc_i  : RVVVCIXBuiltinSetWOSuffix<["i"], "0KzKzKzKzKzKz", [2, 3], UseGPR=0>;
66  defm sf_vc_xv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUe",  [0, 2, 3],  UseGPR=1>;
67  defm sf_vc_iv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvKz",  [0, 2, 3],  UseGPR=0>;
68  defm sf_vc_vv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUv",  [0, 2, 3],  UseGPR=0>;
69  defm sf_vc_fv    : RVVVCIXBuiltinSet<["si",  "l"], "0KzKzUvFe",  [0, 2, 3],  UseGPR=0>;
70  defm sf_vc_xvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUe",  [0, 1, 2, 3],  UseGPR=1>;
71  defm sf_vc_ivv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvKz",  [0, 1, 2, 3],  UseGPR=0>;
72  defm sf_vc_vvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUv",  [0, 1, 2, 3],  UseGPR=0>;
73  defm sf_vc_fvv   : RVVVCIXBuiltinSet<["si",  "l"], "0KzUvUvFe",  [0, 1, 2, 3],  UseGPR=0>;
74  defm sf_vc_v_x   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzUe",   [-1, 1, 2], UseGPR=1>;
75  defm sf_vc_v_i   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzKz",   [-1, 1, 2], UseGPR=0>;
76  defm sf_vc_v_xv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUe",   [-1, 0, 1, 2], UseGPR=1>;
77  defm sf_vc_v_iv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvKz",   [-1, 0, 1, 2], UseGPR=0>;
78  defm sf_vc_v_vv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUv",   [-1, 0, 1, 2], UseGPR=0>;
79  defm sf_vc_v_fv  : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvFe",   [-1, 0, 1, 2], UseGPR=0>;
80  defm sf_vc_v_xvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUe", [-1, 0, 1, 2, 3], UseGPR=1>;
81  defm sf_vc_v_ivv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvKz", [-1, 0, 1, 2, 3], UseGPR=0>;
82  defm sf_vc_v_vvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUv", [-1, 0, 1, 2, 3], UseGPR=0>;
83  defm sf_vc_v_fvv : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvUvFe", [-1, 0, 1, 2, 3], UseGPR=0>;
84  let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
85    defm sf_vc_xvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUe",  [0, 1, 2, 3],  UseGPR=1>;
86    defm sf_vc_ivw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvKz",  [0, 1, 2, 3],  UseGPR=0>;
87    defm sf_vc_vvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUv",  [0, 1, 2, 3],  UseGPR=0>;
88    defm sf_vc_fvw   : RVVVCIXBuiltinSet<["si"],  "0KzUwUvFe",  [0, 1, 2, 3],  UseGPR=0>;
89    defm sf_vc_v_xvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUe", [-1, 0, 1, 2, 3], UseGPR=1>;
90    defm sf_vc_v_ivw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvKz", [-1, 0, 1, 2, 3], UseGPR=0>;
91    defm sf_vc_v_vvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUv", [-1, 0, 1, 2, 3], UseGPR=0>;
92    defm sf_vc_v_fvw : RVVVCIXBuiltinSet<["si"],  "UwKzUwUvFe", [-1, 0, 1, 2, 3], UseGPR=0>;
93  }
94}
95
96multiclass RVVVFWMACCBuiltinSet<list<list<string>> suffixes_prototypes> {
97  let OverloadedName = NAME,
98      Name = NAME,
99      HasMasked = false,
100      Log2LMUL = [-2, -1, 0, 1, 2] in
101    defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "y", suffixes_prototypes>;
102}
103
104multiclass RVVVQMACCDODBuiltinSet<list<list<string>> suffixes_prototypes> {
105  let OverloadedName = NAME,
106      Name = NAME,
107      HasMasked = false,
108      Log2LMUL = [0, 1, 2, 3] in
109    defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "i", suffixes_prototypes>;
110}
111
112multiclass RVVVQMACCQOQBuiltinSet<list<list<string>> suffixes_prototypes> {
113  let OverloadedName = NAME,
114      Name = NAME,
115      HasMasked = false,
116      Log2LMUL = [-1, 0, 1, 2] in
117    defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "s", suffixes_prototypes>;
118}
119
120multiclass RVVVFNRCLIPBuiltinSet<string suffix, string prototype, string type_range> {
121  let Log2LMUL = [-3, -2, -1, 0, 1, 2],
122      Name = NAME,
123      IRName = NAME,
124      MaskedIRName = NAME # "_mask" in
125  def : RVVConvBuiltin<suffix, prototype, type_range, NAME>;
126}
127
128let UnMaskedPolicyScheme = HasPolicyOperand in
129  let RequiredFeatures = ["Xsfvqmaccdod"] in {
130    defm sf_vqmaccu_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)SUv(FixedSEW:8)Uv"]]>;
131    defm sf_vqmacc_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)Sv(FixedSEW:8)v"]]>;
132    defm sf_vqmaccus_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)SUv(FixedSEW:8)v"]]>;
133    defm sf_vqmaccsu_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)Sv(FixedSEW:8)Uv"]]>;
134  }
135
136let UnMaskedPolicyScheme = HasPolicyOperand in
137  let RequiredFeatures = ["Xsfvqmaccqoq"] in {
138    defm sf_vqmaccu_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)SUv(FixedSEW:8)Uv"]]>;
139    defm sf_vqmacc_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)Sv(FixedSEW:8)v"]]>;
140    defm sf_vqmaccus_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)SUv(FixedSEW:8)v"]]>;
141    defm sf_vqmaccsu_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)Sv(FixedSEW:8)Uv"]]>;
142  }
143
144let UnMaskedPolicyScheme = HasPolicyOperand in
145  let RequiredFeatures = ["Xsfvfwmaccqqq"] in
146    defm sf_vfwmacc_4x4x4 : RVVVFWMACCBuiltinSet<[["", "Fw", "FwFwSvv"]]>;
147
148let UnMaskedPolicyScheme = HasPassthruOperand, RequiredFeatures = ["Xsfvfnrclipxfqf"] in {
149let ManualCodegen = [{
150  {
151    // LLVM intrinsic
152    // Unmasked: (passthru, vector_in, scalar_in, frm, vl)
153    // Masked:   (passthru, vector_in, scalar_in, mask, frm, vl, policy)
154
155    SmallVector<llvm::Value*, 7> Operands;
156    bool HasMaskedOff = !(
157        (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
158        (!IsMasked && PolicyAttrs & RVV_VTA));
159    bool HasRoundModeOp = IsMasked ?
160      (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) :
161      (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
162
163    unsigned Offset = IsMasked ?
164        (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0);
165
166    if (!HasMaskedOff)
167      Operands.push_back(llvm::PoisonValue::get(ResultType));
168    else
169      Operands.push_back(Ops[IsMasked ? 1 : 0]);
170
171    Operands.push_back(Ops[Offset]); // op0
172    Operands.push_back(Ops[Offset + 1]); // op1
173
174    if (IsMasked)
175      Operands.push_back(Ops[0]); // mask
176
177    if (HasRoundModeOp) {
178      Operands.push_back(Ops[Offset + 2]); // frm
179      Operands.push_back(Ops[Offset + 3]); // vl
180    } else {
181      Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm
182      Operands.push_back(Ops[Offset + 2]); // vl
183    }
184
185    if (IsMasked)
186      Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
187
188    IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Operands.back()->getType()};
189    llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
190    return Builder.CreateCall(F, Operands, "");
191  }
192}] in {
193  let HasFRMRoundModeOp = true in {
194    defm sf_vfnrclip_x_f_qf : RVVVFNRCLIPBuiltinSet<"v", "vFqfu", "c">;
195    defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqfu", "c">;
196  }
197  defm sf_vfnrclip_x_f_qf : RVVVFNRCLIPBuiltinSet<"v", "vFqf", "c">;
198  defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqf", "c">;
199}
200}
201