arm_mve_defs.td 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. //===- arm_mve_defs.td - definitions and infrastructure for arm_mve.td ----===//
  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. // The definitions in this file are designed to work in close conjunction with
  10. // clang/utils/TableGen/MveEmitter.cpp. Comments in there will probably be
  11. // useful as well.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. // -----------------------------------------------------------------------------
  15. // Forward declarations.
  16. class Type;
  17. // -----------------------------------------------------------------------------
  18. // Dummy record used as the dag operator for the argument list of an intrinsic.
  19. //
  20. // We store arguments as a dag rather than a list<Type> so that we can give
  21. // each one a name, to be used in codegen. For example, (args Vector:$a,
  22. // Scalar:$b) defines the names $a and $b which the specification of the code
  23. // for that intrinsic can refer to.
  24. def args;
  25. // -----------------------------------------------------------------------------
  26. // Family of nodes for use in the codegen dag for an intrinsic, corresponding
  27. // to function calls that return LLVM IR nodes.
  28. class IRBuilderParam<int index_> { int index = index_; }
  29. class IRBuilderAddrParam<int index_> : IRBuilderParam<index_>;
  30. class IRBuilderIntParam<int index_, string type_> : IRBuilderParam<index_> {
  31. string type = type_;
  32. }
  33. class IRBuilderBase {
  34. // The prefix of the function call, including an open parenthesis.
  35. string prefix;
  36. // Any parameters that have types that have to be treated specially by the
  37. // Tablegen back end. Generally these will be types other than llvm::Value *,
  38. // although not all other types need special treatment (e.g. llvm::Type *).
  39. list<IRBuilderParam> special_params = [];
  40. }
  41. class IRBuilder<string func> : IRBuilderBase {
  42. // The usual case: a method called on the code gen function's instance of
  43. // llvm::IRBuilder.
  44. let prefix = "Builder." # func # "(";
  45. }
  46. class IRFunction<string func> : IRBuilderBase {
  47. // Some other function that doesn't use the IRBuilder at all.
  48. let prefix = func # "(";
  49. }
  50. class CGHelperFn<string func> : IRBuilderBase {
  51. // A helper function defined in CGBuiltin.cpp, which takes the IRBuilder as
  52. // an argument.
  53. let prefix = func # "(Builder, ";
  54. }
  55. class CGFHelperFn<string func> : IRBuilderBase {
  56. // Like CGHelperFn, but also takes the CodeGenFunction itself.
  57. let prefix = func # "(Builder, this, ";
  58. }
  59. def add: IRBuilder<"CreateAdd">;
  60. def mul: IRBuilder<"CreateMul">;
  61. def not: IRBuilder<"CreateNot">;
  62. def or: IRBuilder<"CreateOr">;
  63. def and: IRBuilder<"CreateAnd">;
  64. def xor: IRBuilder<"CreateXor">;
  65. def sub: IRBuilder<"CreateSub">;
  66. def shl: IRBuilder<"CreateShl">;
  67. def lshr: IRBuilder<"CreateLShr">;
  68. def immshr: CGHelperFn<"MVEImmediateShr"> {
  69. let special_params = [IRBuilderIntParam<1, "unsigned">,
  70. IRBuilderIntParam<2, "bool">];
  71. }
  72. def fadd: IRBuilder<"CreateFAdd">;
  73. def fmul: IRBuilder<"CreateFMul">;
  74. def fsub: IRBuilder<"CreateFSub">;
  75. def load: IRBuilder<"CreateLoad"> {
  76. let special_params = [IRBuilderAddrParam<0>];
  77. }
  78. def store: IRBuilder<"CreateStore"> {
  79. let special_params = [IRBuilderAddrParam<1>];
  80. }
  81. def xval: IRBuilder<"CreateExtractValue"> {
  82. let special_params = [IRBuilderIntParam<1, "unsigned">];
  83. }
  84. def ielt_const: IRBuilder<"CreateInsertElement"> {
  85. let special_params = [IRBuilderIntParam<2, "uint64_t">];
  86. }
  87. def ielt_var: IRBuilder<"CreateInsertElement">;
  88. def xelt_var: IRBuilder<"CreateExtractElement">;
  89. def trunc: IRBuilder<"CreateTrunc">;
  90. def bitcast: IRBuilder<"CreateBitCast">;
  91. def vreinterpret: CGFHelperFn<"ARMMVEVectorReinterpret">;
  92. def extend: CGHelperFn<"SignOrZeroExtend"> {
  93. let special_params = [IRBuilderIntParam<2, "bool">];
  94. }
  95. def zeroinit: IRFunction<"llvm::Constant::getNullValue">;
  96. def int_min: CGHelperFn<"ARMMVEConstantSplat<1,0>">;
  97. def int_max: CGHelperFn<"ARMMVEConstantSplat<0,1>">;
  98. def uint_max: CGHelperFn<"ARMMVEConstantSplat<1,1>">;
  99. def undef: IRFunction<"UndefValue::get">;
  100. def icmp_eq: IRBuilder<"CreateICmpEQ">;
  101. def icmp_ne: IRBuilder<"CreateICmpNE">;
  102. def icmp_ugt: IRBuilder<"CreateICmpUGT">;
  103. def icmp_uge: IRBuilder<"CreateICmpUGE">;
  104. def icmp_ult: IRBuilder<"CreateICmpULT">;
  105. def icmp_ule: IRBuilder<"CreateICmpULE">;
  106. def icmp_sgt: IRBuilder<"CreateICmpSGT">;
  107. def icmp_sge: IRBuilder<"CreateICmpSGE">;
  108. def icmp_slt: IRBuilder<"CreateICmpSLT">;
  109. def icmp_sle: IRBuilder<"CreateICmpSLE">;
  110. def fcmp_eq: IRBuilder<"CreateFCmpOEQ">;
  111. def fcmp_ne: IRBuilder<"CreateFCmpUNE">; // not O: it must return true on NaNs
  112. def fcmp_gt: IRBuilder<"CreateFCmpOGT">;
  113. def fcmp_ge: IRBuilder<"CreateFCmpOGE">;
  114. def fcmp_lt: IRBuilder<"CreateFCmpOLT">;
  115. def fcmp_le: IRBuilder<"CreateFCmpOLE">;
  116. def splat: CGHelperFn<"ARMMVEVectorSplat">;
  117. def select: IRBuilder<"CreateSelect">;
  118. def fneg: IRBuilder<"CreateFNeg">;
  119. def sitofp: IRBuilder<"CreateSIToFP">;
  120. def uitofp: IRBuilder<"CreateUIToFP">;
  121. def fptosi: IRBuilder<"CreateFPToSI">;
  122. def fptoui: IRBuilder<"CreateFPToUI">;
  123. def vrev: CGHelperFn<"ARMMVEVectorElementReverse"> {
  124. let special_params = [IRBuilderIntParam<1, "unsigned">];
  125. }
  126. def unzip: CGHelperFn<"VectorUnzip"> {
  127. let special_params = [IRBuilderIntParam<1, "bool">];
  128. }
  129. def zip: CGHelperFn<"VectorZip">;
  130. // Trivial 'codegen' function that just returns its argument. Useful
  131. // for wrapping up a variable name like $foo into a thing you can pass
  132. // around as type 'dag'.
  133. def id: IRBuilderBase {
  134. // All the other cases of IRBuilderBase use 'prefix' to specify a function
  135. // call, including the open parenthesis. MveEmitter puts the closing paren on
  136. // the end. So if we _just_ specify an open paren with no function name
  137. // before it, then the generated C++ code will simply wrap the input value in
  138. // parentheses, returning it unchanged.
  139. let prefix = "(";
  140. }
  141. // Helper for making boolean flags in IR
  142. def i1: IRBuilderBase {
  143. let prefix = "llvm::ConstantInt::get(Builder.getInt1Ty(), ";
  144. let special_params = [IRBuilderIntParam<0, "bool">];
  145. }
  146. // A node that makes an Address out of a pointer-typed Value, by
  147. // providing an alignment as the second argument.
  148. def address;
  149. // Another node class you can use in the codegen dag. This one corresponds to
  150. // an IR intrinsic function, which has to be specialized to a particular list
  151. // of types.
  152. class IRIntBase<string name_, list<Type> params_ = [], bit appendKind_ = 0> {
  153. string intname = name_; // base name of the intrinsic
  154. list<Type> params = params_; // list of parameter types
  155. // If this flag is set, then the IR intrinsic name will get a suffix _s, _u
  156. // or _f depending on whether the main parameter type of the ACLE intrinsic
  157. // being generated is a signed integer, unsigned integer, or float. Mostly
  158. // this is useful for signed vs unsigned integers, because the ACLE
  159. // intrinsics and the source-level integer types distinguish them, but at IR
  160. // level the distinction has moved from the type system into the operations
  161. // and you just have i32 or i16 etc. So when an IR intrinsic has to vary with
  162. // signedness, you set this bit, and then you can still put the signed and
  163. // unsigned versions in the same subclass of Intrinsic, and the Tablegen
  164. // backend will take care of adding _s or _u as appropriate in each instance.
  165. bit appendKind = appendKind_;
  166. }
  167. // Mostly we'll be using @llvm.arm.mve.* intrinsics, so here's a trivial
  168. // subclass that puts on that prefix.
  169. class IRInt<string name, list<Type> params = [], bit appendKind = 0>
  170. : IRIntBase<"arm_mve_" # name, params, appendKind>;
  171. // The 'seq' node in a codegen dag specifies a set of IR operations to be
  172. // performed in order. It has the special ability to define extra variable
  173. // names, on top of the ones that refer to the intrinsic's parameters. For
  174. // example:
  175. //
  176. // (seq (foo this, that):$a,
  177. // (bar this, $a):$b
  178. // (add $a, $b))
  179. //
  180. // defines the name $a to refer to the return value of the 'foo' operation;
  181. // then the 'bar' operation uses $a as one of its arguments, and the return
  182. // value of that is assigned the name $b; finally, $a and $b are added to give
  183. // the return value of the seq construction as a whole.
  184. def seq;
  185. // Another magic operation is 'unsignedflag', which you give a scalar
  186. // _type_ as an argument, and it expands into 1 for an unsigned type
  187. // and 0 for a signed (or floating) one.
  188. def unsignedflag;
  189. // 'bitsize' also takes a scalar type, and expands into an integer
  190. // constant giving its size in bits.
  191. def bitsize;
  192. // If you put CustomCodegen<"foo"> in an intrinsic's codegen field, it
  193. // indicates that the IR generation for that intrinsic is done by handwritten
  194. // C++ and not autogenerated at all. The effect in the MVE builtin codegen
  195. // function is to break out of the main switch and fall through to the
  196. // manual-codegen cases below it, having set the CustomCodeGenType enumerated
  197. // variable to the value given by the 'type' string here.
  198. class CustomCodegen<string type_> { string type = type_; }
  199. // -----------------------------------------------------------------------------
  200. // System for building up complex instances of Type from simple ones.
  201. // ComplexType is used to represent any more complicated type: vectors,
  202. // multivectors, pointers etc. Its dag argument specifies how the type should
  203. // be constructed from simpler types. The operator of the dag will always be an
  204. // instance of ComplexTypeOp, defined below.
  205. class ComplexType<dag spec_>: Type { dag spec = spec_; }
  206. // Operators you can use in the ComplexType spec dag. These are an intermediate
  207. // layer, interpreted by MveEmitter::getType() in the Tablegen backend, and
  208. // only used in the definitions below. Actual intrinsic definitions in
  209. // arm_mve.td will use the defs defined below here.
  210. class ComplexTypeOp;
  211. def CTO_Parameter: ComplexTypeOp;
  212. def CTO_Vec: ComplexTypeOp;
  213. def CTO_Pred: ComplexTypeOp;
  214. class CTO_Tuple<int n_>: ComplexTypeOp { int n = n_; }
  215. class CTO_Pointer<bit const_>: ComplexTypeOp { bit const = const_; }
  216. def CTO_CopyKind: ComplexTypeOp;
  217. class CTO_ScaleSize<int num_, int denom_>: ComplexTypeOp {
  218. int num = num_;
  219. int denom = denom_;
  220. }
  221. // -----------------------------------------------------------------------------
  222. // Instances of Type intended to be used directly in the specification of an
  223. // intrinsic in arm_mve.td.
  224. // The type Void can be used for the return type of an intrinsic, and as the
  225. // parameter type for intrinsics that aren't actually parameterised by any kind
  226. // of _s32 / _f16 / _u8 suffix.
  227. def Void : Type;
  228. // A wrapper you can put on an intrinsic's argument type to prevent it from
  229. // being automatically promoted to i32 from a smaller integer type.
  230. class unpromoted<Type t> : Type { Type underlying_type = t; }
  231. // Primitive types: base class, and an instance for the set of scalar integer
  232. // and floating types that MVE uses.
  233. class PrimitiveType<string kind_, int size_>: Type {
  234. string kind = kind_;
  235. int size = size_;
  236. string nameOverride = "";
  237. }
  238. // The type records defined by these foreaches have names like s32, f16, u8.
  239. foreach size = [8, 16, 32, 64] in
  240. foreach kind = ["u", "s"] in
  241. def kind # size: PrimitiveType<kind, size>;
  242. foreach size = [16, 32] in
  243. foreach kind = ["f"] in
  244. def kind # size: PrimitiveType<kind, size>;
  245. // Sometimes we need to refer to a type by a different name in C, when
  246. // ACLE defines a function parameter to be something like 'unsigned'
  247. // rather than uint32_t.
  248. def uint: PrimitiveType<"u", 32> { let nameOverride = "unsigned"; }
  249. def sint: PrimitiveType<"s", 32> { let nameOverride = "int"; }
  250. // VecOf<t> expects t to be a scalar, and gives a 128-bit vector of whatever it
  251. // is.
  252. class VecOf<Type t>: ComplexType<(CTO_Vec t)>;
  253. // NarrowedVecOf<t,v> expects t to be a scalar type, and v to be a vector
  254. // type. It returns a vector type whose element type is t, and whose lane
  255. // count is the same as the lane count of v. (Used as an intermediate value
  256. // type in the IR representation of a widening load: you load a vector of
  257. // small things out of memory, and then zext/sext them into a full 128-bit
  258. // output vector.)
  259. class NarrowedVecOf<Type t, Type v>: ComplexType<(CTO_Vec t, v)>;
  260. // PredOf expects t to be a scalar, and expands to a predicate vector which
  261. // (logically speaking) has the same number of lanes as VecOf<t> would.
  262. class PredOf<Type t>: ComplexType<(CTO_Pred t)>;
  263. // Scalar expands to whatever is the main parameter type of the current
  264. // intrinsic. Vector and Predicate expand to the vector and predicate types
  265. // corresponding to that.
  266. def Scalar: ComplexType<(CTO_Parameter)>;
  267. def Vector: VecOf<Scalar>;
  268. def Predicate: PredOf<Scalar>;
  269. // MultiVector<n> expands to a type containing n instances of Vector. (There's
  270. // no need to define this for a general underlying vector type, since it's only
  271. // used by vld2q and friends, which don't need that generality.)
  272. class MultiVector<int n>: ComplexType<(CTO_Tuple<n> Vector)>;
  273. // Ptr<t> and CPtr<t> expand to a pointer to t, or a pointer to const t,
  274. // respectively.
  275. class Ptr<Type t>: ComplexType<(CTO_Pointer<0> t)>;
  276. class CPtr<Type t>: ComplexType<(CTO_Pointer<1> t)>;
  277. // CopyKind<s,k> expects s and k to be scalar types. It returns a scalar type
  278. // whose kind (signed, unsigned or float) matches that of k, and whose size
  279. // matches that of s.
  280. class CopyKind<Type s, Type k>: ComplexType<(CTO_CopyKind s, k)>;
  281. // DoubleSize<k> expects k to be a scalar type. It returns a scalar type
  282. // whose kind (signed, unsigned or float) matches that of k, and whose size
  283. // is double that of k, if possible.
  284. class DoubleSize<Type k> : ComplexType<(CTO_ScaleSize<2, 1> k)>;
  285. class HalfSize<Type k> : ComplexType<(CTO_ScaleSize<1, 2> k)>;
  286. // Unsigned<t> expects t to be a scalar type, and expands to the unsigned
  287. // integer scalar of the same size. So it returns u16 if you give it s16 or
  288. // f16 (or u16 itself). Similarly, Signed<t> makes the type signed.
  289. class Unsigned<Type t>: ComplexType<(CTO_CopyKind t, u32)>;
  290. class Signed<Type t>: ComplexType<(CTO_CopyKind t, s32)>;
  291. // UScalar and UVector expand to the unsigned-integer versions of
  292. // Scalar and Vector. SScalar and SVector are signed-integer versions.
  293. def UScalar: Unsigned<Scalar>;
  294. def UVector: VecOf<UScalar>;
  295. def SScalar: Signed<Scalar>;
  296. def SVector: VecOf<SScalar>;
  297. // DblVector expands to a vector of scalars of size twice the size of Scalar.
  298. // DblPredicate expands to a predicate corresponding to DblVector
  299. // HalfVector, similarly, expands to a vector of half-sized scalars. And
  300. // UHalfVector is a vector of half-sized _unsigned integers_.
  301. def DblVector: VecOf<DoubleSize<Scalar>>;
  302. def DblPredicate: PredOf<DoubleSize<Scalar>>;
  303. def HalfScalar: HalfSize<Scalar>;
  304. def HalfVector: VecOf<HalfScalar>;
  305. def UHalfScalar: Unsigned<HalfSize<Scalar>>;
  306. def UHalfVector: VecOf<UHalfScalar>;
  307. // Expands to the 32-bit integer of the same signedness as Scalar.
  308. def Scalar32: CopyKind<u32, Scalar>;
  309. // Expands to the 64-bit integer of the same signedness as Scalar.
  310. def Scalar64: CopyKind<u64, Scalar>;
  311. // -----------------------------------------------------------------------------
  312. // Internal definitions for specifying immediate arguments for an intrinsic.
  313. class ImmediateBounds;
  314. class Immediate<Type type_, ImmediateBounds bounds_>: Type {
  315. Type type = type_;
  316. ImmediateBounds bounds = bounds_;
  317. string extra;
  318. string extraarg;
  319. }
  320. class IB_ConstRange<int lo_, int hi_> : ImmediateBounds {
  321. int lo = lo_;
  322. int hi = hi_;
  323. }
  324. def IB_UEltValue : ImmediateBounds;
  325. def IB_LaneIndex : ImmediateBounds;
  326. class IB_EltBit<int base_, Type type_ = Scalar> : ImmediateBounds {
  327. int base = base_;
  328. Type type = type_;
  329. }
  330. def IB_ExtraArg_LaneSize;
  331. // -----------------------------------------------------------------------------
  332. // End-user definitions for immediate arguments.
  333. // imm_simd and imm_simd_restrictive are used for the immediate operands to
  334. // intrinsics like vmvnq or vorrq. imm_simd_restrictive has to be an 8-bit
  335. // value shifted left by a whole number of bytes; imm_simd_vmvn can also be of
  336. // the form 0xXXFF for some byte value XX.
  337. def imm_simd_restrictive : Immediate<Scalar, IB_UEltValue> {
  338. let extra = "ShiftedByte";
  339. let extraarg = "!lanesize";
  340. }
  341. def imm_simd_vmvn : Immediate<Scalar, IB_UEltValue> {
  342. let extra = "ShiftedByteOrXXFF";
  343. let extraarg = "!lanesize";
  344. }
  345. // imm_1toN can take any value from 1 to N inclusive, where N is the number of
  346. // bits in the main parameter type. (E.g. an immediate shift count, in an
  347. // intrinsic that shifts every lane of a vector by the same amount.)
  348. //
  349. // imm_0toNm1 is the same but with the range offset by 1, i.e. 0 to N-1
  350. // inclusive.
  351. //
  352. // imm_1toHalfN is like imm_1toN, but applied to a half-width type.
  353. // (So if Scalar is s16, for example, it'll give you the range 1 to 8.)
  354. def imm_1toN : Immediate<sint, IB_EltBit<1>>;
  355. def imm_0toNm1 : Immediate<sint, IB_EltBit<0>>;
  356. def imm_1toHalfN : Immediate<sint, IB_EltBit<1, HalfSize<Scalar>>>;
  357. // imm_lane has to be the index of a vector lane in the main vector type, i.e
  358. // it can range from 0 to (128 / size of scalar)-1 inclusive. (e.g. vgetq_lane)
  359. def imm_lane : Immediate<sint, IB_LaneIndex>;
  360. // imm_1to32 can be in the range 1 to 32, unconditionally. (e.g. scalar shift
  361. // intrinsics)
  362. def imm_1to32 : Immediate<sint, IB_ConstRange<1, 32>>;
  363. // imm_1248 can be 1, 2, 4 or 8. (e.g. vidupq)
  364. def imm_1248 : Immediate<sint, IB_ConstRange<1, 8>> {
  365. let extra = "Power2";
  366. }
  367. // imm_mem7bit<n> is a valid immediate offset for a load/store intrinsic whose
  368. // memory access size is n bytes (e.g. 1 for vldrb_[whatever], 2 for vldrh,
  369. // ...). The set of valid immediates for these is {-127*n, ..., -1*n, 0*n, 1*n,
  370. // ..., 127*n}.
  371. class imm_mem7bit<int membytes>
  372. : Immediate<sint, IB_ConstRange<!mul(membytes, -127), !mul(membytes, 127)>> {
  373. let extra = !if(!eq(membytes, 1), ?, "Multiple");
  374. let extraarg = !cast<string>(membytes);
  375. }
  376. // -----------------------------------------------------------------------------
  377. // Specification of ways that the full name of an intrinsic can be mapped to
  378. // its shorter polymorphic name.
  379. class PolymorphicNameType<int nt_, string x_> {
  380. int NumTypeSuffixesToDiscard = nt_;
  381. string ExtraSuffixToDiscard = x_;
  382. }
  383. // PNT_None: the intrinsic is not polymorphic at all, so its short name is the
  384. // same as its long name. (E.g. scalar shift intrinsics such as uqshl.)
  385. def PNT_None: PolymorphicNameType<0, ?>;
  386. // PNT_Type: the usual case, in which the polymorphic name is made by dropping
  387. // the type suffix, so it ends up the same as the Tablegen record name. E.g.
  388. // vaddq_u16 -> vaddq.
  389. def PNT_Type: PolymorphicNameType<1, ?>;
  390. // PNT_2Type: the polymorphic name is made by dropping _two_ type suffixes.
  391. // E.g. vcvtq_f16_u16 -> vcvtq.
  392. def PNT_2Type: PolymorphicNameType<2, ?>;
  393. // PNT_NType: the polymorphic name is made by dropping an "_n" suffix and a
  394. // type. E.g. vaddq_n_u16 -> vaddq.
  395. def PNT_NType: PolymorphicNameType<1, "n">;
  396. // PNT_NType: the polymorphic name is made by just dropping an "_n" suffix
  397. // (even if it isn't at the end of the name). E.g. vidupq_n_u16 -> vidupq_u16.
  398. def PNT_N: PolymorphicNameType<0, "n">;
  399. // PNT_WBType: the polymorphic name is made by dropping an "_wb" suffix and a
  400. // type. E.g. vidupq_m_wb_u16 -> vidupq_m.
  401. def PNT_WBType: PolymorphicNameType<1, "wb">;
  402. // PNT_WB: the polymorphic name is made by just dropping "_wb". E.g.
  403. // vidupq_wb_u16 -> vidupq_u16.
  404. def PNT_WB: PolymorphicNameType<0, "wb">;
  405. // -----------------------------------------------------------------------------
  406. // The main class Intrinsic. Define one of these for each family of ACLE
  407. // intrinsics which are the same apart from some final type suffix (e.g.
  408. // vaddq_{s8,u8,f16,...}.
  409. //
  410. // The record's name plus that type suffix is taken to be the full unambiguous
  411. // name of the function. Its shorter polymorphic name is constructed from that
  412. // in turn, in a way specified by the PolymorphicNameType system above.
  413. class Intrinsic<Type ret_, dag args_, dag codegen_> {
  414. // List of parameter types to suffix to this intrinsic's name. A separate
  415. // actual ACLE intrinsic will be generated for each of these. Set it to
  416. // [Void] if the intrinsic is not polymorphic at all.
  417. list<Type> params;
  418. // Return type and arguments for the intrinsic.
  419. Type ret = ret_;
  420. dag args = args_;
  421. // Specification of how to generate its IR.
  422. dag codegen = codegen_;
  423. // Default to PNT_Type, which is by far the most common case.
  424. PolymorphicNameType pnt = PNT_Type;
  425. // A very few intrinsics _only_ have a polymorphic name.
  426. bit polymorphicOnly = 0;
  427. // True if the builtin has to avoid evaluating its arguments.
  428. bit nonEvaluating = 0;
  429. // True if the intrinsic needs only the C header part (no codegen, semantic
  430. // checks, etc). Used for redeclaring MVE intrinsics in the arm_cde.h header.
  431. bit headerOnly = 0;
  432. // Use to override the suffix letter to make e.g.vfooq_p16
  433. // with an override suffix letter of "p".
  434. string overrideKindLetter = "";
  435. // Name of the architecture extension, used in the Clang builtin name
  436. string builtinExtension = "mve";
  437. }
  438. // Sometimes you have to use two separate Intrinsic declarations to
  439. // declare intrinsics that are logically the same family (e.g. vaddq,
  440. // because it needs to expand to an Add or FAdd IR node depending on
  441. // type). For that purpose, you can derive from NameOverride to
  442. // specify the intrinsic's base name independently of the Tablegen
  443. // record name.
  444. class NameOverride<string basename_> {
  445. string basename = basename_;
  446. }
  447. // A wrapper to define both _m and _x versions of a predicated
  448. // intrinsic.
  449. //
  450. // We provide optional parameters to override the polymorphic name
  451. // types separately for the _m and _x variants, because sometimes they
  452. // polymorph differently (typically because the type of the inactive
  453. // parameter can be used as a disambiguator if it's present).
  454. multiclass IntrinsicMX<Type rettype, dag arguments, dag cg,
  455. bit wantXVariant = 1,
  456. string nameSuffix = "",
  457. PolymorphicNameType pnt_m = PNT_Type,
  458. PolymorphicNameType pnt_x = PNT_Type> {
  459. // The _m variant takes an initial parameter called $inactive, which
  460. // provides the input value of the output register, i.e. all the
  461. // inactive lanes in the predicated operation take their values from
  462. // this.
  463. def : Intrinsic<rettype, !con((args rettype:$inactive), arguments), cg>,
  464. NameOverride<NAME # "_m" # nameSuffix> {
  465. let pnt = pnt_m;
  466. }
  467. if wantXVariant then {
  468. // The _x variant leaves off that parameter, and simply uses an
  469. // undef value of the same type.
  470. def : Intrinsic<rettype, arguments, (seq (undef rettype):$inactive, cg)>,
  471. NameOverride<NAME # "_x" # nameSuffix> {
  472. let pnt = pnt_x;
  473. }
  474. }
  475. }
  476. // Same as above, but with an additional parameter 'basename' which overrides
  477. // the C intrinsic base name
  478. multiclass IntrinsicMXNameOverride<Type rettype, dag arguments, dag cg,
  479. string basename, bit wantXVariant = 1,
  480. string nameSuffix = "",
  481. PolymorphicNameType pnt_m = PNT_Type,
  482. PolymorphicNameType pnt_x = PNT_Type> {
  483. def "_m" # nameSuffix:
  484. Intrinsic<rettype, !con((args rettype:$inactive), arguments), cg>,
  485. NameOverride<basename # "_m" # nameSuffix> {
  486. let pnt = pnt_m;
  487. }
  488. if wantXVariant then {
  489. def "_x" # nameSuffix:
  490. Intrinsic<rettype, arguments, (seq (undef rettype):$inactive, cg)>,
  491. NameOverride<basename # "_x" # nameSuffix> {
  492. let pnt = pnt_x;
  493. }
  494. }
  495. }
  496. // -----------------------------------------------------------------------------
  497. // Convenience lists of parameter types. 'T' is just a container record, so you
  498. // can define a typical intrinsic with 'let Params = T.Usual', or similar,
  499. // instead of having to repeat a long list every time.
  500. def T {
  501. list<Type> None = [Void];
  502. list<Type> Signed = [s8, s16, s32];
  503. list<Type> Unsigned = [u8, u16, u32];
  504. list<Type> Int = Signed # Unsigned;
  505. list<Type> Float = [f16, f32];
  506. list<Type> Usual = Int # Float;
  507. list<Type> Int8 = [s8, u8];
  508. list<Type> Int16 = [s16, u16];
  509. list<Type> Int32 = [s32, u32];
  510. list<Type> Int64 = [s64, u64];
  511. list<Type> Poly = [u8, u16]; // Actually p8 and p16
  512. list<Type> All8 = Int8;
  513. list<Type> All16 = Int16 # [f16];
  514. list<Type> All32 = Int32 # [f32];
  515. list<Type> All64 = Int64;
  516. list<Type> All = Usual # All64;
  517. }
  518. // -----------------------------------------------------------------------------
  519. // Container record for DAG constant values. These constants are used because
  520. // bit/int class/multiclass parameters cannot be used to produce a dag node:
  521. // for example (u32 x) where x is 0 is transformed into (u32 { 0 }) by the
  522. // Tablegen parser.
  523. def V {
  524. dag False = (u32 0);
  525. dag True = (u32 1);
  526. }