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 <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 /// Set an inherent attribute by name.
471 ///
472 /// This method is available as a transient facility in the migration process
473 /// to use Properties instead.
474 void setInherentAttr(StringAttr name, Attribute value);
475
476 /// Access a discardable attribute by name, returns a null Attribute if the
477 /// discardable attribute does not exist.
478 Attribute getDiscardableAttr(StringRef name) { return attrs.get(name); }
479
480 /// Access a discardable attribute by name, returns a null Attribute if the
481 /// discardable attribute does not exist.
482 Attribute getDiscardableAttr(StringAttr name) { return attrs.get(name); }
483
484 /// Set a discardable attribute by name.
485 void setDiscardableAttr(StringAttr name, Attribute value) {
486 NamedAttrList attributes(attrs);
487 if (attributes.set(name, value) != value)
488 attrs = attributes.getDictionary(getContext());
489 }
490 void setDiscardableAttr(StringRef name, Attribute value) {
491 setDiscardableAttr(StringAttr::get(getContext(), name), value);
492 }
493
494 /// Remove the discardable attribute with the specified name if it exists.
495 /// Return the attribute that was erased, or nullptr if there was no attribute
496 /// with such name.
498 NamedAttrList attributes(attrs);
499 Attribute removedAttr = attributes.erase(name);
500 if (removedAttr)
501 attrs = attributes.getDictionary(getContext());
502 return removedAttr;
503 }
505 return removeDiscardableAttr(StringAttr::get(getContext(), name));
506 }
507
508 /// Return a range of all of discardable attributes on this operation. Note
509 /// that for unregistered operations that are not storing inherent attributes
510 /// as properties, all attributes are considered discardable.
512 std::optional<RegisteredOperationName> opName = getRegisteredInfo();
513 ArrayRef<StringAttr> attributeNames =
514 opName ? getRegisteredInfo()->getAttributeNames()
516 return llvm::make_filter_range(
517 attrs.getValue(),
518 [this, attributeNames](const NamedAttribute attribute) {
519 return getPropertiesStorage() ||
520 !llvm::is_contained(attributeNames, attribute.getName());
521 });
522 }
523
524 /// Return all of the discardable attributes on this operation as a
525 /// DictionaryAttr.
528 return attrs;
529 return DictionaryAttr::get(getContext(),
530 llvm::to_vector(getDiscardableAttrs()));
531 }
532
533 /// Return all attributes that are not stored as properties.
534 DictionaryAttr getRawDictionaryAttrs() { return attrs; }
535
536 /// Return all of the attributes on this operation.
538
539 /// Return all of the attributes on this operation as a DictionaryAttr.
540 DictionaryAttr getAttrDictionary();
541
542 /// Set the attributes from a dictionary on this operation.
543 /// These methods are expensive: if the dictionary only contains discardable
544 /// attributes, `setDiscardableAttrs` is more efficient.
545 void setAttrs(DictionaryAttr newAttrs);
546 void setAttrs(ArrayRef<NamedAttribute> newAttrs);
547 /// Set the discardable attribute dictionary on this operation.
548 void setDiscardableAttrs(DictionaryAttr newAttrs) {
549 assert(newAttrs && "expected valid attribute dictionary");
550 attrs = newAttrs;
551 }
553 setDiscardableAttrs(DictionaryAttr::get(getContext(), newAttrs));
554 }
555
556 /// Return the specified attribute if present, null otherwise.
557 /// These methods are expensive: if the dictionary only contains discardable
558 /// attributes, `getDiscardableAttr` is more efficient.
559 Attribute getAttr(StringAttr name) {
561 if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
562 return *inherentAttr;
563 }
564 return attrs.get(name);
565 }
566 Attribute getAttr(StringRef name) {
568 if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
569 return *inherentAttr;
570 }
571 return attrs.get(name);
572 }
573
574 template <typename AttrClass>
575 AttrClass getAttrOfType(StringAttr name) {
576 return llvm::dyn_cast_or_null<AttrClass>(getAttr(name));
577 }
578 template <typename AttrClass>
579 AttrClass getAttrOfType(StringRef name) {
580 return llvm::dyn_cast_or_null<AttrClass>(getAttr(name));
581 }
582
583 /// Return true if the operation has an attribute with the provided name,
584 /// false otherwise.
585 bool hasAttr(StringAttr name) {
587 if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
588 return (bool)*inherentAttr;
589 }
590 return attrs.contains(name);
591 }
592 bool hasAttr(StringRef name) {
594 if (std::optional<Attribute> inherentAttr = getInherentAttr(name))
595 return (bool)*inherentAttr;
596 }
597 return attrs.contains(name);
598 }
599 template <typename AttrClass, typename NameT>
600 bool hasAttrOfType(NameT &&name) {
601 return static_cast<bool>(
602 getAttrOfType<AttrClass>(std::forward<NameT>(name)));
603 }
604
605 /// If the an attribute exists with the specified name, change it to the new
606 /// value. Otherwise, add a new attribute with the specified name/value.
607 void setAttr(StringAttr name, Attribute value) {
609 if (getInherentAttr(name)) {
610 setInherentAttr(name, value);
611 return;
612 }
613 }
614 NamedAttrList attributes(attrs);
615 if (attributes.set(name, value) != value)
616 attrs = attributes.getDictionary(getContext());
617 }
618 void setAttr(StringRef name, Attribute value) {
619 setAttr(StringAttr::get(getContext(), name), value);
620 }
621
622 /// Remove the attribute with the specified name if it exists. Return the
623 /// attribute that was erased, or nullptr if there was no attribute with such
624 /// name.
625 Attribute removeAttr(StringAttr name) {
627 if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) {
628 setInherentAttr(name, {});
629 return *inherentAttr;
630 }
631 }
632 NamedAttrList attributes(attrs);
633 Attribute removedAttr = attributes.erase(name);
634 if (removedAttr)
635 attrs = attributes.getDictionary(getContext());
636 return removedAttr;
637 }
638 Attribute removeAttr(StringRef name) {
639 return removeAttr(StringAttr::get(getContext(), name));
640 }
641
642 /// A utility iterator that filters out non-dialect attributes.
643 class dialect_attr_iterator
644 : public llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
645 bool (*)(NamedAttribute)> {
646 static bool filter(NamedAttribute attr) {
647 // Dialect attributes are prefixed by the dialect name, like operations.
648 return attr.getName().strref().count('.');
649 }
650
651 explicit dialect_attr_iterator(ArrayRef<NamedAttribute>::iterator it,
653 : llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator,
654 bool (*)(NamedAttribute)>(it, end, &filter) {}
655
656 // Allow access to the constructor.
657 friend Operation;
658 };
660
661 /// Return a range corresponding to the dialect attributes for this operation.
663 auto attrs = getAttrs();
664 return {dialect_attr_iterator(attrs.begin(), attrs.end()),
665 dialect_attr_iterator(attrs.end(), attrs.end())};
666 }
668 auto attrs = getAttrs();
669 return dialect_attr_iterator(attrs.begin(), attrs.end());
670 }
672 auto attrs = getAttrs();
673 return dialect_attr_iterator(attrs.end(), attrs.end());
674 }
675
676 /// Set the dialect attributes for this operation, and preserve all inherent.
677 template <typename DialectAttrT>
678 void setDialectAttrs(DialectAttrT &&dialectAttrs) {
679 NamedAttrList attrs;
680 attrs.append(std::begin(dialectAttrs), std::end(dialectAttrs));
681 for (auto attr : getAttrs())
682 if (!attr.getName().strref().contains('.'))
683 attrs.push_back(attr);
684 setAttrs(attrs.getDictionary(getContext()));
685 }
686
687 /// Sets default attributes on unset attributes.
690 name.populateDefaultAttrs(attrs);
691 setAttrs(attrs.getDictionary(getContext()));
692 }
693
694 //===--------------------------------------------------------------------===//
695 // Blocks
696 //===--------------------------------------------------------------------===//
697
698 /// Returns the number of regions held by this operation.
699 unsigned getNumRegions() { return numRegions; }
700
701 /// Returns the regions held by this operation.
703 // Check the count first, as computing the trailing objects can be slow.
704 if (numRegions == 0)
706
707 return getTrailingObjects<Region>(numRegions);
708 }
709
710 /// Returns the region held by this operation at position 'index'.
711 Region &getRegion(unsigned index) {
712 assert(index < numRegions && "invalid region index");
713 return getRegions()[index];
714 }
715
716 //===--------------------------------------------------------------------===//
717 // Successors
718 //===--------------------------------------------------------------------===//
719
721 return getTrailingObjects<BlockOperand>(numSuccs);
722 }
723
724 // Successor iteration.
725 using succ_iterator = SuccessorRange::iterator;
729
730 bool hasSuccessors() { return numSuccs != 0; }
731 unsigned getNumSuccessors() { return numSuccs; }
732
734 assert(index < getNumSuccessors());
735 return getBlockOperands()[index].get();
736 }
737 void setSuccessor(Block *block, unsigned index);
738
739 //===--------------------------------------------------------------------===//
740 // Accessors for various properties of operations
741 //===--------------------------------------------------------------------===//
742
743 /// Attempt to fold this operation with the specified constant operand values
744 /// - the elements in "operands" will correspond directly to the operands of
745 /// the operation, but may be null if non-constant.
746 ///
747 /// If folding was successful, this function returns "success".
748 /// * If this operation was modified in-place (but not folded away),
749 /// `results` is empty.
750 /// * Otherwise, `results` is filled with the folded results.
751 /// If folding was unsuccessful, this function returns "failure".
752 LogicalResult fold(ArrayRef<Attribute> operands,
754
755 /// Attempt to fold this operation.
756 ///
757 /// If folding was successful, this function returns "success".
758 /// * If this operation was modified in-place (but not folded away),
759 /// `results` is empty.
760 /// * Otherwise, `results` is filled with the folded results.
761 /// If folding was unsuccessful, this function returns "failure".
762 LogicalResult fold(SmallVectorImpl<OpFoldResult> &results);
763
764 /// Returns true if `InterfaceT` has been promised by the dialect or
765 /// implemented.
766 template <typename InterfaceT>
768 return name.hasPromiseOrImplementsInterface<InterfaceT>();
769 }
770
771 /// Returns true if the operation was registered with a particular trait, e.g.
772 /// hasTrait<OperandsAreSignlessIntegerLike>().
773 template <template <typename T> class Trait>
774 bool hasTrait() {
775 return name.hasTrait<Trait>();
776 }
777
778 /// Returns true if the operation *might* have the provided trait. This
779 /// means that either the operation is unregistered, or it was registered with
780 /// the provide trait.
781 template <template <typename T> class Trait>
783 return name.mightHaveTrait<Trait>();
784 }
785
786 //===--------------------------------------------------------------------===//
787 // Operation Walkers
788 //===--------------------------------------------------------------------===//
789
790 /// Walk the operation by calling the callback for each nested operation
791 /// (including this one), block or region, depending on the callback provided.
792 /// The order in which regions, blocks and operations at the same nesting
793 /// level are visited (e.g., lexicographical or reverse lexicographical order)
794 /// is determined by 'Iterator'. The walk order for enclosing regions, blocks
795 /// and operations with respect to their nested ones is specified by 'Order'
796 /// (post-order by default). A callback on a block or operation is allowed to
797 /// erase that block or operation if either:
798 /// * the walk is in post-order, or
799 /// * the walk is in pre-order and the walk is skipped after the erasure.
800 ///
801 /// The callback method can take any of the following forms:
802 /// void(Operation*) : Walk all operations opaquely.
803 /// * op->walk([](Operation *nestedOp) { ...});
804 /// void(OpT) : Walk all operations of the given derived type.
805 /// * op->walk([](ReturnOp returnOp) { ...});
806 /// WalkResult(Operation*|OpT) : Walk operations, but allow for
807 /// interruption/skipping.
808 /// * op->walk([](... op) {
809 /// // Skip the walk of this op based on some invariant.
810 /// if (some_invariant)
811 /// return WalkResult::skip();
812 /// // Interrupt, i.e cancel, the walk based on some invariant.
813 /// if (another_invariant)
814 /// return WalkResult::interrupt();
815 /// return WalkResult::advance();
816 /// });
817 template <WalkOrder Order = WalkOrder::PostOrder,
818 typename Iterator = ForwardIterator, typename FnT,
819 typename RetT = detail::walkResultType<FnT>>
820 std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 1,
821 RetT>
822 walk(FnT &&callback) {
823 return detail::walk<Order, Iterator>(this, std::forward<FnT>(callback));
824 }
825
826 /// Generic walker with a stage aware callback. Walk the operation by calling
827 /// the callback for each nested operation (including this one) N+1 times,
828 /// where N is the number of regions attached to that operation.
829 ///
830 /// The callback method can take any of the following forms:
831 /// void(Operation *, const WalkStage &) : Walk all operation opaquely
832 /// * op->walk([](Operation *nestedOp, const WalkStage &stage) { ...});
833 /// void(OpT, const WalkStage &) : Walk all operations of the given derived
834 /// type.
835 /// * op->walk([](ReturnOp returnOp, const WalkStage &stage) { ...});
836 /// WalkResult(Operation*|OpT, const WalkStage &stage) : Walk operations,
837 /// but allow for interruption/skipping.
838 /// * op->walk([](... op, const WalkStage &stage) {
839 /// // Skip the walk of this op based on some invariant.
840 /// if (some_invariant)
841 /// return WalkResult::skip();
842 /// // Interrupt, i.e cancel, the walk based on some invariant.
843 /// if (another_invariant)
844 /// return WalkResult::interrupt();
845 /// return WalkResult::advance();
846 /// });
847 template <typename FnT, typename RetT = detail::walkResultType<FnT>>
848 std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 2,
849 RetT>
850 walk(FnT &&callback) {
851 return detail::walk(this, std::forward<FnT>(callback));
852 }
853
854 //===--------------------------------------------------------------------===//
855 // Uses
856 //===--------------------------------------------------------------------===//
857
858 /// Drop all uses of results of this operation.
859 void dropAllUses() {
861 result.dropAllUses();
862 }
863
866
869
870 /// Returns a range of all uses, which is useful for iterating over all uses.
872
873 /// Returns true if this operation has exactly one use.
874 bool hasOneUse() { return llvm::hasSingleElement(getUses()); }
875
876 /// Returns true if this operation has no uses.
877 bool use_empty() { return getResults().use_empty(); }
878
879 /// Returns true if the results of this operation are used outside of the
880 /// given block.
882 return llvm::any_of(getOpResults(), [block](OpResult result) {
883 return result.isUsedOutsideOfBlock(block);
884 });
885 }
886
887 //===--------------------------------------------------------------------===//
888 // Users
889 //===--------------------------------------------------------------------===//
890
893
896
897 /// Returns a range of all users.
899
900 //===--------------------------------------------------------------------===//
901 // Other
902 //===--------------------------------------------------------------------===//
903
904 /// Emit an error with the op name prefixed, like "'dim' op " which is
905 /// convenient for verifiers.
906 InFlightDiagnostic emitOpError(const Twine &message = {});
907
908 /// Emit an error about fatal conditions with this operation, reporting up to
909 /// any diagnostic handlers that may be listening.
910 InFlightDiagnostic emitError(const Twine &message = {});
911
912 /// Emit a warning about this operation, reporting up to any diagnostic
913 /// handlers that may be listening.
914 InFlightDiagnostic emitWarning(const Twine &message = {});
915
916 /// Emit a remark about this operation, reporting up to any diagnostic
917 /// handlers that may be listening.
918 InFlightDiagnostic emitRemark(const Twine &message = {});
919
920 /// Returns the properties storage size.
922 return ((int)propertiesStorageSize) * 8;
923 }
924
925 /// Return a generic (but typed) reference to the property type storage.
927 if (propertiesStorageSize)
928 return PropertyRef(name.getOpPropertiesTypeID(),
930 return {};
931 }
932
934 if (propertiesStorageSize)
935 return PropertyRef(
936 name.getOpPropertiesTypeID(),
937 reinterpret_cast<void *>(const_cast<detail::OpProperties *>(
938 getTrailingObjects<detail::OpProperties>())));
939 return {};
940 }
941
942 /// Returns a pointer to the properties storage (if it exists) with no type
943 /// information.
945 return reinterpret_cast<void *>(const_cast<detail::OpProperties *>(
946 getTrailingObjects<detail::OpProperties>()));
947 }
948
949 /// Return the properties converted to an attribute.
950 /// This is expensive, and mostly useful when dealing with unregistered
951 /// operation. Returns an empty attribute if no properties are present.
953
954 /// Set the properties from the provided attribute.
955 /// This is an expensive operation that can fail if the attribute is not
956 /// matching the expectations of the properties for this operation. This is
957 /// mostly useful for unregistered operations or used when parsing the
958 /// generic format. An optional diagnostic emitter can be passed in for richer
959 /// errors, if none is passed then behavior is undefined in error case.
960 LogicalResult
963
964 /// Copy properties from an existing other properties object. The two objects
965 /// must be the same type.
967
968 /// Compute a hash for the op properties (if any).
969 llvm::hash_code hashProperties();
970
971private:
972 //===--------------------------------------------------------------------===//
973 // Ordering
974 //===--------------------------------------------------------------------===//
975
976 /// This value represents an invalid index ordering for an operation within a
977 /// block.
978 static constexpr unsigned kInvalidOrderIdx = -1;
979
980 /// This value represents the stride to use when computing a new order for an
981 /// operation.
982 static constexpr unsigned kOrderStride = 5;
983
984 /// Update the order index of this operation if necessary,
985 /// potentially recomputing the order of the parent block.
986 void updateOrderIfNecessary();
987
988 /// Returns true if this operation has a valid order.
989 bool hasValidOrder() { return orderIndex != kInvalidOrderIdx; }
990
991private:
992 Operation(Location location, OperationName name, unsigned numResults,
993 unsigned numSuccessors, unsigned numRegions,
994 int propertiesStorageSize, DictionaryAttr attributes,
995 PropertyRef properties, bool hasOperandStorage);
996
997 // Operations are deleted through the destroy() member because they are
998 // allocated with malloc.
999 ~Operation();
1000
1001 /// Returns the additional size necessary for allocating the given objects
1002 /// before an Operation in-memory.
1003 static size_t prefixAllocSize(unsigned numOutOfLineResults,
1004 unsigned numInlineResults) {
1005 return sizeof(detail::OutOfLineOpResult) * numOutOfLineResults +
1006 sizeof(detail::InlineOpResult) * numInlineResults;
1007 }
1008 /// Returns the additional size allocated before this Operation in-memory.
1009 size_t prefixAllocSize() {
1010 unsigned numResults = getNumResults();
1011 unsigned numOutOfLineResults = OpResult::getNumTrailing(numResults);
1012 unsigned numInlineResults = OpResult::getNumInline(numResults);
1013 return prefixAllocSize(numOutOfLineResults, numInlineResults);
1014 }
1015
1016 /// Returns the operand storage object.
1017 detail::OperandStorage &getOperandStorage() {
1018 assert(hasOperandStorage && "expected operation to have operand storage");
1019 return *getTrailingObjects<detail::OperandStorage>();
1020 }
1021
1022 /// Returns a pointer to the use list for the given out-of-line result.
1023 detail::OutOfLineOpResult *getOutOfLineOpResult(unsigned resultNumber) {
1024 // Out-of-line results are stored in reverse order after (before in memory)
1025 // the inline results.
1026 return reinterpret_cast<detail::OutOfLineOpResult *>(getInlineOpResult(
1028 ++resultNumber;
1029 }
1030
1031 /// Returns a pointer to the use list for the given inline result.
1032 detail::InlineOpResult *getInlineOpResult(unsigned resultNumber) {
1033 // Inline results are stored in reverse order before the operation in
1034 // memory.
1035 return reinterpret_cast<detail::InlineOpResult *>(this) - ++resultNumber;
1036 }
1037
1038 /// Returns a pointer to the use list for the given result, which may be
1039 /// either inline or out-of-line.
1040 detail::OpResultImpl *getOpResultImpl(unsigned resultNumber) {
1041 assert(resultNumber < getNumResults() &&
1042 "Result number is out of range for operation");
1043 unsigned maxInlineResults = detail::OpResultImpl::getMaxInlineResults();
1044 if (resultNumber < maxInlineResults)
1045 return getInlineOpResult(resultNumber);
1046 return getOutOfLineOpResult(resultNumber - maxInlineResults);
1047 }
1048
1049 /// Provide a 'getParent' method for ilist_node_with_parent methods.
1050 /// We mark it as a const function because ilist_node_with_parent specifically
1051 /// requires a 'getParent() const' method. Once ilist_node removes this
1052 /// constraint, we should drop the const to fit the rest of the MLIR const
1053 /// model.
1054 Block *getParent() const { return block; }
1055
1056 /// Expose a few methods explicitly for the debugger to call for
1057 /// visualization.
1058#ifndef NDEBUG
1059 LLVM_DUMP_METHOD operand_range debug_getOperands() { return getOperands(); }
1060 LLVM_DUMP_METHOD result_range debug_getResults() { return getResults(); }
1061 LLVM_DUMP_METHOD SuccessorRange debug_getSuccessors() {
1062 return getSuccessors();
1063 }
1064 LLVM_DUMP_METHOD MutableArrayRef<Region> debug_getRegions() {
1065 return getRegions();
1066 }
1067#endif
1068
1069 /// The operation block that contains this operation.
1070 Block *block = nullptr;
1071
1072 /// This holds information about the source location the operation was defined
1073 /// or derived from.
1074 Location location;
1075
1076 /// Relative order of this operation in its parent block. Used for
1077 /// O(1) local dominance checks between operations.
1078 mutable unsigned orderIndex = 0;
1079
1080 const unsigned numResults;
1081 const unsigned numSuccs;
1082 const unsigned numRegions : 23;
1083
1084 /// This bit signals whether this operation has an operand storage or not. The
1085 /// operand storage may be elided for operations that are known to never have
1086 /// operands.
1087 bool hasOperandStorage : 1;
1088
1089 /// The size of the storage for properties (if any), divided by 8: since the
1090 /// Properties storage will always be rounded up to the next multiple of 8 we
1091 /// save some bits here.
1092 unsigned char propertiesStorageSize : 8;
1093 /// This is the maximum size we support to allocate properties inline with an
1094 /// operation: this must match the bitwidth above.
1095 static constexpr int64_t propertiesCapacity = 8 * 256;
1096
1097 /// This holds the name of the operation.
1098 OperationName name;
1099
1100 /// This holds general named attributes for the operation.
1101 DictionaryAttr attrs;
1102
1103 // allow ilist_traits access to 'block' field.
1104 friend struct llvm::ilist_traits<Operation>;
1105
1106 // allow block to access the 'orderIndex' field.
1107 friend class Block;
1108
1109 // allow value to access the 'ResultStorage' methods.
1110 friend class Value;
1111
1112 // allow ilist_node_with_parent to access the 'getParent' method.
1113 friend class llvm::ilist_node_with_parent<Operation, Block>;
1114
1115 // This stuff is used by the TrailingObjects template.
1116 friend llvm::TrailingObjects<Operation, detail::OperandStorage,
1118 OpOperand>;
1119 size_t numTrailingObjects(OverloadToken<detail::OperandStorage>) const {
1120 return hasOperandStorage ? 1 : 0;
1121 }
1122 size_t numTrailingObjects(OverloadToken<BlockOperand>) const {
1123 return numSuccs;
1124 }
1125 size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; }
1126 size_t numTrailingObjects(OverloadToken<detail::OpProperties>) const {
1127 return getPropertiesStorageSize();
1128 }
1129};
1130
1132 const_cast<Operation &>(op).print(os, OpPrintingFlags().useLocalScope());
1133 return os;
1134}
1135
1136/// A wrapper class that allows for printing an operation with a set of flags,
1137/// useful to act as a "stream modifier" to customize printing an operation
1138/// with a stream using the operator<< overload, e.g.:
1139/// llvm::dbgs() << OpWithFlags(op, OpPrintingFlags().skipRegions());
1140/// This always prints the operation with the local scope, to avoid introducing
1141/// spurious newlines in the stream.
1143public:
1145 : op(op), theFlags(flags) {}
1146 OpPrintingFlags &flags() { return theFlags; }
1147 const OpPrintingFlags &flags() const { return theFlags; }
1148 Operation *getOperation() const { return op; }
1149
1150private:
1151 Operation *op;
1152 OpPrintingFlags theFlags;
1154};
1155
1157 opWithFlags.flags().useLocalScope();
1158 opWithFlags.op->print(os, opWithFlags.flags());
1159 return os;
1160}
1161
1162/// A wrapper class that allows for printing an operation with a custom
1163/// AsmState, useful to act as a "stream modifier" to customize printing an
1164/// operation with a stream using the operator<< overload, e.g.:
1165/// llvm::dbgs() << OpWithState(op, OpPrintingFlags().skipRegions());
1167public:
1168 OpWithState(Operation *op, AsmState &state) : op(op), theState(state) {}
1169
1170private:
1171 Operation *op;
1172 AsmState &theState;
1173 friend raw_ostream &operator<<(raw_ostream &os, const OpWithState &op);
1174};
1175
1177 const OpWithState &opWithState) {
1178 opWithState.op->print(os, const_cast<OpWithState &>(opWithState).theState);
1179 return os;
1180}
1181
1182} // namespace mlir
1183
1184namespace llvm {
1185/// Cast from an (const) Operation * to a derived operation type.
1186template <typename T>
1188 : public ValueFromPointerCast<T, ::mlir::Operation,
1189 CastInfo<T, ::mlir::Operation *>> {
1190 static bool isPossible(::mlir::Operation *op) { return T::classof(op); }
1191};
1192template <typename T>
1193struct CastInfo<T, const ::mlir::Operation *>
1194 : public ConstStrippingForwardingCast<T, const ::mlir::Operation *,
1195 CastInfo<T, ::mlir::Operation *>> {};
1196
1197/// Cast from an (const) Operation & to a derived operation type.
1198template <typename T>
1200 : public NullableValueCastFailed<T>,
1201 public DefaultDoCastIfPossible<T, ::mlir::Operation &,
1202 CastInfo<T, ::mlir::Operation>> {
1203 // Provide isPossible here because here we have the const-stripping from
1204 // ConstStrippingCast.
1205 static bool isPossible(::mlir::Operation &val) { return T::classof(&val); }
1206 static T doCast(::mlir::Operation &val) { return T(&val); }
1207};
1208template <typename T>
1209struct CastInfo<T, const ::mlir::Operation>
1210 : public ConstStrippingForwardingCast<T, const ::mlir::Operation,
1211 CastInfo<T, ::mlir::Operation>> {};
1212
1213/// Cast (const) Operation * to itself. This is helpful to avoid SFINAE in
1214/// templated implementations that should work on both base and derived
1215/// operation types.
1216template <>
1218 : public NullableValueCastFailed<::mlir::Operation *>,
1220 ::mlir::Operation *, ::mlir::Operation *,
1221 CastInfo<::mlir::Operation *, ::mlir::Operation *>> {
1222 static bool isPossible(::mlir::Operation *op) { return true; }
1223 static ::mlir::Operation *doCast(::mlir::Operation *op) { return op; }
1224};
1225template <>
1228 const ::mlir::Operation *, const ::mlir::Operation *,
1229 CastInfo<::mlir::Operation *, ::mlir::Operation *>> {};
1230} // namespace llvm
1231
1232#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:1142
OpWithFlags(Operation *op, OpPrintingFlags flags={})
Definition Operation.h:1144
friend raw_ostream & operator<<(raw_ostream &os, OpWithFlags op)
Definition Operation.h:1156
const OpPrintingFlags & flags() const
Definition Operation.h:1147
Operation * getOperation() const
Definition Operation.h:1148
OpPrintingFlags & flags()
Definition Operation.h:1146
A wrapper class that allows for printing an operation with a custom AsmState, useful to act as a "str...
Definition Operation.h:1166
OpWithState(Operation *op, AsmState &state)
Definition Operation.h:1168
friend raw_ostream & operator<<(raw_ostream &os, const OpWithState &op)
Definition Operation.h:1176
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:645
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:926
AttrClass getAttrOfType(StringRef name)
Definition Operation.h:579
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Definition Operation.h:243
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:478
void replaceUsesOfWith(Value from, Value to)
Replace any uses of 'from' with 'to' within this operation.
PropertyRef getPropertiesStorage() const
Definition Operation.h:933
void copyProperties(PropertyRef rhs)
Copy properties from an existing other properties object.
MutableArrayRef< BlockOperand > getBlockOperands()
Definition Operation.h:720
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:850
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Definition Operation.h:711
bool use_empty()
Returns true if this operation has no uses.
Definition Operation.h:877
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:774
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:859
AttrClass getAttrOfType(StringAttr name)
Definition Operation.h:575
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition Operation.h:559
bool hasAttr(StringRef name)
Definition Operation.h:592
operand_range::type_range operand_type_range
Definition Operation.h:419
bool hasAttrOfType(NameT &&name)
Definition Operation.h:600
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:585
unsigned getNumSuccessors()
Definition Operation.h:731
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:537
operand_iterator operand_begin()
Definition Operation.h:399
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Definition Operation.h:782
result_range::use_iterator use_iterator
Definition Operation.h:864
bool hasOneUse()
Returns true if this operation has exactly one use.
Definition Operation.h:874
dialect_attr_iterator dialect_attr_begin()
Definition Operation.h:667
Attribute getAttr(StringRef name)
Definition Operation.h:566
Block * getBlock()
Returns the operation block that contains this operation.
Definition Operation.h:230
user_iterator user_end()
Definition Operation.h:895
void setDiscardableAttr(StringAttr name, Attribute value)
Set a discardable attribute by name.
Definition Operation.h:485
Attribute removeAttr(StringRef name)
Definition Operation.h:638
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:432
use_iterator use_begin()
Definition Operation.h:867
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:504
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:699
void setDialectAttrs(DialectAttrT &&dialectAttrs)
Set the dialect attributes for this operation, and preserve all inherent.
Definition Operation.h:678
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:767
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
Definition Operation.h:534
void dropAllDefinedValueUses()
Drop uses of all values defined by this operation or its nested regions.
iterator_range< user_iterator > user_range
Definition Operation.h:892
iterator_range< dialect_attr_iterator > dialect_attr_range
Definition Operation.h:659
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:688
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:891
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:482
bool isUsedOutsideOfBlock(Block *block)
Returns true if the results of this operation are used outside of the given block.
Definition Operation.h:881
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:607
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:511
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:526
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:552
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
Definition Operation.h:662
LogicalResult setPropertiesFromAttribute(Attribute attr, function_ref< InFlightDiagnostic()> emitError)
Set the properties from the provided attribute.
bool hasSuccessors()
Definition Operation.h:730
operand_type_range getOperandTypes()
Definition Operation.h:422
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition Operation.h:702
result_iterator result_end()
Definition Operation.h:439
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:1107
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:497
LLVM_DUMP_METHOD void dumpPretty()
void setDiscardableAttr(StringRef name, Attribute value)
Definition Operation.h:490
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:865
void * getRawPropertiesStorageUnsafe()
Returns a pointer to the properties storage (if it exists) with no type information.
Definition Operation.h:944
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:822
Block * getSuccessor(unsigned index)
Definition Operation.h:733
user_range getUsers()
Returns a range of all users.
Definition Operation.h:898
SuccessorRange getSuccessors()
Definition Operation.h:728
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:921
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:625
SuccessorRange::iterator succ_iterator
Definition Operation.h:725
dialect_attr_iterator dialect_attr_end()
Definition Operation.h:671
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:871
void setAttr(StringRef name, Attribute value)
Definition Operation.h:618
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:894
friend class Value
Definition Operation.h:1110
void setDiscardableAttrs(DictionaryAttr newAttrs)
Set the discardable attribute dictionary on this operation.
Definition Operation.h:548
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:727
use_iterator use_end()
Definition Operation.h:868
void erase()
Remove this operation from its parent block and delete it.
succ_iterator successor_begin()
Definition Operation.h:726
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: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:228
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:1206
static bool isPossible(::mlir::Operation &val)
Definition Operation.h:1205
static bool isPossible(::mlir::Operation *op)
Definition Operation.h:1190
::mlir::Operation * doCast(::mlir::Operation *op)
Definition Operation.h:1223
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.