LLVM 22.0.0git
LowLevelType.h
Go to the documentation of this file.
1//== llvm/CodeGenTypes/LowLevelType.h -------------------------- -*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// Implement a low-level type suitable for MachineInstr level instruction
10/// selection.
11///
12/// For a type attached to a MachineInstr, we only care about 2 details: total
13/// size and the number of vector lanes (if any). Accordingly, there are 4
14/// possible valid type-kinds:
15///
16/// * `sN` for scalars and aggregates
17/// * `<N x sM>` for vectors, which must have at least 2 elements.
18/// * `pN` for pointers
19///
20/// Other information required for correct selection is expected to be carried
21/// by the opcode, or non-type flags. For example the distinction between G_ADD
22/// and G_FADD for int/float or fast-math flags.
23///
24//===----------------------------------------------------------------------===//
25
26#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H
27#define LLVM_CODEGEN_LOWLEVELTYPE_H
28
32#include "llvm/Support/Debug.h"
33#include <cassert>
34
35namespace llvm {
36
37class Type;
38class raw_ostream;
39
40class LLT {
41public:
42 /// Get a low-level scalar or aggregate "bag of bits".
43 static constexpr LLT scalar(unsigned SizeInBits) {
44 return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
45 ElementCount::getFixed(0), SizeInBits,
46 /*AddressSpace=*/0};
47 }
48
49 /// Get a low-level token; just a scalar with zero bits (or no size).
50 static constexpr LLT token() {
51 return LLT{/*isPointer=*/false, /*isVector=*/false,
52 /*isScalar=*/true, ElementCount::getFixed(0),
53 /*SizeInBits=*/0,
54 /*AddressSpace=*/0};
55 }
56
57 /// Get a low-level pointer in the given address space.
58 static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
59 assert(SizeInBits > 0 && "invalid pointer size");
60 return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
61 ElementCount::getFixed(0), SizeInBits, AddressSpace};
62 }
63
64 /// Get a low-level vector of some number of elements and element width.
65 static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
66 assert(!EC.isScalar() && "invalid number of vector elements");
67 return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
68 EC, ScalarSizeInBits, /*AddressSpace=*/0};
69 }
70
71 /// Get a low-level vector of some number of elements and element type.
72 static constexpr LLT vector(ElementCount EC, LLT ScalarTy) {
73 assert(!EC.isScalar() && "invalid number of vector elements");
74 assert(!ScalarTy.isVector() && "invalid vector element type");
75 return LLT{ScalarTy.isPointer(),
76 /*isVector=*/true,
77 /*isScalar=*/false,
78 EC,
79 ScalarTy.getSizeInBits().getFixedValue(),
80 ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
81 }
82
83 /// Get a 16-bit IEEE half value.
84 /// TODO: Add IEEE semantics to type - This currently returns a simple `scalar(16)`.
85 static constexpr LLT float16() {
86 return scalar(16);
87 }
88
89 /// Get a 32-bit IEEE float value.
90 static constexpr LLT float32() {
91 return scalar(32);
92 }
93
94 /// Get a 64-bit IEEE double value.
95 static constexpr LLT float64() {
96 return scalar(64);
97 }
98
99 /// Get a low-level fixed-width vector of some number of elements and element
100 /// width.
101 static constexpr LLT fixed_vector(unsigned NumElements,
102 unsigned ScalarSizeInBits) {
103 return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
104 }
105
106 /// Get a low-level fixed-width vector of some number of elements and element
107 /// type.
108 static constexpr LLT fixed_vector(unsigned NumElements, LLT ScalarTy) {
109 return vector(ElementCount::getFixed(NumElements), ScalarTy);
110 }
111
112 /// Get a low-level scalable vector of some number of elements and element
113 /// width.
114 static constexpr LLT scalable_vector(unsigned MinNumElements,
115 unsigned ScalarSizeInBits) {
116 return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
117 }
118
119 /// Get a low-level scalable vector of some number of elements and element
120 /// type.
121 static constexpr LLT scalable_vector(unsigned MinNumElements, LLT ScalarTy) {
122 return vector(ElementCount::getScalable(MinNumElements), ScalarTy);
123 }
124
125 static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy) {
126 return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
127 }
128
129 static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
130 assert(ScalarSize <= std::numeric_limits<unsigned>::max() &&
131 "Not enough bits in LLT to represent size");
132 return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
133 }
134
135 explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
136 ElementCount EC, uint64_t SizeInBits,
137 unsigned AddressSpace)
138 : LLT() {
139 init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
140 }
141 explicit constexpr LLT()
142 : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
143
144 LLVM_ABI explicit LLT(MVT VT);
145
146 constexpr bool isValid() const { return IsScalar || RawData != 0; }
147 constexpr bool isScalar() const { return IsScalar; }
148 constexpr bool isToken() const { return IsScalar && RawData == 0; };
149 constexpr bool isVector() const { return isValid() && IsVector; }
150 constexpr bool isPointer() const {
151 return isValid() && IsPointer && !IsVector;
152 }
153 constexpr bool isPointerVector() const { return IsPointer && isVector(); }
154 constexpr bool isPointerOrPointerVector() const {
155 return IsPointer && isValid();
156 }
157
158 /// Returns the number of elements in a vector LLT. Must only be called on
159 /// vector types.
160 constexpr uint16_t getNumElements() const {
161 if (isScalable())
163 "Possible incorrect use of LLT::getNumElements() for "
164 "scalable vector. Scalable flag may be dropped, use "
165 "LLT::getElementCount() instead");
167 }
168
169 /// Returns true if the LLT is a scalable vector. Must only be called on
170 /// vector types.
171 constexpr bool isScalable() const {
172 assert(isVector() && "Expected a vector type");
173 return getFieldValue(VectorScalableFieldInfo);
174 }
175
176 /// Returns true if the LLT is a fixed vector. Returns false otherwise, even
177 /// if the LLT is not a vector type.
178 constexpr bool isFixedVector() const { return isVector() && !isScalable(); }
179
180 /// Returns true if the LLT is a scalable vector. Returns false otherwise,
181 /// even if the LLT is not a vector type.
182 constexpr bool isScalableVector() const { return isVector() && isScalable(); }
183
184 constexpr ElementCount getElementCount() const {
185 assert(IsVector && "cannot get number of elements on scalar/aggregate");
186 return ElementCount::get(getFieldValue(VectorElementsFieldInfo),
187 isScalable());
188 }
189
190 /// Returns the total size of the type. Must only be called on sized types.
191 constexpr TypeSize getSizeInBits() const {
192 if (isPointer() || isScalar())
194 auto EC = getElementCount();
195 return TypeSize(getScalarSizeInBits() * EC.getKnownMinValue(),
196 EC.isScalable());
197 }
198
199 /// Returns the total size of the type in bytes, i.e. number of whole bytes
200 /// needed to represent the size in bits. Must only be called on sized types.
201 constexpr TypeSize getSizeInBytes() const {
202 TypeSize BaseSize = getSizeInBits();
203 return {(BaseSize.getKnownMinValue() + 7) / 8, BaseSize.isScalable()};
204 }
205
206 constexpr LLT getScalarType() const {
207 return isVector() ? getElementType() : *this;
208 }
209
210 /// Returns a vector with the same number of elements but the new element
211 /// type. Must only be called on vector types.
212 constexpr LLT changeVectorElementType(LLT NewEltTy) const {
213 return LLT::vector(getElementCount(), NewEltTy);
214 }
215
216 /// If this type is a vector, return a vector with the same number of elements
217 /// but the new element type. Otherwise, return the new element type.
218 constexpr LLT changeElementType(LLT NewEltTy) const {
219 return isVector() ? changeVectorElementType(NewEltTy) : NewEltTy;
220 }
221
222 /// If this type is a vector, return a vector with the same number of elements
223 /// but the new element size. Otherwise, return the new element type. Invalid
224 /// for pointer types. For pointer types, use changeElementType.
225 constexpr LLT changeElementSize(unsigned NewEltSize) const {
227 "invalid to directly change element size for pointers");
228 return isVector() ? LLT::vector(getElementCount(), NewEltSize)
229 : LLT::scalar(NewEltSize);
230 }
231
232 /// Return a vector with the same element type and the new element count. Must
233 /// be called on vector types.
235 assert(isVector() &&
236 "cannot change vector element count of non-vector type");
237 return LLT::vector(EC, getElementType());
238 }
239
240 /// Return a vector or scalar with the same element type and the new element
241 /// count.
242 constexpr LLT changeElementCount(ElementCount EC) const {
244 }
245
246 /// Return a type that is \p Factor times smaller. Reduces the number of
247 /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
248 /// not attempt to handle cases that aren't evenly divisible.
249 constexpr LLT divide(int Factor) const {
250 assert(Factor != 1);
251 assert((!isScalar() || getScalarSizeInBits() != 0) &&
252 "cannot divide scalar of size zero");
253 if (isVector()) {
254 assert(getElementCount().isKnownMultipleOf(Factor));
255 return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
257 }
258
259 assert(getScalarSizeInBits() % Factor == 0);
260 return scalar(getScalarSizeInBits() / Factor);
261 }
262
263 /// Produce a vector type that is \p Factor times bigger, preserving the
264 /// element type. For a scalar or pointer, this will produce a new vector with
265 /// \p Factor elements.
266 constexpr LLT multiplyElements(int Factor) const {
267 if (isVector()) {
268 return scalarOrVector(getElementCount().multiplyCoefficientBy(Factor),
270 }
271
272 return fixed_vector(Factor, *this);
273 }
274
275 constexpr bool isByteSized() const {
277 }
278
279 constexpr unsigned getScalarSizeInBits() const {
281 return getFieldValue(PointerSizeFieldInfo);
282 return getFieldValue(ScalarSizeFieldInfo);
283 }
284
285 constexpr unsigned getAddressSpace() const {
287 "cannot get address space of non-pointer type");
288 return getFieldValue(PointerAddressSpaceFieldInfo);
289 }
290
291 /// Returns the vector's element type. Only valid for vector types.
292 constexpr LLT getElementType() const {
293 assert(isVector() && "cannot get element type of scalar/aggregate");
294 if (IsPointer)
296 else
297 return scalar(getScalarSizeInBits());
298 }
299
300 LLVM_ABI void print(raw_ostream &OS) const;
301
302#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
303 LLVM_DUMP_METHOD void dump() const;
304#endif
305
306 constexpr bool operator==(const LLT &RHS) const {
307 return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
308 IsScalar == RHS.IsScalar && RHS.RawData == RawData;
309 }
310
311 constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
312
313 friend struct DenseMapInfo<LLT>;
315
316private:
317 /// LLT is packed into 64 bits as follows:
318 /// isScalar : 1
319 /// isPointer : 1
320 /// isVector : 1
321 /// with 61 bits remaining for Kind-specific data, packed in bitfields
322 /// as described below. As there isn't a simple portable way to pack bits
323 /// into bitfields, here the different fields in the packed structure is
324 /// described in static const *Field variables. Each of these variables
325 /// is a 2-element array, with the first element describing the bitfield size
326 /// and the second element describing the bitfield offset.
327 ///
328 /// +--------+---------+--------+----------+----------------------+
329 /// |isScalar|isPointer|isVector| RawData |Notes |
330 /// +--------+---------+--------+----------+----------------------+
331 /// | 0 | 0 | 0 | 0 |Invalid |
332 /// +--------+---------+--------+----------+----------------------+
333 /// | 0 | 0 | 1 | 0 |Tombstone Key |
334 /// +--------+---------+--------+----------+----------------------+
335 /// | 0 | 1 | 0 | 0 |Empty Key |
336 /// +--------+---------+--------+----------+----------------------+
337 /// | 1 | 0 | 0 | 0 |Token |
338 /// +--------+---------+--------+----------+----------------------+
339 /// | 1 | 0 | 0 | non-zero |Scalar |
340 /// +--------+---------+--------+----------+----------------------+
341 /// | 0 | 1 | 0 | non-zero |Pointer |
342 /// +--------+---------+--------+----------+----------------------+
343 /// | 0 | 0 | 1 | non-zero |Vector of non-pointer |
344 /// +--------+---------+--------+----------+----------------------+
345 /// | 0 | 1 | 1 | non-zero |Vector of pointer |
346 /// +--------+---------+--------+----------+----------------------+
347 ///
348 /// Everything else is reserved.
349 typedef int BitFieldInfo[2];
350 ///
351 /// This is how the bitfields are packed per Kind:
352 /// * Invalid:
353 /// gets encoded as RawData == 0, as that is an invalid encoding, since for
354 /// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
355 /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
356 /// SizeInBits: 32;
357 static constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
358 /// * Pointer (isPointer == 1 && isVector == 0):
359 /// SizeInBits: 16;
360 /// AddressSpace: 24;
361 static constexpr BitFieldInfo PointerSizeFieldInfo{16, 45};
362 static constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 21};
363 /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
364 /// NumElements: 16;
365 /// SizeOfElement: 32;
366 /// Scalable: 1;
367 static constexpr BitFieldInfo VectorElementsFieldInfo{16, 5};
368 static constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
369 /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
370 /// NumElements: 16;
371 /// SizeOfElement: 16;
372 /// AddressSpace: 24;
373 /// Scalable: 1;
374
375 uint64_t IsScalar : 1;
376 uint64_t IsPointer : 1;
377 uint64_t IsVector : 1;
378 uint64_t RawData : 61;
379
380 static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
381 const int FieldSizeInBits = FieldInfo[0];
382 return (((uint64_t)1) << FieldSizeInBits) - 1;
383 }
384 static constexpr uint64_t maskAndShift(uint64_t Val, uint64_t Mask,
385 uint8_t Shift) {
386 assert(Val <= Mask && "Value too large for field");
387 return (Val & Mask) << Shift;
388 }
389 static constexpr uint64_t maskAndShift(uint64_t Val,
390 const BitFieldInfo FieldInfo) {
391 return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
392 }
393
394 constexpr uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
395 return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
396 }
397
398 constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
399 ElementCount EC, uint64_t SizeInBits,
400 unsigned AddressSpace) {
401 assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
402 "Not enough bits in LLT to represent size");
403 this->IsPointer = IsPointer;
404 this->IsVector = IsVector;
405 this->IsScalar = IsScalar;
406 if (IsPointer) {
407 RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
408 maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
409 } else {
410 RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
411 }
412 if (IsVector) {
413 RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
414 maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
415 }
416 }
417
418public:
419 constexpr uint64_t getUniqueRAWLLTData() const {
420 return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
421 ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
422 }
423};
424
425inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
426 Ty.print(OS);
427 return OS;
428}
429
430template<> struct DenseMapInfo<LLT> {
431 static inline LLT getEmptyKey() {
432 LLT Invalid;
433 Invalid.IsPointer = true;
434 return Invalid;
435 }
436 static inline LLT getTombstoneKey() {
437 LLT Invalid;
438 Invalid.IsVector = true;
439 return Invalid;
440 }
441 static inline unsigned getHashValue(const LLT &Ty) {
442 uint64_t Val = Ty.getUniqueRAWLLTData();
444 }
445 static bool isEqual(const LLT &LHS, const LLT &RHS) {
446 return LHS == RHS;
447 }
448};
449
450}
451
452#endif // LLVM_CODEGEN_LOWLEVELTYPE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
This file defines DenseMapInfo traits for DenseMap.
static std::pair< Value *, APInt > getMask(Value *WideMask, unsigned Factor, ElementCount LeafValueEC)
Value * RHS
Value * LHS
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:315
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLVM_ABI void print(raw_ostream &OS) const
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize)
constexpr unsigned getScalarSizeInBits() const
constexpr LLT(bool isPointer, bool isVector, bool isScalar, ElementCount EC, uint64_t SizeInBits, unsigned AddressSpace)
constexpr bool isScalar() const
static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits)
Get a low-level scalable vector of some number of elements and element width.
constexpr bool operator==(const LLT &RHS) const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
constexpr LLT multiplyElements(int Factor) const
Produce a vector type that is Factor times bigger, preserving the element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
constexpr bool isPointerVector() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool operator!=(const LLT &RHS) const
friend class GISelInstProfileBuilder
constexpr bool isToken() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr uint64_t getUniqueRAWLLTData() const
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT()
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT vector(ElementCount EC, LLT ScalarTy)
Get a low-level vector of some number of elements and element type.
constexpr ElementCount getElementCount() const
constexpr LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
static constexpr LLT fixed_vector(unsigned NumElements, LLT ScalarTy)
Get a low-level fixed-width vector of some number of elements and element type.
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
static constexpr LLT token()
Get a low-level token; just a scalar with zero bits (or no size).
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
LLVM_DUMP_METHOD void dump() const
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr LLT getScalarType() const
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
static constexpr LLT scalable_vector(unsigned MinNumElements, LLT ScalarTy)
Get a low-level scalable vector of some number of elements and element type.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
constexpr LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
constexpr LLT divide(int Factor) const
Return a type that is Factor times smaller.
Machine Value Type.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:180
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:177
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
static bool isEqual(const LLT &LHS, const LLT &RHS)
static unsigned getHashValue(const LLT &Ty)
An information struct used to provide DenseMap with the various necessary components for a given valu...