File: GenXIntrinsics.h

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (315 lines) | stat: -rw-r--r-- 15,039 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

//
// This file declares a class to access a table of extra information about the
// llvm.genx.* intrinsics, used by the vISA register allocator and function
// writer to decide exactly what operand type to use. The more usual approach
// in an LLVM target is to have an intrinsic map to an instruction in
// instruction selection, then have register category information on the
// instruction. But we are not using the target independent code generator, we
// are generating code directly from LLVM IR.
//
//===----------------------------------------------------------------------===//
#ifndef GENXINTRINSICS_H
#define GENXINTRINSICS_H
#include "GenX.h"
#include "GenXVisa.h"
#include "Probe/Assertion.h"
#include <unordered_map>

#define GENX_ITR_CATVAL(v) ((v) << CATBASE)
#define GENX_ITR_FLAGENUM(o, v) ((v) << ((o) + FLAGBASE))
#define GENX_ITR_FLAGMASK(o, w) (((1 << (w)) - 1) << ((o) + FLAGBASE))
#define GENX_ITR_FLAGVAL(o) GENX_ITR_FLAGENUM(o, 1)

namespace llvm {
class CallInst;

class GenXIntrinsicInfo {
public:
  enum {
    // General format of intrinsic descriptor words:
    //   Bits 31..24: Category enumeration
    //   Bits 23..8:  Flags, if any, meaning and layout depends on category
    //   Bits 7..0:   Operand or literal, if any
    //
    // One exception to the above is LITERAL, where everything that isn't
    // the category field is assumed to be the literal value.
    //
    // If you want to re-apportion space in the descriptor word (typically
    // because you need another flag and you can't express what you need to
    // do without creating one) then just modify FLAGBASE and FLAGWIDTH
    // below, and everything else will shake itself out appropriately.
    // Currently 8 bits are allocated for the category enumaration bitfield,
    // although the actual enumeration values defined only require 6 bits -
    // and there is still plenty of space left over even within that.
    // Similarly, there are 8 bits allocated to the operand bitfield, and
    // currently the maximum needed is 5.
    //
    // At the moment, the GENERAL category has 4 unused flag bits available
    // to it, the RAW category has 13 unused bits, and the ARGCOUNT category
    // has 13 unused bits. No other categories make use of the flags yet,
    // so it should be a good while yet before it's necessary to resize
    // the bitfields.

    FLAGBASE = 8,
    FLAGWIDTH = 16,
    CATBASE = FLAGBASE + FLAGWIDTH,

    CATMASK = ~((1 << CATBASE) - 1),
    FLAGMASK = ((~((1 << FLAGBASE) - 1)) ^ CATMASK),
    OPNDMASK = ~(CATMASK | FLAGMASK),

    // A field that does not contain an operand number or literal value:
    IMPLICITPRED =          GENX_ITR_CATVAL(0x01), // implicit predication field
    NULLRAW =               GENX_ITR_CATVAL(0x02), // null raw operand
    ISBARRIER =             GENX_ITR_CATVAL(0x03), // intrinsic is barrier: suppress nobarrier attribute

    EXECSIZE =              GENX_ITR_CATVAL(0x04), // execution size
    EXECSIZE_GE2 =          GENX_ITR_CATVAL(0x05), // execution size (must be >= 2)
    EXECSIZE_GE4 =          GENX_ITR_CATVAL(0x06), // execution size (must be >= 4)
    EXECSIZE_GE8 =          GENX_ITR_CATVAL(0x07), // execution size (must be >= 8)
    EXECSIZE_NOT2 =         GENX_ITR_CATVAL(0x08), // execution size (cannot be 2)

    ELEMENTWISE =           GENX_ITR_CATVAL(0x09), // intrinsic has element-wise semantics

    // A field that contains a literal value the operand field
    LITERAL =               GENX_ITR_CATVAL(0x0a), // literal byte (usually opcode)
    LITMASK =               ~CATMASK,

