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