File: Region.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 (297 lines) | stat: -rw-r--r-- 13,263 bytes parent folder | download | duplicates (2)
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
/*========================== begin_copyright_notice ============================

Copyright (C) 2018-2022 Intel Corporation

SPDX-License-Identifier: MIT

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

//
/// CMRegion : region information
/// -------------------------------
///
/// An object of class CMRegion describes the region parameters of a Gen region.
/// It is a transient object, in that a pass constructs it as needed and then
/// forgets it. It does not persist between passes, as the region parameters are
/// fully described by the arguments to the rdregion and wrregion intrinsics.
///
/// The region parameters in a CMRegion are:
///
/// * ElementBytes : number of bytes per element
/// * ElementTy : Type of element
/// * NumElements : total number of elements in the region (number of rows is
///   thus NumElements/Width)
/// * VStride : vertical stride in elements
/// * Width : row width in elements
/// * Stride : horizontal stride in elements
/// * Offset : constant part of offset
/// * Indirect : variable index (nullptr for direct region, scalar value for
///   single indirect, vector value for multi indirect)
/// * IndirectIdx : start index in vector indirect. This is always 0 when
///   constructing a CMRegion, but can be set to a non-zero value before
///   calling a method to create a new rdregion/wrregion intrinsic
/// * IndirectAddrOffset : offset from the address value where region
///   origin starts
/// * Mask : mask (predicate) for wrregion, nullptr if none
/// * ParentWidth : the parent width value (a statement that no row crosses a
///   boundary of a multiple of this number of elements)
///
/// There are the following constructors:
///
/// * Construct from a Type or Value, setting the GenXRegion to a region that
///   covers the whole value.
/// * Construct from a rdregion/wrregion intrinsic, setting the GenXRegion to
/// the
///   region described by the intrinsic.
/// * Construct from a bitmap of which elements need to be in the region. This
///   is used from GenXConstants when constructing a splat region when loading
///   a constant in multiple stages.
///
/// CMRegion is not used to represent the region parameters in predicate
/// regions, since they are much simpler. But GenXRegion does contain static
/// methods to create rdpredregion etc intrinsics given the predicate region
/// parameters.
///
//===----------------------------------------------------------------------===//

#ifndef VC_UTILS_GENX_REGION_H
#define VC_UTILS_GENX_REGION_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/GenXIntrinsics/GenXIntrinsics.h"

namespace llvm {
class Constant;
class DataLayout;
class DebugLoc;
class Function;
class Instruction;
class Module;
class Twine;
class Type;
class Value;
class VectorType;
class raw_ostream;
} // namespace llvm

namespace vc {
namespace WrPredRegionOperand {
enum { OldValue, NewValue, Offset };
} // namespace WrPredRegionOperand

// CMRegion : description of an operand's region
class CMRegion {
  using Constant = llvm::Constant;
  using DataLayout = llvm::DataLayout;
  using DebugLoc = llvm::DebugLoc;
  using Function = llvm::Function;
  using Instruction = llvm::Instruction;
  using Module = llvm::Module;
  using Twine = llvm::Twine;
  using Type = llvm::Type;
  using Value = llvm::Value;
  using VectorType = llvm::VectorType;
  using raw_ostream = llvm::raw_ostream;

public:
  unsigned ElementBytes;
  Type *ElementTy;
  unsigned NumElements;
  int VStride;
  unsigned Width;
  int Stride;
  // NOTE: with the current design region may have both non-zero \p Offset and
  //       set \p Indirect, which means indirect access + constant offset, which
  //       is a form of indirect access.
  int Offset;
  Value *Indirect;
  unsigned IndirectIdx; // start index in vector Indirect
  unsigned IndirectAddrOffset;
  Value *Mask;          // 0 else mask for wrregion
  unsigned ParentWidth; // 0 else parent width
  // Default constructor: assume single element
  CMRegion()
      : ElementBytes(0), ElementTy(0), NumElements(1), VStride(1), Width(1),
        Stride(1), Offset(0), Indirect(0), IndirectIdx(0),
        IndirectAddrOffset(0), Mask(0), ParentWidth(0) {}
  // Construct from a type.
  CMRegion(Type *Ty, const DataLayout *DL = nullptr);
  // Construct from a value.
  CMRegion(const Value *V, const DataLayout *DL = nullptr);
  // Construct from a rd/wr region/element
  CMRegion(const Instruction *Inst, bool WantParentWidth = false);
  // Construct from a bitmap of which elements to set (legal 1D region)
  CMRegion(unsigned Bits, unsigned ElementBytes);
  // Create rdregion intrinsic from this Region
  // Returns a scalar if the Region has one element and AllowScalar is true.
  // Otherwise returns a vector.
  Instruction *createRdRegion(Value *Input, const Twine &Name,
                              Instruction *InsertBefore, const DebugLoc &DL,
                              bool AllowScalar = false);
  // Modify Region object for a subregion
  void getSubregion(unsigned StartIdx, unsigned Size);
  // Create wrregion intrinsic from this Region
  Instruction *createWrRegion(Value *OldVal, Value *Input, const Twine &Name,
                              Instruction *InsertBefore, const DebugLoc &DL);
  // Create wrconstregion intrinsic from this Region
  Instruction *createWrConstRegion(Value *OldVal, Value *Input,
                                   const Twine &Name, Instruction *InsertBefore,
                                   const DebugLoc &DL);
  // Create rdpredregion from given start index and size
  static Instruction *createRdPredRegion(Value *Input, unsigned Index,
                                         unsigned Size, const Twine &Name,
                                         Instruction *InsertBefore,
                                         const DebugLoc &DL);
  static Value *createRdPredRegionOrConst(Value *Input, unsigned Index,
                                          unsigned Size, const Twine &Name,
                                          Instruction *InsertBefore,
                                          const DebugLoc &DL);
  // Create rdregion representing vector splat
  static Value *createRdVectorSplat(const DataLayout &DL, unsigned NumElements,
                                    Value *Input, const Twine &Name,
                                    Instruction *InsertBefore,
                                    const DebugLoc &DbgLoc);
  // Create wrpredregion from given start index
  static Instruction *createWrPredRegion(Value *OldVal, Value *Input,
                                         unsigned Index, const Twine &Name,
                                         Instruction *InsertBefore,
                                         const DebugLoc &DL);
  // Create wrpredpredregion from given start index
  static Instruction *createWrPredPredRegion(Value *OldVal, Value *Input,
                                             unsigned Index, Value *Pred,
                                             const Twine &Name,
                                             Instruction *InsertBefore,
                                             const DebugLoc &DL);
  // Set the called function in an intrinsic call
  static void setRegionCalledFunc(Instruction *Inst);
  // Compare two regions to see if they have the same region parameters other
  // than start offset (not allowing element type to be different).
  bool isStrictlySimilar(const CMRegion &R2) const {
    return VStride == R2.VStride && Width == R2.Width && Stride == R2.Stride &&
           Mask == R2.Mask;
  }
  // Compare two regions to see if they have the same region parameters other
  // than start offset (also allowing element type to be different).
  bool isSimilar(const CMRegion &R2) const;
  // Compare two regions to see if they have the same region parameters (also
  // allowing element type to be different).
  bool operator==(const CMRegion &R2) const {
    return isSimilar(R2) && Offset == R2.Offset && Indirect == R2.Indirect &&
           IndirectIdx == R2.IndirectIdx;
  }
  bool operator!=(const CMRegion &R2) const { return !(*this == R2); }
  // Compare two regions to see if they overlaps each other.
  bool overlap(const CMRegion &R2) const;
  // Test whether a region is scalar
  bool isScalar() const {
    return !Stride && (Width == NumElements || !VStride);
  }
  // Checks whether region <vstride;width;stride> can really be represented as
  // 1D region <stride'>.
  bool is1D() const;
  // For 1D region (can be represented as <stride>) return the stride.
  // The behavior is undefined for not 1D regions.
  int get1DStride() const;
  // For destination region (1D region) returns its stride. Unlike get1DStride
  // cannot return 0 stride.
  // The behavior is undefined for not 1D regions.
  int getDstStride() const;
  // Test whether a region is 2D
  bool is2D() const { return !isScalar() && Width != NumElements; }
  // Test whether a region is contiguous.
  bool isContiguous() const;
  // Test whether a region covers exactly the whole of the given type, allowing
  // for the element type being different.
  bool isWhole(Type *Ty, const DataLayout *DL = nullptr) const;
  // Test whether the region has a whole number of rows. (append() can result
  // in a region with an incomplete final row, which is normally not allowed.)
  bool isWholeNumRows() const { return !(NumElements % Width); }
  // Evaluate rdregion with constant input.
  Constant *evaluateConstantRdRegion(Constant *Input, bool AllowScalar);
  // evaluateConstantWrRegion : evaluate wrregion with constant inputs
  Constant *evaluateConstantWrRegion(Constant *OldVal, Constant *NewVal);
  // append : append region AR to this region
  bool append(CMRegion AR);
  // changeElementType : change the element type of the region
  bool changeElementType(Type *NewElementType, const DataLayout *DL);
  // Debug dump/print
  void dump() const;
  void print(raw_ostream &OS) const;
  // Check whether the region is multi indirect. Returns true if Indirect has
  // VectorType (a sign of multi indirection)
  bool isMultiIndirect() const {
    return Indirect && llvm::isa<VectorType>(Indirect->getType());
  }
  // Get indices in vector that represent accessed elements for this region
  llvm::SmallVector<unsigned, 8> getAccessIndices() const;
  // Get bit mask in which ones values represent bytes which
  // were accessed by this region
  llvm::SmallBitVector getAccessBitMap(int MinTrackingOffset = 0) const;
  // Length of single row in bytes
  unsigned getRowLength() const {
    return Stride ? (Width * Stride * ElementBytes) : ElementBytes;
  }
  // Length of whole region in bytes
  unsigned getLength() const {
    return VStride * ((NumElements / Width) - 1) * ElementBytes +
           getRowLength();
  }

  // Returns the region offset in muber of elements.
  // This method cannot be called for (multi-)indirect regions.
  unsigned getOffsetInElements() const;

  // Returns selected region type. Corresonds to rdregion return value type or
  // wrregion new value operand type.
  // Set \p UseDegenerateVectorType to produce <1 x Ty> instead of Ty.
  Type *getRegionType(bool UseDegenerateVectorType = false) const;

  // Sets \p ElementTy field with \p Ty and sets \p ElementByte accordingly.
  // Data layout \p DL must be provided for pointer types.
  void setElementTy(Type *Ty, DataLayout *DL = nullptr);

protected:
  // Create wrregion or wrconstregion intrinsic from this Region
  Instruction *createWrCommonRegion(llvm::GenXIntrinsic::ID IID, Value *OldVal,
                                    Value *Input, const Twine &Name,
                                    Instruction *InsertBefore,
                                    const DebugLoc &DL);
  // Get the function declaration for a region intrinsic
  static Function *getGenXRegionDeclaration(Module *M,
                                            llvm::GenXIntrinsic::ID IID,
                                            Type *RetTy,
                                            llvm::ArrayRef<Value *> Args);
  // Get (or create instruction for) the start index of a region.
  Value *getStartIdx(const Twine &Name, Instruction *InsertBefore,
                     const DebugLoc &DL);
};

/* Note: Region is a more specialized class for constructing Regions,
   the primary difference is that Region class requires only Value interface
   and is not aware about Instruction stuff.
*/
class Region : public CMRegion {
  using DataLayout = llvm::DataLayout;
  using Type = llvm::Type;
  using Value = llvm::Value;

public:
  // Default constructor: assume single element
  Region() : CMRegion() {}
  // Construct from a type.
  Region(Type *Ty, const DataLayout *DL = nullptr) : CMRegion(Ty, DL){};
  // Construct from a value.
  Region(const Value *V, const DataLayout *DL = nullptr) : CMRegion(V, DL){};
  // Construct from a bitmap of which elements to set (legal 1D region)
  Region(unsigned Bits, unsigned ElementBytes) : CMRegion(Bits, ElementBytes){};
};

inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CMRegion &R) {
  R.print(OS);
  return OS;
}
} // namespace vc

#endif // VC_UTILS_GENX_REGION_H