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 foreach r = range in 51 let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")), 52 ["Xsfvcp", "RV64"], ["Xsfvcp"]) in 53 defm : VCIXBuiltinSet<NAME, NAME, "Uv", prototype, r, intrinsic_types>; 54} 55 56multiclass RVVVCIXBuiltinSetWVType<list<string> range, string prototype, 57 list<int> intrinsic_types, bit UseGPR> { 58 foreach r = range in 59 let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")), 60 ["Xsfvcp", "RV64"], ["Xsfvcp"]) in 61 // These intrinsics don't have any vector types in the output and inputs, 62 // but we still need to add vetvli for them. So we encode different 63 // VTYPE into the intrinsic names, and then will know which vsetvli is 64 // correct. 65 foreach s = VCIXSuffix<r>.suffix in 66 // Since we already encode the Vtype into the name, so just set 67 // Log2LMUL to zero. Otherwise the RISCVVEmitter will expand 68 // lots of redundant intrinsic but have same names. 69 let Log2LMUL = [0] in 70 def : VCIXBuiltinSet<NAME # "_u" # s, NAME # "_e" # s, 71 "", prototype, r, intrinsic_types>; 72} 73 74let SupportOverloading = false in { 75 defm sf_vc_x_se : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzUe", [0, 3], UseGPR=1>; 76 defm sf_vc_i_se : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzKz", [2, 3], UseGPR=0>; 77 defm sf_vc_xv : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUe", [0, 2, 3], UseGPR=1>; 78 defm sf_vc_iv : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvKz", [0, 2, 3], UseGPR=0>; 79 defm sf_vc_vv : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUv", [0, 2, 3], UseGPR=0>; 80 defm sf_vc_fv : RVVVCIXBuiltinSet<["si", "l"], "0KzKzUvFe", [0, 2, 3], UseGPR=0>; 81 defm sf_vc_xvv : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUe", [0, 1, 2, 3], UseGPR=1>; 82 defm sf_vc_ivv : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvKz", [0, 1, 2, 3], UseGPR=0>; 83 defm sf_vc_vvv : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUv", [0, 1, 2, 3], UseGPR=0>; 84 defm sf_vc_fvv : RVVVCIXBuiltinSet<["si", "l"], "0KzUvUvFe", [0, 1, 2, 3], UseGPR=0>; 85 defm sf_vc_v_x : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzUe", [-1, 1, 2], UseGPR=1>; 86 defm sf_vc_v_i : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzKz", [-1, 1, 2], UseGPR=0>; 87 defm sf_vc_v_xv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUe", [-1, 0, 1, 2], UseGPR=1>; 88 defm sf_vc_v_iv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvKz", [-1, 0, 1, 2], UseGPR=0>; 89 defm sf_vc_v_vv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUv", [-1, 0, 1, 2], UseGPR=0>; 90 defm sf_vc_v_fv : RVVVCIXBuiltinSet<["si", "l"], "UvKzUvFe", [-1, 0, 1, 2], UseGPR=0>; 91 defm sf_vc_v_xvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUe", [-1, 0, 1, 2, 3], UseGPR=1>; 92 defm sf_vc_v_ivv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvKz", [-1, 0, 1, 2, 3], UseGPR=0>; 93 defm sf_vc_v_vvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUv", [-1, 0, 1, 2, 3], UseGPR=0>; 94 defm sf_vc_v_fvv : RVVVCIXBuiltinSet<["si", "l"], "UvKzUvUvFe", [-1, 0, 1, 2, 3], UseGPR=0>; 95 let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { 96 defm sf_vc_xvw : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUe", [0, 1, 2, 3], UseGPR=1>; 97 defm sf_vc_ivw : RVVVCIXBuiltinSet<["csi"], "0KzUwUvKz", [0, 1, 2, 3], UseGPR=0>; 98 defm sf_vc_vvw : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUv", [0, 1, 2, 3], UseGPR=0>; 99 defm sf_vc_fvw : RVVVCIXBuiltinSet<["si"], "0KzUwUvFe", [0, 1, 2, 3], UseGPR=0>; 100 defm sf_vc_v_xvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUe", [-1, 0, 1, 2, 3], UseGPR=1>; 101 defm sf_vc_v_ivw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvKz", [-1, 0, 1, 2, 3], UseGPR=0>; 102 defm sf_vc_v_vvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUv", [-1, 0, 1, 2, 3], UseGPR=0>; 103 defm sf_vc_v_fvw : RVVVCIXBuiltinSet<["si"], "UwKzUwUvFe", [-1, 0, 1, 2, 3], UseGPR=0>; 104 } 105} 106 107multiclass RVVVFWMACCBuiltinSet<list<list<string>> suffixes_prototypes> { 108 let OverloadedName = NAME, 109 Name = NAME, 110 HasMasked = false, 111 Log2LMUL = [-2, -1, 0, 1, 2] in 112 defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "y", suffixes_prototypes>; 113} 114 115multiclass RVVVQMACCDODBuiltinSet<list<list<string>> suffixes_prototypes> { 116 let OverloadedName = NAME, 117 Name = NAME, 118 HasMasked = false, 119 Log2LMUL = [0, 1, 2, 3] in 120 defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "i", suffixes_prototypes>; 121} 122 123multiclass RVVVQMACCQOQBuiltinSet<list<list<string>> suffixes_prototypes> { 124 let OverloadedName = NAME, 125 Name = NAME, 126 HasMasked = false, 127 Log2LMUL = [-1, 0, 1, 2] in 128 defm NAME : RVVOutOp1Op2BuiltinSet<NAME, "s", suffixes_prototypes>; 129} 130 131multiclass RVVVFNRCLIPBuiltinSet<string suffix, string prototype, string type_range> { 132 let Log2LMUL = [-3, -2, -1, 0, 1, 2], 133 Name = NAME, 134 IRName = NAME, 135 MaskedIRName = NAME # "_mask" in 136 def : RVVConvBuiltin<suffix, prototype, type_range, NAME>; 137} 138 139let UnMaskedPolicyScheme = HasPolicyOperand in 140 let RequiredFeatures = ["Xsfvqmaccdod"] in { 141 defm sf_vqmaccu_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)SUv(FixedSEW:8)Uv"]]>; 142 defm sf_vqmacc_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)Sv(FixedSEW:8)v"]]>; 143 defm sf_vqmaccus_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)SUv(FixedSEW:8)v"]]>; 144 defm sf_vqmaccsu_2x8x2 : RVVVQMACCDODBuiltinSet<[["", "v", "vv(FixedSEW:8)Sv(FixedSEW:8)Uv"]]>; 145 } 146 147let UnMaskedPolicyScheme = HasPolicyOperand in 148 let RequiredFeatures = ["Xsfvqmaccqoq"] in { 149 defm sf_vqmaccu_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)SUv(FixedSEW:8)Uv"]]>; 150 defm sf_vqmacc_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)Sv(FixedSEW:8)v"]]>; 151 defm sf_vqmaccus_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)SUv(FixedSEW:8)v"]]>; 152 defm sf_vqmaccsu_4x8x4 : RVVVQMACCQOQBuiltinSet<[["", "w", "ww(FixedSEW:8)Sv(FixedSEW:8)Uv"]]>; 153 } 154 155let UnMaskedPolicyScheme = HasPolicyOperand in 156 let RequiredFeatures = ["Xsfvfwmaccqqq"] in 157 defm sf_vfwmacc_4x4x4 : RVVVFWMACCBuiltinSet<[["", "Fw", "FwFwSvv"]]>; 158 159let UnMaskedPolicyScheme = HasPassthruOperand, RequiredFeatures = ["Xsfvfnrclipxfqf"] in { 160let ManualCodegen = [{ 161 { 162 // LLVM intrinsic 163 // Unmasked: (passthru, vector_in, scalar_in, frm, vl) 164 // Masked: (passthru, vector_in, scalar_in, mask, frm, vl, policy) 165 166 SmallVector<llvm::Value*, 7> Operands; 167 bool HasMaskedOff = !( 168 (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || 169 (!IsMasked && PolicyAttrs & RVV_VTA)); 170 bool HasRoundModeOp = IsMasked ? 171 (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : 172 (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); 173 174 unsigned Offset = IsMasked ? 175 (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); 176 177 if (!HasMaskedOff) 178 Operands.push_back(llvm::PoisonValue::get(ResultType)); 179 else 180 Operands.push_back(Ops[IsMasked ? 1 : 0]); 181 182 Operands.push_back(Ops[Offset]); // op0 183 Operands.push_back(Ops[Offset + 1]); // op1 184 185 if (IsMasked) 186 Operands.push_back(Ops[0]); // mask 187 188 if (HasRoundModeOp) { 189 Operands.push_back(Ops[Offset + 2]); // frm 190 Operands.push_back(Ops[Offset + 3]); // vl 191 } else { 192 Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm 193 Operands.push_back(Ops[Offset + 2]); // vl 194 } 195 196 if (IsMasked) 197 Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); 198 199 IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Operands.back()->getType()}; 200 llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); 201 return Builder.CreateCall(F, Operands, ""); 202 } 203}] in { 204 let HasFRMRoundModeOp = true in { 205 defm sf_vfnrclip_x_f_qf : RVVVFNRCLIPBuiltinSet<"v", "vFqfu", "c">; 206 defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqfu", "c">; 207 } 208 defm sf_vfnrclip_x_f_qf : RVVVFNRCLIPBuiltinSet<"v", "vFqf", "c">; 209 defm sf_vfnrclip_xu_f_qf : RVVVFNRCLIPBuiltinSet<"Uv", "UvFqf", "c">; 210} 211} 212