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