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