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