    // A field that contains an operand number, other than general:
    FIRST_OPERAND =         GENX_ITR_CATVAL(0x10),
    LOG2OWORDS =            GENX_ITR_CATVAL(0x10), // log2 number of owords
    NUMGRFS =               GENX_ITR_CATVAL(0x11), // rounded up number of GRFs
    EXECSIZE_FROM_ARG =     GENX_ITR_CATVAL(0x12), // exec_size field inferred from width of
                                                   // predication arg
    SVMGATHERBLOCKSIZE =    GENX_ITR_CATVAL(0x13), // svm gather block size, inferred from data type
    LOG2OWORDS_PLUS_8 =     GENX_ITR_CATVAL(0x14), // log2 number of owords, plus 8
    GATHERNUMELTS =         GENX_ITR_CATVAL(0x15), // gather/scatter "num elements" field
    TRANSPOSEHEIGHT =       GENX_ITR_CATVAL(0x16), // block_height field in transpose
    LOG2ELTSIZE =           GENX_ITR_CATVAL(0x17), // log2 element size in gather/scatter
    ARGCOUNT =              GENX_ITR_CATVAL(0x18), // Byte containing number of non-undef operands
    EXECSIZE_FROM_BYTE =    GENX_ITR_CATVAL(0x19), // exec_size specified in byte
      ARGCOUNTMASK =        GENX_ITR_FLAGMASK(0, 3), // Space for minumum argument count
      ARGCOUNTMIN1 =        GENX_ITR_FLAGENUM(0, 1), // Must have at least one argument
    BITWIDTH =              GENX_ITR_CATVAL(0x1a), // bit width of svm atomic instructions

    // A field that contains an operand number, other than general, and it
    // is the "real" use of the operand, rather than an auxiliary use
    // such as a "number of GRFs" field relating to this operand.
    FIRST_REAL_OPERAND =    GENX_ITR_CATVAL(0x20),
    BYTE =                  GENX_ITR_CATVAL(0x20), // constant byte operand
    SHORT =                 GENX_ITR_CATVAL(0x21), // constant short operand
    INT =                   GENX_ITR_CATVAL(0x22), // constant int operand
    ADDRESS =               GENX_ITR_CATVAL(0x23), // address operand
    PREDICATE =             GENX_ITR_CATVAL(0x24), // predicate operand
      PREDICATE_ZEROED =    GENX_ITR_FLAGVAL(0),
    Z_PREDICATE = PREDICATE | PREDICATE_ZEROED,
    SAMPLER =               GENX_ITR_CATVAL(0x25), // sampler operand
    SURFACE =               GENX_ITR_CATVAL(0x26), // surface operand
    // byte height of media 2D block, inferred from the width operand
    // pointed at and the size of the return type or final operand type
    MEDIAHEIGHT =           GENX_ITR_CATVAL(0x27),
    // predication control field from explicit predicate arg
    PREDICATION =           GENX_ITR_CATVAL(0x28),
    // chmask field in load/sample, with exec size bit
    SAMPLECHMASK =          GENX_ITR_CATVAL(0x29),
    // does not appear in the vISA output, but needs to be two address
    // coalesced with result
    TWOADDR =               GENX_ITR_CATVAL(0x2a),
    CONSTVI1ASI32 =         GENX_ITR_CATVAL(0x2b), // constant vXi1 written as i32 (used in setp)
    RAW =                   GENX_ITR_CATVAL(0x2c), // raw operand or result,
      // Raw descriptor flags, 3 bits used
      RAW_UNSIGNED =        GENX_ITR_FLAGVAL(0),   // raw operand/result must be unsigned
      RAW_SIGNED =          GENX_ITR_FLAGVAL(1),   // raw operand/result must be signed
      RAW_NULLALLOWED =     GENX_ITR_FLAGVAL(2),   // raw operand or result can be null (V0)
    URAW =                  RAW | RAW_UNSIGNED,
    SRAW =                  RAW | RAW_SIGNED,
    EXECSIZE_NOMASK =       GENX_ITR_CATVAL(0x2d), // execution size with NoMask

