/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/CodeGen/LowLevelType.h
Line | Count | Source (jump to first uncovered line) |
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 | 7.54M | static LLT scalar(unsigned SizeInBits) { |
52 | 7.54M | assert(SizeInBits > 0 && "invalid scalar size"); |
53 | 7.54M | return LLT{Scalar, 1, SizeInBits}; |
54 | 7.54M | } |
55 | | |
56 | | /// Get a low-level pointer in the given address space (defaulting to 0). |
57 | 2.15M | static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) { |
58 | 2.15M | return LLT{Pointer, AddressSpace, SizeInBits}; |
59 | 2.15M | } |
60 | | |
61 | | /// Get a low-level vector of some number of elements and element width. |
62 | | /// \p NumElements must be at least 2. |
63 | 296k | static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) { |
64 | 296k | assert(NumElements > 1 && "invalid number of vector elements"); |
65 | 296k | return LLT{Vector, NumElements, ScalarSizeInBits}; |
66 | 296k | } |
67 | | |
68 | | /// Get a low-level vector of some number of elements and element type. |
69 | 0 | static LLT vector(uint16_t NumElements, LLT ScalarTy) { |
70 | 0 | assert(NumElements > 1 && "invalid number of vector elements"); |
71 | 0 | assert(ScalarTy.isScalar() && "invalid vector element type"); |
72 | 0 | return LLT{Vector, NumElements, ScalarTy.getSizeInBits()}; |
73 | 0 | } |
74 | | |
75 | | explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits) |
76 | 67.6M | : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) { |
77 | 67.6M | assert((Kind != Vector || ElementsOrAddrSpace > 1) && |
78 | 67.6M | "invalid number of vector elements"); |
79 | 67.6M | } |
80 | | |
81 | 21.7M | 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 | 7.80M | bool isValid() const { return Kind != Invalid; } |
89 | | |
90 | 31.4M | bool isScalar() const { return Kind == Scalar; } |
91 | | |
92 | 46.0M | bool isPointer() const { return Kind == Pointer; } |
93 | | |
94 | 17.8M | 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 | 601k | uint16_t getNumElements() const { |
99 | 601k | assert(isVector() && "cannot get number of elements on scalar/aggregate"); |
100 | 601k | return ElementsOrAddrSpace; |
101 | 601k | } |
102 | | |
103 | | /// Returns the total size of the type. Must only be called on sized types. |
104 | 45.8M | unsigned getSizeInBits() const { |
105 | 45.8M | if (isPointer() || 45.8M isScalar()31.2M ) |
106 | 45.8M | return SizeInBits; |
107 | 4.83k | return SizeInBits * ElementsOrAddrSpace; |
108 | 45.8M | } |
109 | | |
110 | 11.6k | unsigned getScalarSizeInBits() const { |
111 | 11.6k | return SizeInBits; |
112 | 11.6k | } |
113 | | |
114 | 1.49M | unsigned getAddressSpace() const { |
115 | 1.49M | assert(isPointer() && "cannot get address space of non-pointer type"); |
116 | 1.49M | return ElementsOrAddrSpace; |
117 | 1.49M | } |
118 | | |
119 | | /// Returns the vector's element type. Only valid for vector types. |
120 | 601k | LLT getElementType() const { |
121 | 601k | assert(isVector() && "cannot get element type of scalar/aggregate"); |
122 | 601k | return scalar(SizeInBits); |
123 | 601k | } |
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 | 10.2k | LLT halfScalarSize() const { |
129 | 10.2k | assert(!isPointer() && getScalarSizeInBits() > 1 && |
130 | 10.2k | getScalarSizeInBits() % 2 == 0 && "cannot half size of this type"); |
131 | 10.2k | return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2}; |
132 | 10.2k | } |
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 | 584k | LLT doubleScalarSize() const { |
138 | 584k | assert(!isPointer() && "cannot change size of this type"); |
139 | 584k | return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2}; |
140 | 584k | } |
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 | 25 | LLT halfElements() const { |
147 | 25 | assert(isVector() && ElementsOrAddrSpace % 2 == 0 && |
148 | 25 | "cannot half odd vector"); |
149 | 25 | if (ElementsOrAddrSpace == 2) |
150 | 5 | return scalar(SizeInBits); |
151 | 25 | |
152 | 20 | return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2), |
153 | 20 | SizeInBits}; |
154 | 25 | } |
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 | 27 | LLT doubleElements() const { |
161 | 27 | assert(!isPointer() && "cannot double elements in pointer"); |
162 | 27 | return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2), |
163 | 27 | SizeInBits}; |
164 | 27 | } |
165 | | |
166 | | void print(raw_ostream &OS) const; |
167 | | |
168 | 182M | bool operator==(const LLT &RHS) const { |
169 | 131M | return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits && |
170 | 111M | ElementsOrAddrSpace == RHS.ElementsOrAddrSpace; |
171 | 182M | } |
172 | | |
173 | 3.74M | 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 | 13.1k | inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) { |
183 | 13.1k | Ty.print(OS); |
184 | 13.1k | return OS; |
185 | 13.1k | } |
186 | | |
187 | | template<> struct DenseMapInfo<LLT> { |
188 | 31.3M | static inline LLT getEmptyKey() { |
189 | 31.3M | return LLT{LLT::Invalid, 0, -1u}; |
190 | 31.3M | } |
191 | 25.6M | static inline LLT getTombstoneKey() { |
192 | 25.6M | return LLT{LLT::Invalid, 0, -2u}; |
193 | 25.6M | } |
194 | 20.0M | static inline unsigned getHashValue(const LLT &Ty) { |
195 | 20.0M | uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) | |
196 | 20.0M | ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind; |
197 | 20.0M | return DenseMapInfo<uint64_t>::getHashValue(Val); |
198 | 20.0M | } |
199 | 175M | static bool isEqual(const LLT &LHS, const LLT &RHS) { |
200 | 175M | return LHS == RHS; |
201 | 175M | } |
202 | | }; |
203 | | |
204 | | } |
205 | | |
206 | | #endif |