MLIR  15.0.0git
BuiltinAttributes.h
Go to the documentation of this file.
1 //===- BuiltinAttributes.h - MLIR Builtin 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_BUILTINATTRIBUTES_H
10 #define MLIR_IR_BUILTINATTRIBUTES_H
11 
14 #include "llvm/ADT/APFloat.h"
15 #include "llvm/ADT/Sequence.h"
16 #include <complex>
17 
18 namespace mlir {
19 class AffineMap;
20 class BoolAttr;
21 class DenseIntElementsAttr;
22 class FlatSymbolRefAttr;
23 class FunctionType;
24 class IntegerSet;
25 class IntegerType;
26 class Location;
27 class Operation;
28 class ShapedType;
29 
30 //===----------------------------------------------------------------------===//
31 // Elements Attributes
32 //===----------------------------------------------------------------------===//
33 
34 namespace detail {
35 /// Pair of raw pointer and a boolean flag of whether the pointer holds a splat,
36 using DenseIterPtrAndSplat = std::pair<const char *, bool>;
37 
38 /// Impl iterator for indexed DenseElementsAttr iterators that records a data
39 /// pointer and data index that is adjusted for the case of a splat attribute.
40 template <typename ConcreteT, typename T, typename PointerT = T *,
41  typename ReferenceT = T &>
43  : public llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
44  PointerT, ReferenceT> {
45 protected:
46  DenseElementIndexedIteratorImpl(const char *data, bool isSplat,
47  size_t dataIndex)
48  : llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
49  PointerT, ReferenceT>({data, isSplat},
50  dataIndex) {}
51 
52  /// Return the current index for this iterator, adjusted for the case of a
53  /// splat.
54  ptrdiff_t getDataIndex() const {
55  bool isSplat = this->base.second;
56  return isSplat ? 0 : this->index;
57  }
58 
59  /// Return the data base pointer.
60  const char *getData() const { return this->base.first; }
61 };
62 
63 /// Type trait detector that checks if a given type T is a complex type.
64 template <typename T> struct is_complex_t : public std::false_type {};
65 template <typename T>
66 struct is_complex_t<std::complex<T>> : public std::true_type {};
67 } // namespace detail
68 
69 /// An attribute that represents a reference to a dense vector or tensor
70 /// object.
71 class DenseElementsAttr : public Attribute {
72 public:
74 
75  /// Allow implicit conversion to ElementsAttr.
76  operator ElementsAttr() const {
77  return *this ? cast<ElementsAttr>() : nullptr;
78  }
79 
80  /// Type trait used to check if the given type T is a potentially valid C++
81  /// floating point type that can be used to access the underlying element
82  /// types of a DenseElementsAttr.
83  // TODO: Use std::disjunction when C++17 is supported.
84  template <typename T> struct is_valid_cpp_fp_type {
85  /// The type is a valid floating point type if it is a builtin floating
86  /// point type, or is a potentially user defined floating point type. The
87  /// latter allows for supporting users that have custom types defined for
88  /// bfloat16/half/etc.
90  (std::numeric_limits<T>::is_specialized &&
91  !std::numeric_limits<T>::is_integer);
92  };
93 
94  /// Method for support type inquiry through isa, cast and dyn_cast.
95  static bool classof(Attribute attr);
96 
97  /// Constructs a dense elements attribute from an array of element values.
98  /// Each element attribute value is expected to be an element of 'type'.
99  /// 'type' must be a vector or tensor with static shape. If the element of
100  /// `type` is non-integer/index/float it is assumed to be a string type.
101  static DenseElementsAttr get(ShapedType type, ArrayRef<Attribute> values);
102 
103  /// Constructs a dense integer elements attribute from an array of integer
104  /// or floating-point values. Each value is expected to be the same bitwidth
105  /// of the element type of 'type'. 'type' must be a vector or tensor with
106  /// static shape.
107  template <typename T, typename = typename std::enable_if<
108  std::numeric_limits<T>::is_integer ||
110  static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) {
111  const char *data = reinterpret_cast<const char *>(values.data());
112  return getRawIntOrFloat(
113  type, ArrayRef<char>(data, values.size() * sizeof(T)), sizeof(T),
114  std::numeric_limits<T>::is_integer, std::numeric_limits<T>::is_signed);
115  }
116 
117  /// Constructs a dense integer elements attribute from a single element.
118  template <typename T, typename = typename std::enable_if<
119  std::numeric_limits<T>::is_integer ||
122  static DenseElementsAttr get(const ShapedType &type, T value) {
123  return get(type, llvm::makeArrayRef(value));
124  }
125 
126  /// Constructs a dense complex elements attribute from an array of complex
127  /// values. Each value is expected to be the same bitwidth of the element type
128  /// of 'type'. 'type' must be a vector or tensor with static shape.
129  template <typename T, typename ElementT = typename T::value_type,
130  typename = typename std::enable_if<
132  (std::numeric_limits<ElementT>::is_integer ||
134  static DenseElementsAttr get(const ShapedType &type, ArrayRef<T> values) {
135  const char *data = reinterpret_cast<const char *>(values.data());
136  return getRawComplex(type, ArrayRef<char>(data, values.size() * sizeof(T)),
137  sizeof(T), std::numeric_limits<ElementT>::is_integer,
138  std::numeric_limits<ElementT>::is_signed);
139  }
140 
141  /// Overload of the above 'get' method that is specialized for boolean values.
142  static DenseElementsAttr get(ShapedType type, ArrayRef<bool> values);
143 
144  /// Overload of the above 'get' method that is specialized for StringRef
145  /// values.
146  static DenseElementsAttr get(ShapedType type, ArrayRef<StringRef> values);
147 
148  /// Constructs a dense integer elements attribute from an array of APInt
149  /// values. Each APInt value is expected to have the same bitwidth as the
150  /// element type of 'type'. 'type' must be a vector or tensor with static
151  /// shape.
152  static DenseElementsAttr get(ShapedType type, ArrayRef<APInt> values);
153 
154  /// Constructs a dense complex elements attribute from an array of APInt
155  /// values. Each APInt value is expected to have the same bitwidth as the
156  /// element type of 'type'. 'type' must be a vector or tensor with static
157  /// shape.
158  static DenseElementsAttr get(ShapedType type,
160 
161  /// Constructs a dense float elements attribute from an array of APFloat
162  /// values. Each APFloat value is expected to have the same bitwidth as the
163  /// element type of 'type'. 'type' must be a vector or tensor with static
164  /// shape.
165  static DenseElementsAttr get(ShapedType type, ArrayRef<APFloat> values);
166 
167  /// Constructs a dense complex elements attribute from an array of APFloat
168  /// values. Each APFloat value is expected to have the same bitwidth as the
169  /// element type of 'type'. 'type' must be a vector or tensor with static
170  /// shape.
171  static DenseElementsAttr get(ShapedType type,
173 
174  /// Construct a dense elements attribute for an initializer_list of values.
175  /// Each value is expected to be the same bitwidth of the element type of
176  /// 'type'. 'type' must be a vector or tensor with static shape.
177  template <typename T>
178  static DenseElementsAttr get(const ShapedType &type,
179  const std::initializer_list<T> &list) {
180  return get(type, ArrayRef<T>(list));
181  }
182 
183  /// Construct a dense elements attribute from a raw buffer representing the
184  /// data for this attribute. Users are encouraged to use one of the
185  /// constructors above, which provide more safeties. However, this
186  /// constructor is useful for tools which may want to interop and can
187  /// follow the precise definition.
188  ///
189  /// The format of the raw buffer is a densely packed array of values that
190  /// can be bitcast to the storage format of the element type specified.
191  /// Types that are not byte aligned will be:
192  /// - For bitwidth > 1: Rounded up to the next byte.
193  /// - For bitwidth = 1: Packed into 8bit bytes with bits corresponding to
194  /// the linear order of the shape type from MSB to LSB, padded to on the
195  /// right.
196  static DenseElementsAttr getFromRawBuffer(ShapedType type,
197  ArrayRef<char> rawBuffer);
198 
199  /// Returns true if the given buffer is a valid raw buffer for the given type.
200  /// `detectedSplat` is set if the buffer is valid and represents a splat
201  /// buffer. The definition may be expanded over time, but currently, a
202  /// splat buffer is detected if:
203  /// - For >1bit: The buffer consists of a single element.
204  /// - For 1bit: The buffer consists of a single byte with value 0 or 255.
205  ///
206  /// User code should be prepared for additional, conformant patterns to be
207  /// identified as splats in the future.
208  static bool isValidRawBuffer(ShapedType type, ArrayRef<char> rawBuffer,
209  bool &detectedSplat);
210 
211  //===--------------------------------------------------------------------===//
212  // Iterators
213  //===--------------------------------------------------------------------===//
214 
215  /// The iterator range over the given iterator type T.
216  template <typename IteratorT>
218 
219  /// The iterator for the given element type T.
220  template <typename T, typename AttrT = DenseElementsAttr>
221  using iterator = decltype(std::declval<AttrT>().template value_begin<T>());
222  /// The iterator range over the given element T.
223  template <typename T, typename AttrT = DenseElementsAttr>
224  using iterator_range =
225  decltype(std::declval<AttrT>().template getValues<T>());
226 
227  /// A utility iterator that allows walking over the internal Attribute values
228  /// of a DenseElementsAttr.
230  : public llvm::indexed_accessor_iterator<AttributeElementIterator,
231  const void *, Attribute,
232  Attribute, Attribute> {
233  public:
234  /// Accesses the Attribute value at this iterator position.
235  Attribute operator*() const;
236 
237  private:
238  friend DenseElementsAttr;
239 
240  /// Constructs a new iterator.
241  AttributeElementIterator(DenseElementsAttr attr, size_t index);
242  };
243 
244  /// Iterator for walking raw element values of the specified type 'T', which
245  /// may be any c++ data type matching the stored representation: int32_t,
246  /// float, etc.
247  template <typename T>
249  : public detail::DenseElementIndexedIteratorImpl<ElementIterator<T>,
250  const T> {
251  public:
252  /// Accesses the raw value at this iterator position.
253  const T &operator*() const {
254  return reinterpret_cast<const T *>(this->getData())[this->getDataIndex()];
255  }
256 
257  private:
258  friend DenseElementsAttr;
259 
260  /// Constructs a new iterator.
261  ElementIterator(const char *data, bool isSplat, size_t dataIndex)
263  data, isSplat, dataIndex) {}
264  };
265 
266  /// A utility iterator that allows walking over the internal bool values.
268  : public detail::DenseElementIndexedIteratorImpl<BoolElementIterator,
269  bool, bool, bool> {
270  public:
271  /// Accesses the bool value at this iterator position.
272  bool operator*() const;
273 
274  private:
275  friend DenseElementsAttr;
276 
277  /// Constructs a new iterator.
278  BoolElementIterator(DenseElementsAttr attr, size_t dataIndex);
279  };
280 
281  /// A utility iterator that allows walking over the internal raw APInt values.
283  : public detail::DenseElementIndexedIteratorImpl<IntElementIterator,
284  APInt, APInt, APInt> {
285  public:
286  /// Accesses the raw APInt value at this iterator position.
287  APInt operator*() const;
288 
289  private:
290  friend DenseElementsAttr;
291 
292  /// Constructs a new iterator.
293  IntElementIterator(DenseElementsAttr attr, size_t dataIndex);
294 
295  /// The bitwidth of the element type.
296  size_t bitWidth;
297  };
298 
299  /// A utility iterator that allows walking over the internal raw complex APInt
300  /// values.
303  ComplexIntElementIterator, std::complex<APInt>, std::complex<APInt>,
304  std::complex<APInt>> {
305  public:
306  /// Accesses the raw std::complex<APInt> value at this iterator position.
307  std::complex<APInt> operator*() const;
308 
309  private:
310  friend DenseElementsAttr;
311 
312  /// Constructs a new iterator.
313  ComplexIntElementIterator(DenseElementsAttr attr, size_t dataIndex);
314 
315  /// The bitwidth of the element type.
316  size_t bitWidth;
317  };
318 
319  /// Iterator for walking over APFloat values.
321  : public llvm::mapped_iterator_base<FloatElementIterator,
322  IntElementIterator, APFloat> {
323  public:
324  /// Map the element to the iterator result type.
325  APFloat mapElement(const APInt &value) const {
326  return APFloat(*smt, value);
327  }
328 
329  private:
330  friend DenseElementsAttr;
331 
332  /// Initializes the float element iterator to the specified iterator.
333  FloatElementIterator(const llvm::fltSemantics &smt, IntElementIterator it)
334  : BaseT(it), smt(&smt) {}
335 
336  /// The float semantics to use when constructing the APFloat.
337  const llvm::fltSemantics *smt;
338  };
339 
340  /// Iterator for walking over complex APFloat values.
342  : public llvm::mapped_iterator_base<ComplexFloatElementIterator,
343  ComplexIntElementIterator,
344  std::complex<APFloat>> {
345  public:
346  /// Map the element to the iterator result type.
347  std::complex<APFloat> mapElement(const std::complex<APInt> &value) const {
348  return {APFloat(*smt, value.real()), APFloat(*smt, value.imag())};
349  }
350 
351  private:
352  friend DenseElementsAttr;
353 
354  /// Initializes the float element iterator to the specified iterator.
355  ComplexFloatElementIterator(const llvm::fltSemantics &smt,
357  : BaseT(it), smt(&smt) {}
358 
359  /// The float semantics to use when constructing the APFloat.
360  const llvm::fltSemantics *smt;
361  };
362 
363  //===--------------------------------------------------------------------===//
364  // Value Querying
365  //===--------------------------------------------------------------------===//
366 
367  /// Returns true if this attribute corresponds to a splat, i.e. if all element
368  /// values are the same.
369  bool isSplat() const;
370 
371  /// Return the splat value for this attribute. This asserts that the attribute
372  /// corresponds to a splat.
373  template <typename T>
376  T>::type
377  getSplatValue() const {
378  assert(isSplat() && "expected the attribute to be a splat");
379  return *value_begin<T>();
380  }
381  /// Return the splat value for derived attribute element types.
382  template <typename T>
385  T>::type
386  getSplatValue() const {
387  return getSplatValue<Attribute>().template cast<T>();
388  }
389 
390  /// Return the held element values as a range of integer or floating-point
391  /// values.
392  template <typename T>
395  std::numeric_limits<T>::is_integer) ||
397  template <typename T, typename = IntFloatValueTemplateCheckT<T>>
399  assert(isValidIntOrFloat(sizeof(T), std::numeric_limits<T>::is_integer,
400  std::numeric_limits<T>::is_signed));
401  const char *rawData = getRawData().data();
402  bool splat = isSplat();
403  return {Attribute::getType(), ElementIterator<T>(rawData, splat, 0),
404  ElementIterator<T>(rawData, splat, getNumElements())};
405  }
406  template <typename T, typename = IntFloatValueTemplateCheckT<T>>
408  assert(isValidIntOrFloat(sizeof(T), std::numeric_limits<T>::is_integer,
409  std::numeric_limits<T>::is_signed));
410  return ElementIterator<T>(getRawData().data(), isSplat(), 0);
411  }
412  template <typename T, typename = IntFloatValueTemplateCheckT<T>>
414  assert(isValidIntOrFloat(sizeof(T), std::numeric_limits<T>::is_integer,
415  std::numeric_limits<T>::is_signed));
416  return ElementIterator<T>(getRawData().data(), isSplat(), getNumElements());
417  }
418 
419  /// Return the held element values as a range of std::complex.
420  template <typename T, typename ElementT>
423  (std::numeric_limits<ElementT>::is_integer ||
425  template <typename T, typename ElementT = typename T::value_type,
428  assert(isValidComplex(sizeof(T), std::numeric_limits<ElementT>::is_integer,
429  std::numeric_limits<ElementT>::is_signed));
430  const char *rawData = getRawData().data();
431  bool splat = isSplat();
432  return {Attribute::getType(), ElementIterator<T>(rawData, splat, 0),
433  ElementIterator<T>(rawData, splat, getNumElements())};
434  }
435  template <typename T, typename ElementT = typename T::value_type,
438  assert(isValidComplex(sizeof(T), std::numeric_limits<ElementT>::is_integer,
439  std::numeric_limits<ElementT>::is_signed));
440  return ElementIterator<T>(getRawData().data(), isSplat(), 0);
441  }
442  template <typename T, typename ElementT = typename T::value_type,
445  assert(isValidComplex(sizeof(T), std::numeric_limits<ElementT>::is_integer,
446  std::numeric_limits<ElementT>::is_signed));
447  return ElementIterator<T>(getRawData().data(), isSplat(), getNumElements());
448  }
449 
450  /// Return the held element values as a range of StringRef.
451  template <typename T>
454  template <typename T, typename = StringRefValueTemplateCheckT<T>>
456  auto stringRefs = getRawStringData();
457  const char *ptr = reinterpret_cast<const char *>(stringRefs.data());
458  bool splat = isSplat();
459  return {Attribute::getType(), ElementIterator<StringRef>(ptr, splat, 0),
461  }
462  template <typename T, typename = StringRefValueTemplateCheckT<T>>
464  const char *ptr = reinterpret_cast<const char *>(getRawStringData().data());
465  return ElementIterator<StringRef>(ptr, isSplat(), 0);
466  }
467  template <typename T, typename = StringRefValueTemplateCheckT<T>>
469  const char *ptr = reinterpret_cast<const char *>(getRawStringData().data());
470  return ElementIterator<StringRef>(ptr, isSplat(), getNumElements());
471  }
472 
473  /// Return the held element values as a range of Attributes.
474  template <typename T>
477  template <typename T, typename = AttributeValueTemplateCheckT<T>>
479  return {Attribute::getType(), value_begin<Attribute>(),
480  value_end<Attribute>()};
481  }
482  template <typename T, typename = AttributeValueTemplateCheckT<T>>
484  return AttributeElementIterator(*this, 0);
485  }
486  template <typename T, typename = AttributeValueTemplateCheckT<T>>
488  return AttributeElementIterator(*this, getNumElements());
489  }
490 
491  /// Return the held element values a range of T, where T is a derived
492  /// attribute type.
493  template <typename T>
497  template <typename T>
499  : public llvm::mapped_iterator_base<DerivedAttributeElementIterator<T>,
500  AttributeElementIterator, T> {
501  using llvm::mapped_iterator_base<DerivedAttributeElementIterator<T>,
503  T>::mapped_iterator_base;
504 
505  /// Map the element to the iterator result type.
506  T mapElement(Attribute attr) const { return attr.cast<T>(); }
507  };
508  template <typename T, typename = DerivedAttrValueTemplateCheckT<T>>
510  using DerivedIterT = DerivedAttributeElementIterator<T>;
511  return {Attribute::getType(), DerivedIterT(value_begin<Attribute>()),
512  DerivedIterT(value_end<Attribute>())};
513  }
514  template <typename T, typename = DerivedAttrValueTemplateCheckT<T>>
516  return {value_begin<Attribute>()};
517  }
518  template <typename T, typename = DerivedAttrValueTemplateCheckT<T>>
520  return {value_end<Attribute>()};
521  }
522 
523  /// Return the held element values as a range of bool. The element type of
524  /// this attribute must be of integer type of bitwidth 1.
525  template <typename T>
528  template <typename T, typename = BoolValueTemplateCheckT<T>>
530  assert(isValidBool() && "bool is not the value of this elements attribute");
531  return {Attribute::getType(), BoolElementIterator(*this, 0),
533  }
534  template <typename T, typename = BoolValueTemplateCheckT<T>>
536  assert(isValidBool() && "bool is not the value of this elements attribute");
537  return BoolElementIterator(*this, 0);
538  }
539  template <typename T, typename = BoolValueTemplateCheckT<T>>
541  assert(isValidBool() && "bool is not the value of this elements attribute");
542  return BoolElementIterator(*this, getNumElements());
543  }
544 
545  /// Return the held element values as a range of APInts. The element type of
546  /// this attribute must be of integer type.
547  template <typename T>
550  template <typename T, typename = APIntValueTemplateCheckT<T>>
552  assert(getElementType().isIntOrIndex() && "expected integral type");
553  return {Attribute::getType(), raw_int_begin(), raw_int_end()};
554  }
555  template <typename T, typename = APIntValueTemplateCheckT<T>>
557  assert(getElementType().isIntOrIndex() && "expected integral type");
558  return raw_int_begin();
559  }
560  template <typename T, typename = APIntValueTemplateCheckT<T>>
562  assert(getElementType().isIntOrIndex() && "expected integral type");
563  return raw_int_end();
564  }
565 
566  /// Return the held element values as a range of complex APInts. The element
567  /// type of this attribute must be a complex of integer type.
568  template <typename T>
569  using ComplexAPIntValueTemplateCheckT = typename std::enable_if<
570  std::is_same<T, std::complex<APInt>>::value>::type;
571  template <typename T, typename = ComplexAPIntValueTemplateCheckT<T>>
573  return getComplexIntValues();
574  }
575  template <typename T, typename = ComplexAPIntValueTemplateCheckT<T>>
577  return complex_value_begin();
578  }
579  template <typename T, typename = ComplexAPIntValueTemplateCheckT<T>>
581  return complex_value_end();
582  }
583 
584  /// Return the held element values as a range of APFloat. The element type of
585  /// this attribute must be of float type.
586  template <typename T>
589  template <typename T, typename = APFloatValueTemplateCheckT<T>>
591  return getFloatValues();
592  }
593  template <typename T, typename = APFloatValueTemplateCheckT<T>>
595  return float_value_begin();
596  }
597  template <typename T, typename = APFloatValueTemplateCheckT<T>>
599  return float_value_end();
600  }
601 
602  /// Return the held element values as a range of complex APFloat. The element
603  /// type of this attribute must be a complex of float type.
604  template <typename T>
605  using ComplexAPFloatValueTemplateCheckT = typename std::enable_if<
606  std::is_same<T, std::complex<APFloat>>::value>::type;
607  template <typename T, typename = ComplexAPFloatValueTemplateCheckT<T>>
609  return getComplexFloatValues();
610  }
611  template <typename T, typename = ComplexAPFloatValueTemplateCheckT<T>>
613  return complex_float_value_begin();
614  }
615  template <typename T, typename = ComplexAPFloatValueTemplateCheckT<T>>
617  return complex_float_value_end();
618  }
619 
620  /// Return the raw storage data held by this attribute. Users should generally
621  /// not use this directly, as the internal storage format is not always in the
622  /// form the user might expect.
623  ArrayRef<char> getRawData() const;
624 
625  /// Return the raw StringRef data held by this attribute.
626  ArrayRef<StringRef> getRawStringData() const;
627 
628  /// Return the type of this ElementsAttr, guaranteed to be a vector or tensor
629  /// with static shape.
630  ShapedType getType() const;
631 
632  /// Return the element type of this DenseElementsAttr.
633  Type getElementType() const;
634 
635  /// Returns the number of elements held by this attribute.
636  int64_t getNumElements() const;
637 
638  /// Returns the number of elements held by this attribute.
639  int64_t size() const { return getNumElements(); }
640 
641  /// Returns if the number of elements held by this attribute is 0.
642  bool empty() const { return size() == 0; }
643 
644  //===--------------------------------------------------------------------===//
645  // Mutation Utilities
646  //===--------------------------------------------------------------------===//
647 
648  /// Return a new DenseElementsAttr that has the same data as the current
649  /// attribute, but has been reshaped to 'newType'. The new type must have the
650  /// same total number of elements as well as element type.
651  DenseElementsAttr reshape(ShapedType newType);
652 
653  /// Return a new DenseElementsAttr that has the same data as the current
654  /// attribute, but with a different shape for a splat type. The new type must
655  /// have the same element type.
656  DenseElementsAttr resizeSplat(ShapedType newType);
657 
658  /// Return a new DenseElementsAttr that has the same data as the current
659  /// attribute, but has bitcast elements to 'newElType'. The new type must have
660  /// the same bitwidth as the current element type.
661  DenseElementsAttr bitcast(Type newElType);
662 
663  /// Generates a new DenseElementsAttr by mapping each int value to a new
664  /// underlying APInt. The new values can represent either an integer or float.
665  /// This underlying type must be an DenseIntElementsAttr.
666  DenseElementsAttr mapValues(Type newElementType,
667  function_ref<APInt(const APInt &)> mapping) const;
668 
669  /// Generates a new DenseElementsAttr by mapping each float value to a new
670  /// underlying APInt. the new values can represent either an integer or float.
671  /// This underlying type must be an DenseFPElementsAttr.
673  mapValues(Type newElementType,
674  function_ref<APInt(const APFloat &)> mapping) const;
675 
676 protected:
677  /// Iterators to various elements that require out-of-line definition. These
678  /// are hidden from the user to encourage consistent use of the
679  /// getValues/value_begin/value_end API.
681  return IntElementIterator(*this, 0);
682  }
684  return IntElementIterator(*this, getNumElements());
685  }
686  iterator_range_impl<ComplexIntElementIterator> getComplexIntValues() const;
687  ComplexIntElementIterator complex_value_begin() const;
688  ComplexIntElementIterator complex_value_end() const;
689  iterator_range_impl<FloatElementIterator> getFloatValues() const;
690  FloatElementIterator float_value_begin() const;
691  FloatElementIterator float_value_end() const;
693  getComplexFloatValues() const;
694  ComplexFloatElementIterator complex_float_value_begin() const;
695  ComplexFloatElementIterator complex_float_value_end() const;
696 
697  /// Overload of the raw 'get' method that asserts that the given type is of
698  /// complex type. This method is used to verify type invariants that the
699  /// templatized 'get' method cannot.
700  static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data,
701  int64_t dataEltSize, bool isInt,
702  bool isSigned);
703 
704  /// Overload of the raw 'get' method that asserts that the given type is of
705  /// integer or floating-point type. This method is used to verify type
706  /// invariants that the templatized 'get' method cannot.
707  static DenseElementsAttr getRawIntOrFloat(ShapedType type,
708  ArrayRef<char> data,
709  int64_t dataEltSize, bool isInt,
710  bool isSigned);
711 
712  /// Check the information for a C++ data type, check if this type is valid for
713  /// the current attribute. This method is used to verify specific type
714  /// invariants that the templatized 'getValues' method cannot.
715  bool isValidBool() const { return getElementType().isInteger(1); }
716  bool isValidIntOrFloat(int64_t dataEltSize, bool isInt, bool isSigned) const;
717  bool isValidComplex(int64_t dataEltSize, bool isInt, bool isSigned) const;
718 };
719 
720 /// An attribute that represents a reference to a splat vector or tensor
721 /// constant, meaning all of the elements have the same value.
723 public:
724  using DenseElementsAttr::DenseElementsAttr;
725 
726  /// Method for support type inquiry through isa, cast and dyn_cast.
727  static bool classof(Attribute attr) {
728  auto denseAttr = attr.dyn_cast<DenseElementsAttr>();
729  return denseAttr && denseAttr.isSplat();
730  }
731 };
732 } // namespace mlir
733 
734 //===----------------------------------------------------------------------===//
735 // Tablegen Attribute Declarations
736 //===----------------------------------------------------------------------===//
737 
738 #define GET_ATTRDEF_CLASSES
739 #include "mlir/IR/BuiltinAttributes.h.inc"
740 
741 //===----------------------------------------------------------------------===//
742 // C++ Attribute Declarations
743 //===----------------------------------------------------------------------===//
744 
745 namespace mlir {
746 namespace detail {
747 /// Base class for DenseArrayAttr that is instantiated and specialized for each
748 /// supported element type below.
749 template <typename T>
751 public:
752  using DenseArrayBaseAttr::DenseArrayBaseAttr;
753 
754  /// Implicit conversion to ArrayRef<T>.
755  operator ArrayRef<T>() const;
756  ArrayRef<T> asArrayRef() { return ArrayRef<T>{*this}; }
757 
758  /// Builder from ArrayRef<T>.
759  static DenseArrayAttr get(MLIRContext *context, ArrayRef<T> content);
760 
761  /// Print the short form `[42, 100, -1]` without any type prefix.
762  void print(AsmPrinter &printer) const;
763  void print(raw_ostream &os) const;
764  /// Print the short form `42, 100, -1` without any braces or type prefix.
765  void printWithoutBraces(raw_ostream &os) const;
766 
767  /// Parse the short form `[42, 100, -1]` without any type prefix.
768  static Attribute parse(AsmParser &parser, Type odsType);
769 
770  /// Parse the short form `42, 100, -1` without any type prefix or braces.
771  static Attribute parseWithoutBraces(AsmParser &parser, Type odsType);
772 
773  /// Support for isa<>/cast<>.
774  static bool classof(Attribute attr);
775 };
776 template <>
777 void DenseArrayAttr<int8_t>::printWithoutBraces(raw_ostream &os) const;
778 
779 extern template class DenseArrayAttr<int8_t>;
780 extern template class DenseArrayAttr<int16_t>;
781 extern template class DenseArrayAttr<int32_t>;
782 extern template class DenseArrayAttr<int64_t>;
783 extern template class DenseArrayAttr<float>;
784 extern template class DenseArrayAttr<double>;
785 } // namespace detail
786 
787 // Public name for all the supported DenseArrayAttr
794 
795 //===----------------------------------------------------------------------===//
796 // BoolAttr
797 //===----------------------------------------------------------------------===//
798 
799 /// Special case of IntegerAttr to represent boolean integers, i.e., signless i1
800 /// integers.
801 class BoolAttr : public Attribute {
802 public:
803  using Attribute::Attribute;
804  using ValueType = bool;
805 
806  static BoolAttr get(MLIRContext *context, bool value);
807 
808  /// Enable conversion to IntegerAttr. This uses conversion vs. inheritance to
809  /// avoid bringing in all of IntegerAttrs methods.
810  operator IntegerAttr() const { return IntegerAttr(impl); }
811 
812  /// Return the boolean value of this attribute.
813  bool getValue() const;
814 
815  /// Methods for support type inquiry through isa, cast, and dyn_cast.
816  static bool classof(Attribute attr);
817 };
818 
819 //===----------------------------------------------------------------------===//
820 // FlatSymbolRefAttr
821 //===----------------------------------------------------------------------===//
822 
823 /// A symbol reference with a reference path containing a single element. This
824 /// is used to refer to an operation within the current symbol table.
825 class FlatSymbolRefAttr : public SymbolRefAttr {
826 public:
827  using SymbolRefAttr::SymbolRefAttr;
828  using ValueType = StringRef;
829 
830  /// Construct a symbol reference for the given value name.
831  static FlatSymbolRefAttr get(StringAttr value) {
832  return SymbolRefAttr::get(value);
833  }
834  static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value) {
835  return SymbolRefAttr::get(ctx, value);
836  }
837 
838  /// Convenience getter for building a SymbolRefAttr based on an operation
839  /// that implements the SymbolTrait.
840  static FlatSymbolRefAttr get(Operation *symbol) {
841  return SymbolRefAttr::get(symbol);
842  }
843 
844  /// Returns the name of the held symbol reference as a StringAttr.
845  StringAttr getAttr() const { return getRootReference(); }
846 
847  /// Returns the name of the held symbol reference.
848  StringRef getValue() const { return getAttr().getValue(); }
849 
850  /// Methods for support type inquiry through isa, cast, and dyn_cast.
851  static bool classof(Attribute attr) {
852  SymbolRefAttr refAttr = attr.dyn_cast<SymbolRefAttr>();
853  return refAttr && refAttr.getNestedReferences().empty();
854  }
855 
856 private:
857  using SymbolRefAttr::get;
858  using SymbolRefAttr::getNestedReferences;
859 };
860 
861 //===----------------------------------------------------------------------===//
862 // DenseFPElementsAttr
863 //===----------------------------------------------------------------------===//
864 
865 /// An attribute that represents a reference to a dense float vector or tensor
866 /// object. Each element is stored as a double.
868 public:
870 
871  using DenseIntOrFPElementsAttr::DenseIntOrFPElementsAttr;
872 
873  /// Get an instance of a DenseFPElementsAttr with the given arguments. This
874  /// simply wraps the DenseElementsAttr::get calls.
875  template <typename Arg>
876  static DenseFPElementsAttr get(const ShapedType &type, Arg &&arg) {
877  return DenseElementsAttr::get(type, llvm::makeArrayRef(arg))
878  .template cast<DenseFPElementsAttr>();
879  }
880  template <typename T>
881  static DenseFPElementsAttr get(const ShapedType &type,
882  const std::initializer_list<T> &list) {
883  return DenseElementsAttr::get(type, list)
884  .template cast<DenseFPElementsAttr>();
885  }
886 
887  /// Generates a new DenseElementsAttr by mapping each value attribute, and
888  /// constructing the DenseElementsAttr given the new element type.
890  mapValues(Type newElementType,
891  function_ref<APInt(const APFloat &)> mapping) const;
892 
893  /// Iterator access to the float element values.
894  iterator begin() const { return float_value_begin(); }
895  iterator end() const { return float_value_end(); }
896 
897  /// Method for supporting type inquiry through isa, cast and dyn_cast.
898  static bool classof(Attribute attr);
899 };
900 
901 //===----------------------------------------------------------------------===//
902 // DenseIntElementsAttr
903 //===----------------------------------------------------------------------===//
904 
905 /// An attribute that represents a reference to a dense integer vector or tensor
906 /// object.
908 public:
909  /// DenseIntElementsAttr iterates on APInt, so we can use the raw element
910  /// iterator directly.
912 
913  using DenseIntOrFPElementsAttr::DenseIntOrFPElementsAttr;
914 
915  /// Get an instance of a DenseIntElementsAttr with the given arguments. This
916  /// simply wraps the DenseElementsAttr::get calls.
917  template <typename Arg>
918  static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg) {
919  return DenseElementsAttr::get(type, llvm::makeArrayRef(arg))
920  .template cast<DenseIntElementsAttr>();
921  }
922  template <typename T>
923  static DenseIntElementsAttr get(const ShapedType &type,
924  const std::initializer_list<T> &list) {
925  return DenseElementsAttr::get(type, list)
926  .template cast<DenseIntElementsAttr>();
927  }
928 
929  /// Generates a new DenseElementsAttr by mapping each value attribute, and
930  /// constructing the DenseElementsAttr given the new element type.
931  DenseElementsAttr mapValues(Type newElementType,
932  function_ref<APInt(const APInt &)> mapping) const;
933 
934  /// Iterator access to the integer element values.
935  iterator begin() const { return raw_int_begin(); }
936  iterator end() const { return raw_int_end(); }
937 
938  /// Method for supporting type inquiry through isa, cast and dyn_cast.
939  static bool classof(Attribute attr);
940 };
941 
942 //===----------------------------------------------------------------------===//
943 // SparseElementsAttr
944 //===----------------------------------------------------------------------===//
945 
946 template <typename T>
947 auto SparseElementsAttr::value_begin() const -> iterator<T> {
948  auto zeroValue = getZeroValue<T>();
949  auto valueIt = getValues().value_begin<T>();
950  const std::vector<ptrdiff_t> flatSparseIndices(getFlattenedSparseIndices());
951  std::function<T(ptrdiff_t)> mapFn =
952  [flatSparseIndices{flatSparseIndices}, valueIt{std::move(valueIt)},
953  zeroValue{std::move(zeroValue)}](ptrdiff_t index) {
954  // Try to map the current index to one of the sparse indices.
955  for (unsigned i = 0, e = flatSparseIndices.size(); i != e; ++i)
956  if (flatSparseIndices[i] == index)
957  return *std::next(valueIt, i);
958  // Otherwise, return the zero value.
959  return zeroValue;
960  };
961  return iterator<T>(llvm::seq<ptrdiff_t>(0, getNumElements()).begin(), mapFn);
962 }
963 
964 //===----------------------------------------------------------------------===//
965 // StringAttr
966 //===----------------------------------------------------------------------===//
967 
968 /// Define comparisons for StringAttr against nullptr and itself to avoid the
969 /// StringRef overloads from being chosen when not desirable.
970 inline bool operator==(StringAttr lhs, std::nullptr_t) { return !lhs; }
971 inline bool operator!=(StringAttr lhs, std::nullptr_t) {
972  return static_cast<bool>(lhs);
973 }
974 inline bool operator==(StringAttr lhs, StringAttr rhs) {
975  return (Attribute)lhs == (Attribute)rhs;
976 }
977 inline bool operator!=(StringAttr lhs, StringAttr rhs) { return !(lhs == rhs); }
978 
979 /// Allow direct comparison with StringRef.
980 inline bool operator==(StringAttr lhs, StringRef rhs) {
981  return lhs.getValue() == rhs;
982 }
983 inline bool operator!=(StringAttr lhs, StringRef rhs) { return !(lhs == rhs); }
984 inline bool operator==(StringRef lhs, StringAttr rhs) {
985  return rhs.getValue() == lhs;
986 }
987 inline bool operator!=(StringRef lhs, StringAttr rhs) { return !(lhs == rhs); }
988 
989 inline Type StringAttr::getType() const { return Attribute::getType(); }
990 
991 } // namespace mlir
992 
993 //===----------------------------------------------------------------------===//
994 // Attribute Utilities
995 //===----------------------------------------------------------------------===//
996 
997 namespace llvm {
998 
999 template <>
1000 struct DenseMapInfo<mlir::StringAttr> : public DenseMapInfo<mlir::Attribute> {
1001  static mlir::StringAttr getEmptyKey() {
1002  const void *pointer = llvm::DenseMapInfo<const void *>::getEmptyKey();
1003  return mlir::StringAttr::getFromOpaquePointer(pointer);
1004  }
1005  static mlir::StringAttr getTombstoneKey() {
1006  const void *pointer = llvm::DenseMapInfo<const void *>::getTombstoneKey();
1007  return mlir::StringAttr::getFromOpaquePointer(pointer);
1008  }
1009 };
1010 template <>
1011 struct PointerLikeTypeTraits<mlir::StringAttr>
1012  : public PointerLikeTypeTraits<mlir::Attribute> {
1013  static inline mlir::StringAttr getFromVoidPointer(void *p) {
1014  return mlir::StringAttr::getFromOpaquePointer(p);
1015  }
1016 };
1017 
1018 template <>
1019 struct PointerLikeTypeTraits<mlir::SymbolRefAttr>
1020  : public PointerLikeTypeTraits<mlir::Attribute> {
1021  static inline mlir::SymbolRefAttr getFromVoidPointer(void *ptr) {
1022  return mlir::SymbolRefAttr::getFromOpaquePointer(ptr);
1023  }
1024 };
1025 
1026 } // namespace llvm
1027 
1028 #endif // MLIR_IR_BUILTINATTRIBUTES_H
TODO: Remove this file when SCCP and integer range analysis have been ported to the new framework...
void printWithoutBraces(raw_ostream &os) const
Print the short form 42, 100, -1 without any braces or type prefix.
typename std::enable_if<(!std::is_same< T, bool >::value &&std::numeric_limits< T >::is_integer)||is_valid_cpp_fp_type< T >::value >::type IntFloatValueTemplateCheckT
Return the held element values as a range of integer or floating-point values.
An attribute that represents a reference to a dense float vector or tensor object.
U cast() const
Definition: Attributes.h:130
ElementIterator< StringRef > value_begin() const
T mapElement(Attribute attr) const
Map the element to the iterator result type.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:221
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
iterator_range_impl< ElementIterator< T > > getValues() const
typename std::enable_if< std::is_same< T, std::complex< APInt > >::value >::type ComplexAPIntValueTemplateCheckT
Return the held element values as a range of complex APInts.
static bool classof(Attribute attr)
Method for support type inquiry through isa, cast and dyn_cast.
FloatElementIterator value_begin() const
A symbol reference with a reference path containing a single element.
A utility iterator that allows walking over the internal raw APInt values.
FloatElementIterator value_end() const
static bool classof(Attribute attr)
Methods for support type inquiry through isa, cast, and dyn_cast.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
bool isValidBool() const
Check the information for a C++ data type, check if this type is valid for the current attribute...
A utility iterator that allows walking over the internal raw complex APInt values.
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity...
Definition: SPIRVOps.cpp:688
std::enable_if< std::is_base_of< Attribute, T >::value &&!std::is_same< Attribute, T >::value, T >::type getSplatValue() const
Return the splat value for derived attribute element types.
Type trait detector that checks if a given type T is a complex type.
bool operator!=(StringAttr lhs, std::nullptr_t)
static mlir::SymbolRefAttr getFromVoidPointer(void *ptr)
ComplexFloatElementIterator value_begin() const
DerivedAttributeElementIterator< T > value_begin() const
iterator_range_impl< ComplexIntElementIterator > getValues() const
static bool isValidIntOrFloat(Type type, int64_t dataEltSize, bool isInt, bool isSigned)
Check the information for a C++ data type, check if this type is valid for the current attribute...
typename std::enable_if< std::is_same< T, std::complex< APFloat > >::value >::type ComplexAPFloatValueTemplateCheckT
Return the held element values as a range of complex APFloat.
AttributeElementIterator value_end() const
std::complex< APFloat > mapElement(const std::complex< APInt > &value) const
Map the element to the iterator result type.
ElementIterator< T > value_end() const
iterator_range_impl< ElementIterator< StringRef > > getValues() const
static constexpr const bool value
iterator begin() const
Iterator access to the float element values.
ElementIterator< StringRef > value_end() const
A utility iterator that allows walking over the internal bool values.
AttributeElementIterator value_begin() const
typename std::enable_if< std::is_base_of< Attribute, T >::value &&!std::is_same< Attribute, T >::value >::type DerivedAttrValueTemplateCheckT
Return the held element values a range of T, where T is a derived attribute type. ...
constexpr Attribute()
Definition: Attributes.h:36
typename std::enable_if< std::is_same< T, StringRef >::value >::type StringRefValueTemplateCheckT
Return the held element values as a range of StringRef.
typename std::enable_if< std::is_same< T, APInt >::value >::type APIntValueTemplateCheckT
Return the held element values as a range of APInts.
static mlir::StringAttr getFromVoidPointer(void *p)
An attribute that represents a reference to a dense vector or tensor object.
APFloat mapElement(const APInt &value) const
Map the element to the iterator result type.
iterator_range_impl< AttributeElementIterator > getValues() const
iterator_range_impl< ElementIterator< T > > getValues() const
iterator_range_impl< FloatElementIterator > getValues() const
Attributes are known-constant values of operations.
Definition: Attributes.h:24
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
ptrdiff_t getDataIndex() const
Return the current index for this iterator, adjusted for the case of a splat.
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
Iterator for walking over APFloat values.
IntElementIterator raw_int_begin() const
Iterators to various elements that require out-of-line definition.
IntElementIterator raw_int_end() const
iterator_range_impl< BoolElementIterator > getValues() const
ElementIterator< T > value_begin() const
StringRef getValue() const
Returns the name of the held symbol reference.
typename std::enable_if< std::is_same< T, Attribute >::value >::type AttributeValueTemplateCheckT
Return the held element values as a range of Attributes.
const char * getData() const
Return the data base pointer.
ComplexIntElementIterator value_begin() const
IntElementIterator value_end() const
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This base class exposes generic asm parser hooks, usable across the various derived parsers...
iterator_range_impl< IntElementIterator > getValues() const
ElementIterator< T > value_end() const
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
DerivedAttributeElementIterator< T > value_end() const
An attribute that represents a reference to a splat vector or tensor constant, meaning all of the ele...
IntElementIterator value_begin() const
Type getType() const
Return the type of this attribute.
Definition: Attributes.h:66
BoolElementIterator value_end() const
decltype(std::declval< AttrT >().template value_begin< T >()) iterator
The iterator for the given element type T.
decltype(std::declval< AttrT >().template getValues< T >()) iterator_range
The iterator range over the given element T.
U dyn_cast() const
Definition: Attributes.h:124
static int64_t getNumElements(ShapedType type)
Definition: TensorOps.cpp:753
typename std::enable_if< std::is_same< T, APFloat >::value >::type APFloatValueTemplateCheckT
Return the held element values as a range of APFloat.
Iterator for walking raw element values of the specified type &#39;T&#39;, which may be any c++ data type mat...
const T & operator*() const
Accesses the raw value at this iterator position.
ElementIterator< T > value_begin() const
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
int64_t size() const
Returns the number of elements held by this attribute.
typename std::enable_if< detail::is_complex_t< T >::value &&(std::numeric_limits< ElementT >::is_integer||is_valid_cpp_fp_type< ElementT >::value)>::type ComplexValueTemplateCheckT
Return the held element values as a range of std::complex.
This class provides iterator utilities for an ElementsAttr range.
ComplexFloatElementIterator value_end() const
This base class exposes generic asm printer hooks, usable across the various derived printers...
iterator_range_impl< DerivedAttributeElementIterator< T > > getValues() const
Base class for DenseArrayAttr that is instantiated and specialized for each supported element type be...
AffineExpr operator*(int64_t val, AffineExpr expr)
Definition: AffineExpr.h:245
BoolElementIterator value_begin() const
iterator_range_impl< ComplexFloatElementIterator > getValues() const
ComplexIntElementIterator value_end() const
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
Iterator for walking over complex APFloat values.
static mlir::StringAttr getTombstoneKey()
Impl iterator for indexed DenseElementsAttr iterators that records a data pointer and data index that...
std::enable_if<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T >::type getSplatValue() const
Return the splat value for this attribute.
A utility iterator that allows walking over the internal Attribute values of a DenseElementsAttr.
iterator begin() const
Iterator access to the integer element values.
Type trait used to check if the given type T is a potentially valid C++ floating point type that can ...
std::pair< const char *, bool > DenseIterPtrAndSplat
Pair of raw pointer and a boolean flag of whether the pointer holds a splat,.
DenseElementIndexedIteratorImpl(const char *data, bool isSplat, size_t dataIndex)
bool operator==(StringAttr lhs, std::nullptr_t)
Define comparisons for StringAttr against nullptr and itself to avoid the StringRef overloads from be...
bool empty() const
Returns if the number of elements held by this attribute is 0.
An attribute that represents a reference to a dense integer vector or tensor object.
typename std::enable_if< std::is_same< T, bool >::value >::type BoolValueTemplateCheckT
Return the held element values as a range of bool.