1//==------ riscv_vector_common.td - RISC-V V-ext builtin class ------------===// 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 RVV builtin base class for RISC-V V-extension. 10// 11//===----------------------------------------------------------------------===// 12 13//===----------------------------------------------------------------------===// 14// Instruction definitions 15//===----------------------------------------------------------------------===// 16// Each record of the class RVVBuiltin defines a collection of builtins (i.e. 17// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1", 18// "vadd_vv_i32m2", etc). 19// 20// The elements of this collection are defined by an instantiation process the 21// range of which is specified by the cross product of the LMUL attribute and 22// every element in the attribute TypeRange. By default builtins have LMUL = [1, 23// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we 24// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL. 25// 26// LMUL represents the fact that the types of values used by that builtin are 27// values generated by instructions that are executed under that LMUL. However, 28// this does not mean the builtin is necessarily lowered into an instruction 29// that executes under the specified LMUL. An example where this happens are 30// loads and stores of masks. A mask like `vbool8_t` can be generated, for 31// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two 32// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will 33// be performed under LMUL=1 because mask registers are not grouped. 34// 35// TypeRange is a non-empty sequence of basic types: 36// 37// c: int8_t (i8) 38// s: int16_t (i16) 39// i: int32_t (i32) 40// l: int64_t (i64) 41// x: float16_t (half) 42// f: float32_t (float) 43// d: float64_t (double) 44// y: bfloat16_t (bfloat16) 45// 46// This way, given an LMUL, a record with a TypeRange "sil" will cause the 47// definition of 3 builtins. Each type "t" in the TypeRange (in this example 48// they are int16_t, int32_t, int64_t) is used as a parameter that drives the 49// definition of that particular builtin (for the given LMUL). 50// 51// During the instantiation, types can be transformed or modified using type 52// transformers. Given a type "t" the following primitive type transformers can 53// be applied to it to yield another type. 54// 55// e: type of "t" as is (identity) 56// v: computes a vector type whose element type is "t" for the current LMUL 57// w: computes a vector type identical to what 'v' computes except for the 58// element type which is twice as wide as the element type of 'v' 59// q: computes a vector type identical to what 'v' computes except for the 60// element type which is four times as wide as the element type of 'v' 61// o: computes a vector type identical to what 'v' computes except for the 62// element type which is eight times as wide as the element type of 'v' 63// m: computes a vector type identical to what 'v' computes except for the 64// element type which is bool 65// 0: void type, ignores "t" 66// z: size_t, ignores "t" 67// t: ptrdiff_t, ignores "t" 68// u: unsigned long, ignores "t" 69// l: long, ignores "t" 70// f: float32, ignores "t" 71// 72// So for instance if t is "i", i.e. int, then "e" will yield int again. "v" 73// will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t. 74// Accordingly "w" would yield __rvv_int64m2_t. 75// 76// A type transformer can be prefixed by other non-primitive type transformers. 77// 78// P: constructs a pointer to the current type 79// C: adds const to the type 80// K: requires the integer type to be a constant expression 81// U: given an integer type or vector type, computes its unsigned variant 82// I: given a vector type, compute the vector type with integer type 83// elements of the same width 84// F: given a vector type, compute the vector type with floating-point type 85// elements of the same width 86// S: given a vector type, computes its equivalent one for LMUL=1. This is a 87// no-op if the vector was already LMUL=1 88// (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a 89// vector type (SEW and LMUL) and EEW (8/16/32/64), computes its 90// equivalent integer vector type with EEW and corresponding ELMUL (elmul = 91// (eew/sew) * lmul). For example, vector type is __rvv_float16m4 92// (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector 93// type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new 94// builtins if its equivalent type has illegal lmul. 95// (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another 96// vector type which only changed SEW as given value. Ignore to define a new 97// builtin if its equivalent type has illegal lmul or the SEW does not changed. 98// (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW 99// and LMUL), and computes another vector type which only changed LMUL as 100// given value. The new LMUL should be smaller than the old one. Ignore to 101// define a new builtin if its equivalent type has illegal lmul. 102// (SEFixedLog2LMUL:Value): Smaller or Equal Fixed Log2LMUL. Given a vector 103// type (SEW and LMUL), and computes another vector type which only 104// changed LMUL as given value. The new LMUL should be smaller than or 105// equal to the old one. Ignore to define a new builtin if its equivalent 106// type has illegal lmul. 107// (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW 108// and LMUL), and computes another vector type which only changed LMUL as 109// given value. The new LMUL should be larger than the old one. Ignore to 110// define a new builtin if its equivalent type has illegal lmul. 111// 112// Following with the example above, if t is "i", then "Ue" will yield unsigned 113// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would 114// yield __rvv_float64m2_t, etc. 115// 116// Each builtin is then defined by applying each type in TypeRange against the 117// sequence of type transformers described in Suffix and Prototype. 118// 119// The name of the builtin is defined by the Name attribute (which defaults to 120// the name of the class) appended (separated with an underscore) the Suffix 121// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il", 122// the builtin generated will be __builtin_rvv_foo_i32m1 and 123// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one 124// type transformer (say "vv") each of the types is separated with an 125// underscore as in "__builtin_rvv_foo_i32m1_i32m1". 126// 127// The C/C++ prototype of the builtin is defined by the Prototype attribute. 128// Prototype is a non-empty sequence of type transformers, the first of which 129// is the return type of the builtin and the rest are the parameters of the 130// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si" 131// a first builtin will have type 132// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin 133// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again 134// under LMUL=1). 135// 136// There are a number of attributes that are used to constraint the number and 137// shape of the builtins generated. Refer to the comments below for them. 138 139class PolicyScheme<int val>{ 140 int Value = val; 141} 142def NonePolicy : PolicyScheme<0>; 143def HasPassthruOperand : PolicyScheme<1>; 144def HasPolicyOperand : PolicyScheme<2>; 145 146class RVVBuiltin<string suffix, string prototype, string type_range, 147 string overloaded_suffix = ""> { 148 // Base name that will be prepended in __builtin_rvv_ and appended the 149 // computed Suffix. 150 string Name = NAME; 151 152 // If not empty, each instantiated builtin will have this appended after an 153 // underscore (_). It is instantiated like Prototype. 154 string Suffix = suffix; 155 156 // If empty, default OverloadedName is sub string of `Name` which end of first 157 // '_'. For example, the default overloaded name is `vadd` for Name `vadd_vv`. 158 // It's used for describe some special naming cases. 159 string OverloadedName = ""; 160 161 // If not empty, each OverloadedName will have this appended after an 162 // underscore (_). It is instantiated like Prototype. 163 string OverloadedSuffix = overloaded_suffix; 164 165 // The different variants of the builtin, parameterised with a type. 166 string TypeRange = type_range; 167 168 // We use each type described in TypeRange and LMUL with prototype to 169 // instantiate a specific element of the set of builtins being defined. 170 // Prototype attribute defines the C/C++ prototype of the builtin. It is a 171 // non-empty sequence of type transformers, the first of which is the return 172 // type of the builtin and the rest are the parameters of the builtin, in 173 // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a 174 // first builtin will have type 175 // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin 176 // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t). 177 string Prototype = prototype; 178 179 // This builtin has a masked form. 180 bit HasMasked = true; 181 182 // If HasMasked, this flag states that this builtin has a maskedoff operand. It 183 // is always the first operand in builtin and IR intrinsic. 184 bit HasMaskedOffOperand = true; 185 186 // This builtin has a granted vector length parameter. 187 bit HasVL = true; 188 189 // The policy scheme for masked intrinsic IR. 190 // It could be NonePolicy or HasPolicyOperand. 191 // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is 192 // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The 193 // policy operand is located at the last position. 194 PolicyScheme MaskedPolicyScheme = HasPolicyOperand; 195 196 // The policy scheme for unmasked intrinsic IR. 197 // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand. 198 // HasPassthruOperand: Has a passthru operand to decide tail policy. If it is 199 // poison, tail policy is tail agnostic, otherwise policy is tail undisturbed. 200 // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail 201 // undisturbed. 202 PolicyScheme UnMaskedPolicyScheme = NonePolicy; 203 204 // This builtin support tail agnostic and undisturbed policy. 205 bit HasTailPolicy = true; 206 // This builtin support mask agnostic and undisturbed policy. 207 bit HasMaskPolicy = true; 208 209 // This builtin prototype with TA or TAMA policy could not support overloading 210 // API. Other policy intrinsic functions would support overloading API with 211 // suffix `_tu`, `tumu`, `tuma`, `tamu` and `tama`. 212 bit SupportOverloading = true; 213 214 // This builtin is valid for the given Log2LMULs. 215 list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3]; 216 217 // Manual code in clang codegen riscv_vector_builtin_cg.inc 218 code ManualCodegen = [{}]; 219 220 // When emit the automatic clang codegen, it describes what types we have to use 221 // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise, 222 // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd 223 // parameter of the unmasked version. k can't be the mask operand's position. 224 list<int> IntrinsicTypes = []; 225 226 // If these names are not empty, this is the ID of the LLVM intrinsic 227 // we want to lower to. 228 string IRName = NAME; 229 230 // If HasMasked, this is the ID of the LLVM intrinsic we want to lower to. 231 string MaskedIRName = NAME #"_mask"; 232 233 // Use clang_builtin_alias to save the number of builtins. 234 bit HasBuiltinAlias = true; 235 236 // Features required to enable for this builtin. 237 list<string> RequiredFeatures = []; 238 239 // Number of fields for Load/Store Segment instructions. 240 int NF = 1; 241 242 // Set to true if the builtin is associated with tuple types. 243 bit IsTuple = false; 244 245 // Set to true if the builtin has a parameter that models floating-point 246 // rounding mode control 247 bit HasFRMRoundModeOp = false; 248} 249 250// This is the code emitted in the header. 251class RVVHeader { 252 code HeaderCode; 253} 254 255//===----------------------------------------------------------------------===// 256// Basic classes with automatic codegen. 257//===----------------------------------------------------------------------===// 258 259class RVVOutBuiltin<string suffix, string prototype, string type_range> 260 : RVVBuiltin<suffix, prototype, type_range> { 261 let IntrinsicTypes = [-1]; 262} 263 264class RVVOp0Builtin<string suffix, string prototype, string type_range> 265 : RVVBuiltin<suffix, prototype, type_range> { 266 let IntrinsicTypes = [0]; 267} 268 269class RVVOutOp1Builtin<string suffix, string prototype, string type_range> 270 : RVVBuiltin<suffix, prototype, type_range> { 271 let IntrinsicTypes = [-1, 1]; 272} 273 274class RVVOutOp0Op1Builtin<string suffix, string prototype, string type_range> 275 : RVVBuiltin<suffix, prototype, type_range> { 276 let IntrinsicTypes = [-1, 0, 1]; 277} 278 279multiclass RVVBuiltinSet<string intrinsic_name, string type_range, 280 list<list<string>> suffixes_prototypes, 281 list<int> intrinsic_types> { 282 let IRName = intrinsic_name, MaskedIRName = intrinsic_name # "_mask", 283 IntrinsicTypes = intrinsic_types in { 284 foreach s_p = suffixes_prototypes in { 285 let Name = NAME # "_" # s_p[0] in { 286 defvar suffix = s_p[1]; 287 defvar prototype = s_p[2]; 288 def : RVVBuiltin<suffix, prototype, type_range>; 289 } 290 } 291 } 292} 293 294// IntrinsicTypes is output, op0, op1 [-1, 0, 1] 295multiclass RVVOutOp0Op1BuiltinSet<string intrinsic_name, string type_range, 296 list<list<string>> suffixes_prototypes> 297 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, 298 [-1, 0, 1]>; 299 300multiclass RVVOutBuiltinSet<string intrinsic_name, string type_range, 301 list<list<string>> suffixes_prototypes> 302 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1]>; 303 304multiclass RVVOp0BuiltinSet<string intrinsic_name, string type_range, 305 list<list<string>> suffixes_prototypes> 306 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0]>; 307 308// IntrinsicTypes is output, op1 [-1, 0] 309multiclass RVVOutOp0BuiltinSet<string intrinsic_name, string type_range, 310 list<list<string>> suffixes_prototypes> 311 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 0]>; 312 313// IntrinsicTypes is output, op1 [-1, 1] 314multiclass RVVOutOp1BuiltinSet<string intrinsic_name, string type_range, 315 list<list<string>> suffixes_prototypes> 316 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1]>; 317 318multiclass RVVOp0Op1BuiltinSet<string intrinsic_name, string type_range, 319 list<list<string>> suffixes_prototypes> 320 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1]>; 321 322multiclass RVVOutOp1Op2BuiltinSet<string intrinsic_name, string type_range, 323 list<list<string>> suffixes_prototypes> 324 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1, 2]>; 325 326// IntrinsicTypes is output, op2 [-1, 2] 327multiclass RVVOutOp2BuiltinSet<string intrinsic_name, string type_range, 328 list<list<string>> suffixes_prototypes> 329 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 2]>; 330 331multiclass RVVSignedBinBuiltinSet 332 : RVVOutOp1BuiltinSet<NAME, "csil", 333 [["vv", "v", "vvv"], 334 ["vx", "v", "vve"]]>; 335 336multiclass RVVSignedBinBuiltinSetRoundingMode 337 : RVVOutOp1BuiltinSet<NAME, "csil", 338 [["vv", "v", "vvvu"], 339 ["vx", "v", "vveu"]]>; 340 341multiclass RVVUnsignedBinBuiltinSet 342 : RVVOutOp1BuiltinSet<NAME, "csil", 343 [["vv", "Uv", "UvUvUv"], 344 ["vx", "Uv", "UvUvUe"]]>; 345 346multiclass RVVUnsignedBinBuiltinSetRoundingMode 347 : RVVOutOp1BuiltinSet<NAME, "csil", 348 [["vv", "Uv", "UvUvUvu"], 349 ["vx", "Uv", "UvUvUeu"]]>; 350 351multiclass RVVIntBinBuiltinSet 352 : RVVSignedBinBuiltinSet, 353 RVVUnsignedBinBuiltinSet; 354 355multiclass RVVInt64BinBuiltinSet 356 : RVVOutOp1BuiltinSet<NAME, "l", 357 [["vv", "v", "vvv"], 358 ["vx", "v", "vve"]]>, 359 RVVOutOp1BuiltinSet<NAME, "l", 360 [["vv", "Uv", "UvUvUv"], 361 ["vx", "Uv", "UvUvUe"]]>; 362 363multiclass RVVSlideOneBuiltinSet 364 : RVVOutOp1BuiltinSet<NAME, "csil", 365 [["vx", "v", "vve"], 366 ["vx", "Uv", "UvUvUe"]]>; 367 368multiclass RVVSignedShiftBuiltinSet 369 : RVVOutOp1BuiltinSet<NAME, "csil", 370 [["vv", "v", "vvUv"], 371 ["vx", "v", "vvz"]]>; 372 373multiclass RVVSignedShiftBuiltinSetRoundingMode 374 : RVVOutOp1BuiltinSet<NAME, "csil", 375 [["vv", "v", "vvUvu"], 376 ["vx", "v", "vvzu"]]>; 377 378multiclass RVVUnsignedShiftBuiltinSet 379 : RVVOutOp1BuiltinSet<NAME, "csil", 380 [["vv", "Uv", "UvUvUv"], 381 ["vx", "Uv", "UvUvz"]]>; 382 383multiclass RVVUnsignedShiftBuiltinSetRoundingMode 384 : RVVOutOp1BuiltinSet<NAME, "csil", 385 [["vv", "Uv", "UvUvUvu"], 386 ["vx", "Uv", "UvUvzu"]]>; 387 388multiclass RVVShiftBuiltinSet 389 : RVVSignedShiftBuiltinSet, 390 RVVUnsignedShiftBuiltinSet; 391 392let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { 393 multiclass RVVSignedNShiftBuiltinSet 394 : RVVOutOp0Op1BuiltinSet<NAME, "csil", 395 [["wv", "v", "vwUv"], 396 ["wx", "v", "vwz"]]>; 397 398 multiclass RVVSignedNShiftBuiltinSetRoundingMode 399 : RVVOutOp0Op1BuiltinSet<NAME, "csil", 400 [["wv", "v", "vwUvu"], 401 ["wx", "v", "vwzu"]]>; 402 403 multiclass RVVUnsignedNShiftBuiltinSet 404 : RVVOutOp0Op1BuiltinSet<NAME, "csil", 405 [["wv", "Uv", "UvUwUv"], 406 ["wx", "Uv", "UvUwz"]]>; 407 408 multiclass RVVUnsignedNShiftBuiltinSetRoundingMode 409 : RVVOutOp0Op1BuiltinSet<NAME, "csil", 410 [["wv", "Uv", "UvUwUvu"], 411 ["wx", "Uv", "UvUwzu"]]>; 412 413} 414 415multiclass RVVCarryinBuiltinSet 416 : RVVOutOp1BuiltinSet<NAME, "csil", 417 [["vvm", "v", "vvvm"], 418 ["vxm", "v", "vvem"], 419 ["vvm", "Uv", "UvUvUvm"], 420 ["vxm", "Uv", "UvUvUem"]]>; 421 422multiclass RVVCarryOutInBuiltinSet<string intrinsic_name> 423 : RVVOp0Op1BuiltinSet<intrinsic_name, "csil", 424 [["vvm", "vm", "mvvm"], 425 ["vxm", "vm", "mvem"], 426 ["vvm", "Uvm", "mUvUvm"], 427 ["vxm", "Uvm", "mUvUem"]]>; 428 429multiclass RVVSignedMaskOutBuiltinSet 430 : RVVOp0Op1BuiltinSet<NAME, "csil", 431 [["vv", "vm", "mvv"], 432 ["vx", "vm", "mve"]]>; 433 434multiclass RVVUnsignedMaskOutBuiltinSet 435 : RVVOp0Op1BuiltinSet<NAME, "csil", 436 [["vv", "Uvm", "mUvUv"], 437 ["vx", "Uvm", "mUvUe"]]>; 438 439multiclass RVVIntMaskOutBuiltinSet 440 : RVVSignedMaskOutBuiltinSet, 441 RVVUnsignedMaskOutBuiltinSet; 442 443class RVVIntExt<string intrinsic_name, string suffix, string prototype, 444 string type_range> 445 : RVVBuiltin<suffix, prototype, type_range> { 446 let IRName = intrinsic_name; 447 let MaskedIRName = intrinsic_name # "_mask"; 448 let OverloadedName = NAME; 449 let IntrinsicTypes = [-1, 0]; 450} 451 452let HasMaskedOffOperand = false in { 453 multiclass RVVIntTerBuiltinSet { 454 defm "" : RVVOutOp1BuiltinSet<NAME, "csil", 455 [["vv", "v", "vvvv"], 456 ["vx", "v", "vvev"], 457 ["vv", "Uv", "UvUvUvUv"], 458 ["vx", "Uv", "UvUvUeUv"]]>; 459 } 460 multiclass RVVFloatingTerBuiltinSet { 461 defm "" : RVVOutOp1BuiltinSet<NAME, "fd", 462 [["vv", "v", "vvvv"], 463 ["vf", "v", "vvev"]]>; 464 let RequiredFeatures = ["Zvfh"] in 465 defm "" : RVVOutOp1BuiltinSet<NAME, "x", 466 [["vv", "v", "vvvv"], 467 ["vf", "v", "vvev"]]>; 468 } 469 multiclass RVVFloatingTerBuiltinSetRoundingMode { 470 defm "" : RVVOutOp1BuiltinSet<NAME, "fd", 471 [["vv", "v", "vvvvu"], 472 ["vf", "v", "vvevu"]]>; 473 let RequiredFeatures = ["Zvfh"] in 474 defm "" : RVVOutOp1BuiltinSet<NAME, "x", 475 [["vv", "v", "vvvvu"], 476 ["vf", "v", "vvevu"]]>; 477 } 478} 479 480let HasMaskedOffOperand = false, Log2LMUL = [-2, -1, 0, 1, 2] in { 481 multiclass RVVFloatingWidenTerBuiltinSet { 482 defm "" : RVVOutOp1Op2BuiltinSet<NAME, "f", 483 [["vv", "w", "wwvv"], 484 ["vf", "w", "wwev"]]>; 485 let RequiredFeatures = ["Zvfh"] in 486 defm "" : RVVOutOp1Op2BuiltinSet<NAME, "x", 487 [["vv", "w", "wwvv"], 488 ["vf", "w", "wwev"]]>; 489 } 490 multiclass RVVFloatingWidenTerBuiltinSetRoundingMode { 491 defm "" : RVVOutOp1Op2BuiltinSet<NAME, "f", 492 [["vv", "w", "wwvvu"], 493 ["vf", "w", "wwevu"]]>; 494 let RequiredFeatures = ["Zvfh"] in 495 defm "" : RVVOutOp1Op2BuiltinSet<NAME, "x", 496 [["vv", "w", "wwvvu"], 497 ["vf", "w", "wwevu"]]>; 498 } 499} 500 501multiclass RVVFloatingBinBuiltinSet { 502 defm "" : RVVOutOp1BuiltinSet<NAME, "fd", 503 [["vv", "v", "vvv"], 504 ["vf", "v", "vve"]]>; 505 let RequiredFeatures = ["Zvfh"] in 506 defm "" : RVVOutOp1BuiltinSet<NAME, "x", 507 [["vv", "v", "vvv"], 508 ["vf", "v", "vve"]]>; 509} 510 511multiclass RVVFloatingBinBuiltinSetRoundingMode { 512 defm "" : RVVOutOp1BuiltinSet<NAME, "fd", 513 [["vv", "v", "vvvu"], 514 ["vf", "v", "vveu"]]>; 515 let RequiredFeatures = ["Zvfh"] in 516 defm "" : RVVOutOp1BuiltinSet<NAME, "x", 517 [["vv", "v", "vvvu"], 518 ["vf", "v", "vveu"]]>; 519} 520 521multiclass RVVFloatingBinVFBuiltinSet { 522 defm "" : RVVOutOp1BuiltinSet<NAME, "fd", 523 [["vf", "v", "vve"]]>; 524 let RequiredFeatures = ["Zvfh"] in 525 defm "" : RVVOutOp1BuiltinSet<NAME, "x", 526 [["vf", "v", "vve"]]>; 527} 528 529multiclass RVVFloatingBinVFBuiltinSetRoundingMode { 530 defm "" : RVVOutOp1BuiltinSet<NAME, "fd", 531 [["vf", "v", "vveu"]]>; 532 let RequiredFeatures = ["Zvfh"] in 533 defm "" : RVVOutOp1BuiltinSet<NAME, "x", 534 [["vf", "v", "vveu"]]>; 535} 536 537multiclass RVVFloatingMaskOutBuiltinSet { 538 defm "" : RVVOp0Op1BuiltinSet<NAME, "fd", 539 [["vv", "vm", "mvv"], 540 ["vf", "vm", "mve"]]>; 541 let RequiredFeatures = ["Zvfh"] in 542 defm "" : RVVOp0Op1BuiltinSet<NAME, "x", 543 [["vv", "vm", "mvv"], 544 ["vf", "vm", "mve"]]>; 545} 546 547multiclass RVVFloatingMaskOutVFBuiltinSet 548 : RVVOp0Op1BuiltinSet<NAME, "fd", 549 [["vf", "vm", "mve"]]>; 550 551multiclass RVVConvBuiltinSet<string intrinsic_name, string type_range, 552 list<list<string>> suffixes_prototypes> { 553let Name = intrinsic_name, 554 IRName = intrinsic_name, 555 MaskedIRName = intrinsic_name # "_mask", 556 IntrinsicTypes = [-1, 0] in { 557 foreach s_p = suffixes_prototypes in { 558 defvar suffix = s_p[0]; 559 defvar prototype = s_p[1]; 560 def : RVVBuiltin<suffix, prototype, type_range>; 561 } 562 } 563} 564 565 566class RVVMaskBinBuiltin : RVVOutBuiltin<"m", "mmm", "c"> { 567 let Name = NAME # "_mm"; 568 let HasMasked = false; 569} 570 571class RVVMaskUnaryBuiltin : RVVOutBuiltin<"m", "mm", "c"> { 572 let Name = NAME # "_m"; 573} 574 575class RVVMaskNullaryBuiltin : RVVOutBuiltin<"m", "m", "c"> { 576 let Name = NAME # "_m"; 577 let HasMasked = false; 578 let SupportOverloading = false; 579} 580 581class RVVMaskOp0Builtin<string prototype> : RVVOp0Builtin<"m", prototype, "c"> { 582 let Name = NAME # "_m"; 583 let HasMaskedOffOperand = false; 584} 585 586let UnMaskedPolicyScheme = HasPolicyOperand, 587 HasMaskedOffOperand = false in { 588 multiclass RVVSlideUpBuiltinSet { 589 defm "" : RVVOutBuiltinSet<NAME, "csilfd", 590 [["vx","v", "vvvz"]]>; 591 let RequiredFeatures = ["Zvfh"] in 592 defm "" : RVVOutBuiltinSet<NAME, "x", 593 [["vx","v", "vvvz"]]>; 594 defm "" : RVVOutBuiltinSet<NAME, "csil", 595 [["vx","Uv", "UvUvUvz"]]>; 596 } 597} 598 599let UnMaskedPolicyScheme = HasPassthruOperand, 600 ManualCodegen = [{ 601 if (IsMasked) { 602 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); 603 if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) 604 Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); 605 } else { 606 if (PolicyAttrs & RVV_VTA) 607 Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); 608 } 609 610 Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); 611 IntrinsicTypes = {ResultType, Ops.back()->getType()}; 612 }] in { 613 multiclass RVVSlideDownBuiltinSet { 614 defm "" : RVVOutBuiltinSet<NAME, "csilfd", 615 [["vx","v", "vvz"]]>; 616 let RequiredFeatures = ["Zvfh"] in 617 defm "" : RVVOutBuiltinSet<NAME, "x", 618 [["vx","v", "vvz"]]>; 619 defm "" : RVVOutBuiltinSet<NAME, "csil", 620 [["vx","Uv", "UvUvz"]]>; 621 } 622} 623 624class RVVConvBuiltin<string suffix, string prototype, string type_range, 625 string overloaded_name> 626 : RVVBuiltin<suffix, prototype, type_range> { 627 let IntrinsicTypes = [-1, 0]; 628 let OverloadedName = overloaded_name; 629} 630 631class RVVConvToSignedBuiltin<string overloaded_name> 632 : RVVConvBuiltin<"Iv", "Ivv", "xfd", overloaded_name>; 633 634class RVVConvToUnsignedBuiltin<string overloaded_name> 635 : RVVConvBuiltin<"Uv", "Uvv", "xfd", overloaded_name>; 636 637class RVVConvToWidenSignedBuiltin<string overloaded_name> 638 : RVVConvBuiltin<"Iw", "Iwv", "xf", overloaded_name>; 639 640class RVVConvToWidenUnsignedBuiltin<string overloaded_name> 641 : RVVConvBuiltin<"Uw", "Uwv", "xf", overloaded_name>; 642 643class RVVConvToNarrowingSignedBuiltin<string overloaded_name> 644 : RVVConvBuiltin<"Iv", "IvFw", "si", overloaded_name>; 645 646class RVVConvToNarrowingUnsignedBuiltin<string overloaded_name> 647 : RVVConvBuiltin<"Uv", "UvFw", "si", overloaded_name>; 648 649let HasMaskedOffOperand = true in { 650 multiclass RVVSignedReductionBuiltin { 651 defm "" : RVVOutOp0BuiltinSet<NAME, "csil", 652 [["vs", "vSv", "SvvSv"]]>; 653 } 654 multiclass RVVUnsignedReductionBuiltin { 655 defm "" : RVVOutOp0BuiltinSet<NAME, "csil", 656 [["vs", "UvUSv", "USvUvUSv"]]>; 657 } 658 multiclass RVVFloatingReductionBuiltin { 659 defm "" : RVVOutOp0BuiltinSet<NAME, "fd", 660 [["vs", "vSv", "SvvSv"]]>; 661 let RequiredFeatures = ["Zvfh"] in 662 defm "" : RVVOutOp0BuiltinSet<NAME, "x", 663 [["vs", "vSv", "SvvSv"]]>; 664 } 665 multiclass RVVFloatingReductionBuiltinRoundingMode { 666 defm "" : RVVOutOp0BuiltinSet<NAME, "fd", 667 [["vs", "vSv", "SvvSvu"]]>; 668 let RequiredFeatures = ["Zvfh"] in 669 defm "" : RVVOutOp0BuiltinSet<NAME, "x", 670 [["vs", "vSv", "SvvSvu"]]>; 671 } 672 multiclass RVVFloatingWidenReductionBuiltin { 673 defm "" : RVVOutOp0BuiltinSet<NAME, "f", 674 [["vs", "vSw", "SwvSw"]]>; 675 let RequiredFeatures = ["Zvfh"] in 676 defm "" : RVVOutOp0BuiltinSet<NAME, "x", 677 [["vs", "vSw", "SwvSw"]]>; 678 } 679 multiclass RVVFloatingWidenReductionBuiltinRoundingMode { 680 defm "" : RVVOutOp0BuiltinSet<NAME, "f", 681 [["vs", "vSw", "SwvSwu"]]>; 682 let RequiredFeatures = ["Zvfh"] in 683 defm "" : RVVOutOp0BuiltinSet<NAME, "x", 684 [["vs", "vSw", "SwvSwu"]]>; 685 } 686} 687 688multiclass RVVIntReductionBuiltinSet 689 : RVVSignedReductionBuiltin, 690 RVVUnsignedReductionBuiltin; 691 692// For widen operation which has different mangling name. 693multiclass RVVWidenBuiltinSet<string intrinsic_name, string type_range, 694 list<list<string>> suffixes_prototypes> { 695 let Log2LMUL = [-3, -2, -1, 0, 1, 2], 696 IRName = intrinsic_name, MaskedIRName = intrinsic_name # "_mask" in { 697 foreach s_p = suffixes_prototypes in { 698 let Name = NAME # "_" # s_p[0], 699 OverloadedName = NAME # "_" # s_p[0] in { 700 defvar suffix = s_p[1]; 701 defvar prototype = s_p[2]; 702 def : RVVOutOp0Op1Builtin<suffix, prototype, type_range>; 703 } 704 } 705 } 706} 707 708// For widen operation with widen operand which has different mangling name. 709multiclass RVVWidenWOp0BuiltinSet<string intrinsic_name, string type_range, 710 list<list<string>> suffixes_prototypes> { 711 let Log2LMUL = [-3, -2, -1, 0, 1, 2], 712 IRName = intrinsic_name, MaskedIRName = intrinsic_name # "_mask" in { 713 foreach s_p = suffixes_prototypes in { 714 let Name = NAME # "_" # s_p[0], 715 OverloadedName = NAME # "_" # s_p[0] in { 716 defvar suffix = s_p[1]; 717 defvar prototype = s_p[2]; 718 def : RVVOutOp1Builtin<suffix, prototype, type_range>; 719 } 720 } 721 } 722} 723 724multiclass RVVSignedWidenBinBuiltinSet 725 : RVVWidenBuiltinSet<NAME, "csi", 726 [["vv", "w", "wvv"], 727 ["vx", "w", "wve"]]>; 728 729multiclass RVVSignedWidenOp0BinBuiltinSet 730 : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi", 731 [["wv", "w", "wwv"], 732 ["wx", "w", "wwe"]]>; 733 734multiclass RVVUnsignedWidenBinBuiltinSet 735 : RVVWidenBuiltinSet<NAME, "csi", 736 [["vv", "Uw", "UwUvUv"], 737 ["vx", "Uw", "UwUvUe"]]>; 738 739multiclass RVVUnsignedWidenOp0BinBuiltinSet 740 : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi", 741 [["wv", "Uw", "UwUwUv"], 742 ["wx", "Uw", "UwUwUe"]]>; 743 744multiclass RVVFloatingWidenBinBuiltinSet { 745 defm "" : RVVWidenBuiltinSet<NAME, "f", 746 [["vv", "w", "wvv"], 747 ["vf", "w", "wve"]]>; 748 let RequiredFeatures = ["Zvfh"] in 749 defm "" : RVVWidenBuiltinSet<NAME, "x", 750 [["vv", "w", "wvv"], 751 ["vf", "w", "wve"]]>; 752} 753 754multiclass RVVFloatingWidenBinBuiltinSetRoundingMode { 755 defm "" : RVVWidenBuiltinSet<NAME, "f", 756 [["vv", "w", "wvvu"], 757 ["vf", "w", "wveu"]]>; 758 let RequiredFeatures = ["Zvfh"] in 759 defm "" : RVVWidenBuiltinSet<NAME, "x", 760 [["vv", "w", "wvvu"], 761 ["vf", "w", "wveu"]]>; 762} 763 764multiclass RVVFloatingWidenOp0BinBuiltinSet { 765 defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "f", 766 [["wv", "w", "wwv"], 767 ["wf", "w", "wwe"]]>; 768 let RequiredFeatures = ["Zvfh"] in 769 defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "x", 770 [["wv", "w", "wwv"], 771 ["wf", "w", "wwe"]]>; 772} 773 774multiclass RVVFloatingWidenOp0BinBuiltinSetRoundingMode { 775 defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "f", 776 [["wv", "w", "wwvu"], 777 ["wf", "w", "wweu"]]>; 778 let RequiredFeatures = ["Zvfh"] in 779 defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "x", 780 [["wv", "w", "wwvu"], 781 ["wf", "w", "wweu"]]>; 782} 783