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