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