LLVM 17.0.0git
LowLevelTypeImpl.h
Go to the documentation of this file.
1//== llvm/Support/LowLevelTypeImpl.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_SUPPORT_LOWLEVELTYPEIMPL_H
27#define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
28
30#include "llvm/Support/Debug.h"
32#include <cassert>
33
34namespace llvm {
35
36class Type;
37class raw_ostream;
38
39class LLT {
40public:
41 /// Get a low-level scalar or aggregate "bag of bits".
42 static constexpr LLT scalar(unsigned SizeInBits) {
43 return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
44 ElementCount::getFixed(0), SizeInBits,
45 /*AddressSpace=*/0};
46 }
47
48 /// Get a low-level pointer in the given address space.
49 static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
50 assert(SizeInBits > 0 && "invalid pointer size");
51 return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
52 ElementCount::getFixed(0), SizeInBits, AddressSpace};
53 }
54
55 /// Get a low-level vector of some number of elements and element width.
56 static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
57 assert(!EC.isScalar() && "invalid number of vector elements");
58 return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
59 EC, ScalarSizeInBits, /*AddressSpace=*/0};
60 }
61
62 /// Get a low-level vector of some number of elements and element type.
63 static constexpr LLT vector(ElementCount EC, LLT ScalarTy) {
64 assert(!EC.isScalar() && "invalid number of vector elements");
65 assert(!ScalarTy.isVector() && "invalid vector element type");
66 return LLT{ScalarTy.isPointer(),
67 /*isVector=*/true,
68 /*isScalar=*/false,
69 EC,
70 ScalarTy.getSizeInBits().getFixedValue(),
71 ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
72 }
73
74 /// Get a low-level fixed-width vector of some number of elements and element
75 /// width.
76 static constexpr LLT fixed_vector(unsigned NumElements,
77 unsigned ScalarSizeInBits) {
78 return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
79 }
80
81 /// Get a low-level fixed-width vector of some number of elements and element
82 /// type.
83 static constexpr LLT fixed_vector(unsigned NumElements, LLT ScalarTy) {
84 return vector(ElementCount::getFixed(NumElements), ScalarTy);
85 }
86
87 /// Get a low-level scalable vector of some number of elements and element
88 /// width.
89 static constexpr LLT scalable_vector(unsigned MinNumElements,
90 unsigned ScalarSizeInBits) {
91 return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
92 }
93
94 /// Get a low-level scalable vector of some number of elements and element
95 /// type.
96 static constexpr LLT scalable_vector(unsigned MinNumElements, LLT ScalarTy) {
97 return vector(ElementCount::getScalable(MinNumElements), ScalarTy);
98 }
99
100 static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy) {
101 return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
102 }
103
104 static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
105 assert(ScalarSize <= std::numeric_limits<unsigned>::max() &&
106 "Not enough bits in LLT to represent size");
107 return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
108 }
109
110 explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
111 ElementCount EC, uint64_t SizeInBits,
112 unsigned AddressSpace)
113 : LLT() {
114 init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
115 }
116 explicit constexpr LLT()
117 : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
118
119 explicit LLT(MVT VT);
120
121 constexpr bool isValid() const { return IsScalar || RawData != 0; }
122
123 constexpr bool isScalar() const { return IsScalar; }
124
125 constexpr bool isPointer() const {
126 return isValid() && IsPointer && !IsVector;
127 }
128
129 constexpr bool isVector() const { return isValid() && IsVector; }
130
131 /// Returns the number of elements in a vector LLT. Must only be called on
132 /// vector types.
133 constexpr uint16_t getNumElements() const {
134 if (isScalable())
136 "Possible incorrect use of LLT::getNumElements() for "
137 "scalable vector. Scalable flag may be dropped, use "
138 "LLT::getElementCount() instead");
140 }
141
142 /// Returns true if the LLT is a scalable vector. Must only be called on
143 /// vector types.
144 constexpr bool isScalable() const {
145 assert(isVector() && "Expected a vector type");
146 return IsPointer ? getFieldValue(PointerVectorScalableFieldInfo)
147 : getFieldValue(VectorScalableFieldInfo);
148 }
149
150 constexpr ElementCount getElementCount() const {
151 assert(IsVector && "cannot get number of elements on scalar/aggregate");
152 return ElementCount::get(IsPointer
153 ? getFieldValue(PointerVectorElementsFieldInfo)
154 : getFieldValue(VectorElementsFieldInfo),
155 isScalable());
156 }
157
158 /// Returns the total size of the type. Must only be called on sized types.
159 constexpr TypeSize getSizeInBits() const {
160 if (isPointer() || isScalar())
162 auto EC = getElementCount();
163 return TypeSize(getScalarSizeInBits() * EC.getKnownMinValue(),
164 EC.isScalable());
165 }
166
167 /// Returns the total size of the type in bytes, i.e. number of whole bytes
168 /// needed to represent the size in bits. Must only be called on sized types.
169 constexpr TypeSize getSizeInBytes() const {
170 TypeSize BaseSize = getSizeInBits();
171 return {(BaseSize.getKnownMinValue() + 7) / 8, BaseSize.isScalable()};
172 }
173
174 constexpr LLT getScalarType() const {
175 return isVector() ? getElementType() : *this;
176 }
177
178 /// If this type is a vector, return a vector with the same number of elements
179 /// but the new element type. Otherwise, return the new element type.
180 constexpr LLT changeElementType(LLT NewEltTy) const {
181 return isVector() ? LLT::vector(getElementCount(), NewEltTy) : NewEltTy;
182 }
183
184 /// If this type is a vector, return a vector with the same number of elements
185 /// but the new element size. Otherwise, return the new element type. Invalid
186 /// for pointer types. For pointer types, use changeElementType.
187 constexpr LLT changeElementSize(unsigned NewEltSize) const {
189 "invalid to directly change element size for pointers");
190 return isVector() ? LLT::vector(getElementCount(), NewEltSize)
191 : LLT::scalar(NewEltSize);
192 }
193
194 /// Return a vector or scalar with the same element type and the new element
195 /// count.
196 constexpr LLT changeElementCount(ElementCount EC) const {
198 }
199
200 /// Return a type that is \p Factor times smaller. Reduces the number of
201 /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
202 /// not attempt to handle cases that aren't evenly divisible.
203 constexpr LLT divide(int Factor) const {
204 assert(Factor != 1);
205 assert((!isScalar() || getScalarSizeInBits() != 0) &&
206 "cannot divide scalar of size zero");
207 if (isVector()) {
208 assert(getElementCount().isKnownMultipleOf(Factor));
209 return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
211 }
212
213 assert(getScalarSizeInBits() % Factor == 0);
214 return scalar(getScalarSizeInBits() / Factor);
215 }
216
217 /// Produce a vector type that is \p Factor times bigger, preserving the
218 /// element type. For a scalar or pointer, this will produce a new vector with
219 /// \p Factor elements.
220 constexpr LLT multiplyElements(int Factor) const {
221 if (isVector()) {
222 return scalarOrVector(getElementCount().multiplyCoefficientBy(Factor),
224 }
225
226 return fixed_vector(Factor, *this);
227 }
228
229 constexpr bool isByteSized() const {
231 }
232
233 constexpr unsigned getScalarSizeInBits() const {
234 if (IsScalar)
235 return getFieldValue(ScalarSizeFieldInfo);
236 if (IsVector) {
237 if (!IsPointer)
238 return getFieldValue(VectorSizeFieldInfo);
239 else
240 return getFieldValue(PointerVectorSizeFieldInfo);
241 } else if (IsPointer)
242 return getFieldValue(PointerSizeFieldInfo);
243 else
244 llvm_unreachable("unexpected LLT");
245 }
246
247 constexpr unsigned getAddressSpace() const {
248 assert(RawData != 0 && "Invalid Type");
249 assert(IsPointer && "cannot get address space of non-pointer type");
250 if (!IsVector)
251 return getFieldValue(PointerAddressSpaceFieldInfo);
252 else
253 return getFieldValue(PointerVectorAddressSpaceFieldInfo);
254 }
255
256 /// Returns the vector's element type. Only valid for vector types.
257 constexpr LLT getElementType() const {
258 assert(isVector() && "cannot get element type of scalar/aggregate");
259 if (IsPointer)
261 else
262 return scalar(getScalarSizeInBits());
263 }
264
265 void print(raw_ostream &OS) const;
266
267#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
268 LLVM_DUMP_METHOD void dump() const {
269 print(dbgs());
270 dbgs() << '\n';
271 }
272#endif
273
274 constexpr bool operator==(const LLT &RHS) const {
275 return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
276 IsScalar == RHS.IsScalar && RHS.RawData == RawData;
277 }
278
279 constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
280
281 friend struct DenseMapInfo<LLT>;
283
284private:
285 /// LLT is packed into 64 bits as follows:
286 /// isScalar : 1
287 /// isPointer : 1
288 /// isVector : 1
289 /// with 61 bits remaining for Kind-specific data, packed in bitfields
290 /// as described below. As there isn't a simple portable way to pack bits
291 /// into bitfields, here the different fields in the packed structure is
292 /// described in static const *Field variables. Each of these variables
293 /// is a 2-element array, with the first element describing the bitfield size
294 /// and the second element describing the bitfield offset.
295 typedef int BitFieldInfo[2];
296 ///
297 /// This is how the bitfields are packed per Kind:
298 /// * Invalid:
299 /// gets encoded as RawData == 0, as that is an invalid encoding, since for
300 /// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
301 /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
302 /// SizeInBits: 32;
303 static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0};
304 /// * Pointer (isPointer == 1 && isVector == 0):
305 /// SizeInBits: 16;
306 /// AddressSpace: 24;
307 static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0};
308 static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
309 24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
310 static_assert((PointerAddressSpaceFieldInfo[0] +
311 PointerAddressSpaceFieldInfo[1]) <= 61,
312 "Insufficient bits to encode all data");
313 /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
314 /// NumElements: 16;
315 /// SizeOfElement: 32;
316 /// Scalable: 1;
317 static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 0};
318 static const constexpr BitFieldInfo VectorSizeFieldInfo{
319 32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
320 static const constexpr BitFieldInfo VectorScalableFieldInfo{
321 1, VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]};
322 static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 61,
323 "Insufficient bits to encode all data");
324 /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
325 /// NumElements: 16;
326 /// SizeOfElement: 16;
327 /// AddressSpace: 24;
328 /// Scalable: 1;
329 static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0};
330 static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{
331 16,
332 PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]};
333 static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{
334 24, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]};
335 static const constexpr BitFieldInfo PointerVectorScalableFieldInfo{
336 1, PointerVectorAddressSpaceFieldInfo[0] +
337 PointerVectorAddressSpaceFieldInfo[1]};
338 static_assert((PointerVectorAddressSpaceFieldInfo[0] +
339 PointerVectorAddressSpaceFieldInfo[1]) <= 61,
340 "Insufficient bits to encode all data");
341
342 uint64_t IsScalar : 1;
343 uint64_t IsPointer : 1;
344 uint64_t IsVector : 1;
345 uint64_t RawData : 61;
346
347 static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
348 const int FieldSizeInBits = FieldInfo[0];
349 return (((uint64_t)1) << FieldSizeInBits) - 1;
350 }
351 static constexpr uint64_t maskAndShift(uint64_t Val, uint64_t Mask,
352 uint8_t Shift) {
353 assert(Val <= Mask && "Value too large for field");
354 return (Val & Mask) << Shift;
355 }
356 static constexpr uint64_t maskAndShift(uint64_t Val,
357 const BitFieldInfo FieldInfo) {
358 return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
359 }
360
361 constexpr uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
362 return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
363 }
364
365 constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
366 ElementCount EC, uint64_t SizeInBits,
367 unsigned AddressSpace) {
368 assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
369 "Not enough bits in LLT to represent size");
370 this->IsPointer = IsPointer;
371 this->IsVector = IsVector;
372 this->IsScalar = IsScalar;
373 if (IsScalar)
374 RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
375 else if (IsVector) {
376 assert(EC.isVector() && "invalid number of vector elements");
377 if (!IsPointer)
378 RawData =
379 maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
380 maskAndShift(SizeInBits, VectorSizeFieldInfo) |
381 maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
382 else
383 RawData =
384 maskAndShift(EC.getKnownMinValue(),
385 PointerVectorElementsFieldInfo) |
386 maskAndShift(SizeInBits, PointerVectorSizeFieldInfo) |
387 maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo) |
388 maskAndShift(EC.isScalable() ? 1 : 0,
389 PointerVectorScalableFieldInfo);
390 } else if (IsPointer)
391 RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
392 maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
393 else
394 llvm_unreachable("unexpected LLT configuration");
395 }
396
397public:
398 constexpr uint64_t getUniqueRAWLLTData() const {
399 return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
400 ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
401 }
402};
403
405 Ty.print(OS);
406 return OS;
407}
408
409template<> struct DenseMapInfo<LLT> {
410 static inline LLT getEmptyKey() {
411 LLT Invalid;
412 Invalid.IsPointer = true;
413 return Invalid;
414 }
415 static inline LLT getTombstoneKey() {
416 LLT Invalid;
417 Invalid.IsVector = true;
418 return Invalid;
419 }
420 static inline unsigned getHashValue(const LLT &Ty) {
421 uint64_t Val = Ty.getUniqueRAWLLTData();
423 }
424 static bool isEqual(const LLT &LHS, const LLT &RHS) {
425 return LHS == RHS;
426 }
427};
428
429}
430
431#endif // LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
Replace within non kernel function use of LDS with pointer
RelocType Type
Definition: COFFYAML.cpp:390
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:492
This file defines DenseMapInfo traits for DenseMap.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
Value * RHS
Value * LHS
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition: TypeSize.h:294
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition: TypeSize.h:291
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition: TypeSize.h:297
void print(raw_ostream &OS) const
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.
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
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
LLVM_DUMP_METHOD void dump() 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.
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 LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
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 divide(int Factor) const
Return a type that is Factor times smaller.
Machine Value Type.
static constexpr TypeSize Fixed(ScalarTy ExactSize)
Definition: TypeSize.h:331
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:175
constexpr ScalarTy getFixedValue() const
Definition: TypeSize.h:182
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition: TypeSize.h:166
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition: TypeSize.h:163
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
AddressSpace
Definition: NVPTXBaseInfo.h:21
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void reportInvalidSizeRequest(const char *Msg)
Reports a diagnostic message to indicate an invalid size request has been done on a scalable vector.
Definition: TypeSize.cpp:38
@ Invalid
Denotes invalid value.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:292
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...
Definition: DenseMapInfo.h:51