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
|