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 /// If this type is a vector, return a vector with the same number of elements
211 /// but the new element type. Otherwise, return the new element type.
212 constexpr LLT changeElementType(LLT NewEltTy) const {
213 return isVector() ? LLT::vector(getElementCount(), NewEltTy) : NewEltTy;
214 }
215
216 /// If this type is a vector, return a vector with the same number of elements
217 /// but the new element size. Otherwise, return the new element type. Invalid
218 /// for pointer types. For pointer types, use changeElementType.
219 constexpr LLT changeElementSize(unsigned NewEltSize) const {
221 "invalid to directly change element size for pointers");
222 return isVector() ? LLT::vector(getElementCount(), NewEltSize)
223 : LLT::scalar(NewEltSize);
224 }
225
226 /// Return a vector or scalar with the same element type and the new element
227 /// count.
228 constexpr LLT changeElementCount(ElementCount EC) const {
230 }
231
232 /// Return a type that is \p Factor times smaller. Reduces the number of
233 /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
234 /// not attempt to handle cases that aren't evenly divisible.
235 constexpr LLT divide(int Factor) const {
236 assert(Factor != 1);
237 assert((!isScalar() || getScalarSizeInBits() != 0) &&
238 "cannot divide scalar of size zero");
239 if (isVector()) {
240 assert(getElementCount().isKnownMultipleOf(Factor));
241 return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
243 }
244
245 assert(getScalarSizeInBits() % Factor == 0);
246 return scalar(getScalarSizeInBits() / Factor);
247 }
248
249 /// Produce a vector type that is \p Factor times bigger, preserving the
250 /// element type. For a scalar or pointer, this will produce a new vector with
251 /// \p Factor elements.
252 constexpr LLT multiplyElements(int Factor) const {
253 if (isVector()) {
254 return scalarOrVector(getElementCount().multiplyCoefficientBy(Factor),
256 }
257
258 return fixed_vector(Factor, *this);
259 }
260
261 constexpr bool isByteSized() const {
263 }
264
265 constexpr unsigned getScalarSizeInBits() const {
267 return getFieldValue(PointerSizeFieldInfo);
268 return getFieldValue(ScalarSizeFieldInfo);
269 }
270
271 constexpr unsigned getAddressSpace() const {
273 "cannot get address space of non-pointer type");
274 return getFieldValue(PointerAddressSpaceFieldInfo);
275 }
276
277 /// Returns the vector's element type. Only valid for vector types.
278 constexpr LLT getElementType() const {
279 assert(isVector() && "cannot get element type of scalar/aggregate");
280 if (IsPointer)
282 else
283 return scalar(getScalarSizeInBits());
284 }
285
286 LLVM_ABI void print(raw_ostream &OS) const;
287
288#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
289 LLVM_DUMP_METHOD void dump() const;
290#endif
291
292 constexpr bool operator==(const LLT &RHS) const {
293 return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
294 IsScalar == RHS.IsScalar && RHS.RawData == RawData;
295 }
296
297 constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
298
299 friend struct DenseMapInfo<LLT>;
301
302private:
303 /// LLT is packed into 64 bits as follows:
304 /// isScalar : 1
305 /// isPointer : 1
306 /// isVector : 1
307 /// with 61 bits remaining for Kind-specific data, packed in bitfields
308 /// as described below. As there isn't a simple portable way to pack bits
309 /// into bitfields, here the different fields in the packed structure is
310 /// described in static const *Field variables. Each of these variables
311 /// is a 2-element array, with the first element describing the bitfield size
312 /// and the second element describing the bitfield offset.
313 ///
314 /// +--------+---------+--------+----------+----------------------+
315 /// |isScalar|isPointer|isVector| RawData |Notes |
316 /// +--------+---------+--------+----------+----------------------+
317 /// | 0 | 0 | 0 | 0 |Invalid |
318 /// +--------+---------+--------+----------+----------------------+
319 /// | 0 | 0 | 1 | 0 |Tombstone Key |
320 /// +--------+---------+--------+----------+----------------------+
321 /// | 0 | 1 | 0 | 0 |Empty Key |
322 /// +--------+---------+--------+----------+----------------------+
323 /// | 1 | 0 | 0 | 0 |Token |
324 /// +--------+---------+--------+----------+----------------------+
325 /// | 1 | 0 | 0 | non-zero |Scalar |
326 /// +--------+---------+--------+----------+----------------------+
327 /// | 0 | 1 | 0 | non-zero |Pointer |
328 /// +--------+---------+--------+----------+----------------------+
329 /// | 0 | 0 | 1 | non-zero |Vector of non-pointer |
330 /// +--------+---------+--------+----------+----------------------+
331 /// | 0 | 1 | 1 | non-zero |Vector of pointer |
332 /// +--------+---------+--------+----------+----------------------+
333 ///
334 /// Everything else is reserved.
335 typedef int BitFieldInfo[2];
336 ///
337 /// This is how the bitfields are packed per Kind:
338 /// * Invalid:
339 /// gets encoded as RawData == 0, as that is an invalid encoding, since for
340 /// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
341 /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
342 /// SizeInBits: 32;
343 static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
344 /// * Pointer (isPointer == 1 && isVector == 0):
345 /// SizeInBits: 16;
346 /// AddressSpace: 24;
347 static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 45};
348 static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 21};
349 /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
350 /// NumElements: 16;
351 /// SizeOfElement: 32;
352 /// Scalable: 1;
353 static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 5};
354 static const constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
355 /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
356 /// NumElements: 16;
357 /// SizeOfElement: 16;
358 /// AddressSpace: 24;
359 /// Scalable: 1;
360
361 uint64_t IsScalar : 1;
362 uint64_t IsPointer : 1;
363 uint64_t IsVector : 1;
364 uint64_t RawData : 61;
365
366 static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
367 const int FieldSizeInBits = FieldInfo[0];
368 return (((uint64_t)1) << FieldSizeInBits) - 1;
369 }
370 static constexpr uint64_t maskAndShift(uint64_t Val, uint64_t Mask,
371 uint8_t Shift) {
372 assert(Val <= Mask && "Value too large for field");
373 return (Val & Mask) << Shift;
374 }
375 static constexpr uint64_t maskAndShift(uint64_t Val,
376 const BitFieldInfo FieldInfo) {
377 return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
378 }
379
380 constexpr uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
381 return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
382 }
383
384 constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
385 ElementCount EC, uint64_t SizeInBits,
386 unsigned AddressSpace) {
387 assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
388 "Not enough bits in LLT to represent size");
389 this->IsPointer = IsPointer;
390 this->IsVector = IsVector;
391 this->IsScalar = IsScalar;
392 if (IsPointer) {
393 RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
394 maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
395 } else {
396 RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
397 }
398 if (IsVector) {
399 RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
400 maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
401 }
402 }
403
404public:
405 constexpr uint64_t getUniqueRAWLLTData() const {
406 return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
407 ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
408 }
409};
410
411inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
412 Ty.print(OS);
413 return OS;
414}
415
416template<> struct DenseMapInfo<LLT> {
417 static inline LLT getEmptyKey() {
418 LLT Invalid;
419 Invalid.IsPointer = true;
420 return Invalid;
421 }
422 static inline LLT getTombstoneKey() {
423 LLT Invalid;
424 Invalid.IsVector = true;
425 return Invalid;
426 }
427 static inline unsigned getHashValue(const LLT &Ty) {
428 uint64_t Val = Ty.getUniqueRAWLLTData();
430 }
431 static bool isEqual(const LLT &LHS, const LLT &RHS) {
432 return LHS == RHS;
433 }
434};
435
436}
437
438#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 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)
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:181
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:169
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
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...