]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/CodeGen/LowLevelType.h
Merge ^/head r311808 through r311811.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / CodeGen / LowLevelType.h
1 //== llvm/CodeGen/GlobalISel/LowLevelType.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_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
28 #define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
29
30 #include <cassert>
31 #include "llvm/ADT/DenseMapInfo.h"
32 #include "llvm/CodeGen/ValueTypes.h"
33
34 namespace llvm {
35
36 class DataLayout;
37 class LLVMContext;
38 class Type;
39 class raw_ostream;
40
41 class LLT {
42 public:
43   enum TypeKind : uint16_t {
44     Invalid,
45     Scalar,
46     Pointer,
47     Vector,
48   };
49
50   /// Get a low-level scalar or aggregate "bag of bits".
51   static LLT scalar(unsigned SizeInBits) {
52     assert(SizeInBits > 0 && "invalid scalar size");
53     return LLT{Scalar, 1, SizeInBits};
54   }
55
56   /// Get a low-level pointer in the given address space (defaulting to 0).
57   static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
58     return LLT{Pointer, AddressSpace, SizeInBits};
59   }
60
61   /// Get a low-level vector of some number of elements and element width.
62   /// \p NumElements must be at least 2.
63   static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
64     assert(NumElements > 1 && "invalid number of vector elements");
65     return LLT{Vector, NumElements, ScalarSizeInBits};
66   }
67
68   /// Get a low-level vector of some number of elements and element type.
69   static LLT vector(uint16_t NumElements, LLT ScalarTy) {
70     assert(NumElements > 1 && "invalid number of vector elements");
71     assert(ScalarTy.isScalar() && "invalid vector element type");
72     return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
73   }
74
75   explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
76     : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
77     assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
78            "invalid number of vector elements");
79   }
80
81   explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
82
83   /// Construct a low-level type based on an LLVM type.
84   explicit LLT(Type &Ty, const DataLayout &DL);
85
86   explicit LLT(MVT VT);
87
88   bool isValid() const { return Kind != Invalid; }
89
90   bool isScalar() const { return Kind == Scalar; }
91
92   bool isPointer() const { return Kind == Pointer; }
93
94   bool isVector() const { return Kind == Vector; }
95
96   /// Returns the number of elements in a vector LLT. Must only be called on
97   /// vector types.
98   uint16_t getNumElements() const {
99     assert(isVector() && "cannot get number of elements on scalar/aggregate");
100     return ElementsOrAddrSpace;
101   }
102
103   /// Returns the total size of the type. Must only be called on sized types.
104   unsigned getSizeInBits() const {
105     if (isPointer() || isScalar())
106       return SizeInBits;
107     return SizeInBits * ElementsOrAddrSpace;
108   }
109
110   unsigned getScalarSizeInBits() const {
111     return SizeInBits;
112   }
113
114   unsigned getAddressSpace() const {
115     assert(isPointer() && "cannot get address space of non-pointer type");
116     return ElementsOrAddrSpace;
117   }
118
119   /// Returns the vector's element type. Only valid for vector types.
120   LLT getElementType() const {
121     assert(isVector() && "cannot get element type of scalar/aggregate");
122     return scalar(SizeInBits);
123   }
124
125   /// Get a low-level type with half the size of the original, by halving the
126   /// size of the scalar type involved. For example `s32` will become `s16`,
127   /// `<2 x s32>` will become `<2 x s16>`.
128   LLT halfScalarSize() const {
129     assert(!isPointer() && getScalarSizeInBits() > 1 &&
130            getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
131     return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
132   }
133
134   /// Get a low-level type with twice the size of the original, by doubling the
135   /// size of the scalar type involved. For example `s32` will become `s64`,
136   /// `<2 x s32>` will become `<2 x s64>`.
137   LLT doubleScalarSize() const {
138     assert(!isPointer() && "cannot change size of this type");
139     return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
140   }
141
142   /// Get a low-level type with half the size of the original, by halving the
143   /// number of vector elements of the scalar type involved. The source must be
144   /// a vector type with an even number of elements. For example `<4 x s32>`
145   /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
146   LLT halfElements() const {
147     assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
148            "cannot half odd vector");
149     if (ElementsOrAddrSpace == 2)
150       return scalar(SizeInBits);
151
152     return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
153                SizeInBits};
154   }
155
156   /// Get a low-level type with twice the size of the original, by doubling the
157   /// number of vector elements of the scalar type involved. The source must be
158   /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
159   /// the number of elements in sN produces <2 x sN>.
160   LLT doubleElements() const {
161     assert(!isPointer() && "cannot double elements in pointer");
162     return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
163                SizeInBits};
164   }
165
166   void print(raw_ostream &OS) const;
167
168   bool operator==(const LLT &RHS) const {
169     return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
170            ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
171   }
172
173   bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
174
175   friend struct DenseMapInfo<LLT>;
176 private:
177   unsigned SizeInBits;
178   uint16_t ElementsOrAddrSpace;
179   TypeKind Kind;
180 };
181
182 inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
183   Ty.print(OS);
184   return OS;
185 }
186
187 template<> struct DenseMapInfo<LLT> {
188   static inline LLT getEmptyKey() {
189     return LLT{LLT::Invalid, 0, -1u};
190   }
191   static inline LLT getTombstoneKey() {
192     return LLT{LLT::Invalid, 0, -2u};
193   }
194   static inline unsigned getHashValue(const LLT &Ty) {
195     uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
196                    ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
197     return DenseMapInfo<uint64_t>::getHashValue(Val);
198   }
199   static bool isEqual(const LLT &LHS, const LLT &RHS) {
200     return LHS == RHS;
201   }
202 };
203
204 }
205
206 #endif