1 //== llvm/Support/LowLevelTypeImpl.h --------------------------- -*- C++ -*-==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// Implement a low-level type suitable for MachineInstr level instruction 10 /// selection. 11 /// 12 /// For a type attached to a MachineInstr, we only care about 2 details: total 13 /// size and the number of vector lanes (if any). Accordingly, there are 4 14 /// possible valid type-kinds: 15 /// 16 /// * `sN` for scalars and aggregates 17 /// * `<N x sM>` for vectors, which must have at least 2 elements. 18 /// * `pN` for pointers 19 /// 20 /// Other information required for correct selection is expected to be carried 21 /// by the opcode, or non-type flags. For example the distinction between G_ADD 22 /// and G_FADD for int/float or fast-math flags. 23 /// 24 //===----------------------------------------------------------------------===// 25 26 #ifndef LLVM_SUPPORT_LOWLEVELTYPEIMPL_H 27 #define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H 28 29 #include "llvm/ADT/DenseMapInfo.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/MachineValueType.h" 32 #include <cassert> 33 34 namespace llvm { 35 36 class DataLayout; 37 class Type; 38 class raw_ostream; 39 40 class LLT { 41 public: 42 /// Get a low-level scalar or aggregate "bag of bits". scalar(unsigned SizeInBits)43 static LLT scalar(unsigned SizeInBits) { 44 return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true, 45 ElementCount::getFixed(0), SizeInBits, 46 /*AddressSpace=*/0}; 47 } 48 49 /// Get a low-level pointer in the given address space. pointer(unsigned AddressSpace,unsigned SizeInBits)50 static LLT pointer(unsigned AddressSpace, unsigned SizeInBits) { 51 assert(SizeInBits > 0 && "invalid pointer size"); 52 return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false, 53 ElementCount::getFixed(0), SizeInBits, AddressSpace}; 54 } 55 56 /// Get a low-level vector of some number of elements and element width. vector(ElementCount EC,unsigned ScalarSizeInBits)57 static LLT vector(ElementCount EC, unsigned ScalarSizeInBits) { 58 assert(!EC.isScalar() && "invalid number of vector elements"); 59 return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false, 60 EC, ScalarSizeInBits, /*AddressSpace=*/0}; 61 } 62 63 /// Get a low-level vector of some number of elements and element type. vector(ElementCount EC,LLT ScalarTy)64 static LLT vector(ElementCount EC, LLT ScalarTy) { 65 assert(!EC.isScalar() && "invalid number of vector elements"); 66 assert(!ScalarTy.isVector() && "invalid vector element type"); 67 return LLT{ScalarTy.isPointer(), /*isVector=*/true, /*isScalar=*/false, 68 EC, 69 ScalarTy.getSizeInBits().getFixedSize(), 70 ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0}; 71 } 72 73 /// Get a low-level fixed-width vector of some number of elements and element 74 /// width. fixed_vector(unsigned NumElements,unsigned ScalarSizeInBits)75 static LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) { 76 return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits); 77 } 78 79 /// Get a low-level fixed-width vector of some number of elements and element 80 /// type. fixed_vector(unsigned NumElements,LLT ScalarTy)81 static LLT fixed_vector(unsigned NumElements, LLT ScalarTy) { 82 return vector(ElementCount::getFixed(NumElements), ScalarTy); 83 } 84 85 /// Get a low-level scalable vector of some number of elements and element 86 /// width. scalable_vector(unsigned MinNumElements,unsigned ScalarSizeInBits)87 static LLT scalable_vector(unsigned MinNumElements, 88 unsigned ScalarSizeInBits) { 89 return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits); 90 } 91 92 /// Get a low-level scalable vector of some number of elements and element 93 /// type. scalable_vector(unsigned MinNumElements,LLT ScalarTy)94 static LLT scalable_vector(unsigned MinNumElements, LLT ScalarTy) { 95 return vector(ElementCount::getScalable(MinNumElements), ScalarTy); 96 } 97 scalarOrVector(ElementCount EC,LLT ScalarTy)98 static LLT scalarOrVector(ElementCount EC, LLT ScalarTy) { 99 return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy); 100 } 101 scalarOrVector(ElementCount EC,uint64_t ScalarSize)102 static LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) { 103 assert(ScalarSize <= std::numeric_limits<unsigned>::max() && 104 "Not enough bits in LLT to represent size"); 105 return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize))); 106 } 107 LLT(bool isPointer,bool isVector,bool isScalar,ElementCount EC,uint64_t SizeInBits,unsigned AddressSpace)108 explicit LLT(bool isPointer, bool isVector, bool isScalar, ElementCount EC, 109 uint64_t SizeInBits, unsigned AddressSpace) { 110 init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace); 111 } LLT()112 explicit LLT() 113 : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {} 114 115 explicit LLT(MVT VT); 116 isValid()117 bool isValid() const { return IsScalar || RawData != 0; } 118 isScalar()119 bool isScalar() const { return IsScalar; } 120 isPointer()121 bool isPointer() const { return isValid() && IsPointer && !IsVector; } 122 isVector()123 bool isVector() const { return isValid() && IsVector; } 124 125 /// Returns the number of elements in a vector LLT. Must only be called on 126 /// vector types. getNumElements()127 uint16_t getNumElements() const { 128 if (isScalable()) 129 llvm::reportInvalidSizeRequest( 130 "Possible incorrect use of LLT::getNumElements() for " 131 "scalable vector. Scalable flag may be dropped, use " 132 "LLT::getElementCount() instead"); 133 return getElementCount().getKnownMinValue(); 134 } 135 136 /// Returns true if the LLT is a scalable vector. Must only be called on 137 /// vector types. isScalable()138 bool isScalable() const { 139 assert(isVector() && "Expected a vector type"); 140 return IsPointer ? getFieldValue(PointerVectorScalableFieldInfo) 141 : getFieldValue(VectorScalableFieldInfo); 142 } 143 getElementCount()144 ElementCount getElementCount() const { 145 assert(IsVector && "cannot get number of elements on scalar/aggregate"); 146 return ElementCount::get(IsPointer 147 ? getFieldValue(PointerVectorElementsFieldInfo) 148 : getFieldValue(VectorElementsFieldInfo), 149 isScalable()); 150 } 151 152 /// Returns the total size of the type. Must only be called on sized types. getSizeInBits()153 TypeSize getSizeInBits() const { 154 if (isPointer() || isScalar()) 155 return TypeSize::Fixed(getScalarSizeInBits()); 156 auto EC = getElementCount(); 157 return TypeSize(getScalarSizeInBits() * EC.getKnownMinValue(), 158 EC.isScalable()); 159 } 160 161 /// Returns the total size of the type in bytes, i.e. number of whole bytes 162 /// needed to represent the size in bits. Must only be called on sized types. getSizeInBytes()163 TypeSize getSizeInBytes() const { 164 TypeSize BaseSize = getSizeInBits(); 165 return {(BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable()}; 166 } 167 getScalarType()168 LLT getScalarType() const { 169 return isVector() ? getElementType() : *this; 170 } 171 172 /// If this type is a vector, return a vector with the same number of elements 173 /// but the new element type. Otherwise, return the new element type. changeElementType(LLT NewEltTy)174 LLT changeElementType(LLT NewEltTy) const { 175 return isVector() ? LLT::vector(getElementCount(), NewEltTy) : NewEltTy; 176 } 177 178 /// If this type is a vector, return a vector with the same number of elements 179 /// but the new element size. Otherwise, return the new element type. Invalid 180 /// for pointer types. For pointer types, use changeElementType. changeElementSize(unsigned NewEltSize)181 LLT changeElementSize(unsigned NewEltSize) const { 182 assert(!getScalarType().isPointer() && 183 "invalid to directly change element size for pointers"); 184 return isVector() ? LLT::vector(getElementCount(), NewEltSize) 185 : LLT::scalar(NewEltSize); 186 } 187 188 /// Return a vector or scalar with the same element type and the new element 189 /// count. changeElementCount(ElementCount EC)190 LLT changeElementCount(ElementCount EC) const { 191 return LLT::scalarOrVector(EC, getScalarType()); 192 } 193 194 /// Return a type that is \p Factor times smaller. Reduces the number of 195 /// elements if this is a vector, or the bitwidth for scalar/pointers. Does 196 /// not attempt to handle cases that aren't evenly divisible. divide(int Factor)197 LLT divide(int Factor) const { 198 assert(Factor != 1); 199 assert((!isScalar() || getScalarSizeInBits() != 0) && 200 "cannot divide scalar of size zero"); 201 if (isVector()) { 202 assert(getElementCount().isKnownMultipleOf(Factor)); 203 return scalarOrVector(getElementCount().divideCoefficientBy(Factor), 204 getElementType()); 205 } 206 207 assert(getScalarSizeInBits() % Factor == 0); 208 return scalar(getScalarSizeInBits() / Factor); 209 } 210 isByteSized()211 bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); } 212 getScalarSizeInBits()213 unsigned getScalarSizeInBits() const { 214 if (IsScalar) 215 return getFieldValue(ScalarSizeFieldInfo); 216 if (IsVector) { 217 if (!IsPointer) 218 return getFieldValue(VectorSizeFieldInfo); 219 else 220 return getFieldValue(PointerVectorSizeFieldInfo); 221 } else if (IsPointer) 222 return getFieldValue(PointerSizeFieldInfo); 223 else 224 llvm_unreachable("unexpected LLT"); 225 } 226 getAddressSpace()227 unsigned getAddressSpace() const { 228 assert(RawData != 0 && "Invalid Type"); 229 assert(IsPointer && "cannot get address space of non-pointer type"); 230 if (!IsVector) 231 return getFieldValue(PointerAddressSpaceFieldInfo); 232 else 233 return getFieldValue(PointerVectorAddressSpaceFieldInfo); 234 } 235 236 /// Returns the vector's element type. Only valid for vector types. getElementType()237 LLT getElementType() const { 238 assert(isVector() && "cannot get element type of scalar/aggregate"); 239 if (IsPointer) 240 return pointer(getAddressSpace(), getScalarSizeInBits()); 241 else 242 return scalar(getScalarSizeInBits()); 243 } 244 245 void print(raw_ostream &OS) const; 246 247 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()248 LLVM_DUMP_METHOD void dump() const { 249 print(dbgs()); 250 dbgs() << '\n'; 251 } 252 #endif 253 254 bool operator==(const LLT &RHS) const { 255 return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector && 256 IsScalar == RHS.IsScalar && RHS.RawData == RawData; 257 } 258 259 bool operator!=(const LLT &RHS) const { return !(*this == RHS); } 260 261 friend struct DenseMapInfo<LLT>; 262 friend class GISelInstProfileBuilder; 263 264 private: 265 /// LLT is packed into 64 bits as follows: 266 /// isScalar : 1 267 /// isPointer : 1 268 /// isVector : 1 269 /// with 61 bits remaining for Kind-specific data, packed in bitfields 270 /// as described below. As there isn't a simple portable way to pack bits 271 /// into bitfields, here the different fields in the packed structure is 272 /// described in static const *Field variables. Each of these variables 273 /// is a 2-element array, with the first element describing the bitfield size 274 /// and the second element describing the bitfield offset. 275 typedef int BitFieldInfo[2]; 276 /// 277 /// This is how the bitfields are packed per Kind: 278 /// * Invalid: 279 /// gets encoded as RawData == 0, as that is an invalid encoding, since for 280 /// valid encodings, SizeInBits/SizeOfElement must be larger than 0. 281 /// * Non-pointer scalar (isPointer == 0 && isVector == 0): 282 /// SizeInBits: 32; 283 static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0}; 284 /// * Pointer (isPointer == 1 && isVector == 0): 285 /// SizeInBits: 16; 286 /// AddressSpace: 24; 287 static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0}; 288 static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{ 289 24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]}; 290 static_assert((PointerAddressSpaceFieldInfo[0] + 291 PointerAddressSpaceFieldInfo[1]) <= 61, 292 "Insufficient bits to encode all data"); 293 /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1): 294 /// NumElements: 16; 295 /// SizeOfElement: 32; 296 /// Scalable: 1; 297 static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 0}; 298 static const constexpr BitFieldInfo VectorSizeFieldInfo{ 299 32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]}; 300 static const constexpr BitFieldInfo VectorScalableFieldInfo{ 301 1, VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]}; 302 static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 61, 303 "Insufficient bits to encode all data"); 304 /// * Vector-of-pointer (isPointer == 1 && isVector == 1): 305 /// NumElements: 16; 306 /// SizeOfElement: 16; 307 /// AddressSpace: 24; 308 /// Scalable: 1; 309 static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0}; 310 static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{ 311 16, 312 PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]}; 313 static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{ 314 24, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]}; 315 static const constexpr BitFieldInfo PointerVectorScalableFieldInfo{ 316 1, PointerVectorAddressSpaceFieldInfo[0] + 317 PointerVectorAddressSpaceFieldInfo[1]}; 318 static_assert((PointerVectorAddressSpaceFieldInfo[0] + 319 PointerVectorAddressSpaceFieldInfo[1]) <= 61, 320 "Insufficient bits to encode all data"); 321 322 uint64_t IsScalar : 1; 323 uint64_t IsPointer : 1; 324 uint64_t IsVector : 1; 325 uint64_t RawData : 61; 326 327 static uint64_t getMask(const BitFieldInfo FieldInfo) { 328 const int FieldSizeInBits = FieldInfo[0]; 329 return (((uint64_t)1) << FieldSizeInBits) - 1; 330 } 331 static uint64_t maskAndShift(uint64_t Val, uint64_t Mask, uint8_t Shift) { 332 assert(Val <= Mask && "Value too large for field"); 333 return (Val & Mask) << Shift; 334 } 335 static uint64_t maskAndShift(uint64_t Val, const BitFieldInfo FieldInfo) { 336 return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]); 337 } 338 uint64_t getFieldValue(const BitFieldInfo FieldInfo) const { 339 return getMask(FieldInfo) & (RawData >> FieldInfo[1]); 340 } 341 342 void init(bool IsPointer, bool IsVector, bool IsScalar, ElementCount EC, 343 uint64_t SizeInBits, unsigned AddressSpace) { 344 assert(SizeInBits <= std::numeric_limits<unsigned>::max() && 345 "Not enough bits in LLT to represent size"); 346 this->IsPointer = IsPointer; 347 this->IsVector = IsVector; 348 this->IsScalar = IsScalar; 349 if (IsScalar) 350 RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo); 351 else if (IsVector) { 352 assert(EC.isVector() && "invalid number of vector elements"); 353 if (!IsPointer) 354 RawData = 355 maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) | 356 maskAndShift(SizeInBits, VectorSizeFieldInfo) | 357 maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo); 358 else 359 RawData = 360 maskAndShift(EC.getKnownMinValue(), 361 PointerVectorElementsFieldInfo) | 362 maskAndShift(SizeInBits, PointerVectorSizeFieldInfo) | 363 maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo) | 364 maskAndShift(EC.isScalable() ? 1 : 0, 365 PointerVectorScalableFieldInfo); 366 } else if (IsPointer) 367 RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) | 368 maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo); 369 else 370 llvm_unreachable("unexpected LLT configuration"); 371 } 372 373 public: 374 uint64_t getUniqueRAWLLTData() const { 375 return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 | 376 ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector); 377 } 378 }; 379 380 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) { 381 Ty.print(OS); 382 return OS; 383 } 384 385 template<> struct DenseMapInfo<LLT> { 386 static inline LLT getEmptyKey() { 387 LLT Invalid; 388 Invalid.IsPointer = true; 389 return Invalid; 390 } 391 static inline LLT getTombstoneKey() { 392 LLT Invalid; 393 Invalid.IsVector = true; 394 return Invalid; 395 } 396 static inline unsigned getHashValue(const LLT &Ty) { 397 uint64_t Val = Ty.getUniqueRAWLLTData(); 398 return DenseMapInfo<uint64_t>::getHashValue(Val); 399 } 400 static bool isEqual(const LLT &LHS, const LLT &RHS) { 401 return LHS == RHS; 402 } 403 }; 404 405 } 406 407 #endif // LLVM_SUPPORT_LOWLEVELTYPEIMPL_H 408