MLIR  14.0.0git
OperationSupport.h
Go to the documentation of this file.
1 //===- OperationSupport.h ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a number of support types that Operation and related
10 // classes build on top of.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_IR_OPERATIONSUPPORT_H
15 #define MLIR_IR_OPERATIONSUPPORT_H
16 
17 #include "mlir/IR/BlockSupport.h"
19 #include "mlir/IR/Location.h"
20 #include "mlir/IR/TypeRange.h"
21 #include "mlir/IR/Types.h"
22 #include "mlir/IR/Value.h"
24 #include "llvm/ADT/BitmaskEnum.h"
25 #include "llvm/ADT/PointerUnion.h"
26 #include "llvm/Support/PointerLikeTypeTraits.h"
27 #include "llvm/Support/TrailingObjects.h"
28 #include <memory>
29 
30 namespace llvm {
31 class BitVector;
32 } // namespace llvm
33 
34 namespace mlir {
35 class Dialect;
36 class DictionaryAttr;
37 class ElementsAttr;
38 class MutableOperandRangeRange;
39 class Operation;
40 struct OperationState;
41 class OpAsmParser;
42 class OpAsmParserResult;
43 class OpAsmPrinter;
44 class OperandRange;
45 class OperandRangeRange;
46 class OpFoldResult;
47 class ParseResult;
48 class Pattern;
49 class Region;
50 class ResultRange;
51 class RewritePattern;
52 class Type;
53 class Value;
54 class ValueRange;
55 template <typename ValueRangeT>
56 class ValueTypeRange;
57 
58 class RewritePatternSet;
59 using OwningRewritePatternList = RewritePatternSet;
60 
61 //===----------------------------------------------------------------------===//
62 // OperationName
63 //===----------------------------------------------------------------------===//
64 
66 public:
68  llvm::unique_function<void(RewritePatternSet &, MLIRContext *) const>;
69  using FoldHookFn = llvm::unique_function<LogicalResult(
71  using HasTraitFn = llvm::unique_function<bool(TypeID) const>;
72  using ParseAssemblyFn =
73  llvm::unique_function<ParseResult(OpAsmParser &, OperationState &) const>;
74  using PrintAssemblyFn =
75  llvm::unique_function<void(Operation *, OpAsmPrinter &, StringRef) const>;
76  using VerifyInvariantsFn =
77  llvm::unique_function<LogicalResult(Operation *) const>;
78 
79 protected:
80  /// This class represents a type erased version of an operation. It contains
81  /// all of the components necessary for opaquely interacting with an
82  /// operation. If the operation is not registered, some of these components
83  /// may not be populated.
84  struct Impl {
85  Impl(StringAttr name)
86  : name(name), dialect(nullptr), interfaceMap(llvm::None) {}
87 
88  /// The name of the operation.
89  StringAttr name;
90 
91  //===------------------------------------------------------------------===//
92  // Registered Operation Info
93 
94  /// The following fields are only populated when the operation is
95  /// registered.
96 
97  /// Returns true if the operation has been registered, i.e. if the
98  /// registration info has been populated.
99  bool isRegistered() const { return dialect; }
100 
101  /// This is the dialect that this operation belongs to.
103 
104  /// The unique identifier of the derived Op class.
106 
107  /// A map of interfaces that were registered to this operation.
109 
110  /// Internal callback hooks provided by the op implementation.
117 
118  /// A list of attribute names registered to this operation in StringAttr
119  /// form. This allows for operation classes to use StringAttr for attribute
120  /// lookup/creation/etc., as opposed to raw strings.
122  };
123 
124 public:
125  OperationName(StringRef name, MLIRContext *context);
126 
127  /// Return if this operation is registered.
128  bool isRegistered() const { return impl->isRegistered(); }
129 
130  /// If this operation is registered, returns the registered information, None
131  /// otherwise.
132  Optional<RegisteredOperationName> getRegisteredInfo() const;
133 
134  /// Returns true if the operation was registered with a particular trait, e.g.
135  /// hasTrait<OperandsAreSignlessIntegerLike>(). Returns false if the operation
136  /// is unregistered.
137  template <template <typename T> class Trait> bool hasTrait() const {
138  return hasTrait(TypeID::get<Trait>());
139  }
140  bool hasTrait(TypeID traitID) const {
141  return isRegistered() && impl->hasTraitFn(traitID);
142  }
143 
144  /// Returns true if the operation *might* have the provided trait. This
145  /// means that either the operation is unregistered, or it was registered with
146  /// the provide trait.
147  template <template <typename T> class Trait> bool mightHaveTrait() const {
148  return mightHaveTrait(TypeID::get<Trait>());
149  }
150  bool mightHaveTrait(TypeID traitID) const {
151  return !isRegistered() || impl->hasTraitFn(traitID);
152  }
153 
154  /// Returns an instance of the concept object for the given interface if it
155  /// was registered to this operation, null otherwise. This should not be used
156  /// directly.
157  template <typename T> typename T::Concept *getInterface() const {
158  return impl->interfaceMap.lookup<T>();
159  }
160 
161  /// Returns true if this operation has the given interface registered to it.
162  template <typename T> bool hasInterface() const {
163  return hasInterface(TypeID::get<T>());
164  }
165  bool hasInterface(TypeID interfaceID) const {
166  return impl->interfaceMap.contains(interfaceID);
167  }
168 
169  /// Return the dialect this operation is registered to if the dialect is
170  /// loaded in the context, or nullptr if the dialect isn't loaded.
171  Dialect *getDialect() const {
172  return isRegistered() ? impl->dialect : impl->name.getReferencedDialect();
173  }
174 
175  /// Return the name of the dialect this operation is registered to.
176  StringRef getDialectNamespace() const;
177 
178  /// Return the operation name with dialect name stripped, if it has one.
179  StringRef stripDialect() const { return getStringRef().split('.').second; }
180 
181  /// Return the name of this operation. This always succeeds.
182  StringRef getStringRef() const { return getIdentifier(); }
183 
184  /// Return the name of this operation as a StringAttr.
185  StringAttr getIdentifier() const { return impl->name; }
186 
187  void print(raw_ostream &os) const;
188  void dump() const;
189 
190  /// Represent the operation name as an opaque pointer. (Used to support
191  /// PointerLikeTypeTraits).
192  void *getAsOpaquePointer() const { return const_cast<Impl *>(impl); }
193  static OperationName getFromOpaquePointer(const void *pointer) {
194  return OperationName(
195  const_cast<Impl *>(reinterpret_cast<const Impl *>(pointer)));
196  }
197 
198  bool operator==(const OperationName &rhs) const { return impl == rhs.impl; }
199  bool operator!=(const OperationName &rhs) const { return !(*this == rhs); }
200 
201 protected:
202  OperationName(Impl *impl) : impl(impl) {}
203 
204  /// The internal implementation of the operation name.
206 
207  /// Allow access to the Impl struct.
209 };
210 
211 inline raw_ostream &operator<<(raw_ostream &os, OperationName info) {
212  info.print(os);
213  return os;
214 }
215 
216 // Make operation names hashable.
217 inline llvm::hash_code hash_value(OperationName arg) {
218  return llvm::hash_value(arg.getAsOpaquePointer());
219 }
220 
221 //===----------------------------------------------------------------------===//
222 // RegisteredOperationName
223 //===----------------------------------------------------------------------===//
224 
225 /// This is a "type erased" representation of a registered operation. This
226 /// should only be used by things like the AsmPrinter and other things that need
227 /// to be parameterized by generic operation hooks. Most user code should use
228 /// the concrete operation types.
230 public:
231  /// Lookup the registered operation information for the given operation.
232  /// Returns None if the operation isn't registered.
233  static Optional<RegisteredOperationName> lookup(StringRef name,
234  MLIRContext *ctx);
235 
236  /// Register a new operation in a Dialect object.
237  /// This constructor is used by Dialect objects when they register the list of
238  /// operations they contain.
239  template <typename T>
240  static void insert(Dialect &dialect) {
241  insert(T::getOperationName(), dialect, TypeID::get<T>(),
242  T::getParseAssemblyFn(), T::getPrintAssemblyFn(),
243  T::getVerifyInvariantsFn(), T::getFoldHookFn(),
244  T::getGetCanonicalizationPatternsFn(), T::getInterfaceMap(),
245  T::getHasTraitFn(), T::getAttributeNames());
246  }
247  /// The use of this method is in general discouraged in favor of
248  /// 'insert<CustomOp>(dialect)'.
249  static void
250  insert(StringRef name, Dialect &dialect, TypeID typeID,
251  ParseAssemblyFn &&parseAssembly, PrintAssemblyFn &&printAssembly,
252  VerifyInvariantsFn &&verifyInvariants, FoldHookFn &&foldHook,
253  GetCanonicalizationPatternsFn &&getCanonicalizationPatterns,
254  detail::InterfaceMap &&interfaceMap, HasTraitFn &&hasTrait,
255  ArrayRef<StringRef> attrNames);
256 
257  /// Return the dialect this operation is registered to.
258  Dialect &getDialect() const { return *impl->dialect; }
259 
260  /// Return the unique identifier of the derived Op class.
261  TypeID getTypeID() const { return impl->typeID; }
262 
263  /// Use the specified object to parse this ops custom assembly format.
264  ParseResult parseAssembly(OpAsmParser &parser, OperationState &result) const;
265 
266  /// Return the static hook for parsing this operation assembly.
268  return impl->parseAssemblyFn;
269  }
270 
271  /// This hook implements the AsmPrinter for this operation.
273  StringRef defaultDialect) const {
274  return impl->printAssemblyFn(op, p, defaultDialect);
275  }
276 
277  /// This hook implements the verifier for this operation. It should emits an
278  /// error message and returns failure if a problem is detected, or returns
279  /// success if everything is ok.
281  return impl->verifyInvariantsFn(op);
282  }
283 
284  /// This hook implements a generalized folder for this operation. Operations
285  /// can implement this to provide simplifications rules that are applied by
286  /// the Builder::createOrFold API and the canonicalization pass.
287  ///
288  /// This is an intentionally limited interface - implementations of this hook
289  /// can only perform the following changes to the operation:
290  ///
291  /// 1. They can leave the operation alone and without changing the IR, and
292  /// return failure.
293  /// 2. They can mutate the operation in place, without changing anything else
294  /// in the IR. In this case, return success.
295  /// 3. They can return a list of existing values that can be used instead of
296  /// the operation. In this case, fill in the results list and return
297  /// success. The caller will remove the operation and use those results
298  /// instead.
299  ///
300  /// This allows expression of some simple in-place canonicalizations (e.g.
301  /// "x+0 -> x", "min(x,y,x,z) -> min(x,y,z)", "x+y-x -> y", etc), as well as
302  /// generalized constant folding.
304  SmallVectorImpl<OpFoldResult> &results) const {
305  return impl->foldHookFn(op, operands, results);
306  }
307 
308  /// This hook returns any canonicalization pattern rewrites that the operation
309  /// supports, for use by the canonicalization pass.
311  MLIRContext *context) const {
312  return impl->getCanonicalizationPatternsFn(results, context);
313  }
314 
315  /// Attach the given models as implementations of the corresponding interfaces
316  /// for the concrete operation.
317  template <typename... Models>
319  impl->interfaceMap.insert<Models...>();
320  }
321 
322  /// Returns true if the operation has a particular trait.
323  template <template <typename T> class Trait> bool hasTrait() const {
324  return hasTrait(TypeID::get<Trait>());
325  }
326 
327  /// Returns true if the operation has a particular trait.
328  bool hasTrait(TypeID traitID) const { return impl->hasTraitFn(traitID); }
329 
330  /// Return the list of cached attribute names registered to this operation.
331  /// The order of attributes cached here is unique to each type of operation,
332  /// and the interpretation of this attribute list should generally be driven
333  /// by the respective operation. In many cases, this caching removes the need
334  /// to use the raw string name of a known attribute.
335  ///
336  /// For example the ODS generator, with an op defining the following
337  /// attributes:
338  ///
339  /// let arguments = (ins I32Attr:$attr1, I32Attr:$attr2);
340  ///
341  /// ... may produce an order here of ["attr1", "attr2"]. This allows for the
342  /// ODS generator to directly access the cached name for a known attribute,
343  /// greatly simplifying the cost and complexity of attribute usage produced by
344  /// the generator.
345  ///
347  return impl->attributeNames;
348  }
349 
350  /// Represent the operation name as an opaque pointer. (Used to support
351  /// PointerLikeTypeTraits).
352  static RegisteredOperationName getFromOpaquePointer(const void *pointer) {
354  const_cast<Impl *>(reinterpret_cast<const Impl *>(pointer)));
355  }
356 
357 private:
359 
360  /// Allow access to the constructor.
361  friend OperationName;
362 };
363 
365 OperationName::getRegisteredInfo() const {
366  return isRegistered() ? RegisteredOperationName(impl)
368 }
369 
370 //===----------------------------------------------------------------------===//
371 // Attribute Dictionary-Like Interface
372 //===----------------------------------------------------------------------===//
373 
374 /// Attribute collections provide a dictionary-like interface. Define common
375 /// lookup functions.
376 namespace impl {
377 
378 /// Unsorted string search or identifier lookups are linear scans.
379 template <typename IteratorT, typename NameT>
380 std::pair<IteratorT, bool> findAttrUnsorted(IteratorT first, IteratorT last,
381  NameT name) {
382  for (auto it = first; it != last; ++it)
383  if (it->getName() == name)
384  return {it, true};
385  return {last, false};
386 }
387 
388 /// Using llvm::lower_bound requires an extra string comparison to check whether
389 /// the returned iterator points to the found element or whether it indicates
390 /// the lower bound. Skip this redundant comparison by checking if `compare ==
391 /// 0` during the binary search.
392 template <typename IteratorT>
393 std::pair<IteratorT, bool> findAttrSorted(IteratorT first, IteratorT last,
394  StringRef name) {
395  ptrdiff_t length = std::distance(first, last);
396 
397  while (length > 0) {
398  ptrdiff_t half = length / 2;
399  IteratorT mid = first + half;
400  int compare = mid->getName().strref().compare(name);
401  if (compare < 0) {
402  first = mid + 1;
403  length = length - half - 1;
404  } else if (compare > 0) {
405  length = half;
406  } else {
407  return {mid, true};
408  }
409  }
410  return {first, false};
411 }
412 
413 /// StringAttr lookups on large attribute lists will switch to string binary
414 /// search. String binary searches become significantly faster than linear scans
415 /// with the identifier when the attribute list becomes very large.
416 template <typename IteratorT>
417 std::pair<IteratorT, bool> findAttrSorted(IteratorT first, IteratorT last,
418  StringAttr name) {
419  constexpr unsigned kSmallAttributeList = 16;
420  if (std::distance(first, last) > kSmallAttributeList)
421  return findAttrSorted(first, last, name.strref());
422  return findAttrUnsorted(first, last, name);
423 }
424 
425 } // namespace impl
426 
427 //===----------------------------------------------------------------------===//
428 // NamedAttrList
429 //===----------------------------------------------------------------------===//
430 
431 /// NamedAttrList is array of NamedAttributes that tracks whether it is sorted
432 /// and does some basic work to remain sorted.
434 public:
439  using size_type = size_t;
440 
441  NamedAttrList() : dictionarySorted({}, true) {}
443  NamedAttrList(DictionaryAttr attributes);
444  NamedAttrList(const_iterator in_start, const_iterator in_end);
445 
446  bool operator!=(const NamedAttrList &other) const {
447  return !(*this == other);
448  }
449  bool operator==(const NamedAttrList &other) const {
450  return attrs == other.attrs;
451  }
452 
453  /// Add an attribute with the specified name.
454  void append(StringRef name, Attribute attr);
455 
456  /// Add an attribute with the specified name.
457  void append(StringAttr name, Attribute attr) {
458  append(NamedAttribute(name, attr));
459  }
460 
461  /// Append the given named attribute.
462  void append(NamedAttribute attr) { push_back(attr); }
463 
464  /// Add an array of named attributes.
465  template <typename RangeT>
466  void append(RangeT &&newAttributes) {
467  append(std::begin(newAttributes), std::end(newAttributes));
468  }
469 
470  /// Add a range of named attributes.
471  template <typename IteratorT>
472  void append(IteratorT in_start, IteratorT in_end) {
473  // TODO: expand to handle case where values appended are in order & after
474  // end of current list.
475  dictionarySorted.setPointerAndInt(nullptr, false);
476  attrs.append(in_start, in_end);
477  }
478 
479  /// Replaces the attributes with new list of attributes.
480  void assign(const_iterator in_start, const_iterator in_end);
481 
482  /// Replaces the attributes with new list of attributes.
484  assign(range.begin(), range.end());
485  }
486 
487  bool empty() const { return attrs.empty(); }
488 
489  void reserve(size_type N) { attrs.reserve(N); }
490 
491  /// Add an attribute with the specified name.
492  void push_back(NamedAttribute newAttribute);
493 
494  /// Pop last element from list.
495  void pop_back() { attrs.pop_back(); }
496 
497  /// Returns an entry with a duplicate name the list, if it exists, else
498  /// returns llvm::None.
499  Optional<NamedAttribute> findDuplicate() const;
500 
501  /// Return a dictionary attribute for the underlying dictionary. This will
502  /// return an empty dictionary attribute if empty rather than null.
503  DictionaryAttr getDictionary(MLIRContext *context) const;
504 
505  /// Return all of the attributes on this operation.
506  ArrayRef<NamedAttribute> getAttrs() const;
507 
508  /// Return the specified attribute if present, null otherwise.
509  Attribute get(StringAttr name) const;
510  Attribute get(StringRef name) const;
511 
512  /// Return the specified named attribute if present, None otherwise.
513  Optional<NamedAttribute> getNamed(StringRef name) const;
514  Optional<NamedAttribute> getNamed(StringAttr name) const;
515 
516  /// If the an attribute exists with the specified name, change it to the new
517  /// value. Otherwise, add a new attribute with the specified name/value.
518  /// Returns the previous attribute value of `name`, or null if no
519  /// attribute previously existed with `name`.
520  Attribute set(StringAttr name, Attribute value);
521  Attribute set(StringRef name, Attribute value);
522 
523  /// Erase the attribute with the given name from the list. Return the
524  /// attribute that was erased, or nullptr if there was no attribute with such
525  /// name.
526  Attribute erase(StringAttr name);
527  Attribute erase(StringRef name);
528 
529  iterator begin() { return attrs.begin(); }
530  iterator end() { return attrs.end(); }
531  const_iterator begin() const { return attrs.begin(); }
532  const_iterator end() const { return attrs.end(); }
533 
534  NamedAttrList &operator=(const SmallVectorImpl<NamedAttribute> &rhs);
535  operator ArrayRef<NamedAttribute>() const;
536 
537 private:
538  /// Return whether the attributes are sorted.
539  bool isSorted() const { return dictionarySorted.getInt(); }
540 
541  /// Erase the attribute at the given iterator position.
543 
544  /// Lookup an attribute in the list.
545  template <typename AttrListT, typename NameT>
546  static auto findAttr(AttrListT &attrs, NameT name) {
547  return attrs.isSorted()
548  ? impl::findAttrSorted(attrs.begin(), attrs.end(), name)
549  : impl::findAttrUnsorted(attrs.begin(), attrs.end(), name);
550  }
551 
552  // These are marked mutable as they may be modified (e.g., sorted)
553  mutable SmallVector<NamedAttribute, 4> attrs;
554  // Pair with cached DictionaryAttr and status of whether attrs is sorted.
555  // Note: just because sorted does not mean a DictionaryAttr has been created
556  // but the case where there is a DictionaryAttr but attrs isn't sorted should
557  // not occur.
558  mutable llvm::PointerIntPair<Attribute, 1, bool> dictionarySorted;
559 };
560 
561 //===----------------------------------------------------------------------===//
562 // OperationState
563 //===----------------------------------------------------------------------===//
564 
565 /// This represents an operation in an abstracted form, suitable for use with
566 /// the builder APIs. This object is a large and heavy weight object meant to
567 /// be used as a temporary object on the stack. It is generally unwise to put
568 /// this in a collection.
573  /// Types of the results of this operation.
576  /// Successors of this operation and their respective operands.
578  /// Regions that the op will hold.
580 
581 public:
582  OperationState(Location location, StringRef name);
583  OperationState(Location location, OperationName name);
584 
585  OperationState(Location location, OperationName name, ValueRange operands,
586  TypeRange types, ArrayRef<NamedAttribute> attributes,
587  BlockRange successors = {},
589  OperationState(Location location, StringRef name, ValueRange operands,
590  TypeRange types, ArrayRef<NamedAttribute> attributes,
591  BlockRange successors = {},
593 
594  void addOperands(ValueRange newOperands);
595 
596  void addTypes(ArrayRef<Type> newTypes) {
597  types.append(newTypes.begin(), newTypes.end());
598  }
599  template <typename RangeT>
600  std::enable_if_t<!std::is_convertible<RangeT, ArrayRef<Type>>::value>
601  addTypes(RangeT &&newTypes) {
602  types.append(newTypes.begin(), newTypes.end());
603  }
604 
605  /// Add an attribute with the specified name.
606  void addAttribute(StringRef name, Attribute attr) {
607  addAttribute(StringAttr::get(getContext(), name), attr);
608  }
609 
610  /// Add an attribute with the specified name.
611  void addAttribute(StringAttr name, Attribute attr) {
612  attributes.append(name, attr);
613  }
614 
615  /// Add an array of named attributes.
617  attributes.append(newAttributes);
618  }
619 
620  void addSuccessors(Block *successor) { successors.push_back(successor); }
621  void addSuccessors(BlockRange newSuccessors);
622 
623  /// Create a region that should be attached to the operation. These regions
624  /// can be filled in immediately without waiting for Operation to be
625  /// created. When it is, the region bodies will be transferred.
626  Region *addRegion();
627 
628  /// Take a region that should be attached to the Operation. The body of the
629  /// region will be transferred when the Operation is constructed. If the
630  /// region is null, a new empty region will be attached to the Operation.
631  void addRegion(std::unique_ptr<Region> &&region);
632 
633  /// Take ownership of a set of regions that should be attached to the
634  /// Operation.
635  void addRegions(MutableArrayRef<std::unique_ptr<Region>> regions);
636 
637  /// Get the context held by this operation state.
638  MLIRContext *getContext() const { return location->getContext(); }
639 };
640 
641 //===----------------------------------------------------------------------===//
642 // OperandStorage
643 //===----------------------------------------------------------------------===//
644 
645 namespace detail {
646 /// This class handles the management of operation operands. Operands are
647 /// stored either in a trailing array, or a dynamically resizable vector.
648 class alignas(8) OperandStorage {
649 public:
650  OperandStorage(Operation *owner, OpOperand *trailingOperands,
651  ValueRange values);
652  ~OperandStorage();
653 
654  /// Replace the operands contained in the storage with the ones provided in
655  /// 'values'.
656  void setOperands(Operation *owner, ValueRange values);
657 
658  /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
659  /// with the ones provided in 'operands'. 'operands' may be smaller or larger
660  /// than the range pointed to by 'start'+'length'.
661  void setOperands(Operation *owner, unsigned start, unsigned length,
662  ValueRange operands);
663 
664  /// Erase the operands held by the storage within the given range.
665  void eraseOperands(unsigned start, unsigned length);
666 
667  /// Erase the operands held by the storage that have their corresponding bit
668  /// set in `eraseIndices`.
669  void eraseOperands(const llvm::BitVector &eraseIndices);
670 
671  /// Get the operation operands held by the storage.
672  MutableArrayRef<OpOperand> getOperands() { return {operandStorage, size()}; }
673 
674  /// Return the number of operands held in the storage.
675  unsigned size() { return numOperands; }
676 
677 private:
678  /// Resize the storage to the given size. Returns the array containing the new
679  /// operands.
680  MutableArrayRef<OpOperand> resize(Operation *owner, unsigned newSize);
681 
682  /// The total capacity number of operands that the storage can hold.
683  unsigned capacity : 31;
684  /// A flag indicating if the operand storage was dynamically allocated, as
685  /// opposed to inlined into the owning operation.
686  unsigned isStorageDynamic : 1;
687  /// The number of operands within the storage.
688  unsigned numOperands;
689  /// A pointer to the operand storage.
690  OpOperand *operandStorage;
691 };
692 } // namespace detail
693 
694 //===----------------------------------------------------------------------===//
695 // OpPrintingFlags
696 //===----------------------------------------------------------------------===//
697 
698 /// Set of flags used to control the behavior of the various IR print methods
699 /// (e.g. Operation::Print).
701 public:
702  OpPrintingFlags();
703  OpPrintingFlags(llvm::NoneType) : OpPrintingFlags() {}
704 
705  /// Enables the elision of large elements attributes by printing a lexically
706  /// valid but otherwise meaningless form instead of the element data. The
707  /// `largeElementLimit` is used to configure what is considered to be a
708  /// "large" ElementsAttr by providing an upper limit to the number of
709  /// elements.
710  OpPrintingFlags &elideLargeElementsAttrs(int64_t largeElementLimit = 16);
711 
712  /// Enable printing of debug information. If 'prettyForm' is set to true,
713  /// debug information is printed in a more readable 'pretty' form. Note: The
714  /// IR generated with 'prettyForm' is not parsable.
715  OpPrintingFlags &enableDebugInfo(bool prettyForm = false);
716 
717  /// Always print operations in the generic form.
718  OpPrintingFlags &printGenericOpForm();
719 
720  /// Use local scope when printing the operation. This allows for using the
721  /// printer in a more localized and thread-safe setting, but may not
722  /// necessarily be identical to what the IR will look like when dumping
723  /// the full module.
724  OpPrintingFlags &useLocalScope();
725 
726  /// Return if the given ElementsAttr should be elided.
727  bool shouldElideElementsAttr(ElementsAttr attr) const;
728 
729  /// Return the size limit for printing large ElementsAttr.
730  Optional<int64_t> getLargeElementsAttrLimit() const;
731 
732  /// Return if debug information should be printed.
733  bool shouldPrintDebugInfo() const;
734 
735  /// Return if debug information should be printed in the pretty form.
736  bool shouldPrintDebugInfoPrettyForm() const;
737 
738  /// Return if operations should be printed in the generic form.
739  bool shouldPrintGenericOpForm() const;
740 
741  /// Return if the printer should use local scope when dumping the IR.
742  bool shouldUseLocalScope() const;
743 
744 private:
745  /// Elide large elements attributes if the number of elements is larger than
746  /// the upper limit.
747  Optional<int64_t> elementsAttrElementLimit;
748 
749  /// Print debug information.
750  bool printDebugInfoFlag : 1;
751  bool printDebugInfoPrettyFormFlag : 1;
752 
753  /// Print operations in the generic form.
754  bool printGenericOpFormFlag : 1;
755 
756  /// Print operations with numberings local to the current operation.
757  bool printLocalScope : 1;
758 };
759 
760 //===----------------------------------------------------------------------===//
761 // Operation Value-Iterators
762 //===----------------------------------------------------------------------===//
763 
764 //===----------------------------------------------------------------------===//
765 // OperandRange
766 
767 /// This class implements the operand iterators for the Operation class.
769  OperandRange, OpOperand *, Value, Value, Value> {
770 public:
771  using RangeBaseT::RangeBaseT;
772 
773  /// Returns the types of the values within this range.
776  type_range getTypes() const { return {begin(), end()}; }
777  auto getType() const { return getTypes(); }
778 
779  /// Return the operand index of the first element of this range. The range
780  /// must not be empty.
781  unsigned getBeginOperandIndex() const;
782 
783  /// Split this range into a set of contiguous subranges using the given
784  /// elements attribute, which contains the sizes of the sub ranges.
785  OperandRangeRange split(ElementsAttr segmentSizes) const;
786 
787 private:
788  /// See `llvm::detail::indexed_accessor_range_base` for details.
789  static OpOperand *offset_base(OpOperand *object, ptrdiff_t index) {
790  return object + index;
791  }
792  /// See `llvm::detail::indexed_accessor_range_base` for details.
793  static Value dereference_iterator(OpOperand *object, ptrdiff_t index) {
794  return object[index].get();
795  }
796 
797  /// Allow access to `offset_base` and `dereference_iterator`.
798  friend RangeBaseT;
799 };
800 
801 //===----------------------------------------------------------------------===//
802 // OperandRangeRange
803 
804 /// This class represents a contiguous range of operand ranges, e.g. from a
805 /// VariadicOfVariadic operand group.
806 class OperandRangeRange final
807  : public llvm::indexed_accessor_range<
808  OperandRangeRange, std::pair<OpOperand *, Attribute>, OperandRange,
809  OperandRange, OperandRange> {
810  using OwnerT = std::pair<OpOperand *, Attribute>;
811  using RangeBaseT =
812  llvm::indexed_accessor_range<OperandRangeRange, OwnerT, OperandRange,
813  OperandRange, OperandRange>;
814 
815 public:
816  using RangeBaseT::RangeBaseT;
817 
818  /// Returns the range of types of the values within this range.
819  TypeRangeRange getTypes() const { return TypeRangeRange(*this); }
820  auto getType() const { return getTypes(); }
821 
822  /// Construct a range given a parent set of operands, and an I32 elements
823  /// attribute containing the sizes of the sub ranges.
824  OperandRangeRange(OperandRange operands, Attribute operandSegments);
825 
826  /// Flatten all of the sub ranges into a single contiguous operand range.
827  OperandRange join() const;
828 
829 private:
830  /// See `llvm::indexed_accessor_range` for details.
831  static OperandRange dereference(const OwnerT &object, ptrdiff_t index);
832 
833  /// Allow access to `dereference_iterator`.
834  friend RangeBaseT;
835 };
836 
837 //===----------------------------------------------------------------------===//
838 // MutableOperandRange
839 
840 /// This class provides a mutable adaptor for a range of operands. It allows for
841 /// setting, inserting, and erasing operands from the given range.
843 public:
844  /// A pair of a named attribute corresponding to an operand segment attribute,
845  /// and the index within that attribute. The attribute should correspond to an
846  /// i32 DenseElementsAttr.
847  using OperandSegment = std::pair<unsigned, NamedAttribute>;
848 
849  /// Construct a new mutable range from the given operand, operand start index,
850  /// and range length. `operandSegments` is an optional set of operand segments
851  /// to be updated when mutating the operand list.
852  MutableOperandRange(Operation *owner, unsigned start, unsigned length,
853  ArrayRef<OperandSegment> operandSegments = llvm::None);
855 
856  /// Slice this range into a sub range, with the additional operand segment.
858  slice(unsigned subStart, unsigned subLen,
859  Optional<OperandSegment> segment = llvm::None) const;
860 
861  /// Append the given values to the range.
862  void append(ValueRange values);
863 
864  /// Assign this range to the given values.
865  void assign(ValueRange values);
866 
867  /// Assign the range to the given value.
868  void assign(Value value);
869 
870  /// Erase the operands within the given sub-range.
871  void erase(unsigned subStart, unsigned subLen = 1);
872 
873  /// Clear this range and erase all of the operands.
874  void clear();
875 
876  /// Returns the current size of the range.
877  unsigned size() const { return length; }
878 
879  /// Returns if the current range is empty.
880  bool empty() const { return size() == 0; }
881 
882  /// Allow implicit conversion to an OperandRange.
883  operator OperandRange() const;
884 
885  /// Returns the owning operation.
886  Operation *getOwner() const { return owner; }
887 
888  /// Split this range into a set of contiguous subranges using the given
889  /// elements attribute, which contains the sizes of the sub ranges.
890  MutableOperandRangeRange split(NamedAttribute segmentSizes) const;
891 
892 private:
893  /// Update the length of this range to the one provided.
894  void updateLength(unsigned newLength);
895 
896  /// The owning operation of this range.
897  Operation *owner;
898 
899  /// The start index of the operand range within the owner operand list, and
900  /// the length starting from `start`.
901  unsigned start, length;
902 
903  /// Optional set of operand segments that should be updated when mutating the
904  /// length of this range.
905  SmallVector<OperandSegment, 1> operandSegments;
906 };
907 
908 //===----------------------------------------------------------------------===//
909 // MutableOperandRangeRange
910 
911 /// This class represents a contiguous range of mutable operand ranges, e.g.
912 /// from a VariadicOfVariadic operand group.
914  : public llvm::indexed_accessor_range<
915  MutableOperandRangeRange,
916  std::pair<MutableOperandRange, NamedAttribute>, MutableOperandRange,
917  MutableOperandRange, MutableOperandRange> {
918  using OwnerT = std::pair<MutableOperandRange, NamedAttribute>;
919  using RangeBaseT =
920  llvm::indexed_accessor_range<MutableOperandRangeRange, OwnerT,
921  MutableOperandRange, MutableOperandRange,
922  MutableOperandRange>;
923 
924 public:
925  using RangeBaseT::RangeBaseT;
926 
927  /// Construct a range given a parent set of operands, and an I32 tensor
928  /// elements attribute containing the sizes of the sub ranges.
929  MutableOperandRangeRange(const MutableOperandRange &operands,
930  NamedAttribute operandSegmentAttr);
931 
932  /// Flatten all of the sub ranges into a single contiguous mutable operand
933  /// range.
934  MutableOperandRange join() const;
935 
936  /// Allow implicit conversion to an OperandRangeRange.
937  operator OperandRangeRange() const;
938 
939 private:
940  /// See `llvm::indexed_accessor_range` for details.
941  static MutableOperandRange dereference(const OwnerT &object, ptrdiff_t index);
942 
943  /// Allow access to `dereference_iterator`.
944  friend RangeBaseT;
945 };
946 
947 //===----------------------------------------------------------------------===//
948 // ResultRange
949 
950 /// This class implements the result iterators for the Operation class.
951 class ResultRange final
953  ResultRange, detail::OpResultImpl *, OpResult, OpResult, OpResult> {
954 public:
955  using RangeBaseT::RangeBaseT;
956  ResultRange(OpResult result);
957 
958  //===--------------------------------------------------------------------===//
959  // Types
960  //===--------------------------------------------------------------------===//
961 
962  /// Returns the types of the values within this range.
965  type_range getTypes() const { return {begin(), end()}; }
966  auto getType() const { return getTypes(); }
967 
968  //===--------------------------------------------------------------------===//
969  // Uses
970  //===--------------------------------------------------------------------===//
971 
972  class UseIterator;
975 
976  /// Returns a range of all uses of results within this range, which is useful
977  /// for iterating over all uses.
978  use_range getUses() const;
979  use_iterator use_begin() const;
980  use_iterator use_end() const;
981 
982  /// Returns true if no results in this range have uses.
983  bool use_empty() const {
984  return llvm::all_of(*this,
985  [](OpResult result) { return result.use_empty(); });
986  }
987 
988  /// Replace all uses of results of this range with the provided 'values'. The
989  /// size of `values` must match the size of this range.
990  template <typename ValuesT>
992  replaceAllUsesWith(ValuesT &&values) {
993  assert(static_cast<size_t>(std::distance(values.begin(), values.end())) ==
994  size() &&
995  "expected 'values' to correspond 1-1 with the number of results");
996 
997  for (auto it : llvm::zip(*this, values))
998  std::get<0>(it).replaceAllUsesWith(std::get<1>(it));
999  }
1000 
1001  /// Replace all uses of results of this range with results of 'op'.
1002  void replaceAllUsesWith(Operation *op);
1003 
1004  //===--------------------------------------------------------------------===//
1005  // Users
1006  //===--------------------------------------------------------------------===//
1007 
1010 
1011  /// Returns a range of all users.
1012  user_range getUsers();
1013  user_iterator user_begin();
1014  user_iterator user_end();
1015 
1016 private:
1017  /// See `llvm::detail::indexed_accessor_range_base` for details.
1018  static detail::OpResultImpl *offset_base(detail::OpResultImpl *object,
1019  ptrdiff_t index) {
1020  return object->getNextResultAtOffset(index);
1021  }
1022  /// See `llvm::detail::indexed_accessor_range_base` for details.
1023  static OpResult dereference_iterator(detail::OpResultImpl *object,
1024  ptrdiff_t index) {
1025  return offset_base(object, index);
1026  }
1027 
1028  /// Allow access to `offset_base` and `dereference_iterator`.
1029  friend RangeBaseT;
1030 };
1031 
1032 /// This class implements a use iterator for a range of operation results.
1033 /// This iterates over all uses of all results within the given result range.
1035  : public llvm::iterator_facade_base<UseIterator, std::forward_iterator_tag,
1036  OpOperand> {
1037 public:
1038  /// Initialize the UseIterator. Specify `end` to return iterator to last
1039  /// use, otherwise this is an iterator to the first use.
1040  explicit UseIterator(ResultRange results, bool end = false);
1041 
1042  using llvm::iterator_facade_base<UseIterator, std::forward_iterator_tag,
1043  OpOperand>::operator++;
1044  UseIterator &operator++();
1045  OpOperand *operator->() const { return use.getOperand(); }
1046  OpOperand &operator*() const { return *use.getOperand(); }
1047 
1048  bool operator==(const UseIterator &rhs) const { return use == rhs.use; }
1049  bool operator!=(const UseIterator &rhs) const { return !(*this == rhs); }
1050 
1051 private:
1052  void skipOverResultsWithNoUsers();
1053 
1054  /// The range of results being iterated over.
1055  ResultRange::iterator it, endIt;
1056  /// The use of the result.
1057  Value::use_iterator use;
1058 };
1059 
1060 //===----------------------------------------------------------------------===//
1061 // ValueRange
1062 
1063 /// This class provides an abstraction over the different types of ranges over
1064 /// Values. In many cases, this prevents the need to explicitly materialize a
1065 /// SmallVector/std::vector. This class should be used in places that are not
1066 /// suitable for a more derived type (e.g. ArrayRef) or a template range
1067 /// parameter.
1068 class ValueRange final
1070  ValueRange,
1071  PointerUnion<const Value *, OpOperand *, detail::OpResultImpl *>,
1072  Value, Value, Value> {
1073 public:
1074  /// The type representing the owner of a ValueRange. This is either a list of
1075  /// values, operands, or results.
1076  using OwnerT =
1078 
1079  using RangeBaseT::RangeBaseT;
1080 
1081  template <typename Arg,
1082  typename = typename std::enable_if_t<
1083  std::is_constructible<ArrayRef<Value>, Arg>::value &&
1085  ValueRange(Arg &&arg) : ValueRange(ArrayRef<Value>(std::forward<Arg>(arg))) {}
1086  ValueRange(const Value &value) : ValueRange(&value, /*count=*/1) {}
1087  ValueRange(const std::initializer_list<Value> &values)
1088  : ValueRange(ArrayRef<Value>(values)) {}
1090  : ValueRange(OperandRange(values)) {}
1092  : ValueRange(ResultRange(values)) {}
1094  : ValueRange(ArrayRef<Value>(values.data(), values.size())) {}
1095  ValueRange(ArrayRef<Value> values = llvm::None);
1096  ValueRange(OperandRange values);
1097  ValueRange(ResultRange values);
1098 
1099  /// Returns the types of the values within this range.
1102  type_range getTypes() const { return {begin(), end()}; }
1103  auto getType() const { return getTypes(); }
1104 
1105 private:
1106  /// See `llvm::detail::indexed_accessor_range_base` for details.
1107  static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
1108  /// See `llvm::detail::indexed_accessor_range_base` for details.
1109  static Value dereference_iterator(const OwnerT &owner, ptrdiff_t index);
1110 
1111  /// Allow access to `offset_base` and `dereference_iterator`.
1112  friend RangeBaseT;
1113 };
1114 
1115 //===----------------------------------------------------------------------===//
1116 // Operation Equivalency
1117 //===----------------------------------------------------------------------===//
1118 
1119 /// This class provides utilities for computing if two operations are
1120 /// equivalent.
1122  enum Flags {
1123  None = 0,
1124 
1125  // When provided, the location attached to the operation are ignored.
1126  IgnoreLocations = 1,
1127 
1128  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IgnoreLocations)
1129  };
1130 
1131  /// Compute a hash for the given operation.
1132  /// The `hashOperands` and `hashResults` callbacks are expected to return a
1133  /// unique hash_code for a given Value.
1134  static llvm::hash_code computeHash(
1135  Operation *op,
1136  function_ref<llvm::hash_code(Value)> hashOperands =
1137  [](Value v) { return hash_value(v); },
1139  [](Value v) { return hash_value(v); },
1140  Flags flags = Flags::None);
1141 
1142  /// Helper that can be used with `computeHash` above to ignore operation
1143  /// operands/result mapping.
1144  static llvm::hash_code ignoreHashValue(Value) { return llvm::hash_code{}; }
1145  /// Helper that can be used with `computeHash` above to ignore operation
1146  /// operands/result mapping.
1147  static llvm::hash_code directHashValue(Value v) { return hash_value(v); }
1148 
1149  /// Compare two operations and return if they are equivalent.
1150  /// `mapOperands` and `mapResults` are optional callbacks that allows the
1151  /// caller to check the mapping of SSA value between the lhs and rhs
1152  /// operations. It is expected to return success if the mapping is valid and
1153  /// failure if it conflicts with a previous mapping.
1154  static bool
1155  isEquivalentTo(Operation *lhs, Operation *rhs,
1156  function_ref<LogicalResult(Value, Value)> mapOperands,
1157  function_ref<LogicalResult(Value, Value)> mapResults,
1158  Flags flags = Flags::None);
1159 
1160  /// Helper that can be used with `isEquivalentTo` above to ignore operation
1161  /// operands/result mapping.
1163  return success();
1164  }
1165  /// Helper that can be used with `isEquivalentTo` above to ignore operation
1166  /// operands/result mapping.
1168  return success(lhs == rhs);
1169  }
1170 };
1171 
1172 /// Enable Bitmask enums for OperationEquivalence::Flags.
1174 
1175 } // namespace mlir
1176 
1177 namespace llvm {
1178 template <>
1179 struct DenseMapInfo<mlir::OperationName> {
1181  void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
1183  }
1187  }
1188  static unsigned getHashValue(mlir::OperationName val) {
1190  }
1192  return lhs == rhs;
1193  }
1194 };
1195 template <>
1196 struct DenseMapInfo<mlir::RegisteredOperationName>
1197  : public DenseMapInfo<mlir::OperationName> {
1199  void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
1201  }
1205  }
1206 };
1207 
1208 template <>
1209 struct PointerLikeTypeTraits<mlir::OperationName> {
1210  static inline void *getAsVoidPointer(mlir::OperationName I) {
1211  return const_cast<void *>(I.getAsOpaquePointer());
1212  }
1213  static inline mlir::OperationName getFromVoidPointer(void *P) {
1215  }
1216  static constexpr int NumLowBitsAvailable =
1217  PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
1218 };
1219 template <>
1220 struct PointerLikeTypeTraits<mlir::RegisteredOperationName>
1221  : public PointerLikeTypeTraits<mlir::OperationName> {
1224  }
1225 };
1226 
1227 } // namespace llvm
1228 
1229 #endif
bool use_empty() const
Returns true if no results in this range have uses.
Include the generated interface declarations.
static unsigned getHashValue(mlir::OperationName val)
void append(IteratorT in_start, IteratorT in_end)
Add a range of named attributes.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
This class provides an abstraction for a range of TypeRange.
Definition: TypeRange.h:102
ValueRange(const Value &value)
void print(raw_ostream &os) const
Definition: AsmPrinter.cpp:49
StringRef stripDialect() const
Return the operation name with dialect name stripped, if it has one.
bool isRegistered() const
Return if this operation is registered.
FoldHookFn foldHookFn
Internal callback hooks provided by the op implementation.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
bool hasTrait() const
Returns true if the operation has a particular trait.
SmallVector< Block *, 1 > successors
Successors of this operation and their respective operands.
const_iterator begin() const
static mlir::OperationName getEmptyKey()
void * getAsOpaquePointer() const
Represent the operation name as an opaque pointer.
This is a value defined by a result of an operation.
Definition: Value.h:423
bool operator==(const UseIterator &rhs) const
Block represents an ordered list of Operations.
Definition: Block.h:29
SmallVectorImpl< NamedAttribute >::const_iterator const_iterator
void reserve(size_type N)
OpResultImpl * getNextResultAtOffset(intptr_t offset)
Returns the next operation result at offset after this result.
Definition: Value.cpp:130
StringAttr getIdentifier() const
Return the name of this operation as a StringAttr.
bool hasInterface() const
Returns true if this operation has the given interface registered to it.
void print(OpAsmPrinter &p, FunctionLibraryOp op)
Definition: Shape.cpp:1111
GetCanonicalizationPatternsFn getCanonicalizationPatternsFn
This class implements the result iterators for the Operation class.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
Enable Bitmask enums for OperationEquivalence::Flags.
type_range getTypes() const
T::Concept * getInterface() const
Returns an instance of the concept object for the given interface if it was registered to this operat...
An iterator over the users of an IRObject.
Definition: UseDefLists.h:25
The OpAsmParser has methods for interacting with the asm parser: parsing things from it...
bool mightHaveTrait(TypeID traitID) const
static mlir::RegisteredOperationName getEmptyKey()
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &) const > ParseAssemblyFn
static constexpr const bool value
bool hasInterface(TypeID interfaceID) const
SmallVector< Value, 4 > operands
bool operator==(const OperationName &rhs) const
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:52
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
void getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) const
This hook returns any canonicalization pattern rewrites that the operation supports, for use by the canonicalization pass.
static OperationName getFromOpaquePointer(const void *pointer)
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:137
bool hasTrait() const
Returns true if the operation was registered with a particular trait, e.g.
Operation * getOwner() const
Returns the owning operation.
This class provides utilities for computing if two operations are equivalent.
std::enable_if_t<!std::is_convertible< ValuesT, Operation * >::value > replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this range with the provided &#39;values&#39;.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:126
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
This class represents a contiguous range of mutable operand ranges, e.g.
This class provides an efficient mapping between a given Interface type, and a particular implementat...
llvm::unique_function< LogicalResult(Operation *) const > VerifyInvariantsFn
static mlir::OperationName getFromVoidPointer(void *P)
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:20
static void * getAsVoidPointer(mlir::OperationName I)
llvm::unique_function< void(Operation *, OpAsmPrinter &, StringRef) const > PrintAssemblyFn
MappingLevel & operator++(MappingLevel &mappingLevel)
Bounded increment on MappingLevel.
const_iterator end() const
Attributes are known-constant values of operations.
Definition: Attributes.h:24
detail::InterfaceMap interfaceMap
A map of interfaces that were registered to this operation.
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
VerifyInvariantsFn verifyInvariantsFn
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:42
bool operator!=(const OperationName &rhs) const
static mlir::RegisteredOperationName getFromVoidPointer(void *P)
TypeID getTypeID() const
Return the unique identifier of the derived Op class.
ValueRange(ArrayRef< BlockArgument > values)
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:38
void addTypes(ArrayRef< Type > newTypes)
void append(RangeT &&newAttributes)
Add an array of named attributes.
bool operator!=(const UseIterator &rhs) const
This class represents a type erased version of an operation.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
LogicalResult foldHook(Operation *op, ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results) const
This hook implements a generalized folder for this operation.
auto getType() const
This class provides a mutable adaptor for a range of operands.
TypeID typeID
The unique identifier of the derived Op class.
This represents an operation in an abstracted form, suitable for use with the builder APIs...
static RegisteredOperationName getFromOpaquePointer(const void *pointer)
Represent the operation name as an opaque pointer.
This class represents a contiguous range of operand ranges, e.g.
static llvm::hash_code directHashValue(Value v)
Helper that can be used with computeHash above to ignore operation operands/result mapping...
ValueRange(iterator_range< ResultRange::iterator > values)
auto getType() const
bool operator!=(const NamedAttrList &other) const
friend MLIRContextImpl
Allow access to the Impl struct.
llvm::unique_function< void(RewritePatternSet &, MLIRContext *) const > GetCanonicalizationPatternsFn
static bool isEqual(mlir::OperationName lhs, mlir::OperationName rhs)
std::pair< IteratorT, bool > findAttrSorted(IteratorT first, IteratorT last, StringAttr name)
StringAttr lookups on large attribute lists will switch to string binary search.
void addSuccessors(Block *successor)
static mlir::RegisteredOperationName getTombstoneKey()
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:84
ParseAssemblyFn parseAssemblyFn
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
bool use_empty() const
Returns true if this value has no uses.
Definition: Value.h:202
ValueRange(iterator_range< OperandRange::iterator > values)
std::pair< IteratorT, bool > findAttrUnsorted(IteratorT first, IteratorT last, NameT name)
Unsorted string search or identifier lookups are linear scans.
static LogicalResult exactValueMatch(Value lhs, Value rhs)
Helper that can be used with isEquivalentTo above to ignore operation operands/result mapping...
This class implements a use iterator for a range of operation results.
This class implements iteration on the types of a given range of values.
Definition: Block.h:26
unsigned size()
Return the number of operands held in the storage.
static llvm::hash_code ignoreHashValue(Value)
Helper that can be used with computeHash above to ignore operation operands/result mapping...
MLIRContext * getContext() const
Get the context held by this operation state.
NamedAttrList attributes
bool operator==(const NamedAttrList &other) const
StringAttr name
The name of the operation.
void pop_back()
Pop last element from list.
bool hasTrait(TypeID traitID) const
Returns true if the operation has a particular trait.
Set of flags used to control the behavior of the various IR print methods (e.g.
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
std::enable_if_t<!std::is_convertible< RangeT, ArrayRef< Type > >::value > addTypes(RangeT &&newTypes)
std::ostream & operator<<(std::ostream &out, const llvm::Twine &twine)
unsigned size() const
Returns the current size of the range.
type_range getTypes() const
static bool hasTrait(TypeID traitID)
Returns true if this given Trait ID matches the IDs of any of the provided trait types Traits...
static void insert(Dialect &dialect)
Register a new operation in a Dialect object.
SmallVectorImpl< NamedAttribute >::iterator iterator
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
This class represents an operand of an operation.
Definition: Value.h:249
This class provides an abstraction over the different types of ranges over Blocks.
Definition: BlockSupport.h:104
int compare(Fraction x, Fraction y)
Three-way comparison between two fractions.
Definition: Fraction.h:46
ArrayRef< StringAttr > getAttributeNames() const
Return the list of cached attribute names registered to this operation.
bool mightHaveTrait() const
Returns true if the operation might have the provided trait.
static LogicalResult ignoreValueEquivalence(Value lhs, Value rhs)
Helper that can be used with isEquivalentTo above to ignore operation operands/result mapping...
void append(NamedAttribute attr)
Append the given named attribute.
bool empty() const
Returns if the current range is empty.
This class implements the operand iterators for the Operation class.
This class provides the implementation for an operation result.
Definition: Value.h:347
Dialect * getDialect() const
Return the dialect this operation is registered to if the dialect is loaded in the context...
std::pair< unsigned, NamedAttribute > OperandSegment
A pair of a named attribute corresponding to an operand segment attribute, and the index within that ...
static llvm::hash_code computeHash(SymbolOpInterface symbolOp)
Computes a hash code to represent symbolOp based on all its attributes except for the symbol name...
llvm::unique_function< LogicalResult(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) const > FoldHookFn
Dialect * dialect
This is the dialect that this operation belongs to.
TypeRangeRange getTypes() const
Returns the range of types of the values within this range.
MutableArrayRef< OpOperand > getOperands()
Get the operation operands held by the storage.
llvm::hash_code hash_value(OperationName arg)
void append(StringAttr name, Attribute attr)
Add an attribute with the specified name.
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
bool hasTrait(TypeID traitID) const
This is a "type erased" representation of a registered operation.
Dialect & getDialect() const
Return the dialect this operation is registered to.
LogicalResult verifyInvariants(Operation *op) const
This hook implements the verifier for this operation.
ValueRange(const std::initializer_list< Value > &values)
RewritePatternSet OwningRewritePatternList
void addAttribute(StringAttr name, Attribute attr)
Add an attribute with the specified name.
This class represents success/failure for operation parsing.
Definition: OpDefinition.h:36
static mlir::OperationName getTombstoneKey()
llvm::unique_function< bool(TypeID) const > HasTraitFn
This class provides an abstraction over the different types of ranges over Values.
Impl * impl
The internal implementation of the operation name.
void assign(ArrayRef< NamedAttribute > range)
Replaces the attributes with new list of attributes.
ArrayRef< StringAttr > attributeNames
A list of attribute names registered to this operation in StringAttr form.
PrintAssemblyFn printAssemblyFn
bool isRegistered() const
The following fields are only populated when the operation is registered.
void attachInterface()
Attach the given models as implementations of the corresponding interfaces for the concrete operation...
OpPrintingFlags(llvm::NoneType)
const ParseAssemblyFn & getParseAssemblyFn() const
Return the static hook for parsing this operation assembly.
type_range getTypes() const
SmallVector< Type, 4 > types
Types of the results of this operation.
This class handles the management of operation operands.