1//===--- arm_sve_sme_incl.td - ARM SVE/SME compiler interface -------------===//
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 common properites of TableGen definitions use for both
10//  SVE and SME intrinsics.
11//
12//      https://developer.arm.com/architectures/system-architectures/software-standards/acle
13//
14//===----------------------------------------------------------------------===//
15
16//===----------------------------------------------------------------------===//
17// Instruction definitions
18//===----------------------------------------------------------------------===//
19// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and
20// a sequence of typespecs.
21//
22// The name is the base name of the intrinsic, for example "svld1". This is
23// then mangled by the tblgen backend to add type information ("svld1_s16").
24//
25// A typespec is a sequence of uppercase characters (modifiers) followed by one
26// lowercase character. A typespec encodes a particular "base type" of the
27// intrinsic.
28//
29// An example typespec is "Us" - unsigned short - svuint16_t. The available
30// typespec codes are given below.
31//
32// The string given to an Inst class is a sequence of typespecs. The intrinsic
33// is instantiated for every typespec in the sequence. For example "sdUsUd".
34//
35// The prototype is a string that defines the return type of the intrinsic
36// and the type of each argument. The return type and every argument gets a
37// "modifier" that can change in some way the "base type" of the intrinsic.
38//
39// The modifier 'd' means "default" and does not modify the base type in any
40// way. The available modifiers are given below.
41//
42// Typespecs
43// ---------
44// c: char
45// s: short
46// i: int
47// l: long
48// q: int128_t
49// f: float
50// h: half-float
51// d: double
52// b: bfloat
53
54// Typespec modifiers
55// ------------------
56// P: boolean
57// U: unsigned
58// Q: svcount
59
60// Prototype modifiers
61// -------------------
62// prototype: return (arg, arg, ...)
63//
64// 2,3,4: array of default vectors
65// v: void
66// x: vector of signed integers
67// u: vector of unsigned integers
68// d: default
69// c: const pointer type
70// P: predicate type
71// s: scalar of element type
72// a: scalar of element type (splat to vector type)
73// R: scalar of 1/2 width element type (splat to vector type)
74// r: scalar of 1/4 width element type (splat to vector type)
75// @: unsigned scalar of 1/4 width element type (splat to vector type)
76// e: 1/2 width unsigned elements, 2x element count
77// b: 1/4 width unsigned elements, 4x element count
78// h: 1/2 width elements, 2x element count
79// q: 1/4 width elements, 4x element count
80// o: 4x width elements, 1/4 element count
81//
82// w: vector of element type promoted to 64bits, vector maintains
83//    signedness of its element type.
84// f: element type promoted to uint64_t (splat to vector type)
85// j: element type promoted to 64bits (splat to vector type)
86// K: element type bitcast to a signed integer (splat to vector type)
87// L: element type bitcast to an unsigned integer (splat to vector type)
88//
89// i: constant uint64_t
90// k: int32_t
91// l: int64_t
92// m: uint32_t
93// n: uint64_t
94
95// t: svint32_t
96// z: svuint32_t
97// g: svuint64_t
98// O: svfloat16_t
99// M: svfloat32_t
100// N: svfloat64_t
101
102// J: Prefetch type (sv_prfop)
103
104// %: pointer to void
105
106// A: pointer to int8_t
107// B: pointer to int16_t
108// C: pointer to int32_t
109// D: pointer to int64_t
110
111// E: pointer to uint8_t
112// F: pointer to uint16_t
113// G: pointer to uint32_t
114// H: pointer to uint64_t
115
116// Q: const pointer to void
117
118// S: const pointer to int8_t
119// T: const pointer to int16_t
120// U: const pointer to int32_t
121// V: const pointer to int64_t
122//
123// W: const pointer to uint8_t
124// X: const pointer to uint16_t
125// Y: const pointer to uint32_t
126// Z: const pointer to uint64_t
127
128// Prototype modifiers added for SVE2p1
129// }: svcount_t
130
131class MergeType<int val, string suffix=""> {
132  int Value = val;
133  string Suffix = suffix;
134}
135def MergeNone    : MergeType<0>;
136def MergeAny     : MergeType<1, "_x">;
137def MergeOp1     : MergeType<2, "_m">;
138def MergeZero    : MergeType<3, "_z">;
139def MergeAnyExp  : MergeType<4, "_x">; // Use merged builtin with explicit
140def MergeZeroExp : MergeType<5, "_z">; // generation of its inactive argument.
141
142class EltType<int val> {
143  int Value = val;
144}
145def EltTyInvalid : EltType<0>;
146def EltTyInt8    : EltType<1>;
147def EltTyInt16   : EltType<2>;
148def EltTyInt32   : EltType<3>;
149def EltTyInt64   : EltType<4>;
150def EltTyInt128  : EltType<5>;
151def EltTyFloat16 : EltType<6>;
152def EltTyFloat32 : EltType<7>;
153def EltTyFloat64 : EltType<8>;
154def EltTyBool8   : EltType<9>;
155def EltTyBool16  : EltType<10>;
156def EltTyBool32  : EltType<11>;
157def EltTyBool64  : EltType<12>;
158def EltTyBFloat16 : EltType<13>;
159
160class MemEltType<int val> {
161  int Value = val;
162}
163def MemEltTyDefault   : MemEltType<0>;
164def MemEltTyInt8      : MemEltType<1>;
165def MemEltTyInt16     : MemEltType<2>;
166def MemEltTyInt32     : MemEltType<3>;
167def MemEltTyInt64     : MemEltType<4>;
168
169class FlagType<int val> {
170  int Value = val;
171}
172
173// These must be kept in sync with the flags in utils/TableGen/SveEmitter.h
174// and include/clang/Basic/TargetBuiltins.h
175def NoFlags                   : FlagType<0x00000000>;
176def FirstEltType              : FlagType<0x00000001>;
177//      :                                     :
178//      :                                     :
179def EltTypeMask               : FlagType<0x0000000f>;
180def FirstMemEltType           : FlagType<0x00000010>;
181//      :                                     :
182//      :                                     :
183def MemEltTypeMask            : FlagType<0x00000070>;
184def FirstMergeTypeMask        : FlagType<0x00000080>;
185//      :                                     :
186//      :                                     :
187def MergeTypeMask             : FlagType<0x00000380>;
188def FirstSplatOperand         : FlagType<0x00000400>;
189//      :                                     :
190// These flags are used to specify which scalar operand
191// needs to be duplicated/splatted into a vector.
192//      :                                     :
193def SplatOperandMask          : FlagType<0x00001C00>;
194def IsLoad                    : FlagType<0x00002000>;
195def IsStore                   : FlagType<0x00004000>;
196def IsGatherLoad              : FlagType<0x00008000>;
197def IsScatterStore            : FlagType<0x00010000>;
198def IsStructLoad              : FlagType<0x00020000>;
199def IsStructStore             : FlagType<0x00040000>;
200def IsZExtReturn              : FlagType<0x00080000>; // Return value is sign-extend by default
201def IsOverloadNone            : FlagType<0x00100000>; // Intrinsic does not take any overloaded types.
202def IsOverloadWhile           : FlagType<0x00200000>; // Use {default type, typeof(operand1)} as overloaded types.
203def IsOverloadWhileRW         : FlagType<0x00400000>; // Use {pred(default type), typeof(operand0)} as overloaded types.
204def IsOverloadCvt             : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types.
205def OverloadKindMask          : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type.
206def IsByteIndexed             : FlagType<0x01000000>;
207def IsAppendSVALL             : FlagType<0x02000000>; // Appends SV_ALL as the last operand.
208def IsInsertOp1SVALL          : FlagType<0x04000000>; // Inserts SV_ALL as the second operand.
209def IsPrefetch                : FlagType<0x08000000>; // Contiguous prefetches.
210def IsGatherPrefetch          : FlagType<0x10000000>;
211def ReverseCompare            : FlagType<0x20000000>; // Compare operands must be swapped.
212def ReverseUSDOT              : FlagType<0x40000000>; // Unsigned/signed operands must be swapped.
213def IsUndef                   : FlagType<0x80000000>; // Codegen `undef` of given type.
214def IsTupleCreate             : FlagType<0x100000000>;
215def IsTupleGet                : FlagType<0x200000000>;
216def IsTupleSet                : FlagType<0x400000000>;
217def ReverseMergeAnyBinOp      : FlagType<0x800000000>; // e.g. Implement SUBR_X using SUB_X.
218def ReverseMergeAnyAccOp      : FlagType<0x1000000000>; // e.g. Implement MSB_X using MLS_X.
219def IsStreaming               : FlagType<0x2000000000>;
220def IsStreamingCompatible     : FlagType<0x4000000000>;
221def IsSharedZA                : FlagType<0x8000000000>;
222def IsPreservesZA             : FlagType<0x10000000000>;
223def IsReadZA                  : FlagType<0x20000000000>;
224def IsWriteZA                 : FlagType<0x40000000000>;
225
226// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h
227class ImmCheckType<int val> {
228  int Value = val;
229}
230def ImmCheck0_31                : ImmCheckType<0>;  // 0..31 (used for e.g. predicate patterns)
231def ImmCheck1_16                : ImmCheckType<1>;  // 1..16
232def ImmCheckExtract             : ImmCheckType<2>;  // 0..(2048/sizeinbits(elt) - 1)
233def ImmCheckShiftRight          : ImmCheckType<3>;  // 1..sizeinbits(elt)
234def ImmCheckShiftRightNarrow    : ImmCheckType<4>;  // 1..sizeinbits(elt)/2
235def ImmCheckShiftLeft           : ImmCheckType<5>;  // 0..(sizeinbits(elt) - 1)
236def ImmCheck0_7                 : ImmCheckType<6>;  // 0..7
237def ImmCheckLaneIndex           : ImmCheckType<7>;  // 0..(128/(1*sizeinbits(elt)) - 1)
238def ImmCheckLaneIndexCompRotate : ImmCheckType<8>;  // 0..(128/(2*sizeinbits(elt)) - 1)
239def ImmCheckLaneIndexDot        : ImmCheckType<9>;  // 0..(128/(4*sizeinbits(elt)) - 1)
240def ImmCheckComplexRot90_270    : ImmCheckType<10>; // [90,270]
241def ImmCheckComplexRotAll90     : ImmCheckType<11>; // [0, 90, 180,270]
242def ImmCheck0_13                : ImmCheckType<12>; // 0..13
243def ImmCheck0_1                 : ImmCheckType<13>; // 0..1
244def ImmCheck0_2                 : ImmCheckType<14>; // 0..2
245def ImmCheck0_3                 : ImmCheckType<15>; // 0..3
246def ImmCheck0_0                 : ImmCheckType<16>; // 0..0
247def ImmCheck0_15                : ImmCheckType<17>; // 0..15
248def ImmCheck0_255               : ImmCheckType<18>; // 0..255
249
250class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> {
251  int Arg = arg;
252  int EltSizeArg = eltSizeArg;
253  ImmCheckType Kind = kind;
254}
255
256class Inst<string n, string p, string t, MergeType mt, string i,
257           list<FlagType> ft, list<ImmCheck> ch, MemEltType met> {
258  string Name = n;
259  string Prototype = p;
260  string Types = t;
261  string TargetGuard = "sve";
262  int Merge = mt.Value;
263  string MergeSuffix = mt.Suffix;
264  string LLVMIntrinsic = i;
265  list<FlagType> Flags = ft;
266  list<ImmCheck> ImmChecks = ch;
267  int MemEltType = met.Value;
268}
269
270// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8")
271class SInst<string n, string p, string t, MergeType mt, string i = "",
272            list<FlagType> ft = [], list<ImmCheck> ch = []>
273    : Inst<n, p, t, mt, i, ft, ch, MemEltTyDefault> {
274}
275
276// MInst: Instructions which access memory
277class MInst<string n, string p, string t, list<FlagType> f,
278            MemEltType met = MemEltTyDefault, string i = "",
279            list<ImmCheck> ch = []>
280    : Inst<n, p, t, MergeNone, i, f, ch, met> {
281}
282