MLIR  16.0.0git
Operation.h
Go to the documentation of this file.
1 //===- Operation.h - MLIR Operation Class -----------------------*- 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 the Operation class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_IR_OPERATION_H
14 #define MLIR_IR_OPERATION_H
15 
16 #include "mlir/IR/Block.h"
18 #include "mlir/IR/Diagnostics.h"
20 #include "mlir/IR/Region.h"
21 #include "llvm/ADT/Twine.h"
22 
23 namespace mlir {
24 /// Operation is a basic unit of execution within MLIR. Operations can
25 /// be nested within `Region`s held by other operations effectively forming a
26 /// tree. Child operations are organized into operation blocks represented by a
27 /// 'Block' class.
28 class alignas(8) Operation final
29  : public llvm::ilist_node_with_parent<Operation, Block>,
30  private llvm::TrailingObjects<Operation, detail::OperandStorage,
31  BlockOperand, Region, OpOperand> {
32 public:
33  /// Create a new Operation with the specific fields.
34  static Operation *create(Location location, OperationName name,
35  TypeRange resultTypes, ValueRange operands,
36  NamedAttrList &&attributes, BlockRange successors,
37  unsigned numRegions);
38 
39  /// Create a new Operation from the fields stored in `state`.
40  static Operation *create(const OperationState &state);
41 
42  /// Create a new Operation with the specific fields.
43  static Operation *create(Location location, OperationName name,
44  TypeRange resultTypes, ValueRange operands,
45  NamedAttrList &&attributes,
46  BlockRange successors = {},
47  RegionRange regions = {});
48 
49  /// The name of an operation is the key identifier for it.
50  OperationName getName() { return name; }
51 
52  /// If this operation has a registered operation description, return it.
53  /// Otherwise return None.
55  return getName().getRegisteredInfo();
56  }
57 
58  /// Returns true if this operation has a registered operation description,
59  /// otherwise false.
60  bool isRegistered() { return getName().isRegistered(); }
61 
62  /// Remove this operation from its parent block and delete it.
63  void erase();
64 
65  /// Remove the operation from its parent block, but don't delete it.
66  void remove();
67 
68  /// Class encompassing various options related to cloning an operation. Users
69  /// of this class should pass it to Operation's 'clone' methods.
70  /// Current options include:
71  /// * Whether cloning should recursively traverse into the regions of the
72  /// operation or not.
73  /// * Whether cloning should also clone the operands of the operation.
74  class CloneOptions {
75  public:
76  /// Default constructs an option with all flags set to false. That means all
77  /// parts of an operation that may optionally not be cloned, are not cloned.
78  CloneOptions();
79 
80  /// Constructs an instance with the clone regions and clone operands flags
81  /// set accordingly.
83 
84  /// Returns an instance with all flags set to true. This is the default
85  /// when using the clone method and clones all parts of the operation.
86  static CloneOptions all();
87 
88  /// Configures whether cloning should traverse into any of the regions of
89  /// the operation. If set to true, the operation's regions are recursively
90  /// cloned. If set to false, cloned operations will have the same number of
91  /// regions, but they will be empty.
92  /// Cloning of nested operations in the operation's regions are currently
93  /// unaffected by other flags.
94  CloneOptions &cloneRegions(bool enable = true);
95 
96  /// Returns whether regions of the operation should be cloned as well.
97  bool shouldCloneRegions() const { return cloneRegionsFlag; }
98 
99  /// Configures whether operation' operands should be cloned. Otherwise the
100  /// resulting clones will simply have zero operands.
101  CloneOptions &cloneOperands(bool enable = true);
102 
103  /// Returns whether operands should be cloned as well.
104  bool shouldCloneOperands() const { return cloneOperandsFlag; }
105 
106  private:
107  /// Whether regions should be cloned.
108  bool cloneRegionsFlag : 1;
109  /// Whether operands should be cloned.
110  bool cloneOperandsFlag : 1;
111  };
112 
113  /// Create a deep copy of this operation, remapping any operands that use
114  /// values outside of the operation using the map that is provided (leaving
115  /// them alone if no entry is present). Replaces references to cloned
116  /// sub-operations to the corresponding operation that is copied, and adds
117  /// those mappings to the map.
118  /// Optionally, one may configure what parts of the operation to clone using
119  /// the options parameter.
120  ///
121  /// Calling this method from multiple threads is generally safe if through the
122  /// process of cloning no new uses of 'Value's from outside the operation are
123  /// created. Cloning an isolated-from-above operation with no operands, such
124  /// as top level function operations, is therefore always safe. Using the
125  /// mapper, it is possible to avoid adding uses to outside operands by
126  /// remapping them to 'Value's owned by the caller thread.
128  CloneOptions options = CloneOptions::all());
129  Operation *clone(CloneOptions options = CloneOptions::all());
130 
131  /// Create a partial copy of this operation without traversing into attached
132  /// regions. The new operation will have the same number of regions as the
133  /// original one, but they will be left empty.
134  /// Operands are remapped using `mapper` (if present), and `mapper` is updated
135  /// to contain the results.
137 
138  /// Create a partial copy of this operation without traversing into attached
139  /// regions. The new operation will have the same number of regions as the
140  /// original one, but they will be left empty.
142 
143  /// Returns the operation block that contains this operation.
144  Block *getBlock() { return block; }
145 
146  /// Return the context this operation is associated with.
147  MLIRContext *getContext() { return location->getContext(); }
148 
149  /// Return the dialect this operation is associated with, or nullptr if the
150  /// associated dialect is not loaded.
152 
153  /// The source location the operation was defined or derived from.
154  Location getLoc() { return location; }
155 
156  /// Set the source location the operation was defined or derived from.
157  void setLoc(Location loc) { location = loc; }
158 
159  /// Returns the region to which the instruction belongs. Returns nullptr if
160  /// the instruction is unlinked.
161  Region *getParentRegion() { return block ? block->getParent() : nullptr; }
162 
163  /// Returns the closest surrounding operation that contains this operation
164  /// or nullptr if this is a top-level operation.
165  Operation *getParentOp() { return block ? block->getParentOp() : nullptr; }
166 
167  /// Return the closest surrounding parent operation that is of type 'OpTy'.
168  template <typename OpTy>
170  auto *op = this;
171  while ((op = op->getParentOp()))
172  if (auto parentOp = dyn_cast<OpTy>(op))
173  return parentOp;
174  return OpTy();
175  }
176 
177  /// Returns the closest surrounding parent operation with trait `Trait`.
178  template <template <typename T> class Trait>
180  Operation *op = this;
181  while ((op = op->getParentOp()))
182  if (op->hasTrait<Trait>())
183  return op;
184  return nullptr;
185  }
186 
187  /// Return true if this operation is a proper ancestor of the `other`
188  /// operation.
189  bool isProperAncestor(Operation *other);
190 
191  /// Return true if this operation is an ancestor of the `other` operation. An
192  /// operation is considered as its own ancestor, use `isProperAncestor` to
193  /// avoid this.
194  bool isAncestor(Operation *other) {
195  return this == other || isProperAncestor(other);
196  }
197 
198  /// Replace any uses of 'from' with 'to' within this operation.
199  void replaceUsesOfWith(Value from, Value to);
200 
201  /// Replace all uses of results of this operation with the provided 'values'.
202  template <typename ValuesT>
203  void replaceAllUsesWith(ValuesT &&values) {
204  getResults().replaceAllUsesWith(std::forward<ValuesT>(values));
205  }
206 
207  /// Destroys this operation and its subclass data.
208  void destroy();
209 
210  /// This drops all operand uses from this operation, which is an essential
211  /// step in breaking cyclic dependences between references when they are to
212  /// be deleted.
213  void dropAllReferences();
214 
215  /// Drop uses of all values defined by this operation or its nested regions.
217 
218  /// Unlink this operation from its current block and insert it right before
219  /// `existingOp` which may be in the same or another block in the same
220  /// function.
221  void moveBefore(Operation *existingOp);
222 
223  /// Unlink this operation from its current block and insert it right before
224  /// `iterator` in the specified block.
225  void moveBefore(Block *block, llvm::iplist<Operation>::iterator iterator);
226 
227  /// Unlink this operation from its current block and insert it right after
228  /// `existingOp` which may be in the same or another block in the same
229  /// function.
230  void moveAfter(Operation *existingOp);
231 
232  /// Unlink this operation from its current block and insert it right after
233  /// `iterator` in the specified block.
234  void moveAfter(Block *block, llvm::iplist<Operation>::iterator iterator);
235 
236  /// Given an operation 'other' that is within the same parent block, return
237  /// whether the current operation is before 'other' in the operation list
238  /// of the parent block.
239  /// Note: This function has an average complexity of O(1), but worst case may
240  /// take O(N) where N is the number of operations within the parent block.
241  bool isBeforeInBlock(Operation *other);
242 
243  void print(raw_ostream &os, const OpPrintingFlags &flags = llvm::None);
244  void print(raw_ostream &os, AsmState &state);
245  void dump();
246 
247  //===--------------------------------------------------------------------===//
248  // Operands
249  //===--------------------------------------------------------------------===//
250 
251  /// Replace the current operands of this operation with the ones provided in
252  /// 'operands'.
253  void setOperands(ValueRange operands);
254 
255  /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
256  /// with the ones provided in 'operands'. 'operands' may be smaller or larger
257  /// than the range pointed to by 'start'+'length'.
258  void setOperands(unsigned start, unsigned length, ValueRange operands);
259 
260  /// Insert the given operands into the operand list at the given 'index'.
261  void insertOperands(unsigned index, ValueRange operands);
262 
263  unsigned getNumOperands() {
264  return LLVM_LIKELY(hasOperandStorage) ? getOperandStorage().size() : 0;
265  }
266 
267  Value getOperand(unsigned idx) { return getOpOperand(idx).get(); }
268  void setOperand(unsigned idx, Value value) {
269  return getOpOperand(idx).set(value);
270  }
271 
272  /// Erase the operand at position `idx`.
273  void eraseOperand(unsigned idx) { eraseOperands(idx); }
274 
275  /// Erase the operands starting at position `idx` and ending at position
276  /// 'idx'+'length'.
277  void eraseOperands(unsigned idx, unsigned length = 1) {
278  getOperandStorage().eraseOperands(idx, length);
279  }
280 
281  /// Erases the operands that have their corresponding bit set in
282  /// `eraseIndices` and removes them from the operand list.
283  void eraseOperands(const BitVector &eraseIndices) {
284  getOperandStorage().eraseOperands(eraseIndices);
285  }
286 
287  // Support operand iteration.
289  using operand_iterator = operand_range::iterator;
290 
293 
294  /// Returns an iterator on the underlying Value's.
297  return OperandRange(operands.data(), operands.size());
298  }
299 
301  return LLVM_LIKELY(hasOperandStorage) ? getOperandStorage().getOperands()
303  }
304 
305  OpOperand &getOpOperand(unsigned idx) {
306  return getOperandStorage().getOperands()[idx];
307  }
308 
309  // Support operand type iteration.
315 
316  //===--------------------------------------------------------------------===//
317  // Results
318  //===--------------------------------------------------------------------===//
319 
320  /// Return the number of results held by this operation.
321  unsigned getNumResults() { return numResults; }
322 
323  /// Get the 'idx'th result of this operation.
324  OpResult getResult(unsigned idx) { return OpResult(getOpResultImpl(idx)); }
325 
326  /// Support result iteration.
328  using result_iterator = result_range::iterator;
329 
330  result_iterator result_begin() { return getResults().begin(); }
331  result_iterator result_end() { return getResults().end(); }
333  return numResults == 0 ? result_range(nullptr, 0)
334  : result_range(getInlineOpResult(0), numResults);
335  }
336 
338  OpResult getOpResult(unsigned idx) { return getResult(idx); }
339 
340  /// Support result type iteration.
346 
347  //===--------------------------------------------------------------------===//
348  // Attributes
349  //===--------------------------------------------------------------------===//
350 
351  // Operations may optionally carry a list of attributes that associate
352  // constants to names. Attributes may be dynamically added and removed over
353  // the lifetime of an operation.
354 
355  /// Return all of the attributes on this operation.
356  ArrayRef<NamedAttribute> getAttrs() { return attrs.getValue(); }
357 
358  /// Return all of the attributes on this operation as a DictionaryAttr.
359  DictionaryAttr getAttrDictionary() { return attrs; }
360 
361  /// Set the attribute dictionary on this operation.
362  void setAttrs(DictionaryAttr newAttrs) {
363  assert(newAttrs && "expected valid attribute dictionary");
364  attrs = newAttrs;
365  }
367  setAttrs(DictionaryAttr::get(getContext(), newAttrs));
368  }
369 
370  /// Return the specified attribute if present, null otherwise.
371  Attribute getAttr(StringAttr name) { return attrs.get(name); }
372  Attribute getAttr(StringRef name) { return attrs.get(name); }
373 
374  template <typename AttrClass>
375  AttrClass getAttrOfType(StringAttr name) {
376  return getAttr(name).dyn_cast_or_null<AttrClass>();
377  }
378  template <typename AttrClass>
379  AttrClass getAttrOfType(StringRef name) {
380  return getAttr(name).dyn_cast_or_null<AttrClass>();
381  }
382 
383  /// Return true if the operation has an attribute with the provided name,
384  /// false otherwise.
385  bool hasAttr(StringAttr name) { return attrs.contains(name); }
386  bool hasAttr(StringRef name) { return attrs.contains(name); }
387  template <typename AttrClass, typename NameT>
388  bool hasAttrOfType(NameT &&name) {
389  return static_cast<bool>(
390  getAttrOfType<AttrClass>(std::forward<NameT>(name)));
391  }
392 
393  /// If the an attribute exists with the specified name, change it to the new
394  /// value. Otherwise, add a new attribute with the specified name/value.
395  void setAttr(StringAttr name, Attribute value) {
396  NamedAttrList attributes(attrs);
397  if (attributes.set(name, value) != value)
398  attrs = attributes.getDictionary(getContext());
399  }
400  void setAttr(StringRef name, Attribute value) {
401  setAttr(StringAttr::get(getContext(), name), value);
402  }
403 
404  /// Remove the attribute with the specified name if it exists. Return the
405  /// attribute that was erased, or nullptr if there was no attribute with such
406  /// name.
407  Attribute removeAttr(StringAttr name) {
408  NamedAttrList attributes(attrs);
409  Attribute removedAttr = attributes.erase(name);
410  if (removedAttr)
411  attrs = attributes.getDictionary(getContext());
412  return removedAttr;
413  }
414  Attribute removeAttr(StringRef name) {
415  return removeAttr(StringAttr::get(getContext(), name));
416  }
417 
418  /// A utility iterator that filters out non-dialect attributes.
420  : public llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
421  bool (*)(NamedAttribute)> {
422  static bool filter(NamedAttribute attr) {
423  // Dialect attributes are prefixed by the dialect name, like operations.
424  return attr.getName().strref().count('.');
425  }
426 
429  : llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
430  bool (*)(NamedAttribute)>(it, end, &filter) {}
431 
432  // Allow access to the constructor.
433  friend Operation;
434  };
436 
437  /// Return a range corresponding to the dialect attributes for this operation.
439  auto attrs = getAttrs();
440  return {dialect_attr_iterator(attrs.begin(), attrs.end()),
441  dialect_attr_iterator(attrs.end(), attrs.end())};
442  }
444  auto attrs = getAttrs();
445  return dialect_attr_iterator(attrs.begin(), attrs.end());
446  }
448  auto attrs = getAttrs();
449  return dialect_attr_iterator(attrs.end(), attrs.end());
450  }
451 
452  /// Set the dialect attributes for this operation, and preserve all dependent.
453  template <typename DialectAttrT>
454  void setDialectAttrs(DialectAttrT &&dialectAttrs) {
455  NamedAttrList attrs;
456  attrs.append(std::begin(dialectAttrs), std::end(dialectAttrs));
457  for (auto attr : getAttrs())
458  if (!attr.getName().strref().contains('.'))
459  attrs.push_back(attr);
461  }
462 
463  /// Sets default attributes on unset attributes.
465  if (auto registered = getRegisteredInfo()) {
467  registered->populateDefaultAttrs(attrs);
469  }
470  }
471 
472  //===--------------------------------------------------------------------===//
473  // Blocks
474  //===--------------------------------------------------------------------===//
475 
476  /// Returns the number of regions held by this operation.
477  unsigned getNumRegions() { return numRegions; }
478 
479  /// Returns the regions held by this operation.
481  auto *regions = getTrailingObjects<Region>();
482  return {regions, numRegions};
483  }
484 
485  /// Returns the region held by this operation at position 'index'.
486  Region &getRegion(unsigned index) {
487  assert(index < numRegions && "invalid region index");
488  return getRegions()[index];
489  }
490 
491  //===--------------------------------------------------------------------===//
492  // Successors
493  //===--------------------------------------------------------------------===//
494 
496  return {getTrailingObjects<BlockOperand>(), numSuccs};
497  }
498 
499  // Successor iteration.
500  using succ_iterator = SuccessorRange::iterator;
504 
505  bool hasSuccessors() { return numSuccs != 0; }
506  unsigned getNumSuccessors() { return numSuccs; }
507 
508  Block *getSuccessor(unsigned index) {
509  assert(index < getNumSuccessors());
510  return getBlockOperands()[index].get();
511  }
512  void setSuccessor(Block *block, unsigned index);
513 
514  //===--------------------------------------------------------------------===//
515  // Accessors for various properties of operations
516  //===--------------------------------------------------------------------===//
517 
518  /// Attempt to fold this operation with the specified constant operand values
519  /// - the elements in "operands" will correspond directly to the operands of
520  /// the operation, but may be null if non-constant. If folding is successful,
521  /// this fills in the `results` vector. If not, `results` is unspecified.
524 
525  /// Returns true if the operation was registered with a particular trait, e.g.
526  /// hasTrait<OperandsAreSignlessIntegerLike>().
527  template <template <typename T> class Trait>
528  bool hasTrait() {
529  return name.hasTrait<Trait>();
530  }
531 
532  /// Returns true if the operation *might* have the provided trait. This
533  /// means that either the operation is unregistered, or it was registered with
534  /// the provide trait.
535  template <template <typename T> class Trait>
536  bool mightHaveTrait() {
537  return name.mightHaveTrait<Trait>();
538  }
539 
540  //===--------------------------------------------------------------------===//
541  // Operation Walkers
542  //===--------------------------------------------------------------------===//
543 
544  /// Walk the operation by calling the callback for each nested operation
545  /// (including this one), block or region, depending on the callback provided.
546  /// Regions, blocks and operations at the same nesting level are visited in
547  /// lexicographical order. The walk order for enclosing regions, blocks and
548  /// operations with respect to their nested ones is specified by 'Order'
549  /// (post-order by default). A callback on a block or operation is allowed to
550  /// erase that block or operation if either:
551  /// * the walk is in post-order, or
552  /// * the walk is in pre-order and the walk is skipped after the erasure.
553  ///
554  /// The callback method can take any of the following forms:
555  /// void(Operation*) : Walk all operations opaquely.
556  /// * op->walk([](Operation *nestedOp) { ...});
557  /// void(OpT) : Walk all operations of the given derived type.
558  /// * op->walk([](ReturnOp returnOp) { ...});
559  /// WalkResult(Operation*|OpT) : Walk operations, but allow for
560  /// interruption/skipping.
561  /// * op->walk([](... op) {
562  /// // Skip the walk of this op based on some invariant.
563  /// if (some_invariant)
564  /// return WalkResult::skip();
565  /// // Interrupt, i.e cancel, the walk based on some invariant.
566  /// if (another_invariant)
567  /// return WalkResult::interrupt();
568  /// return WalkResult::advance();
569  /// });
570  template <WalkOrder Order = WalkOrder::PostOrder, typename FnT,
571  typename RetT = detail::walkResultType<FnT>>
572  std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 1,
573  RetT>
574  walk(FnT &&callback) {
575  return detail::walk<Order>(this, std::forward<FnT>(callback));
576  }
577 
578  /// Generic walker with a stage aware callback. Walk the operation by calling
579  /// the callback for each nested operation (including this one) N+1 times,
580  /// where N is the number of regions attached to that operation.
581  ///
582  /// The callback method can take any of the following forms:
583  /// void(Operation *, const WalkStage &) : Walk all operation opaquely
584  /// * op->walk([](Operation *nestedOp, const WalkStage &stage) { ...});
585  /// void(OpT, const WalkStage &) : Walk all operations of the given derived
586  /// type.
587  /// * op->walk([](ReturnOp returnOp, const WalkStage &stage) { ...});
588  /// WalkResult(Operation*|OpT, const WalkStage &stage) : Walk operations,
589  /// but allow for interruption/skipping.
590  /// * op->walk([](... op, const WalkStage &stage) {
591  /// // Skip the walk of this op based on some invariant.
592  /// if (some_invariant)
593  /// return WalkResult::skip();
594  /// // Interrupt, i.e cancel, the walk based on some invariant.
595  /// if (another_invariant)
596  /// return WalkResult::interrupt();
597  /// return WalkResult::advance();
598  /// });
599  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
600  std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 2,
601  RetT>
602  walk(FnT &&callback) {
603  return detail::walk(this, std::forward<FnT>(callback));
604  }
605 
606  //===--------------------------------------------------------------------===//
607  // Uses
608  //===--------------------------------------------------------------------===//
609 
610  /// Drop all uses of results of this operation.
611  void dropAllUses() {
612  for (OpResult result : getOpResults())
613  result.dropAllUses();
614  }
615 
618 
621 
622  /// Returns a range of all uses, which is useful for iterating over all uses.
624 
625  /// Returns true if this operation has exactly one use.
626  bool hasOneUse() { return llvm::hasSingleElement(getUses()); }
627 
628  /// Returns true if this operation has no uses.
629  bool use_empty() { return getResults().use_empty(); }
630 
631  /// Returns true if the results of this operation are used outside of the
632  /// given block.
634  return llvm::any_of(getOpResults(), [block](OpResult result) {
635  return result.isUsedOutsideOfBlock(block);
636  });
637  }
638 
639  //===--------------------------------------------------------------------===//
640  // Users
641  //===--------------------------------------------------------------------===//
642 
645 
648 
649  /// Returns a range of all users.
650  user_range getUsers() { return {user_begin(), user_end()}; }
651 
652  //===--------------------------------------------------------------------===//
653  // Other
654  //===--------------------------------------------------------------------===//
655 
656  /// Emit an error with the op name prefixed, like "'dim' op " which is
657  /// convenient for verifiers.
658  InFlightDiagnostic emitOpError(const Twine &message = {});
659 
660  /// Emit an error about fatal conditions with this operation, reporting up to
661  /// any diagnostic handlers that may be listening.
662  InFlightDiagnostic emitError(const Twine &message = {});
663 
664  /// Emit a warning about this operation, reporting up to any diagnostic
665  /// handlers that may be listening.
666  InFlightDiagnostic emitWarning(const Twine &message = {});
667 
668  /// Emit a remark about this operation, reporting up to any diagnostic
669  /// handlers that may be listening.
670  InFlightDiagnostic emitRemark(const Twine &message = {});
671 
672 private:
673  //===--------------------------------------------------------------------===//
674  // Ordering
675  //===--------------------------------------------------------------------===//
676 
677  /// This value represents an invalid index ordering for an operation within a
678  /// block.
679  static constexpr unsigned kInvalidOrderIdx = -1;
680 
681  /// This value represents the stride to use when computing a new order for an
682  /// operation.
683  static constexpr unsigned kOrderStride = 5;
684 
685  /// Update the order index of this operation of this operation if necessary,
686  /// potentially recomputing the order of the parent block.
687  void updateOrderIfNecessary();
688 
689  /// Returns true if this operation has a valid order.
690  bool hasValidOrder() { return orderIndex != kInvalidOrderIdx; }
691 
692 private:
693  Operation(Location location, OperationName name, unsigned numResults,
694  unsigned numSuccessors, unsigned numRegions,
695  DictionaryAttr attributes, bool hasOperandStorage);
696 
697  // Operations are deleted through the destroy() member because they are
698  // allocated with malloc.
699  ~Operation();
700 
701  /// Returns the additional size necessary for allocating the given objects
702  /// before an Operation in-memory.
703  static size_t prefixAllocSize(unsigned numOutOfLineResults,
704  unsigned numInlineResults) {
705  return sizeof(detail::OutOfLineOpResult) * numOutOfLineResults +
706  sizeof(detail::InlineOpResult) * numInlineResults;
707  }
708  /// Returns the additional size allocated before this Operation in-memory.
709  size_t prefixAllocSize() {
710  unsigned numResults = getNumResults();
711  unsigned numOutOfLineResults = OpResult::getNumTrailing(numResults);
712  unsigned numInlineResults = OpResult::getNumInline(numResults);
713  return prefixAllocSize(numOutOfLineResults, numInlineResults);
714  }
715 
716  /// Returns the operand storage object.
717  detail::OperandStorage &getOperandStorage() {
718  assert(hasOperandStorage && "expected operation to have operand storage");
719  return *getTrailingObjects<detail::OperandStorage>();
720  }
721 
722  /// Returns a pointer to the use list for the given out-of-line result.
723  detail::OutOfLineOpResult *getOutOfLineOpResult(unsigned resultNumber) {
724  // Out-of-line results are stored in reverse order after (before in memory)
725  // the inline results.
726  return reinterpret_cast<detail::OutOfLineOpResult *>(getInlineOpResult(
728  ++resultNumber;
729  }
730 
731  /// Returns a pointer to the use list for the given inline result.
732  detail::InlineOpResult *getInlineOpResult(unsigned resultNumber) {
733  // Inline results are stored in reverse order before the operation in
734  // memory.
735  return reinterpret_cast<detail::InlineOpResult *>(this) - ++resultNumber;
736  }
737 
738  /// Returns a pointer to the use list for the given result, which may be
739  /// either inline or out-of-line.
740  detail::OpResultImpl *getOpResultImpl(unsigned resultNumber) {
741  unsigned maxInlineResults = detail::OpResultImpl::getMaxInlineResults();
742  if (resultNumber < maxInlineResults)
743  return getInlineOpResult(resultNumber);
744  return getOutOfLineOpResult(resultNumber - maxInlineResults);
745  }
746 
747  /// Provide a 'getParent' method for ilist_node_with_parent methods.
748  /// We mark it as a const function because ilist_node_with_parent specifically
749  /// requires a 'getParent() const' method. Once ilist_node removes this
750  /// constraint, we should drop the const to fit the rest of the MLIR const
751  /// model.
752  Block *getParent() const { return block; }
753 
754  /// The operation block that contains this operation.
755  Block *block = nullptr;
756 
757  /// This holds information about the source location the operation was defined
758  /// or derived from.
759  Location location;
760 
761  /// Relative order of this operation in its parent block. Used for
762  /// O(1) local dominance checks between operations.
763  mutable unsigned orderIndex = 0;
764 
765  const unsigned numResults;
766  const unsigned numSuccs;
767  const unsigned numRegions : 31;
768 
769  /// This bit signals whether this operation has an operand storage or not. The
770  /// operand storage may be elided for operations that are known to never have
771  /// operands.
772  bool hasOperandStorage : 1;
773 
774  /// This holds the name of the operation.
775  OperationName name;
776 
777  /// This holds general named attributes for the operation.
778  DictionaryAttr attrs;
779 
780  // allow ilist_traits access to 'block' field.
781  friend struct llvm::ilist_traits<Operation>;
782 
783  // allow block to access the 'orderIndex' field.
784  friend class Block;
785 
786  // allow value to access the 'ResultStorage' methods.
787  friend class Value;
788 
789  // allow ilist_node_with_parent to access the 'getParent' method.
790  friend class llvm::ilist_node_with_parent<Operation, Block>;
791 
792  // This stuff is used by the TrailingObjects template.
793  friend llvm::TrailingObjects<Operation, detail::OperandStorage, BlockOperand,
794  Region, OpOperand>;
795  size_t numTrailingObjects(OverloadToken<detail::OperandStorage>) const {
796  return hasOperandStorage ? 1 : 0;
797  }
798  size_t numTrailingObjects(OverloadToken<BlockOperand>) const {
799  return numSuccs;
800  }
801  size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; }
802 };
803 
804 inline raw_ostream &operator<<(raw_ostream &os, const Operation &op) {
805  const_cast<Operation &>(op).print(os, OpPrintingFlags().useLocalScope());
806  return os;
807 }
808 
809 } // namespace mlir
810 
811 namespace llvm {
812 /// Cast from an (const) Operation * to a derived operation type.
813 template <typename T>
814 struct CastInfo<T, ::mlir::Operation *>
815  : public ValueFromPointerCast<T, ::mlir::Operation,
816  CastInfo<T, ::mlir::Operation *>> {
817  static bool isPossible(::mlir::Operation *op) { return T::classof(op); }
818 };
819 template <typename T>
820 struct CastInfo<T, const ::mlir::Operation *>
821  : public ConstStrippingForwardingCast<T, const ::mlir::Operation *,
822  CastInfo<T, ::mlir::Operation *>> {};
823 
824 /// Cast from an (const) Operation & to a derived operation type.
825 template <typename T>
827  : public NullableValueCastFailed<T>,
828  public DefaultDoCastIfPossible<T, ::mlir::Operation &,
829  CastInfo<T, ::mlir::Operation>> {
830  // Provide isPossible here because here we have the const-stripping from
831  // ConstStrippingCast.
832  static bool isPossible(::mlir::Operation &val) { return T::classof(&val); }
833  static T doCast(::mlir::Operation &val) { return T(&val); }
834 };
835 template <typename T>
836 struct CastInfo<T, const ::mlir::Operation>
837  : public ConstStrippingForwardingCast<T, const ::mlir::Operation,
838  CastInfo<T, ::mlir::Operation>> {};
839 
840 /// Cast (const) Operation * to itself. This is helpful to avoid SFINAE in
841 /// templated implementations that should work on both base and derived
842 /// operation types.
843 template <>
845  : public NullableValueCastFailed<::mlir::Operation *>,
847  ::mlir::Operation *, ::mlir::Operation *,
848  CastInfo<::mlir::Operation *, ::mlir::Operation *>> {
849  static bool isPossible(::mlir::Operation *op) { return true; }
850  static ::mlir::Operation *doCast(::mlir::Operation *op) { return op; }
851 };
852 template <>
853 struct CastInfo<const ::mlir::Operation *, const ::mlir::Operation *>
855  const ::mlir::Operation *, const ::mlir::Operation *,
856  CastInfo<::mlir::Operation *, ::mlir::Operation *>> {};
857 } // namespace llvm
858 
859 #endif // MLIR_IR_OPERATION_H
static constexpr const bool value
static llvm::ManagedStatic< PassManagerOptions > options
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This class provides management for the lifetime of the state used when printing the IR.
Definition: AsmState.h:524
Attributes are known-constant values of operations.
Definition: Attributes.h:25
U dyn_cast_or_null() const
Definition: Attributes.h:132
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:20
A block operand represents an operand that holds a reference to a Block, e.g.
Definition: BlockSupport.h:30
This class provides an abstraction over the different types of ranges over Blocks.
Definition: BlockSupport.h:106
Block represents an ordered list of Operations.
Definition: Block.h:30
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition: Block.cpp:26
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:30
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
IRValueT get() const
Return the current value being used by this operand.
Definition: UseDefLists.h:137
void set(IRValueT newValue)
Set the current value being used by this operand.
Definition: UseDefLists.h:140
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:307
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:64
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:56
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:150
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:32
This class represents an operand of an operation.
Definition: Value.h:247
Set of flags used to control the behavior of the various IR print methods (e.g.
OpPrintingFlags & useLocalScope()
Use local scope when printing the operation.
Definition: AsmPrinter.cpp:235
This is a value defined by a result of an operation.
Definition: Value.h:442
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:41
type_range getTypes() const
Definition: ValueRange.cpp:26
ValueTypeRange< OperandRange > type_range
Definition: ValueRange.h:47
ValueTypeIterator< iterator > type_iterator
Returns the types of the values within this range.
Definition: ValueRange.h:46
bool hasTrait() const
Returns true if the operation was registered with a particular trait, e.g.
Dialect * getDialect() const
Return the dialect this operation is registered to if the dialect is loaded in the context,...
bool mightHaveTrait() const
Returns true if the operation might have the provided trait.
bool isRegistered() const
Return if this operation is registered.
Optional< RegisteredOperationName > getRegisteredInfo() const
If this operation is registered, returns the registered information, None otherwise.
Class encompassing various options related to cloning an operation.
Definition: Operation.h:74
bool shouldCloneRegions() const
Returns whether regions of the operation should be cloned as well.
Definition: Operation.h:97
CloneOptions()
Default constructs an option with all flags set to false.
Definition: Operation.cpp:520
static CloneOptions all()
Returns an instance with all flags set to true.
Definition: Operation.cpp:526
bool shouldCloneOperands() const
Returns whether operands should be cloned as well.
Definition: Operation.h:104
CloneOptions & cloneRegions(bool enable=true)
Configures whether cloning should traverse into any of the regions of the operation.
Definition: Operation.cpp:530
CloneOptions & cloneOperands(bool enable=true)
Configures whether operation' operands should be cloned.
Definition: Operation.cpp:535
A utility iterator that filters out non-dialect attributes.
Definition: Operation.h:421
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:31
AttrClass getAttrOfType(StringRef name)
Definition: Operation.h:379
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Definition: Operation.h:157
void eraseOperands(const BitVector &eraseIndices)
Erases the operands that have their corresponding bit set in eraseIndices and removes them from the o...
Definition: Operation.h:283
void replaceUsesOfWith(Value from, Value to)
Replace any uses of 'from' with 'to' within this operation.
Definition: Operation.cpp:184
ResultRange result_range
Support result iteration.
Definition: Operation.h:327
LogicalResult fold(ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results)
Attempt to fold this operation with the specified constant operand values.
Definition: Operation.cpp:490
void setAttrs(ArrayRef< NamedAttribute > newAttrs)
Definition: Operation.h:366
bool use_empty()
Returns true if this operation has no uses.
Definition: Operation.h:629
Value getOperand(unsigned idx)
Definition: Operation.h:267
OpResult getOpResult(unsigned idx)
Definition: Operation.h:338
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:528
Operation * cloneWithoutRegions()
Create a partial copy of this operation without traversing into attached regions.
Definition: Operation.cpp:548
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Definition: Operation.h:151
void insertOperands(unsigned index, ValueRange operands)
Insert the given operands into the operand list at the given 'index'.
Definition: Operation.cpp:213
void dropAllUses()
Drop all uses of results of this operation.
Definition: Operation.h:611
AttrClass getAttrOfType(StringAttr name)
Definition: Operation.h:375
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition: Operation.h:371
bool hasAttr(StringRef name)
Definition: Operation.h:386
OpOperand & getOpOperand(unsigned idx)
Definition: Operation.h:305
bool hasAttrOfType(NameT &&name)
Definition: Operation.h:388
void setOperand(unsigned idx, Value value)
Definition: Operation.h:268
Block * getSuccessor(unsigned index)
Definition: Operation.h:508
bool hasAttr(StringAttr name)
Return true if the operation has an attribute with the provided name, false otherwise.
Definition: Operation.h:385
unsigned getNumSuccessors()
Definition: Operation.h:506
bool isBeforeInBlock(Operation *other)
Given an operation 'other' that is within the same parent block, return whether the current operation...
Definition: Operation.cpp:265
result_iterator result_begin()
Definition: Operation.h:330
void eraseOperands(unsigned idx, unsigned length=1)
Erase the operands starting at position idx and ending at position 'idx'+'length'.
Definition: Operation.h:277
void dropAllReferences()
This drops all operand uses from this operation, which is an essential step in breaking cyclic depend...
Definition: Operation.cpp:463
bool isRegistered()
Returns true if this operation has a registered operation description, otherwise false.
Definition: Operation.h:60
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:237
result_range::iterator result_iterator
Definition: Operation.h:328
void setAttrs(DictionaryAttr newAttrs)
Set the attribute dictionary on this operation.
Definition: Operation.h:362
operand_iterator operand_begin()
Definition: Operation.h:291
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Definition: Operation.h:536
bool hasOneUse()
Returns true if this operation has exactly one use.
Definition: Operation.h:626
dialect_attr_iterator dialect_attr_begin()
Definition: Operation.h:443
void print(raw_ostream &os, const OpPrintingFlags &flags=llvm::None)
Attribute getAttr(StringRef name)
Definition: Operation.h:372
user_iterator user_end()
Definition: Operation.h:647
Attribute removeAttr(StringRef name)
Definition: Operation.h:414
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:324
use_iterator use_begin()
Definition: Operation.h:619
Operation * clone(BlockAndValueMapping &mapper, CloneOptions options=CloneOptions::all())
Create a deep copy of this operation, remapping any operands that use values outside of the operation...
Definition: Operation.cpp:558
operand_type_iterator operand_type_end()
Definition: Operation.h:313
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:147
unsigned getNumRegions()
Returns the number of regions held by this operation.
Definition: Operation.h:477
void setDialectAttrs(DialectAttrT &&dialectAttrs)
Set the dialect attributes for this operation, and preserve all dependent.
Definition: Operation.h:454
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:154
void eraseOperand(unsigned idx)
Erase the operand at position idx.
Definition: Operation.h:273
void dropAllDefinedValueUses()
Drop uses of all values defined by this operation or its nested regions.
Definition: Operation.cpp:476
unsigned getNumOperands()
Definition: Operation.h:263
result_type_iterator result_type_end()
Definition: Operation.h:344
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:165
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
Definition: Operation.cpp:49
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
Definition: Operation.h:356
void populateDefaultAttrs()
Sets default attributes on unset attributes.
Definition: Operation.h:464
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:225
Block * getBlock()
Returns the operation block that contains this operation.
Definition: Operation.h:144
ValueUserIterator< use_iterator, OpOperand > user_iterator
Definition: Operation.h:643
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition: Operation.h:169
operand_iterator operand_end()
Definition: Operation.h:292
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Definition: Operation.h:486
bool isUsedOutsideOfBlock(Block *block)
Returns true if the results of this operation are used outside of the given block.
Definition: Operation.h:633
result_type_iterator result_type_begin()
Definition: Operation.h:343
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
Definition: Operation.h:395
Operation * getParentWithTrait()
Returns the closest surrounding parent operation with trait Trait.
Definition: Operation.h:179
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:480
void destroy()
Destroys this operation and its subclass data.
Definition: Operation.cpp:165
DictionaryAttr getAttrDictionary()
Return all of the attributes on this operation as a DictionaryAttr.
Definition: Operation.h:359
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:50
void remove()
Remove the operation from its parent block, but don't delete it.
Definition: Operation.cpp:426
Optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
Definition: Operation.h:54
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
Definition: Operation.h:438
MutableArrayRef< BlockOperand > getBlockOperands()
Definition: Operation.h:495
bool hasSuccessors()
Definition: Operation.h:505
operand_type_range getOperandTypes()
Definition: Operation.h:314
result_iterator result_end()
Definition: Operation.h:331
MutableArrayRef< OpOperand > getOpOperands()
Definition: Operation.h:300
friend class Block
Definition: Operation.h:784
result_type_range getResultTypes()
Definition: Operation.h:345
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:295
void setSuccessor(Block *block, unsigned index)
Definition: Operation.cpp:484
void moveBefore(Operation *existingOp)
Unlink this operation from its current block and insert it right before existingOp which may be in th...
Definition: Operation.cpp:434
bool isAncestor(Operation *other)
Return true if this operation is an ancestor of the other operation.
Definition: Operation.h:194
void replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this operation with the provided 'values'.
Definition: Operation.h:203
void setOperands(ValueRange operands)
Replace the current operands of this operation with the ones provided in 'operands'.
Definition: Operation.cpp:194
user_range getUsers()
Returns a range of all users.
Definition: Operation.h:650
SuccessorRange getSuccessors()
Definition: Operation.h:503
result_range getOpResults()
Definition: Operation.h:337
Region * getParentRegion()
Returns the region to which the instruction belongs.
Definition: Operation.h:161
result_range getResults()
Definition: Operation.h:332
Attribute removeAttr(StringAttr name)
Remove the attribute with the specified name if it exists.
Definition: Operation.h:407
SuccessorRange::iterator succ_iterator
Definition: Operation.h:500
dialect_attr_iterator dialect_attr_end()
Definition: Operation.h:447
bool isProperAncestor(Operation *other)
Return true if this operation is a proper ancestor of the other operation.
Definition: Operation.cpp:176
use_range getUses()
Returns a range of all uses, which is useful for iterating over all uses.
Definition: Operation.h:623
void setAttr(StringRef name, Attribute value)
Definition: Operation.h:400
InFlightDiagnostic emitRemark(const Twine &message={})
Emit a remark about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:246
operand_range::iterator operand_iterator
Definition: Operation.h:289
user_iterator user_begin()
Definition: Operation.h:646
void moveAfter(Operation *existingOp)
Unlink this operation from its current block and insert it right after existingOp which may be in the...
Definition: Operation.cpp:448
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition: Operation.h:574
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:512
succ_iterator successor_end()
Definition: Operation.h:502
use_iterator use_end()
Definition: Operation.h:620
void erase()
Remove this operation from its parent block and delete it.
Definition: Operation.cpp:418
succ_iterator successor_begin()
Definition: Operation.h:501
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==2, RetT > walk(FnT &&callback)
Generic walker with a stage aware callback.
Definition: Operation.h:602
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:321
operand_type_iterator operand_type_begin()
Definition: Operation.h:312
This class provides an abstraction over the different types of ranges over Regions.
Definition: Region.h:331
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 implements a use iterator for a range of operation results.
Definition: ValueRange.h:313
This class implements the result iterators for the Operation class.
Definition: ValueRange.h:230
use_range getUses() const
Returns a range of all uses of results within this range, which is useful for iterating over all uses...
bool use_empty() const
Returns true if no results in this range have uses.
Definition: ValueRange.h:260
ValueTypeRange< ResultRange > type_range
Definition: ValueRange.h:241
use_iterator use_begin() const
ValueTypeIterator< iterator > type_iterator
Returns the types of the values within this range.
Definition: ValueRange.h:240
use_iterator use_end() const
type_range getTypes() const
Definition: ValueRange.cpp:35
std::enable_if_t<!std::is_convertible< ValuesT, Operation * >::value > replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this range with the provided 'values'.
Definition: ValueRange.h:269
iterator_range< use_iterator > use_range
Definition: ValueRange.h:251
UseIterator use_iterator
Definition: ValueRange.h:250
This class implements the successor iterators for Block.
Definition: BlockSupport.h:73
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:349
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:118
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:131
An iterator over the users of an IRObject.
Definition: UseDefLists.h:291
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:85
bool isUsedOutsideOfBlock(Block *block)
Returns true if the value is used outside of the given block.
Definition: Value.cpp:90
static unsigned getMaxInlineResults()
Returns the maximum number of results that can be stored inline.
Definition: Value.h:367
This class handles the management of operation operands.
MutableArrayRef< OpOperand > getOperands()
Get the operation operands held by the storage.
void eraseOperands(unsigned start, unsigned length)
Erase the operands held by the storage within the given range.
unsigned size()
Return the number of operands held in the storage.
Include the generated interface declarations.
Definition: CallGraph.h:229
decltype(walk(nullptr, std::declval< FnT >())) walkResultType
Utility to provide the return type of a templated walk method.
Definition: Visitors.h:319
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
Definition: Visitors.cpp:24
Include the generated interface declarations.
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition: Visitors.h:62
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Definition: AliasAnalysis.h:78
static T doCast(::mlir::Operation &val)
Definition: Operation.h:833
static bool isPossible(::mlir::Operation &val)
Definition: Operation.h:832
static bool isPossible(::mlir::Operation *op)
Definition: Operation.h:817
::mlir::Operation * doCast(::mlir::Operation *op)
Definition: Operation.h:850
static bool isPossible(::mlir::Operation *op)
Definition: Operation.h:849
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
This represents an operation in an abstracted form, suitable for use with the builder APIs.