1 //== llvm/CodeGen/GlobalISel/LowLevelType.h -------------------- -*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// Implement a low-level type suitable for MachineInstr level instruction
13 /// For a type attached to a MachineInstr, we only care about 2 details: total
14 /// size and the number of vector lanes (if any). Accordingly, there are 4
15 /// possible valid type-kinds:
17 /// * `sN` for scalars and aggregates
18 /// * `<N x sM>` for vectors, which must have at least 2 elements.
19 /// * `pN` for pointers
21 /// Other information required for correct selection is expected to be carried
22 /// by the opcode, or non-type flags. For example the distinction between G_ADD
23 /// and G_FADD for int/float or fast-math flags.
25 //===----------------------------------------------------------------------===//
27 #ifndef LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
28 #define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
31 #include "llvm/ADT/DenseMapInfo.h"
32 #include "llvm/CodeGen/ValueTypes.h"
43 enum TypeKind : uint16_t {
50 /// Get a low-level scalar or aggregate "bag of bits".
51 static LLT scalar(unsigned SizeInBits) {
52 assert(SizeInBits > 0 && "invalid scalar size");
53 return LLT{Scalar, 1, SizeInBits};
56 /// Get a low-level pointer in the given address space (defaulting to 0).
57 static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
58 return LLT{Pointer, AddressSpace, SizeInBits};
61 /// Get a low-level vector of some number of elements and element width.
62 /// \p NumElements must be at least 2.
63 static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
64 assert(NumElements > 1 && "invalid number of vector elements");
65 return LLT{Vector, NumElements, ScalarSizeInBits};
68 /// Get a low-level vector of some number of elements and element type.
69 static LLT vector(uint16_t NumElements, LLT ScalarTy) {
70 assert(NumElements > 1 && "invalid number of vector elements");
71 assert(ScalarTy.isScalar() && "invalid vector element type");
72 return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
75 explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
76 : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
77 assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
78 "invalid number of vector elements");
81 explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
83 /// Construct a low-level type based on an LLVM type.
84 explicit LLT(Type &Ty, const DataLayout &DL);
88 bool isValid() const { return Kind != Invalid; }
90 bool isScalar() const { return Kind == Scalar; }
92 bool isPointer() const { return Kind == Pointer; }
94 bool isVector() const { return Kind == Vector; }
96 /// Returns the number of elements in a vector LLT. Must only be called on
98 uint16_t getNumElements() const {
99 assert(isVector() && "cannot get number of elements on scalar/aggregate");
100 return ElementsOrAddrSpace;
103 /// Returns the total size of the type. Must only be called on sized types.
104 unsigned getSizeInBits() const {
105 if (isPointer() || isScalar())
107 return SizeInBits * ElementsOrAddrSpace;
110 unsigned getScalarSizeInBits() const {
114 unsigned getAddressSpace() const {
115 assert(isPointer() && "cannot get address space of non-pointer type");
116 return ElementsOrAddrSpace;
119 /// Returns the vector's element type. Only valid for vector types.
120 LLT getElementType() const {
121 assert(isVector() && "cannot get element type of scalar/aggregate");
122 return scalar(SizeInBits);
125 /// Get a low-level type with half the size of the original, by halving the
126 /// size of the scalar type involved. For example `s32` will become `s16`,
127 /// `<2 x s32>` will become `<2 x s16>`.
128 LLT halfScalarSize() const {
129 assert(!isPointer() && getScalarSizeInBits() > 1 &&
130 getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
131 return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
134 /// Get a low-level type with twice the size of the original, by doubling the
135 /// size of the scalar type involved. For example `s32` will become `s64`,
136 /// `<2 x s32>` will become `<2 x s64>`.
137 LLT doubleScalarSize() const {
138 assert(!isPointer() && "cannot change size of this type");
139 return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
142 /// Get a low-level type with half the size of the original, by halving the
143 /// number of vector elements of the scalar type involved. The source must be
144 /// a vector type with an even number of elements. For example `<4 x s32>`
145 /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
146 LLT halfElements() const {
147 assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
148 "cannot half odd vector");
149 if (ElementsOrAddrSpace == 2)
150 return scalar(SizeInBits);
152 return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
156 /// Get a low-level type with twice the size of the original, by doubling the
157 /// number of vector elements of the scalar type involved. The source must be
158 /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
159 /// the number of elements in sN produces <2 x sN>.
160 LLT doubleElements() const {
161 assert(!isPointer() && "cannot double elements in pointer");
162 return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
166 void print(raw_ostream &OS) const;
168 bool operator==(const LLT &RHS) const {
169 return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
170 ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
173 bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
175 friend struct DenseMapInfo<LLT>;
178 uint16_t ElementsOrAddrSpace;
182 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
187 template<> struct DenseMapInfo<LLT> {
188 static inline LLT getEmptyKey() {
189 return LLT{LLT::Invalid, 0, -1u};
191 static inline LLT getTombstoneKey() {
192 return LLT{LLT::Invalid, 0, -2u};
194 static inline unsigned getHashValue(const LLT &Ty) {
195 uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
196 ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
197 return DenseMapInfo<uint64_t>::getHashValue(Val);
199 static bool isEqual(const LLT &LHS, const LLT &RHS) {