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"
17 #include "mlir/IR/BuiltinAttributes.h"
18 #include "mlir/IR/Diagnostics.h"
19 #include "mlir/IR/OperationSupport.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, BlockOperand, Region,
31                                     detail::OperandStorage> {
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                            ArrayRef<NamedAttribute> attributes,
37                            BlockRange successors, unsigned numRegions);
38 
39   /// Overload of create that takes an existing DictionaryAttr to avoid
40   /// unnecessarily uniquing a list of attributes.
41   static Operation *create(Location location, OperationName name,
42                            TypeRange resultTypes, ValueRange operands,
43                            DictionaryAttr attributes, BlockRange successors,
44                            unsigned numRegions);
45 
46   /// Create a new Operation from the fields stored in `state`.
47   static Operation *create(const OperationState &state);
48 
49   /// Create a new Operation with the specific fields.
50   static Operation *create(Location location, OperationName name,
51                            TypeRange resultTypes, ValueRange operands,
52                            DictionaryAttr attributes,
53                            BlockRange successors = {},
54                            RegionRange regions = {});
55 
56   /// The name of an operation is the key identifier for it.
getName()57   OperationName getName() { return name; }
58 
59   /// If this operation has a registered operation description, return it.
60   /// Otherwise return null.
getAbstractOperation()61   const AbstractOperation *getAbstractOperation() {
62     return getName().getAbstractOperation();
63   }
64 
65   /// Returns true if this operation has a registered operation description,
66   /// otherwise false.
isRegistered()67   bool isRegistered() { return getAbstractOperation(); }
68 
69   /// Remove this operation from its parent block and delete it.
70   void erase();
71 
72   /// Remove the operation from its parent block, but don't delete it.
73   void remove();
74 
75   /// Create a deep copy of this operation, remapping any operands that use
76   /// values outside of the operation using the map that is provided (leaving
77   /// them alone if no entry is present).  Replaces references to cloned
78   /// sub-operations to the corresponding operation that is copied, and adds
79   /// those mappings to the map.
80   Operation *clone(BlockAndValueMapping &mapper);
81   Operation *clone();
82 
83   /// Create a partial copy of this operation without traversing into attached
84   /// regions. The new operation will have the same number of regions as the
85   /// original one, but they will be left empty.
86   /// Operands are remapped using `mapper` (if present), and `mapper` is updated
87   /// to contain the results.
88   Operation *cloneWithoutRegions(BlockAndValueMapping &mapper);
89 
90   /// Create a partial copy of this operation without traversing into attached
91   /// regions. The new operation will have the same number of regions as the
92   /// original one, but they will be left empty.
93   Operation *cloneWithoutRegions();
94 
95   /// Returns the operation block that contains this operation.
getBlock()96   Block *getBlock() { return block; }
97 
98   /// Return the context this operation is associated with.
getContext()99   MLIRContext *getContext() { return location->getContext(); }
100 
101   /// Return the dialect this operation is associated with, or nullptr if the
102   /// associated dialect is not registered.
getDialect()103   Dialect *getDialect() { return getName().getDialect(); }
104 
105   /// The source location the operation was defined or derived from.
getLoc()106   Location getLoc() { return location; }
107 
108   /// Set the source location the operation was defined or derived from.
setLoc(Location loc)109   void setLoc(Location loc) { location = loc; }
110 
111   /// Returns the region to which the instruction belongs. Returns nullptr if
112   /// the instruction is unlinked.
getParentRegion()113   Region *getParentRegion() { return block ? block->getParent() : nullptr; }
114 
115   /// Returns the closest surrounding operation that contains this operation
116   /// or nullptr if this is a top-level operation.
getParentOp()117   Operation *getParentOp() { return block ? block->getParentOp() : nullptr; }
118 
119   /// Return the closest surrounding parent operation that is of type 'OpTy'.
getParentOfType()120   template <typename OpTy> OpTy getParentOfType() {
121     auto *op = this;
122     while ((op = op->getParentOp()))
123       if (auto parentOp = dyn_cast<OpTy>(op))
124         return parentOp;
125     return OpTy();
126   }
127 
128   /// Returns the closest surrounding parent operation with trait `Trait`.
129   template <template <typename T> class Trait>
getParentWithTrait()130   Operation *getParentWithTrait() {
131     Operation *op = this;
132     while ((op = op->getParentOp()))
133       if (op->hasTrait<Trait>())
134         return op;
135     return nullptr;
136   }
137 
138   /// Return true if this operation is a proper ancestor of the `other`
139   /// operation.
140   bool isProperAncestor(Operation *other);
141 
142   /// Return true if this operation is an ancestor of the `other` operation. An
143   /// operation is considered as its own ancestor, use `isProperAncestor` to
144   /// avoid this.
isAncestor(Operation * other)145   bool isAncestor(Operation *other) {
146     return this == other || isProperAncestor(other);
147   }
148 
149   /// Replace any uses of 'from' with 'to' within this operation.
150   void replaceUsesOfWith(Value from, Value to);
151 
152   /// Replace all uses of results of this operation with the provided 'values'.
153   template <typename ValuesT>
154   std::enable_if_t<!std::is_convertible<ValuesT, Operation *>::value>
replaceAllUsesWith(ValuesT && values)155   replaceAllUsesWith(ValuesT &&values) {
156     assert(std::distance(values.begin(), values.end()) == getNumResults() &&
157            "expected 'values' to correspond 1-1 with the number of results");
158 
159     auto valueIt = values.begin();
160     for (unsigned i = 0, e = getNumResults(); i != e; ++i)
161       getResult(i).replaceAllUsesWith(*(valueIt++));
162   }
163 
164   /// Replace all uses of results of this operation with results of 'op'.
replaceAllUsesWith(Operation * op)165   void replaceAllUsesWith(Operation *op) {
166     assert(getNumResults() == op->getNumResults());
167     for (unsigned i = 0, e = getNumResults(); i != e; ++i)
168       getResult(i).replaceAllUsesWith(op->getResult(i));
169   }
170 
171   /// Destroys this operation and its subclass data.
172   void destroy();
173 
174   /// This drops all operand uses from this operation, which is an essential
175   /// step in breaking cyclic dependences between references when they are to
176   /// be deleted.
177   void dropAllReferences();
178 
179   /// Drop uses of all values defined by this operation or its nested regions.
180   void dropAllDefinedValueUses();
181 
182   /// Unlink this operation from its current block and insert it right before
183   /// `existingOp` which may be in the same or another block in the same
184   /// function.
185   void moveBefore(Operation *existingOp);
186 
187   /// Unlink this operation from its current block and insert it right before
188   /// `iterator` in the specified block.
189   void moveBefore(Block *block, llvm::iplist<Operation>::iterator iterator);
190 
191   /// Unlink this operation from its current block and insert it right after
192   /// `existingOp` which may be in the same or another block in the same
193   /// function.
194   void moveAfter(Operation *existingOp);
195 
196   /// Unlink this operation from its current block and insert it right after
197   /// `iterator` in the specified block.
198   void moveAfter(Block *block, llvm::iplist<Operation>::iterator iterator);
199 
200   /// Given an operation 'other' that is within the same parent block, return
201   /// whether the current operation is before 'other' in the operation list
202   /// of the parent block.
203   /// Note: This function has an average complexity of O(1), but worst case may
204   /// take O(N) where N is the number of operations within the parent block.
205   bool isBeforeInBlock(Operation *other);
206 
207   void print(raw_ostream &os, const OpPrintingFlags &flags = llvm::None);
208   void print(raw_ostream &os, AsmState &state,
209              const OpPrintingFlags &flags = llvm::None);
210   void dump();
211 
212   //===--------------------------------------------------------------------===//
213   // Operands
214   //===--------------------------------------------------------------------===//
215 
216   /// Replace the current operands of this operation with the ones provided in
217   /// 'operands'.
218   void setOperands(ValueRange operands);
219 
220   /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
221   /// with the ones provided in 'operands'. 'operands' may be smaller or larger
222   /// than the range pointed to by 'start'+'length'.
223   void setOperands(unsigned start, unsigned length, ValueRange operands);
224 
225   /// Insert the given operands into the operand list at the given 'index'.
226   void insertOperands(unsigned index, ValueRange operands);
227 
getNumOperands()228   unsigned getNumOperands() {
229     return LLVM_LIKELY(hasOperandStorage) ? getOperandStorage().size() : 0;
230   }
231 
getOperand(unsigned idx)232   Value getOperand(unsigned idx) { return getOpOperand(idx).get(); }
setOperand(unsigned idx,Value value)233   void setOperand(unsigned idx, Value value) {
234     return getOpOperand(idx).set(value);
235   }
236 
237   /// Erase the operand at position `idx`.
eraseOperand(unsigned idx)238   void eraseOperand(unsigned idx) { eraseOperands(idx); }
239 
240   /// Erase the operands starting at position `idx` and ending at position
241   /// 'idx'+'length'.
242   void eraseOperands(unsigned idx, unsigned length = 1) {
243     getOperandStorage().eraseOperands(idx, length);
244   }
245 
246   /// Erases the operands that have their corresponding bit set in
247   /// `eraseIndices` and removes them from the operand list.
eraseOperands(const llvm::BitVector & eraseIndices)248   void eraseOperands(const llvm::BitVector &eraseIndices) {
249     getOperandStorage().eraseOperands(eraseIndices);
250   }
251 
252   // Support operand iteration.
253   using operand_range = OperandRange;
254   using operand_iterator = operand_range::iterator;
255 
operand_begin()256   operand_iterator operand_begin() { return getOperands().begin(); }
operand_end()257   operand_iterator operand_end() { return getOperands().end(); }
258 
259   /// Returns an iterator on the underlying Value's.
getOperands()260   operand_range getOperands() { return operand_range(this); }
261 
getOpOperands()262   MutableArrayRef<OpOperand> getOpOperands() {
263     return LLVM_LIKELY(hasOperandStorage) ? getOperandStorage().getOperands()
264                                           : MutableArrayRef<OpOperand>();
265   }
266 
getOpOperand(unsigned idx)267   OpOperand &getOpOperand(unsigned idx) { return getOpOperands()[idx]; }
268 
269   // Support operand type iteration.
270   using operand_type_iterator = operand_range::type_iterator;
271   using operand_type_range = operand_range::type_range;
operand_type_begin()272   operand_type_iterator operand_type_begin() { return operand_begin(); }
operand_type_end()273   operand_type_iterator operand_type_end() { return operand_end(); }
getOperandTypes()274   operand_type_range getOperandTypes() { return getOperands().getTypes(); }
275 
276   //===--------------------------------------------------------------------===//
277   // Results
278   //===--------------------------------------------------------------------===//
279 
280   /// Return the number of results held by this operation.
getNumResults()281   unsigned getNumResults() { return numResults; }
282 
283   /// Get the 'idx'th result of this operation.
getResult(unsigned idx)284   OpResult getResult(unsigned idx) { return OpResult(getOpResultImpl(idx)); }
285 
286   /// Support result iteration.
287   using result_range = ResultRange;
288   using result_iterator = result_range::iterator;
289 
result_begin()290   result_iterator result_begin() { return getResults().begin(); }
result_end()291   result_iterator result_end() { return getResults().end(); }
getResults()292   result_range getResults() {
293     return numResults == 0 ? result_range(nullptr, 0)
294                            : result_range(getInlineOpResult(0), numResults);
295   }
296 
getOpResults()297   result_range getOpResults() { return getResults(); }
getOpResult(unsigned idx)298   OpResult getOpResult(unsigned idx) { return getResult(idx); }
299 
300   /// Support result type iteration.
301   using result_type_iterator = result_range::type_iterator;
302   using result_type_range = result_range::type_range;
result_type_begin()303   result_type_iterator result_type_begin() { return getResultTypes().begin(); }
result_type_end()304   result_type_iterator result_type_end() { return getResultTypes().end(); }
getResultTypes()305   result_type_range getResultTypes() { return getResults().getTypes(); }
306 
307   //===--------------------------------------------------------------------===//
308   // Attributes
309   //===--------------------------------------------------------------------===//
310 
311   // Operations may optionally carry a list of attributes that associate
312   // constants to names.  Attributes may be dynamically added and removed over
313   // the lifetime of an operation.
314 
315   /// Return all of the attributes on this operation.
getAttrs()316   ArrayRef<NamedAttribute> getAttrs() { return attrs.getValue(); }
317 
318   /// Return all of the attributes on this operation as a DictionaryAttr.
getAttrDictionary()319   DictionaryAttr getAttrDictionary() { return attrs; }
320 
321   /// Set the attribute dictionary on this operation.
setAttrs(DictionaryAttr newAttrs)322   void setAttrs(DictionaryAttr newAttrs) {
323     assert(newAttrs && "expected valid attribute dictionary");
324     attrs = newAttrs;
325   }
setAttrs(ArrayRef<NamedAttribute> newAttrs)326   void setAttrs(ArrayRef<NamedAttribute> newAttrs) {
327     setAttrs(DictionaryAttr::get(getContext(), newAttrs));
328   }
329 
330   /// Return the specified attribute if present, null otherwise.
getAttr(Identifier name)331   Attribute getAttr(Identifier name) { return attrs.get(name); }
getAttr(StringRef name)332   Attribute getAttr(StringRef name) { return attrs.get(name); }
333 
getAttrOfType(Identifier name)334   template <typename AttrClass> AttrClass getAttrOfType(Identifier name) {
335     return getAttr(name).dyn_cast_or_null<AttrClass>();
336   }
getAttrOfType(StringRef name)337   template <typename AttrClass> AttrClass getAttrOfType(StringRef name) {
338     return getAttr(name).dyn_cast_or_null<AttrClass>();
339   }
340 
341   /// Return true if the operation has an attribute with the provided name,
342   /// false otherwise.
hasAttr(Identifier name)343   bool hasAttr(Identifier name) { return static_cast<bool>(getAttr(name)); }
hasAttr(StringRef name)344   bool hasAttr(StringRef name) { return static_cast<bool>(getAttr(name)); }
345   template <typename AttrClass, typename NameT>
hasAttrOfType(NameT && name)346   bool hasAttrOfType(NameT &&name) {
347     return static_cast<bool>(
348         getAttrOfType<AttrClass>(std::forward<NameT>(name)));
349   }
350 
351   /// If the an attribute exists with the specified name, change it to the new
352   /// value. Otherwise, add a new attribute with the specified name/value.
setAttr(Identifier name,Attribute value)353   void setAttr(Identifier name, Attribute value) {
354     NamedAttrList attributes(attrs);
355     if (attributes.set(name, value) != value)
356       attrs = attributes.getDictionary(getContext());
357   }
setAttr(StringRef name,Attribute value)358   void setAttr(StringRef name, Attribute value) {
359     setAttr(Identifier::get(name, getContext()), value);
360   }
361 
362   /// Remove the attribute with the specified name if it exists. Return the
363   /// attribute that was erased, or nullptr if there was no attribute with such
364   /// name.
removeAttr(Identifier name)365   Attribute removeAttr(Identifier name) {
366     NamedAttrList attributes(attrs);
367     Attribute removedAttr = attributes.erase(name);
368     if (removedAttr)
369       attrs = attributes.getDictionary(getContext());
370     return removedAttr;
371   }
removeAttr(StringRef name)372   Attribute removeAttr(StringRef name) {
373     return removeAttr(Identifier::get(name, getContext()));
374   }
375 
376   /// A utility iterator that filters out non-dialect attributes.
377   class dialect_attr_iterator
378       : public llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
379                                      bool (*)(NamedAttribute)> {
filter(NamedAttribute attr)380     static bool filter(NamedAttribute attr) {
381       // Dialect attributes are prefixed by the dialect name, like operations.
382       return attr.first.strref().count('.');
383     }
384 
dialect_attr_iterator(ArrayRef<NamedAttribute>::iterator it,ArrayRef<NamedAttribute>::iterator end)385     explicit dialect_attr_iterator(ArrayRef<NamedAttribute>::iterator it,
386                                    ArrayRef<NamedAttribute>::iterator end)
387         : llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
388                                 bool (*)(NamedAttribute)>(it, end, &filter) {}
389 
390     // Allow access to the constructor.
391     friend Operation;
392   };
393   using dialect_attr_range = iterator_range<dialect_attr_iterator>;
394 
395   /// Return a range corresponding to the dialect attributes for this operation.
getDialectAttrs()396   dialect_attr_range getDialectAttrs() {
397     auto attrs = getAttrs();
398     return {dialect_attr_iterator(attrs.begin(), attrs.end()),
399             dialect_attr_iterator(attrs.end(), attrs.end())};
400   }
dialect_attr_begin()401   dialect_attr_iterator dialect_attr_begin() {
402     auto attrs = getAttrs();
403     return dialect_attr_iterator(attrs.begin(), attrs.end());
404   }
dialect_attr_end()405   dialect_attr_iterator dialect_attr_end() {
406     auto attrs = getAttrs();
407     return dialect_attr_iterator(attrs.end(), attrs.end());
408   }
409 
410   /// Set the dialect attributes for this operation, and preserve all dependent.
411   template <typename DialectAttrT>
setDialectAttrs(DialectAttrT && dialectAttrs)412   void setDialectAttrs(DialectAttrT &&dialectAttrs) {
413     NamedAttrList attrs;
414     attrs.append(std::begin(dialectAttrs), std::end(dialectAttrs));
415     for (auto attr : getAttrs())
416       if (!attr.first.strref().contains('.'))
417         attrs.push_back(attr);
418     setAttrs(attrs.getDictionary(getContext()));
419   }
420 
421   //===--------------------------------------------------------------------===//
422   // Blocks
423   //===--------------------------------------------------------------------===//
424 
425   /// Returns the number of regions held by this operation.
getNumRegions()426   unsigned getNumRegions() { return numRegions; }
427 
428   /// Returns the regions held by this operation.
getRegions()429   MutableArrayRef<Region> getRegions() {
430     auto *regions = getTrailingObjects<Region>();
431     return {regions, numRegions};
432   }
433 
434   /// Returns the region held by this operation at position 'index'.
getRegion(unsigned index)435   Region &getRegion(unsigned index) {
436     assert(index < numRegions && "invalid region index");
437     return getRegions()[index];
438   }
439 
440   //===--------------------------------------------------------------------===//
441   // Successors
442   //===--------------------------------------------------------------------===//
443 
getBlockOperands()444   MutableArrayRef<BlockOperand> getBlockOperands() {
445     return {getTrailingObjects<BlockOperand>(), numSuccs};
446   }
447 
448   // Successor iteration.
449   using succ_iterator = SuccessorRange::iterator;
successor_begin()450   succ_iterator successor_begin() { return getSuccessors().begin(); }
successor_end()451   succ_iterator successor_end() { return getSuccessors().end(); }
getSuccessors()452   SuccessorRange getSuccessors() { return SuccessorRange(this); }
453 
hasSuccessors()454   bool hasSuccessors() { return numSuccs != 0; }
getNumSuccessors()455   unsigned getNumSuccessors() { return numSuccs; }
456 
getSuccessor(unsigned index)457   Block *getSuccessor(unsigned index) {
458     assert(index < getNumSuccessors());
459     return getBlockOperands()[index].get();
460   }
461   void setSuccessor(Block *block, unsigned index);
462 
463   //===--------------------------------------------------------------------===//
464   // Accessors for various properties of operations
465   //===--------------------------------------------------------------------===//
466 
467   /// Attempt to fold this operation with the specified constant operand values
468   /// - the elements in "operands" will correspond directly to the operands of
469   /// the operation, but may be null if non-constant. If folding is successful,
470   /// this fills in the `results` vector. If not, `results` is unspecified.
471   LogicalResult fold(ArrayRef<Attribute> operands,
472                      SmallVectorImpl<OpFoldResult> &results);
473 
474   /// Returns true if the operation was registered with a particular trait, e.g.
475   /// hasTrait<OperandsAreSignlessIntegerLike>().
hasTrait()476   template <template <typename T> class Trait> bool hasTrait() {
477     const AbstractOperation *abstractOp = getAbstractOperation();
478     return abstractOp ? abstractOp->hasTrait<Trait>() : false;
479   }
480 
481   /// Returns true if the operation is *might* have the provided trait. This
482   /// means that either the operation is unregistered, or it was registered with
483   /// the provide trait.
mightHaveTrait()484   template <template <typename T> class Trait> bool mightHaveTrait() {
485     const AbstractOperation *abstractOp = getAbstractOperation();
486     return abstractOp ? abstractOp->hasTrait<Trait>() : true;
487   }
488 
489   //===--------------------------------------------------------------------===//
490   // Operation Walkers
491   //===--------------------------------------------------------------------===//
492 
493   /// Walk the operation by calling the callback for each nested operation
494   /// (including this one), block or region, depending on the callback provided.
495   /// Regions, blocks and operations at the same nesting level are visited in
496   /// lexicographical order. The walk order for enclosing regions, blocks and
497   /// operations with respect to their nested ones is specified by 'Order'
498   /// (post-order by default). A callback on a block or operation is allowed to
499   /// erase that block or operation if either:
500   ///   * the walk is in post-order, or
501   ///   * the walk is in pre-order and the walk is skipped after the erasure.
502   ///
503   /// The callback method can take any of the following forms:
504   ///   void(Operation*) : Walk all operations opaquely.
505   ///     * op->walk([](Operation *nestedOp) { ...});
506   ///   void(OpT) : Walk all operations of the given derived type.
507   ///     * op->walk([](ReturnOp returnOp) { ...});
508   ///   WalkResult(Operation*|OpT) : Walk operations, but allow for
509   ///                                interruption/skipping.
510   ///     * op->walk([](... op) {
511   ///         // Skip the walk of this op based on some invariant.
512   ///         if (some_invariant)
513   ///           return WalkResult::skip();
514   ///         // Interrupt, i.e cancel, the walk based on some invariant.
515   ///         if (another_invariant)
516   ///           return WalkResult::interrupt();
517   ///         return WalkResult::advance();
518   ///       });
519   template <WalkOrder Order = WalkOrder::PostOrder, typename FnT,
520             typename RetT = detail::walkResultType<FnT>>
walk(FnT && callback)521   RetT walk(FnT &&callback) {
522     return detail::walk<Order>(this, std::forward<FnT>(callback));
523   }
524 
525   //===--------------------------------------------------------------------===//
526   // Uses
527   //===--------------------------------------------------------------------===//
528 
529   /// Drop all uses of results of this operation.
dropAllUses()530   void dropAllUses() {
531     for (OpResult result : getOpResults())
532       result.dropAllUses();
533   }
534 
535   using use_iterator = result_range::use_iterator;
536   using use_range = result_range::use_range;
537 
use_begin()538   use_iterator use_begin() { return getResults().use_begin(); }
use_end()539   use_iterator use_end() { return getResults().use_end(); }
540 
541   /// Returns a range of all uses, which is useful for iterating over all uses.
getUses()542   use_range getUses() { return getResults().getUses(); }
543 
544   /// Returns true if this operation has exactly one use.
hasOneUse()545   bool hasOneUse() { return llvm::hasSingleElement(getUses()); }
546 
547   /// Returns true if this operation has no uses.
use_empty()548   bool use_empty() { return getResults().use_empty(); }
549 
550   /// Returns true if the results of this operation are used outside of the
551   /// given block.
isUsedOutsideOfBlock(Block * block)552   bool isUsedOutsideOfBlock(Block *block) {
553     return llvm::any_of(getOpResults(), [block](OpResult result) {
554       return result.isUsedOutsideOfBlock(block);
555     });
556   }
557 
558   //===--------------------------------------------------------------------===//
559   // Users
560   //===--------------------------------------------------------------------===//
561 
562   using user_iterator = ValueUserIterator<use_iterator, OpOperand>;
563   using user_range = iterator_range<user_iterator>;
564 
user_begin()565   user_iterator user_begin() { return user_iterator(use_begin()); }
user_end()566   user_iterator user_end() { return user_iterator(use_end()); }
567 
568   /// Returns a range of all users.
getUsers()569   user_range getUsers() { return {user_begin(), user_end()}; }
570 
571   //===--------------------------------------------------------------------===//
572   // Other
573   //===--------------------------------------------------------------------===//
574 
575   /// Emit an error with the op name prefixed, like "'dim' op " which is
576   /// convenient for verifiers.
577   InFlightDiagnostic emitOpError(const Twine &message = {});
578 
579   /// Emit an error about fatal conditions with this operation, reporting up to
580   /// any diagnostic handlers that may be listening.
581   InFlightDiagnostic emitError(const Twine &message = {});
582 
583   /// Emit a warning about this operation, reporting up to any diagnostic
584   /// handlers that may be listening.
585   InFlightDiagnostic emitWarning(const Twine &message = {});
586 
587   /// Emit a remark about this operation, reporting up to any diagnostic
588   /// handlers that may be listening.
589   InFlightDiagnostic emitRemark(const Twine &message = {});
590 
591 private:
592   //===--------------------------------------------------------------------===//
593   // Ordering
594   //===--------------------------------------------------------------------===//
595 
596   /// This value represents an invalid index ordering for an operation within a
597   /// block.
598   static constexpr unsigned kInvalidOrderIdx = -1;
599 
600   /// This value represents the stride to use when computing a new order for an
601   /// operation.
602   static constexpr unsigned kOrderStride = 5;
603 
604   /// Update the order index of this operation of this operation if necessary,
605   /// potentially recomputing the order of the parent block.
606   void updateOrderIfNecessary();
607 
608   /// Returns true if this operation has a valid order.
hasValidOrder()609   bool hasValidOrder() { return orderIndex != kInvalidOrderIdx; }
610 
611 private:
612   Operation(Location location, OperationName name, unsigned numResults,
613             unsigned numSuccessors, unsigned numRegions,
614             DictionaryAttr attributes, bool hasOperandStorage);
615 
616   // Operations are deleted through the destroy() member because they are
617   // allocated with malloc.
618   ~Operation();
619 
620   /// Returns the additional size necessary for allocating the given objects
621   /// before an Operation in-memory.
prefixAllocSize(unsigned numOutOfLineResults,unsigned numInlineResults)622   static size_t prefixAllocSize(unsigned numOutOfLineResults,
623                                 unsigned numInlineResults) {
624     return sizeof(detail::OutOfLineOpResult) * numOutOfLineResults +
625            sizeof(detail::InlineOpResult) * numInlineResults;
626   }
627   /// Returns the additional size allocated before this Operation in-memory.
prefixAllocSize()628   size_t prefixAllocSize() {
629     unsigned numResults = getNumResults();
630     unsigned numOutOfLineResults = OpResult::getNumTrailing(numResults);
631     unsigned numInlineResults = OpResult::getNumInline(numResults);
632     return prefixAllocSize(numOutOfLineResults, numInlineResults);
633   }
634 
635   /// Returns the operand storage object.
getOperandStorage()636   detail::OperandStorage &getOperandStorage() {
637     assert(hasOperandStorage && "expected operation to have operand storage");
638     return *getTrailingObjects<detail::OperandStorage>();
639   }
640 
641   /// Returns a pointer to the use list for the given out-of-line result.
getOutOfLineOpResult(unsigned resultNumber)642   detail::OutOfLineOpResult *getOutOfLineOpResult(unsigned resultNumber) {
643     // Out-of-line results are stored in reverse order after (before in memory)
644     // the inline results.
645     return reinterpret_cast<detail::OutOfLineOpResult *>(getInlineOpResult(
646                detail::OpResultImpl::getMaxInlineResults() - 1)) -
647            ++resultNumber;
648   }
649 
650   /// Returns a pointer to the use list for the given inline result.
getInlineOpResult(unsigned resultNumber)651   detail::InlineOpResult *getInlineOpResult(unsigned resultNumber) {
652     // Inline results are stored in reverse order before the operation in
653     // memory.
654     return reinterpret_cast<detail::InlineOpResult *>(this) - ++resultNumber;
655   }
656 
657   /// Returns a pointer to the use list for the given result, which may be
658   /// either inline or out-of-line.
getOpResultImpl(unsigned resultNumber)659   detail::OpResultImpl *getOpResultImpl(unsigned resultNumber) {
660     unsigned maxInlineResults = detail::OpResultImpl::getMaxInlineResults();
661     if (resultNumber < maxInlineResults)
662       return getInlineOpResult(resultNumber);
663     return getOutOfLineOpResult(resultNumber - maxInlineResults);
664   }
665 
666   /// Provide a 'getParent' method for ilist_node_with_parent methods.
667   /// We mark it as a const function because ilist_node_with_parent specifically
668   /// requires a 'getParent() const' method. Once ilist_node removes this
669   /// constraint, we should drop the const to fit the rest of the MLIR const
670   /// model.
getParent()671   Block *getParent() const { return block; }
672 
673   /// The operation block that contains this operation.
674   Block *block = nullptr;
675 
676   /// This holds information about the source location the operation was defined
677   /// or derived from.
678   Location location;
679 
680   /// Relative order of this operation in its parent block. Used for
681   /// O(1) local dominance checks between operations.
682   mutable unsigned orderIndex = 0;
683 
684   const unsigned numResults;
685   const unsigned numSuccs;
686   const unsigned numRegions : 31;
687 
688   /// This bit signals whether this operation has an operand storage or not. The
689   /// operand storage may be elided for operations that are known to never have
690   /// operands.
691   bool hasOperandStorage : 1;
692 
693   /// This holds the name of the operation.
694   OperationName name;
695 
696   /// This holds general named attributes for the operation.
697   DictionaryAttr attrs;
698 
699   // allow ilist_traits access to 'block' field.
700   friend struct llvm::ilist_traits<Operation>;
701 
702   // allow block to access the 'orderIndex' field.
703   friend class Block;
704 
705   // allow value to access the 'ResultStorage' methods.
706   friend class Value;
707 
708   // allow ilist_node_with_parent to access the 'getParent' method.
709   friend class llvm::ilist_node_with_parent<Operation, Block>;
710 
711   // This stuff is used by the TrailingObjects template.
712   friend llvm::TrailingObjects<Operation, BlockOperand, Region,
713                                detail::OperandStorage>;
714   size_t numTrailingObjects(OverloadToken<BlockOperand>) const {
715     return numSuccs;
716   }
717   size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; }
718 };
719 
720 inline raw_ostream &operator<<(raw_ostream &os, const Operation &op) {
721   const_cast<Operation &>(op).print(os, OpPrintingFlags().useLocalScope());
722   return os;
723 }
724 
725 } // end namespace mlir
726 
727 namespace llvm {
728 /// Provide isa functionality for operation casts.
729 template <typename T> struct isa_impl<T, ::mlir::Operation> {
730   static inline bool doit(const ::mlir::Operation &op) {
731     return T::classof(const_cast<::mlir::Operation *>(&op));
732   }
733 };
734 
735 /// Provide specializations for operation casts as the resulting T is value
736 /// typed.
737 template <typename T> struct cast_retty_impl<T, ::mlir::Operation *> {
738   using ret_type = T;
739 };
740 template <typename T> struct cast_retty_impl<T, ::mlir::Operation> {
741   using ret_type = T;
742 };
743 template <class T>
744 struct cast_convert_val<T, ::mlir::Operation, ::mlir::Operation> {
745   static T doit(::mlir::Operation &val) { return T(&val); }
746 };
747 template <class T>
748 struct cast_convert_val<T, ::mlir::Operation *, ::mlir::Operation *> {
749   static T doit(::mlir::Operation *val) { return T(val); }
750 };
751 } // end namespace llvm
752 
753 #endif // MLIR_IR_OPERATION_H
754