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