1 //== llvm/CodeGen/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 
29 #include "llvm/ADT/DenseMapInfo.h"
30 #include "llvm/CodeGen/MachineValueType.h"
31 #include "llvm/Support/Debug.h"
32 #include <cassert>
33 
34 namespace llvm {
35 
36 class Type;
37 class raw_ostream;
38 
39 class LLT {
40 public:
41   /// Get a low-level scalar or aggregate "bag of bits".
scalar(unsigned SizeInBits)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.
pointer(unsigned AddressSpace,unsigned SizeInBits)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.
vector(ElementCount EC,unsigned ScalarSizeInBits)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.
vector(ElementCount EC,LLT ScalarTy)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 16-bit IEEE half value.
75   /// TODO: Add IEEE semantics to type - This currently returns a simple `scalar(16)`.
float16()76   static constexpr LLT float16() {
77     return scalar(16);
78   }
79 
80   /// Get a 32-bit IEEE float value.
float32()81   static constexpr LLT float32() {
82     return scalar(32);
83   }
84 
85   /// Get a 64-bit IEEE double value.
float64()86   static constexpr LLT float64() {
87     return scalar(64);
88   }
89 
90   /// Get a low-level fixed-width vector of some number of elements and element
91   /// width.
fixed_vector(unsigned NumElements,unsigned ScalarSizeInBits)92   static constexpr LLT fixed_vector(unsigned NumElements,
93                                     unsigned ScalarSizeInBits) {
94     return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
95   }
96 
97   /// Get a low-level fixed-width vector of some number of elements and element
98   /// type.
fixed_vector(unsigned NumElements,LLT ScalarTy)99   static constexpr LLT fixed_vector(unsigned NumElements, LLT ScalarTy) {
100     return vector(ElementCount::getFixed(NumElements), ScalarTy);
101   }
102 
103   /// Get a low-level scalable vector of some number of elements and element
104   /// width.
scalable_vector(unsigned MinNumElements,unsigned ScalarSizeInBits)105   static constexpr LLT scalable_vector(unsigned MinNumElements,
106                                        unsigned ScalarSizeInBits) {
107     return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
108   }
109 
110   /// Get a low-level scalable vector of some number of elements and element
111   /// type.
scalable_vector(unsigned MinNumElements,LLT ScalarTy)112   static constexpr LLT scalable_vector(unsigned MinNumElements, LLT ScalarTy) {
113     return vector(ElementCount::getScalable(MinNumElements), ScalarTy);
114   }
115 
scalarOrVector(ElementCount EC,LLT ScalarTy)116   static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy) {
117     return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
118   }
119 
scalarOrVector(ElementCount EC,uint64_t ScalarSize)120   static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
121     assert(ScalarSize <= std::numeric_limits<unsigned>::max() &&
122            "Not enough bits in LLT to represent size");
123     return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
124   }
125 
LLT(bool isPointer,bool isVector,bool isScalar,ElementCount EC,uint64_t SizeInBits,unsigned AddressSpace)126   explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
127                          ElementCount EC, uint64_t SizeInBits,
128                          unsigned AddressSpace)
129       : LLT() {
130     init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
131   }
LLT()132   explicit constexpr LLT()
133       : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
134 
135   explicit LLT(MVT VT);
136 
isValid()137   constexpr bool isValid() const { return IsScalar || RawData != 0; }
138 
isScalar()139   constexpr bool isScalar() const { return IsScalar; }
140 
isPointer()141   constexpr bool isPointer() const {
142     return isValid() && IsPointer && !IsVector;
143   }
144 
isVector()145   constexpr bool isVector() const { return isValid() && IsVector; }
146 
147   /// Returns the number of elements in a vector LLT. Must only be called on
148   /// vector types.
getNumElements()149   constexpr uint16_t getNumElements() const {
150     if (isScalable())
151       llvm::reportInvalidSizeRequest(
152           "Possible incorrect use of LLT::getNumElements() for "
153           "scalable vector. Scalable flag may be dropped, use "
154           "LLT::getElementCount() instead");
155     return getElementCount().getKnownMinValue();
156   }
157 
158   /// Returns true if the LLT is a scalable vector. Must only be called on
159   /// vector types.
isScalable()160   constexpr bool isScalable() const {
161     assert(isVector() && "Expected a vector type");
162     return IsPointer ? getFieldValue(PointerVectorScalableFieldInfo)
163                      : getFieldValue(VectorScalableFieldInfo);
164   }
165 
166   /// Returns true if the LLT is a fixed vector. Returns false otherwise, even
167   /// if the LLT is not a vector type.
isFixedVector()168   constexpr bool isFixedVector() const { return isVector() && !isScalable(); }
169 
170   /// Returns true if the LLT is a scalable vector. Returns false otherwise,
171   /// even if the LLT is not a vector type.
isScalableVector()172   constexpr bool isScalableVector() const { return isVector() && isScalable(); }
173 
getElementCount()174   constexpr ElementCount getElementCount() const {
175     assert(IsVector && "cannot get number of elements on scalar/aggregate");
176     return ElementCount::get(IsPointer
177                                  ? getFieldValue(PointerVectorElementsFieldInfo)
178                                  : getFieldValue(VectorElementsFieldInfo),
179                              isScalable());
180   }
181 
182   /// Returns the total size of the type. Must only be called on sized types.
getSizeInBits()183   constexpr TypeSize getSizeInBits() const {
184     if (isPointer() || isScalar())
185       return TypeSize::getFixed(getScalarSizeInBits());
186     auto EC = getElementCount();
187     return TypeSize(getScalarSizeInBits() * EC.getKnownMinValue(),
188                     EC.isScalable());
189   }
190 
191   /// Returns the total size of the type in bytes, i.e. number of whole bytes
192   /// needed to represent the size in bits. Must only be called on sized types.
getSizeInBytes()193   constexpr TypeSize getSizeInBytes() const {
194     TypeSize BaseSize = getSizeInBits();
195     return {(BaseSize.getKnownMinValue() + 7) / 8, BaseSize.isScalable()};
196   }
197 
getScalarType()198   constexpr LLT getScalarType() const {
199     return isVector() ? getElementType() : *this;
200   }
201 
202   /// If this type is a vector, return a vector with the same number of elements
203   /// but the new element type. Otherwise, return the new element type.
changeElementType(LLT NewEltTy)204   constexpr LLT changeElementType(LLT NewEltTy) const {
205     return isVector() ? LLT::vector(getElementCount(), NewEltTy) : NewEltTy;
206   }
207 
208   /// If this type is a vector, return a vector with the same number of elements
209   /// but the new element size. Otherwise, return the new element type. Invalid
210   /// for pointer types. For pointer types, use changeElementType.
changeElementSize(unsigned NewEltSize)211   constexpr LLT changeElementSize(unsigned NewEltSize) const {
212     assert(!getScalarType().isPointer() &&
213            "invalid to directly change element size for pointers");
214     return isVector() ? LLT::vector(getElementCount(), NewEltSize)
215                       : LLT::scalar(NewEltSize);
216   }
217 
218   /// Return a vector or scalar with the same element type and the new element
219   /// count.
changeElementCount(ElementCount EC)220   constexpr LLT changeElementCount(ElementCount EC) const {
221     return LLT::scalarOrVector(EC, getScalarType());
222   }
223 
224   /// Return a type that is \p Factor times smaller. Reduces the number of
225   /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
226   /// not attempt to handle cases that aren't evenly divisible.
divide(int Factor)227   constexpr LLT divide(int Factor) const {
228     assert(Factor != 1);
229     assert((!isScalar() || getScalarSizeInBits() != 0) &&
230            "cannot divide scalar of size zero");
231     if (isVector()) {
232       assert(getElementCount().isKnownMultipleOf(Factor));
233       return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
234                             getElementType());
235     }
236 
237     assert(getScalarSizeInBits() % Factor == 0);
238     return scalar(getScalarSizeInBits() / Factor);
239   }
240 
241   /// Produce a vector type that is \p Factor times bigger, preserving the
242   /// element type. For a scalar or pointer, this will produce a new vector with
243   /// \p Factor elements.
multiplyElements(int Factor)244   constexpr LLT multiplyElements(int Factor) const {
245     if (isVector()) {
246       return scalarOrVector(getElementCount().multiplyCoefficientBy(Factor),
247                             getElementType());
248     }
249 
250     return fixed_vector(Factor, *this);
251   }
252 
isByteSized()253   constexpr bool isByteSized() const {
254     return getSizeInBits().isKnownMultipleOf(8);
255   }
256 
getScalarSizeInBits()257   constexpr unsigned getScalarSizeInBits() const {
258     if (IsScalar)
259       return getFieldValue(ScalarSizeFieldInfo);
260     if (IsVector) {
261       if (!IsPointer)
262         return getFieldValue(VectorSizeFieldInfo);
263       else
264         return getFieldValue(PointerVectorSizeFieldInfo);
265     }
266     assert(IsPointer && "unexpected LLT");
267     return getFieldValue(PointerSizeFieldInfo);
268   }
269 
getAddressSpace()270   constexpr unsigned getAddressSpace() const {
271     assert(RawData != 0 && "Invalid Type");
272     assert(IsPointer && "cannot get address space of non-pointer type");
273     if (!IsVector)
274       return getFieldValue(PointerAddressSpaceFieldInfo);
275     else
276       return getFieldValue(PointerVectorAddressSpaceFieldInfo);
277   }
278 
279   /// Returns the vector's element type. Only valid for vector types.
getElementType()280   constexpr LLT getElementType() const {
281     assert(isVector() && "cannot get element type of scalar/aggregate");
282     if (IsPointer)
283       return pointer(getAddressSpace(), getScalarSizeInBits());
284     else
285       return scalar(getScalarSizeInBits());
286   }
287 
288   void print(raw_ostream &OS) const;
289 
290 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
291   LLVM_DUMP_METHOD void dump() const;
292 #endif
293 
294   constexpr bool operator==(const LLT &RHS) const {
295     return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
296            IsScalar == RHS.IsScalar && RHS.RawData == RawData;
297   }
298 
299   constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
300 
301   friend struct DenseMapInfo<LLT>;
302   friend class GISelInstProfileBuilder;
303 
304 private:
305   /// LLT is packed into 64 bits as follows:
306   /// isScalar : 1
307   /// isPointer : 1
308   /// isVector  : 1
309   /// with 61 bits remaining for Kind-specific data, packed in bitfields
310   /// as described below. As there isn't a simple portable way to pack bits
311   /// into bitfields, here the different fields in the packed structure is
312   /// described in static const *Field variables. Each of these variables
313   /// is a 2-element array, with the first element describing the bitfield size
314   /// and the second element describing the bitfield offset.
315   typedef int BitFieldInfo[2];
316   ///
317   /// This is how the bitfields are packed per Kind:
318   /// * Invalid:
319   ///   gets encoded as RawData == 0, as that is an invalid encoding, since for
320   ///   valid encodings, SizeInBits/SizeOfElement must be larger than 0.
321   /// * Non-pointer scalar (isPointer == 0 && isVector == 0):
322   ///   SizeInBits: 32;
323   static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0};
324   /// * Pointer (isPointer == 1 && isVector == 0):
325   ///   SizeInBits: 16;
326   ///   AddressSpace: 24;
327   static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0};
328   static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
329       24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
330   static_assert((PointerAddressSpaceFieldInfo[0] +
331                  PointerAddressSpaceFieldInfo[1]) <= 61,
332                 "Insufficient bits to encode all data");
333   /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
334   ///   NumElements: 16;
335   ///   SizeOfElement: 32;
336   ///   Scalable: 1;
337   static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 0};
338   static const constexpr BitFieldInfo VectorSizeFieldInfo{
339       32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
340   static const constexpr BitFieldInfo VectorScalableFieldInfo{
341       1, VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]};
342   static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 61,
343                 "Insufficient bits to encode all data");
344   /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
345   ///   NumElements: 16;
346   ///   SizeOfElement: 16;
347   ///   AddressSpace: 24;
348   ///   Scalable: 1;
349   static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0};
350   static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{
351       16,
352       PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]};
353   static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{
354       24, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]};
355   static const constexpr BitFieldInfo PointerVectorScalableFieldInfo{
356       1, PointerVectorAddressSpaceFieldInfo[0] +
357              PointerVectorAddressSpaceFieldInfo[1]};
358   static_assert((PointerVectorAddressSpaceFieldInfo[0] +
359                  PointerVectorAddressSpaceFieldInfo[1]) <= 61,
360                 "Insufficient bits to encode all data");
361 
362   uint64_t IsScalar : 1;
363   uint64_t IsPointer : 1;
364   uint64_t IsVector : 1;
365   uint64_t RawData : 61;
366 
367   static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
368     const int FieldSizeInBits = FieldInfo[0];
369     return (((uint64_t)1) << FieldSizeInBits) - 1;
370   }
371   static constexpr uint64_t maskAndShift(uint64_t Val, uint64_t Mask,
372                                          uint8_t Shift) {
373     assert(Val <= Mask && "Value too large for field");
374     return (Val & Mask) << Shift;
375   }
376   static constexpr uint64_t maskAndShift(uint64_t Val,
377                                          const BitFieldInfo FieldInfo) {
378     return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
379   }
380 
381   constexpr uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
382     return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
383   }
384 
385   constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
386                       ElementCount EC, uint64_t SizeInBits,
387                       unsigned AddressSpace) {
388     assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
389            "Not enough bits in LLT to represent size");
390     this->IsPointer = IsPointer;
391     this->IsVector = IsVector;
392     this->IsScalar = IsScalar;
393     if (IsScalar)
394       RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
395     else if (IsVector) {
396       assert(EC.isVector() && "invalid number of vector elements");
397       if (!IsPointer)
398         RawData =
399             maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
400             maskAndShift(SizeInBits, VectorSizeFieldInfo) |
401             maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
402       else
403         RawData =
404             maskAndShift(EC.getKnownMinValue(),
405                          PointerVectorElementsFieldInfo) |
406             maskAndShift(SizeInBits, PointerVectorSizeFieldInfo) |
407             maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo) |
408             maskAndShift(EC.isScalable() ? 1 : 0,
409                          PointerVectorScalableFieldInfo);
410     } else if (IsPointer)
411       RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
412                 maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
413     else
414       llvm_unreachable("unexpected LLT configuration");
415   }
416 
417 public:
418   constexpr uint64_t getUniqueRAWLLTData() const {
419     return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
420            ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
421   }
422 };
423 
424 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
425   Ty.print(OS);
426   return OS;
427 }
428 
429 template<> struct DenseMapInfo<LLT> {
430   static inline LLT getEmptyKey() {
431     LLT Invalid;
432     Invalid.IsPointer = true;
433     return Invalid;
434   }
435   static inline LLT getTombstoneKey() {
436     LLT Invalid;
437     Invalid.IsVector = true;
438     return Invalid;
439   }
440   static inline unsigned getHashValue(const LLT &Ty) {
441     uint64_t Val = Ty.getUniqueRAWLLTData();
442     return DenseMapInfo<uint64_t>::getHashValue(Val);
443   }
444   static bool isEqual(const LLT &LHS, const LLT &RHS) {
445     return LHS == RHS;
446   }
447 };
448 
449 }
450 
451 #endif // LLVM_CODEGEN_LOWLEVELTYPE_H
452