1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #ifndef IGA_IR_TYPES_HPP
10 #define IGA_IR_TYPES_HPP
11
12 // WARNING: the IR is subject to change without any notice. External tools
13 // should use the official interfaces in the external API. Those interfaces
14 // are tested between releases and maintained even with changes to the IR.
15
16
17 #include <cstdint>
18 #include <tuple>
19
20 #include "../EnumBitset.hpp"
21 #include "../api/iga_bxml_enums.hpp"
22 #include "../api/iga_types_ext.hpp"
23
24 namespace iga
25 {
26
27 // The GEN platform version
28 enum class Platform
29 {
30 // GEN version encoding. The version encoding must be the same as GEN_VER in iga.h
31 #define IGA_GEN_VER_ORDINAL(MAJ,MIN) ((MAJ)<<16)|(MIN)
32
33 // XE version encoding. The version encoding must be the same as XE_VER in iga.h
34 #define IGA_XE_VER_ORDINAL(XE,SUBVER) (((XE)<<24)|SUBVER)
35
36 INVALID = 0,
37
38 GEN6 = IGA_GEN_VER_ORDINAL( 6, 0 ),
39 GEN7 = IGA_GEN_VER_ORDINAL( 7, 0 ),
40 GEN7P5 = IGA_GEN_VER_ORDINAL( 7, 5 ),
41 GEN8 = IGA_GEN_VER_ORDINAL( 8, 0 ),
42 GEN8LP = IGA_GEN_VER_ORDINAL( 8, 1 ),
43 GEN9 = IGA_GEN_VER_ORDINAL( 9, 0 ),
44 GEN9LP = IGA_GEN_VER_ORDINAL( 9, 1 ),
45 GEN9P5 = IGA_GEN_VER_ORDINAL( 9, 5 ),
46 GEN10 = IGA_GEN_VER_ORDINAL(10, 0 ),
47 GEN11 = IGA_GEN_VER_ORDINAL(11, 0 ),
48 // XE version
49 XE = IGA_XE_VER_ORDINAL(1, 0), // TGL
50 XE_HP = IGA_XE_VER_ORDINAL(1, 1), // XE_HP
51 XE_HPG = IGA_XE_VER_ORDINAL(1, 2),
52 XE_HPC = IGA_XE_VER_ORDINAL(1, 4), // XeHPC-XT, preserved (1, 3) for XeHPC-XL
53 FUTURE = 0x7FFFFFFF
54 #undef IGA_GEN_VER_ORDINAL
55 };
56
57 struct Predication
58 {
59 PredCtrl function;
60 bool inverse; // TODO: enum
61
Predicationiga::Predication62 Predication() : function(PredCtrl::NONE), inverse(false) { }
Predicationiga::Predication63 Predication(PredCtrl ctrl, bool inv) : function(ctrl), inverse(inv) { }
64 };
65
66
67 typedef BranchCtrl BranchCntrl; // for backwards compatibility
68
ExecSizeToInt(ExecSize es)69 static inline int ExecSizeToInt(ExecSize es)
70 {
71 return static_cast<int>(es);
72 }
ExecSizeFromInt(int es)73 static inline ExecSize ExecSizeFromInt(int es)
74 {
75 return static_cast<ExecSize>(es);
76 }
77
78 // for math macro register access (madm, math.invm, and math.rsqrtm)
79 // e.g. madm (8) r13.mme2:f r14:mme7:f r16:nomme ...
80 // ^^^^ ^^^^ ^^^^^
81 enum class MathMacroExt
82 {
83 INVALID,
84 MME0, // encodes as 0000b
85 MME1, // encodes as 0001b
86 MME2, // encodes as 0010b
87 MME3, // encodes as 0011b
88 MME4, // encodes as 0100b
89 MME5, // encodes as 0101b
90 MME6, // encodes as 0110b
91 MME7, // encodes as 0111b
92 NOMME, // encodes as 1000b
93 };
94
95
96 // how much to shift <right,left> to get to from byte offset
97 // to subregister offset
98 // I.e. subReg = (byteOff << left) >> right;
99 // this allows us to scale a subregister byte offset up OR down
100 static inline std::tuple<uint32_t, uint32_t>
TypeSizeShiftsOffsetToSubreg(Type type)101 TypeSizeShiftsOffsetToSubreg(Type type)
102 {
103 uint32_t shl = 0, shr = 0; // by default no scaling
104
105 switch (type) {
106 // subbyte types
107 case Type::U1:
108 shl = 3;
109 break;
110 case Type::U2:
111 case Type::S2:
112 shl = 2;
113 break;
114 case Type::U4:
115 case Type::S4:
116 shl = 1;
117 break;
118
119 case Type::QF:
120 case Type::BF8:
121 break;
122 case Type::TF32:
123 shr = 2;
124 break;
125
126 // 1-byte types
127 case Type::UB:
128 case Type::B:
129 break;
130 // 2-byte types
131 case Type::UW:
132 case Type::W:
133 case Type::HF:
134 case Type::BF:
135 shr = 1;
136 break;
137 // 4-byte types
138 case Type::UD:
139 case Type::D:
140 case Type::F:
141 case Type::NF: // NF regions the same as F
142 shr = 2;
143 break;
144 case Type::UQ:
145 case Type::Q:
146 case Type::DF:
147 shr = 3;
148 break;
149 default: // invalid types
150 break;
151 }
152 return std::make_tuple(shl,shr);
153 }
154
155 // e.g. Type::UD == 32
TypeSizeInBits(Type t)156 static inline uint32_t TypeSizeInBits(Type t)
157 {
158 auto ti = TypeSizeShiftsOffsetToSubreg(t);
159 return (8 << std::get<1>(ti)) >> std::get<0>(ti);
160 }
TypeSizeInBitsWithDefault(Type type,int dft=0)161 static inline uint32_t TypeSizeInBitsWithDefault(Type type, int dft = 0)
162 {
163 return type == Type::INVALID ? dft : TypeSizeInBits(type);
164 }
TypeIs64b(Type t)165 static inline bool TypeIs64b(Type t)
166 {
167 return TypeSizeInBitsWithDefault(t,0) == 64;
168 }
TypeIsFloating(Type t)169 static inline bool TypeIsFloating(Type t)
170 {
171 switch (t)
172 {
173 case Type::F:
174 case Type::BF:
175 case Type::QF:
176 case Type::BF8:
177 case Type::TF32:
178 case Type::HF:
179 case Type::DF:
180 case Type::VF:
181 case Type::NF:
182 return true;
183 default:
184 return false;
185 }
186 }
187 // static inline bool TypeIsSubByte(Type t) {
188 // return std::get<1>(TypeSizeShiftsOffsetToSubreg(t)) > 0;
189 // }
190
191 struct Region {
192 enum class Vert {
193 VT_0 = 0,
194 VT_1 = 1,
195 VT_2 = 2,
196 VT_4 = 4,
197 VT_8 = 8,
198 VT_16 = 16,
199 VT_32 = 32,
200
201 VT_VxH = 31, // special VxH mode for indirect region
202 VT_INVALID = 63,
203 };
204 enum class Width {
205 WI_1 = 1,
206 WI_2 = 2,
207 WI_4 = 4,
208 WI_8 = 8,
209 WI_16 = 16,
210 WI_INVALID = 31
211 };
212 enum class Horz {
213 HZ_0 = 0, // not permitted on DstOps (unless MBZ)
214 HZ_1 = 1,
215 HZ_2 = 2,
216 HZ_4 = 4,
217 HZ_INVALID = 15
218 };
219 union {
220 struct {
221 unsigned int v : 6;
222 unsigned int w : 5;
223 unsigned int h : 4;
224 };
225 uint32_t bits;
226 };
227
setiga::Region228 constexpr void set(Vert _v, Width _w, Horz _h) {
229 this->bits = 0; // clear padding
230 v = static_cast<unsigned int>(_v);
231 w = static_cast<unsigned int>(_w);
232 h = static_cast<unsigned int>(_h);
233 }
234
setiga::Region235 constexpr void set(Vert vt) {
236 v = static_cast<unsigned int>(vt);
237 }
setiga::Region238 constexpr void set(Width wi) {
239 w = static_cast<unsigned int>(wi);
240 }
setiga::Region241 constexpr void set(Horz hz) {
242 h = static_cast<unsigned int>(hz);
243 }
setDstHziga::Region244 constexpr void setDstHz(Horz hz) {
245 set(Vert::VT_INVALID, Width::WI_INVALID, hz);
246 }
247
getHziga::Region248 Horz getHz() const {return static_cast<Horz>(h);}
getVtiga::Region249 Vert getVt() const {return static_cast<Vert>(v);}
getWiiga::Region250 Width getWi() const {return static_cast<Width>(w);}
251
252 // checks if a region is invalid (assembler will program it to correct bits)
isInvalidiga::Region253 bool isInvalid() const {
254 return *this == INVALID;
255 }
256 // checks if a region is of the for <V;W,H>
isVWHiga::Region257 bool isVWH() const {
258 return
259 getVt() != Vert::VT_INVALID &&
260 getWi() != Width::WI_INVALID &&
261 getHz() != Horz::HZ_INVALID;
262 }
263
264 // define [in]equality based on bits
operator ==iga::Region265 bool operator ==(const Region &b) const {
266 // careful: fails if padding differs (we prevent that now)
267 return b.bits == bits;
268 }
operator !=iga::Region269 bool operator !=(const Region &b) const {
270 return !(*this == b);
271 }
272
273
274 // some useful region constants
275 static const Region INVALID; // all RESERVED elements
276 //
277 // dst
278 static const Region DST1; // <1>
279 static const Region DST2; // <2>
280 static const Region DST4; // <4>
281 //
282 // generalized src regions
283 static const Region SRC010; // <0;1,0> (broadcast scalar)
284 static const Region SRC110; // <1;1,0> (packed access)
285 static const Region SRC210; // <2;1,0> (even strided access)
286 static const Region SRC410; // <4;1,0> (quarter stided access)
287 //
288 // older src regions
289 static const Region SRC221; // <2;2,1>
290 static const Region SRC441; // <4;4,1>
291 static const Region SRC881; // <8;8,1>
292 static const Region SRCFF1; // <16;16,1>
293 //
294 // special cases
295 // ternary src0/src1
296 static const Region SRC0X0; // <0;0> (ternary align1 src0 and src1)
297 static const Region SRC2X1; // <2;1> (ternary align1 src0 and src1)
298 static const Region SRC1X0; // <1;0> XE_LP changes 2 to 1 in encoding
299 static const Region SRC4X1; // <4;1> (ternary align1 src0 and src1)
300 // ternary src2
301 static const Region SRC8X1; // <8;1> (ternary align1 src0 and src1)
302 static const Region SRCXX0; // <0> (ternary align1 src2)
303 static const Region SRCXX1; // <1> (ternary align1 src2)
304 static const Region SRCXX2; // <2> (ternary align1 src2)
305 };
306
307 // A set of instruction options
308 typedef EnumBitset<InstOpt> InstOptSet;
309
310
311 struct RegRef {
312 uint16_t regNum = 0;
313 uint16_t subRegNum = 0;
314
RegRefiga::RegRef315 constexpr RegRef() { }
RegRefiga::RegRef316 constexpr RegRef(uint16_t rNum, uint16_t srNum)
317 : regNum(rNum), subRegNum(srNum) { }
RegRefiga::RegRef318 constexpr RegRef(int rNum, int srNum)
319 : regNum((uint8_t)rNum), subRegNum((uint8_t)srNum) { }
RegRefiga::RegRef320 constexpr RegRef(uint32_t rNum, uint32_t srNum)
321 : regNum((uint8_t)rNum), subRegNum((uint8_t)srNum) { }
322
operator ==iga::RegRef323 bool operator==(const RegRef &rr) const {
324 return regNum == rr.regNum && subRegNum == rr.subRegNum;
325 }
operator !=iga::RegRef326 bool operator!=(const RegRef &rr) const {
327 return !(*this == rr);
328 }
329 };
330
331 static constexpr RegRef REGREF_INVALID {0xFF, 0xFF};
332 static constexpr RegRef REGREF_ZERO_ZERO {0, 0};
333
334 struct SendDesc {
335 enum class Kind {IMM, REG32A};
336 Kind type;
337
338 union {
339 RegRef reg;
340 uint32_t imm;
341 };
342
SendDesciga::SendDesc343 constexpr SendDesc() : SendDesc(0) { }
SendDesciga::SendDesc344 constexpr SendDesc(uint32_t desc) : type(Kind::IMM), imm(desc) { }
SendDesciga::SendDesc345 constexpr SendDesc(RegRef a0r) : type(Kind::REG32A), reg(a0r) { }
346
isRegiga::SendDesc347 bool isReg() const {return type == Kind::REG32A;}
isImmiga::SendDesc348 bool isImm() const {return type == Kind::IMM;}
349 };
350
351 } // namespace
352 #endif
353