1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2018-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 //
10 /// CMRegion : region information
11 /// -------------------------------
12 ///
13 /// An object of class CMRegion describes the region parameters of a Gen region.
14 /// It is a transient object, in that a pass constructs it as needed and then
15 /// forgets it. It does not persist between passes, as the region parameters are
16 /// fully described by the arguments to the rdregion and wrregion intrinsics.
17 ///
18 /// The region parameters in a CMRegion are:
19 ///
20 /// * ElementBytes : number of bytes per element
21 /// * ElementTy : Type of element
22 /// * NumElements : total number of elements in the region (number of rows is
23 ///   thus NumElements/Width)
24 /// * VStride : vertical stride in elements
25 /// * Width : row width in elements
26 /// * Stride : horizontal stride in elements
27 /// * Offset : constant part of offset
28 /// * Indirect : variable index (nullptr for direct region, scalar value for
29 ///   single indirect, vector value for multi indirect)
30 /// * IndirectIdx : start index in vector indirect. This is always 0 when
31 ///   constructing a CMRegion, but can be set to a non-zero value before
32 ///   calling a method to create a new rdregion/wrregion intrinsic
33 /// * IndirectAddrOffset : offset from the address value where region
34 ///   origin starts
35 /// * Mask : mask (predicate) for wrregion, nullptr if none
36 /// * ParentWidth : the parent width value (a statement that no row crosses a
37 ///   boundary of a multiple of this number of elements)
38 ///
39 /// There are the following constructors:
40 ///
41 /// * Construct from a Type or Value, setting the GenXRegion to a region that
42 ///   covers the whole value.
43 /// * Construct from a rdregion/wrregion intrinsic, setting the GenXRegion to the
44 ///   region described by the intrinsic.
45 /// * Construct from a bitmap of which elements need to be in the region. This
46 ///   is used from GenXConstants when constructing a splat region when loading
47 ///   a constant in multiple stages.
48 ///
49 /// CMRegion is not used to represent the region parameters in predicate regions,
50 /// since they are much simpler. But GenXRegion does contain static methods to create
51 /// rdpredregion etc intrinsics given the predicate region parameters.
52 ///
53 //===----------------------------------------------------------------------===//
54 
55 #ifndef VC_UTILS_GENX_REGION_H
56 #define VC_UTILS_GENX_REGION_H
57 
58 #include "llvm/ADT/ArrayRef.h"
59 #include "llvm/ADT/SmallBitVector.h"
60 #include "llvm/GenXIntrinsics/GenXIntrinsics.h"
61 
62 namespace llvm {
63 
64 class Constant;
65 class DataLayout;
66 class Value;
67 class Function;
68 class Module;
69 class Type;
70 class Instruction;
71 class raw_ostream;
72 class Twine;
73 class DebugLoc;
74 
75 namespace WrPredRegionOperand {
76 enum { OldValue, NewValue, Offset };
77 } // namespace WrPredRegionOperand
78 
79 // CMRegion : description of an operand's region
80 class CMRegion {
81 public:
82   unsigned ElementBytes;
83   Type *ElementTy;
84   unsigned NumElements;
85   int VStride;
86   unsigned Width;
87   int Stride;
88   int Offset;
89   Value *Indirect;
90   unsigned IndirectIdx; // start index in vector Indirect
91   unsigned IndirectAddrOffset;
92   Value *Mask;          // 0 else mask for wrregion
93   unsigned ParentWidth; // 0 else parent width
94   // Default constructor: assume single element
CMRegion()95   CMRegion()
96       : ElementBytes(0), ElementTy(0), NumElements(1), VStride(1), Width(1),
97         Stride(1), Offset(0), Indirect(0), IndirectIdx(0),
98         IndirectAddrOffset(0), Mask(0), ParentWidth(0) {}
99   // Construct from a type.
100   CMRegion(Type *Ty, const DataLayout *DL = nullptr);
101   // Construct from a value.
102   CMRegion(Value *V, const DataLayout *DL = nullptr);
103   // Construct from a rd/wr region/element
104   CMRegion(Instruction *Inst, bool WantParentWidth = false);
105   // Construct from a bitmap of which elements to set (legal 1D region)
106   CMRegion(unsigned Bits, unsigned ElementBytes);
107   // Create rdregion intrinsic from this Region
108   // Returns a scalar if the Region has one element and AllowScalar is true.
109   // Otherwise returns a vector.
110   Instruction *createRdRegion(Value *Input, const Twine &Name,
111                               Instruction *InsertBefore, const DebugLoc &DL,
112                               bool AllowScalar = false);
113   // Modify Region object for a subregion
114   void getSubregion(unsigned StartIdx, unsigned Size);
115   // Create wrregion intrinsic from this Region
116   Instruction *createWrRegion(Value *OldVal, Value *Input, const Twine &Name,
117                               Instruction *InsertBefore, const DebugLoc &DL);
118   // Create wrconstregion intrinsic from this Region
119   Instruction *createWrConstRegion(Value *OldVal, Value *Input,
120                                    const Twine &Name, Instruction *InsertBefore,
121                                    const DebugLoc &DL);
122   // Create rdpredregion from given start index and size
123   static Instruction *createRdPredRegion(Value *Input, unsigned Index,
124                                          unsigned Size, const Twine &Name,
125                                          Instruction *InsertBefore,
126                                          const DebugLoc &DL);
127   static Value *createRdPredRegionOrConst(Value *Input, unsigned Index,
128                                           unsigned Size, const Twine &Name,
129                                           Instruction *InsertBefore,
130                                           const DebugLoc &DL);
131   // Create rdregion representing vector splat
132   static Value *createRdVectorSplat(const DataLayout &DL, unsigned NumElements,
133                                     Value *Input, const Twine &Name,
134                                     Instruction *InsertBefore,
135                                     const DebugLoc &DbgLoc);
136   // Create wrpredregion from given start index
137   static Instruction *createWrPredRegion(Value *OldVal, Value *Input,
138                                          unsigned Index, const Twine &Name,
139                                          Instruction *InsertBefore,
140                                          const DebugLoc &DL);
141   // Create wrpredpredregion from given start index
142   static Instruction *createWrPredPredRegion(Value *OldVal, Value *Input,
143                                              unsigned Index, Value *Pred,
144                                              const Twine &Name,
145                                              Instruction *InsertBefore,
146                                              const DebugLoc &DL);
147   // Set the called function in an intrinsic call
148   static void setRegionCalledFunc(Instruction *Inst);
149   // Compare two regions to see if they have the same region parameters other
150   // than start offset (not allowing element type to be different).
isStrictlySimilar(const CMRegion & R2)151   bool isStrictlySimilar(const CMRegion &R2) const {
152     return VStride == R2.VStride && Width == R2.Width && Stride == R2.Stride &&
153            Mask == R2.Mask;
154   }
155   // Compare two regions to see if they have the same region parameters other
156   // than start offset (also allowing element type to be different).
157   bool isSimilar(const CMRegion &R2) const;
158   // Compare two regions to see if they have the same region parameters (also
159   // allowing element type to be different).
160   bool operator==(const CMRegion &R2) const {
161     return isSimilar(R2) && Offset == R2.Offset && Indirect == R2.Indirect
162         && IndirectIdx == R2.IndirectIdx;
163   }
164   bool operator!=(const CMRegion &R2) const { return !(*this == R2); }
165   // Compare two regions to see if they overlaps each other.
166   bool overlap(const CMRegion &R2) const;
167   // Test whether a region is scalar
isScalar()168   bool isScalar() const {
169     return !Stride && (Width == NumElements || !VStride);
170   }
171   // Test whether a region is 2D
is2D()172   bool is2D() const { return !isScalar() && Width != NumElements; }
173   // Test whether a region is contiguous.
174   bool isContiguous() const;
175   // Test whether a region covers exactly the whole of the given type, allowing
176   // for the element type being different.
177   bool isWhole(Type *Ty) const;
178   // Test whether the region has a whole number of rows. (append() can result
179   // in a region with an incomplete final row, which is normally not allowed.)
isWholeNumRows()180   bool isWholeNumRows() const { return !(NumElements % Width); }
181   // Evaluate rdregion with constant input.
182   Constant *evaluateConstantRdRegion(Constant *Input, bool AllowScalar);
183   // evaluateConstantWrRegion : evaluate wrregion with constant inputs
184   Constant *evaluateConstantWrRegion(Constant *OldVal, Constant *NewVal);
185   // append : append region AR to this region
186   bool append(CMRegion AR);
187   // changeElementType : change the element type of the region
188   bool changeElementType(Type *NewElementType, const DataLayout *DL);
189   // Debug dump/print
190   void dump() const;
191   void print(raw_ostream &OS) const;
192   // Check whether the region is multi indirect. Returns true if Indirect has
193   // VectorType (a sign of multi indirection)
isMultiIndirect()194   bool isMultiIndirect() const {
195     return Indirect && isa<VectorType>(Indirect->getType());
196   }
197   // Get bit mask in which ones values represent bytes which
198   // were accessed by this region
199   BitVector getAccessBitMap(int MinTrackingOffset = 0) const;
200   // Length of single row in bytes
getRowLength()201   unsigned getRowLength() const {
202     return Stride ? (Width * Stride * ElementBytes) : ElementBytes;
203   }
204   // Length of whole region in bytes
getLength()205   unsigned getLength() const {
206     return VStride * ((NumElements / Width) - 1) * ElementBytes +
207                 getRowLength();
208   }
209 
210 protected:
211   // Create wrregion or wrconstregion intrinsic from this Region
212   Instruction *createWrCommonRegion(GenXIntrinsic::ID, Value *OldVal,
213                                     Value *Input, const Twine &Name,
214                                     Instruction *InsertBefore,
215                                     const DebugLoc &DL);
216   // Get the function declaration for a region intrinsic
217   static Function *getGenXRegionDeclaration(Module *M, GenXIntrinsic::ID IID, Type *RetTy,
218                                         ArrayRef<Value *> Args);
219   // Get (or create instruction for) the start index of a region.
220   Value *getStartIdx(const Twine &Name, Instruction *InsertBefore, const DebugLoc &DL);
221 };
222 
223 /* Note: Region is a more specialized class for constructing Regions,
224    the primary difference is that Region class requires only Value interface
225    and is not aware about Instruction stuff.
226 */
227 class Region : public CMRegion {
228 public:
229   // Default constructor: assume single element
Region()230   Region() : CMRegion() {}
231   // Construct from a type.
CMRegion(Ty,DL)232   Region(Type *Ty, const DataLayout *DL = nullptr) : CMRegion(Ty, DL) {};
233   // Construct from a value.
CMRegion(V,DL)234   Region(Value *V, const DataLayout *DL = nullptr) : CMRegion(V, DL) {};
235   // Construct from a bitmap of which elements to set (legal 1D region)
Region(unsigned Bits,unsigned ElementBytes)236   Region(unsigned Bits, unsigned ElementBytes)
237     : CMRegion(Bits, ElementBytes) {};
238 };
239 
240 inline raw_ostream &operator<<(raw_ostream &OS, const CMRegion &R) {
241   R.print(OS);
242   return OS;
243 }
244 
245 } // end namespace llvm
246 
247 #endif // VC_UTILS_GENX_REGION_H
248