Line data Source code
1 : //== llvm/Support/LowLevelTypeImpl.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_SUPPORT_LOWLEVELTYPEIMPL_H
28 : #define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
29 :
30 : #include "llvm/ADT/DenseMapInfo.h"
31 : #include "llvm/Support/MachineValueType.h"
32 : #include <cassert>
33 :
34 : namespace llvm {
35 :
36 : class DataLayout;
37 : class Type;
38 : class raw_ostream;
39 :
40 : class LLT {
41 : public:
42 : /// Get a low-level scalar or aggregate "bag of bits".
43 : static LLT scalar(unsigned SizeInBits) {
44 : assert(SizeInBits > 0 && "invalid scalar size");
45 : return LLT{/*isPointer=*/false, /*isVector=*/false, /*NumElements=*/0,
46 : SizeInBits, /*AddressSpace=*/0};
47 : }
48 :
49 : /// Get a low-level pointer in the given address space (defaulting to 0).
50 : static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
51 : assert(SizeInBits > 0 && "invalid pointer size");
52 : return LLT{/*isPointer=*/true, /*isVector=*/false, /*NumElements=*/0,
53 : SizeInBits, AddressSpace};
54 : }
55 :
56 : /// Get a low-level vector of some number of elements and element width.
57 : /// \p NumElements must be at least 2.
58 : static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
59 : assert(NumElements > 1 && "invalid number of vector elements");
60 : assert(ScalarSizeInBits > 0 && "invalid vector element size");
61 : return LLT{/*isPointer=*/false, /*isVector=*/true, NumElements,
62 : ScalarSizeInBits, /*AddressSpace=*/0};
63 : }
64 :
65 : /// Get a low-level vector of some number of elements and element type.
66 2540 : static LLT vector(uint16_t NumElements, LLT ScalarTy) {
67 : assert(NumElements > 1 && "invalid number of vector elements");
68 : assert(!ScalarTy.isVector() && "invalid vector element type");
69 2540 : return LLT{ScalarTy.isPointer(), /*isVector=*/true, NumElements,
70 : ScalarTy.getSizeInBits(),
71 2524 : ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
72 : }
73 :
74 : explicit LLT(bool isPointer, bool isVector, uint16_t NumElements,
75 : unsigned SizeInBits, unsigned AddressSpace) {
76 : init(isPointer, isVector, NumElements, SizeInBits, AddressSpace);
77 : }
78 456259 : explicit LLT() : IsPointer(false), IsVector(false), RawData(0) {}
79 :
80 : explicit LLT(MVT VT);
81 :
82 19546154 : bool isValid() const { return RawData != 0; }
83 :
84 4445723 : bool isScalar() const { return isValid() && !IsPointer && !IsVector; }
85 :
86 7630559 : bool isPointer() const { return isValid() && IsPointer && !IsVector; }
87 :
88 3101762 : bool isVector() const { return isValid() && IsVector; }
89 :
90 : /// Returns the number of elements in a vector LLT. Must only be called on
91 : /// vector types.
92 : uint16_t getNumElements() const {
93 : assert(IsVector && "cannot get number of elements on scalar/aggregate");
94 1288894 : if (!IsPointer)
95 453006 : return getFieldValue(VectorElementsFieldInfo);
96 : else
97 15 : return getFieldValue(PointerVectorElementsFieldInfo);
98 : }
99 :
100 : /// Returns the total size of the type. Must only be called on sized types.
101 4306128 : unsigned getSizeInBits() const {
102 7391859 : if (isPointer() || isScalar())
103 : return getScalarSizeInBits();
104 1006162 : return getScalarSizeInBits() * getNumElements();
105 : }
106 :
107 : unsigned getScalarSizeInBits() const {
108 : assert(RawData != 0 && "Invalid Type");
109 5174506 : if (!IsVector) {
110 3315653 : if (!IsPointer)
111 601684 : return getFieldValue(ScalarSizeFieldInfo);
112 : else
113 22111 : return getFieldValue(PointerSizeFieldInfo);
114 : } else {
115 1015832 : if (!IsPointer)
116 1858826 : return getFieldValue(VectorSizeFieldInfo);
117 : else
118 27 : return getFieldValue(PointerVectorSizeFieldInfo);
119 : }
120 : }
121 :
122 : unsigned getAddressSpace() const {
123 : assert(RawData != 0 && "Invalid Type");
124 : assert(IsPointer && "cannot get address space of non-pointer type");
125 195859 : if (!IsVector)
126 195839 : return getFieldValue(PointerAddressSpaceFieldInfo);
127 : else
128 20 : return getFieldValue(PointerVectorAddressSpaceFieldInfo);
129 : }
130 :
131 : /// Returns the vector's element type. Only valid for vector types.
132 843021 : LLT getElementType() const {
133 : assert(isVector() && "cannot get element type of scalar/aggregate");
134 843021 : if (IsPointer)
135 20 : return pointer(getAddressSpace(), getScalarSizeInBits());
136 : else
137 : return scalar(getScalarSizeInBits());
138 : }
139 :
140 : void print(raw_ostream &OS) const;
141 :
142 0 : bool operator==(const LLT &RHS) const {
143 63697499 : return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
144 54213704 : RHS.RawData == RawData;
145 : }
146 :
147 19633 : bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
148 :
149 : friend struct DenseMapInfo<LLT>;
150 :
151 : private:
152 : /// LLT is packed into 64 bits as follows:
153 : /// isPointer : 1
154 : /// isVector : 1
155 : /// with 62 bits remaining for Kind-specific data, packed in bitfields
156 : /// as described below. As there isn't a simple portable way to pack bits
157 : /// into bitfields, here the different fields in the packed structure is
158 : /// described in static const *Field variables. Each of these variables
159 : /// is a 2-element array, with the first element describing the bitfield size
160 : /// and the second element describing the bitfield offset.
161 : typedef int BitFieldInfo[2];
162 : ///
163 : /// This is how the bitfields are packed per Kind:
164 : /// * Invalid:
165 : /// gets encoded as RawData == 0, as that is an invalid encoding, since for
166 : /// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
167 : /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
168 : /// SizeInBits: 32;
169 : static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0};
170 : /// * Pointer (isPointer == 1 && isVector == 0):
171 : /// SizeInBits: 16;
172 : /// AddressSpace: 23;
173 : static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0};
174 : static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
175 : 23, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
176 : /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
177 : /// NumElements: 16;
178 : /// SizeOfElement: 32;
179 : static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 0};
180 : static const constexpr BitFieldInfo VectorSizeFieldInfo{
181 : 32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
182 : /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
183 : /// NumElements: 16;
184 : /// SizeOfElement: 16;
185 : /// AddressSpace: 23;
186 : static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0};
187 : static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{
188 : 16,
189 : PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]};
190 : static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{
191 : 23, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]};
192 :
193 : uint64_t IsPointer : 1;
194 : uint64_t IsVector : 1;
195 : uint64_t RawData : 62;
196 :
197 0 : static uint64_t getMask(const BitFieldInfo FieldInfo) {
198 0 : const int FieldSizeInBits = FieldInfo[0];
199 0 : return (((uint64_t)1) << FieldSizeInBits) - 1;
200 : }
201 : static uint64_t maskAndShift(uint64_t Val, uint64_t Mask, uint8_t Shift) {
202 : assert(Val <= Mask && "Value too large for field");
203 29814 : return (Val & Mask) << Shift;
204 : }
205 : static uint64_t maskAndShift(uint64_t Val, const BitFieldInfo FieldInfo) {
206 : return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
207 : }
208 : uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
209 6658823 : return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
210 : }
211 :
212 : void init(bool IsPointer, bool IsVector, uint16_t NumElements,
213 : unsigned SizeInBits, unsigned AddressSpace) {
214 2051 : this->IsPointer = IsPointer;
215 2051 : this->IsVector = IsVector;
216 136 : if (!IsVector) {
217 : if (!IsPointer)
218 900124 : RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
219 : else
220 36372 : RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
221 : maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
222 : } else {
223 : assert(NumElements > 1 && "invalid number of vector elements");
224 2540 : if (!IsPointer)
225 52416 : RawData = maskAndShift(NumElements, VectorElementsFieldInfo) |
226 26208 : maskAndShift(SizeInBits, VectorSizeFieldInfo);
227 : else
228 : RawData =
229 32 : maskAndShift(NumElements, PointerVectorElementsFieldInfo) |
230 16 : maskAndShift(SizeInBits, PointerVectorSizeFieldInfo) |
231 : maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo);
232 : }
233 : }
234 : };
235 :
236 997 : inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
237 19200 : Ty.print(OS);
238 997 : return OS;
239 : }
240 :
241 : template<> struct DenseMapInfo<LLT> {
242 : static inline LLT getEmptyKey() {
243 : LLT Invalid;
244 : Invalid.IsPointer = true;
245 : return Invalid;
246 : }
247 : static inline LLT getTombstoneKey() {
248 : LLT Invalid;
249 : Invalid.IsVector = true;
250 : return Invalid;
251 : }
252 : static inline unsigned getHashValue(const LLT &Ty) {
253 6883798 : uint64_t Val = ((uint64_t)Ty.RawData) << 2 | ((uint64_t)Ty.IsPointer) << 1 |
254 3441899 : ((uint64_t)Ty.IsVector);
255 : return DenseMapInfo<uint64_t>::getHashValue(Val);
256 : }
257 0 : static bool isEqual(const LLT &LHS, const LLT &RHS) {
258 64306703 : return LHS == RHS;
259 : }
260 : };
261 :
262 : }
263 :
264 : #endif // LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
|