xref: /llvm-project/mlir/include/mlir/IR/Operation.h (revision 644643a4ee931ce24c27702851a93160cf0f1248)
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 #include <optional>
23 
24 namespace mlir {
25 namespace detail {
26 /// This is a "tag" used for mapping the properties storage in
27 /// llvm::TrailingObjects.
28 enum class OpProperties : char {};
29 } // namespace detail
30 
31 /// Operation is the basic unit of execution within MLIR.
32 ///
33 /// The following documentation are recommended to understand this class:
34 /// - https://mlir.llvm.org/docs/LangRef/#operations
35 /// - https://mlir.llvm.org/docs/Tutorials/UnderstandingTheIRStructure/
36 ///
37 /// An Operation is defined first by its name, which is a unique string. The
38 /// name is interpreted so that if it contains a '.' character, the part before
39 /// is the dialect name this operation belongs to, and everything that follows
40 /// is this operation name within the dialect.
41 ///
42 /// An Operation defines zero or more SSA `Value` that we refer to as the
43 /// Operation results. This array of Value is actually stored in memory before
44 /// the Operation itself in reverse order. That is for an Operation with 3
45 /// results we allocate the following memory layout:
46 ///
47 ///  [Result2, Result1, Result0, Operation]
48 ///                              ^ this is where `Operation*` pointer points to.
49 ///
50 /// A consequence of this is that this class must be heap allocated, which is
51 /// handled by the various `create` methods. Each result contains:
52 ///  - one pointer to the first use (see `OpOperand`)
53 ///  - the type of the SSA Value this result defines.
54 ///  - the index for this result in the array.
55 /// The results are defined as subclass of `ValueImpl`, and more precisely as
56 /// the only two subclasses of `OpResultImpl`: `InlineOpResult` and
57 /// `OutOfLineOpResult`. The former is used for the first 5 results and the
58 /// latter for the subsequent ones. They differ in how they store their index:
59 /// the first 5 results only need 3 bits and thus are packed with the Type
60 /// pointer, while the subsequent one have an extra `unsigned` value and thus
61 /// need more space.
62 ///
63 /// An Operation also has zero or more operands: these are uses of SSA Value,
64 /// which can be the results of other operations or Block arguments. Each of
65 /// these uses is an instance of `OpOperand`. This optional array is initially
66 /// tail allocated with the operation class itself, but can be dynamically moved
67 /// out-of-line in a dynamic allocation as needed.
68 ///
69 /// An Operation may contain optionally one or multiple Regions, stored in a
70 /// tail allocated array. Each `Region` is a list of Blocks. Each `Block` is
71 /// itself a list of Operations. This structure is effectively forming a tree.
72 ///
73 /// Some operations like branches also refer to other Block, in which case they
74 /// would have an array of `BlockOperand`.
75 ///
76 /// An Operation may contain optionally a "Properties" object: this is a
77 /// pre-defined C++ object with a fixed size. This object is owned by the
78 /// operation and deleted with the operation. It can be converted to an
79 /// Attribute on demand, or loaded from an Attribute.
80 ///
81 ///
82 /// Finally an Operation also contain an optional `DictionaryAttr`, a Location,
83 /// and a pointer to its parent Block (if any).
84 class alignas(8) Operation final
85     : public llvm::ilist_node_with_parent<Operation, Block>,
86       private llvm::TrailingObjects<Operation, detail::OperandStorage,
87                                     detail::OpProperties, BlockOperand, Region,
88                                     OpOperand> {
89 public:
90   /// Create a new Operation with the specific fields. This constructor
91   /// populates the provided attribute list with default attributes if
92   /// necessary.
93   static Operation *create(Location location, OperationName name,
94                            TypeRange resultTypes, ValueRange operands,
95                            NamedAttrList &&attributes,
96                            OpaqueProperties properties, BlockRange successors,
97                            unsigned numRegions);
98 
99   /// Create a new Operation with the specific fields. This constructor uses an
100   /// existing attribute dictionary to avoid uniquing a list of attributes.
101   static Operation *create(Location location, OperationName name,
102                            TypeRange resultTypes, ValueRange operands,
103                            DictionaryAttr attributes,
104                            OpaqueProperties properties, BlockRange successors,
105                            unsigned numRegions);
106 
107   /// Create a new Operation from the fields stored in `state`.
108   static Operation *create(const OperationState &state);
109 
110   /// Create a new Operation with the specific fields.
111   static Operation *create(Location location, OperationName name,
112                            TypeRange resultTypes, ValueRange operands,
113                            NamedAttrList &&attributes,
114                            OpaqueProperties properties,
115                            BlockRange successors = {},
116                            RegionRange regions = {});
117 
118   /// The name of an operation is the key identifier for it.
119   OperationName getName() { return name; }
120 
121   /// If this operation has a registered operation description, return it.
122   /// Otherwise return std::nullopt.
123   std::optional<RegisteredOperationName> getRegisteredInfo() {
124     return getName().getRegisteredInfo();
125   }
126 
127   /// Returns true if this operation has a registered operation description,
128   /// otherwise false.
129   bool isRegistered() { return getName().isRegistered(); }
130 
131   /// Remove this operation from its parent block and delete it.
132   void erase();
133 
134   /// Remove the operation from its parent block, but don't delete it.
135   void remove();
136 
137   /// Class encompassing various options related to cloning an operation. Users
138   /// of this class should pass it to Operation's 'clone' methods.
139   /// Current options include:
140   /// * Whether cloning should recursively traverse into the regions of the
141   ///   operation or not.
142   /// * Whether cloning should also clone the operands of the operation.
143   class CloneOptions {
144   public:
145     /// Default constructs an option with all flags set to false. That means all
146     /// parts of an operation that may optionally not be cloned, are not cloned.
147     CloneOptions();
148 
149     /// Constructs an instance with the clone regions and clone operands flags
150     /// set accordingly.
151     CloneOptions(bool cloneRegions, bool cloneOperands);
152 
153     /// Returns an instance with all flags set to true. This is the default
154     /// when using the clone method and clones all parts of the operation.
155     static CloneOptions all();
156 
157     /// Configures whether cloning should traverse into any of the regions of
158     /// the operation. If set to true, the operation's regions are recursively
159     /// cloned. If set to false, cloned operations will have the same number of
160     /// regions, but they will be empty.
161     /// Cloning of nested operations in the operation's regions are currently
162     /// unaffected by other flags.
163     CloneOptions &cloneRegions(bool enable = true);
164 
165     /// Returns whether regions of the operation should be cloned as well.
166     bool shouldCloneRegions() const { return cloneRegionsFlag; }
167 
168     /// Configures whether operation' operands should be cloned. Otherwise the
169     /// resulting clones will simply have zero operands.
170     CloneOptions &cloneOperands(bool enable = true);
171 
172     /// Returns whether operands should be cloned as well.
173     bool shouldCloneOperands() const { return cloneOperandsFlag; }
174 
175   private:
176     /// Whether regions should be cloned.
177     bool cloneRegionsFlag : 1;
178     /// Whether operands should be cloned.
179     bool cloneOperandsFlag : 1;
180   };
181 
182   /// Create a deep copy of this operation, remapping any operands that use
183   /// values outside of the operation using the map that is provided (leaving
184   /// them alone if no entry is present).  Replaces references to cloned
185   /// sub-operations to the corresponding operation that is copied, and adds
186   /// those mappings to the map.
187   /// Optionally, one may configure what parts of the operation to clone using
188   /// the options parameter.
189   ///
190   /// Calling this method from multiple threads is generally safe if through the
191   /// process of cloning no new uses of 'Value's from outside the operation are
192   /// created. Cloning an isolated-from-above operation with no operands, such
193   /// as top level function operations, is therefore always safe. Using the
194   /// mapper, it is possible to avoid adding uses to outside operands by
195   /// remapping them to 'Value's owned by the caller thread.
196   Operation *clone(IRMapping &mapper,
197                    CloneOptions options = CloneOptions::all());
198   Operation *clone(CloneOptions options = CloneOptions::all());
199 
200   /// Create a partial copy of this operation without traversing into attached
201   /// regions. The new operation will have the same number of regions as the
202   /// original one, but they will be left empty.
203   /// Operands are remapped using `mapper` (if present), and `mapper` is updated
204   /// to contain the results.
205   Operation *cloneWithoutRegions(IRMapping &mapper);
206 
207   /// Create a partial copy of this operation without traversing into attached
208   /// regions. The new operation will have the same number of regions as the
209   /// original one, but they will be left empty.
210   Operation *cloneWithoutRegions();
211 
212   /// Returns the operation block that contains this operation.
213   Block *getBlock() { return block; }
214 
215   /// Return the context this operation is associated with.
216   MLIRContext *getContext() { return location->getContext(); }
217 
218   /// Return the dialect this operation is associated with, or nullptr if the
219   /// associated dialect is not loaded.
220   Dialect *getDialect() { return getName().getDialect(); }
221 
222   /// The source location the operation was defined or derived from.
223   Location getLoc() { return location; }
224 
225   /// Set the source location the operation was defined or derived from.
226   void setLoc(Location loc) { location = loc; }
227 
228   /// Returns the region to which the instruction belongs. Returns nullptr if
229   /// the instruction is unlinked.
230   Region *getParentRegion() { return block ? block->getParent() : nullptr; }
231 
232   /// Returns the closest surrounding operation that contains this operation
233   /// or nullptr if this is a top-level operation.
234   Operation *getParentOp() { return block ? block->getParentOp() : nullptr; }
235 
236   /// Return the closest surrounding parent operation that is of type 'OpTy'.
237   template <typename OpTy>
238   OpTy getParentOfType() {
239     auto *op = this;
240     while ((op = op->getParentOp()))
241       if (auto parentOp = dyn_cast<OpTy>(op))
242         return parentOp;
243     return OpTy();
244   }
245 
246   /// Returns the closest surrounding parent operation with trait `Trait`.
247   template <template <typename T> class Trait>
248   Operation *getParentWithTrait() {
249     Operation *op = this;
250     while ((op = op->getParentOp()))
251       if (op->hasTrait<Trait>())
252         return op;
253     return nullptr;
254   }
255 
256   /// Return true if this operation is a proper ancestor of the `other`
257   /// operation.
258   bool isProperAncestor(Operation *other);
259 
260   /// Return true if this operation is an ancestor of the `other` operation. An
261   /// operation is considered as its own ancestor, use `isProperAncestor` to
262   /// avoid this.
263   bool isAncestor(Operation *other) {
264     return this == other || isProperAncestor(other);
265   }
266 
267   /// Replace any uses of 'from' with 'to' within this operation.
268   void replaceUsesOfWith(Value from, Value to);
269 
270   /// Replace all uses of results of this operation with the provided 'values'.
271   template <typename ValuesT>
272   void replaceAllUsesWith(ValuesT &&values) {
273     getResults().replaceAllUsesWith(std::forward<ValuesT>(values));
274   }
275 
276   /// Replace uses of results of this operation with the provided `values` if
277   /// the given callback returns true.
278   template <typename ValuesT>
279   void replaceUsesWithIf(ValuesT &&values,
280                          function_ref<bool(OpOperand &)> shouldReplace) {
281     getResults().replaceUsesWithIf(std::forward<ValuesT>(values),
282                                    shouldReplace);
283   }
284 
285   /// Destroys this operation and its subclass data.
286   void destroy();
287 
288   /// This drops all operand uses from this operation, which is an essential
289   /// step in breaking cyclic dependences between references when they are to
290   /// be deleted.
291   void dropAllReferences();
292 
293   /// Drop uses of all values defined by this operation or its nested regions.
294   void dropAllDefinedValueUses();
295 
296   /// Unlink this operation from its current block and insert it right before
297   /// `existingOp` which may be in the same or another block in the same
298   /// function.
299   void moveBefore(Operation *existingOp);
300 
301   /// Unlink this operation from its current block and insert it right before
302   /// `iterator` in the specified block.
303   void moveBefore(Block *block, llvm::iplist<Operation>::iterator iterator);
304 
305   /// Unlink this operation from its current block and insert it right after
306   /// `existingOp` which may be in the same or another block in the same
307   /// function.
308   void moveAfter(Operation *existingOp);
309 
310   /// Unlink this operation from its current block and insert it right after
311   /// `iterator` in the specified block.
312   void moveAfter(Block *block, llvm::iplist<Operation>::iterator iterator);
313 
314   /// Given an operation 'other' that is within the same parent block, return
315   /// whether the current operation is before 'other' in the operation list
316   /// of the parent block.
317   /// Note: This function has an average complexity of O(1), but worst case may
318   /// take O(N) where N is the number of operations within the parent block.
319   bool isBeforeInBlock(Operation *other);
320 
321   void print(raw_ostream &os, const OpPrintingFlags &flags = std::nullopt);
322   void print(raw_ostream &os, AsmState &state);
323   void dump();
324 
325   // Dump pretty printed IR. This method is helpful for better readability if
326   // the Operation is not verified because it won't disable custom printers to
327   // fall back to the generic one.
328   LLVM_DUMP_METHOD void dumpPretty();
329 
330   //===--------------------------------------------------------------------===//
331   // Operands
332   //===--------------------------------------------------------------------===//
333 
334   /// Replace the current operands of this operation with the ones provided in
335   /// 'operands'.
336   void setOperands(ValueRange operands);
337 
338   /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
339   /// with the ones provided in 'operands'. 'operands' may be smaller or larger
340   /// than the range pointed to by 'start'+'length'.
341   void setOperands(unsigned start, unsigned length, ValueRange operands);
342 
343   /// Insert the given operands into the operand list at the given 'index'.
344   void insertOperands(unsigned index, ValueRange operands);
345 
346   unsigned getNumOperands() {
347     return LLVM_LIKELY(hasOperandStorage) ? getOperandStorage().size() : 0;
348   }
349 
350   Value getOperand(unsigned idx) { return getOpOperand(idx).get(); }
351   void setOperand(unsigned idx, Value value) {
352     return getOpOperand(idx).set(value);
353   }
354 
355   /// Erase the operand at position `idx`.
356   void eraseOperand(unsigned idx) { eraseOperands(idx); }
357 
358   /// Erase the operands starting at position `idx` and ending at position
359   /// 'idx'+'length'.
360   void eraseOperands(unsigned idx, unsigned length = 1) {
361     getOperandStorage().eraseOperands(idx, length);
362   }
363 
364   /// Erases the operands that have their corresponding bit set in
365   /// `eraseIndices` and removes them from the operand list.
366   void eraseOperands(const BitVector &eraseIndices) {
367     getOperandStorage().eraseOperands(eraseIndices);
368   }
369 
370   // Support operand iteration.
371   using operand_range = OperandRange;
372   using operand_iterator = operand_range::iterator;
373 
374   operand_iterator operand_begin() { return getOperands().begin(); }
375   operand_iterator operand_end() { return getOperands().end(); }
376 
377   /// Returns an iterator on the underlying Value's.
378   operand_range getOperands() {
379     MutableArrayRef<OpOperand> operands = getOpOperands();
380     return OperandRange(operands.data(), operands.size());
381   }
382 
383   MutableArrayRef<OpOperand> getOpOperands() {
384     return LLVM_LIKELY(hasOperandStorage) ? getOperandStorage().getOperands()
385                                           : MutableArrayRef<OpOperand>();
386   }
387 
388   OpOperand &getOpOperand(unsigned idx) {
389     return getOperandStorage().getOperands()[idx];
390   }
391 
392   // Support operand type iteration.
393   using operand_type_iterator = operand_range::type_iterator;
394   using operand_type_range = operand_range::type_range;
395   operand_type_iterator operand_type_begin() { return operand_begin(); }
396   operand_type_iterator operand_type_end() { return operand_end(); }
397   operand_type_range getOperandTypes() { return getOperands().getTypes(); }
398 
399   //===--------------------------------------------------------------------===//
400   // Results
401   //===--------------------------------------------------------------------===//
402 
403   /// Return the number of results held by this operation.
404   unsigned getNumResults() { return numResults; }
405 
406   /// Get the 'idx'th result of this operation.
407   OpResult getResult(unsigned idx) { return OpResult(getOpResultImpl(idx)); }
408 
409   /// Support result iteration.
410   using result_range = ResultRange;
411   using result_iterator = result_range::iterator;
412 
413   result_iterator result_begin() { return getResults().begin(); }
414   result_iterator result_end() { return getResults().end(); }
415   result_range getResults() {
416     return numResults == 0 ? result_range(nullptr, 0)
417                            : result_range(getInlineOpResult(0), numResults);
418   }
419 
420   result_range getOpResults() { return getResults(); }
421   OpResult getOpResult(unsigned idx) { return getResult(idx); }
422 
423   /// Support result type iteration.
424   using result_type_iterator = result_range::type_iterator;
425   using result_type_range = result_range::type_range;
426   result_type_iterator result_type_begin() { return getResultTypes().begin(); }
427   result_type_iterator result_type_end() { return getResultTypes().end(); }
428   result_type_range getResultTypes() { return getResults().getTypes(); }
429 
430   //===--------------------------------------------------------------------===//
431   // Attributes
432   //===--------------------------------------------------------------------===//
433 
434   // Operations may optionally carry a list of attributes that associate
435   // constants to names.  Attributes may be dynamically added and removed over
436   // the lifetime of an operation.
437 
438   /// Access an inherent attribute by name: returns an empty optional if there
439   /// is no inherent attribute with this name.
440   ///
441   /// This method is available as a transient facility in the migration process
442   /// to use Properties instead.
443   std::optional<Attribute> getInherentAttr(StringRef name);
444 
445   /// Set an inherent attribute by name.
446   ///
447   /// This method is available as a transient facility in the migration process
448   /// to use Properties instead.
449   void setInherentAttr(StringAttr name, Attribute value);
450 
451   /// Access a discardable attribute by name, returns an null Attribute if the
452   /// discardable attribute does not exist.
453   Attribute getDiscardableAttr(StringRef name) { return attrs.get(name); }
454 
455   /// Access a discardable attribute by name, returns an null Attribute if the
456   /// discardable attribute does not exist.
457   Attribute getDiscardableAttr(StringAttr name) { return attrs.get(name); }
458 
459   /// Set a discardable attribute by name.
460   void setDiscardableAttr(StringAttr name, Attribute value) {
461     NamedAttrList attributes(attrs);
462     if (attributes.set(name, value) != value)
463       attrs = attributes.getDictionary(getContext());
464   }
465   void setDiscardableAttr(StringRef name, Attribute value) {
466     setDiscardableAttr(StringAttr::get(getContext(), name), value);
467   }
468 
469   /// Remove the discardable attribute with the specified name if it exists.
470   /// Return the attribute that was erased, or nullptr if there was no attribute
471   /// with such name.
472   Attribute removeDiscardableAttr(StringAttr name) {
473     NamedAttrList attributes(attrs);
474     Attribute removedAttr = attributes.erase(name);
475     if (removedAttr)
476       attrs = attributes.getDictionary(getContext());
477     return removedAttr;
478   }
479   Attribute removeDiscardableAttr(StringRef name) {
480     return removeDiscardableAttr(StringAttr::get(getContext(), name));
481   }
482 
483   /// Return a range of all of discardable attributes on this operation. Note
484   /// that for unregistered operations that are not storing inherent attributes
485   /// as properties, all attributes are considered discardable.
486   auto getDiscardableAttrs() {
487     std::optional<RegisteredOperationName> opName = getRegisteredInfo();
488     ArrayRef<StringAttr> attributeNames =
489         opName ? getRegisteredInfo()->getAttributeNames()
490                : ArrayRef<StringAttr>();
491     return llvm::make_filter_range(
492         attrs.getValue(),
493         [this, attributeNames](const NamedAttribute attribute) {
494           return getPropertiesStorage() ||
495                  !llvm::is_contained(attributeNames, attribute.getName());
496         });
497   }
498 
499   /// Return all of the discardable attributes on this operation as a
500   /// DictionaryAttr.
501   DictionaryAttr getDiscardableAttrDictionary() {
502     if (getPropertiesStorage())
503       return attrs;
504     return DictionaryAttr::get(getContext(),
505                                llvm::to_vector(getDiscardableAttrs()));
506   }
507 
508   /// Return all attributes that are not stored as properties.
509   DictionaryAttr getRawDictionaryAttrs() { return attrs; }
510 
511   /// Return all of the attributes on this operation.
512   ArrayRef<NamedAttribute> getAttrs() { return getAttrDictionary().getValue(); }
513 
514   /// Return all of the attributes on this operation as a DictionaryAttr.
515   DictionaryAttr getAttrDictionary();
516 
517   /// Set the attributes from a dictionary on this operation.
518   /// These methods are expensive: if the dictionnary only contains discardable
519   /// attributes, `setDiscardableAttrs` is more efficient.
520   void setAttrs(DictionaryAttr newAttrs);
521   void setAttrs(ArrayRef<NamedAttribute> newAttrs);
522   /// Set the discardable attribute dictionary on this operation.
523   void setDiscardableAttrs(DictionaryAttr newAttrs) {
524     assert(newAttrs && "expected valid attribute dictionary");
525     attrs = newAttrs;
526   }
527   void setDiscardableAttrs(ArrayRef<NamedAttribute> newAttrs) {
528     setDiscardableAttrs(DictionaryAttr::get(getContext(), newAttrs));
529   }
530 
531   /// Return the specified attribute if present, null otherwise.
532   /// These methods are expensive: if the dictionnary only contains discardable
533   /// attributes, `getDiscardableAttr` is more efficient.
534   Attribute getAttr(StringAttr name) {
535     if (getPropertiesStorageSize()) {
536       if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
537         return *inherentAttr;
538     }
539     return attrs.get(name);
540   }
541   Attribute getAttr(StringRef name) {
542     if (getPropertiesStorageSize()) {
543       if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
544         return *inherentAttr;
545     }
546     return attrs.get(name);
547   }
548 
549   template <typename AttrClass>
550   AttrClass getAttrOfType(StringAttr name) {
551     return llvm::dyn_cast_or_null<AttrClass>(getAttr(name));
552   }
553   template <typename AttrClass>
554   AttrClass getAttrOfType(StringRef name) {
555     return llvm::dyn_cast_or_null<AttrClass>(getAttr(name));
556   }
557 
558   /// Return true if the operation has an attribute with the provided name,
559   /// false otherwise.
560   bool hasAttr(StringAttr name) {
561     if (getPropertiesStorageSize()) {
562       if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
563         return (bool)*inherentAttr;
564     }
565     return attrs.contains(name);
566   }
567   bool hasAttr(StringRef name) {
568     if (getPropertiesStorageSize()) {
569       if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
570         return (bool)*inherentAttr;
571     }
572     return attrs.contains(name);
573   }
574   template <typename AttrClass, typename NameT>
575   bool hasAttrOfType(NameT &&name) {
576     return static_cast<bool>(
577         getAttrOfType<AttrClass>(std::forward<NameT>(name)));
578   }
579 
580   /// If the an attribute exists with the specified name, change it to the new
581   /// value. Otherwise, add a new attribute with the specified name/value.
582   void setAttr(StringAttr name, Attribute value) {
583     if (getPropertiesStorageSize()) {
584       if (getInherentAttr(name)) {
585         setInherentAttr(name, value);
586         return;
587       }
588     }
589     NamedAttrList attributes(attrs);
590     if (attributes.set(name, value) != value)
591       attrs = attributes.getDictionary(getContext());
592   }
593   void setAttr(StringRef name, Attribute value) {
594     setAttr(StringAttr::get(getContext(), name), value);
595   }
596 
597   /// Remove the attribute with the specified name if it exists. Return the
598   /// attribute that was erased, or nullptr if there was no attribute with such
599   /// name.
600   Attribute removeAttr(StringAttr name) {
601     if (getPropertiesStorageSize()) {
602       if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) {
603         setInherentAttr(name, {});
604         return *inherentAttr;
605       }
606     }
607     NamedAttrList attributes(attrs);
608     Attribute removedAttr = attributes.erase(name);
609     if (removedAttr)
610       attrs = attributes.getDictionary(getContext());
611     return removedAttr;
612   }
613   Attribute removeAttr(StringRef name) {
614     return removeAttr(StringAttr::get(getContext(), name));
615   }
616 
617   /// A utility iterator that filters out non-dialect attributes.
618   class dialect_attr_iterator
619       : public llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
620                                      bool (*)(NamedAttribute)> {
621     static bool filter(NamedAttribute attr) {
622       // Dialect attributes are prefixed by the dialect name, like operations.
623       return attr.getName().strref().count('.');
624     }
625 
626     explicit dialect_attr_iterator(ArrayRef<NamedAttribute>::iterator it,
627                                    ArrayRef<NamedAttribute>::iterator end)
628         : llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
629                                 bool (*)(NamedAttribute)>(it, end, &filter) {}
630 
631     // Allow access to the constructor.
632     friend Operation;
633   };
634   using dialect_attr_range = iterator_range<dialect_attr_iterator>;
635 
636   /// Return a range corresponding to the dialect attributes for this operation.
637   dialect_attr_range getDialectAttrs() {
638     auto attrs = getAttrs();
639     return {dialect_attr_iterator(attrs.begin(), attrs.end()),
640             dialect_attr_iterator(attrs.end(), attrs.end())};
641   }
642   dialect_attr_iterator dialect_attr_begin() {
643     auto attrs = getAttrs();
644     return dialect_attr_iterator(attrs.begin(), attrs.end());
645   }
646   dialect_attr_iterator dialect_attr_end() {
647     auto attrs = getAttrs();
648     return dialect_attr_iterator(attrs.end(), attrs.end());
649   }
650 
651   /// Set the dialect attributes for this operation, and preserve all inherent.
652   template <typename DialectAttrT>
653   void setDialectAttrs(DialectAttrT &&dialectAttrs) {
654     NamedAttrList attrs;
655     attrs.append(std::begin(dialectAttrs), std::end(dialectAttrs));
656     for (auto attr : getAttrs())
657       if (!attr.getName().strref().contains('.'))
658         attrs.push_back(attr);
659     setAttrs(attrs.getDictionary(getContext()));
660   }
661 
662   /// Sets default attributes on unset attributes.
663   void populateDefaultAttrs() {
664     NamedAttrList attrs(getAttrDictionary());
665     name.populateDefaultAttrs(attrs);
666     setAttrs(attrs.getDictionary(getContext()));
667   }
668 
669   //===--------------------------------------------------------------------===//
670   // Blocks
671   //===--------------------------------------------------------------------===//
672 
673   /// Returns the number of regions held by this operation.
674   unsigned getNumRegions() { return numRegions; }
675 
676   /// Returns the regions held by this operation.
677   MutableArrayRef<Region> getRegions() {
678     // Check the count first, as computing the trailing objects can be slow.
679     if (numRegions == 0)
680       return MutableArrayRef<Region>();
681 
682     auto *regions = getTrailingObjects<Region>();
683     return {regions, numRegions};
684   }
685 
686   /// Returns the region held by this operation at position 'index'.
687   Region &getRegion(unsigned index) {
688     assert(index < numRegions && "invalid region index");
689     return getRegions()[index];
690   }
691 
692   //===--------------------------------------------------------------------===//
693   // Successors
694   //===--------------------------------------------------------------------===//
695 
696   MutableArrayRef<BlockOperand> getBlockOperands() {
697     return {getTrailingObjects<BlockOperand>(), numSuccs};
698   }
699 
700   // Successor iteration.
701   using succ_iterator = SuccessorRange::iterator;
702   succ_iterator successor_begin() { return getSuccessors().begin(); }
703   succ_iterator successor_end() { return getSuccessors().end(); }
704   SuccessorRange getSuccessors() { return SuccessorRange(this); }
705 
706   bool hasSuccessors() { return numSuccs != 0; }
707   unsigned getNumSuccessors() { return numSuccs; }
708 
709   Block *getSuccessor(unsigned index) {
710     assert(index < getNumSuccessors());
711     return getBlockOperands()[index].get();
712   }
713   void setSuccessor(Block *block, unsigned index);
714 
715   //===--------------------------------------------------------------------===//
716   // Accessors for various properties of operations
717   //===--------------------------------------------------------------------===//
718 
719   /// Attempt to fold this operation with the specified constant operand values
720   /// - the elements in "operands" will correspond directly to the operands of
721   /// the operation, but may be null if non-constant.
722   ///
723   /// If folding was successful, this function returns "success".
724   /// * If this operation was modified in-place (but not folded away),
725   ///   `results` is empty.
726   /// * Otherwise, `results` is filled with the folded results.
727   /// If folding was unsuccessful, this function returns "failure".
728   LogicalResult fold(ArrayRef<Attribute> operands,
729                      SmallVectorImpl<OpFoldResult> &results);
730 
731   /// Attempt to fold this operation.
732   ///
733   /// If folding was successful, this function returns "success".
734   /// * If this operation was modified in-place (but not folded away),
735   ///   `results` is empty.
736   /// * Otherwise, `results` is filled with the folded results.
737   /// If folding was unsuccessful, this function returns "failure".
738   LogicalResult fold(SmallVectorImpl<OpFoldResult> &results);
739 
740   /// Returns true if `InterfaceT` has been promised by the dialect or
741   /// implemented.
742   template <typename InterfaceT>
743   bool hasPromiseOrImplementsInterface() const {
744     return name.hasPromiseOrImplementsInterface<InterfaceT>();
745   }
746 
747   /// Returns true if the operation was registered with a particular trait, e.g.
748   /// hasTrait<OperandsAreSignlessIntegerLike>().
749   template <template <typename T> class Trait>
750   bool hasTrait() {
751     return name.hasTrait<Trait>();
752   }
753 
754   /// Returns true if the operation *might* have the provided trait. This
755   /// means that either the operation is unregistered, or it was registered with
756   /// the provide trait.
757   template <template <typename T> class Trait>
758   bool mightHaveTrait() {
759     return name.mightHaveTrait<Trait>();
760   }
761 
762   //===--------------------------------------------------------------------===//
763   // Operation Walkers
764   //===--------------------------------------------------------------------===//
765 
766   /// Walk the operation by calling the callback for each nested operation
767   /// (including this one), block or region, depending on the callback provided.
768   /// The order in which regions, blocks and operations at the same nesting
769   /// level are visited (e.g., lexicographical or reverse lexicographical order)
770   /// is determined by 'Iterator'. The walk order for enclosing regions, blocks
771   /// and operations with respect to their nested ones is specified by 'Order'
772   /// (post-order by default). A callback on a block or operation is allowed to
773   /// erase that block or operation if either:
774   ///   * the walk is in post-order, or
775   ///   * the walk is in pre-order and the walk is skipped after the erasure.
776   ///
777   /// The callback method can take any of the following forms:
778   ///   void(Operation*) : Walk all operations opaquely.
779   ///     * op->walk([](Operation *nestedOp) { ...});
780   ///   void(OpT) : Walk all operations of the given derived type.
781   ///     * op->walk([](ReturnOp returnOp) { ...});
782   ///   WalkResult(Operation*|OpT) : Walk operations, but allow for
783   ///                                interruption/skipping.
784   ///     * op->walk([](... op) {
785   ///         // Skip the walk of this op based on some invariant.
786   ///         if (some_invariant)
787   ///           return WalkResult::skip();
788   ///         // Interrupt, i.e cancel, the walk based on some invariant.
789   ///         if (another_invariant)
790   ///           return WalkResult::interrupt();
791   ///         return WalkResult::advance();
792   ///       });
793   template <WalkOrder Order = WalkOrder::PostOrder,
794             typename Iterator = ForwardIterator, typename FnT,
795             typename RetT = detail::walkResultType<FnT>>
796   std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 1,
797                    RetT>
798   walk(FnT &&callback) {
799     return detail::walk<Order, Iterator>(this, std::forward<FnT>(callback));
800   }
801 
802   /// Generic walker with a stage aware callback. Walk the operation by calling
803   /// the callback for each nested operation (including this one) N+1 times,
804   /// where N is the number of regions attached to that operation.
805   ///
806   /// The callback method can take any of the following forms:
807   ///   void(Operation *, const WalkStage &) : Walk all operation opaquely
808   ///     * op->walk([](Operation *nestedOp, const WalkStage &stage) { ...});
809   ///   void(OpT, const WalkStage &) : Walk all operations of the given derived
810   ///                                  type.
811   ///     * op->walk([](ReturnOp returnOp, const WalkStage &stage) { ...});
812   ///   WalkResult(Operation*|OpT, const WalkStage &stage) : Walk operations,
813   ///          but allow for interruption/skipping.
814   ///     * op->walk([](... op, const WalkStage &stage) {
815   ///         // Skip the walk of this op based on some invariant.
816   ///         if (some_invariant)
817   ///           return WalkResult::skip();
818   ///         // Interrupt, i.e cancel, the walk based on some invariant.
819   ///         if (another_invariant)
820   ///           return WalkResult::interrupt();
821   ///         return WalkResult::advance();
822   ///       });
823   template <typename FnT, typename RetT = detail::walkResultType<FnT>>
824   std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 2,
825                    RetT>
826   walk(FnT &&callback) {
827     return detail::walk(this, std::forward<FnT>(callback));
828   }
829 
830   //===--------------------------------------------------------------------===//
831   // Uses
832   //===--------------------------------------------------------------------===//
833 
834   /// Drop all uses of results of this operation.
835   void dropAllUses() {
836     for (OpResult result : getOpResults())
837       result.dropAllUses();
838   }
839 
840   using use_iterator = result_range::use_iterator;
841   using use_range = result_range::use_range;
842 
843   use_iterator use_begin() { return getResults().use_begin(); }
844   use_iterator use_end() { return getResults().use_end(); }
845 
846   /// Returns a range of all uses, which is useful for iterating over all uses.
847   use_range getUses() { return getResults().getUses(); }
848 
849   /// Returns true if this operation has exactly one use.
850   bool hasOneUse() { return llvm::hasSingleElement(getUses()); }
851 
852   /// Returns true if this operation has no uses.
853   bool use_empty() { return getResults().use_empty(); }
854 
855   /// Returns true if the results of this operation are used outside of the
856   /// given block.
857   bool isUsedOutsideOfBlock(Block *block) {
858     return llvm::any_of(getOpResults(), [block](OpResult result) {
859       return result.isUsedOutsideOfBlock(block);
860     });
861   }
862 
863   //===--------------------------------------------------------------------===//
864   // Users
865   //===--------------------------------------------------------------------===//
866 
867   using user_iterator = ValueUserIterator<use_iterator, OpOperand>;
868   using user_range = iterator_range<user_iterator>;
869 
870   user_iterator user_begin() { return user_iterator(use_begin()); }
871   user_iterator user_end() { return user_iterator(use_end()); }
872 
873   /// Returns a range of all users.
874   user_range getUsers() { return {user_begin(), user_end()}; }
875 
876   //===--------------------------------------------------------------------===//
877   // Other
878   //===--------------------------------------------------------------------===//
879 
880   /// Emit an error with the op name prefixed, like "'dim' op " which is
881   /// convenient for verifiers.
882   InFlightDiagnostic emitOpError(const Twine &message = {});
883 
884   /// Emit an error about fatal conditions with this operation, reporting up to
885   /// any diagnostic handlers that may be listening.
886   InFlightDiagnostic emitError(const Twine &message = {});
887 
888   /// Emit a warning about this operation, reporting up to any diagnostic
889   /// handlers that may be listening.
890   InFlightDiagnostic emitWarning(const Twine &message = {});
891 
892   /// Emit a remark about this operation, reporting up to any diagnostic
893   /// handlers that may be listening.
894   InFlightDiagnostic emitRemark(const Twine &message = {});
895 
896   /// Returns the properties storage size.
897   int getPropertiesStorageSize() const {
898     return ((int)propertiesStorageSize) * 8;
899   }
900   /// Returns the properties storage.
901   OpaqueProperties getPropertiesStorage() {
902     if (propertiesStorageSize)
903       return getPropertiesStorageUnsafe();
904     return {nullptr};
905   }
906   OpaqueProperties getPropertiesStorage() const {
907     if (propertiesStorageSize)
908       return {reinterpret_cast<void *>(const_cast<detail::OpProperties *>(
909           getTrailingObjects<detail::OpProperties>()))};
910     return {nullptr};
911   }
912   /// Returns the properties storage without checking whether properties are
913   /// present.
914   OpaqueProperties getPropertiesStorageUnsafe() {
915     return {
916         reinterpret_cast<void *>(getTrailingObjects<detail::OpProperties>())};
917   }
918 
919   /// Return the properties converted to an attribute.
920   /// This is expensive, and mostly useful when dealing with unregistered
921   /// operation. Returns an empty attribute if no properties are present.
922   Attribute getPropertiesAsAttribute();
923 
924   /// Set the properties from the provided attribute.
925   /// This is an expensive operation that can fail if the attribute is not
926   /// matching the expectations of the properties for this operation. This is
927   /// mostly useful for unregistered operations or used when parsing the
928   /// generic format. An optional diagnostic emitter can be passed in for richer
929   /// errors, if none is passed then behavior is undefined in error case.
930   LogicalResult
931   setPropertiesFromAttribute(Attribute attr,
932                              function_ref<InFlightDiagnostic()> emitError);
933 
934   /// Copy properties from an existing other properties object. The two objects
935   /// must be the same type.
936   void copyProperties(OpaqueProperties rhs);
937 
938   /// Compute a hash for the op properties (if any).
939   llvm::hash_code hashProperties();
940 
941 private:
942   //===--------------------------------------------------------------------===//
943   // Ordering
944   //===--------------------------------------------------------------------===//
945 
946   /// This value represents an invalid index ordering for an operation within a
947   /// block.
948   static constexpr unsigned kInvalidOrderIdx = -1;
949 
950   /// This value represents the stride to use when computing a new order for an
951   /// operation.
952   static constexpr unsigned kOrderStride = 5;
953 
954   /// Update the order index of this operation of this operation if necessary,
955   /// potentially recomputing the order of the parent block.
956   void updateOrderIfNecessary();
957 
958   /// Returns true if this operation has a valid order.
959   bool hasValidOrder() { return orderIndex != kInvalidOrderIdx; }
960 
961 private:
962   Operation(Location location, OperationName name, unsigned numResults,
963             unsigned numSuccessors, unsigned numRegions,
964             int propertiesStorageSize, DictionaryAttr attributes,
965             OpaqueProperties properties, bool hasOperandStorage);
966 
967   // Operations are deleted through the destroy() member because they are
968   // allocated with malloc.
969   ~Operation();
970 
971   /// Returns the additional size necessary for allocating the given objects
972   /// before an Operation in-memory.
973   static size_t prefixAllocSize(unsigned numOutOfLineResults,
974                                 unsigned numInlineResults) {
975     return sizeof(detail::OutOfLineOpResult) * numOutOfLineResults +
976            sizeof(detail::InlineOpResult) * numInlineResults;
977   }
978   /// Returns the additional size allocated before this Operation in-memory.
979   size_t prefixAllocSize() {
980     unsigned numResults = getNumResults();
981     unsigned numOutOfLineResults = OpResult::getNumTrailing(numResults);
982     unsigned numInlineResults = OpResult::getNumInline(numResults);
983     return prefixAllocSize(numOutOfLineResults, numInlineResults);
984   }
985 
986   /// Returns the operand storage object.
987   detail::OperandStorage &getOperandStorage() {
988     assert(hasOperandStorage && "expected operation to have operand storage");
989     return *getTrailingObjects<detail::OperandStorage>();
990   }
991 
992   /// Returns a pointer to the use list for the given out-of-line result.
993   detail::OutOfLineOpResult *getOutOfLineOpResult(unsigned resultNumber) {
994     // Out-of-line results are stored in reverse order after (before in memory)
995     // the inline results.
996     return reinterpret_cast<detail::OutOfLineOpResult *>(getInlineOpResult(
997                detail::OpResultImpl::getMaxInlineResults() - 1)) -
998            ++resultNumber;
999   }
1000 
1001   /// Returns a pointer to the use list for the given inline result.
1002   detail::InlineOpResult *getInlineOpResult(unsigned resultNumber) {
1003     // Inline results are stored in reverse order before the operation in
1004     // memory.
1005     return reinterpret_cast<detail::InlineOpResult *>(this) - ++resultNumber;
1006   }
1007 
1008   /// Returns a pointer to the use list for the given result, which may be
1009   /// either inline or out-of-line.
1010   detail::OpResultImpl *getOpResultImpl(unsigned resultNumber) {
1011     assert(resultNumber < getNumResults() &&
1012            "Result number is out of range for operation");
1013     unsigned maxInlineResults = detail::OpResultImpl::getMaxInlineResults();
1014     if (resultNumber < maxInlineResults)
1015       return getInlineOpResult(resultNumber);
1016     return getOutOfLineOpResult(resultNumber - maxInlineResults);
1017   }
1018 
1019   /// Provide a 'getParent' method for ilist_node_with_parent methods.
1020   /// We mark it as a const function because ilist_node_with_parent specifically
1021   /// requires a 'getParent() const' method. Once ilist_node removes this
1022   /// constraint, we should drop the const to fit the rest of the MLIR const
1023   /// model.
1024   Block *getParent() const { return block; }
1025 
1026   /// Expose a few methods explicitly for the debugger to call for
1027   /// visualization.
1028 #ifndef NDEBUG
1029   LLVM_DUMP_METHOD operand_range debug_getOperands() { return getOperands(); }
1030   LLVM_DUMP_METHOD result_range debug_getResults() { return getResults(); }
1031   LLVM_DUMP_METHOD SuccessorRange debug_getSuccessors() {
1032     return getSuccessors();
1033   }
1034   LLVM_DUMP_METHOD MutableArrayRef<Region> debug_getRegions() {
1035     return getRegions();
1036   }
1037 #endif
1038 
1039   /// The operation block that contains this operation.
1040   Block *block = nullptr;
1041 
1042   /// This holds information about the source location the operation was defined
1043   /// or derived from.
1044   Location location;
1045 
1046   /// Relative order of this operation in its parent block. Used for
1047   /// O(1) local dominance checks between operations.
1048   mutable unsigned orderIndex = 0;
1049 
1050   const unsigned numResults;
1051   const unsigned numSuccs;
1052   const unsigned numRegions : 23;
1053 
1054   /// This bit signals whether this operation has an operand storage or not. The
1055   /// operand storage may be elided for operations that are known to never have
1056   /// operands.
1057   bool hasOperandStorage : 1;
1058 
1059   /// The size of the storage for properties (if any), divided by 8: since the
1060   /// Properties storage will always be rounded up to the next multiple of 8 we
1061   /// save some bits here.
1062   unsigned char propertiesStorageSize : 8;
1063   /// This is the maximum size we support to allocate properties inline with an
1064   /// operation: this must match the bitwidth above.
1065   static constexpr int64_t propertiesCapacity = 8 * 256;
1066 
1067   /// This holds the name of the operation.
1068   OperationName name;
1069 
1070   /// This holds general named attributes for the operation.
1071   DictionaryAttr attrs;
1072 
1073   // allow ilist_traits access to 'block' field.
1074   friend struct llvm::ilist_traits<Operation>;
1075 
1076   // allow block to access the 'orderIndex' field.
1077   friend class Block;
1078 
1079   // allow value to access the 'ResultStorage' methods.
1080   friend class Value;
1081 
1082   // allow ilist_node_with_parent to access the 'getParent' method.
1083   friend class llvm::ilist_node_with_parent<Operation, Block>;
1084 
1085   // This stuff is used by the TrailingObjects template.
1086   friend llvm::TrailingObjects<Operation, detail::OperandStorage,
1087                                detail::OpProperties, BlockOperand, Region,
1088                                OpOperand>;
1089   size_t numTrailingObjects(OverloadToken<detail::OperandStorage>) const {
1090     return hasOperandStorage ? 1 : 0;
1091   }
1092   size_t numTrailingObjects(OverloadToken<BlockOperand>) const {
1093     return numSuccs;
1094   }
1095   size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; }
1096   size_t numTrailingObjects(OverloadToken<detail::OpProperties>) const {
1097     return getPropertiesStorageSize();
1098   }
1099 };
1100 
1101 inline raw_ostream &operator<<(raw_ostream &os, const Operation &op) {
1102   const_cast<Operation &>(op).print(os, OpPrintingFlags().useLocalScope());
1103   return os;
1104 }
1105 
1106 } // namespace mlir
1107 
1108 namespace llvm {
1109 /// Cast from an (const) Operation * to a derived operation type.
1110 template <typename T>
1111 struct CastInfo<T, ::mlir::Operation *>
1112     : public ValueFromPointerCast<T, ::mlir::Operation,
1113                                   CastInfo<T, ::mlir::Operation *>> {
1114   static bool isPossible(::mlir::Operation *op) { return T::classof(op); }
1115 };
1116 template <typename T>
1117 struct CastInfo<T, const ::mlir::Operation *>
1118     : public ConstStrippingForwardingCast<T, const ::mlir::Operation *,
1119                                           CastInfo<T, ::mlir::Operation *>> {};
1120 
1121 /// Cast from an (const) Operation & to a derived operation type.
1122 template <typename T>
1123 struct CastInfo<T, ::mlir::Operation>
1124     : public NullableValueCastFailed<T>,
1125       public DefaultDoCastIfPossible<T, ::mlir::Operation &,
1126                                      CastInfo<T, ::mlir::Operation>> {
1127   // Provide isPossible here because here we have the const-stripping from
1128   // ConstStrippingCast.
1129   static bool isPossible(::mlir::Operation &val) { return T::classof(&val); }
1130   static T doCast(::mlir::Operation &val) { return T(&val); }
1131 };
1132 template <typename T>
1133 struct CastInfo<T, const ::mlir::Operation>
1134     : public ConstStrippingForwardingCast<T, const ::mlir::Operation,
1135                                           CastInfo<T, ::mlir::Operation>> {};
1136 
1137 /// Cast (const) Operation * to itself. This is helpful to avoid SFINAE in
1138 /// templated implementations that should work on both base and derived
1139 /// operation types.
1140 template <>
1141 struct CastInfo<::mlir::Operation *, ::mlir::Operation *>
1142     : public NullableValueCastFailed<::mlir::Operation *>,
1143       public DefaultDoCastIfPossible<
1144           ::mlir::Operation *, ::mlir::Operation *,
1145           CastInfo<::mlir::Operation *, ::mlir::Operation *>> {
1146   static bool isPossible(::mlir::Operation *op) { return true; }
1147   static ::mlir::Operation *doCast(::mlir::Operation *op) { return op; }
1148 };
1149 template <>
1150 struct CastInfo<const ::mlir::Operation *, const ::mlir::Operation *>
1151     : public ConstStrippingForwardingCast<
1152           const ::mlir::Operation *, const ::mlir::Operation *,
1153           CastInfo<::mlir::Operation *, ::mlir::Operation *>> {};
1154 } // namespace llvm
1155 
1156 #endif // MLIR_IR_OPERATION_H
1157