File indexing completed on 2026-05-10 08:43:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #ifndef LLVM_CODEGEN_LOWLEVELTYPE_H
0027 #define LLVM_CODEGEN_LOWLEVELTYPE_H
0028
0029 #include "llvm/ADT/DenseMapInfo.h"
0030 #include "llvm/CodeGenTypes/MachineValueType.h"
0031 #include "llvm/Support/Debug.h"
0032 #include <cassert>
0033
0034 namespace llvm {
0035
0036 class Type;
0037 class raw_ostream;
0038
0039 class LLT {
0040 public:
0041
0042 static constexpr LLT scalar(unsigned SizeInBits) {
0043 return LLT{false, false, true,
0044 ElementCount::getFixed(0), SizeInBits,
0045 0};
0046 }
0047
0048
0049 static constexpr LLT token() {
0050 return LLT{false, false,
0051 true, ElementCount::getFixed(0),
0052 0,
0053 0};
0054 }
0055
0056
0057 static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
0058 assert(SizeInBits > 0 && "invalid pointer size");
0059 return LLT{true, false, false,
0060 ElementCount::getFixed(0), SizeInBits, AddressSpace};
0061 }
0062
0063
0064 static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
0065 assert(!EC.isScalar() && "invalid number of vector elements");
0066 return LLT{false, true, false,
0067 EC, ScalarSizeInBits, 0};
0068 }
0069
0070
0071 static constexpr LLT vector(ElementCount EC, LLT ScalarTy) {
0072 assert(!EC.isScalar() && "invalid number of vector elements");
0073 assert(!ScalarTy.isVector() && "invalid vector element type");
0074 return LLT{ScalarTy.isPointer(),
0075 true,
0076 false,
0077 EC,
0078 ScalarTy.getSizeInBits().getFixedValue(),
0079 ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
0080 }
0081
0082
0083
0084 static constexpr LLT float16() {
0085 return scalar(16);
0086 }
0087
0088
0089 static constexpr LLT float32() {
0090 return scalar(32);
0091 }
0092
0093
0094 static constexpr LLT float64() {
0095 return scalar(64);
0096 }
0097
0098
0099
0100 static constexpr LLT fixed_vector(unsigned NumElements,
0101 unsigned ScalarSizeInBits) {
0102 return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
0103 }
0104
0105
0106
0107 static constexpr LLT fixed_vector(unsigned NumElements, LLT ScalarTy) {
0108 return vector(ElementCount::getFixed(NumElements), ScalarTy);
0109 }
0110
0111
0112
0113 static constexpr LLT scalable_vector(unsigned MinNumElements,
0114 unsigned ScalarSizeInBits) {
0115 return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
0116 }
0117
0118
0119
0120 static constexpr LLT scalable_vector(unsigned MinNumElements, LLT ScalarTy) {
0121 return vector(ElementCount::getScalable(MinNumElements), ScalarTy);
0122 }
0123
0124 static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy) {
0125 return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
0126 }
0127
0128 static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
0129 assert(ScalarSize <= std::numeric_limits<unsigned>::max() &&
0130 "Not enough bits in LLT to represent size");
0131 return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
0132 }
0133
0134 explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
0135 ElementCount EC, uint64_t SizeInBits,
0136 unsigned AddressSpace)
0137 : LLT() {
0138 init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
0139 }
0140 explicit constexpr LLT()
0141 : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
0142
0143 explicit LLT(MVT VT);
0144
0145 constexpr bool isValid() const { return IsScalar || RawData != 0; }
0146 constexpr bool isScalar() const { return IsScalar; }
0147 constexpr bool isToken() const { return IsScalar && RawData == 0; };
0148 constexpr bool isVector() const { return isValid() && IsVector; }
0149 constexpr bool isPointer() const {
0150 return isValid() && IsPointer && !IsVector;
0151 }
0152 constexpr bool isPointerVector() const { return IsPointer && isVector(); }
0153 constexpr bool isPointerOrPointerVector() const {
0154 return IsPointer && isValid();
0155 }
0156
0157
0158
0159 constexpr uint16_t getNumElements() const {
0160 if (isScalable())
0161 llvm::reportInvalidSizeRequest(
0162 "Possible incorrect use of LLT::getNumElements() for "
0163 "scalable vector. Scalable flag may be dropped, use "
0164 "LLT::getElementCount() instead");
0165 return getElementCount().getKnownMinValue();
0166 }
0167
0168
0169
0170 constexpr bool isScalable() const {
0171 assert(isVector() && "Expected a vector type");
0172 return getFieldValue(VectorScalableFieldInfo);
0173 }
0174
0175
0176
0177 constexpr bool isFixedVector() const { return isVector() && !isScalable(); }
0178
0179
0180
0181 constexpr bool isScalableVector() const { return isVector() && isScalable(); }
0182
0183 constexpr ElementCount getElementCount() const {
0184 assert(IsVector && "cannot get number of elements on scalar/aggregate");
0185 return ElementCount::get(getFieldValue(VectorElementsFieldInfo),
0186 isScalable());
0187 }
0188
0189
0190 constexpr TypeSize getSizeInBits() const {
0191 if (isPointer() || isScalar())
0192 return TypeSize::getFixed(getScalarSizeInBits());
0193 auto EC = getElementCount();
0194 return TypeSize(getScalarSizeInBits() * EC.getKnownMinValue(),
0195 EC.isScalable());
0196 }
0197
0198
0199
0200 constexpr TypeSize getSizeInBytes() const {
0201 TypeSize BaseSize = getSizeInBits();
0202 return {(BaseSize.getKnownMinValue() + 7) / 8, BaseSize.isScalable()};
0203 }
0204
0205 constexpr LLT getScalarType() const {
0206 return isVector() ? getElementType() : *this;
0207 }
0208
0209
0210
0211 constexpr LLT changeElementType(LLT NewEltTy) const {
0212 return isVector() ? LLT::vector(getElementCount(), NewEltTy) : NewEltTy;
0213 }
0214
0215
0216
0217
0218 constexpr LLT changeElementSize(unsigned NewEltSize) const {
0219 assert(!isPointerOrPointerVector() &&
0220 "invalid to directly change element size for pointers");
0221 return isVector() ? LLT::vector(getElementCount(), NewEltSize)
0222 : LLT::scalar(NewEltSize);
0223 }
0224
0225
0226
0227 constexpr LLT changeElementCount(ElementCount EC) const {
0228 return LLT::scalarOrVector(EC, getScalarType());
0229 }
0230
0231
0232
0233
0234 constexpr LLT divide(int Factor) const {
0235 assert(Factor != 1);
0236 assert((!isScalar() || getScalarSizeInBits() != 0) &&
0237 "cannot divide scalar of size zero");
0238 if (isVector()) {
0239 assert(getElementCount().isKnownMultipleOf(Factor));
0240 return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
0241 getElementType());
0242 }
0243
0244 assert(getScalarSizeInBits() % Factor == 0);
0245 return scalar(getScalarSizeInBits() / Factor);
0246 }
0247
0248
0249
0250
0251 constexpr LLT multiplyElements(int Factor) const {
0252 if (isVector()) {
0253 return scalarOrVector(getElementCount().multiplyCoefficientBy(Factor),
0254 getElementType());
0255 }
0256
0257 return fixed_vector(Factor, *this);
0258 }
0259
0260 constexpr bool isByteSized() const {
0261 return getSizeInBits().isKnownMultipleOf(8);
0262 }
0263
0264 constexpr unsigned getScalarSizeInBits() const {
0265 if (isPointerOrPointerVector())
0266 return getFieldValue(PointerSizeFieldInfo);
0267 return getFieldValue(ScalarSizeFieldInfo);
0268 }
0269
0270 constexpr unsigned getAddressSpace() const {
0271 assert(isPointerOrPointerVector() &&
0272 "cannot get address space of non-pointer type");
0273 return getFieldValue(PointerAddressSpaceFieldInfo);
0274 }
0275
0276
0277 constexpr LLT getElementType() const {
0278 assert(isVector() && "cannot get element type of scalar/aggregate");
0279 if (IsPointer)
0280 return pointer(getAddressSpace(), getScalarSizeInBits());
0281 else
0282 return scalar(getScalarSizeInBits());
0283 }
0284
0285 void print(raw_ostream &OS) const;
0286
0287 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0288 LLVM_DUMP_METHOD void dump() const;
0289 #endif
0290
0291 constexpr bool operator==(const LLT &RHS) const {
0292 return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
0293 IsScalar == RHS.IsScalar && RHS.RawData == RawData;
0294 }
0295
0296 constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
0297
0298 friend struct DenseMapInfo<LLT>;
0299 friend class GISelInstProfileBuilder;
0300
0301 private:
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334 typedef int BitFieldInfo[2];
0335
0336
0337
0338
0339
0340
0341
0342 static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
0343
0344
0345
0346 static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 45};
0347 static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 21};
0348
0349
0350
0351
0352 static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 5};
0353 static const constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
0354
0355
0356
0357
0358
0359
0360 uint64_t IsScalar : 1;
0361 uint64_t IsPointer : 1;
0362 uint64_t IsVector : 1;
0363 uint64_t RawData : 61;
0364
0365 static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
0366 const int FieldSizeInBits = FieldInfo[0];
0367 return (((uint64_t)1) << FieldSizeInBits) - 1;
0368 }
0369 static constexpr uint64_t maskAndShift(uint64_t Val, uint64_t Mask,
0370 uint8_t Shift) {
0371 assert(Val <= Mask && "Value too large for field");
0372 return (Val & Mask) << Shift;
0373 }
0374 static constexpr uint64_t maskAndShift(uint64_t Val,
0375 const BitFieldInfo FieldInfo) {
0376 return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
0377 }
0378
0379 constexpr uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
0380 return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
0381 }
0382
0383 constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
0384 ElementCount EC, uint64_t SizeInBits,
0385 unsigned AddressSpace) {
0386 assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
0387 "Not enough bits in LLT to represent size");
0388 this->IsPointer = IsPointer;
0389 this->IsVector = IsVector;
0390 this->IsScalar = IsScalar;
0391 if (IsPointer) {
0392 RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
0393 maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
0394 } else {
0395 RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
0396 }
0397 if (IsVector) {
0398 RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
0399 maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
0400 }
0401 }
0402
0403 public:
0404 constexpr uint64_t getUniqueRAWLLTData() const {
0405 return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
0406 ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
0407 }
0408 };
0409
0410 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
0411 Ty.print(OS);
0412 return OS;
0413 }
0414
0415 template<> struct DenseMapInfo<LLT> {
0416 static inline LLT getEmptyKey() {
0417 LLT Invalid;
0418 Invalid.IsPointer = true;
0419 return Invalid;
0420 }
0421 static inline LLT getTombstoneKey() {
0422 LLT Invalid;
0423 Invalid.IsVector = true;
0424 return Invalid;
0425 }
0426 static inline unsigned getHashValue(const LLT &Ty) {
0427 uint64_t Val = Ty.getUniqueRAWLLTData();
0428 return DenseMapInfo<uint64_t>::getHashValue(Val);
0429 }
0430 static bool isEqual(const LLT &LHS, const LLT &RHS) {
0431 return LHS == RHS;
0432 }
0433 };
0434
0435 }
0436
0437 #endif