    // A general operand
    GENERAL =               GENX_ITR_CATVAL(0x2e),
    // A general operand with compile-time signedness choosing
    GENERAL_CTSIGN =        GENERAL,
    // A predefined surface operand
    PREDEF_SURFACE =        GENX_ITR_CATVAL(0x2f),
    // Modifiers for destination or source, 7 bits used
    UNSIGNED =              GENX_ITR_FLAGVAL(0), // int type forced to unsigned
    SIGNED =                GENX_ITR_FLAGVAL(1), // int type forced to signed
    OWALIGNED =             GENX_ITR_FLAGVAL(2), // must be oword aligned
    GRFALIGNED =            GENX_ITR_FLAGVAL(3), // must be grf aligned
    RESTRICTION =           GENX_ITR_FLAGMASK(4, 3), // field with operand width restriction
      FIXED4 =              GENX_ITR_FLAGENUM(4, 1), // operand is fixed size 4 vector and contiguous
      CONTIGUOUS =          GENX_ITR_FLAGENUM(4, 2), // operand must be contiguous
      SCALARORCONTIGUOUS =  GENX_ITR_FLAGENUM(4, 3), // operand must be stride 0 or contiguous
      TWICEWIDTH =          GENX_ITR_FLAGENUM(4, 4), // operand is twice the execution width
      STRIDE1 =             GENX_ITR_FLAGENUM(4, 5), // horizontal stride must be 1
      ONLY_LEGAL_REGION =   GENX_ITR_FLAGENUM(4, 6), // instruction can be baled with only legal
                                                     // region that won`t be splitted
    // Modifiers for destination only, 2 bits used
    SATURATION =            GENX_ITR_FLAGMASK(7, 2),
    SATURATION_DEFAULT =    GENX_ITR_FLAGENUM(7, 0), // saturation default: not saturated, fp is
                                                     //  allowed to bale in to saturate inst
    SATURATION_SATURATE =   GENX_ITR_FLAGENUM(7, 1), // saturated
    SATURATION_NOSAT =      GENX_ITR_FLAGENUM(7, 2), // fp not allowed to bale in to saturate inst
    SATURATION_INTALLOWED = GENX_ITR_FLAGENUM(7, 3), // int is allowed to bale in to saturate,
                                   // because inst cannot overflow so
                                   // saturation only required on destination
                                   // truncation
    // Modifiers for source only, 3 bits used
    NOIMM =                 GENX_ITR_FLAGVAL(7), // source not allowed to be immediate
    MODIFIER =              GENX_ITR_FLAGMASK(8, 2),
    MODIFIER_DEFAULT =      GENX_ITR_FLAGENUM(8, 0), // src modifier default: none
    MODIFIER_ARITH =        GENX_ITR_FLAGENUM(8, 1), // src modifier: arithmetic
    MODIFIER_LOGIC =        GENX_ITR_FLAGENUM(8, 2), // src modifier: logic
    MODIFIER_EXTONLY =      GENX_ITR_FLAGENUM(8, 3), // src modifier: extend only
    DIRECTONLY =            GENX_ITR_FLAGVAL(10), // indirect region not allowed
  };
  struct ArgInfo {
    unsigned Info;
    // Construct argument with empty info.
    ArgInfo() : Info(0) {}
    // Construct from a field read from the intrinsics info table.
    ArgInfo(unsigned Info) : Info(Info) {}
    // getCategory : return field category
    unsigned getCategory() const { return Info & CATMASK; }
    // getAlignment : get any special alignment requirement, else align to 1
    // byte
    VISA_Align getAlignment() const {
      if (isGeneral()) {
        if (Info & GRFALIGNED)
          return VISA_Align::ALIGN_GRF;
        if (Info & OWALIGNED)
          return VISA_Align::ALIGN_OWORD;
        return VISA_Align::ALIGN_BYTE;
      }
      if (isRaw())
        return VISA_Align::ALIGN_GRF;
      return VISA_Align::ALIGN_BYTE;
    }
    // isGeneral : test whether this is a general operand
    bool isGeneral() const { return getCategory() == GENERAL; }
    bool needsSigned() const {
      if (isGeneral())
        return Info & SIGNED;
      if (isRaw())
        return Info & RAW_SIGNED;
      return false;
    }
    bool needsUnsigned() const {
      if (isGeneral())
        return Info & UNSIGNED;
      if (isRaw())
        return Info & RAW_UNSIGNED;
      return false;
    }
    bool isDirectOnly() const { return Info & DIRECTONLY; }
    bool rawNullAllowed() const {
      IGC_ASSERT(isRaw());
      return Info & RAW_NULLALLOWED;
    }
    // isArgOrRet : test whether this field has an arg index
    bool isArgOrRet() const {
      if (isGeneral()) return true;
      if ((Info & CATMASK) >= FIRST_OPERAND)
        return true;
      return false;
    }
    // isRealArgOrRet : test whether this field has an arg index, and is
    // a "real" use of the arg
    bool isRealArgOrRet() const {
      if (isGeneral()) return true;
      if ((Info & CATMASK) >= FIRST_REAL_OPERAND)
        return true;
      return false;
    }
    // getArgCountMin : return minimum number of arguments
    int getArgCountMin() const {
      IGC_ASSERT(getCategory() == ARGCOUNT);
      return (Info & ARGCOUNTMASK) >> FLAGBASE;
    }
    // getArgIdx : return argument index for this field, or -1 for return value
    //  (assuming isArgOrRet())
    int getArgIdx() const {
      IGC_ASSERT(isArgOrRet());
      return (Info & OPNDMASK) - 1;
    }
    // getLiteral : for a LITERAL or EXECSIZE field, return the literal value
    unsigned getLiteral() const { return Info & LITMASK; }
    // isRet : test whether this is the field for the return value
    //  (assuming isArgOrRet())
    bool isRet() const { return getArgIdx() < 0; }
    // isRaw : test whether this is a raw arg or return value
    bool isRaw() const { return getCategory() == RAW; }
    // getSaturation : return saturation info for the arg
    unsigned getSaturation() const { return Info & SATURATION; }
    // getRestriction : return operand width/region restriction, one of
    // 0 (no restriction), FIXED4, CONTIGUOUS, TWICEWIDTH
    unsigned getRestriction() const { return Info & RESTRICTION; }
    // isImmediateDisallowed : test whether immediate disallowed
    //  (assuming isArgOrRet())
    bool isImmediateDisallowed() const {
      IGC_ASSERT(isArgOrRet());
      if (isGeneral())
        return Info & NOIMM;
      if (isRaw())
        return true;
      switch (Info & CATMASK) {
        case TWOADDR:
        case PREDICATION:
        case SURFACE:
        case SAMPLER:
          return true;
        default: break;
      }
      return false;
    }
    // getModifier : get what source modifier is allowed
    unsigned getModifier() const {
      IGC_ASSERT(isGeneral());
      IGC_ASSERT(isArgOrRet());
      IGC_ASSERT(!isRet());
      return Info & MODIFIER;
    }
  };

