blob: e008503f734b9536a8d39c4150b27bf50df9a980 [file] [log] [blame]
//===- CodeGenTypes/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 <cassert>
#include <cstdint>
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,
};
static_assert(FIRST_VALUETYPE > 0);
static_assert(LAST_VALUETYPE < token);
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.
/// If HandleUnknown is true, unknown types are returned as Other,
/// otherwise they are invalid.
/// NB: This includes pointer types, which require a DataLayout to convert
/// to a concrete value type.
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