//===- CodeGen/MachineValueType.h - Machine-Level types ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the set of machine-level target independent types which // legal values in the code generator use. // // Constants and properties are defined in ValueTypes.td. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H #define LLVM_CODEGEN_MACHINEVALUETYPE_H #include "llvm/ADT/Sequence.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/TypeSize.h" #include #include namespace llvm { class Type; class raw_ostream; /// Machine Value Type. Every type that is supported natively by some /// processor targeted by LLVM occurs here. This means that any legal value /// type can be represented by an MVT. class MVT { public: enum SimpleValueType : uint8_t { // Simple value types that aren't explicitly part of this enumeration // are considered extended value types. INVALID_SIMPLE_VALUE_TYPE = 0, #define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc) Ty = n, #define GET_VT_RANGES #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_ATTR #undef GET_VT_RANGES VALUETYPE_SIZE = LAST_VALUETYPE + 1, // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors // This value must be a multiple of 32. MAX_ALLOWED_VALUETYPE = 224, }; static_assert(FIRST_VALUETYPE > 0); static_assert(LAST_VALUETYPE < MAX_ALLOWED_VALUETYPE); SimpleValueType SimpleTy = INVALID_SIMPLE_VALUE_TYPE; constexpr MVT() = default; constexpr MVT(SimpleValueType SVT) : SimpleTy(SVT) {} bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } bool operator!=(const MVT& S) const { return SimpleTy != S.SimpleTy; } bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } /// Support for debugging, callable in GDB: VT.dump() void dump() const; /// Implement operator<<. void print(raw_ostream &OS) const; /// Return true if this is a valid simple valuetype. bool isValid() const { return (SimpleTy >= MVT::FIRST_VALUETYPE && SimpleTy <= MVT::LAST_VALUETYPE); } /// Return true if this is a FP or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && SimpleTy <= MVT::LAST_FP_VALUETYPE) || (SimpleTy >= MVT::FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_FP_FIXEDLEN_VECTOR_VALUETYPE) || (SimpleTy >= MVT::FIRST_FP_SCALABLE_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_FP_SCALABLE_VECTOR_VALUETYPE)); } /// Return true if this is an integer or a vector integer type. bool isInteger() const { return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || (SimpleTy >= MVT::FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE) || (SimpleTy >= MVT::FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE)); } /// Return true if this is an integer, not including vectors. bool isScalarInteger() const { return (SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE); } /// Return true if this is a vector value type. bool isVector() const { return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); } /// Return true if this is a vector value type where the /// runtime length is machine dependent bool isScalableVector() const { return (SimpleTy >= MVT::FIRST_SCALABLE_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_SCALABLE_VECTOR_VALUETYPE); } /// Return true if this is a custom target type that has a scalable size. bool isScalableTargetExtVT() const { return SimpleTy == MVT::aarch64svcount; } /// Return true if the type is a scalable type. bool isScalableVT() const { return isScalableVector() || isScalableTargetExtVT(); } bool isFixedLengthVector() const { return (SimpleTy >= MVT::FIRST_FIXEDLEN_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_FIXEDLEN_VECTOR_VALUETYPE); } /// Return true if this is a 16-bit vector type. bool is16BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 16); } /// Return true if this is a 32-bit vector type. bool is32BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 32); } /// Return true if this is a 64-bit vector type. bool is64BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 64); } /// Return true if this is a 128-bit vector type. bool is128BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 128); } /// Return true if this is a 256-bit vector type. bool is256BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 256); } /// Return true if this is a 512-bit vector type. bool is512BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 512); } /// Return true if this is a 1024-bit vector type. bool is1024BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 1024); } /// Return true if this is a 2048-bit vector type. bool is2048BitVector() const { return (isFixedLengthVector() && getFixedSizeInBits() == 2048); } /// Return true if this is an overloaded type for TableGen. bool isOverloaded() const { switch (SimpleTy) { #define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc) \ case Ty: \ return Any; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_ATTR default: return false; } } /// Return a vector with the same number of elements as this vector, but /// with the element type converted to an integer type with the same /// bitwidth. MVT changeVectorElementTypeToInteger() const { MVT EltTy = getVectorElementType(); MVT IntTy = MVT::getIntegerVT(EltTy.getSizeInBits()); MVT VecTy = MVT::getVectorVT(IntTy, getVectorElementCount()); assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE && "Simple vector VT not representable by simple integer vector VT!"); return VecTy; } /// Return a VT for a vector type whose attributes match ourselves /// with the exception of the element type that is chosen by the caller. MVT changeVectorElementType(MVT EltVT) const { MVT VecTy = MVT::getVectorVT(EltVT, getVectorElementCount()); assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE && "Simple vector VT not representable by simple integer vector VT!"); return VecTy; } /// Return the type converted to an equivalently sized integer or vector /// with integer element type. Similar to changeVectorElementTypeToInteger, /// but also handles scalars. MVT changeTypeToInteger() { if (isVector()) return changeVectorElementTypeToInteger(); return MVT::getIntegerVT(getSizeInBits()); } /// Return a VT for a vector type with the same element type but /// half the number of elements. MVT getHalfNumVectorElementsVT() const { MVT EltVT = getVectorElementType(); auto EltCnt = getVectorElementCount(); assert(EltCnt.isKnownEven() && "Splitting vector, but not in half!"); return getVectorVT(EltVT, EltCnt.divideCoefficientBy(2)); } // Return a VT for a vector type with the same element type but // double the number of elements. MVT getDoubleNumVectorElementsVT() const { MVT EltVT = getVectorElementType(); auto EltCnt = getVectorElementCount(); return MVT::getVectorVT(EltVT, EltCnt * 2); } /// Returns true if the given vector is a power of 2. bool isPow2VectorType() const { unsigned NElts = getVectorMinNumElements(); return !(NElts & (NElts - 1)); } /// Widens the length of the given vector MVT up to the nearest power of 2 /// and returns that type. MVT getPow2VectorType() const { if (isPow2VectorType()) return *this; ElementCount NElts = getVectorElementCount(); unsigned NewMinCount = 1 << Log2_32_Ceil(NElts.getKnownMinValue()); NElts = ElementCount::get(NewMinCount, NElts.isScalable()); return MVT::getVectorVT(getVectorElementType(), NElts); } /// If this is a vector, return the element type, otherwise return this. MVT getScalarType() const { return isVector() ? getVectorElementType() : *this; } MVT getVectorElementType() const { switch (SimpleTy) { default: llvm_unreachable("Not a vector MVT!"); #define GET_VT_VECATTR(Ty, Sc, nElem, ElTy, ElSz) \ case Ty: \ return ElTy; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_VECATTR } } /// Given a vector type, return the minimum number of elements it contains. unsigned getVectorMinNumElements() const { switch (SimpleTy) { default: llvm_unreachable("Not a vector MVT!"); #define GET_VT_VECATTR(Ty, Sc, nElem, ElTy, ElSz) \ case Ty: \ return nElem; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_VECATTR } } ElementCount getVectorElementCount() const { return ElementCount::get(getVectorMinNumElements(), isScalableVector()); } unsigned getVectorNumElements() const { if (isScalableVector()) llvm::reportInvalidSizeRequest( "Possible incorrect use of MVT::getVectorNumElements() for " "scalable vector. Scalable flag may be dropped, use " "MVT::getVectorElementCount() instead"); return getVectorMinNumElements(); } /// Returns the size of the specified MVT in bits. /// /// If the value type is a scalable vector type, the scalable property will /// be set and the runtime size will be a positive integer multiple of the /// base size. TypeSize getSizeInBits() const { static constexpr TypeSize SizeTable[] = { #define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc) \ TypeSize(Sz, Sc || Ty == aarch64svcount /* FIXME: Not in the td. */), #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_ATTR }; switch (SimpleTy) { case INVALID_SIMPLE_VALUE_TYPE: llvm_unreachable("getSizeInBits called on extended MVT."); case Other: llvm_unreachable("Value type is non-standard value, Other."); case iPTR: llvm_unreachable("Value type size is target-dependent. Ask TLI."); case iPTRAny: case iAny: case fAny: case vAny: case Any: llvm_unreachable("Value type is overloaded."); case token: llvm_unreachable("Token type is a sentinel that cannot be used " "in codegen and has no size"); case Metadata: llvm_unreachable("Value type is metadata."); default: assert(SimpleTy < VALUETYPE_SIZE && "Unexpected value type!"); return SizeTable[SimpleTy - FIRST_VALUETYPE]; } } /// Return the size of the specified fixed width value type in bits. The /// function will assert if the type is scalable. uint64_t getFixedSizeInBits() const { return getSizeInBits().getFixedValue(); } uint64_t getScalarSizeInBits() const { return getScalarType().getSizeInBits().getFixedValue(); } /// Return the number of bytes overwritten by a store of the specified value /// type. /// /// If the value type is a scalable vector type, the scalable property will /// be set and the runtime size will be a positive integer multiple of the /// base size. TypeSize getStoreSize() const { TypeSize BaseSize = getSizeInBits(); return {(BaseSize.getKnownMinValue() + 7) / 8, BaseSize.isScalable()}; } // Return the number of bytes overwritten by a store of this value type or // this value type's element type in the case of a vector. uint64_t getScalarStoreSize() const { return getScalarType().getStoreSize().getFixedValue(); } /// Return the number of bits overwritten by a store of the specified value /// type. /// /// If the value type is a scalable vector type, the scalable property will /// be set and the runtime size will be a positive integer multiple of the /// base size. TypeSize getStoreSizeInBits() const { return getStoreSize() * 8; } /// Returns true if the number of bits for the type is a multiple of an /// 8-bit byte. bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); } /// Return true if we know at compile time this has more bits than VT. bool knownBitsGT(MVT VT) const { return TypeSize::isKnownGT(getSizeInBits(), VT.getSizeInBits()); } /// Return true if we know at compile time this has more than or the same /// bits as VT. bool knownBitsGE(MVT VT) const { return TypeSize::isKnownGE(getSizeInBits(), VT.getSizeInBits()); } /// Return true if we know at compile time this has fewer bits than VT. bool knownBitsLT(MVT VT) const { return TypeSize::isKnownLT(getSizeInBits(), VT.getSizeInBits()); } /// Return true if we know at compile time this has fewer than or the same /// bits as VT. bool knownBitsLE(MVT VT) const { return TypeSize::isKnownLE(getSizeInBits(), VT.getSizeInBits()); } /// Return true if this has more bits than VT. bool bitsGT(MVT VT) const { assert(isScalableVector() == VT.isScalableVector() && "Comparison between scalable and fixed types"); return knownBitsGT(VT); } /// Return true if this has no less bits than VT. bool bitsGE(MVT VT) const { assert(isScalableVector() == VT.isScalableVector() && "Comparison between scalable and fixed types"); return knownBitsGE(VT); } /// Return true if this has less bits than VT. bool bitsLT(MVT VT) const { assert(isScalableVector() == VT.isScalableVector() && "Comparison between scalable and fixed types"); return knownBitsLT(VT); } /// Return true if this has no more bits than VT. bool bitsLE(MVT VT) const { assert(isScalableVector() == VT.isScalableVector() && "Comparison between scalable and fixed types"); return knownBitsLE(VT); } static MVT getFloatingPointVT(unsigned BitWidth) { #define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc) \ if (FP == 3 && sz == BitWidth) \ return Ty; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_ATTR llvm_unreachable("Bad bit width!"); } static MVT getIntegerVT(unsigned BitWidth) { #define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc) \ if (Int == 3 && sz == BitWidth) \ return Ty; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_ATTR return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); } static MVT getVectorVT(MVT VT, unsigned NumElements) { #define GET_VT_VECATTR(Ty, Sc, nElem, ElTy, ElSz) \ if (!Sc && VT.SimpleTy == ElTy && NumElements == nElem) \ return Ty; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_VECATTR return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); } static MVT getScalableVectorVT(MVT VT, unsigned NumElements) { #define GET_VT_VECATTR(Ty, Sc, nElem, ElTy, ElSz) \ if (Sc && VT.SimpleTy == ElTy && NumElements == nElem) \ return Ty; #include "llvm/CodeGen/GenVT.inc" #undef GET_VT_VECATTR return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); } static MVT getVectorVT(MVT VT, unsigned NumElements, bool IsScalable) { if (IsScalable) return getScalableVectorVT(VT, NumElements); return getVectorVT(VT, NumElements); } static MVT getVectorVT(MVT VT, ElementCount EC) { if (EC.isScalable()) return getScalableVectorVT(VT, EC.getKnownMinValue()); return getVectorVT(VT, EC.getKnownMinValue()); } /// Return the value type corresponding to the specified type. This returns /// all pointers as iPTR. If HandleUnknown is true, unknown types are /// returned as Other, otherwise they are invalid. static MVT getVT(Type *Ty, bool HandleUnknown = false); public: /// SimpleValueType Iteration /// @{ static auto all_valuetypes() { return enum_seq_inclusive(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE, force_iteration_on_noniterable_enum); } static auto integer_valuetypes() { return enum_seq_inclusive(MVT::FIRST_INTEGER_VALUETYPE, MVT::LAST_INTEGER_VALUETYPE, force_iteration_on_noniterable_enum); } static auto fp_valuetypes() { return enum_seq_inclusive(MVT::FIRST_FP_VALUETYPE, MVT::LAST_FP_VALUETYPE, force_iteration_on_noniterable_enum); } static auto vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_VECTOR_VALUETYPE, MVT::LAST_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } static auto fixedlen_vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_FIXEDLEN_VECTOR_VALUETYPE, MVT::LAST_FIXEDLEN_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } static auto scalable_vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_SCALABLE_VECTOR_VALUETYPE, MVT::LAST_SCALABLE_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } static auto integer_fixedlen_vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE, MVT::LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } static auto fp_fixedlen_vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE, MVT::LAST_FP_FIXEDLEN_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } static auto integer_scalable_vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE, MVT::LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } static auto fp_scalable_vector_valuetypes() { return enum_seq_inclusive(MVT::FIRST_FP_SCALABLE_VECTOR_VALUETYPE, MVT::LAST_FP_SCALABLE_VECTOR_VALUETYPE, force_iteration_on_noniterable_enum); } /// @} }; inline raw_ostream &operator<<(raw_ostream &OS, const MVT &VT) { VT.print(OS); return OS; } } // end namespace llvm #endif // LLVM_CODEGEN_MACHINEVALUETYPE_H