  using DescrType = llvm::SmallVector<ArgInfo, 8>;

  // Construct a GenXIntrinsicInfo for a particular intrinsic
  GenXIntrinsicInfo(unsigned IntrinId) { InfoIt = getTable().find(IntrinId); }
  bool isNull() const { return InfoIt == getTable().cend(); }
  bool isNotNull() const { return !isNull(); }
  // Return instruction description.
  ArrayRef<ArgInfo> getInstDesc() const {
    return isNull() ? ArrayRef<ArgInfo>{} : ArrayRef<ArgInfo>{InfoIt->second};
  }
  // Get the category and modifier for an arg idx
  ArgInfo getArgInfo(int Idx) const;
  // Get the trailing null zone, if any.
  unsigned getTrailingNullZoneStart(CallInst *CI) const;
  // Get the category and modifier for the return value
  ArgInfo getRetInfo() const { return getArgInfo(-1); }
  // Get bitmap of allowed execution sizes
  unsigned getExecSizeAllowedBits() const;
  // Determine if a predicated destination mask is permitted
  bool getPredAllowed() const;
  // Determine if intrinsic is element-wise
  bool isElementWise() const;
  // Get The overrided execution size or 0.
  static unsigned getOverridedExecSize(CallInst *CI,
                                       const GenXSubtarget *ST = nullptr);

private:
  using TableType = std::unordered_map<unsigned, DescrType>;
  static const TableType &getTable();
  TableType::const_iterator InfoIt;
};

} // namespace llvm
#endif // ndef GENXINTRINSICS_H