riscv_vector.td 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173
  1. //==--- riscv_vector.td - RISC-V V-ext Builtin 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 V-extension. See:
  10. //
  11. // https://github.com/riscv/rvv-intrinsic-doc
  12. //
  13. //===----------------------------------------------------------------------===//
  14. //===----------------------------------------------------------------------===//
  15. // Instruction definitions
  16. //===----------------------------------------------------------------------===//
  17. // Each record of the class RVVBuiltin defines a collection of builtins (i.e.
  18. // "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1",
  19. // "vadd_vv_i32m2", etc).
  20. //
  21. // The elements of this collection are defined by an instantiation process the
  22. // range of which is specified by the cross product of the LMUL attribute and
  23. // every element in the attribute TypeRange. By default builtins have LMUL = [1,
  24. // 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we
  25. // use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL.
  26. //
  27. // LMUL represents the fact that the types of values used by that builtin are
  28. // values generated by instructions that are executed under that LMUL. However,
  29. // this does not mean the builtin is necessarily lowered into an instruction
  30. // that executes under the specified LMUL. An example where this happens are
  31. // loads and stores of masks. A mask like `vbool8_t` can be generated, for
  32. // instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two
  33. // `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will
  34. // be performed under LMUL=1 because mask registers are not grouped.
  35. //
  36. // TypeRange is a non-empty sequence of basic types:
  37. //
  38. // c: int8_t (i8)
  39. // s: int16_t (i16)
  40. // i: int32_t (i32)
  41. // l: int64_t (i64)
  42. // x: float16_t (half)
  43. // f: float32_t (float)
  44. // d: float64_t (double)
  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. //
  71. // So for instance if t is "i", i.e. int, then "e" will yield int again. "v"
  72. // will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t.
  73. // Accordingly "w" would yield __rvv_int64m2_t.
  74. //
  75. // A type transformer can be prefixed by other non-primitive type transformers.
  76. //
  77. // P: constructs a pointer to the current type
  78. // C: adds const to the type
  79. // K: requires the integer type to be a constant expression
  80. // U: given an integer type or vector type, computes its unsigned variant
  81. // I: given a vector type, compute the vector type with integer type
  82. // elements of the same width
  83. // F: given a vector type, compute the vector type with floating-point type
  84. // elements of the same width
  85. // S: given a vector type, computes its equivalent one for LMUL=1. This is a
  86. // no-op if the vector was already LMUL=1
  87. // (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a
  88. // vector type (SEW and LMUL) and EEW (8/16/32/64), computes its
  89. // equivalent integer vector type with EEW and corresponding ELMUL (elmul =
  90. // (eew/sew) * lmul). For example, vector type is __rvv_float16m4
  91. // (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector
  92. // type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new
  93. // builtins if its equivalent type has illegal lmul.
  94. // (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another
  95. // vector type which only changed SEW as given value. Ignore to define a new
  96. // builtin if its equivalent type has illegal lmul or the SEW does not changed.
  97. // (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW
  98. // and LMUL), and computes another vector type which only changed LMUL as
  99. // given value. The new LMUL should be smaller than the old one. Ignore to
  100. // define a new builtin if its equivalent type has illegal lmul.
  101. // (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
  102. // and LMUL), and computes another vector type which only changed LMUL as
  103. // given value. The new LMUL should be larger than the old one. Ignore to
  104. // define a new builtin if its equivalent type has illegal lmul.
  105. //
  106. // Following with the example above, if t is "i", then "Ue" will yield unsigned
  107. // int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would
  108. // yield __rvv_float64m2_t, etc.
  109. //
  110. // Each builtin is then defined by applying each type in TypeRange against the
  111. // sequence of type transformers described in Suffix and Prototype.
  112. //
  113. // The name of the builtin is defined by the Name attribute (which defaults to
  114. // the name of the class) appended (separated with an underscore) the Suffix
  115. // attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il",
  116. // the builtin generated will be __builtin_rvv_foo_i32m1 and
  117. // __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one
  118. // type transformer (say "vv") each of the types is separated with an
  119. // underscore as in "__builtin_rvv_foo_i32m1_i32m1".
  120. //
  121. // The C/C++ prototype of the builtin is defined by the Prototype attribute.
  122. // Prototype is a non-empty sequence of type transformers, the first of which
  123. // is the return type of the builtin and the rest are the parameters of the
  124. // builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si"
  125. // a first builtin will have type
  126. // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin
  127. // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again
  128. // under LMUL=1).
  129. //
  130. // There are a number of attributes that are used to constraint the number and
  131. // shape of the builtins generated. Refer to the comments below for them.
  132. class RVVBuiltin<string suffix, string prototype, string type_range,
  133. string mangled_suffix = ""> {
  134. // Base name that will be prepended in __builtin_rvv_ and appended the
  135. // computed Suffix.
  136. string Name = NAME;
  137. // If not empty, each instantiated builtin will have this appended after an
  138. // underscore (_). It is instantiated like Prototype.
  139. string Suffix = suffix;
  140. // If empty, default MangledName is sub string of `Name` which end of first
  141. // '_'. For example, the default mangled name is `vadd` for Name `vadd_vv`.
  142. // It's used for describe some special naming cases.
  143. string MangledName = "";
  144. // If not empty, each MangledName will have this appended after an
  145. // underscore (_). It is instantiated like Prototype.
  146. string MangledSuffix = mangled_suffix;
  147. // The different variants of the builtin, parameterised with a type.
  148. string TypeRange = type_range;
  149. // We use each type described in TypeRange and LMUL with prototype to
  150. // instantiate a specific element of the set of builtins being defined.
  151. // Prototype attribute defines the C/C++ prototype of the builtin. It is a
  152. // non-empty sequence of type transformers, the first of which is the return
  153. // type of the builtin and the rest are the parameters of the builtin, in
  154. // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a
  155. // first builtin will have type
  156. // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin
  157. // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t).
  158. string Prototype = prototype;
  159. // This builtin has a masked form.
  160. bit HasMask = true;
  161. // If HasMask, this flag states that this builtin has a maskedoff operand. It
  162. // is always the first operand in builtin and IR intrinsic.
  163. bit HasMaskedOffOperand = true;
  164. // This builtin has a granted vector length parameter.
  165. bit HasVL = true;
  166. // There are several cases for specifying tail policy.
  167. // 1. Add tail policy argument to masked intrinsics. It may have the maskedoff
  168. // argument or not.
  169. // * Have the maskedoff argument: (HasPolicy = true, HasMaskedOffOperand = true)
  170. // Ex: vadd_vv_i8m1_mt(mask, maskedoff, op1, op2, vl, ta);
  171. // * Do not have the maskedoff argument: (HasPolicy = true, HasMaskedOffOperand = false)
  172. // Ex: vmacc_vv_i8m1_mt(mask, vd, vs1, vs2, vl, ta);
  173. // 2. Add dest argument for no mask intrinsics. (TODO)
  174. // Ex: vmv_v_x_i8m1_t(dest, src, vl);
  175. // 3. Always tail agnostic. (HasPolicy = false)
  176. // Ex: vmseq_vv_i8m1_b8_m(mask, maskedoff, op1, op2, vl);
  177. // The tail policy argument is located at the last position.
  178. bit HasPolicy = true;
  179. // This builtin supports non-masked function overloading api.
  180. // All masked operations support overloading api.
  181. bit HasNoMaskedOverloaded = true;
  182. // This builtin is valid for the given Log2LMULs.
  183. list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3];
  184. // Manual code in clang codegen riscv_vector_builtin_cg.inc
  185. code ManualCodegen = [{}];
  186. code ManualCodegenMask = [{}];
  187. // When emit the automatic clang codegen, it describes what types we have to use
  188. // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise,
  189. // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd
  190. // parameter of the unmasked version. k can't be the mask operand's position.
  191. list<int> IntrinsicTypes = [];
  192. // If these names are not empty, this is the ID of the LLVM intrinsic
  193. // we want to lower to.
  194. string IRName = NAME;
  195. // If HasMask, this is the ID of the LLVM intrinsic we want to lower to.
  196. string IRNameMask = NAME #"_mask";
  197. // If non empty, this is the code emitted in the header, otherwise
  198. // an automatic definition in header is emitted.
  199. string HeaderCode = "";
  200. // Features required to enable for this builtin.
  201. list<string> RequiredFeatures = [];
  202. // Number of fields for Load/Store Segment instructions.
  203. int NF = 1;
  204. }
  205. class RVVHeader
  206. {
  207. code HeaderCode;
  208. }
  209. //===----------------------------------------------------------------------===//
  210. // Basic classes with automatic codegen.
  211. //===----------------------------------------------------------------------===//
  212. class RVVOutBuiltin<string suffix, string prototype, string type_range>
  213. : RVVBuiltin<suffix, prototype, type_range> {
  214. let IntrinsicTypes = [-1];
  215. }
  216. class RVVOp0Builtin<string suffix, string prototype, string type_range>
  217. : RVVBuiltin<suffix, prototype, type_range> {
  218. let IntrinsicTypes = [0];
  219. }
  220. class RVVOutOp1Builtin<string suffix, string prototype, string type_range>
  221. : RVVBuiltin<suffix, prototype, type_range> {
  222. let IntrinsicTypes = [-1, 1];
  223. }
  224. class RVVOutOp0Op1Builtin<string suffix, string prototype, string type_range>
  225. : RVVBuiltin<suffix, prototype, type_range> {
  226. let IntrinsicTypes = [-1, 0, 1];
  227. }
  228. multiclass RVVBuiltinSet<string intrinsic_name, string type_range,
  229. list<list<string>> suffixes_prototypes,
  230. list<int> intrinsic_types> {
  231. let IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask",
  232. IntrinsicTypes = intrinsic_types in {
  233. foreach s_p = suffixes_prototypes in {
  234. let Name = NAME # "_" # s_p[0] in {
  235. defvar suffix = s_p[1];
  236. defvar prototype = s_p[2];
  237. def : RVVBuiltin<suffix, prototype, type_range>;
  238. }
  239. }
  240. }
  241. }
  242. // IntrinsicTypes is output, op0, op1 [-1, 0, 1]
  243. multiclass RVVOutOp0Op1BuiltinSet<string intrinsic_name, string type_range,
  244. list<list<string>> suffixes_prototypes>
  245. : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes,
  246. [-1, 0, 1]>;
  247. multiclass RVVOutBuiltinSet<string intrinsic_name, string type_range,
  248. list<list<string>> suffixes_prototypes>
  249. : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1]>;
  250. multiclass RVVOp0BuiltinSet<string intrinsic_name, string type_range,
  251. list<list<string>> suffixes_prototypes>
  252. : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0]>;
  253. // IntrinsicTypes is output, op1 [-1, 1]
  254. multiclass RVVOutOp1BuiltinSet<string intrinsic_name, string type_range,
  255. list<list<string>> suffixes_prototypes>
  256. : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1]>;
  257. multiclass RVVOp0Op1BuiltinSet<string intrinsic_name, string type_range,
  258. list<list<string>> suffixes_prototypes>
  259. : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1]>;
  260. multiclass RVVOutOp1Op2BuiltinSet<string intrinsic_name, string type_range,
  261. list<list<string>> suffixes_prototypes>
  262. : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1, 2]>;
  263. multiclass RVVSignedBinBuiltinSet
  264. : RVVOutOp1BuiltinSet<NAME, "csil",
  265. [["vv", "v", "vvv"],
  266. ["vx", "v", "vve"]]>;
  267. multiclass RVVUnsignedBinBuiltinSet
  268. : RVVOutOp1BuiltinSet<NAME, "csil",
  269. [["vv", "Uv", "UvUvUv"],
  270. ["vx", "Uv", "UvUvUe"]]>;
  271. multiclass RVVIntBinBuiltinSet
  272. : RVVSignedBinBuiltinSet,
  273. RVVUnsignedBinBuiltinSet;
  274. multiclass RVVSlideOneBuiltinSet
  275. : RVVOutOp1BuiltinSet<NAME, "csil",
  276. [["vx", "v", "vve"],
  277. ["vx", "Uv", "UvUve"]]>;
  278. multiclass RVVSignedShiftBuiltinSet
  279. : RVVOutOp1BuiltinSet<NAME, "csil",
  280. [["vv", "v", "vvUv"],
  281. ["vx", "v", "vvz"]]>;
  282. multiclass RVVUnsignedShiftBuiltinSet
  283. : RVVOutOp1BuiltinSet<NAME, "csil",
  284. [["vv", "Uv", "UvUvUv"],
  285. ["vx", "Uv", "UvUvz"]]>;
  286. multiclass RVVShiftBuiltinSet
  287. : RVVSignedShiftBuiltinSet,
  288. RVVUnsignedShiftBuiltinSet;
  289. let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
  290. multiclass RVVSignedNShiftBuiltinSet
  291. : RVVOutOp0Op1BuiltinSet<NAME, "csil",
  292. [["wv", "v", "vwUv"],
  293. ["wx", "v", "vwz"]]>;
  294. multiclass RVVUnsignedNShiftBuiltinSet
  295. : RVVOutOp0Op1BuiltinSet<NAME, "csil",
  296. [["wv", "Uv", "UvUwUv"],
  297. ["wx", "Uv", "UvUwz"]]>;
  298. }
  299. multiclass RVVCarryinBuiltinSet
  300. : RVVOutOp1BuiltinSet<NAME, "csil",
  301. [["vvm", "v", "vvvm"],
  302. ["vxm", "v", "vvem"],
  303. ["vvm", "Uv", "UvUvUvm"],
  304. ["vxm", "Uv", "UvUvUem"]]>;
  305. multiclass RVVCarryOutInBuiltinSet<string intrinsic_name>
  306. : RVVOp0Op1BuiltinSet<intrinsic_name, "csil",
  307. [["vvm", "vm", "mvvm"],
  308. ["vxm", "vm", "mvem"],
  309. ["vvm", "Uvm", "mUvUvm"],
  310. ["vxm", "Uvm", "mUvUem"]]>;
  311. multiclass RVVSignedMaskOutBuiltinSet
  312. : RVVOp0Op1BuiltinSet<NAME, "csil",
  313. [["vv", "vm", "mvv"],
  314. ["vx", "vm", "mve"]]>;
  315. multiclass RVVUnsignedMaskOutBuiltinSet
  316. : RVVOp0Op1BuiltinSet<NAME, "csil",
  317. [["vv", "Uvm", "mUvUv"],
  318. ["vx", "Uvm", "mUvUe"]]>;
  319. multiclass RVVIntMaskOutBuiltinSet
  320. : RVVSignedMaskOutBuiltinSet,
  321. RVVUnsignedMaskOutBuiltinSet;
  322. class RVVIntExt<string intrinsic_name, string suffix, string prototype,
  323. string type_range>
  324. : RVVBuiltin<suffix, prototype, type_range> {
  325. let IRName = intrinsic_name;
  326. let IRNameMask = intrinsic_name # "_mask";
  327. let MangledName = NAME;
  328. let IntrinsicTypes = [-1, 0];
  329. }
  330. let HasMaskedOffOperand = false in {
  331. multiclass RVVIntTerBuiltinSet {
  332. defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
  333. [["vv", "v", "vvvv"],
  334. ["vx", "v", "vvev"],
  335. ["vv", "Uv", "UvUvUvUv"],
  336. ["vx", "Uv", "UvUvUeUv"]]>;
  337. }
  338. multiclass RVVFloatingTerBuiltinSet {
  339. defm "" : RVVOutOp1BuiltinSet<NAME, "xfd",
  340. [["vv", "v", "vvvv"],
  341. ["vf", "v", "vvev"]]>;
  342. }
  343. }
  344. let HasMaskedOffOperand = false, Log2LMUL = [-2, -1, 0, 1, 2] in {
  345. multiclass RVVFloatingWidenTerBuiltinSet {
  346. defm "" : RVVOutOp1Op2BuiltinSet<NAME, "xf",
  347. [["vv", "w", "wwvv"],
  348. ["vf", "w", "wwev"]]>;
  349. }
  350. }
  351. multiclass RVVFloatingBinBuiltinSet
  352. : RVVOutOp1BuiltinSet<NAME, "xfd",
  353. [["vv", "v", "vvv"],
  354. ["vf", "v", "vve"]]>;
  355. multiclass RVVFloatingBinVFBuiltinSet
  356. : RVVOutOp1BuiltinSet<NAME, "xfd",
  357. [["vf", "v", "vve"]]>;
  358. multiclass RVVFloatingMaskOutBuiltinSet
  359. : RVVOp0Op1BuiltinSet<NAME, "xfd",
  360. [["vv", "vm", "mvv"],
  361. ["vf", "vm", "mve"]]>;
  362. multiclass RVVFloatingMaskOutVFBuiltinSet
  363. : RVVOp0Op1BuiltinSet<NAME, "fd",
  364. [["vf", "vm", "mve"]]>;
  365. class RVVMaskBinBuiltin : RVVOutBuiltin<"m", "mmm", "c"> {
  366. let Name = NAME # "_mm";
  367. let HasMask = false;
  368. }
  369. class RVVMaskUnaryBuiltin : RVVOutBuiltin<"m", "mm", "c"> {
  370. let Name = NAME # "_m";
  371. }
  372. class RVVMaskNullaryBuiltin : RVVOutBuiltin<"m", "m", "c"> {
  373. let Name = NAME # "_m";
  374. let HasMask = false;
  375. let HasNoMaskedOverloaded = false;
  376. }
  377. class RVVMaskOp0Builtin<string prototype> : RVVOp0Builtin<"m", prototype, "c"> {
  378. let Name = NAME # "_m";
  379. let HasMaskedOffOperand = false;
  380. }
  381. let HasMaskedOffOperand = false in {
  382. multiclass RVVSlideBuiltinSet {
  383. defm "" : RVVOutBuiltinSet<NAME, "csilxfd",
  384. [["vx","v", "vvvz"]]>;
  385. defm "" : RVVOutBuiltinSet<NAME, "csil",
  386. [["vx","Uv", "UvUvUvz"]]>;
  387. }
  388. }
  389. class RVVFloatingUnaryBuiltin<string builtin_suffix, string ir_suffix,
  390. string prototype>
  391. : RVVOutBuiltin<ir_suffix, prototype, "xfd"> {
  392. let Name = NAME # "_" # builtin_suffix;
  393. }
  394. class RVVFloatingUnaryVVBuiltin : RVVFloatingUnaryBuiltin<"v", "v", "vv">;
  395. class RVVConvBuiltin<string suffix, string prototype, string type_range,
  396. string mangled_name>
  397. : RVVBuiltin<suffix, prototype, type_range> {
  398. let IntrinsicTypes = [-1, 0];
  399. let MangledName = mangled_name;
  400. }
  401. class RVVConvToSignedBuiltin<string mangled_name>
  402. : RVVConvBuiltin<"Iv", "Ivv", "xfd", mangled_name>;
  403. class RVVConvToUnsignedBuiltin<string mangled_name>
  404. : RVVConvBuiltin<"Uv", "Uvv", "xfd", mangled_name>;
  405. class RVVConvToWidenSignedBuiltin<string mangled_name>
  406. : RVVConvBuiltin<"Iw", "Iwv", "xf", mangled_name>;
  407. class RVVConvToWidenUnsignedBuiltin<string mangled_name>
  408. : RVVConvBuiltin<"Uw", "Uwv", "xf", mangled_name>;
  409. class RVVConvToNarrowingSignedBuiltin<string mangled_name>
  410. : RVVConvBuiltin<"Iv", "IvFw", "csi", mangled_name>;
  411. class RVVConvToNarrowingUnsignedBuiltin<string mangled_name>
  412. : RVVConvBuiltin<"Uv", "UvFw", "csi", mangled_name>;
  413. let HasMaskedOffOperand = false in {
  414. multiclass RVVSignedReductionBuiltin {
  415. defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
  416. [["vs", "vSv", "SvSvvSv"]]>;
  417. }
  418. multiclass RVVUnsignedReductionBuiltin {
  419. defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
  420. [["vs", "UvUSv", "USvUSvUvUSv"]]>;
  421. }
  422. multiclass RVVFloatingReductionBuiltin {
  423. defm "" : RVVOutOp1BuiltinSet<NAME, "xfd",
  424. [["vs", "vSv", "SvSvvSv"]]>;
  425. }
  426. multiclass RVVFloatingWidenReductionBuiltin {
  427. defm "" : RVVOutOp1BuiltinSet<NAME, "xf",
  428. [["vs", "vSw", "SwSwvSw"]]>;
  429. }
  430. }
  431. multiclass RVVIntReductionBuiltinSet
  432. : RVVSignedReductionBuiltin,
  433. RVVUnsignedReductionBuiltin;
  434. // For widen operation which has different mangling name.
  435. multiclass RVVWidenBuiltinSet<string intrinsic_name, string type_range,
  436. list<list<string>> suffixes_prototypes> {
  437. let Log2LMUL = [-3, -2, -1, 0, 1, 2],
  438. IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask" in {
  439. foreach s_p = suffixes_prototypes in {
  440. let Name = NAME # "_" # s_p[0],
  441. MangledName = NAME # "_" # s_p[0] in {
  442. defvar suffix = s_p[1];
  443. defvar prototype = s_p[2];
  444. def : RVVOutOp0Op1Builtin<suffix, prototype, type_range>;
  445. }
  446. }
  447. }
  448. }
  449. // For widen operation with widen operand which has different mangling name.
  450. multiclass RVVWidenWOp0BuiltinSet<string intrinsic_name, string type_range,
  451. list<list<string>> suffixes_prototypes> {
  452. let Log2LMUL = [-3, -2, -1, 0, 1, 2],
  453. IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask" in {
  454. foreach s_p = suffixes_prototypes in {
  455. let Name = NAME # "_" # s_p[0],
  456. MangledName = NAME # "_" # s_p[0] in {
  457. defvar suffix = s_p[1];
  458. defvar prototype = s_p[2];
  459. def : RVVOutOp1Builtin<suffix, prototype, type_range>;
  460. }
  461. }
  462. }
  463. }
  464. multiclass RVVSignedWidenBinBuiltinSet
  465. : RVVWidenBuiltinSet<NAME, "csi",
  466. [["vv", "w", "wvv"],
  467. ["vx", "w", "wve"]]>;
  468. multiclass RVVSignedWidenOp0BinBuiltinSet
  469. : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
  470. [["wv", "w", "wwv"],
  471. ["wx", "w", "wwe"]]>;
  472. multiclass RVVUnsignedWidenBinBuiltinSet
  473. : RVVWidenBuiltinSet<NAME, "csi",
  474. [["vv", "Uw", "UwUvUv"],
  475. ["vx", "Uw", "UwUvUe"]]>;
  476. multiclass RVVUnsignedWidenOp0BinBuiltinSet
  477. : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
  478. [["wv", "Uw", "UwUwUv"],
  479. ["wx", "Uw", "UwUwUe"]]>;
  480. multiclass RVVFloatingWidenBinBuiltinSet
  481. : RVVWidenBuiltinSet<NAME, "xf",
  482. [["vv", "w", "wvv"],
  483. ["vf", "w", "wve"]]>;
  484. multiclass RVVFloatingWidenOp0BinBuiltinSet
  485. : RVVWidenWOp0BuiltinSet<NAME # "_w", "xf",
  486. [["wv", "w", "wwv"],
  487. ["wf", "w", "wwe"]]>;
  488. defvar TypeList = ["c","s","i","l","x","f","d"];
  489. defvar EEWList = [["8", "(Log2EEW:3)"],
  490. ["16", "(Log2EEW:4)"],
  491. ["32", "(Log2EEW:5)"],
  492. ["64", "(Log2EEW:6)"]];
  493. class IsFloat<string type> {
  494. bit val = !or(!eq(type, "x"), !eq(type, "f"), !eq(type, "d"));
  495. }
  496. let HasNoMaskedOverloaded = false,
  497. HasPolicy = false,
  498. ManualCodegen = [{
  499. IntrinsicTypes = {ResultType, Ops[1]->getType()};
  500. Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
  501. }],
  502. ManualCodegenMask= [{
  503. // Move mask to right before vl.
  504. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  505. IntrinsicTypes = {ResultType, Ops[3]->getType()};
  506. Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
  507. }] in {
  508. class RVVVLEMaskBuiltin : RVVBuiltin<"m", "mPCUe", "c"> {
  509. let Name = "vlm_v";
  510. let IRName = "vlm";
  511. let HasMask = false;
  512. }
  513. }
  514. let HasNoMaskedOverloaded = false,
  515. ManualCodegen = [{
  516. IntrinsicTypes = {ResultType, Ops[1]->getType()};
  517. Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
  518. Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
  519. }],
  520. ManualCodegenMask= [{
  521. // Move mask to right before vl.
  522. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  523. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  524. IntrinsicTypes = {ResultType, Ops[3]->getType()};
  525. Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
  526. }] in {
  527. multiclass RVVVLEBuiltin<list<string> types> {
  528. let Name = NAME # "_v",
  529. IRName = "vle",
  530. IRNameMask ="vle_mask" in {
  531. foreach type = types in {
  532. def : RVVBuiltin<"v", "vPCe", type>;
  533. if !not(IsFloat<type>.val) then {
  534. def : RVVBuiltin<"Uv", "UvPCUe", type>;
  535. }
  536. }
  537. }
  538. }
  539. }
  540. multiclass RVVVLEFFBuiltin<list<string> types> {
  541. let Name = NAME # "_v",
  542. IRName = "vleff",
  543. IRNameMask = "vleff_mask",
  544. HasNoMaskedOverloaded = false,
  545. ManualCodegen = [{
  546. {
  547. IntrinsicTypes = {ResultType, Ops[2]->getType()};
  548. Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
  549. Value *NewVL = Ops[1];
  550. Ops.erase(Ops.begin() + 1);
  551. Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
  552. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  553. llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
  554. llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
  555. // Store new_vl.
  556. clang::CharUnits Align =
  557. CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType());
  558. Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {1}),
  559. Address(NewVL, Align));
  560. return V;
  561. }
  562. }],
  563. ManualCodegenMask = [{
  564. {
  565. // Move mask to right before vl.
  566. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  567. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  568. IntrinsicTypes = {ResultType, Ops[4]->getType()};
  569. Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
  570. Value *NewVL = Ops[2];
  571. Ops.erase(Ops.begin() + 2);
  572. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  573. llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
  574. llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
  575. // Store new_vl.
  576. clang::CharUnits Align =
  577. CGM.getNaturalPointeeTypeAlignment(E->getArg(3)->getType());
  578. Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {1}),
  579. Address(NewVL, Align));
  580. return V;
  581. }
  582. }] in {
  583. foreach type = types in {
  584. def : RVVBuiltin<"v", "vPCePz", type>;
  585. // Skip floating types for unsigned versions.
  586. if !not(IsFloat<type>.val) then {
  587. def : RVVBuiltin<"Uv", "UvPCUePz", type>;
  588. }
  589. }
  590. }
  591. }
  592. multiclass RVVVLSEBuiltin<list<string> types> {
  593. let Name = NAME # "_v",
  594. IRName = "vlse",
  595. IRNameMask ="vlse_mask",
  596. HasNoMaskedOverloaded = false,
  597. ManualCodegen = [{
  598. IntrinsicTypes = {ResultType, Ops[2]->getType()};
  599. Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
  600. Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
  601. }],
  602. ManualCodegenMask= [{
  603. // Move mask to right before vl.
  604. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  605. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  606. IntrinsicTypes = {ResultType, Ops[4]->getType()};
  607. Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
  608. }] in {
  609. foreach type = types in {
  610. def : RVVBuiltin<"v", "vPCet", type>;
  611. if !not(IsFloat<type>.val) then {
  612. def : RVVBuiltin<"Uv", "UvPCUet", type>;
  613. }
  614. }
  615. }
  616. }
  617. multiclass RVVIndexedLoad<string op> {
  618. let ManualCodegen = [{
  619. IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()};
  620. Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
  621. Ops.insert(Ops.begin(), llvm::UndefValue::get(ResultType));
  622. }],
  623. ManualCodegenMask = [{
  624. // Move mask to right before vl.
  625. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  626. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  627. IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops[4]->getType()};
  628. Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
  629. }] in {
  630. foreach type = TypeList in {
  631. foreach eew_list = EEWList[0-2] in {
  632. defvar eew = eew_list[0];
  633. defvar eew_type = eew_list[1];
  634. let Name = op # eew # "_v", IRName = op, IRNameMask = op # "_mask" in {
  635. def: RVVBuiltin<"v", "vPCe" # eew_type # "Uv", type>;
  636. if !not(IsFloat<type>.val) then {
  637. def: RVVBuiltin<"Uv", "UvPCUe" # eew_type # "Uv", type>;
  638. }
  639. }
  640. }
  641. defvar eew64 = "64";
  642. defvar eew64_type = "(Log2EEW:6)";
  643. let Name = op # eew64 # "_v", IRName = op, IRNameMask = op # "_mask",
  644. RequiredFeatures = ["RV64"] in {
  645. def: RVVBuiltin<"v", "vPCe" # eew64_type # "Uv", type>;
  646. if !not(IsFloat<type>.val) then {
  647. def: RVVBuiltin<"Uv", "UvPCUe" # eew64_type # "Uv", type>;
  648. }
  649. }
  650. }
  651. }
  652. }
  653. let HasMaskedOffOperand = false,
  654. HasPolicy = false,
  655. ManualCodegen = [{
  656. // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl)
  657. std::swap(Ops[0], Ops[1]);
  658. Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
  659. IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType()};
  660. }],
  661. ManualCodegenMask= [{
  662. // Builtin: (mask, ptr, value, vl). Intrinsic: (value, ptr, mask, vl)
  663. std::swap(Ops[0], Ops[2]);
  664. Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
  665. IntrinsicTypes = {Ops[0]->getType(), Ops[3]->getType()};
  666. }] in {
  667. class RVVVSEMaskBuiltin : RVVBuiltin<"m", "0PUem", "c"> {
  668. let Name = "vsm_v";
  669. let IRName = "vsm";
  670. let HasMask = false;
  671. }
  672. multiclass RVVVSEBuiltin<list<string> types> {
  673. let Name = NAME # "_v",
  674. IRName = "vse",
  675. IRNameMask = "vse_mask" in {
  676. foreach type = types in {
  677. def : RVVBuiltin<"v", "0Pev", type>;
  678. if !not(IsFloat<type>.val) then {
  679. def : RVVBuiltin<"Uv", "0PUeUv", type>;
  680. }
  681. }
  682. }
  683. }
  684. }
  685. multiclass RVVVSSEBuiltin<list<string> types> {
  686. let Name = NAME # "_v",
  687. IRName = "vsse",
  688. IRNameMask = "vsse_mask",
  689. HasMaskedOffOperand = false,
  690. HasPolicy = false,
  691. ManualCodegen = [{
  692. // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
  693. std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
  694. Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
  695. IntrinsicTypes = {Ops[0]->getType(), Ops[3]->getType()};
  696. }],
  697. ManualCodegenMask= [{
  698. // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, mask, vl)
  699. std::swap(Ops[0], Ops[3]);
  700. Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
  701. IntrinsicTypes = {Ops[0]->getType(), Ops[4]->getType()};
  702. }] in {
  703. foreach type = types in {
  704. def : RVVBuiltin<"v", "0Petv", type>;
  705. if !not(IsFloat<type>.val) then {
  706. def : RVVBuiltin<"Uv", "0PUetUv", type>;
  707. }
  708. }
  709. }
  710. }
  711. multiclass RVVIndexedStore<string op> {
  712. let HasMaskedOffOperand = false,
  713. HasPolicy = false,
  714. ManualCodegen = [{
  715. // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl)
  716. std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
  717. Ops[1] = Builder.CreateBitCast(Ops[1],Ops[0]->getType()->getPointerTo());
  718. IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType(), Ops[3]->getType()};
  719. }],
  720. ManualCodegenMask= [{
  721. // Builtin: (mask, ptr, index, value, vl). Intrinsic: (value, ptr, index, mask, vl)
  722. std::swap(Ops[0], Ops[3]);
  723. Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
  724. IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType(), Ops[4]->getType()};
  725. }] in {
  726. foreach type = TypeList in {
  727. foreach eew_list = EEWList[0-2] in {
  728. defvar eew = eew_list[0];
  729. defvar eew_type = eew_list[1];
  730. let Name = op # eew # "_v", IRName = op, IRNameMask = op # "_mask" in {
  731. def : RVVBuiltin<"v", "0Pe" # eew_type # "Uvv", type>;
  732. if !not(IsFloat<type>.val) then {
  733. def : RVVBuiltin<"Uv", "0PUe" # eew_type # "UvUv", type>;
  734. }
  735. }
  736. }
  737. defvar eew64 = "64";
  738. defvar eew64_type = "(Log2EEW:6)";
  739. let Name = op # eew64 # "_v", IRName = op, IRNameMask = op # "_mask",
  740. RequiredFeatures = ["RV64"] in {
  741. def : RVVBuiltin<"v", "0Pe" # eew64_type # "Uvv", type>;
  742. if !not(IsFloat<type>.val) then {
  743. def : RVVBuiltin<"Uv", "0PUe" # eew64_type # "UvUv", type>;
  744. }
  745. }
  746. }
  747. }
  748. }
  749. defvar NFList = [2, 3, 4, 5, 6, 7, 8];
  750. class PVString<int nf, bit signed> {
  751. string S =
  752. !cond(!eq(nf, 2): !if(signed, "PvPv", "PUvPUv"),
  753. !eq(nf, 3): !if(signed, "PvPvPv", "PUvPUvPUv"),
  754. !eq(nf, 4): !if(signed, "PvPvPvPv", "PUvPUvPUvPUv"),
  755. !eq(nf, 5): !if(signed, "PvPvPvPvPv", "PUvPUvPUvPUvPUv"),
  756. !eq(nf, 6): !if(signed, "PvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUv"),
  757. !eq(nf, 7): !if(signed, "PvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUv"),
  758. !eq(nf, 8): !if(signed, "PvPvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUvPUv"));
  759. }
  760. multiclass RVVUnitStridedSegLoad<string op> {
  761. foreach type = TypeList in {
  762. defvar eew = !cond(!eq(type, "c") : "8",
  763. !eq(type, "s") : "16",
  764. !eq(type, "i") : "32",
  765. !eq(type, "l") : "64",
  766. !eq(type, "x") : "16",
  767. !eq(type, "f") : "32",
  768. !eq(type, "d") : "64");
  769. foreach nf = NFList in {
  770. let Name = op # nf # "e" # eew # "_v",
  771. IRName = op # nf,
  772. IRNameMask = op # nf # "_mask",
  773. NF = nf,
  774. HasNoMaskedOverloaded = false,
  775. ManualCodegen = [{
  776. {
  777. // builtin: (val0 address, val1 address, ..., ptr, vl)
  778. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  779. Ops[NF + 1]->getType()};
  780. // intrinsic: (ptr, vl)
  781. llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1]};
  782. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  783. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  784. clang::CharUnits Align =
  785. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  786. llvm::Value *V;
  787. for (unsigned I = 0; I < NF; ++I) {
  788. V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  789. Address(Ops[I], Align));
  790. }
  791. return V;
  792. }
  793. }],
  794. ManualCodegenMask = [{
  795. {
  796. // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, vl)
  797. // intrinsic: (maskedoff0, ..., ptr, mask, vl)
  798. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  799. Ops[2 * NF + 2]->getType()};
  800. SmallVector<llvm::Value*, 12> Operands;
  801. for (unsigned I = 0; I < NF; ++I)
  802. Operands.push_back(Ops[NF + I + 1]);
  803. Operands.push_back(Ops[2 * NF + 1]);
  804. Operands.push_back(Ops[NF]);
  805. Operands.push_back(Ops[2 * NF + 2]);
  806. Operands.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  807. assert(Operands.size() == NF + 4);
  808. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  809. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  810. clang::CharUnits Align =
  811. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  812. llvm::Value *V;
  813. for (unsigned I = 0; I < NF; ++I) {
  814. V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  815. Address(Ops[I], Align));
  816. }
  817. return V;
  818. }
  819. }] in {
  820. defvar PV = PVString<nf, /*signed=*/true>.S;
  821. defvar PUV = PVString<nf, /*signed=*/false>.S;
  822. def : RVVBuiltin<"v", "0" # PV # "PCe", type>;
  823. if !not(IsFloat<type>.val) then {
  824. def : RVVBuiltin<"Uv", "0" # PUV # "PCUe", type>;
  825. }
  826. }
  827. }
  828. }
  829. }
  830. multiclass RVVUnitStridedSegLoadFF<string op> {
  831. foreach type = TypeList in {
  832. defvar eew = !cond(!eq(type, "c") : "8",
  833. !eq(type, "s") : "16",
  834. !eq(type, "i") : "32",
  835. !eq(type, "l") : "64",
  836. !eq(type, "x") : "16",
  837. !eq(type, "f") : "32",
  838. !eq(type, "d") : "64");
  839. foreach nf = NFList in {
  840. let Name = op # nf # "e" # eew # "ff_v",
  841. IRName = op # nf # "ff",
  842. IRNameMask = op # nf # "ff_mask",
  843. NF = nf,
  844. HasNoMaskedOverloaded = false,
  845. ManualCodegen = [{
  846. {
  847. // builtin: (val0 address, val1 address, ..., ptr, new_vl, vl)
  848. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  849. Ops[NF + 2]->getType()};
  850. // intrinsic: (ptr, vl)
  851. llvm::Value *Operands[] = {Ops[NF], Ops[NF + 2]};
  852. Value *NewVL = Ops[NF + 1];
  853. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  854. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  855. clang::CharUnits Align =
  856. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  857. for (unsigned I = 0; I < NF; ++I) {
  858. Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  859. Address(Ops[I], Align));
  860. }
  861. // Store new_vl.
  862. return Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {NF}),
  863. Address(NewVL, Align));
  864. }
  865. }],
  866. ManualCodegenMask = [{
  867. {
  868. // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, new_vl, vl)
  869. // intrinsic: (maskedoff0, ..., ptr, mask, vl)
  870. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  871. Ops[2 * NF + 3]->getType()};
  872. SmallVector<llvm::Value*, 12> Operands;
  873. for (unsigned I = 0; I < NF; ++I)
  874. Operands.push_back(Ops[NF + I + 1]);
  875. Operands.push_back(Ops[2 * NF + 1]);
  876. Operands.push_back(Ops[NF]);
  877. Operands.push_back(Ops[2 * NF + 3]);
  878. Operands.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  879. Value *NewVL = Ops[2 * NF + 2];
  880. assert(Operands.size() == NF + 4);
  881. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  882. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  883. clang::CharUnits Align =
  884. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  885. for (unsigned I = 0; I < NF; ++I) {
  886. Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  887. Address(Ops[I], Align));
  888. }
  889. // Store new_vl.
  890. return Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {NF}),
  891. Address(NewVL, Align));
  892. }
  893. }] in {
  894. defvar PV = PVString<nf, /*signed=*/true>.S;
  895. defvar PUV = PVString<nf, /*signed=*/false>.S;
  896. def : RVVBuiltin<"v", "0" # PV # "PCe" # "Pz", type>;
  897. if !not(IsFloat<type>.val) then {
  898. def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "Pz", type>;
  899. }
  900. }
  901. }
  902. }
  903. }
  904. multiclass RVVStridedSegLoad<string op> {
  905. foreach type = TypeList in {
  906. defvar eew = !cond(!eq(type, "c") : "8",
  907. !eq(type, "s") : "16",
  908. !eq(type, "i") : "32",
  909. !eq(type, "l") : "64",
  910. !eq(type, "x") : "16",
  911. !eq(type, "f") : "32",
  912. !eq(type, "d") : "64");
  913. foreach nf = NFList in {
  914. let Name = op # nf # "e" # eew # "_v",
  915. IRName = op # nf,
  916. IRNameMask = op # nf # "_mask",
  917. NF = nf,
  918. HasNoMaskedOverloaded = false,
  919. ManualCodegen = [{
  920. {
  921. // builtin: (val0 address, val1 address, ..., ptr, stride, vl)
  922. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  923. Ops[NF + 2]->getType()};
  924. // intrinsic: (ptr, stride, vl)
  925. llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1], Ops[NF + 2]};
  926. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  927. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  928. clang::CharUnits Align =
  929. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  930. llvm::Value *V;
  931. for (unsigned I = 0; I < NF; ++I) {
  932. V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  933. Address(Ops[I], Align));
  934. }
  935. return V;
  936. }
  937. }],
  938. ManualCodegenMask = [{
  939. {
  940. // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, stride, vl)
  941. // intrinsic: (maskedoff0, ..., ptr, stride, mask, vl)
  942. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  943. Ops[2 * NF + 3]->getType()};
  944. SmallVector<llvm::Value*, 12> Operands;
  945. for (unsigned I = 0; I < NF; ++I)
  946. Operands.push_back(Ops[NF + I + 1]);
  947. Operands.push_back(Ops[2 * NF + 1]);
  948. Operands.push_back(Ops[2 * NF + 2]);
  949. Operands.push_back(Ops[NF]);
  950. Operands.push_back(Ops[2 * NF + 3]);
  951. Operands.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  952. assert(Operands.size() == NF + 5);
  953. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  954. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  955. clang::CharUnits Align =
  956. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  957. llvm::Value *V;
  958. for (unsigned I = 0; I < NF; ++I) {
  959. V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  960. Address(Ops[I], Align));
  961. }
  962. return V;
  963. }
  964. }] in {
  965. defvar PV = PVString<nf, /*signed=*/true>.S;
  966. defvar PUV = PVString<nf, /*signed=*/false>.S;
  967. def : RVVBuiltin<"v", "0" # PV # "PCe" # "t", type>;
  968. if !not(IsFloat<type>.val) then {
  969. def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "t", type>;
  970. }
  971. }
  972. }
  973. }
  974. }
  975. multiclass RVVIndexedSegLoad<string op> {
  976. foreach type = TypeList in {
  977. foreach eew_info = EEWList in {
  978. defvar eew = eew_info[0];
  979. defvar eew_type = eew_info[1];
  980. foreach nf = NFList in {
  981. let Name = op # nf # "ei" # eew # "_v",
  982. IRName = op # nf,
  983. IRNameMask = op # nf # "_mask",
  984. NF = nf,
  985. ManualCodegen = [{
  986. {
  987. // builtin: (val0 address, val1 address, ..., ptr, index, vl)
  988. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  989. Ops[NF + 1]->getType(), Ops[NF + 2]->getType()};
  990. // intrinsic: (ptr, index, vl)
  991. llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1], Ops[NF + 2]};
  992. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  993. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  994. clang::CharUnits Align =
  995. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  996. llvm::Value *V;
  997. for (unsigned I = 0; I < NF; ++I) {
  998. V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  999. Address(Ops[I], Align));
  1000. }
  1001. return V;
  1002. }
  1003. }],
  1004. ManualCodegenMask = [{
  1005. {
  1006. // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, index, vl)
  1007. IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()),
  1008. Ops[2 * NF + 2]->getType(), Ops[2 * NF + 3]->getType()};
  1009. // intrinsic: (maskedoff0, ..., ptr, index, mask, vl)
  1010. SmallVector<llvm::Value*, 12> Operands;
  1011. for (unsigned I = 0; I < NF; ++I)
  1012. Operands.push_back(Ops[NF + I + 1]);
  1013. Operands.push_back(Ops[2 * NF + 1]);
  1014. Operands.push_back(Ops[2 * NF + 2]);
  1015. Operands.push_back(Ops[NF]);
  1016. Operands.push_back(Ops[2 * NF + 3]);
  1017. Operands.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  1018. assert(Operands.size() == NF + 5);
  1019. llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
  1020. llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
  1021. clang::CharUnits Align =
  1022. CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType());
  1023. llvm::Value *V;
  1024. for (unsigned I = 0; I < NF; ++I) {
  1025. V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
  1026. Address(Ops[I], Align));
  1027. }
  1028. return V;
  1029. }
  1030. }] in {
  1031. defvar PV = PVString<nf, /*signed=*/true>.S;
  1032. defvar PUV = PVString<nf, /*signed=*/false>.S;
  1033. def : RVVBuiltin<"v", "0" # PV # "PCe" # eew_type # "Uv", type>;
  1034. if !not(IsFloat<type>.val) then {
  1035. def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # eew_type # "Uv", type>;
  1036. }
  1037. }
  1038. }
  1039. }
  1040. }
  1041. }
  1042. class VString<int nf, bit signed> {
  1043. string S = !cond(!eq(nf, 2): !if(signed, "vv", "UvUv"),
  1044. !eq(nf, 3): !if(signed, "vvv", "UvUvUv"),
  1045. !eq(nf, 4): !if(signed, "vvvv", "UvUvUvUv"),
  1046. !eq(nf, 5): !if(signed, "vvvvv", "UvUvUvUvUv"),
  1047. !eq(nf, 6): !if(signed, "vvvvvv", "UvUvUvUvUvUv"),
  1048. !eq(nf, 7): !if(signed, "vvvvvvv", "UvUvUvUvUvUvUv"),
  1049. !eq(nf, 8): !if(signed, "vvvvvvvv", "UvUvUvUvUvUvUvUv"));
  1050. }
  1051. multiclass RVVUnitStridedSegStore<string op> {
  1052. foreach type = TypeList in {
  1053. defvar eew = !cond(!eq(type, "c") : "8",
  1054. !eq(type, "s") : "16",
  1055. !eq(type, "i") : "32",
  1056. !eq(type, "l") : "64",
  1057. !eq(type, "x") : "16",
  1058. !eq(type, "f") : "32",
  1059. !eq(type, "d") : "64");
  1060. foreach nf = NFList in {
  1061. let Name = op # nf # "e" # eew # "_v",
  1062. IRName = op # nf,
  1063. IRNameMask = op # nf # "_mask",
  1064. NF = nf,
  1065. HasMaskedOffOperand = false,
  1066. HasPolicy = false,
  1067. ManualCodegen = [{
  1068. {
  1069. // Builtin: (ptr, val0, val1, ..., vl)
  1070. // Intrinsic: (val0, val1, ..., ptr, vl)
  1071. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  1072. IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()};
  1073. assert(Ops.size() == NF + 2);
  1074. }
  1075. }],
  1076. ManualCodegenMask = [{
  1077. {
  1078. // Builtin: (mask, ptr, val0, val1, ..., vl)
  1079. // Intrinsic: (val0, val1, ..., ptr, mask, vl)
  1080. std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1);
  1081. std::swap(Ops[NF], Ops[NF + 1]);
  1082. IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 2]->getType()};
  1083. assert(Ops.size() == NF + 3);
  1084. }
  1085. }] in {
  1086. defvar V = VString<nf, /*signed=*/true>.S;
  1087. defvar UV = VString<nf, /*signed=*/false>.S;
  1088. def : RVVBuiltin<"v", "0Pe" # V, type>;
  1089. if !not(IsFloat<type>.val) then {
  1090. def : RVVBuiltin<"Uv", "0PUe" # UV, type>;
  1091. }
  1092. }
  1093. }
  1094. }
  1095. }
  1096. multiclass RVVStridedSegStore<string op> {
  1097. foreach type = TypeList in {
  1098. defvar eew = !cond(!eq(type, "c") : "8",
  1099. !eq(type, "s") : "16",
  1100. !eq(type, "i") : "32",
  1101. !eq(type, "l") : "64",
  1102. !eq(type, "x") : "16",
  1103. !eq(type, "f") : "32",
  1104. !eq(type, "d") : "64");
  1105. foreach nf = NFList in {
  1106. let Name = op # nf # "e" # eew # "_v",
  1107. IRName = op # nf,
  1108. IRNameMask = op # nf # "_mask",
  1109. NF = nf,
  1110. HasMaskedOffOperand = false,
  1111. HasPolicy = false,
  1112. ManualCodegen = [{
  1113. {
  1114. // Builtin: (ptr, stride, val0, val1, ..., vl).
  1115. // Intrinsic: (val0, val1, ..., ptr, stride, vl)
  1116. std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1);
  1117. IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()};
  1118. assert(Ops.size() == NF + 3);
  1119. }
  1120. }],
  1121. ManualCodegenMask = [{
  1122. {
  1123. // Builtin: (mask, ptr, stride, val0, val1, ..., vl).
  1124. // Intrinsic: (val0, val1, ..., ptr, stride, mask, vl)
  1125. std::rotate(Ops.begin(), Ops.begin() + 3, Ops.end() - 1);
  1126. std::rotate(Ops.begin() + NF, Ops.begin() + NF + 1, Ops.begin() + NF + 3);
  1127. IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()};
  1128. assert(Ops.size() == NF + 4);
  1129. }
  1130. }] in {
  1131. defvar V = VString<nf, /*signed=*/true>.S;
  1132. defvar UV = VString<nf, /*signed=*/false>.S;
  1133. def : RVVBuiltin<"v", "0Pet" # V, type>;
  1134. if !not(IsFloat<type>.val) then {
  1135. def : RVVBuiltin<"Uv", "0PUet" # UV, type>;
  1136. }
  1137. }
  1138. }
  1139. }
  1140. }
  1141. multiclass RVVIndexedSegStore<string op> {
  1142. foreach type = TypeList in {
  1143. foreach eew_info = EEWList in {
  1144. defvar eew = eew_info[0];
  1145. defvar eew_type = eew_info[1];
  1146. foreach nf = NFList in {
  1147. let Name = op # nf # "ei" # eew # "_v",
  1148. IRName = op # nf,
  1149. IRNameMask = op # nf # "_mask",
  1150. NF = nf,
  1151. HasMaskedOffOperand = false,
  1152. HasPolicy = false,
  1153. ManualCodegen = [{
  1154. {
  1155. // Builtin: (ptr, index, val0, val1, ..., vl)
  1156. // Intrinsic: (val0, val1, ..., ptr, index, vl)
  1157. std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1);
  1158. IntrinsicTypes = {Ops[0]->getType(),
  1159. Ops[NF + 1]->getType(), Ops[NF + 2]->getType()};
  1160. assert(Ops.size() == NF + 3);
  1161. }
  1162. }],
  1163. ManualCodegenMask = [{
  1164. {
  1165. // Builtin: (mask, ptr, index, val0, val1, ..., vl)
  1166. // Intrinsic: (val0, val1, ..., ptr, index, mask, vl)
  1167. std::rotate(Ops.begin(), Ops.begin() + 3, Ops.end() - 1);
  1168. std::rotate(Ops.begin() + NF, Ops.begin() + NF + 1, Ops.begin() + NF + 3);
  1169. IntrinsicTypes = {Ops[0]->getType(),
  1170. Ops[NF + 1]->getType(), Ops[NF + 3]->getType()};
  1171. assert(Ops.size() == NF + 4);
  1172. }
  1173. }] in {
  1174. defvar V = VString<nf, /*signed=*/true>.S;
  1175. defvar UV = VString<nf, /*signed=*/false>.S;
  1176. def : RVVBuiltin<"v", "0Pe" # eew_type # "Uv" # V, type>;
  1177. if !not(IsFloat<type>.val) then {
  1178. def : RVVBuiltin<"Uv", "0PUe" # eew_type # "Uv" # UV, type>;
  1179. }
  1180. }
  1181. }
  1182. }
  1183. }
  1184. }
  1185. multiclass RVVPseudoUnaryBuiltin<string IR, string type_range> {
  1186. let Name = NAME,
  1187. IRName = IR,
  1188. IRNameMask = IR # "_mask",
  1189. ManualCodegen = [{
  1190. {
  1191. // op1, vl
  1192. IntrinsicTypes = {ResultType,
  1193. cast<llvm::VectorType>(ResultType)->getElementType(),
  1194. Ops[1]->getType()};
  1195. Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[1]));
  1196. break;
  1197. }
  1198. }],
  1199. ManualCodegenMask = [{
  1200. {
  1201. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  1202. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  1203. // maskedoff, op1, mask, vl
  1204. IntrinsicTypes = {ResultType,
  1205. cast<llvm::VectorType>(ResultType)->getElementType(),
  1206. Ops[3]->getType()};
  1207. Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[1]));
  1208. break;
  1209. }
  1210. }] in {
  1211. def : RVVBuiltin<"v", "vv", type_range>;
  1212. }
  1213. }
  1214. multiclass RVVPseudoVNotBuiltin<string IR, string type_range> {
  1215. let Name = NAME,
  1216. IRName = IR,
  1217. IRNameMask = IR # "_mask",
  1218. ManualCodegen = [{
  1219. {
  1220. // op1, vl
  1221. IntrinsicTypes = {ResultType,
  1222. cast<llvm::VectorType>(ResultType)->getElementType(),
  1223. Ops[1]->getType()};
  1224. Ops.insert(Ops.begin() + 1,
  1225. llvm::Constant::getAllOnesValue(IntrinsicTypes[1]));
  1226. break;
  1227. }
  1228. }],
  1229. ManualCodegenMask = [{
  1230. {
  1231. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  1232. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  1233. // maskedoff, op1, mask, vl
  1234. IntrinsicTypes = {ResultType,
  1235. cast<llvm::VectorType>(ResultType)->getElementType(),
  1236. Ops[3]->getType()};
  1237. Ops.insert(Ops.begin() + 2,
  1238. llvm::Constant::getAllOnesValue(IntrinsicTypes[1]));
  1239. break;
  1240. }
  1241. }] in {
  1242. def : RVVBuiltin<"v", "vv", type_range>;
  1243. def : RVVBuiltin<"Uv", "UvUv", type_range>;
  1244. }
  1245. }
  1246. multiclass RVVPseudoMaskBuiltin<string IR, string type_range> {
  1247. let Name = NAME,
  1248. IRName = IR,
  1249. HasMask = false,
  1250. ManualCodegen = [{
  1251. {
  1252. // op1, vl
  1253. IntrinsicTypes = {ResultType,
  1254. Ops[1]->getType()};
  1255. Ops.insert(Ops.begin() + 1, Ops[0]);
  1256. break;
  1257. }
  1258. }] in {
  1259. def : RVVBuiltin<"m", "mm", type_range>;
  1260. }
  1261. }
  1262. multiclass RVVPseudoVFUnaryBuiltin<string IR, string type_range> {
  1263. let Name = NAME,
  1264. IRName = IR,
  1265. IRNameMask = IR # "_mask",
  1266. ManualCodegen = [{
  1267. {
  1268. // op1, vl
  1269. IntrinsicTypes = {ResultType,
  1270. Ops[0]->getType(), Ops[1]->getType()};
  1271. Ops.insert(Ops.begin() + 1, Ops[0]);
  1272. break;
  1273. }
  1274. }],
  1275. ManualCodegenMask = [{
  1276. {
  1277. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  1278. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  1279. // maskedoff, op1, mask, vl
  1280. IntrinsicTypes = {ResultType,
  1281. Ops[1]->getType(),
  1282. Ops[3]->getType()};
  1283. Ops.insert(Ops.begin() + 2, Ops[1]);
  1284. break;
  1285. }
  1286. }] in {
  1287. def : RVVBuiltin<"v", "vv", type_range>;
  1288. }
  1289. }
  1290. multiclass RVVPseudoVWCVTBuiltin<string IR, string MName, string type_range,
  1291. list<list<string>> suffixes_prototypes> {
  1292. let Name = NAME,
  1293. MangledName = MName,
  1294. IRName = IR,
  1295. IRNameMask = IR # "_mask",
  1296. ManualCodegen = [{
  1297. {
  1298. // op1, vl
  1299. IntrinsicTypes = {ResultType,
  1300. Ops[0]->getType(),
  1301. cast<llvm::VectorType>(Ops[0]->getType())->getElementType(),
  1302. Ops[1]->getType()};
  1303. Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[2]));
  1304. break;
  1305. }
  1306. }],
  1307. ManualCodegenMask = [{
  1308. {
  1309. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  1310. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  1311. // maskedoff, op1, mask, vl
  1312. IntrinsicTypes = {ResultType,
  1313. Ops[1]->getType(),
  1314. cast<llvm::VectorType>(Ops[1]->getType())->getElementType(),
  1315. Ops[3]->getType()};
  1316. Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[2]));
  1317. break;
  1318. }
  1319. }] in {
  1320. foreach s_p = suffixes_prototypes in {
  1321. def : RVVBuiltin<s_p[0], s_p[1], type_range>;
  1322. }
  1323. }
  1324. }
  1325. multiclass RVVPseudoVNCVTBuiltin<string IR, string MName, string type_range,
  1326. list<list<string>> suffixes_prototypes> {
  1327. let Name = NAME,
  1328. MangledName = MName,
  1329. IRName = IR,
  1330. IRNameMask = IR # "_mask",
  1331. ManualCodegen = [{
  1332. {
  1333. // op1, vl
  1334. IntrinsicTypes = {ResultType,
  1335. Ops[0]->getType(),
  1336. Ops[1]->getType(),
  1337. Ops[1]->getType()};
  1338. Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[2]));
  1339. break;
  1340. }
  1341. }],
  1342. ManualCodegenMask = [{
  1343. {
  1344. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
  1345. Ops.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED));
  1346. // maskedoff, op1, mask, vl
  1347. IntrinsicTypes = {ResultType,
  1348. Ops[1]->getType(),
  1349. Ops[3]->getType(),
  1350. Ops[3]->getType()};
  1351. Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[2]));
  1352. break;
  1353. }
  1354. }] in {
  1355. foreach s_p = suffixes_prototypes in {
  1356. def : RVVBuiltin<s_p[0], s_p[1], type_range>;
  1357. }
  1358. }
  1359. }
  1360. // 6. Configuration-Setting Instructions
  1361. // 6.1. vsetvli/vsetvl instructions
  1362. let HasVL = false,
  1363. HasMask = false,
  1364. HasPolicy = false,
  1365. Log2LMUL = [0],
  1366. ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
  1367. {
  1368. // vsetvl is a macro because for it require constant integers in SEW and LMUL.
  1369. let HeaderCode =
  1370. [{
  1371. #define vsetvl_e8mf8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 5)
  1372. #define vsetvl_e8mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 6)
  1373. #define vsetvl_e8mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 7)
  1374. #define vsetvl_e8m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 0)
  1375. #define vsetvl_e8m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 1)
  1376. #define vsetvl_e8m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 2)
  1377. #define vsetvl_e8m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 3)
  1378. #define vsetvl_e16mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 6)
  1379. #define vsetvl_e16mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 7)
  1380. #define vsetvl_e16m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 0)
  1381. #define vsetvl_e16m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 1)
  1382. #define vsetvl_e16m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 2)
  1383. #define vsetvl_e16m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 3)
  1384. #define vsetvl_e32mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 7)
  1385. #define vsetvl_e32m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 0)
  1386. #define vsetvl_e32m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 1)
  1387. #define vsetvl_e32m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 2)
  1388. #define vsetvl_e32m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 3)
  1389. #define vsetvl_e64m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 0)
  1390. #define vsetvl_e64m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 1)
  1391. #define vsetvl_e64m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 2)
  1392. #define vsetvl_e64m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 3)
  1393. }] in
  1394. def vsetvli : RVVBuiltin<"", "zzKzKz", "i">;
  1395. let HeaderCode =
  1396. [{
  1397. #define vsetvlmax_e8mf8() __builtin_rvv_vsetvlimax(0, 5)
  1398. #define vsetvlmax_e8mf4() __builtin_rvv_vsetvlimax(0, 6)
  1399. #define vsetvlmax_e8mf2() __builtin_rvv_vsetvlimax(0, 7)
  1400. #define vsetvlmax_e8m1() __builtin_rvv_vsetvlimax(0, 0)
  1401. #define vsetvlmax_e8m2() __builtin_rvv_vsetvlimax(0, 1)
  1402. #define vsetvlmax_e8m4() __builtin_rvv_vsetvlimax(0, 2)
  1403. #define vsetvlmax_e8m8() __builtin_rvv_vsetvlimax(0, 3)
  1404. #define vsetvlmax_e16mf4() __builtin_rvv_vsetvlimax(1, 6)
  1405. #define vsetvlmax_e16mf2() __builtin_rvv_vsetvlimax(1, 7)
  1406. #define vsetvlmax_e16m1() __builtin_rvv_vsetvlimax(1, 0)
  1407. #define vsetvlmax_e16m2() __builtin_rvv_vsetvlimax(1, 1)
  1408. #define vsetvlmax_e16m4() __builtin_rvv_vsetvlimax(1, 2)
  1409. #define vsetvlmax_e16m8() __builtin_rvv_vsetvlimax(1, 3)
  1410. #define vsetvlmax_e32mf2() __builtin_rvv_vsetvlimax(2, 7)
  1411. #define vsetvlmax_e32m1() __builtin_rvv_vsetvlimax(2, 0)
  1412. #define vsetvlmax_e32m2() __builtin_rvv_vsetvlimax(2, 1)
  1413. #define vsetvlmax_e32m4() __builtin_rvv_vsetvlimax(2, 2)
  1414. #define vsetvlmax_e32m8() __builtin_rvv_vsetvlimax(2, 3)
  1415. #define vsetvlmax_e64m1() __builtin_rvv_vsetvlimax(3, 0)
  1416. #define vsetvlmax_e64m2() __builtin_rvv_vsetvlimax(3, 1)
  1417. #define vsetvlmax_e64m4() __builtin_rvv_vsetvlimax(3, 2)
  1418. #define vsetvlmax_e64m8() __builtin_rvv_vsetvlimax(3, 3)
  1419. }] in
  1420. def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">;
  1421. }
  1422. // 7. Vector Loads and Stores
  1423. // 7.4. Vector Unit-Stride Instructions
  1424. def vlm: RVVVLEMaskBuiltin;
  1425. defm vle8: RVVVLEBuiltin<["c"]>;
  1426. defm vle16: RVVVLEBuiltin<["s","x"]>;
  1427. defm vle32: RVVVLEBuiltin<["i","f"]>;
  1428. defm vle64: RVVVLEBuiltin<["l","d"]>;
  1429. def vsm : RVVVSEMaskBuiltin;
  1430. defm vse8 : RVVVSEBuiltin<["c"]>;
  1431. defm vse16: RVVVSEBuiltin<["s","x"]>;
  1432. defm vse32: RVVVSEBuiltin<["i","f"]>;
  1433. defm vse64: RVVVSEBuiltin<["l","d"]>;
  1434. // 7.5. Vector Strided Instructions
  1435. defm vlse8: RVVVLSEBuiltin<["c"]>;
  1436. defm vlse16: RVVVLSEBuiltin<["s","x"]>;
  1437. defm vlse32: RVVVLSEBuiltin<["i","f"]>;
  1438. defm vlse64: RVVVLSEBuiltin<["l","d"]>;
  1439. defm vsse8 : RVVVSSEBuiltin<["c"]>;
  1440. defm vsse16: RVVVSSEBuiltin<["s","x"]>;
  1441. defm vsse32: RVVVSSEBuiltin<["i","f"]>;
  1442. defm vsse64: RVVVSSEBuiltin<["l","d"]>;
  1443. // 7.6. Vector Indexed Instructions
  1444. defm : RVVIndexedLoad<"vluxei">;
  1445. defm : RVVIndexedLoad<"vloxei">;
  1446. defm : RVVIndexedStore<"vsuxei">;
  1447. defm : RVVIndexedStore<"vsoxei">;
  1448. // 7.7. Unit-stride Fault-Only-First Loads
  1449. defm vle8ff: RVVVLEFFBuiltin<["c"]>;
  1450. defm vle16ff: RVVVLEFFBuiltin<["s","x"]>;
  1451. defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>;
  1452. defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>;
  1453. // 7.8 Vector Load/Store Segment Instructions
  1454. defm : RVVUnitStridedSegLoad<"vlseg">;
  1455. defm : RVVUnitStridedSegLoadFF<"vlseg">;
  1456. defm : RVVStridedSegLoad<"vlsseg">;
  1457. defm : RVVIndexedSegLoad<"vluxseg">;
  1458. defm : RVVIndexedSegLoad<"vloxseg">;
  1459. defm : RVVUnitStridedSegStore<"vsseg">;
  1460. defm : RVVStridedSegStore<"vssseg">;
  1461. defm : RVVIndexedSegStore<"vsuxseg">;
  1462. defm : RVVIndexedSegStore<"vsoxseg">;
  1463. // 12. Vector Integer Arithmetic Instructions
  1464. // 12.1. Vector Single-Width Integer Add and Subtract
  1465. defm vadd : RVVIntBinBuiltinSet;
  1466. defm vsub : RVVIntBinBuiltinSet;
  1467. defm vrsub : RVVOutOp1BuiltinSet<"vrsub", "csil",
  1468. [["vx", "v", "vve"],
  1469. ["vx", "Uv", "UvUvUe"]]>;
  1470. defm vneg_v : RVVPseudoUnaryBuiltin<"vrsub", "csil">;
  1471. // 12.2. Vector Widening Integer Add/Subtract
  1472. // Widening unsigned integer add/subtract, 2*SEW = SEW +/- SEW
  1473. defm vwaddu : RVVUnsignedWidenBinBuiltinSet;
  1474. defm vwsubu : RVVUnsignedWidenBinBuiltinSet;
  1475. // Widening signed integer add/subtract, 2*SEW = SEW +/- SEW
  1476. defm vwadd : RVVSignedWidenBinBuiltinSet;
  1477. defm vwsub : RVVSignedWidenBinBuiltinSet;
  1478. // Widening unsigned integer add/subtract, 2*SEW = 2*SEW +/- SEW
  1479. defm vwaddu : RVVUnsignedWidenOp0BinBuiltinSet;
  1480. defm vwsubu : RVVUnsignedWidenOp0BinBuiltinSet;
  1481. // Widening signed integer add/subtract, 2*SEW = 2*SEW +/- SEW
  1482. defm vwadd : RVVSignedWidenOp0BinBuiltinSet;
  1483. defm vwsub : RVVSignedWidenOp0BinBuiltinSet;
  1484. defm vwcvtu_x_x_v : RVVPseudoVWCVTBuiltin<"vwaddu", "vwcvtu_x", "csi",
  1485. [["Uw", "UwUv"]]>;
  1486. defm vwcvt_x_x_v : RVVPseudoVWCVTBuiltin<"vwadd", "vwcvt_x", "csi",
  1487. [["w", "wv"]]>;
  1488. // 12.3. Vector Integer Extension
  1489. let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
  1490. def vsext_vf2 : RVVIntExt<"vsext", "w", "wv", "csi">;
  1491. def vzext_vf2 : RVVIntExt<"vzext", "Uw", "UwUv", "csi">;
  1492. }
  1493. let Log2LMUL = [-3, -2, -1, 0, 1] in {
  1494. def vsext_vf4 : RVVIntExt<"vsext", "q", "qv", "cs">;
  1495. def vzext_vf4 : RVVIntExt<"vzext", "Uq", "UqUv", "cs">;
  1496. }
  1497. let Log2LMUL = [-3, -2, -1, 0] in {
  1498. def vsext_vf8 : RVVIntExt<"vsext", "o", "ov", "c">;
  1499. def vzext_vf8 : RVVIntExt<"vzext", "Uo", "UoUv", "c">;
  1500. }
  1501. // 12.4. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
  1502. let HasMask = false, HasPolicy = false in {
  1503. defm vadc : RVVCarryinBuiltinSet;
  1504. defm vmadc : RVVCarryOutInBuiltinSet<"vmadc_carry_in">;
  1505. defm vmadc : RVVIntMaskOutBuiltinSet;
  1506. defm vsbc : RVVCarryinBuiltinSet;
  1507. defm vmsbc : RVVCarryOutInBuiltinSet<"vmsbc_borrow_in">;
  1508. defm vmsbc : RVVIntMaskOutBuiltinSet;
  1509. }
  1510. // 12.5. Vector Bitwise Logical Instructions
  1511. defm vand : RVVIntBinBuiltinSet;
  1512. defm vxor : RVVIntBinBuiltinSet;
  1513. defm vor : RVVIntBinBuiltinSet;
  1514. defm vnot_v : RVVPseudoVNotBuiltin<"vxor", "csil">;
  1515. // 12.6. Vector Single-Width Bit Shift Instructions
  1516. defm vsll : RVVShiftBuiltinSet;
  1517. defm vsrl : RVVUnsignedShiftBuiltinSet;
  1518. defm vsra : RVVSignedShiftBuiltinSet;
  1519. // 12.7. Vector Narrowing Integer Right Shift Instructions
  1520. defm vnsrl : RVVUnsignedNShiftBuiltinSet;
  1521. defm vnsra : RVVSignedNShiftBuiltinSet;
  1522. defm vncvt_x_x_w : RVVPseudoVNCVTBuiltin<"vnsrl", "vncvt_x", "csi",
  1523. [["v", "vw"],
  1524. ["Uv", "UvUw"]]>;
  1525. // 12.8. Vector Integer Comparison Instructions
  1526. let HasPolicy = false in {
  1527. defm vmseq : RVVIntMaskOutBuiltinSet;
  1528. defm vmsne : RVVIntMaskOutBuiltinSet;
  1529. defm vmsltu : RVVUnsignedMaskOutBuiltinSet;
  1530. defm vmslt : RVVSignedMaskOutBuiltinSet;
  1531. defm vmsleu : RVVUnsignedMaskOutBuiltinSet;
  1532. defm vmsle : RVVSignedMaskOutBuiltinSet;
  1533. defm vmsgtu : RVVUnsignedMaskOutBuiltinSet;
  1534. defm vmsgt : RVVSignedMaskOutBuiltinSet;
  1535. defm vmsgeu : RVVUnsignedMaskOutBuiltinSet;
  1536. defm vmsge : RVVSignedMaskOutBuiltinSet;
  1537. }
  1538. // 12.9. Vector Integer Min/Max Instructions
  1539. defm vminu : RVVUnsignedBinBuiltinSet;
  1540. defm vmin : RVVSignedBinBuiltinSet;
  1541. defm vmaxu : RVVUnsignedBinBuiltinSet;
  1542. defm vmax : RVVSignedBinBuiltinSet;
  1543. // 12.10. Vector Single-Width Integer Multiply Instructions
  1544. defm vmul : RVVIntBinBuiltinSet;
  1545. let RequiredFeatures = ["FullMultiply"] in {
  1546. defm vmulh : RVVSignedBinBuiltinSet;
  1547. defm vmulhu : RVVUnsignedBinBuiltinSet;
  1548. defm vmulhsu : RVVOutOp1BuiltinSet<"vmulhsu", "csil",
  1549. [["vv", "v", "vvUv"],
  1550. ["vx", "v", "vvUe"]]>;
  1551. }
  1552. // 12.11. Vector Integer Divide Instructions
  1553. defm vdivu : RVVUnsignedBinBuiltinSet;
  1554. defm vdiv : RVVSignedBinBuiltinSet;
  1555. defm vremu : RVVUnsignedBinBuiltinSet;
  1556. defm vrem : RVVSignedBinBuiltinSet;
  1557. // 12.12. Vector Widening Integer Multiply Instructions
  1558. let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
  1559. defm vwmul : RVVOutOp0Op1BuiltinSet<"vwmul", "csi",
  1560. [["vv", "w", "wvv"],
  1561. ["vx", "w", "wve"]]>;
  1562. defm vwmulu : RVVOutOp0Op1BuiltinSet<"vwmulu", "csi",
  1563. [["vv", "Uw", "UwUvUv"],
  1564. ["vx", "Uw", "UwUvUe"]]>;
  1565. defm vwmulsu : RVVOutOp0Op1BuiltinSet<"vwmulsu", "csi",
  1566. [["vv", "w", "wvUv"],
  1567. ["vx", "w", "wvUe"]]>;
  1568. }
  1569. // 12.13. Vector Single-Width Integer Multiply-Add Instructions
  1570. let HasPolicy = false in {
  1571. defm vmacc : RVVIntTerBuiltinSet;
  1572. defm vnmsac : RVVIntTerBuiltinSet;
  1573. defm vmadd : RVVIntTerBuiltinSet;
  1574. defm vnmsub : RVVIntTerBuiltinSet;
  1575. // 12.14. Vector Widening Integer Multiply-Add Instructions
  1576. let HasMaskedOffOperand = false,
  1577. Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
  1578. defm vwmaccu : RVVOutOp1Op2BuiltinSet<"vwmaccu", "csi",
  1579. [["vv", "Uw", "UwUwUvUv"],
  1580. ["vx", "Uw", "UwUwUeUv"]]>;
  1581. defm vwmacc : RVVOutOp1Op2BuiltinSet<"vwmacc", "csi",
  1582. [["vv", "w", "wwvv"],
  1583. ["vx", "w", "wwev"]]>;
  1584. defm vwmaccsu : RVVOutOp1Op2BuiltinSet<"vwmaccsu", "csi",
  1585. [["vv", "w", "wwvUv"],
  1586. ["vx", "w", "wweUv"]]>;
  1587. defm vwmaccus : RVVOutOp1Op2BuiltinSet<"vwmaccus", "csi",
  1588. [["vx", "w", "wwUev"]]>;
  1589. }
  1590. }
  1591. // 12.15. Vector Integer Merge Instructions
  1592. // C/C++ Operand: (mask, op1, op2, vl), Intrinsic: (op1, op2, mask, vl)
  1593. let HasMask = false, HasPolicy = false,
  1594. ManualCodegen = [{
  1595. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
  1596. IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
  1597. }] in {
  1598. defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "csil",
  1599. [["vvm", "v", "vmvv"],
  1600. ["vxm", "v", "vmve"],
  1601. ["vvm", "Uv", "UvmUvUv"],
  1602. ["vxm", "Uv", "UvmUvUe"]]>;
  1603. }
  1604. // 12.16. Vector Integer Move Instructions
  1605. let HasMask = false, HasPolicy = false in {
  1606. let MangledName = "vmv_v" in {
  1607. defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csil",
  1608. [["v", "Uv", "UvUv"]]>;
  1609. defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csilxfd",
  1610. [["v", "v", "vv"]]>;
  1611. }
  1612. let HasNoMaskedOverloaded = false in
  1613. defm vmv_v : RVVOutBuiltinSet<"vmv_v_x", "csil",
  1614. [["x", "v", "ve"],
  1615. ["x", "Uv", "UvUe"]]>;
  1616. }
  1617. // 13. Vector Fixed-Point Arithmetic Instructions
  1618. // 13.1. Vector Single-Width Saturating Add and Subtract
  1619. defm vsaddu : RVVUnsignedBinBuiltinSet;
  1620. defm vsadd : RVVSignedBinBuiltinSet;
  1621. defm vssubu : RVVUnsignedBinBuiltinSet;
  1622. defm vssub : RVVSignedBinBuiltinSet;
  1623. // 13.2. Vector Single-Width Averaging Add and Subtract
  1624. defm vaaddu : RVVUnsignedBinBuiltinSet;
  1625. defm vaadd : RVVSignedBinBuiltinSet;
  1626. defm vasubu : RVVUnsignedBinBuiltinSet;
  1627. defm vasub : RVVSignedBinBuiltinSet;
  1628. // 13.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
  1629. let RequiredFeatures = ["FullMultiply"] in {
  1630. defm vsmul : RVVSignedBinBuiltinSet;
  1631. }
  1632. // 13.4. Vector Single-Width Scaling Shift Instructions
  1633. defm vssrl : RVVUnsignedShiftBuiltinSet;
  1634. defm vssra : RVVSignedShiftBuiltinSet;
  1635. // 13.5. Vector Narrowing Fixed-Point Clip Instructions
  1636. defm vnclipu : RVVUnsignedNShiftBuiltinSet;
  1637. defm vnclip : RVVSignedNShiftBuiltinSet;
  1638. // 14. Vector Floating-Point Instructions
  1639. // 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
  1640. defm vfadd : RVVFloatingBinBuiltinSet;
  1641. defm vfsub : RVVFloatingBinBuiltinSet;
  1642. defm vfrsub : RVVFloatingBinVFBuiltinSet;
  1643. // 14.3. Vector Widening Floating-Point Add/Subtract Instructions
  1644. // Widening FP add/subtract, 2*SEW = SEW +/- SEW
  1645. defm vfwadd : RVVFloatingWidenBinBuiltinSet;
  1646. defm vfwsub : RVVFloatingWidenBinBuiltinSet;
  1647. // Widening FP add/subtract, 2*SEW = 2*SEW +/- SEW
  1648. defm vfwadd : RVVFloatingWidenOp0BinBuiltinSet;
  1649. defm vfwsub : RVVFloatingWidenOp0BinBuiltinSet;
  1650. // 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions
  1651. defm vfmul : RVVFloatingBinBuiltinSet;
  1652. defm vfdiv : RVVFloatingBinBuiltinSet;
  1653. defm vfrdiv : RVVFloatingBinVFBuiltinSet;
  1654. // 14.5. Vector Widening Floating-Point Multiply
  1655. let Log2LMUL = [-2, -1, 0, 1, 2] in {
  1656. defm vfwmul : RVVOutOp0Op1BuiltinSet<"vfwmul", "xf",
  1657. [["vv", "w", "wvv"],
  1658. ["vf", "w", "wve"]]>;
  1659. }
  1660. // 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions
  1661. let HasPolicy = false in {
  1662. defm vfmacc : RVVFloatingTerBuiltinSet;
  1663. defm vfnmacc : RVVFloatingTerBuiltinSet;
  1664. defm vfmsac : RVVFloatingTerBuiltinSet;
  1665. defm vfnmsac : RVVFloatingTerBuiltinSet;
  1666. defm vfmadd : RVVFloatingTerBuiltinSet;
  1667. defm vfnmadd : RVVFloatingTerBuiltinSet;
  1668. defm vfmsub : RVVFloatingTerBuiltinSet;
  1669. defm vfnmsub : RVVFloatingTerBuiltinSet;
  1670. // 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
  1671. defm vfwmacc : RVVFloatingWidenTerBuiltinSet;
  1672. defm vfwnmacc : RVVFloatingWidenTerBuiltinSet;
  1673. defm vfwmsac : RVVFloatingWidenTerBuiltinSet;
  1674. defm vfwnmsac : RVVFloatingWidenTerBuiltinSet;
  1675. }
  1676. // 14.8. Vector Floating-Point Square-Root Instruction
  1677. def vfsqrt : RVVFloatingUnaryVVBuiltin;
  1678. // 14.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction
  1679. def vfrsqrt7 : RVVFloatingUnaryVVBuiltin;
  1680. // 14.10. Vector Floating-Point Reciprocal Estimate Instruction
  1681. def vfrec7 : RVVFloatingUnaryVVBuiltin;
  1682. // 14.11. Vector Floating-Point MIN/MAX Instructions
  1683. defm vfmin : RVVFloatingBinBuiltinSet;
  1684. defm vfmax : RVVFloatingBinBuiltinSet;
  1685. // 14.12. Vector Floating-Point Sign-Injection Instructions
  1686. defm vfsgnj : RVVFloatingBinBuiltinSet;
  1687. defm vfsgnjn : RVVFloatingBinBuiltinSet;
  1688. defm vfsgnjx : RVVFloatingBinBuiltinSet;
  1689. defm vfneg_v : RVVPseudoVFUnaryBuiltin<"vfsgnjn", "xfd">;
  1690. defm vfabs_v : RVVPseudoVFUnaryBuiltin<"vfsgnjx", "xfd">;
  1691. // 14.13. Vector Floating-Point Compare Instructions
  1692. let HasPolicy = false in {
  1693. defm vmfeq : RVVFloatingMaskOutBuiltinSet;
  1694. defm vmfne : RVVFloatingMaskOutBuiltinSet;
  1695. defm vmflt : RVVFloatingMaskOutBuiltinSet;
  1696. defm vmfle : RVVFloatingMaskOutBuiltinSet;
  1697. defm vmfgt : RVVFloatingMaskOutBuiltinSet;
  1698. defm vmfge : RVVFloatingMaskOutBuiltinSet;
  1699. }
  1700. // 14.14. Vector Floating-Point Classify Instruction
  1701. let Name = "vfclass_v", HasPolicy = false in
  1702. def vfclass : RVVOp0Builtin<"Uv", "Uvv", "xfd">;
  1703. // 14.15. Vector Floating-Point Merge Instructio
  1704. // C/C++ Operand: (mask, op1, op2, vl), Builtin: (op1, op2, mask, vl)
  1705. let HasMask = false, HasPolicy = false,
  1706. ManualCodegen = [{
  1707. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
  1708. IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
  1709. }] in {
  1710. defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "xfd",
  1711. [["vvm", "v", "vmvv"]]>;
  1712. defm vfmerge : RVVOutOp1BuiltinSet<"vfmerge", "xfd",
  1713. [["vfm", "v", "vmve"]]>;
  1714. }
  1715. // 14.16. Vector Floating-Point Move Instruction
  1716. let HasMask = false, HasNoMaskedOverloaded = false, HasPolicy = false in
  1717. defm vfmv_v : RVVOutBuiltinSet<"vfmv_v_f", "xfd",
  1718. [["f", "v", "ve"]]>;
  1719. // 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions
  1720. def vfcvt_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_xu">;
  1721. def vfcvt_x_f_v : RVVConvToSignedBuiltin<"vfcvt_x">;
  1722. def vfcvt_rtz_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_rtz_xu">;
  1723. def vfcvt_rtz_x_f_v : RVVConvToSignedBuiltin<"vfcvt_rtz_x">;
  1724. def vfcvt_f_xu_v : RVVConvBuiltin<"Fv", "FvUv", "sil", "vfcvt_f">;
  1725. def vfcvt_f_x_v : RVVConvBuiltin<"Fv", "Fvv", "sil", "vfcvt_f">;
  1726. // 14.18. Widening Floating-Point/Integer Type-Convert Instructions
  1727. let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
  1728. def vfwcvt_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_xu">;
  1729. def vfwcvt_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_x">;
  1730. def vfwcvt_rtz_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_rtz_xu">;
  1731. def vfwcvt_rtz_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_rtz_x">;
  1732. def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">;
  1733. def vfwcvt_f_x_v : RVVConvBuiltin<"Fw", "Fwv", "csi", "vfwcvt_f">;
  1734. def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "xf", "vfwcvt_f">;
  1735. }
  1736. // 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions
  1737. let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
  1738. def vfncvt_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_xu">;
  1739. def vfncvt_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_x">;
  1740. def vfncvt_rtz_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_rtz_xu">;
  1741. def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">;
  1742. def vfncvt_f_xu_w : RVVConvBuiltin<"Fv", "FvUw", "csi", "vfncvt_f">;
  1743. def vfncvt_f_x_w : RVVConvBuiltin<"Fv", "Fvw", "csi", "vfncvt_f">;
  1744. def vfncvt_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_f">;
  1745. def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_rod_f">;
  1746. }
  1747. // 15. Vector Reduction Operations
  1748. // 15.1. Vector Single-Width Integer Reduction Instructions
  1749. let HasPolicy = false in {
  1750. defm vredsum : RVVIntReductionBuiltinSet;
  1751. defm vredmaxu : RVVUnsignedReductionBuiltin;
  1752. defm vredmax : RVVSignedReductionBuiltin;
  1753. defm vredminu : RVVUnsignedReductionBuiltin;
  1754. defm vredmin : RVVSignedReductionBuiltin;
  1755. defm vredand : RVVIntReductionBuiltinSet;
  1756. defm vredor : RVVIntReductionBuiltinSet;
  1757. defm vredxor : RVVIntReductionBuiltinSet;
  1758. // 15.2. Vector Widening Integer Reduction Instructions
  1759. // Vector Widening Integer Reduction Operations
  1760. let HasMaskedOffOperand = false in {
  1761. defm vwredsum : RVVOutOp1BuiltinSet<"vwredsum", "csi",
  1762. [["vs", "vSw", "SwSwvSw"]]>;
  1763. defm vwredsumu : RVVOutOp1BuiltinSet<"vwredsumu", "csi",
  1764. [["vs", "UvUSw", "USwUSwUvUSw"]]>;
  1765. }
  1766. // 15.3. Vector Single-Width Floating-Point Reduction Instructions
  1767. defm vfredmax : RVVFloatingReductionBuiltin;
  1768. defm vfredmin : RVVFloatingReductionBuiltin;
  1769. defm vfredusum : RVVFloatingReductionBuiltin;
  1770. defm vfredosum : RVVFloatingReductionBuiltin;
  1771. // 15.4. Vector Widening Floating-Point Reduction Instructions
  1772. defm vfwredusum : RVVFloatingWidenReductionBuiltin;
  1773. defm vfwredosum : RVVFloatingWidenReductionBuiltin;
  1774. }
  1775. // 16. Vector Mask Instructions
  1776. // 16.1. Vector Mask-Register Logical Instructions
  1777. def vmand : RVVMaskBinBuiltin;
  1778. def vmnand : RVVMaskBinBuiltin;
  1779. def vmandn : RVVMaskBinBuiltin;
  1780. def vmxor : RVVMaskBinBuiltin;
  1781. def vmor : RVVMaskBinBuiltin;
  1782. def vmnor : RVVMaskBinBuiltin;
  1783. def vmorn : RVVMaskBinBuiltin;
  1784. def vmxnor : RVVMaskBinBuiltin;
  1785. // pseudoinstructions
  1786. def vmclr : RVVMaskNullaryBuiltin;
  1787. def vmset : RVVMaskNullaryBuiltin;
  1788. defm vmmv_m : RVVPseudoMaskBuiltin<"vmand", "c">;
  1789. defm vmnot_m : RVVPseudoMaskBuiltin<"vmnand", "c">;
  1790. let HasPolicy = false in {
  1791. // 16.2. Vector count population in mask vcpop.m
  1792. def vcpop : RVVMaskOp0Builtin<"um">;
  1793. // 16.3. vfirst find-first-set mask bit
  1794. def vfirst : RVVMaskOp0Builtin<"lm">;
  1795. // 16.4. vmsbf.m set-before-first mask bit
  1796. def vmsbf : RVVMaskUnaryBuiltin;
  1797. // 16.5. vmsif.m set-including-first mask bit
  1798. def vmsif : RVVMaskUnaryBuiltin;
  1799. // 16.6. vmsof.m set-only-first mask bit
  1800. def vmsof : RVVMaskUnaryBuiltin;
  1801. let HasNoMaskedOverloaded = false in {
  1802. // 16.8. Vector Iota Instruction
  1803. defm viota : RVVOutBuiltinSet<"viota", "csil", [["m", "Uv", "Uvm"]]>;
  1804. // 16.9. Vector Element Index Instruction
  1805. defm vid : RVVOutBuiltinSet<"vid", "csil", [["v", "v", "v"],
  1806. ["v", "Uv", "Uv"]]>;
  1807. }
  1808. }
  1809. // 17. Vector Permutation Instructions
  1810. // 17.1. Integer Scalar Move Instructions
  1811. let HasMask = false, HasPolicy = false in {
  1812. let HasVL = false, MangledName = "vmv_x" in
  1813. defm vmv_x : RVVOp0BuiltinSet<"vmv_x_s", "csil",
  1814. [["s", "ve", "ev"],
  1815. ["s", "UvUe", "UeUv"]]>;
  1816. let MangledName = "vmv_s" in
  1817. defm vmv_s : RVVOutBuiltinSet<"vmv_s_x", "csil",
  1818. [["x", "v", "vve"],
  1819. ["x", "Uv", "UvUvUe"]]>;
  1820. }
  1821. // 17.2. Floating-Point Scalar Move Instructions
  1822. let HasMask = false, HasPolicy = false in {
  1823. let HasVL = false, MangledName = "vfmv_f" in
  1824. defm vfmv_f : RVVOp0BuiltinSet<"vfmv_f_s", "xfd",
  1825. [["s", "ve", "ev"]]>;
  1826. let MangledName = "vfmv_s" in
  1827. defm vfmv_s : RVVOutBuiltinSet<"vfmv_s_f", "xfd",
  1828. [["f", "v", "vve"],
  1829. ["x", "Uv", "UvUvUe"]]>;
  1830. }
  1831. // 17.3. Vector Slide Instructions
  1832. let HasPolicy = false in {
  1833. // 17.3.1. Vector Slideup Instructions
  1834. defm vslideup : RVVSlideBuiltinSet;
  1835. // 17.3.2. Vector Slidedown Instructions
  1836. defm vslidedown : RVVSlideBuiltinSet;
  1837. }
  1838. // 17.3.3. Vector Slide1up Instructions
  1839. defm vslide1up : RVVSlideOneBuiltinSet;
  1840. defm vfslide1up : RVVFloatingBinVFBuiltinSet;
  1841. // 17.3.4. Vector Slide1down Instruction
  1842. defm vslide1down : RVVSlideOneBuiltinSet;
  1843. defm vfslide1down : RVVFloatingBinVFBuiltinSet;
  1844. // 17.4. Vector Register Gather Instructions
  1845. // signed and floating type
  1846. defm vrgather : RVVOutBuiltinSet<"vrgather_vv", "csilxfd",
  1847. [["vv", "v", "vvUv"]]>;
  1848. defm vrgather : RVVOutBuiltinSet<"vrgather_vx", "csilxfd",
  1849. [["vx", "v", "vvz"]]>;
  1850. defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csilxfd",
  1851. [["vv", "v", "vv(Log2EEW:4)Uv"]]>;
  1852. // unsigned type
  1853. defm vrgather : RVVOutBuiltinSet<"vrgather_vv", "csil",
  1854. [["vv", "Uv", "UvUvUv"]]>;
  1855. defm vrgather : RVVOutBuiltinSet<"vrgather_vx", "csil",
  1856. [["vx", "Uv", "UvUvz"]]>;
  1857. defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csil",
  1858. [["vv", "Uv", "UvUv(Log2EEW:4)Uv"]]>;
  1859. // 17.5. Vector Compress Instruction
  1860. let HasMask = false, HasPolicy = false,
  1861. ManualCodegen = [{
  1862. std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
  1863. IntrinsicTypes = {ResultType, Ops[3]->getType()};
  1864. }] in {
  1865. // signed and floating type
  1866. defm vcompress : RVVOutBuiltinSet<"vcompress", "csilxfd",
  1867. [["vm", "v", "vmvv"]]>;
  1868. // unsigned type
  1869. defm vcompress : RVVOutBuiltinSet<"vcompress", "csil",
  1870. [["vm", "Uv", "UvmUvUv"]]>;
  1871. }
  1872. // Miscellaneous
  1873. let HasMask = false, HasVL = false, IRName = "" in {
  1874. let Name = "vreinterpret_v", HasPolicy = false,
  1875. ManualCodegen = [{
  1876. return Builder.CreateBitCast(Ops[0], ResultType);
  1877. }] in {
  1878. // Reinterpret between different type under the same SEW and LMUL
  1879. def vreinterpret_i_u : RVVBuiltin<"Uvv", "vUv", "csil", "v">;
  1880. def vreinterpret_i_f : RVVBuiltin<"Fvv", "vFv", "sil", "v">;
  1881. def vreinterpret_u_i : RVVBuiltin<"vUv", "Uvv", "csil", "Uv">;
  1882. def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "sil", "Uv">;
  1883. def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "sil", "Fv">;
  1884. def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "sil", "Fv">;
  1885. // Reinterpret between different SEW under the same LMUL
  1886. foreach dst_sew = ["(FixedSEW:8)", "(FixedSEW:16)", "(FixedSEW:32)",
  1887. "(FixedSEW:64)"] in {
  1888. def vreinterpret_i_ # dst_sew : RVVBuiltin<"v" # dst_sew # "v",
  1889. dst_sew # "vv", "csil", dst_sew # "v">;
  1890. def vreinterpret_u_ # dst_sew : RVVBuiltin<"Uv" # dst_sew # "Uv",
  1891. dst_sew # "UvUv", "csil", dst_sew # "Uv">;
  1892. }
  1893. }
  1894. let Name = "vundefined", HasNoMaskedOverloaded = false, HasPolicy = false,
  1895. ManualCodegen = [{
  1896. return llvm::UndefValue::get(ResultType);
  1897. }] in {
  1898. def vundefined : RVVBuiltin<"v", "v", "csilxfd">;
  1899. def vundefined_u : RVVBuiltin<"Uv", "Uv", "csil">;
  1900. }
  1901. // LMUL truncation
  1902. // C/C++ Operand: VecTy, IR Operand: VecTy, Index
  1903. let Name = "vlmul_trunc_v", MangledName = "vlmul_trunc", HasPolicy = false,
  1904. ManualCodegen = [{ {
  1905. ID = Intrinsic::experimental_vector_extract;
  1906. IntrinsicTypes = {ResultType, Ops[0]->getType()};
  1907. Ops.push_back(ConstantInt::get(Int64Ty, 0));
  1908. return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
  1909. } }] in {
  1910. foreach dst_lmul = ["(SFixedLog2LMUL:-3)", "(SFixedLog2LMUL:-2)", "(SFixedLog2LMUL:-1)",
  1911. "(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in {
  1912. def vlmul_trunc # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v",
  1913. dst_lmul # "vv", "csilxfd", dst_lmul # "v">;
  1914. def vlmul_trunc_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv",
  1915. dst_lmul # "UvUv", "csil", dst_lmul # "Uv">;
  1916. }
  1917. }
  1918. // LMUL extension
  1919. // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index
  1920. let Name = "vlmul_ext_v", MangledName = "vlmul_ext", HasPolicy = false,
  1921. ManualCodegen = [{
  1922. ID = Intrinsic::experimental_vector_insert;
  1923. IntrinsicTypes = {ResultType, Ops[0]->getType()};
  1924. Ops.push_back(llvm::UndefValue::get(ResultType));
  1925. std::swap(Ops[0], Ops[1]);
  1926. Ops.push_back(ConstantInt::get(Int64Ty, 0));
  1927. return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
  1928. }] in {
  1929. foreach dst_lmul = ["(LFixedLog2LMUL:-2)", "(LFixedLog2LMUL:-1)", "(LFixedLog2LMUL:-0)",
  1930. "(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
  1931. def vlmul_ext # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v",
  1932. dst_lmul # "vv", "csilxfd", dst_lmul # "v">;
  1933. def vlmul_ext_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv",
  1934. dst_lmul # "UvUv", "csil", dst_lmul # "Uv">;
  1935. }
  1936. }
  1937. let Name = "vget_v", HasPolicy = false,
  1938. ManualCodegen = [{
  1939. {
  1940. ID = Intrinsic::experimental_vector_extract;
  1941. auto *VecTy = cast<ScalableVectorType>(ResultType);
  1942. auto *OpVecTy = cast<ScalableVectorType>(Ops[0]->getType());
  1943. // Mask to only valid indices.
  1944. unsigned MaxIndex = OpVecTy->getMinNumElements() / VecTy->getMinNumElements();
  1945. assert(isPowerOf2_32(MaxIndex));
  1946. Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1);
  1947. Ops[1] = Builder.CreateMul(Ops[1],
  1948. ConstantInt::get(Ops[1]->getType(),
  1949. VecTy->getMinNumElements()));
  1950. IntrinsicTypes = {ResultType, Ops[0]->getType()};
  1951. return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
  1952. }
  1953. }] in {
  1954. foreach dst_lmul = ["(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in {
  1955. def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vvKz", "csilxfd", dst_lmul # "v">;
  1956. def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUvKz", "csil", dst_lmul # "Uv">;
  1957. }
  1958. }
  1959. let Name = "vset_v", Log2LMUL = [0, 1, 2], HasPolicy = false,
  1960. ManualCodegen = [{
  1961. {
  1962. ID = Intrinsic::experimental_vector_insert;
  1963. IntrinsicTypes = {ResultType, Ops[2]->getType()};
  1964. auto *ResVecTy = cast<ScalableVectorType>(ResultType);
  1965. auto *VecTy = cast<ScalableVectorType>(Ops[2]->getType());
  1966. // Mask to only valid indices.
  1967. unsigned MaxIndex = ResVecTy->getMinNumElements() / VecTy->getMinNumElements();
  1968. assert(isPowerOf2_32(MaxIndex));
  1969. Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1);
  1970. Ops[1] = Builder.CreateMul(Ops[1],
  1971. ConstantInt::get(Ops[1]->getType(),
  1972. VecTy->getMinNumElements()));
  1973. std::swap(Ops[1], Ops[2]);
  1974. return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
  1975. }
  1976. }] in {
  1977. foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
  1978. def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "v" # dst_lmul # "vKzv", "csilxfd">;
  1979. def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "Uv" # dst_lmul #"UvKzUv", "csil">;
  1980. }
  1981. }
  1982. }
  1983. let HeaderCode = [{
  1984. #define VE_TAIL_UNDISTURBED 0
  1985. #define VE_TAIL_AGNOSTIC 1
  1986. }] in
  1987. def policy : RVVHeader;