1 //===- Attributes.h - MLIR Attribute Classes --------------------*- 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 
9 #ifndef MLIR_IR_ATTRIBUTES_H
10 #define MLIR_IR_ATTRIBUTES_H
11 
12 #include "mlir/IR/AttributeSupport.h"
13 #include "llvm/ADT/APFloat.h"
14 #include "llvm/ADT/Sequence.h"
15 #include "llvm/Support/PointerLikeTypeTraits.h"
16 #include <complex>
17 
18 namespace mlir {
19 class AffineMap;
20 class Dialect;
21 class FunctionType;
22 class Identifier;
23 class IntegerSet;
24 class Location;
25 class MLIRContext;
26 class ShapedType;
27 class Type;
28 
29 namespace detail {
30 
31 struct AffineMapAttributeStorage;
32 struct ArrayAttributeStorage;
33 struct DictionaryAttributeStorage;
34 struct IntegerAttributeStorage;
35 struct IntegerSetAttributeStorage;
36 struct FloatAttributeStorage;
37 struct OpaqueAttributeStorage;
38 struct StringAttributeStorage;
39 struct SymbolRefAttributeStorage;
40 struct TypeAttributeStorage;
41 
42 /// Elements Attributes.
43 struct DenseIntOrFPElementsAttributeStorage;
44 struct DenseStringElementsAttributeStorage;
45 struct OpaqueElementsAttributeStorage;
46 struct SparseElementsAttributeStorage;
47 } // namespace detail
48 
49 /// Attributes are known-constant values of operations and functions.
50 ///
51 /// Instances of the Attribute class are references to immutable, uniqued,
52 /// and immortal values owned by MLIRContext. As such, an Attribute is a thin
53 /// wrapper around an underlying storage pointer. Attributes are usually passed
54 /// by value.
55 class Attribute {
56 public:
57   /// Integer identifier for all the concrete attribute kinds.
58   enum Kind {
59   // Reserve attribute kinds for dialect specific extensions.
60 #define DEFINE_SYM_KIND_RANGE(Dialect)                                         \
61   FIRST_##Dialect##_ATTR, LAST_##Dialect##_ATTR = FIRST_##Dialect##_ATTR + 0xff,
62 #include "DialectSymbolRegistry.def"
63   };
64 
65   /// Utility class for implementing attributes.
66   template <typename ConcreteType, typename BaseType, typename StorageType,
67             template <typename T> class... Traits>
68   using AttrBase = detail::StorageUserBase<ConcreteType, BaseType, StorageType,
69                                            detail::AttributeUniquer, Traits...>;
70 
71   using ImplType = AttributeStorage;
72   using ValueType = void;
73 
Attribute()74   constexpr Attribute() : impl(nullptr) {}
Attribute(const ImplType * impl)75   /* implicit */ Attribute(const ImplType *impl)
76       : impl(const_cast<ImplType *>(impl)) {}
77 
78   Attribute(const Attribute &other) = default;
79   Attribute &operator=(const Attribute &other) = default;
80 
81   bool operator==(Attribute other) const { return impl == other.impl; }
82   bool operator!=(Attribute other) const { return !(*this == other); }
83   explicit operator bool() const { return impl; }
84 
85   bool operator!() const { return impl == nullptr; }
86 
87   template <typename U> bool isa() const;
88   template <typename First, typename Second, typename... Rest>
89   bool isa() const;
90   template <typename U> U dyn_cast() const;
91   template <typename U> U dyn_cast_or_null() const;
92   template <typename U> U cast() const;
93 
94   // Support dyn_cast'ing Attribute to itself.
classof(Attribute)95   static bool classof(Attribute) { return true; }
96 
97   /// Return the classification for this attribute.
getKind()98   unsigned getKind() const { return impl->getKind(); }
99 
100   /// Return the type of this attribute.
101   Type getType() const;
102 
103   /// Return the context this attribute belongs to.
104   MLIRContext *getContext() const;
105 
106   /// Get the dialect this attribute is registered to.
107   Dialect &getDialect() const;
108 
109   /// Print the attribute.
110   void print(raw_ostream &os) const;
111   void dump() const;
112 
113   /// Get an opaque pointer to the attribute.
getAsOpaquePointer()114   const void *getAsOpaquePointer() const { return impl; }
115   /// Construct an attribute from the opaque pointer representation.
getFromOpaquePointer(const void * ptr)116   static Attribute getFromOpaquePointer(const void *ptr) {
117     return Attribute(reinterpret_cast<const ImplType *>(ptr));
118   }
119 
120   friend ::llvm::hash_code hash_value(Attribute arg);
121 
122   /// Return the abstract descriptor for this attribute.
getAbstractAttribute()123   const AbstractAttribute &getAbstractAttribute() const {
124     return impl->getAbstractAttribute();
125   }
126 
127 protected:
128   ImplType *impl;
129 };
130 
131 inline raw_ostream &operator<<(raw_ostream &os, Attribute attr) {
132   attr.print(os);
133   return os;
134 }
135 
136 //===----------------------------------------------------------------------===//
137 // AttributeTraitBase
138 //===----------------------------------------------------------------------===//
139 
140 namespace AttributeTrait {
141 /// This class represents the base of an attribute trait.
142 template <typename ConcreteType, template <typename> class TraitType>
143 using TraitBase = detail::StorageUserTraitBase<ConcreteType, TraitType>;
144 } // namespace AttributeTrait
145 
146 //===----------------------------------------------------------------------===//
147 // AttributeInterface
148 //===----------------------------------------------------------------------===//
149 
150 /// This class represents the base of an attribute interface. See the definition
151 /// of `detail::Interface` for requirements on the `Traits` type.
152 template <typename ConcreteType, typename Traits>
153 class AttributeInterface
154     : public detail::Interface<ConcreteType, Attribute, Traits, Attribute,
155                                AttributeTrait::TraitBase> {
156 public:
157   using Base = AttributeInterface<ConcreteType, Traits>;
158   using InterfaceBase = detail::Interface<ConcreteType, Type, Traits, Type,
159                                           AttributeTrait::TraitBase>;
160   using InterfaceBase::InterfaceBase;
161 
162 private:
163   /// Returns the impl interface instance for the given type.
getInterfaceFor(Attribute attr)164   static typename InterfaceBase::Concept *getInterfaceFor(Attribute attr) {
165     return attr.getAbstractAttribute().getInterface<ConcreteType>();
166   }
167 
168   /// Allow access to 'getInterfaceFor'.
169   friend InterfaceBase;
170 };
171 
172 //===----------------------------------------------------------------------===//
173 // StandardAttributes
174 //===----------------------------------------------------------------------===//
175 
176 namespace StandardAttributes {
177 enum Kind {
178   AffineMap = Attribute::FIRST_STANDARD_ATTR,
179   Array,
180   Dictionary,
181   Float,
182   Integer,
183   IntegerSet,
184   Opaque,
185   String,
186   SymbolRef,
187   Type,
188   Unit,
189 
190   /// Elements Attributes.
191   DenseIntOrFPElements,
192   DenseStringElements,
193   OpaqueElements,
194   SparseElements,
195   FIRST_ELEMENTS_ATTR = DenseIntOrFPElements,
196   LAST_ELEMENTS_ATTR = SparseElements,
197 
198   /// Locations.
199   CallSiteLocation,
200   FileLineColLocation,
201   FusedLocation,
202   NameLocation,
203   OpaqueLocation,
204   UnknownLocation,
205 
206   // Represents a location as a 'void*' pointer to a front-end's opaque
207   // location information, which must live longer than the MLIR objects that
208   // refer to it.  OpaqueLocation's are never serialized.
209   //
210   // TODO: OpaqueLocation,
211 
212   // Represents a value inlined through a function call.
213   // TODO: InlinedLocation,
214 
215   FIRST_LOCATION_ATTR = CallSiteLocation,
216   LAST_LOCATION_ATTR = UnknownLocation,
217 };
218 } // namespace StandardAttributes
219 
220 //===----------------------------------------------------------------------===//
221 // AffineMapAttr
222 //===----------------------------------------------------------------------===//
223 
224 class AffineMapAttr
225     : public Attribute::AttrBase<AffineMapAttr, Attribute,
226                                  detail::AffineMapAttributeStorage> {
227 public:
228   using Base::Base;
229   using ValueType = AffineMap;
230 
231   static AffineMapAttr get(AffineMap value);
232 
233   AffineMap getValue() const;
234 
235   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)236   static bool kindof(unsigned kind) {
237     return kind == StandardAttributes::AffineMap;
238   }
239 };
240 
241 //===----------------------------------------------------------------------===//
242 // ArrayAttr
243 //===----------------------------------------------------------------------===//
244 
245 /// Array attributes are lists of other attributes.  They are not necessarily
246 /// type homogenous given that attributes don't, in general, carry types.
247 class ArrayAttr : public Attribute::AttrBase<ArrayAttr, Attribute,
248                                              detail::ArrayAttributeStorage> {
249 public:
250   using Base::Base;
251   using ValueType = ArrayRef<Attribute>;
252 
253   static ArrayAttr get(ArrayRef<Attribute> value, MLIRContext *context);
254 
255   ArrayRef<Attribute> getValue() const;
256   Attribute operator[](unsigned idx) const;
257 
258   /// Support range iteration.
259   using iterator = llvm::ArrayRef<Attribute>::iterator;
begin()260   iterator begin() const { return getValue().begin(); }
end()261   iterator end() const { return getValue().end(); }
size()262   size_t size() const { return getValue().size(); }
empty()263   bool empty() const { return size() == 0; }
264 
265   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)266   static bool kindof(unsigned kind) {
267     return kind == StandardAttributes::Array;
268   }
269 
270 private:
271   /// Class for underlying value iterator support.
272   template <typename AttrTy>
273   class attr_value_iterator final
274       : public llvm::mapped_iterator<ArrayAttr::iterator,
275                                      AttrTy (*)(Attribute)> {
276   public:
attr_value_iterator(ArrayAttr::iterator it)277     explicit attr_value_iterator(ArrayAttr::iterator it)
278         : llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>(
279               it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {}
280     AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); }
281   };
282 
283 public:
284   template <typename AttrTy>
getAsRange()285   llvm::iterator_range<attr_value_iterator<AttrTy>> getAsRange() {
286     return llvm::make_range(attr_value_iterator<AttrTy>(begin()),
287                             attr_value_iterator<AttrTy>(end()));
288   }
289   template <typename AttrTy, typename UnderlyingTy>
getAsRange()290   auto getAsRange() {
291     return llvm::map_range(getAsRange<AttrTy>(), [](AttrTy attr) {
292       return static_cast<UnderlyingTy>(attr.getValue());
293     });
294   }
295 };
296 
297 //===----------------------------------------------------------------------===//
298 // DictionaryAttr
299 //===----------------------------------------------------------------------===//
300 
301 /// NamedAttribute is used for dictionary attributes, it holds an identifier for
302 /// the name and a value for the attribute. The attribute pointer should always
303 /// be non-null.
304 using NamedAttribute = std::pair<Identifier, Attribute>;
305 
306 bool operator<(const NamedAttribute &lhs, const NamedAttribute &rhs);
307 bool operator<(const NamedAttribute &lhs, StringRef rhs);
308 
309 /// Dictionary attribute is an attribute that represents a sorted collection of
310 /// named attribute values. The elements are sorted by name, and each name must
311 /// be unique within the collection.
312 class DictionaryAttr
313     : public Attribute::AttrBase<DictionaryAttr, Attribute,
314                                  detail::DictionaryAttributeStorage> {
315 public:
316   using Base::Base;
317   using ValueType = ArrayRef<NamedAttribute>;
318 
319   /// Construct a dictionary attribute with the provided list of named
320   /// attributes. This method assumes that the provided list is unordered. If
321   /// the caller can guarantee that the attributes are ordered by name,
322   /// getWithSorted should be used instead.
323   static DictionaryAttr get(ArrayRef<NamedAttribute> value,
324                             MLIRContext *context);
325 
326   /// Construct a dictionary with an array of values that is known to already be
327   /// sorted by name and uniqued.
328   static DictionaryAttr getWithSorted(ArrayRef<NamedAttribute> value,
329                                       MLIRContext *context);
330 
331   ArrayRef<NamedAttribute> getValue() const;
332 
333   /// Return the specified attribute if present, null otherwise.
334   Attribute get(StringRef name) const;
335   Attribute get(Identifier name) const;
336 
337   /// Return the specified named attribute if present, None otherwise.
338   Optional<NamedAttribute> getNamed(StringRef name) const;
339   Optional<NamedAttribute> getNamed(Identifier name) const;
340 
341   /// Support range iteration.
342   using iterator = llvm::ArrayRef<NamedAttribute>::iterator;
343   iterator begin() const;
344   iterator end() const;
empty()345   bool empty() const { return size() == 0; }
346   size_t size() const;
347 
348   /// Sorts the NamedAttributes in the array ordered by name as expected by
349   /// getWithSorted and returns whether the values were sorted.
350   /// Requires: uniquely named attributes.
351   static bool sort(ArrayRef<NamedAttribute> values,
352                    SmallVectorImpl<NamedAttribute> &storage);
353 
354   /// Sorts the NamedAttributes in the array ordered by name as expected by
355   /// getWithSorted in place on an array and returns whether the values needed
356   /// to be sorted.
357   /// Requires: uniquely named attributes.
358   static bool sortInPlace(SmallVectorImpl<NamedAttribute> &array);
359 
360   /// Methods for supporting type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)361   static bool kindof(unsigned kind) {
362     return kind == StandardAttributes::Dictionary;
363   }
364 
365 private:
366   /// Return empty dictionary.
367   static DictionaryAttr getEmpty(MLIRContext *context);
368 };
369 
370 //===----------------------------------------------------------------------===//
371 // FloatAttr
372 //===----------------------------------------------------------------------===//
373 
374 class FloatAttr : public Attribute::AttrBase<FloatAttr, Attribute,
375                                              detail::FloatAttributeStorage> {
376 public:
377   using Base::Base;
378   using ValueType = APFloat;
379 
380   /// Return a float attribute for the specified value in the specified type.
381   /// These methods should only be used for simple constant values, e.g 1.0/2.0,
382   /// that are known-valid both as host double and the 'type' format.
383   static FloatAttr get(Type type, double value);
384   static FloatAttr getChecked(Type type, double value, Location loc);
385 
386   /// Return a float attribute for the specified value in the specified type.
387   static FloatAttr get(Type type, const APFloat &value);
388   static FloatAttr getChecked(Type type, const APFloat &value, Location loc);
389 
390   APFloat getValue() const;
391 
392   /// This function is used to convert the value to a double, even if it loses
393   /// precision.
394   double getValueAsDouble() const;
395   static double getValueAsDouble(APFloat val);
396 
397   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)398   static bool kindof(unsigned kind) {
399     return kind == StandardAttributes::Float;
400   }
401 
402   /// Verify the construction invariants for a double value.
403   static LogicalResult verifyConstructionInvariants(Location loc, Type type,
404                                                     double value);
405   static LogicalResult verifyConstructionInvariants(Location loc, Type type,
406                                                     const APFloat &value);
407 };
408 
409 //===----------------------------------------------------------------------===//
410 // IntegerAttr
411 //===----------------------------------------------------------------------===//
412 
413 class IntegerAttr
414     : public Attribute::AttrBase<IntegerAttr, Attribute,
415                                  detail::IntegerAttributeStorage> {
416 public:
417   using Base::Base;
418   using ValueType = APInt;
419 
420   static IntegerAttr get(Type type, int64_t value);
421   static IntegerAttr get(Type type, const APInt &value);
422 
423   APInt getValue() const;
424   /// Return the integer value as a 64-bit int. The attribute must be a signless
425   /// integer.
426   // TODO: Change callers to use getValue instead.
427   int64_t getInt() const;
428   /// Return the integer value as a signed 64-bit int. The attribute must be
429   /// a signed integer.
430   int64_t getSInt() const;
431   /// Return the integer value as a unsigned 64-bit int. The attribute must be
432   /// an unsigned integer.
433   uint64_t getUInt() const;
434 
435   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)436   static bool kindof(unsigned kind) {
437     return kind == StandardAttributes::Integer;
438   }
439 
440   static LogicalResult verifyConstructionInvariants(Location loc, Type type,
441                                                     int64_t value);
442   static LogicalResult verifyConstructionInvariants(Location loc, Type type,
443                                                     const APInt &value);
444 };
445 
446 //===----------------------------------------------------------------------===//
447 // BoolAttr
448 
449 /// Special case of IntegerAttr to represent boolean integers, i.e., signless i1
450 /// integers.
451 class BoolAttr : public Attribute {
452 public:
453   using Attribute::Attribute;
454   using ValueType = bool;
455 
456   static BoolAttr get(bool value, MLIRContext *context);
457 
458   /// Enable conversion to IntegerAttr. This uses conversion vs. inheritance to
459   /// avoid bringing in all of IntegerAttrs methods.
IntegerAttr()460   operator IntegerAttr() const { return IntegerAttr(impl); }
461 
462   /// Return the boolean value of this attribute.
463   bool getValue() const;
464 
465   /// Methods for support type inquiry through isa, cast, and dyn_cast.
466   static bool classof(Attribute attr);
467 };
468 
469 //===----------------------------------------------------------------------===//
470 // IntegerSetAttr
471 //===----------------------------------------------------------------------===//
472 
473 class IntegerSetAttr
474     : public Attribute::AttrBase<IntegerSetAttr, Attribute,
475                                  detail::IntegerSetAttributeStorage> {
476 public:
477   using Base::Base;
478   using ValueType = IntegerSet;
479 
480   static IntegerSetAttr get(IntegerSet value);
481 
482   IntegerSet getValue() const;
483 
484   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)485   static bool kindof(unsigned kind) {
486     return kind == StandardAttributes::IntegerSet;
487   }
488 };
489 
490 //===----------------------------------------------------------------------===//
491 // OpaqueAttr
492 //===----------------------------------------------------------------------===//
493 
494 /// Opaque attributes represent attributes of non-registered dialects. These are
495 /// attribute represented in their raw string form, and can only usefully be
496 /// tested for attribute equality.
497 class OpaqueAttr : public Attribute::AttrBase<OpaqueAttr, Attribute,
498                                               detail::OpaqueAttributeStorage> {
499 public:
500   using Base::Base;
501 
502   /// Get or create a new OpaqueAttr with the provided dialect and string data.
503   static OpaqueAttr get(Identifier dialect, StringRef attrData, Type type,
504                         MLIRContext *context);
505 
506   /// Get or create a new OpaqueAttr with the provided dialect and string data.
507   /// If the given identifier is not a valid namespace for a dialect, then a
508   /// null attribute is returned.
509   static OpaqueAttr getChecked(Identifier dialect, StringRef attrData,
510                                Type type, Location location);
511 
512   /// Returns the dialect namespace of the opaque attribute.
513   Identifier getDialectNamespace() const;
514 
515   /// Returns the raw attribute data of the opaque attribute.
516   StringRef getAttrData() const;
517 
518   /// Verify the construction of an opaque attribute.
519   static LogicalResult verifyConstructionInvariants(Location loc,
520                                                     Identifier dialect,
521                                                     StringRef attrData,
522                                                     Type type);
523 
kindof(unsigned kind)524   static bool kindof(unsigned kind) {
525     return kind == StandardAttributes::Opaque;
526   }
527 };
528 
529 //===----------------------------------------------------------------------===//
530 // StringAttr
531 //===----------------------------------------------------------------------===//
532 
533 class StringAttr : public Attribute::AttrBase<StringAttr, Attribute,
534                                               detail::StringAttributeStorage> {
535 public:
536   using Base::Base;
537   using ValueType = StringRef;
538 
539   /// Get an instance of a StringAttr with the given string.
540   static StringAttr get(StringRef bytes, MLIRContext *context);
541 
542   /// Get an instance of a StringAttr with the given string and Type.
543   static StringAttr get(StringRef bytes, Type type);
544 
545   StringRef getValue() const;
546 
547   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)548   static bool kindof(unsigned kind) {
549     return kind == StandardAttributes::String;
550   }
551 };
552 
553 //===----------------------------------------------------------------------===//
554 // SymbolRefAttr
555 //===----------------------------------------------------------------------===//
556 
557 class FlatSymbolRefAttr;
558 
559 /// A symbol reference attribute represents a symbolic reference to another
560 /// operation.
561 class SymbolRefAttr
562     : public Attribute::AttrBase<SymbolRefAttr, Attribute,
563                                  detail::SymbolRefAttributeStorage> {
564 public:
565   using Base::Base;
566 
567   /// Construct a symbol reference for the given value name.
568   static FlatSymbolRefAttr get(StringRef value, MLIRContext *ctx);
569 
570   /// Construct a symbol reference for the given value name, and a set of nested
571   /// references that are further resolve to a nested symbol.
572   static SymbolRefAttr get(StringRef value,
573                            ArrayRef<FlatSymbolRefAttr> references,
574                            MLIRContext *ctx);
575 
576   /// Returns the name of the top level symbol reference, i.e. the root of the
577   /// reference path.
578   StringRef getRootReference() const;
579 
580   /// Returns the name of the fully resolved symbol, i.e. the leaf of the
581   /// reference path.
582   StringRef getLeafReference() const;
583 
584   /// Returns the set of nested references representing the path to the symbol
585   /// nested under the root reference.
586   ArrayRef<FlatSymbolRefAttr> getNestedReferences() const;
587 
588   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)589   static bool kindof(unsigned kind) {
590     return kind == StandardAttributes::SymbolRef;
591   }
592 };
593 
594 /// A symbol reference with a reference path containing a single element. This
595 /// is used to refer to an operation within the current symbol table.
596 class FlatSymbolRefAttr : public SymbolRefAttr {
597 public:
598   using SymbolRefAttr::SymbolRefAttr;
599   using ValueType = StringRef;
600 
601   /// Construct a symbol reference for the given value name.
get(StringRef value,MLIRContext * ctx)602   static FlatSymbolRefAttr get(StringRef value, MLIRContext *ctx) {
603     return SymbolRefAttr::get(value, ctx);
604   }
605 
606   /// Returns the name of the held symbol reference.
getValue()607   StringRef getValue() const { return getRootReference(); }
608 
609   /// Methods for support type inquiry through isa, cast, and dyn_cast.
classof(Attribute attr)610   static bool classof(Attribute attr) {
611     SymbolRefAttr refAttr = attr.dyn_cast<SymbolRefAttr>();
612     return refAttr && refAttr.getNestedReferences().empty();
613   }
614 
615 private:
616   using SymbolRefAttr::get;
617   using SymbolRefAttr::getNestedReferences;
618 };
619 
620 //===----------------------------------------------------------------------===//
621 // Type
622 //===----------------------------------------------------------------------===//
623 
624 class TypeAttr : public Attribute::AttrBase<TypeAttr, Attribute,
625                                             detail::TypeAttributeStorage> {
626 public:
627   using Base::Base;
628   using ValueType = Type;
629 
630   static TypeAttr get(Type value);
631 
632   Type getValue() const;
633 
634   /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)635   static bool kindof(unsigned kind) { return kind == StandardAttributes::Type; }
636 };
637 
638 //===----------------------------------------------------------------------===//
639 // UnitAttr
640 //===----------------------------------------------------------------------===//
641 
642 /// Unit attributes are attributes that hold no specific value and are given
643 /// meaning by their existence.
644 class UnitAttr
645     : public Attribute::AttrBase<UnitAttr, Attribute, AttributeStorage> {
646 public:
647   using Base::Base;
648 
649   static UnitAttr get(MLIRContext *context);
650 
kindof(unsigned kind)651   static bool kindof(unsigned kind) { return kind == StandardAttributes::Unit; }
652 };
653 
654 //===----------------------------------------------------------------------===//
655 // Elements Attributes
656 //===----------------------------------------------------------------------===//
657 
658 namespace detail {
659 template <typename T> class ElementsAttrIterator;
660 template <typename T> class ElementsAttrRange;
661 } // namespace detail
662 
663 /// A base attribute that represents a reference to a static shaped tensor or
664 /// vector constant.
665 class ElementsAttr : public Attribute {
666 public:
667   using Attribute::Attribute;
668   template <typename T> using iterator = detail::ElementsAttrIterator<T>;
669   template <typename T> using iterator_range = detail::ElementsAttrRange<T>;
670 
671   /// Return the type of this ElementsAttr, guaranteed to be a vector or tensor
672   /// with static shape.
673   ShapedType getType() const;
674 
675   /// Return the value at the given index. The index is expected to refer to a
676   /// valid element.
677   Attribute getValue(ArrayRef<uint64_t> index) const;
678 
679   /// Return the value of type 'T' at the given index, where 'T' corresponds to
680   /// an Attribute type.
getValue(ArrayRef<uint64_t> index)681   template <typename T> T getValue(ArrayRef<uint64_t> index) const {
682     return getValue(index).template cast<T>();
683   }
684 
685   /// Return the elements of this attribute as a value of type 'T'. Note:
686   /// Aborts if the subclass is OpaqueElementsAttrs, these attrs do not support
687   /// iteration.
688   template <typename T> iterator_range<T> getValues() const;
689 
690   /// Return if the given 'index' refers to a valid element in this attribute.
691   bool isValidIndex(ArrayRef<uint64_t> index) const;
692 
693   /// Returns the number of elements held by this attribute.
694   int64_t getNumElements() const;
695 
696   /// Generates a new ElementsAttr by mapping each int value to a new
697   /// underlying APInt. The new values can represent either an integer or float.
698   /// This ElementsAttr should contain integers.
699   ElementsAttr mapValues(Type newElementType,
700                          function_ref<APInt(const APInt &)> mapping) const;
701 
702   /// Generates a new ElementsAttr by mapping each float value to a new
703   /// underlying APInt. The new values can represent either an integer or float.
704   /// This ElementsAttr should contain floats.
705   ElementsAttr mapValues(Type newElementType,
706                          function_ref<APInt(const APFloat &)> mapping) const;
707 
708   /// Method for support type inquiry through isa, cast and dyn_cast.
classof(Attribute attr)709   static bool classof(Attribute attr) {
710     return attr.getKind() >= StandardAttributes::FIRST_ELEMENTS_ATTR &&
711            attr.getKind() <= StandardAttributes::LAST_ELEMENTS_ATTR;
712   }
713 
714 protected:
715   /// Returns the 1 dimensional flattened row-major index from the given
716   /// multi-dimensional index.
717   uint64_t getFlattenedIndex(ArrayRef<uint64_t> index) const;
718 };
719 
720 namespace detail {
721 /// DenseElementsAttr data is aligned to uint64_t, so this traits class is
722 /// necessary to interop with PointerIntPair.
723 class DenseElementDataPointerTypeTraits {
724 public:
getAsVoidPointer(const char * ptr)725   static inline const void *getAsVoidPointer(const char *ptr) { return ptr; }
getFromVoidPointer(const void * ptr)726   static inline const char *getFromVoidPointer(const void *ptr) {
727     return static_cast<const char *>(ptr);
728   }
729 
730   // Note: We could steal more bits if the need arises.
731   static constexpr int NumLowBitsAvailable = 1;
732 };
733 
734 /// Pair of raw pointer and a boolean flag of whether the pointer holds a splat,
735 using DenseIterPtrAndSplat =
736     llvm::PointerIntPair<const char *, 1, bool,
737                          DenseElementDataPointerTypeTraits>;
738 
739 /// Impl iterator for indexed DenseElementAttr iterators that records a data
740 /// pointer and data index that is adjusted for the case of a splat attribute.
741 template <typename ConcreteT, typename T, typename PointerT = T *,
742           typename ReferenceT = T &>
743 class DenseElementIndexedIteratorImpl
744     : public llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
745                                              PointerT, ReferenceT> {
746 protected:
DenseElementIndexedIteratorImpl(const char * data,bool isSplat,size_t dataIndex)747   DenseElementIndexedIteratorImpl(const char *data, bool isSplat,
748                                   size_t dataIndex)
749       : llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
750                                         PointerT, ReferenceT>({data, isSplat},
751                                                               dataIndex) {}
752 
753   /// Return the current index for this iterator, adjusted for the case of a
754   /// splat.
getDataIndex()755   ptrdiff_t getDataIndex() const {
756     bool isSplat = this->base.getInt();
757     return isSplat ? 0 : this->index;
758   }
759 
760   /// Return the data base pointer.
getData()761   const char *getData() const { return this->base.getPointer(); }
762 };
763 
764 /// Type trait detector that checks if a given type T is a complex type.
765 template <typename T> struct is_complex_t : public std::false_type {};
766 template <typename T>
767 struct is_complex_t<std::complex<T>> : public std::true_type {};
768 } // namespace detail
769 
770 /// An attribute that represents a reference to a dense vector or tensor object.
771 ///
772 class DenseElementsAttr : public ElementsAttr {
773 public:
774   using ElementsAttr::ElementsAttr;
775 
776   /// Method for support type inquiry through isa, cast and dyn_cast.
777   static bool classof(Attribute attr) {
778     return attr.getKind() == StandardAttributes::DenseIntOrFPElements ||
779            attr.getKind() == StandardAttributes::DenseStringElements;
780   }
781 
782   /// Constructs a dense elements attribute from an array of element values.
783   /// Each element attribute value is expected to be an element of 'type'.
784   /// 'type' must be a vector or tensor with static shape. If the element of
785   /// `type` is non-integer/index/float it is assumed to be a string type.
786   static DenseElementsAttr get(ShapedType type, ArrayRef<Attribute> values);
787 
788   /// Constructs a dense integer elements attribute from an array of integer
789   /// or floating-point values. Each value is expected to be the same bitwidth
790   /// of the element type of 'type'. 'type' must be a vector or tensor with
791   /// static shape.
792   template <typename T, typename = typename std::enable_if<
793                             std::numeric_limits<T>::is_integer ||
794                             llvm::is_one_of<T, float, double>::value>::type>
795   static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) {
796     const char *data = reinterpret_cast<const char *>(values.data());
797     return getRawIntOrFloat(
798         type, ArrayRef<char>(data, values.size() * sizeof(T)), sizeof(T),
799         std::numeric_limits<T>::is_integer, std::numeric_limits<T>::is_signed);
800   }
801 
802   /// Constructs a dense integer elements attribute from a single element.
803   template <typename T, typename = typename std::enable_if<
804                             std::numeric_limits<T>::is_integer ||
805                             llvm::is_one_of<T, float, double>::value ||
806                             detail::is_complex_t<T>::value>::type>
807   static DenseElementsAttr get(const ShapedType &type, T value) {
808     return get(type, llvm::makeArrayRef(value));
809   }
810 
811   /// Constructs a dense complex elements attribute from an array of complex
812   /// values. Each value is expected to be the same bitwidth of the element type
813   /// of 'type'. 'type' must be a vector or tensor with static shape.
814   template <typename T, typename ElementT = typename T::value_type,
815             typename = typename std::enable_if<
816                 detail::is_complex_t<T>::value &&
817                 (std::numeric_limits<ElementT>::is_integer ||
818                  llvm::is_one_of<ElementT, float, double>::value)>::type>
819   static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) {
820     const char *data = reinterpret_cast<const char *>(values.data());
821     return getRawComplex(type, ArrayRef<char>(data, values.size() * sizeof(T)),
822                          sizeof(T), std::numeric_limits<ElementT>::is_integer,
823                          std::numeric_limits<ElementT>::is_signed);
824   }
825 
826   /// Overload of the above 'get' method that is specialized for boolean values.
827   static DenseElementsAttr get(ShapedType type, ArrayRef<bool> values);
828 
829   /// Overload of the above 'get' method that is specialized for StringRef
830   /// values.
831   static DenseElementsAttr get(ShapedType type, ArrayRef<StringRef> values);
832 
833   /// Constructs a dense integer elements attribute from an array of APInt
834   /// values. Each APInt value is expected to have the same bitwidth as the
835   /// element type of 'type'. 'type' must be a vector or tensor with static
836   /// shape.
837   static DenseElementsAttr get(ShapedType type, ArrayRef<APInt> values);
838 
839   /// Constructs a dense complex elements attribute from an array of APInt
840   /// values. Each APInt value is expected to have the same bitwidth as the
841   /// element type of 'type'. 'type' must be a vector or tensor with static
842   /// shape.
843   static DenseElementsAttr get(ShapedType type,
844                                ArrayRef<std::complex<APInt>> values);
845 
846   /// Constructs a dense float elements attribute from an array of APFloat
847   /// values. Each APFloat value is expected to have the same bitwidth as the
848   /// element type of 'type'. 'type' must be a vector or tensor with static
849   /// shape.
850   static DenseElementsAttr get(ShapedType type, ArrayRef<APFloat> values);
851 
852   /// Constructs a dense complex elements attribute from an array of APFloat
853   /// values. Each APFloat value is expected to have the same bitwidth as the
854   /// element type of 'type'. 'type' must be a vector or tensor with static
855   /// shape.
856   static DenseElementsAttr get(ShapedType type,
857                                ArrayRef<std::complex<APFloat>> values);
858 
859   /// Construct a dense elements attribute for an initializer_list of values.
860   /// Each value is expected to be the same bitwidth of the element type of
861   /// 'type'. 'type' must be a vector or tensor with static shape.
862   template <typename T>
863   static DenseElementsAttr get(const ShapedType &type,
864                                const std::initializer_list<T> &list) {
865     return get(type, ArrayRef<T>(list));
866   }
867 
868   /// Construct a dense elements attribute from a raw buffer representing the
869   /// data for this attribute. Users should generally not use this methods as
870   /// the expected buffer format may not be a form the user expects.
871   static DenseElementsAttr getFromRawBuffer(ShapedType type,
872                                             ArrayRef<char> rawBuffer,
873                                             bool isSplatBuffer);
874 
875   /// Returns true if the given buffer is a valid raw buffer for the given type.
876   /// `detectedSplat` is set if the buffer is valid and represents a splat
877   /// buffer.
878   static bool isValidRawBuffer(ShapedType type, ArrayRef<char> rawBuffer,
879                                bool &detectedSplat);
880 
881   //===--------------------------------------------------------------------===//
882   // Iterators
883   //===--------------------------------------------------------------------===//
884 
885   /// A utility iterator that allows walking over the internal Attribute values
886   /// of a DenseElementsAttr.
887   class AttributeElementIterator
888       : public llvm::indexed_accessor_iterator<AttributeElementIterator,
889                                                const void *, Attribute,
890                                                Attribute, Attribute> {
891   public:
892     /// Accesses the Attribute value at this iterator position.
893     Attribute operator*() const;
894 
895   private:
896     friend DenseElementsAttr;
897 
898     /// Constructs a new iterator.
899     AttributeElementIterator(DenseElementsAttr attr, size_t index);
900   };
901 
902   /// Iterator for walking raw element values of the specified type 'T', which
903   /// may be any c++ data type matching the stored representation: int32_t,
904   /// float, etc.
905   template <typename T>
906   class ElementIterator
907       : public detail::DenseElementIndexedIteratorImpl<ElementIterator<T>,
908                                                        const T> {
909   public:
910     /// Accesses the raw value at this iterator position.
911     const T &operator*() const {
912       return reinterpret_cast<const T *>(this->getData())[this->getDataIndex()];
913     }
914 
915   private:
916     friend DenseElementsAttr;
917 
918     /// Constructs a new iterator.
919     ElementIterator(const char *data, bool isSplat, size_t dataIndex)
920         : detail::DenseElementIndexedIteratorImpl<ElementIterator<T>, const T>(
921               data, isSplat, dataIndex) {}
922   };
923 
924   /// A utility iterator that allows walking over the internal bool values.
925   class BoolElementIterator
926       : public detail::DenseElementIndexedIteratorImpl<BoolElementIterator,
927                                                        bool, bool, bool> {
928   public:
929     /// Accesses the bool value at this iterator position.
930     bool operator*() const;
931 
932   private:
933     friend DenseElementsAttr;
934 
935     /// Constructs a new iterator.
936     BoolElementIterator(DenseElementsAttr attr, size_t dataIndex);
937   };
938 
939   /// A utility iterator that allows walking over the internal raw APInt values.
940   class IntElementIterator
941       : public detail::DenseElementIndexedIteratorImpl<IntElementIterator,
942                                                        APInt, APInt, APInt> {
943   public:
944     /// Accesses the raw APInt value at this iterator position.
945     APInt operator*() const;
946 
947   private:
948     friend DenseElementsAttr;
949 
950     /// Constructs a new iterator.
951     IntElementIterator(DenseElementsAttr attr, size_t dataIndex);
952 
953     /// The bitwidth of the element type.
954     size_t bitWidth;
955   };
956 
957   /// A utility iterator that allows walking over the internal raw complex APInt
958   /// values.
959   class ComplexIntElementIterator
960       : public detail::DenseElementIndexedIteratorImpl<
961             ComplexIntElementIterator, std::complex<APInt>, std::complex<APInt>,
962             std::complex<APInt>> {
963   public:
964     /// Accesses the raw std::complex<APInt> value at this iterator position.
965     std::complex<APInt> operator*() const;
966 
967   private:
968     friend DenseElementsAttr;
969 
970     /// Constructs a new iterator.
971     ComplexIntElementIterator(DenseElementsAttr attr, size_t dataIndex);
972 
973     /// The bitwidth of the element type.
974     size_t bitWidth;
975   };
976 
977   /// Iterator for walking over APFloat values.
978   class FloatElementIterator final
979       : public llvm::mapped_iterator<IntElementIterator,
980                                      std::function<APFloat(const APInt &)>> {
981     friend DenseElementsAttr;
982 
983     /// Initializes the float element iterator to the specified iterator.
984     FloatElementIterator(const llvm::fltSemantics &smt, IntElementIterator it);
985 
986   public:
987     using reference = APFloat;
988   };
989 
990   /// Iterator for walking over complex APFloat values.
991   class ComplexFloatElementIterator final
992       : public llvm::mapped_iterator<
993             ComplexIntElementIterator,
994             std::function<std::complex<APFloat>(const std::complex<APInt> &)>> {
995     friend DenseElementsAttr;
996 
997     /// Initializes the float element iterator to the specified iterator.
998     ComplexFloatElementIterator(const llvm::fltSemantics &smt,
999                                 ComplexIntElementIterator it);
1000 
1001   public:
1002     using reference = std::complex<APFloat>;
1003   };
1004 
1005   //===--------------------------------------------------------------------===//
1006   // Value Querying
1007   //===--------------------------------------------------------------------===//
1008 
1009   /// Returns if this attribute corresponds to a splat, i.e. if all element
1010   /// values are the same.
1011   bool isSplat() const;
1012 
1013   /// Return the splat value for this attribute. This asserts that the attribute
1014   /// corresponds to a splat.
1015   Attribute getSplatValue() const { return getSplatValue<Attribute>(); }
1016   template <typename T>
1017   typename std::enable_if<!std::is_base_of<Attribute, T>::value ||
1018                               std::is_same<Attribute, T>::value,
1019                           T>::type
1020   getSplatValue() const {
1021     assert(isSplat() && "expected the attribute to be a splat");
1022     return *getValues<T>().begin();
1023   }
1024   /// Return the splat value for derived attribute element types.
1025   template <typename T>
1026   typename std::enable_if<std::is_base_of<Attribute, T>::value &&
1027                               !std::is_same<Attribute, T>::value,
1028                           T>::type
1029   getSplatValue() const {
1030     return getSplatValue().template cast<T>();
1031   }
1032 
1033   /// Return the value at the given index. The 'index' is expected to refer to a
1034   /// valid element.
1035   Attribute getValue(ArrayRef<uint64_t> index) const {
1036     return getValue<Attribute>(index);
1037   }
1038   template <typename T> T getValue(ArrayRef<uint64_t> index) const {
1039     // Skip to the element corresponding to the flattened index.
1040     return *std::next(getValues<T>().begin(), getFlattenedIndex(index));
1041   }
1042 
1043   /// Return the held element values as a range of integer or floating-point
1044   /// values.
1045   template <typename T, typename = typename std::enable_if<
1046                             (!std::is_same<T, bool>::value &&
1047                              std::numeric_limits<T>::is_integer) ||
1048                             llvm::is_one_of<T, float, double>::value>::type>
1049   llvm::iterator_range<ElementIterator<T>> getValues() const {
1050     assert(isValidIntOrFloat(sizeof(T), std::numeric_limits<T>::is_integer,
1051                              std::numeric_limits<T>::is_signed));
1052     const char *rawData = getRawData().data();
1053     bool splat = isSplat();
1054     return {ElementIterator<T>(rawData, splat, 0),
1055             ElementIterator<T>(rawData, splat, getNumElements())};
1056   }
1057 
1058   /// Return the held element values as a range of std::complex.
1059   template <typename T, typename ElementT = typename T::value_type,
1060             typename = typename std::enable_if<
1061                 detail::is_complex_t<T>::value &&
1062                 (std::numeric_limits<ElementT>::is_integer ||
1063                  llvm::is_one_of<ElementT, float, double>::value)>::type>
1064   llvm::iterator_range<ElementIterator<T>> getValues() const {
1065     assert(isValidComplex(sizeof(T), std::numeric_limits<ElementT>::is_integer,
1066                           std::numeric_limits<ElementT>::is_signed));
1067     const char *rawData = getRawData().data();
1068     bool splat = isSplat();
1069     return {ElementIterator<T>(rawData, splat, 0),
1070             ElementIterator<T>(rawData, splat, getNumElements())};
1071   }
1072 
1073   /// Return the held element values as a range of StringRef.
1074   template <typename T, typename = typename std::enable_if<
1075                             std::is_same<T, StringRef>::value>::type>
1076   llvm::iterator_range<ElementIterator<StringRef>> getValues() const {
1077     auto stringRefs = getRawStringData();
1078     const char *ptr = reinterpret_cast<const char *>(stringRefs.data());
1079     bool splat = isSplat();
1080     return {ElementIterator<StringRef>(ptr, splat, 0),
1081             ElementIterator<StringRef>(ptr, splat, getNumElements())};
1082   }
1083 
1084   /// Return the held element values as a range of Attributes.
1085   llvm::iterator_range<AttributeElementIterator> getAttributeValues() const;
1086   template <typename T, typename = typename std::enable_if<
1087                             std::is_same<T, Attribute>::value>::type>
1088   llvm::iterator_range<AttributeElementIterator> getValues() const {
1089     return getAttributeValues();
1090   }
1091   AttributeElementIterator attr_value_begin() const;
1092   AttributeElementIterator attr_value_end() const;
1093 
1094   /// Return the held element values a range of T, where T is a derived
1095   /// attribute type.
1096   template <typename T>
1097   using DerivedAttributeElementIterator =
1098       llvm::mapped_iterator<AttributeElementIterator, T (*)(Attribute)>;
1099   template <typename T, typename = typename std::enable_if<
1100                             std::is_base_of<Attribute, T>::value &&
1101                             !std::is_same<Attribute, T>::value>::type>
1102   llvm::iterator_range<DerivedAttributeElementIterator<T>> getValues() const {
1103     auto castFn = [](Attribute attr) { return attr.template cast<T>(); };
1104     return llvm::map_range(getAttributeValues(),
1105                            static_cast<T (*)(Attribute)>(castFn));
1106   }
1107 
1108   /// Return the held element values as a range of bool. The element type of
1109   /// this attribute must be of integer type of bitwidth 1.
1110   llvm::iterator_range<BoolElementIterator> getBoolValues() const;
1111   template <typename T, typename = typename std::enable_if<
1112                             std::is_same<T, bool>::value>::type>
1113   llvm::iterator_range<BoolElementIterator> getValues() const {
1114     return getBoolValues();
1115   }
1116 
1117   /// Return the held element values as a range of APInts. The element type of
1118   /// this attribute must be of integer type.
1119   llvm::iterator_range<IntElementIterator> getIntValues() const;
1120   template <typename T, typename = typename std::enable_if<
1121                             std::is_same<T, APInt>::value>::type>
1122   llvm::iterator_range<IntElementIterator> getValues() const {
1123     return getIntValues();
1124   }
1125   IntElementIterator int_value_begin() const;
1126   IntElementIterator int_value_end() const;
1127 
1128   /// Return the held element values as a range of complex APInts. The element
1129   /// type of this attribute must be a complex of integer type.
1130   llvm::iterator_range<ComplexIntElementIterator> getComplexIntValues() const;
1131   template <typename T, typename = typename std::enable_if<
1132                             std::is_same<T, std::complex<APInt>>::value>::type>
1133   llvm::iterator_range<ComplexIntElementIterator> getValues() const {
1134     return getComplexIntValues();
1135   }
1136 
1137   /// Return the held element values as a range of APFloat. The element type of
1138   /// this attribute must be of float type.
1139   llvm::iterator_range<FloatElementIterator> getFloatValues() const;
1140   template <typename T, typename = typename std::enable_if<
1141                             std::is_same<T, APFloat>::value>::type>
1142   llvm::iterator_range<FloatElementIterator> getValues() const {
1143     return getFloatValues();
1144   }
1145   FloatElementIterator float_value_begin() const;
1146   FloatElementIterator float_value_end() const;
1147 
1148   /// Return the held element values as a range of complex APFloat. The element
1149   /// type of this attribute must be a complex of float type.
1150   llvm::iterator_range<ComplexFloatElementIterator>
1151   getComplexFloatValues() const;
1152   template <typename T, typename = typename std::enable_if<std::is_same<
1153                             T, std::complex<APFloat>>::value>::type>
1154   llvm::iterator_range<ComplexFloatElementIterator> getValues() const {
1155     return getComplexFloatValues();
1156   }
1157 
1158   /// Return the raw storage data held by this attribute. Users should generally
1159   /// not use this directly, as the internal storage format is not always in the
1160   /// form the user might expect.
1161   ArrayRef<char> getRawData() const;
1162 
1163   /// Return the raw StringRef data held by this attribute.
1164   ArrayRef<StringRef> getRawStringData() const;
1165 
1166   //===--------------------------------------------------------------------===//
1167   // Mutation Utilities
1168   //===--------------------------------------------------------------------===//
1169 
1170   /// Return a new DenseElementsAttr that has the same data as the current
1171   /// attribute, but has been reshaped to 'newType'. The new type must have the
1172   /// same total number of elements as well as element type.
1173   DenseElementsAttr reshape(ShapedType newType);
1174 
1175   /// Generates a new DenseElementsAttr by mapping each int value to a new
1176   /// underlying APInt. The new values can represent either an integer or float.
1177   /// This underlying type must be an DenseIntElementsAttr.
1178   DenseElementsAttr mapValues(Type newElementType,
1179                               function_ref<APInt(const APInt &)> mapping) const;
1180 
1181   /// Generates a new DenseElementsAttr by mapping each float value to a new
1182   /// underlying APInt. the new values can represent either an integer or float.
1183   /// This underlying type must be an DenseFPElementsAttr.
1184   DenseElementsAttr
1185   mapValues(Type newElementType,
1186             function_ref<APInt(const APFloat &)> mapping) const;
1187 
1188 protected:
1189   /// Get iterators to the raw APInt values for each element in this attribute.
1190   IntElementIterator raw_int_begin() const {
1191     return IntElementIterator(*this, 0);
1192   }
1193   IntElementIterator raw_int_end() const {
1194     return IntElementIterator(*this, getNumElements());
1195   }
1196 
1197   /// Overload of the raw 'get' method that asserts that the given type is of
1198   /// complex type. This method is used to verify type invariants that the
1199   /// templatized 'get' method cannot.
1200   static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data,
1201                                          int64_t dataEltSize, bool isInt,
1202                                          bool isSigned);
1203 
1204   /// Overload of the raw 'get' method that asserts that the given type is of
1205   /// integer or floating-point type. This method is used to verify type
1206   /// invariants that the templatized 'get' method cannot.
1207   static DenseElementsAttr getRawIntOrFloat(ShapedType type,
1208                                             ArrayRef<char> data,
1209                                             int64_t dataEltSize, bool isInt,
1210                                             bool isSigned);
1211 
1212   /// Check the information for a C++ data type, check if this type is valid for
1213   /// the current attribute. This method is used to verify specific type
1214   /// invariants that the templatized 'getValues' method cannot.
1215   bool isValidIntOrFloat(int64_t dataEltSize, bool isInt, bool isSigned) const;
1216 
1217   /// Check the information for a C++ data type, check if this type is valid for
1218   /// the current attribute. This method is used to verify specific type
1219   /// invariants that the templatized 'getValues' method cannot.
1220   bool isValidComplex(int64_t dataEltSize, bool isInt, bool isSigned) const;
1221 };
1222 
1223 /// An attribute class for representing dense arrays of strings. The structure
1224 /// storing and querying a list of densely packed strings.
1225 class DenseStringElementsAttr
1226     : public Attribute::AttrBase<DenseStringElementsAttr, DenseElementsAttr,
1227                                  detail::DenseStringElementsAttributeStorage> {
1228 
1229 public:
1230   using Base::Base;
1231 
1232   /// Method for support type inquiry through isa, cast and dyn_cast.
1233   static bool kindof(unsigned kind) {
1234     return kind == StandardAttributes::DenseStringElements;
1235   }
1236 
1237   /// Overload of the raw 'get' method that asserts that the given type is of
1238   /// integer or floating-point type. This method is used to verify type
1239   /// invariants that the templatized 'get' method cannot.
1240   static DenseStringElementsAttr get(ShapedType type, ArrayRef<StringRef> data);
1241 
1242 protected:
1243   friend DenseElementsAttr;
1244 };
1245 
1246 /// An attribute class for specializing behavior of Int and Floating-point
1247 /// densely packed string arrays.
1248 class DenseIntOrFPElementsAttr
1249     : public Attribute::AttrBase<DenseIntOrFPElementsAttr, DenseElementsAttr,
1250                                  detail::DenseIntOrFPElementsAttributeStorage> {
1251 
1252 public:
1253   using Base::Base;
1254 
1255   /// Method for support type inquiry through isa, cast and dyn_cast.
1256   static bool kindof(unsigned kind) {
1257     return kind == StandardAttributes::DenseIntOrFPElements;
1258   }
1259 
1260 protected:
1261   friend DenseElementsAttr;
1262 
1263   /// Constructs a dense elements attribute from an array of raw APFloat values.
1264   /// Each APFloat value is expected to have the same bitwidth as the element
1265   /// type of 'type'. 'type' must be a vector or tensor with static shape.
1266   static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth,
1267                                   ArrayRef<APFloat> values, bool isSplat);
1268 
1269   /// Constructs a dense elements attribute from an array of raw APInt values.
1270   /// Each APInt value is expected to have the same bitwidth as the element type
1271   /// of 'type'. 'type' must be a vector or tensor with static shape.
1272   static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth,
1273                                   ArrayRef<APInt> values, bool isSplat);
1274 
1275   /// Get or create a new dense elements attribute instance with the given raw
1276   /// data buffer. 'type' must be a vector or tensor with static shape.
1277   static DenseElementsAttr getRaw(ShapedType type, ArrayRef<char> data,
1278                                   bool isSplat);
1279 
1280   /// Overload of the raw 'get' method that asserts that the given type is of
1281   /// complex type. This method is used to verify type invariants that the
1282   /// templatized 'get' method cannot.
1283   static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data,
1284                                          int64_t dataEltSize, bool isInt,
1285                                          bool isSigned);
1286 
1287   /// Overload of the raw 'get' method that asserts that the given type is of
1288   /// integer or floating-point type. This method is used to verify type
1289   /// invariants that the templatized 'get' method cannot.
1290   static DenseElementsAttr getRawIntOrFloat(ShapedType type,
1291                                             ArrayRef<char> data,
1292                                             int64_t dataEltSize, bool isInt,
1293                                             bool isSigned);
1294 };
1295 
1296 /// An attribute that represents a reference to a dense float vector or tensor
1297 /// object. Each element is stored as a double.
1298 class DenseFPElementsAttr : public DenseIntOrFPElementsAttr {
1299 public:
1300   using iterator = DenseElementsAttr::FloatElementIterator;
1301 
1302   using DenseIntOrFPElementsAttr::DenseIntOrFPElementsAttr;
1303 
1304   /// Get an instance of a DenseFPElementsAttr with the given arguments. This
1305   /// simply wraps the DenseElementsAttr::get calls.
1306   template <typename Arg>
1307   static DenseFPElementsAttr get(const ShapedType &type, Arg &&arg) {
1308     return DenseElementsAttr::get(type, llvm::makeArrayRef(arg))
1309         .template cast<DenseFPElementsAttr>();
1310   }
1311   template <typename T>
1312   static DenseFPElementsAttr get(const ShapedType &type,
1313                                  const std::initializer_list<T> &list) {
1314     return DenseElementsAttr::get(type, list)
1315         .template cast<DenseFPElementsAttr>();
1316   }
1317 
1318   /// Generates a new DenseElementsAttr by mapping each value attribute, and
1319   /// constructing the DenseElementsAttr given the new element type.
1320   DenseElementsAttr
1321   mapValues(Type newElementType,
1322             function_ref<APInt(const APFloat &)> mapping) const;
1323 
1324   /// Iterator access to the float element values.
1325   iterator begin() const { return float_value_begin(); }
1326   iterator end() const { return float_value_end(); }
1327 
1328   /// Method for supporting type inquiry through isa, cast and dyn_cast.
1329   static bool classof(Attribute attr);
1330 };
1331 
1332 /// An attribute that represents a reference to a dense integer vector or tensor
1333 /// object.
1334 class DenseIntElementsAttr : public DenseIntOrFPElementsAttr {
1335 public:
1336   /// DenseIntElementsAttr iterates on APInt, so we can use the raw element
1337   /// iterator directly.
1338   using iterator = DenseElementsAttr::IntElementIterator;
1339 
1340   using DenseIntOrFPElementsAttr::DenseIntOrFPElementsAttr;
1341 
1342   /// Get an instance of a DenseIntElementsAttr with the given arguments. This
1343   /// simply wraps the DenseElementsAttr::get calls.
1344   template <typename Arg>
1345   static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg) {
1346     return DenseElementsAttr::get(type, llvm::makeArrayRef(arg))
1347         .template cast<DenseIntElementsAttr>();
1348   }
1349   template <typename T>
1350   static DenseIntElementsAttr get(const ShapedType &type,
1351                                   const std::initializer_list<T> &list) {
1352     return DenseElementsAttr::get(type, list)
1353         .template cast<DenseIntElementsAttr>();
1354   }
1355 
1356   /// Generates a new DenseElementsAttr by mapping each value attribute, and
1357   /// constructing the DenseElementsAttr given the new element type.
1358   DenseElementsAttr mapValues(Type newElementType,
1359                               function_ref<APInt(const APInt &)> mapping) const;
1360 
1361   /// Iterator access to the integer element values.
1362   iterator begin() const { return raw_int_begin(); }
1363   iterator end() const { return raw_int_end(); }
1364 
1365   /// Method for supporting type inquiry through isa, cast and dyn_cast.
1366   static bool classof(Attribute attr);
1367 };
1368 
1369 /// An opaque attribute that represents a reference to a vector or tensor
1370 /// constant with opaque content. This representation is for tensor constants
1371 /// which the compiler may not need to interpret. This attribute is always
1372 /// associated with a particular dialect, which provides a method to convert
1373 /// tensor representation to a non-opaque format.
1374 class OpaqueElementsAttr
1375     : public Attribute::AttrBase<OpaqueElementsAttr, ElementsAttr,
1376                                  detail::OpaqueElementsAttributeStorage> {
1377 public:
1378   using Base::Base;
1379   using ValueType = StringRef;
1380 
1381   static OpaqueElementsAttr get(Dialect *dialect, ShapedType type,
1382                                 StringRef bytes);
1383 
1384   StringRef getValue() const;
1385 
1386   /// Return the value at the given index. The 'index' is expected to refer to a
1387   /// valid element.
1388   Attribute getValue(ArrayRef<uint64_t> index) const;
1389 
1390   /// Decodes the attribute value using dialect-specific decoding hook.
1391   /// Returns false if decoding is successful. If not, returns true and leaves
1392   /// 'result' argument unspecified.
1393   bool decode(ElementsAttr &result);
1394 
1395   /// Returns dialect associated with this opaque constant.
1396   Dialect *getDialect() const;
1397 
1398   /// Method for support type inquiry through isa, cast and dyn_cast.
1399   static bool kindof(unsigned kind) {
1400     return kind == StandardAttributes::OpaqueElements;
1401   }
1402 };
1403 
1404 /// An attribute that represents a reference to a sparse vector or tensor
1405 /// object.
1406 ///
1407 /// This class uses COO (coordinate list) encoding to represent the sparse
1408 /// elements in an element attribute. Specifically, the sparse vector/tensor
1409 /// stores the indices and values as two separate dense elements attributes of
1410 /// tensor type (even if the sparse attribute is of vector type, in order to
1411 /// support empty lists). The dense elements attribute indices is a 2-D tensor
1412 /// of 64-bit integer elements with shape [N, ndims], which specifies the
1413 /// indices of the elements in the sparse tensor that contains nonzero values.
1414 /// The dense elements attribute values is a 1-D tensor with shape [N], and it
1415 /// supplies the corresponding values for the indices.
1416 ///
1417 /// For example,
1418 /// `sparse<tensor<3x4xi32>, [[0, 0], [1, 2]], [1, 5]>` represents tensor
1419 /// [[1, 0, 0, 0],
1420 ///  [0, 0, 5, 0],
1421 ///  [0, 0, 0, 0]].
1422 class SparseElementsAttr
1423     : public Attribute::AttrBase<SparseElementsAttr, ElementsAttr,
1424                                  detail::SparseElementsAttributeStorage> {
1425 public:
1426   using Base::Base;
1427 
1428   template <typename T>
1429   using iterator =
1430       llvm::mapped_iterator<llvm::detail::value_sequence_iterator<ptrdiff_t>,
1431                             std::function<T(ptrdiff_t)>>;
1432 
1433   /// 'type' must be a vector or tensor with static shape.
1434   static SparseElementsAttr get(ShapedType type, DenseElementsAttr indices,
1435                                 DenseElementsAttr values);
1436 
1437   DenseIntElementsAttr getIndices() const;
1438 
1439   DenseElementsAttr getValues() const;
1440 
1441   /// Return the values of this attribute in the form of the given type 'T'. 'T'
1442   /// may be any of Attribute, APInt, APFloat, c++ integer/float types, etc.
1443   template <typename T> llvm::iterator_range<iterator<T>> getValues() const {
1444     auto zeroValue = getZeroValue<T>();
1445     auto valueIt = getValues().getValues<T>().begin();
1446     const std::vector<ptrdiff_t> flatSparseIndices(getFlattenedSparseIndices());
1447     // TODO: Move-capture flatSparseIndices when c++14 is available.
1448     std::function<T(ptrdiff_t)> mapFn = [=](ptrdiff_t index) {
1449       // Try to map the current index to one of the sparse indices.
1450       for (unsigned i = 0, e = flatSparseIndices.size(); i != e; ++i)
1451         if (flatSparseIndices[i] == index)
1452           return *std::next(valueIt, i);
1453       // Otherwise, return the zero value.
1454       return zeroValue;
1455     };
1456     return llvm::map_range(llvm::seq<ptrdiff_t>(0, getNumElements()), mapFn);
1457   }
1458 
1459   /// Return the value of the element at the given index. The 'index' is
1460   /// expected to refer to a valid element.
1461   Attribute getValue(ArrayRef<uint64_t> index) const;
1462 
1463   /// Method for support type inquiry through isa, cast and dyn_cast.
1464   static bool kindof(unsigned kind) {
1465     return kind == StandardAttributes::SparseElements;
1466   }
1467 
1468 private:
1469   /// Get a zero APFloat for the given sparse attribute.
1470   APFloat getZeroAPFloat() const;
1471 
1472   /// Get a zero APInt for the given sparse attribute.
1473   APInt getZeroAPInt() const;
1474 
1475   /// Get a zero attribute for the given sparse attribute.
1476   Attribute getZeroAttr() const;
1477 
1478   /// Utility methods to generate a zero value of some type 'T'. This is used by
1479   /// the 'iterator' class.
1480   /// Get a zero for a given attribute type.
1481   template <typename T>
1482   typename std::enable_if<std::is_base_of<Attribute, T>::value, T>::type
1483   getZeroValue() const {
1484     return getZeroAttr().template cast<T>();
1485   }
1486   /// Get a zero for an APInt.
1487   template <typename T>
1488   typename std::enable_if<std::is_same<APInt, T>::value, T>::type
1489   getZeroValue() const {
1490     return getZeroAPInt();
1491   }
1492   template <typename T>
1493   typename std::enable_if<std::is_same<std::complex<APInt>, T>::value, T>::type
1494   getZeroValue() const {
1495     APInt intZero = getZeroAPInt();
1496     return {intZero, intZero};
1497   }
1498   /// Get a zero for an APFloat.
1499   template <typename T>
1500   typename std::enable_if<std::is_same<APFloat, T>::value, T>::type
1501   getZeroValue() const {
1502     return getZeroAPFloat();
1503   }
1504   template <typename T>
1505   typename std::enable_if<std::is_same<std::complex<APFloat>, T>::value,
1506                           T>::type
1507   getZeroValue() const {
1508     APFloat floatZero = getZeroAPFloat();
1509     return {floatZero, floatZero};
1510   }
1511 
1512   /// Get a zero for an C++ integer, float, StringRef, or complex type.
1513   template <typename T>
1514   typename std::enable_if<
1515       std::numeric_limits<T>::is_integer ||
1516           llvm::is_one_of<T, float, double, StringRef>::value ||
1517           (detail::is_complex_t<T>::value &&
1518            !llvm::is_one_of<T, std::complex<APInt>,
1519                             std::complex<APFloat>>::value),
1520       T>::type
1521   getZeroValue() const {
1522     return T();
1523   }
1524 
1525   /// Flatten, and return, all of the sparse indices in this attribute in
1526   /// row-major order.
1527   std::vector<ptrdiff_t> getFlattenedSparseIndices() const;
1528 };
1529 
1530 /// An attribute that represents a reference to a splat vector or tensor
1531 /// constant, meaning all of the elements have the same value.
1532 class SplatElementsAttr : public DenseElementsAttr {
1533 public:
1534   using DenseElementsAttr::DenseElementsAttr;
1535 
1536   /// Method for support type inquiry through isa, cast and dyn_cast.
1537   static bool classof(Attribute attr) {
1538     auto denseAttr = attr.dyn_cast<DenseElementsAttr>();
1539     return denseAttr && denseAttr.isSplat();
1540   }
1541 };
1542 
1543 namespace detail {
1544 /// This class represents a general iterator over the values of an ElementsAttr.
1545 /// It supports all subclasses aside from OpaqueElementsAttr.
1546 template <typename T>
1547 class ElementsAttrIterator
1548     : public llvm::iterator_facade_base<ElementsAttrIterator<T>,
1549                                         std::random_access_iterator_tag, T,
1550                                         std::ptrdiff_t, T, T> {
1551   // NOTE: We use a dummy enable_if here because MSVC cannot use 'decltype'
1552   // inside of a conversion operator.
1553   using DenseIteratorT = typename std::enable_if<
1554       true,
1555       decltype(std::declval<DenseElementsAttr>().getValues<T>().begin())>::type;
1556   using SparseIteratorT = SparseElementsAttr::iterator<T>;
1557 
1558   /// A union containing the specific iterators for each derived attribute kind.
1559   union Iterator {
1560     Iterator(DenseIteratorT &&it) : denseIt(std::move(it)) {}
1561     Iterator(SparseIteratorT &&it) : sparseIt(std::move(it)) {}
1562     Iterator() {}
1563     ~Iterator() {}
1564 
1565     operator const DenseIteratorT &() const { return denseIt; }
1566     operator const SparseIteratorT &() const { return sparseIt; }
1567     operator DenseIteratorT &() { return denseIt; }
1568     operator SparseIteratorT &() { return sparseIt; }
1569 
1570     /// An instance of a dense elements iterator.
1571     DenseIteratorT denseIt;
1572     /// An instance of a sparse elements iterator.
1573     SparseIteratorT sparseIt;
1574   };
1575 
1576   /// Utility method to process a functor on each of the internal iterator
1577   /// types.
1578   template <typename RetT, template <typename> class ProcessFn,
1579             typename... Args>
1580   RetT process(Args &... args) const {
1581     switch (attrKind) {
1582     case StandardAttributes::DenseIntOrFPElements:
1583       return ProcessFn<DenseIteratorT>()(args...);
1584     case StandardAttributes::SparseElements:
1585       return ProcessFn<SparseIteratorT>()(args...);
1586     }
1587     llvm_unreachable("unexpected attribute kind");
1588   }
1589 
1590   /// Utility functors used to generically implement the iterators methods.
1591   template <typename ItT> struct PlusAssign {
1592     void operator()(ItT &it, ptrdiff_t offset) { it += offset; }
1593   };
1594   template <typename ItT> struct Minus {
1595     ptrdiff_t operator()(const ItT &lhs, const ItT &rhs) { return lhs - rhs; }
1596   };
1597   template <typename ItT> struct MinusAssign {
1598     void operator()(ItT &it, ptrdiff_t offset) { it -= offset; }
1599   };
1600   template <typename ItT> struct Dereference {
1601     T operator()(ItT &it) { return *it; }
1602   };
1603   template <typename ItT> struct ConstructIter {
1604     void operator()(ItT &dest, const ItT &it) { ::new (&dest) ItT(it); }
1605   };
1606   template <typename ItT> struct DestructIter {
1607     void operator()(ItT &it) { it.~ItT(); }
1608   };
1609 
1610 public:
1611   ElementsAttrIterator(const ElementsAttrIterator<T> &rhs)
1612       : attrKind(rhs.attrKind) {
1613     process<void, ConstructIter>(it, rhs.it);
1614   }
1615   ~ElementsAttrIterator() { process<void, DestructIter>(it); }
1616 
1617   /// Methods necessary to support random access iteration.
1618   ptrdiff_t operator-(const ElementsAttrIterator<T> &rhs) const {
1619     assert(attrKind == rhs.attrKind && "incompatible iterators");
1620     return process<ptrdiff_t, Minus>(it, rhs.it);
1621   }
1622   bool operator==(const ElementsAttrIterator<T> &rhs) const {
1623     return rhs.attrKind == attrKind && process<bool, std::equal_to>(it, rhs.it);
1624   }
1625   bool operator<(const ElementsAttrIterator<T> &rhs) const {
1626     assert(attrKind == rhs.attrKind && "incompatible iterators");
1627     return process<bool, std::less>(it, rhs.it);
1628   }
1629   ElementsAttrIterator<T> &operator+=(ptrdiff_t offset) {
1630     process<void, PlusAssign>(it, offset);
1631     return *this;
1632   }
1633   ElementsAttrIterator<T> &operator-=(ptrdiff_t offset) {
1634     process<void, MinusAssign>(it, offset);
1635     return *this;
1636   }
1637 
1638   /// Dereference the iterator at the current index.
1639   T operator*() { return process<T, Dereference>(it); }
1640 
1641 private:
1642   template <typename IteratorT>
1643   ElementsAttrIterator(unsigned attrKind, IteratorT &&it)
1644       : attrKind(attrKind), it(std::forward<IteratorT>(it)) {}
1645 
1646   /// Allow accessing the constructor.
1647   friend ElementsAttr;
1648 
1649   /// The kind of derived elements attribute.
1650   unsigned attrKind;
1651 
1652   /// A union containing the specific iterators for each derived kind.
1653   Iterator it;
1654 };
1655 
1656 template <typename T>
1657 class ElementsAttrRange : public llvm::iterator_range<ElementsAttrIterator<T>> {
1658   using llvm::iterator_range<ElementsAttrIterator<T>>::iterator_range;
1659 };
1660 } // namespace detail
1661 
1662 /// Return the elements of this attribute as a value of type 'T'.
1663 template <typename T>
1664 auto ElementsAttr::getValues() const -> iterator_range<T> {
1665   if (DenseElementsAttr denseAttr = dyn_cast<DenseElementsAttr>()) {
1666     auto values = denseAttr.getValues<T>();
1667     return {iterator<T>(getKind(), values.begin()),
1668             iterator<T>(getKind(), values.end())};
1669   }
1670   if (SparseElementsAttr sparseAttr = dyn_cast<SparseElementsAttr>()) {
1671     auto values = sparseAttr.getValues<T>();
1672     return {iterator<T>(getKind(), values.begin()),
1673             iterator<T>(getKind(), values.end())};
1674   }
1675   llvm_unreachable("unexpected attribute kind");
1676 }
1677 
1678 //===----------------------------------------------------------------------===//
1679 // Attributes Utils
1680 //===----------------------------------------------------------------------===//
1681 
1682 template <typename U> bool Attribute::isa() const {
1683   assert(impl && "isa<> used on a null attribute.");
1684   return U::classof(*this);
1685 }
1686 
1687 template <typename First, typename Second, typename... Rest>
1688 bool Attribute::isa() const {
1689   return isa<First>() || isa<Second, Rest...>();
1690 }
1691 
1692 template <typename U> U Attribute::dyn_cast() const {
1693   return isa<U>() ? U(impl) : U(nullptr);
1694 }
1695 template <typename U> U Attribute::dyn_cast_or_null() const {
1696   return (impl && isa<U>()) ? U(impl) : U(nullptr);
1697 }
1698 template <typename U> U Attribute::cast() const {
1699   assert(isa<U>());
1700   return U(impl);
1701 }
1702 
1703 // Make Attribute hashable.
1704 inline ::llvm::hash_code hash_value(Attribute arg) {
1705   return ::llvm::hash_value(arg.impl);
1706 }
1707 
1708 //===----------------------------------------------------------------------===//
1709 // MutableDictionaryAttr
1710 //===----------------------------------------------------------------------===//
1711 
1712 /// A MutableDictionaryAttr is a mutable wrapper around a DictionaryAttr. It
1713 /// provides additional interfaces for adding, removing, replacing attributes
1714 /// within a DictionaryAttr.
1715 ///
1716 /// We assume there will be relatively few attributes on a given operation
1717 /// (maybe a dozen or so, but not hundreds or thousands) so we use linear
1718 /// searches for everything.
1719 class MutableDictionaryAttr {
1720 public:
1721   MutableDictionaryAttr(DictionaryAttr attrs = nullptr)
1722       : attrs((attrs && !attrs.empty()) ? attrs : nullptr) {}
1723   MutableDictionaryAttr(ArrayRef<NamedAttribute> attributes);
1724 
1725   bool operator!=(const MutableDictionaryAttr &other) const {
1726     return !(*this == other);
1727   }
1728   bool operator==(const MutableDictionaryAttr &other) const {
1729     return attrs == other.attrs;
1730   }
1731 
1732   /// Return the underlying dictionary attribute.
1733   DictionaryAttr getDictionary(MLIRContext *context) const;
1734 
1735   /// Return all of the attributes on this operation.
1736   ArrayRef<NamedAttribute> getAttrs() const;
1737 
1738   /// Replace the held attributes with ones provided in 'newAttrs'.
1739   void setAttrs(ArrayRef<NamedAttribute> attributes);
1740 
1741   /// Return the specified attribute if present, null otherwise.
1742   Attribute get(StringRef name) const;
1743   Attribute get(Identifier name) const;
1744 
1745   /// Return the specified named attribute if present, None otherwise.
1746   Optional<NamedAttribute> getNamed(StringRef name) const;
1747   Optional<NamedAttribute> getNamed(Identifier name) const;
1748 
1749   /// If the an attribute exists with the specified name, change it to the new
1750   /// value.  Otherwise, add a new attribute with the specified name/value.
1751   void set(Identifier name, Attribute value);
1752 
1753   enum class RemoveResult { Removed, NotFound };
1754 
1755   /// Remove the attribute with the specified name if it exists.  The return
1756   /// value indicates whether the attribute was present or not.
1757   RemoveResult remove(Identifier name);
1758 
1759   bool empty() const { return attrs == nullptr; }
1760 
1761 private:
1762   friend ::llvm::hash_code hash_value(const MutableDictionaryAttr &arg);
1763 
1764   DictionaryAttr attrs;
1765 };
1766 
1767 inline ::llvm::hash_code hash_value(const MutableDictionaryAttr &arg) {
1768   if (!arg.attrs)
1769     return ::llvm::hash_value((void *)nullptr);
1770   return hash_value(arg.attrs);
1771 }
1772 
1773 } // end namespace mlir.
1774 
1775 namespace llvm {
1776 
1777 // Attribute hash just like pointers.
1778 template <> struct DenseMapInfo<mlir::Attribute> {
1779   static mlir::Attribute getEmptyKey() {
1780     auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
1781     return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer));
1782   }
1783   static mlir::Attribute getTombstoneKey() {
1784     auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
1785     return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer));
1786   }
1787   static unsigned getHashValue(mlir::Attribute val) {
1788     return mlir::hash_value(val);
1789   }
1790   static bool isEqual(mlir::Attribute LHS, mlir::Attribute RHS) {
1791     return LHS == RHS;
1792   }
1793 };
1794 
1795 /// Allow LLVM to steal the low bits of Attributes.
1796 template <> struct PointerLikeTypeTraits<mlir::Attribute> {
1797   static inline void *getAsVoidPointer(mlir::Attribute attr) {
1798     return const_cast<void *>(attr.getAsOpaquePointer());
1799   }
1800   static inline mlir::Attribute getFromVoidPointer(void *ptr) {
1801     return mlir::Attribute::getFromOpaquePointer(ptr);
1802   }
1803   static constexpr int NumLowBitsAvailable = 3;
1804 };
1805 
1806 template <>
1807 struct PointerLikeTypeTraits<mlir::SymbolRefAttr>
1808     : public PointerLikeTypeTraits<mlir::Attribute> {
1809   static inline mlir::SymbolRefAttr getFromVoidPointer(void *ptr) {
1810     return PointerLikeTypeTraits<mlir::Attribute>::getFromVoidPointer(ptr)
1811         .cast<mlir::SymbolRefAttr>();
1812   }
1813 };
1814 
1815 } // namespace llvm
1816 
1817 #endif
1818