Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:38

0001 //== llvm/CodeGenTypes/LowLevelType.h -------------------------- -*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// Implement a low-level type suitable for MachineInstr level instruction
0010 /// selection.
0011 ///
0012 /// For a type attached to a MachineInstr, we only care about 2 details: total
0013 /// size and the number of vector lanes (if any). Accordingly, there are 4
0014 /// possible valid type-kinds:
0015 ///
0016 ///    * `sN` for scalars and aggregates
0017 ///    * `<N x sM>` for vectors, which must have at least 2 elements.
0018 ///    * `pN` for pointers
0019 ///
0020 /// Other information required for correct selection is expected to be carried
0021 /// by the opcode, or non-type flags. For example the distinction between G_ADD
0022 /// and G_FADD for int/float or fast-math flags.
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   /// Get a low-level scalar or aggregate "bag of bits".
0042   static constexpr LLT scalar(unsigned SizeInBits) {
0043     return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
0044                ElementCount::getFixed(0), SizeInBits,
0045                /*AddressSpace=*/0};
0046   }
0047 
0048   /// Get a low-level token; just a scalar with zero bits (or no size).
0049   static constexpr LLT token() {
0050     return LLT{/*isPointer=*/false, /*isVector=*/false,
0051                /*isScalar=*/true,   ElementCount::getFixed(0),
0052                /*SizeInBits=*/0,
0053                /*AddressSpace=*/0};
0054   }
0055 
0056   /// Get a low-level pointer in the given address space.
0057   static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
0058     assert(SizeInBits > 0 && "invalid pointer size");
0059     return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
0060                ElementCount::getFixed(0), SizeInBits, AddressSpace};
0061   }
0062 
0063   /// Get a low-level vector of some number of elements and element width.
0064   static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
0065     assert(!EC.isScalar() && "invalid number of vector elements");
0066     return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
0067                EC, ScalarSizeInBits, /*AddressSpace=*/0};
0068   }
0069 
0070   /// Get a low-level vector of some number of elements and element type.
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                /*isVector=*/true,
0076                /*isScalar=*/false,
0077                EC,
0078                ScalarTy.getSizeInBits().getFixedValue(),
0079                ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
0080   }
0081 
0082   /// Get a 16-bit IEEE half value.
0083   /// TODO: Add IEEE semantics to type - This currently returns a simple `scalar(16)`.
0084   static constexpr LLT float16() {
0085     return scalar(16);
0086   }
0087 
0088   /// Get a 32-bit IEEE float value.
0089   static constexpr LLT float32() {
0090     return scalar(32);
0091   }
0092 
0093   /// Get a 64-bit IEEE double value.
0094   static constexpr LLT float64() {
0095     return scalar(64);
0096   }
0097 
0098   /// Get a low-level fixed-width vector of some number of elements and element
0099   /// width.
0100   static constexpr LLT fixed_vector(unsigned NumElements,
0101                                     unsigned ScalarSizeInBits) {
0102     return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
0103   }
0104 
0105   /// Get a low-level fixed-width vector of some number of elements and element
0106   /// type.
0107   static constexpr LLT fixed_vector(unsigned NumElements, LLT ScalarTy) {
0108     return vector(ElementCount::getFixed(NumElements), ScalarTy);
0109   }
0110 
0111   /// Get a low-level scalable vector of some number of elements and element
0112   /// width.
0113   static constexpr LLT scalable_vector(unsigned MinNumElements,
0114                                        unsigned ScalarSizeInBits) {
0115     return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
0116   }
0117 
0118   /// Get a low-level scalable vector of some number of elements and element
0119   /// type.
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   /// Returns the number of elements in a vector LLT. Must only be called on
0158   /// vector types.
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   /// Returns true if the LLT is a scalable vector. Must only be called on
0169   /// vector types.
0170   constexpr bool isScalable() const {
0171     assert(isVector() && "Expected a vector type");
0172     return getFieldValue(VectorScalableFieldInfo);
0173   }
0174 
0175   /// Returns true if the LLT is a fixed vector. Returns false otherwise, even
0176   /// if the LLT is not a vector type.
0177   constexpr bool isFixedVector() const { return isVector() && !isScalable(); }
0178 
0179   /// Returns true if the LLT is a scalable vector. Returns false otherwise,
0180   /// even if the LLT is not a vector type.
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   /// Returns the total size of the type. Must only be called on sized types.
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   /// Returns the total size of the type in bytes, i.e. number of whole bytes
0199   /// needed to represent the size in bits. Must only be called on sized types.
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   /// If this type is a vector, return a vector with the same number of elements
0210   /// but the new element type. Otherwise, return the new element type.
0211   constexpr LLT changeElementType(LLT NewEltTy) const {
0212     return isVector() ? LLT::vector(getElementCount(), NewEltTy) : NewEltTy;
0213   }
0214 
0215   /// If this type is a vector, return a vector with the same number of elements
0216   /// but the new element size. Otherwise, return the new element type. Invalid
0217   /// for pointer types. For pointer types, use changeElementType.
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   /// Return a vector or scalar with the same element type and the new element
0226   /// count.
0227   constexpr LLT changeElementCount(ElementCount EC) const {
0228     return LLT::scalarOrVector(EC, getScalarType());
0229   }
0230 
0231   /// Return a type that is \p Factor times smaller. Reduces the number of
0232   /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
0233   /// not attempt to handle cases that aren't evenly divisible.
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   /// Produce a vector type that is \p Factor times bigger, preserving the
0249   /// element type. For a scalar or pointer, this will produce a new vector with
0250   /// \p Factor elements.
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   /// Returns the vector's element type. Only valid for vector types.
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   /// LLT is packed into 64 bits as follows:
0303   /// isScalar : 1
0304   /// isPointer : 1
0305   /// isVector  : 1
0306   /// with 61 bits remaining for Kind-specific data, packed in bitfields
0307   /// as described below. As there isn't a simple portable way to pack bits
0308   /// into bitfields, here the different fields in the packed structure is
0309   /// described in static const *Field variables. Each of these variables
0310   /// is a 2-element array, with the first element describing the bitfield size
0311   /// and the second element describing the bitfield offset.
0312   ///
0313   /// +--------+---------+--------+----------+----------------------+
0314   /// |isScalar|isPointer|isVector| RawData  |Notes                 |
0315   /// +--------+---------+--------+----------+----------------------+
0316   /// |   0    |    0    |   0    |    0     |Invalid               |
0317   /// +--------+---------+--------+----------+----------------------+
0318   /// |   0    |    0    |   1    |    0     |Tombstone Key         |
0319   /// +--------+---------+--------+----------+----------------------+
0320   /// |   0    |    1    |   0    |    0     |Empty Key             |
0321   /// +--------+---------+--------+----------+----------------------+
0322   /// |   1    |    0    |   0    |    0     |Token                 |
0323   /// +--------+---------+--------+----------+----------------------+
0324   /// |   1    |    0    |   0    | non-zero |Scalar                |
0325   /// +--------+---------+--------+----------+----------------------+
0326   /// |   0    |    1    |   0    | non-zero |Pointer               |
0327   /// +--------+---------+--------+----------+----------------------+
0328   /// |   0    |    0    |   1    | non-zero |Vector of non-pointer |
0329   /// +--------+---------+--------+----------+----------------------+
0330   /// |   0    |    1    |   1    | non-zero |Vector of pointer     |
0331   /// +--------+---------+--------+----------+----------------------+
0332   ///
0333   /// Everything else is reserved.
0334   typedef int BitFieldInfo[2];
0335   ///
0336   /// This is how the bitfields are packed per Kind:
0337   /// * Invalid:
0338   ///   gets encoded as RawData == 0, as that is an invalid encoding, since for
0339   ///   valid encodings, SizeInBits/SizeOfElement must be larger than 0.
0340   /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
0341   ///   SizeInBits: 32;
0342   static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
0343   /// * Pointer (isPointer == 1 && isVector == 0):
0344   ///   SizeInBits: 16;
0345   ///   AddressSpace: 24;
0346   static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 45};
0347   static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 21};
0348   /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
0349   ///   NumElements: 16;
0350   ///   SizeOfElement: 32;
0351   ///   Scalable: 1;
0352   static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 5};
0353   static const constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
0354   /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
0355   ///   NumElements: 16;
0356   ///   SizeOfElement: 16;
0357   ///   AddressSpace: 24;
0358   ///   Scalable: 1;
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 // LLVM_CODEGEN_LOWLEVELTYPE_H