Home | History | Annotate | Download | only in Support
      1 //== llvm/Support/LowLevelTypeImpl.h --------------------------- -*- C++ -*-==//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 /// Implement a low-level type suitable for MachineInstr level instruction
     11 /// selection.
     12 ///
     13 /// For a type attached to a MachineInstr, we only care about 2 details: total
     14 /// size and the number of vector lanes (if any). Accordingly, there are 4
     15 /// possible valid type-kinds:
     16 ///
     17 ///    * `sN` for scalars and aggregates
     18 ///    * `<N x sM>` for vectors, which must have at least 2 elements.
     19 ///    * `pN` for pointers
     20 ///
     21 /// Other information required for correct selection is expected to be carried
     22 /// by the opcode, or non-type flags. For example the distinction between G_ADD
     23 /// and G_FADD for int/float or fast-math flags.
     24 //
     25 //===----------------------------------------------------------------------===//
     26 
     27 #ifndef LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
     28 #define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
     29 
     30 #include <cassert>
     31 #include "llvm/ADT/DenseMapInfo.h"
     32 #include "llvm/CodeGen/MachineValueType.h"
     33 
     34 namespace llvm {
     35 
     36 class DataLayout;
     37 class Type;
     38 class raw_ostream;
     39 
     40 class LLT {
     41 public:
     42   enum TypeKind : uint16_t {
     43     Invalid,
     44     Scalar,
     45     Pointer,
     46     Vector,
     47   };
     48 
     49   /// Get a low-level scalar or aggregate "bag of bits".
     50   static LLT scalar(unsigned SizeInBits) {
     51     assert(SizeInBits > 0 && "invalid scalar size");
     52     return LLT{Scalar, 1, SizeInBits};
     53   }
     54 
     55   /// Get a low-level pointer in the given address space (defaulting to 0).
     56   static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
     57     return LLT{Pointer, AddressSpace, SizeInBits};
     58   }
     59 
     60   /// Get a low-level vector of some number of elements and element width.
     61   /// \p NumElements must be at least 2.
     62   static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
     63     assert(NumElements > 1 && "invalid number of vector elements");
     64     return LLT{Vector, NumElements, ScalarSizeInBits};
     65   }
     66 
     67   /// Get a low-level vector of some number of elements and element type.
     68   static LLT vector(uint16_t NumElements, LLT ScalarTy) {
     69     assert(NumElements > 1 && "invalid number of vector elements");
     70     assert(ScalarTy.isScalar() && "invalid vector element type");
     71     return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
     72   }
     73 
     74   explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
     75     : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
     76     assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
     77            "invalid number of vector elements");
     78   }
     79 
     80   explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
     81 
     82   explicit LLT(MVT VT);
     83 
     84   bool isValid() const { return Kind != Invalid; }
     85 
     86   bool isScalar() const { return Kind == Scalar; }
     87 
     88   bool isPointer() const { return Kind == Pointer; }
     89 
     90   bool isVector() const { return Kind == Vector; }
     91 
     92   /// Returns the number of elements in a vector LLT. Must only be called on
     93   /// vector types.
     94   uint16_t getNumElements() const {
     95     assert(isVector() && "cannot get number of elements on scalar/aggregate");
     96     return ElementsOrAddrSpace;
     97   }
     98 
     99   /// Returns the total size of the type. Must only be called on sized types.
    100   unsigned getSizeInBits() const {
    101     if (isPointer() || isScalar())
    102       return SizeInBits;
    103     return SizeInBits * ElementsOrAddrSpace;
    104   }
    105 
    106   unsigned getScalarSizeInBits() const {
    107     return SizeInBits;
    108   }
    109 
    110   unsigned getAddressSpace() const {
    111     assert(isPointer() && "cannot get address space of non-pointer type");
    112     return ElementsOrAddrSpace;
    113   }
    114 
    115   /// Returns the vector's element type. Only valid for vector types.
    116   LLT getElementType() const {
    117     assert(isVector() && "cannot get element type of scalar/aggregate");
    118     return scalar(SizeInBits);
    119   }
    120 
    121   /// Get a low-level type with half the size of the original, by halving the
    122   /// size of the scalar type involved. For example `s32` will become `s16`,
    123   /// `<2 x s32>` will become `<2 x s16>`.
    124   LLT halfScalarSize() const {
    125     assert(!isPointer() && getScalarSizeInBits() > 1 &&
    126            getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
    127     return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
    128   }
    129 
    130   /// Get a low-level type with twice the size of the original, by doubling the
    131   /// size of the scalar type involved. For example `s32` will become `s64`,
    132   /// `<2 x s32>` will become `<2 x s64>`.
    133   LLT doubleScalarSize() const {
    134     assert(!isPointer() && "cannot change size of this type");
    135     return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
    136   }
    137 
    138   /// Get a low-level type with half the size of the original, by halving the
    139   /// number of vector elements of the scalar type involved. The source must be
    140   /// a vector type with an even number of elements. For example `<4 x s32>`
    141   /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
    142   LLT halfElements() const {
    143     assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
    144            "cannot half odd vector");
    145     if (ElementsOrAddrSpace == 2)
    146       return scalar(SizeInBits);
    147 
    148     return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
    149                SizeInBits};
    150   }
    151 
    152   /// Get a low-level type with twice the size of the original, by doubling the
    153   /// number of vector elements of the scalar type involved. The source must be
    154   /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
    155   /// the number of elements in sN produces <2 x sN>.
    156   LLT doubleElements() const {
    157     assert(!isPointer() && "cannot double elements in pointer");
    158     return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
    159                SizeInBits};
    160   }
    161 
    162   void print(raw_ostream &OS) const;
    163 
    164   bool operator==(const LLT &RHS) const {
    165     return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
    166            ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
    167   }
    168 
    169   bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
    170 
    171   friend struct DenseMapInfo<LLT>;
    172 private:
    173   unsigned SizeInBits;
    174   uint16_t ElementsOrAddrSpace;
    175   TypeKind Kind;
    176 };
    177 
    178 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
    179   Ty.print(OS);
    180   return OS;
    181 }
    182 
    183 template<> struct DenseMapInfo<LLT> {
    184   static inline LLT getEmptyKey() {
    185     return LLT{LLT::Invalid, 0, -1u};
    186   }
    187   static inline LLT getTombstoneKey() {
    188     return LLT{LLT::Invalid, 0, -2u};
    189   }
    190   static inline unsigned getHashValue(const LLT &Ty) {
    191     uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
    192                    ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
    193     return DenseMapInfo<uint64_t>::getHashValue(Val);
    194   }
    195   static bool isEqual(const LLT &LHS, const LLT &RHS) {
    196     return LHS == RHS;
    197   }
    198 };
    199 
    200 }
    201 
    202 #endif // LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
    203