LLVM  13.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 
29 #include "llvm/ADT/DenseMapInfo.h"
30 #include "llvm/Support/Debug.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.
50  static LLT pointer(unsigned 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  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  return LLT{ScalarTy.isPointer(), /*isVector=*/true, NumElements,
70  ScalarTy.getSizeInBits(),
71  ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
72  }
73 
74  static LLT scalarOrVector(uint16_t NumElements, LLT ScalarTy) {
75  return NumElements == 1 ? ScalarTy : LLT::vector(NumElements, ScalarTy);
76  }
77 
78  static LLT scalarOrVector(uint16_t NumElements, unsigned ScalarSize) {
79  return scalarOrVector(NumElements, LLT::scalar(ScalarSize));
80  }
81 
82  explicit LLT(bool isPointer, bool isVector, uint16_t NumElements,
83  unsigned SizeInBits, unsigned AddressSpace) {
84  init(isPointer, isVector, NumElements, SizeInBits, AddressSpace);
85  }
86  explicit LLT() : IsPointer(false), IsVector(false), RawData(0) {}
87 
88  explicit LLT(MVT VT);
89 
90  bool isValid() const { return RawData != 0; }
91 
92  bool isScalar() const { return isValid() && !IsPointer && !IsVector; }
93 
94  bool isPointer() const { return isValid() && IsPointer && !IsVector; }
95 
96  bool isVector() const { return isValid() && IsVector; }
97 
98  /// Returns the number of elements in a vector LLT. Must only be called on
99  /// vector types.
101  assert(IsVector && "cannot get number of elements on scalar/aggregate");
102  if (!IsPointer)
103  return getFieldValue(VectorElementsFieldInfo);
104  else
105  return getFieldValue(PointerVectorElementsFieldInfo);
106  }
107 
108  /// Returns the total size of the type. Must only be called on sized types.
109  unsigned getSizeInBits() const {
110  if (isPointer() || isScalar())
111  return getScalarSizeInBits();
112  return getScalarSizeInBits() * getNumElements();
113  }
114 
115  /// Returns the total size of the type in bytes, i.e. number of whole bytes
116  /// needed to represent the size in bits. Must only be called on sized types.
117  unsigned getSizeInBytes() const {
118  return (getSizeInBits() + 7) / 8;
119  }
120 
121  LLT getScalarType() const {
122  return isVector() ? getElementType() : *this;
123  }
124 
125  /// If this type is a vector, return a vector with the same number of elements
126  /// but the new element type. Otherwise, return the new element type.
127  LLT changeElementType(LLT NewEltTy) const {
128  return isVector() ? LLT::vector(getNumElements(), NewEltTy) : NewEltTy;
129  }
130 
131  /// If this type is a vector, return a vector with the same number of elements
132  /// but the new element size. Otherwise, return the new element type. Invalid
133  /// for pointer types. For pointer types, use changeElementType.
134  LLT changeElementSize(unsigned NewEltSize) const {
136  "invalid to directly change element size for pointers");
137  return isVector() ? LLT::vector(getNumElements(), NewEltSize)
138  : LLT::scalar(NewEltSize);
139  }
140 
141  /// Return a vector or scalar with the same element type and the new number of
142  /// elements.
143  LLT changeNumElements(unsigned NewNumElts) const {
144  return LLT::scalarOrVector(NewNumElts, getScalarType());
145  }
146 
147  /// Return a type that is \p Factor times smaller. Reduces the number of
148  /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
149  /// not attempt to handle cases that aren't evenly divisible.
150  LLT divide(int Factor) const {
151  assert(Factor != 1);
152  if (isVector()) {
153  assert(getNumElements() % Factor == 0);
154  return scalarOrVector(getNumElements() / Factor, getElementType());
155  }
156 
157  assert(getSizeInBits() % Factor == 0);
158  return scalar(getSizeInBits() / Factor);
159  }
160 
161  bool isByteSized() const { return (getSizeInBits() & 7) == 0; }
162 
163  unsigned getScalarSizeInBits() const {
164  assert(RawData != 0 && "Invalid Type");
165  if (!IsVector) {
166  if (!IsPointer)
167  return getFieldValue(ScalarSizeFieldInfo);
168  else
169  return getFieldValue(PointerSizeFieldInfo);
170  } else {
171  if (!IsPointer)
172  return getFieldValue(VectorSizeFieldInfo);
173  else
174  return getFieldValue(PointerVectorSizeFieldInfo);
175  }
176  }
177 
178  unsigned getAddressSpace() const {
179  assert(RawData != 0 && "Invalid Type");
180  assert(IsPointer && "cannot get address space of non-pointer type");
181  if (!IsVector)
182  return getFieldValue(PointerAddressSpaceFieldInfo);
183  else
184  return getFieldValue(PointerVectorAddressSpaceFieldInfo);
185  }
186 
187  /// Returns the vector's element type. Only valid for vector types.
188  LLT getElementType() const {
189  assert(isVector() && "cannot get element type of scalar/aggregate");
190  if (IsPointer)
192  else
193  return scalar(getScalarSizeInBits());
194  }
195 
196  void print(raw_ostream &OS) const;
197 
198 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
199  LLVM_DUMP_METHOD void dump() const {
200  print(dbgs());
201  dbgs() << '\n';
202  }
203 #endif
204 
205  bool operator==(const LLT &RHS) const {
206  return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
207  RHS.RawData == RawData;
208  }
209 
210  bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
211 
212  friend struct DenseMapInfo<LLT>;
214 
215 private:
216  /// LLT is packed into 64 bits as follows:
217  /// isPointer : 1
218  /// isVector : 1
219  /// with 62 bits remaining for Kind-specific data, packed in bitfields
220  /// as described below. As there isn't a simple portable way to pack bits
221  /// into bitfields, here the different fields in the packed structure is
222  /// described in static const *Field variables. Each of these variables
223  /// is a 2-element array, with the first element describing the bitfield size
224  /// and the second element describing the bitfield offset.
225  typedef int BitFieldInfo[2];
226  ///
227  /// This is how the bitfields are packed per Kind:
228  /// * Invalid:
229  /// gets encoded as RawData == 0, as that is an invalid encoding, since for
230  /// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
231  /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
232  /// SizeInBits: 32;
233  static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0};
234  /// * Pointer (isPointer == 1 && isVector == 0):
235  /// SizeInBits: 16;
236  /// AddressSpace: 24;
237  static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0};
238  static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
239  24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
240  /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
241  /// NumElements: 16;
242  /// SizeOfElement: 32;
243  static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 0};
244  static const constexpr BitFieldInfo VectorSizeFieldInfo{
245  32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
246  /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
247  /// NumElements: 16;
248  /// SizeOfElement: 16;
249  /// AddressSpace: 24;
250  static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0};
251  static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{
252  16,
253  PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]};
254  static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{
255  24, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]};
256 
257  uint64_t IsPointer : 1;
258  uint64_t IsVector : 1;
259  uint64_t RawData : 62;
260 
261  static uint64_t getMask(const BitFieldInfo FieldInfo) {
262  const int FieldSizeInBits = FieldInfo[0];
263  return (((uint64_t)1) << FieldSizeInBits) - 1;
264  }
265  static uint64_t maskAndShift(uint64_t Val, uint64_t Mask, uint8_t Shift) {
266  assert(Val <= Mask && "Value too large for field");
267  return (Val & Mask) << Shift;
268  }
269  static uint64_t maskAndShift(uint64_t Val, const BitFieldInfo FieldInfo) {
270  return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
271  }
272  uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
273  return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
274  }
275 
276  void init(bool IsPointer, bool IsVector, uint16_t NumElements,
277  unsigned SizeInBits, unsigned AddressSpace) {
278  this->IsPointer = IsPointer;
279  this->IsVector = IsVector;
280  if (!IsVector) {
281  if (!IsPointer)
282  RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
283  else
284  RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
285  maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
286  } else {
287  assert(NumElements > 1 && "invalid number of vector elements");
288  if (!IsPointer)
289  RawData = maskAndShift(NumElements, VectorElementsFieldInfo) |
290  maskAndShift(SizeInBits, VectorSizeFieldInfo);
291  else
292  RawData =
293  maskAndShift(NumElements, PointerVectorElementsFieldInfo) |
294  maskAndShift(SizeInBits, PointerVectorSizeFieldInfo) |
295  maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo);
296  }
297  }
298 
299  uint64_t getUniqueRAWLLTData() const {
300  return ((uint64_t)RawData) << 2 | ((uint64_t)IsPointer) << 1 |
301  ((uint64_t)IsVector);
302  }
303 };
304 
305 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
306  Ty.print(OS);
307  return OS;
308 }
309 
310 template<> struct DenseMapInfo<LLT> {
311  static inline LLT getEmptyKey() {
312  LLT Invalid;
313  Invalid.IsPointer = true;
314  return Invalid;
315  }
316  static inline LLT getTombstoneKey() {
317  LLT Invalid;
318  Invalid.IsVector = true;
319  return Invalid;
320  }
321  static inline unsigned getHashValue(const LLT &Ty) {
322  uint64_t Val = Ty.getUniqueRAWLLTData();
324  }
325  static bool isEqual(const LLT &LHS, const LLT &RHS) {
326  return LHS == RHS;
327  }
328 };
329 
330 }
331 
332 #endif // LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
LLVM_DUMP_METHOD
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:499
llvm
Definition: AllocatorList.h:23
llvm::LLT::operator==
bool operator==(const LLT &RHS) const
Definition: LowLevelTypeImpl.h:205
llvm::LLT::dump
LLVM_DUMP_METHOD void dump() const
Definition: LowLevelTypeImpl.h:199
llvm::LLT::getScalarSizeInBits
unsigned getScalarSizeInBits() const
Definition: LowLevelTypeImpl.h:163
llvm::LLT::LLT
LLT(bool isPointer, bool isVector, uint16_t NumElements, unsigned SizeInBits, unsigned AddressSpace)
Definition: LowLevelTypeImpl.h:82
llvm::DenseMapInfo< LLT >::getHashValue
static unsigned getHashValue(const LLT &Ty)
Definition: LowLevelTypeImpl.h:321
llvm::LLT::getScalarType
LLT getScalarType() const
Definition: LowLevelTypeImpl.h:121
Shift
bool Shift
Definition: README.txt:468
llvm::LLT::isValid
bool isValid() const
Definition: LowLevelTypeImpl.h:90
llvm::LLT::scalarOrVector
static LLT scalarOrVector(uint16_t NumElements, LLT ScalarTy)
Definition: LowLevelTypeImpl.h:74
llvm::LLT::print
void print(raw_ostream &OS) const
Definition: LowLevelType.cpp:36
llvm::LLT::isByteSized
bool isByteSized() const
Definition: LowLevelTypeImpl.h:161
llvm::BitmaskEnumDetail::Mask
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
MachineValueType.h
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::DenseMapInfo
Definition: APInt.h:35
llvm::LLT::LLT
LLT()
Definition: LowLevelTypeImpl.h:86
llvm::LLT::changeNumElements
LLT changeNumElements(unsigned NewNumElts) const
Return a vector or scalar with the same element type and the new number of elements.
Definition: LowLevelTypeImpl.h:143
llvm::LLT::getSizeInBits
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelTypeImpl.h:109
llvm::LLT::getSizeInBytes
unsigned getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
Definition: LowLevelTypeImpl.h:117
false
Definition: StackSlotColoring.cpp:142
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:230
llvm::LLT::vector
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
Definition: LowLevelTypeImpl.h:58
llvm::AddressSpace
AddressSpace
Definition: NVPTXBaseInfo.h:21
llvm::LLT::pointer
static LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelTypeImpl.h:50
llvm::LLT::getAddressSpace
unsigned getAddressSpace() const
Definition: LowLevelTypeImpl.h:178
llvm::LLT::divide
LLT divide(int Factor) const
Return a type that is Factor times smaller.
Definition: LowLevelTypeImpl.h:150
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:440
llvm::LLT::isVector
bool isVector() const
Definition: LowLevelTypeImpl.h:96
llvm::LLT::getNumElements
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
Definition: LowLevelTypeImpl.h:100
TemplateParamKind::Type
@ Type
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::LLT::isPointer
bool isPointer() const
Definition: LowLevelTypeImpl.h:94
llvm::DenseMapInfo< LLT >::getEmptyKey
static LLT getEmptyKey()
Definition: LowLevelTypeImpl.h:311
llvm::MVT
Machine Value Type.
Definition: MachineValueType.h:30
llvm::LLT::isScalar
bool isScalar() const
Definition: LowLevelTypeImpl.h:92
llvm::LLT::changeElementType
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.
Definition: LowLevelTypeImpl.h:127
uint16_t
llvm::GISelInstProfileBuilder
Definition: CSEInfo.h:167
llvm::LLT::operator!=
bool operator!=(const LLT &RHS) const
Definition: LowLevelTypeImpl.h:210
llvm::LLT::vector
static LLT vector(uint16_t NumElements, LLT ScalarTy)
Get a low-level vector of some number of elements and element type.
Definition: LowLevelTypeImpl.h:66
llvm::LLT::scalarOrVector
static LLT scalarOrVector(uint16_t NumElements, unsigned ScalarSize)
Definition: LowLevelTypeImpl.h:78
DenseMapInfo.h
llvm::DenseMapInfo< LLT >::isEqual
static bool isEqual(const LLT &LHS, const LLT &RHS)
Definition: LowLevelTypeImpl.h:325
llvm::LLT::getElementType
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
Definition: LowLevelTypeImpl.h:188
llvm::DenseMapInfo< LLT >::getTombstoneKey
static LLT getTombstoneKey()
Definition: LowLevelTypeImpl.h:316
llvm::LLT::scalar
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelTypeImpl.h:43
llvm::LLT::changeElementSize
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.
Definition: LowLevelTypeImpl.h:134
Debug.h
llvm::LLT
Definition: LowLevelTypeImpl.h:40