Line data Source code
1 : //== llvm/CodeGen/GlobalISel/LowLevelType.h -------------------- -*- C++ -*-==//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : /// Implement a low-level type suitable for MachineInstr level instruction
11 : /// selection.
12 : ///
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:
16 : ///
17 : /// * `sN` for scalars and aggregates
18 : /// * `<N x sM>` for vectors, which must have at least 2 elements.
19 : /// * `pN` for pointers
20 : ///
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.
24 : //
25 : //===----------------------------------------------------------------------===//
26 :
27 : #ifndef LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
28 : #define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
29 :
30 : #include <cassert>
31 : #include "llvm/ADT/DenseMapInfo.h"
32 : #include "llvm/CodeGen/ValueTypes.h"
33 :
34 : namespace llvm {
35 :
36 : class DataLayout;
37 : class LLVMContext;
38 : class Type;
39 : class raw_ostream;
40 :
41 : class LLT {
42 : public:
43 : enum TypeKind : uint16_t {
44 : Invalid,
45 : Scalar,
46 : Pointer,
47 : Vector,
48 : };
49 :
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 149458 : return LLT{Scalar, 1, SizeInBits};
54 : }
55 :
56 : /// Get a low-level pointer in the given address space (defaulting to 0).
57 : static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
58 7058 : return LLT{Pointer, AddressSpace, SizeInBits};
59 : }
60 :
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 22274 : return LLT{Vector, NumElements, ScalarSizeInBits};
66 : }
67 :
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 50 : return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
73 : }
74 :
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");
79 : }
80 :
81 42428 : explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
82 :
83 : /// Construct a low-level type based on an LLVM type.
84 : explicit LLT(Type &Ty, const DataLayout &DL);
85 :
86 : explicit LLT(MVT VT);
87 :
88 140 : bool isValid() const { return Kind != Invalid; }
89 :
90 15 : bool isScalar() const { return Kind == Scalar; }
91 :
92 4 : bool isPointer() const { return Kind == Pointer; }
93 :
94 120 : bool isVector() const { return Kind == Vector; }
95 :
96 : /// Returns the number of elements in a vector LLT. Must only be called on
97 : /// vector types.
98 : uint16_t getNumElements() const {
99 : assert(isVector() && "cannot get number of elements on scalar/aggregate");
100 : return ElementsOrAddrSpace;
101 : }
102 :
103 : /// Returns the total size of the type. Must only be called on sized types.
104 : unsigned getSizeInBits() const {
105 9591 : if (isPointer() || isScalar())
106 2454 : return SizeInBits;
107 824 : return SizeInBits * ElementsOrAddrSpace;
108 : }
109 :
110 : unsigned getScalarSizeInBits() const {
111 : return SizeInBits;
112 : }
113 :
114 : unsigned getAddressSpace() const {
115 : assert(isPointer() && "cannot get address space of non-pointer type");
116 23 : return ElementsOrAddrSpace;
117 : }
118 :
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 200734 : return scalar(SizeInBits);
123 : }
124 :
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 33 : return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
132 : }
133 :
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 101 : return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
140 : }
141 :
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 17 : if (ElementsOrAddrSpace == 2)
150 : return scalar(SizeInBits);
151 :
152 24 : return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
153 12 : SizeInBits};
154 : }
155 :
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 54 : return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
163 27 : SizeInBits};
164 : }
165 :
166 : void print(raw_ostream &OS) const;
167 :
168 : bool operator==(const LLT &RHS) const {
169 27108996 : return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
170 11612246 : ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
171 : }
172 :
173 1862 : bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
174 :
175 : friend struct DenseMapInfo<LLT>;
176 : private:
177 : unsigned SizeInBits;
178 : uint16_t ElementsOrAddrSpace;
179 : TypeKind Kind;
180 : };
181 :
182 : inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
183 3300 : Ty.print(OS);
184 : return OS;
185 : }
186 :
187 : template<> struct DenseMapInfo<LLT> {
188 : static inline LLT getEmptyKey() {
189 2224928 : return LLT{LLT::Invalid, 0, -1u};
190 : }
191 : static inline LLT getTombstoneKey() {
192 1403939 : return LLT{LLT::Invalid, 0, -2u};
193 : }
194 : static inline unsigned getHashValue(const LLT &Ty) {
195 1336178 : uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
196 1336178 : ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
197 668089 : return DenseMapInfo<uint64_t>::getHashValue(Val);
198 : }
199 : static bool isEqual(const LLT &LHS, const LLT &RHS) {
200 15494231 : return LHS == RHS;
201 : }
202 : };
203 :
204 : }
205 :
206 : #endif
|