MLIR 22.0.0git
OperationSupport.h
Go to the documentation of this file.
1//===- OperationSupport.h ---------------------------------------*- 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 a number of support types that Operation and related
10// classes build on top of.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_IR_OPERATIONSUPPORT_H
15#define MLIR_IR_OPERATIONSUPPORT_H
16
17#include "mlir/IR/Attributes.h"
20#include "mlir/IR/Diagnostics.h"
22#include "mlir/IR/Location.h"
23#include "mlir/IR/TypeRange.h"
24#include "mlir/IR/Types.h"
25#include "mlir/IR/Value.h"
27#include "llvm/ADT/BitmaskEnum.h"
28#include "llvm/ADT/PointerUnion.h"
29#include "llvm/ADT/STLFunctionalExtras.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/PointerLikeTypeTraits.h"
32#include "llvm/Support/TrailingObjects.h"
33#include <memory>
34#include <optional>
35
36namespace llvm {
37class BitVector;
38} // namespace llvm
39
40namespace mlir {
41class Dialect;
42class DictionaryAttr;
43class ElementsAttr;
44struct EmptyProperties;
46class NamedAttrList;
47class Operation;
48struct OperationState;
49class OpAsmParser;
50class OpAsmPrinter;
51class OperandRange;
53class OpFoldResult;
54class Pattern;
55class Region;
56class ResultRange;
57class RewritePattern;
59class Type;
60class Value;
61class ValueRange;
62template <typename ValueRangeT>
63class ValueTypeRange;
64
65//===----------------------------------------------------------------------===//
66// OpaqueProperties
67//===----------------------------------------------------------------------===//
68
69/// Simple wrapper around a void* in order to express generically how to pass
70/// in op properties through APIs.
72public:
73 OpaqueProperties(void *prop) : properties(prop) {}
74 operator bool() const { return properties != nullptr; }
75 template <typename Dest>
76 Dest as() const {
77 return static_cast<Dest>(const_cast<void *>(properties));
78 }
79
80private:
81 void *properties;
82};
83
84//===----------------------------------------------------------------------===//
85// OperationName
86//===----------------------------------------------------------------------===//
87
89public:
90 using FoldHookFn = llvm::unique_function<LogicalResult(
92 using HasTraitFn = llvm::unique_function<bool(TypeID) const>;
94 llvm::unique_function<ParseResult(OpAsmParser &, OperationState &)>;
95 // Note: RegisteredOperationName is passed as reference here as the derived
96 // class is defined below.
98 llvm::unique_function<void(const OperationName &, NamedAttrList &) const>;
100 llvm::unique_function<void(Operation *, OpAsmPrinter &, StringRef) const>;
102 llvm::unique_function<LogicalResult(Operation *) const>;
104 llvm::unique_function<LogicalResult(Operation *) const>;
105
106 /// This class represents a type erased version of an operation. It contains
107 /// all of the components necessary for opaquely interacting with an
108 /// operation. If the operation is not registered, some of these components
109 /// may not be populated.
111 virtual ~InterfaceConcept() = default;
112 virtual LogicalResult foldHook(Operation *, ArrayRef<Attribute>,
115 MLIRContext *) = 0;
116 virtual bool hasTrait(TypeID) = 0;
119 NamedAttrList &) = 0;
120 virtual void printAssembly(Operation *, OpAsmPrinter &, StringRef) = 0;
121 virtual LogicalResult verifyInvariants(Operation *) = 0;
122 virtual LogicalResult verifyRegionInvariants(Operation *) = 0;
123 /// Implementation for properties
124 virtual std::optional<Attribute> getInherentAttr(Operation *,
125 StringRef name) = 0;
126 virtual void setInherentAttr(Operation *op, StringAttr name,
127 Attribute value) = 0;
128 virtual void populateInherentAttrs(Operation *op, NamedAttrList &attrs) = 0;
129 virtual LogicalResult
132 virtual int getOpPropertyByteSize() = 0;
133 virtual void initProperties(OperationName opName, OpaqueProperties storage,
134 OpaqueProperties init) = 0;
137 OpaqueProperties properties) = 0;
138 virtual LogicalResult
144 virtual llvm::hash_code hashProperties(OpaqueProperties) = 0;
145 };
146
147public:
148 class Impl : public InterfaceConcept {
149 public:
150 Impl(StringRef, Dialect *dialect, TypeID typeID,
156
157 /// Returns true if this is a registered operation.
158 bool isRegistered() const { return typeID != TypeID::get<void>(); }
160 Dialect *getDialect() const { return dialect; }
161 StringAttr getName() const { return name; }
162 TypeID getTypeID() const { return typeID; }
164
165 protected:
166 //===------------------------------------------------------------------===//
167 // Registered Operation Info
168
169 /// The name of the operation.
170 StringAttr name;
171
172 /// The unique identifier of the derived Op class.
174
175 /// The following fields are only populated when the operation is
176 /// registered.
177
178 /// This is the dialect that this operation belongs to.
180
181 /// A map of interfaces that were registered to this operation.
183
184 /// A list of attribute names registered to this operation in StringAttr
185 /// form. This allows for operation classes to use StringAttr for attribute
186 /// lookup/creation/etc., as opposed to raw strings.
188
190 };
191
192protected:
193 /// Default implementation for unregistered operations.
194 struct UnregisteredOpModel : public Impl {
195 using Impl::Impl;
196 LogicalResult foldHook(Operation *, ArrayRef<Attribute>,
199 bool hasTrait(TypeID) final;
201 void populateDefaultAttrs(const OperationName &, NamedAttrList &) final;
202 void printAssembly(Operation *, OpAsmPrinter &, StringRef) final;
203 LogicalResult verifyInvariants(Operation *) final;
204 LogicalResult verifyRegionInvariants(Operation *) final;
205 /// Implementation for properties
206 std::optional<Attribute> getInherentAttr(Operation *op,
207 StringRef name) final;
208 void setInherentAttr(Operation *op, StringAttr name, Attribute value) final;
209 void populateInherentAttrs(Operation *op, NamedAttrList &attrs) final;
210 LogicalResult
213 int getOpPropertyByteSize() final;
214 void initProperties(OperationName opName, OpaqueProperties storage,
215 OpaqueProperties init) final;
218 OpaqueProperties properties) final;
219 LogicalResult
225 llvm::hash_code hashProperties(OpaqueProperties) final;
226 };
227
228public:
229 OperationName(StringRef name, MLIRContext *context);
230
231 /// Return if this operation is registered.
232 bool isRegistered() const { return getImpl()->isRegistered(); }
233
234 /// Return the unique identifier of the derived Op class, or null if not
235 /// registered.
236 TypeID getTypeID() const { return getImpl()->getTypeID(); }
237
238 /// If this operation is registered, returns the registered information,
239 /// std::nullopt otherwise.
240 std::optional<RegisteredOperationName> getRegisteredInfo() const;
241
242 /// This hook implements a generalized folder for this operation. Operations
243 /// can implement this to provide simplifications rules that are applied by
244 /// the Builder::createOrFold API and the canonicalization pass.
245 ///
246 /// This is an intentionally limited interface - implementations of this
247 /// hook can only perform the following changes to the operation:
248 ///
249 /// 1. They can leave the operation alone and without changing the IR, and
250 /// return failure.
251 /// 2. They can mutate the operation in place, without changing anything
252 /// else in the IR. In this case, return success.
253 /// 3. They can return a list of existing values that can be used instead
254 /// of the operation. In this case, fill in the results list and return
255 /// success. The caller will remove the operation and use those results
256 /// instead.
257 ///
258 /// This allows expression of some simple in-place canonicalizations (e.g.
259 /// "x+0 -> x", "min(x,y,x,z) -> min(x,y,z)", "x+y-x -> y", etc), as well as
260 /// generalized constant folding.
261 LogicalResult foldHook(Operation *op, ArrayRef<Attribute> operands,
262 SmallVectorImpl<OpFoldResult> &results) const {
263 return getImpl()->foldHook(op, operands, results);
264 }
265
266 /// This hook returns any canonicalization pattern rewrites that the
267 /// operation supports, for use by the canonicalization pass.
269 MLIRContext *context) const {
270 return getImpl()->getCanonicalizationPatterns(results, context);
271 }
272
273 /// Returns true if the operation was registered with a particular trait, e.g.
274 /// hasTrait<OperandsAreSignlessIntegerLike>(). Returns false if the operation
275 /// is unregistered.
276 template <template <typename T> class Trait>
277 bool hasTrait() const {
279 }
280 bool hasTrait(TypeID traitID) const { return getImpl()->hasTrait(traitID); }
281
282 /// Returns true if the operation *might* have the provided trait. This
283 /// means that either the operation is unregistered, or it was registered with
284 /// the provide trait.
285 template <template <typename T> class Trait>
286 bool mightHaveTrait() const {
288 }
289 bool mightHaveTrait(TypeID traitID) const {
290 return !isRegistered() || getImpl()->hasTrait(traitID);
291 }
292
293 /// Return the static hook for parsing this operation assembly.
297
298 /// This hook implements the method to populate defaults attributes that are
299 /// unset.
301 getImpl()->populateDefaultAttrs(*this, attrs);
302 }
303
304 /// This hook implements the AsmPrinter for this operation.
306 StringRef defaultDialect) const {
307 return getImpl()->printAssembly(op, p, defaultDialect);
308 }
309
310 /// These hooks implement the verifiers for this operation. It should emits
311 /// an error message and returns failure if a problem is detected, or
312 /// returns success if everything is ok.
313 LogicalResult verifyInvariants(Operation *op) const {
314 return getImpl()->verifyInvariants(op);
315 }
316 LogicalResult verifyRegionInvariants(Operation *op) const {
317 return getImpl()->verifyRegionInvariants(op);
318 }
319
320 /// Return the list of cached attribute names registered to this operation.
321 /// The order of attributes cached here is unique to each type of operation,
322 /// and the interpretation of this attribute list should generally be driven
323 /// by the respective operation. In many cases, this caching removes the
324 /// need to use the raw string name of a known attribute.
325 ///
326 /// For example the ODS generator, with an op defining the following
327 /// attributes:
328 ///
329 /// let arguments = (ins I32Attr:$attr1, I32Attr:$attr2);
330 ///
331 /// ... may produce an order here of ["attr1", "attr2"]. This allows for the
332 /// ODS generator to directly access the cached name for a known attribute,
333 /// greatly simplifying the cost and complexity of attribute usage produced
334 /// by the generator.
335 ///
339
340 /// Returns an instance of the concept object for the given interface if it
341 /// was registered to this operation, null otherwise. This should not be used
342 /// directly.
343 template <typename T>
344 typename T::Concept *getInterface() const {
345 return getImpl()->getInterfaceMap().lookup<T>();
346 }
347
348 /// Attach the given models as implementations of the corresponding
349 /// interfaces for the concrete operation.
350 template <typename... Models>
352 // Handle the case where the models resolve a promised interface.
354 *getDialect(), getTypeID(), Models::Interface::getInterfaceID()),
355 ...);
356
357 getImpl()->getInterfaceMap().insertModels<Models...>();
358 }
359
360 /// Returns true if `InterfaceT` has been promised by the dialect or
361 /// implemented.
362 template <typename InterfaceT>
365 getDialect(), getTypeID(), InterfaceT::getInterfaceID()) ||
367 }
368
369 /// Returns true if this operation has the given interface registered to it.
370 template <typename T>
371 bool hasInterface() const {
373 }
374 bool hasInterface(TypeID interfaceID) const {
375 return getImpl()->getInterfaceMap().contains(interfaceID);
376 }
377
378 /// Returns true if the operation *might* have the provided interface. This
379 /// means that either the operation is unregistered, or it was registered with
380 /// the provide interface.
381 template <typename T>
382 bool mightHaveInterface() const {
384 }
385 bool mightHaveInterface(TypeID interfaceID) const {
386 return !isRegistered() || hasInterface(interfaceID);
387 }
388
389 /// Lookup an inherent attribute by name, this method isn't recommended
390 /// and may be removed in the future.
391 std::optional<Attribute> getInherentAttr(Operation *op,
392 StringRef name) const {
393 return getImpl()->getInherentAttr(op, name);
394 }
395
396 void setInherentAttr(Operation *op, StringAttr name, Attribute value) const {
397 return getImpl()->setInherentAttr(op, name, value);
398 }
399
401 return getImpl()->populateInherentAttrs(op, attrs);
402 }
403 /// This method exists for backward compatibility purpose when using
404 /// properties to store inherent attributes, it enables validating the
405 /// attributes when parsed from the older generic syntax pre-Properties.
406 LogicalResult
409 return getImpl()->verifyInherentAttrs(*this, attributes, emitError);
410 }
411 /// This hooks return the number of bytes to allocate for the op properties.
413 return getImpl()->getOpPropertyByteSize();
414 }
415
416 /// This hooks destroy the op properties.
417 void destroyOpProperties(OpaqueProperties properties) const {
418 getImpl()->deleteProperties(properties);
419 }
420
421 /// Initialize the op properties.
423 getImpl()->initProperties(*this, storage, init);
424 }
425
426 /// Set the default values on the ODS attribute in the properties.
428 getImpl()->populateDefaultProperties(*this, properties);
429 }
430
431 /// Return the op properties converted to an Attribute.
435
436 /// Define the op properties from the provided Attribute.
438 OperationName opName, OpaqueProperties properties, Attribute attr,
440 return getImpl()->setPropertiesFromAttr(opName, properties, attr,
441 emitError);
442 }
443
447
451
452 llvm::hash_code hashOpProperties(OpaqueProperties properties) const {
453 return getImpl()->hashProperties(properties);
454 }
455
456 /// Return the dialect this operation is registered to if the dialect is
457 /// loaded in the context, or nullptr if the dialect isn't loaded.
459 return isRegistered() ? getImpl()->getDialect()
460 : getImpl()->getName().getReferencedDialect();
461 }
462
463 /// Return the name of the dialect this operation is registered to.
464 StringRef getDialectNamespace() const;
465
466 /// Return the operation name with dialect name stripped, if it has one.
467 StringRef stripDialect() const { return getStringRef().split('.').second; }
468
469 /// Return the context this operation is associated with.
470 MLIRContext *getContext() { return getIdentifier().getContext(); }
471
472 /// Return the name of this operation. This always succeeds.
473 StringRef getStringRef() const { return getIdentifier(); }
474
475 /// Return the name of this operation as a StringAttr.
476 StringAttr getIdentifier() const { return getImpl()->getName(); }
477
478 void print(raw_ostream &os) const;
479 void dump() const;
480
481 /// Represent the operation name as an opaque pointer. (Used to support
482 /// PointerLikeTypeTraits).
483 void *getAsOpaquePointer() const { return const_cast<Impl *>(impl); }
484 static OperationName getFromOpaquePointer(const void *pointer) {
485 return OperationName(
486 const_cast<Impl *>(reinterpret_cast<const Impl *>(pointer)));
487 }
488
489 bool operator==(const OperationName &rhs) const { return impl == rhs.impl; }
490 bool operator!=(const OperationName &rhs) const { return !(*this == rhs); }
491
492protected:
494 Impl *getImpl() const { return impl; }
495 void setImpl(Impl *rhs) { impl = rhs; }
496
497private:
498 /// The internal implementation of the operation name.
499 Impl *impl = nullptr;
500
501 /// Allow access to the Impl struct.
502 friend MLIRContextImpl;
505};
506
508 info.print(os);
509 return os;
510}
511
512// Make operation names hashable.
513inline llvm::hash_code hash_value(OperationName arg) {
514 return llvm::hash_value(arg.getAsOpaquePointer());
515}
516
517//===----------------------------------------------------------------------===//
518// RegisteredOperationName
519//===----------------------------------------------------------------------===//
520
521/// This is a "type erased" representation of a registered operation. This
522/// should only be used by things like the AsmPrinter and other things that need
523/// to be parameterized by generic operation hooks. Most user code should use
524/// the concrete operation types.
525class RegisteredOperationName : public OperationName {
526public:
527 /// Implementation of the InterfaceConcept for operation APIs that forwarded
528 /// to a concrete op implementation.
529 template <typename ConcreteOp>
530 struct Model : public Impl {
532 : Impl(ConcreteOp::getOperationName(), dialect,
533 TypeID::get<ConcreteOp>(), ConcreteOp::getInterfaceMap()) {}
534 LogicalResult foldHook(Operation *op, ArrayRef<Attribute> attrs,
535 SmallVectorImpl<OpFoldResult> &results) final {
536 return ConcreteOp::getFoldHookFn()(op, attrs, results);
537 }
539 MLIRContext *context) final {
540 ConcreteOp::getCanonicalizationPatterns(set, context);
541 }
542 bool hasTrait(TypeID id) final { return ConcreteOp::getHasTraitFn()(id); }
544 return ConcreteOp::parse;
545 }
546 void populateDefaultAttrs(const OperationName &name,
547 NamedAttrList &attrs) final {
548 ConcreteOp::populateDefaultAttrs(name, attrs);
549 }
551 StringRef name) final {
552 ConcreteOp::getPrintAssemblyFn()(op, printer, name);
553 }
554 LogicalResult verifyInvariants(Operation *op) final {
555 return ConcreteOp::getVerifyInvariantsFn()(op);
556 }
557 LogicalResult verifyRegionInvariants(Operation *op) final {
558 return ConcreteOp::getVerifyRegionInvariantsFn()(op);
559 }
560
561 /// Implementation for "Properties"
562
563 using Properties = std::remove_reference_t<
564 decltype(std::declval<ConcreteOp>().getProperties())>;
565
566 std::optional<Attribute> getInherentAttr(Operation *op,
567 StringRef name) final {
568 if constexpr (hasProperties) {
569 auto concreteOp = cast<ConcreteOp>(op);
570 return ConcreteOp::getInherentAttr(concreteOp->getContext(),
571 concreteOp.getProperties(), name);
572 }
573 // If the op does not have support for properties, we dispatch back to the
574 // dictionnary of discardable attributes for now.
575 return cast<ConcreteOp>(op)->getDiscardableAttr(name);
576 }
577 void setInherentAttr(Operation *op, StringAttr name,
578 Attribute value) final {
579 if constexpr (hasProperties) {
580 auto concreteOp = cast<ConcreteOp>(op);
581 return ConcreteOp::setInherentAttr(concreteOp.getProperties(), name,
582 value);
583 }
584 // If the op does not have support for properties, we dispatch back to the
585 // dictionnary of discardable attributes for now.
586 return cast<ConcreteOp>(op)->setDiscardableAttr(name, value);
587 }
589 if constexpr (hasProperties) {
590 auto concreteOp = cast<ConcreteOp>(op);
591 ConcreteOp::populateInherentAttrs(concreteOp->getContext(),
592 concreteOp.getProperties(), attrs);
593 }
594 }
595 LogicalResult
596 verifyInherentAttrs(OperationName opName, NamedAttrList &attributes,
598 if constexpr (hasProperties)
599 return ConcreteOp::verifyInherentAttrs(opName, attributes, emitError);
600 return success();
601 }
602 // Detect if the concrete operation defined properties.
603 static constexpr bool hasProperties = !std::is_same_v<
604 typename ConcreteOp::template InferredProperties<ConcreteOp>,
606
608 if constexpr (hasProperties)
609 return sizeof(Properties);
610 return 0;
611 }
612 void initProperties(OperationName opName, OpaqueProperties storage,
613 OpaqueProperties init) final {
614 using Properties =
615 typename ConcreteOp::template InferredProperties<ConcreteOp>;
616 if (init)
617 new (storage.as<Properties *>()) Properties(*init.as<Properties *>());
618 else
619 new (storage.as<Properties *>()) Properties();
620 if constexpr (hasProperties)
621 ConcreteOp::populateDefaultProperties(opName,
622 *storage.as<Properties *>());
623 }
625 prop.as<Properties *>()->~Properties();
626 }
627 void populateDefaultProperties(OperationName opName,
628 OpaqueProperties properties) final {
629 if constexpr (hasProperties)
630 ConcreteOp::populateDefaultProperties(opName,
631 *properties.as<Properties *>());
632 }
633
634 LogicalResult
635 setPropertiesFromAttr(OperationName opName, OpaqueProperties properties,
636 Attribute attr,
638 if constexpr (hasProperties) {
639 auto p = properties.as<Properties *>();
640 return ConcreteOp::setPropertiesFromAttr(*p, attr, emitError);
641 }
642 emitError() << "this operation does not support properties";
643 return failure();
644 }
646 if constexpr (hasProperties) {
647 auto concreteOp = cast<ConcreteOp>(op);
648 return ConcreteOp::getPropertiesAsAttr(concreteOp->getContext(),
649 concreteOp.getProperties());
650 }
651 return {};
652 }
654 if constexpr (hasProperties) {
655 return *lhs.as<Properties *>() == *rhs.as<Properties *>();
656 } else {
657 return true;
658 }
659 }
661 *lhs.as<Properties *>() = *rhs.as<Properties *>();
662 }
663 llvm::hash_code hashProperties(OpaqueProperties prop) final {
664 if constexpr (hasProperties)
665 return ConcreteOp::computePropertiesHash(*prop.as<Properties *>());
666
667 return {};
668 }
669 };
670
671 /// Lookup the registered operation information for the given operation.
672 /// Returns std::nullopt if the operation isn't registered.
673 static std::optional<RegisteredOperationName> lookup(StringRef name,
674 MLIRContext *ctx);
675
676 /// Lookup the registered operation information for the given operation.
677 /// Returns std::nullopt if the operation isn't registered.
678 static std::optional<RegisteredOperationName> lookup(TypeID typeID,
679 MLIRContext *ctx);
680
681 /// Register a new operation in a Dialect object.
682 /// This constructor is used by Dialect objects when they register the list
683 /// of operations they contain.
684 template <typename T>
685 static void insert(Dialect &dialect) {
686 insert(std::make_unique<Model<T>>(&dialect), T::getAttributeNames());
687 }
688 /// The use of this method is in general discouraged in favor of
689 /// 'insert<CustomOp>(dialect)'.
690 static void insert(std::unique_ptr<OperationName::Impl> ownedImpl,
691 ArrayRef<StringRef> attrNames);
692
693 /// Return the dialect this operation is registered to.
694 Dialect &getDialect() const { return *getImpl()->getDialect(); }
695
696 /// Represent the operation name as an opaque pointer. (Used to support
697 /// PointerLikeTypeTraits).
698 static RegisteredOperationName getFromOpaquePointer(const void *pointer) {
699 return RegisteredOperationName(
700 const_cast<Impl *>(reinterpret_cast<const Impl *>(pointer)));
701 }
702
703private:
705
706 /// Allow access to the constructor.
707 friend OperationName;
708};
709
710inline std::optional<RegisteredOperationName>
713 : std::optional<RegisteredOperationName>();
714}
715
716//===----------------------------------------------------------------------===//
717// Attribute Dictionary-Like Interface
718//===----------------------------------------------------------------------===//
719
720/// Attribute collections provide a dictionary-like interface. Define common
721/// lookup functions.
722namespace impl {
723
724/// Unsorted string search or identifier lookups are linear scans.
725template <typename IteratorT, typename NameT>
726std::pair<IteratorT, bool> findAttrUnsorted(IteratorT first, IteratorT last,
727 NameT name) {
728 for (auto it = first; it != last; ++it)
729 if (it->getName() == name)
730 return {it, true};
731 return {last, false};
732}
733
734/// Using llvm::lower_bound requires an extra string comparison to check whether
735/// the returned iterator points to the found element or whether it indicates
736/// the lower bound. Skip this redundant comparison by checking if `compare ==
737/// 0` during the binary search.
738template <typename IteratorT>
739std::pair<IteratorT, bool> findAttrSorted(IteratorT first, IteratorT last,
740 StringRef name) {
741 ptrdiff_t length = std::distance(first, last);
742
743 while (length > 0) {
744 ptrdiff_t half = length / 2;
745 IteratorT mid = first + half;
746 int compare = mid->getName().strref().compare(name);
747 if (compare < 0) {
748 first = mid + 1;
749 length = length - half - 1;
750 } else if (compare > 0) {
751 length = half;
752 } else {
753 return {mid, true};
754 }
755 }
756 return {first, false};
757}
758
759/// StringAttr lookups on large attribute lists will switch to string binary
760/// search. String binary searches become significantly faster than linear scans
761/// with the identifier when the attribute list becomes very large.
762template <typename IteratorT>
763std::pair<IteratorT, bool> findAttrSorted(IteratorT first, IteratorT last,
764 StringAttr name) {
765 constexpr unsigned kSmallAttributeList = 16;
766 if (std::distance(first, last) > kSmallAttributeList)
767 return findAttrSorted(first, last, name.strref());
768 return findAttrUnsorted(first, last, name);
769}
770
771/// Get an attribute from a sorted range of named attributes. Returns null if
772/// the attribute was not found.
773template <typename IteratorT, typename NameT>
774Attribute getAttrFromSortedRange(IteratorT first, IteratorT last, NameT name) {
775 std::pair<IteratorT, bool> result = findAttrSorted(first, last, name);
776 return result.second ? result.first->getValue() : Attribute();
777}
778
779/// Get an attribute from a sorted range of named attributes. Returns
780/// std::nullopt if the attribute was not found.
781template <typename IteratorT, typename NameT>
782std::optional<NamedAttribute>
783getNamedAttrFromSortedRange(IteratorT first, IteratorT last, NameT name) {
784 std::pair<IteratorT, bool> result = findAttrSorted(first, last, name);
785 return result.second ? *result.first : std::optional<NamedAttribute>();
786}
787
788} // namespace impl
789
790//===----------------------------------------------------------------------===//
791// NamedAttrList
792//===----------------------------------------------------------------------===//
793
794/// NamedAttrList is array of NamedAttributes that tracks whether it is sorted
795/// and does some basic work to remain sorted.
797public:
802 using size_type = size_t;
803
804 NamedAttrList() : dictionarySorted({}, true) {}
805 LLVM_DEPRECATED("Use NamedAttrList() instead", "NamedAttrList()")
806 NamedAttrList(std::nullopt_t none) : NamedAttrList() {}
808 NamedAttrList(DictionaryAttr attributes);
810
811 template <typename Container>
812 NamedAttrList(const Container &vec)
814
815 bool operator!=(const NamedAttrList &other) const {
816 return !(*this == other);
817 }
818 bool operator==(const NamedAttrList &other) const {
819 return attrs == other.attrs;
820 }
821
822 /// Add an attribute with the specified name.
823 void append(StringRef name, Attribute attr) {
824 append(NamedAttribute(name, attr));
825 }
826
827 /// Add an attribute with the specified name.
828 void append(StringAttr name, Attribute attr) {
829 append(NamedAttribute(name, attr));
830 }
831
832 /// Append the given named attribute.
833 void append(NamedAttribute attr) { push_back(attr); }
834
835 /// Add an array of named attributes.
836 template <typename RangeT>
837 void append(RangeT &&newAttributes) {
838 append(std::begin(newAttributes), std::end(newAttributes));
839 }
840
841 /// Add a range of named attributes.
842 template <typename IteratorT,
843 typename = std::enable_if_t<std::is_convertible<
844 typename std::iterator_traits<IteratorT>::iterator_category,
845 std::input_iterator_tag>::value>>
846 void append(IteratorT inStart, IteratorT inEnd) {
847 // TODO: expand to handle case where values appended are in order & after
848 // end of current list.
849 dictionarySorted.setPointerAndInt(nullptr, false);
850 attrs.append(inStart, inEnd);
851 }
852
853 /// Replaces the attributes with new list of attributes.
854 void assign(const_iterator inStart, const_iterator inEnd);
855
856 /// Replaces the attributes with new list of attributes.
858 assign(range.begin(), range.end());
859 }
860
861 void clear() {
862 attrs.clear();
863 dictionarySorted.setPointerAndInt(nullptr, false);
864 }
865
866 bool empty() const { return attrs.empty(); }
867
868 void reserve(size_type N) { attrs.reserve(N); }
869
870 /// Add an attribute with the specified name.
871 void push_back(NamedAttribute newAttribute);
872
873 /// Pop last element from list.
874 void pop_back() { attrs.pop_back(); }
875
876 /// Returns an entry with a duplicate name the list, if it exists, else
877 /// returns std::nullopt.
878 std::optional<NamedAttribute> findDuplicate() const;
879
880 /// Return a dictionary attribute for the underlying dictionary. This will
881 /// return an empty dictionary attribute if empty rather than null.
882 DictionaryAttr getDictionary(MLIRContext *context) const;
883
884 /// Return all of the attributes on this operation.
886
887 /// Return the specified attribute if present, null otherwise.
888 Attribute get(StringAttr name) const;
889 Attribute get(StringRef name) const;
890
891 /// Return the specified named attribute if present, std::nullopt otherwise.
892 std::optional<NamedAttribute> getNamed(StringRef name) const;
893 std::optional<NamedAttribute> getNamed(StringAttr name) const;
894
895 /// If the an attribute exists with the specified name, change it to the new
896 /// value. Otherwise, add a new attribute with the specified name/value.
897 /// Returns the previous attribute value of `name`, or null if no
898 /// attribute previously existed with `name`.
899 Attribute set(StringAttr name, Attribute value);
900 Attribute set(StringRef name, Attribute value);
901
902 /// Erase the attribute with the given name from the list. Return the
903 /// attribute that was erased, or nullptr if there was no attribute with such
904 /// name.
905 Attribute erase(StringAttr name);
906 Attribute erase(StringRef name);
907
908 iterator begin() { return attrs.begin(); }
909 iterator end() { return attrs.end(); }
910 const_iterator begin() const { return attrs.begin(); }
911 const_iterator end() const { return attrs.end(); }
912
914 operator ArrayRef<NamedAttribute>() const;
915
916private:
917 /// Return whether the attributes are sorted.
918 bool isSorted() const { return dictionarySorted.getInt(); }
919
920 /// Erase the attribute at the given iterator position.
921 Attribute eraseImpl(SmallVectorImpl<NamedAttribute>::iterator it);
922
923 /// Lookup an attribute in the list.
924 template <typename AttrListT, typename NameT>
925 static auto findAttr(AttrListT &attrs, NameT name) {
926 return attrs.isSorted()
927 ? impl::findAttrSorted(attrs.begin(), attrs.end(), name)
928 : impl::findAttrUnsorted(attrs.begin(), attrs.end(), name);
929 }
930
931 // These are marked mutable as they may be modified (e.g., sorted)
932 mutable SmallVector<NamedAttribute, 4> attrs;
933 // Pair with cached DictionaryAttr and status of whether attrs is sorted.
934 // Note: just because sorted does not mean a DictionaryAttr has been created
935 // but the case where there is a DictionaryAttr but attrs isn't sorted should
936 // not occur.
937 mutable llvm::PointerIntPair<Attribute, 1, bool> dictionarySorted;
938};
939
940//===----------------------------------------------------------------------===//
941// OperationState
942//===----------------------------------------------------------------------===//
943
944/// This represents an operation in an abstracted form, suitable for use with
945/// the builder APIs. This object is a large and heavy weight object meant to
946/// be used as a temporary object on the stack. It is generally unwise to put
947/// this in a collection.
952 /// Types of the results of this operation.
955 /// Successors of this operation and their respective operands.
957 /// Regions that the op will hold.
959
960 /// This Attribute is used to opaquely construct the properties of the
961 /// operation. If we're creating an unregistered operation, the Attribute is
962 /// used as-is as the Properties storage of the operation. Otherwise, the
963 /// operation properties are constructed opaquely using its
964 /// `setPropertiesFromAttr` hook. Note that `getOrAddProperties` is the
965 /// preferred method to construct properties from C++.
967
968private:
969 OpaqueProperties properties = nullptr;
970 TypeID propertiesId;
971 llvm::function_ref<void(OpaqueProperties)> propertiesDeleter;
973 propertiesSetter;
974 friend class Operation;
975
976public:
979
983 MutableArrayRef<std::unique_ptr<Region>> regions = {});
984 OperationState(Location location, StringRef name, ValueRange operands,
985 TypeRange types, ArrayRef<NamedAttribute> attributes = {},
986 BlockRange successors = {},
987 MutableArrayRef<std::unique_ptr<Region>> regions = {});
988 OperationState(OperationState &&other) = default;
990 OperationState(const OperationState &other) = delete;
991 OperationState &operator=(const OperationState &other) = delete;
993
994 /// Get (or create) a properties of the provided type to be set on the
995 /// operation on creation.
996 template <typename T>
998 if (!properties) {
999 T *p = new T{};
1000 properties = p;
1001#if defined(__clang__)
1002#if __has_warning("-Wdangling-assignment-gsl")
1003#pragma clang diagnostic push
1004// https://github.com/llvm/llvm-project/issues/126600
1005#pragma clang diagnostic ignored "-Wdangling-assignment-gsl"
1006#endif
1007#endif
1008 propertiesDeleter = [](OpaqueProperties prop) {
1009 delete prop.as<const T *>();
1010 };
1011 propertiesSetter = [](OpaqueProperties newProp,
1012 const OpaqueProperties prop) {
1013 *newProp.as<T *>() = *prop.as<const T *>();
1014 };
1015#if defined(__clang__)
1016#if __has_warning("-Wdangling-assignment-gsl")
1017#pragma clang diagnostic pop
1018#endif
1019#endif
1020 propertiesId = TypeID::get<T>();
1021 }
1022 assert(propertiesId == TypeID::get<T>() && "Inconsistent properties");
1023 return *properties.as<T *>();
1024 }
1025 OpaqueProperties getRawProperties() { return properties; }
1026
1027 // Set the properties defined on this OpState on the given operation,
1028 // optionally emit diagnostics on error through the provided diagnostic.
1029 LogicalResult
1032
1033 // Make `newProperties` the source of the properties that will be copied into
1034 // the operation. The memory referenced by `newProperties` must remain live
1035 // until after the `Operation` is created, at which time it may be
1036 // deallocated. Calls to `getOrAddProperties<>() will return references to
1037 // this memory.
1038 template <typename T>
1039 void useProperties(T &newProperties) {
1040 assert(!properties &&
1041 "Can't provide a properties struct when one has been allocated");
1042 properties = &newProperties;
1043#if defined(__clang__)
1044#if __has_warning("-Wdangling-assignment-gsl")
1045#pragma clang diagnostic push
1046// https://github.com/llvm/llvm-project/issues/126600
1047#pragma clang diagnostic ignored "-Wdangling-assignment-gsl"
1048#endif
1049#endif
1050 propertiesDeleter = [](OpaqueProperties) {};
1051 propertiesSetter = [](OpaqueProperties newProp,
1052 const OpaqueProperties prop) {
1053 *newProp.as<T *>() = *prop.as<const T *>();
1054 };
1055#if defined(__clang__)
1056#if __has_warning("-Wdangling-assignment-gsl")
1057#pragma clang diagnostic pop
1058#endif
1059#endif
1060 propertiesId = TypeID::get<T>();
1061 }
1062
1063 void addOperands(ValueRange newOperands);
1064
1065 void addTypes(ArrayRef<Type> newTypes) {
1066 types.append(newTypes.begin(), newTypes.end());
1067 }
1068 template <typename RangeT>
1069 std::enable_if_t<!std::is_convertible<RangeT, ArrayRef<Type>>::value>
1070 addTypes(RangeT &&newTypes) {
1071 types.append(newTypes.begin(), newTypes.end());
1072 }
1073
1074 /// Add an attribute with the specified name.
1075 void addAttribute(StringRef name, Attribute attr) {
1076 addAttribute(StringAttr::get(getContext(), name), attr);
1077 }
1078
1079 /// Add an attribute with the specified name. `name` and `attr` must not be
1080 /// null.
1081 void addAttribute(StringAttr name, Attribute attr) {
1082 assert(name && "attribute name cannot be null");
1083 assert(attr && "attribute cannot be null");
1084 attributes.append(name, attr);
1085 }
1086
1087 /// Add an array of named attributes.
1089 attributes.append(newAttributes);
1090 }
1091
1092 /// Adds a successor to the operation sate. `successor` must not be null.
1093 void addSuccessors(Block *successor) {
1094 assert(successor && "successor cannot be null");
1095 successors.push_back(successor);
1096 }
1097 void addSuccessors(BlockRange newSuccessors);
1098
1099 /// Create a region that should be attached to the operation. These regions
1100 /// can be filled in immediately without waiting for Operation to be
1101 /// created. When it is, the region bodies will be transferred.
1102 Region *addRegion();
1103
1104 /// Take a region that should be attached to the Operation. The body of the
1105 /// region will be transferred when the Operation is constructed. If the
1106 /// region is null, a new empty region will be attached to the Operation.
1107 void addRegion(std::unique_ptr<Region> &&region);
1108
1109 /// Take ownership of a set of regions that should be attached to the
1110 /// Operation.
1111 void addRegions(MutableArrayRef<std::unique_ptr<Region>> regions);
1112
1113 /// Get the context held by this operation state.
1114 MLIRContext *getContext() const { return location->getContext(); }
1115};
1116
1117//===----------------------------------------------------------------------===//
1118// OperandStorage
1119//===----------------------------------------------------------------------===//
1120
1121namespace detail {
1122/// This class handles the management of operation operands. Operands are
1123/// stored either in a trailing array, or a dynamically resizable vector.
1124class alignas(8) OperandStorage {
1125public:
1126 OperandStorage(Operation *owner, OpOperand *trailingOperands,
1127 ValueRange values);
1129
1130 /// Replace the operands contained in the storage with the ones provided in
1131 /// 'values'.
1132 void setOperands(Operation *owner, ValueRange values);
1133
1134 /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
1135 /// with the ones provided in 'operands'. 'operands' may be smaller or larger
1136 /// than the range pointed to by 'start'+'length'.
1137 void setOperands(Operation *owner, unsigned start, unsigned length,
1138 ValueRange operands);
1139
1140 /// Erase the operands held by the storage within the given range.
1141 void eraseOperands(unsigned start, unsigned length);
1142
1143 /// Erase the operands held by the storage that have their corresponding bit
1144 /// set in `eraseIndices`.
1145 void eraseOperands(const BitVector &eraseIndices);
1146
1147 /// Get the operation operands held by the storage.
1148 MutableArrayRef<OpOperand> getOperands() { return {operandStorage, size()}; }
1149
1150 /// Return the number of operands held in the storage.
1151 unsigned size() { return numOperands; }
1152
1153private:
1154 /// Resize the storage to the given size. Returns the array containing the new
1155 /// operands.
1156 MutableArrayRef<OpOperand> resize(Operation *owner, unsigned newSize);
1157
1158 /// The total capacity number of operands that the storage can hold.
1159 unsigned capacity : 31;
1160 /// A flag indicating if the operand storage was dynamically allocated, as
1161 /// opposed to inlined into the owning operation.
1162 unsigned isStorageDynamic : 1;
1163 /// The number of operands within the storage.
1164 unsigned numOperands;
1165 /// A pointer to the operand storage.
1166 OpOperand *operandStorage;
1167};
1168} // namespace detail
1169
1170//===----------------------------------------------------------------------===//
1171// OpPrintingFlags
1172//===----------------------------------------------------------------------===//
1173
1174/// Set of flags used to control the behavior of the various IR print methods
1175/// (e.g. Operation::Print).
1177public:
1179 LLVM_DEPRECATED("Use OpPrintingFlags() instead", "OpPrintingFlags()")
1180 OpPrintingFlags(std::nullopt_t) : OpPrintingFlags() {}
1181
1182 /// Enables the elision of large elements attributes by printing a lexically
1183 /// valid but otherwise meaningless form instead of the element data. The
1184 /// `largeElementLimit` is used to configure what is considered to be a
1185 /// "large" ElementsAttr by providing an upper limit to the number of
1186 /// elements.
1187 OpPrintingFlags &elideLargeElementsAttrs(int64_t largeElementLimit = 16);
1188
1189 /// Enables the printing of large element attributes with a hex string. The
1190 /// `largeElementLimit` is used to configure what is considered to be a
1191 /// "large" ElementsAttr by providing an upper limit to the number of
1192 /// elements. Use -1 to disable the hex printing.
1194 printLargeElementsAttrWithHex(int64_t largeElementLimit = 100);
1195
1196 /// Enables the elision of large resources strings by omitting them from the
1197 /// `dialect_resources` section. The `largeResourceLimit` is used to configure
1198 /// what is considered to be a "large" resource by providing an upper limit to
1199 /// the string size.
1200 OpPrintingFlags &elideLargeResourceString(int64_t largeResourceLimit = 64);
1201
1202 /// Enable or disable printing of debug information (based on `enable`). If
1203 /// 'prettyForm' is set to true, debug information is printed in a more
1204 /// readable 'pretty' form. Note: The IR generated with 'prettyForm' is not
1205 /// parsable.
1206 OpPrintingFlags &enableDebugInfo(bool enable = true, bool prettyForm = false);
1207
1208 /// Always print operations in the generic form.
1209 OpPrintingFlags &printGenericOpForm(bool enable = true);
1210
1211 /// Skip printing regions.
1212 OpPrintingFlags &skipRegions(bool skip = true);
1213
1214 /// Do not verify the operation when using custom operation printers.
1215 OpPrintingFlags &assumeVerified(bool enable = true);
1216
1217 /// Use local scope when printing the operation. This allows for using the
1218 /// printer in a more localized and thread-safe setting, but may not
1219 /// necessarily be identical to what the IR will look like when dumping
1220 /// the full module.
1221 OpPrintingFlags &useLocalScope(bool enable = true);
1222
1223 /// Print users of values as comments.
1224 OpPrintingFlags &printValueUsers(bool enable = true);
1225
1226 /// Print unique SSA ID numbers for values, block arguments and naming
1227 /// conflicts across all regions
1228 OpPrintingFlags &printUniqueSSAIDs(bool enable = true);
1229
1230 /// Print SSA IDs using their NameLoc, if provided, as prefix.
1231 OpPrintingFlags &printNameLocAsPrefix(bool enable = true);
1232
1233 /// Return if the given ElementsAttr should be elided.
1234 bool shouldElideElementsAttr(ElementsAttr attr) const;
1235
1236 /// Return if the given ElementsAttr should be printed as hex string.
1237 bool shouldPrintElementsAttrWithHex(ElementsAttr attr) const;
1238
1239 /// Return the size limit for printing large ElementsAttr.
1240 std::optional<int64_t> getLargeElementsAttrLimit() const;
1241
1242 /// Return the size limit for printing large ElementsAttr as hex string.
1244
1245 /// Return the size limit in chars for printing large resources.
1246 std::optional<uint64_t> getLargeResourceStringLimit() const;
1247
1248 /// Return if debug information should be printed.
1249 bool shouldPrintDebugInfo() const;
1250
1251 /// Return if debug information should be printed in the pretty form.
1252 bool shouldPrintDebugInfoPrettyForm() const;
1253
1254 /// Return if operations should be printed in the generic form.
1255 bool shouldPrintGenericOpForm() const;
1256
1257 /// Return if regions should be skipped.
1258 bool shouldSkipRegions() const;
1259
1260 /// Return if operation verification should be skipped.
1261 bool shouldAssumeVerified() const;
1262
1263 /// Return if the printer should use local scope when dumping the IR.
1264 bool shouldUseLocalScope() const;
1265
1266 /// Return if the printer should print users of values.
1267 bool shouldPrintValueUsers() const;
1268
1269 /// Return if printer should use unique SSA IDs.
1270 bool shouldPrintUniqueSSAIDs() const;
1271
1272 /// Return if the printer should use NameLocs as prefixes when printing SSA
1273 /// IDs
1274 bool shouldUseNameLocAsPrefix() const;
1275
1276private:
1277 /// Elide large elements attributes if the number of elements is larger than
1278 /// the upper limit.
1279 std::optional<int64_t> elementsAttrElementLimit;
1280
1281 /// Elide printing large resources based on size of string.
1282 std::optional<uint64_t> resourceStringCharLimit;
1283
1284 /// Print large element attributes with hex strings if the number of elements
1285 /// is larger than the upper limit.
1286 int64_t elementsAttrHexElementLimit = 100;
1287
1288 /// Print debug information.
1289 bool printDebugInfoFlag : 1;
1290 bool printDebugInfoPrettyFormFlag : 1;
1291
1292 /// Print operations in the generic form.
1293 bool printGenericOpFormFlag : 1;
1294
1295 /// Always skip Regions.
1296 bool skipRegionsFlag : 1;
1297
1298 /// Skip operation verification.
1299 bool assumeVerifiedFlag : 1;
1300
1301 /// Print operations with numberings local to the current operation.
1302 bool printLocalScope : 1;
1303
1304 /// Print users of values.
1305 bool printValueUsersFlag : 1;
1306
1307 /// Print unique SSA IDs for values, block arguments and naming conflicts
1308 bool printUniqueSSAIDsFlag : 1;
1309
1310 /// Print SSA IDs using NameLocs as prefixes
1311 bool useNameLocAsPrefix : 1;
1312};
1313
1314//===----------------------------------------------------------------------===//
1315// Operation Equivalency
1316//===----------------------------------------------------------------------===//
1317
1318/// This class provides utilities for computing if two operations are
1319/// equivalent.
1321 enum Flags {
1322 None = 0,
1323
1324 // When provided, the location attached to the operation are ignored.
1326
1327 // When provided, the discardable attributes attached to the operation are
1328 // ignored.
1330
1331 // When provided, the properties attached to the operation are ignored.
1333
1334 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IgnoreProperties)
1335 };
1336
1337 /// Compute a hash for the given operation.
1338 /// The `hashOperands` and `hashResults` callbacks are expected to return a
1339 /// unique hash_code for a given Value.
1340 static llvm::hash_code computeHash(
1341 Operation *op,
1342 function_ref<llvm::hash_code(Value)> hashOperands =
1343 [](Value v) { return hash_value(v); },
1344 function_ref<llvm::hash_code(Value)> hashResults =
1345 [](Value v) { return hash_value(v); },
1346 Flags flags = Flags::None);
1347
1348 /// Helper that can be used with `computeHash` above to ignore operation
1349 /// operands/result mapping.
1350 static llvm::hash_code ignoreHashValue(Value) { return llvm::hash_code{}; }
1351 /// Helper that can be used with `computeHash` above to ignore operation
1352 /// operands/result mapping.
1353 static llvm::hash_code directHashValue(Value v) { return hash_value(v); }
1354
1355 /// Compare two operations (including their regions) and return if they are
1356 /// equivalent.
1357 ///
1358 /// * `checkEquivalent` is a callback to check if two values are equivalent.
1359 /// For two operations to be equivalent, their operands must be the same SSA
1360 /// value or this callback must return `success`.
1361 /// * `markEquivalent` is a callback to inform the caller that the analysis
1362 /// determined that two values are equivalent.
1363 /// * `checkCommutativeEquivalent` is an optional callback to check for
1364 /// equivalence across two ranges for a commutative operation. If not passed
1365 /// in, then equivalence is checked pairwise. This callback is needed to be
1366 /// able to query the optional equivalence classes.
1367 ///
1368 /// Note: Additional information regarding value equivalence can be injected
1369 /// into the analysis via `checkEquivalent`. Typically, callers may want
1370 /// values that were determined to be equivalent as per `markEquivalent` to be
1371 /// reflected in `checkEquivalent`, unless `exactValueMatch` or a different
1372 /// equivalence relationship is desired.
1373 static bool
1375 function_ref<LogicalResult(Value, Value)> checkEquivalent,
1376 function_ref<void(Value, Value)> markEquivalent = nullptr,
1377 Flags flags = Flags::None,
1378 function_ref<LogicalResult(ValueRange, ValueRange)>
1379 checkCommutativeEquivalent = nullptr);
1380
1381 /// Compare two operations and return if they are equivalent.
1382 static bool isEquivalentTo(Operation *lhs, Operation *rhs, Flags flags);
1383
1384 /// Compare two regions (including their subregions) and return if they are
1385 /// equivalent. See also `isEquivalentTo` for details.
1386 static bool isRegionEquivalentTo(
1387 Region *lhs, Region *rhs,
1388 function_ref<LogicalResult(Value, Value)> checkEquivalent,
1389 function_ref<void(Value, Value)> markEquivalent,
1391 function_ref<LogicalResult(ValueRange, ValueRange)>
1392 checkCommutativeEquivalent = nullptr);
1393
1394 /// Compare two regions and return if they are equivalent.
1395 static bool isRegionEquivalentTo(Region *lhs, Region *rhs,
1397
1398 /// Helper that can be used with `isEquivalentTo` above to consider ops
1399 /// equivalent even if their operands are not equivalent.
1400 static LogicalResult ignoreValueEquivalence(Value lhs, Value rhs) {
1401 return success();
1402 }
1403 /// Helper that can be used with `isEquivalentTo` above to consider ops
1404 /// equivalent only if their operands are the exact same SSA values.
1405 static LogicalResult exactValueMatch(Value lhs, Value rhs) {
1406 return success(lhs == rhs);
1407 }
1408};
1409
1410/// Enable Bitmask enums for OperationEquivalence::Flags.
1412
1413//===----------------------------------------------------------------------===//
1414// OperationFingerPrint
1415//===----------------------------------------------------------------------===//
1416
1417/// A unique fingerprint for a specific operation, and all of it's internal
1418/// operations (if `includeNested` is set).
1420public:
1421 OperationFingerPrint(Operation *topOp, bool includeNested = true);
1424
1425 bool operator==(const OperationFingerPrint &other) const {
1426 return hash == other.hash;
1427 }
1428 bool operator!=(const OperationFingerPrint &other) const {
1429 return !(*this == other);
1430 }
1431
1432private:
1433 std::array<uint8_t, 20> hash;
1434};
1435
1436} // namespace mlir
1437
1438namespace llvm {
1439template <>
1456template <>
1457struct DenseMapInfo<mlir::RegisteredOperationName>
1458 : public DenseMapInfo<mlir::OperationName> {
1467};
1468
1469template <>
1470struct PointerLikeTypeTraits<mlir::OperationName> {
1471 static inline void *getAsVoidPointer(mlir::OperationName I) {
1472 return const_cast<void *>(I.getAsOpaquePointer());
1473 }
1477 static constexpr int NumLowBitsAvailable =
1478 PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
1479};
1480template <>
1481struct PointerLikeTypeTraits<mlir::RegisteredOperationName>
1482 : public PointerLikeTypeTraits<mlir::OperationName> {
1486};
1487
1488} // namespace llvm
1489
1490#endif
return success()
lhs
Attributes are known-constant values of operations.
Definition Attributes.h:25
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 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
This is the implementation of the MLIRContext class, using the pImpl idiom.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
This class represents a contiguous range of mutable operand ranges, e.g.
Definition ValueRange.h:210
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
std::optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, std::nullopt otherwise.
LLVM_DEPRECATED("Use NamedAttrList() instead", "NamedAttrList()") NamedAttrList(std
void append(IteratorT inStart, IteratorT inEnd)
Add a range of named attributes.
void assign(ArrayRef< NamedAttribute > range)
Replaces the attributes with new list of attributes.
const_iterator begin() const
void assign(const_iterator inStart, const_iterator inEnd)
Replaces the attributes with new list of attributes.
NamedAttribute & reference
SmallVectorImpl< NamedAttribute >::const_iterator const_iterator
void append(NamedAttribute attr)
Append the given named attribute.
bool operator!=(const NamedAttrList &other) const
ArrayRef< NamedAttribute > getAttrs() const
Return all of the attributes on this operation.
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
SmallVectorImpl< NamedAttribute >::iterator iterator
const_iterator end() const
NamedAttrList(const Container &vec)
void append(StringAttr name, Attribute attr)
Add an attribute with the specified name.
void pop_back()
Pop last element from list.
bool operator==(const NamedAttrList &other) const
Attribute get(StringAttr name) const
Return the specified attribute if present, null otherwise.
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.
std::optional< NamedAttribute > findDuplicate() const
Returns an entry with a duplicate name the list, if it exists, else returns std::nullopt.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
void append(RangeT &&newAttributes)
Add an array of named attributes.
void reserve(size_type N)
const NamedAttribute & const_reference
NamedAttrList & operator=(const SmallVectorImpl< NamedAttribute > &rhs)
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This class represents a single result from folding an operation.
This class represents an operand of an operation.
Definition Value.h:257
Set of flags used to control the behavior of the various IR print methods (e.g.
bool shouldElideElementsAttr(ElementsAttr attr) const
Return if the given ElementsAttr should be elided.
std::optional< int64_t > getLargeElementsAttrLimit() const
Return the size limit for printing large ElementsAttr.
bool shouldUseNameLocAsPrefix() const
Return if the printer should use NameLocs as prefixes when printing SSA IDs.
bool shouldAssumeVerified() const
Return if operation verification should be skipped.
OpPrintingFlags & printLargeElementsAttrWithHex(int64_t largeElementLimit=100)
Enables the printing of large element attributes with a hex string.
bool shouldUseLocalScope() const
Return if the printer should use local scope when dumping the IR.
bool shouldPrintDebugInfoPrettyForm() const
Return if debug information should be printed in the pretty form.
bool shouldPrintElementsAttrWithHex(ElementsAttr attr) const
Return if the given ElementsAttr should be printed as hex string.
bool shouldPrintUniqueSSAIDs() const
Return if printer should use unique SSA IDs.
bool shouldPrintValueUsers() const
Return if the printer should print users of values.
int64_t getLargeElementsAttrHexLimit() const
Return the size limit for printing large ElementsAttr as hex string.
bool shouldPrintGenericOpForm() const
Return if operations should be printed in the generic form.
OpPrintingFlags & elideLargeResourceString(int64_t largeResourceLimit=64)
Enables the elision of large resources strings by omitting them from the dialect_resources section.
bool shouldPrintDebugInfo() const
Return if debug information should be printed.
OpPrintingFlags & elideLargeElementsAttrs(int64_t largeElementLimit=16)
Enables the elision of large elements attributes by printing a lexically valid but otherwise meaningl...
OpPrintingFlags & printNameLocAsPrefix(bool enable=true)
Print SSA IDs using their NameLoc, if provided, as prefix.
OpPrintingFlags & printValueUsers(bool enable=true)
Print users of values as comments.
OpPrintingFlags & enableDebugInfo(bool enable=true, bool prettyForm=false)
Enable or disable printing of debug information (based on enable).
OpPrintingFlags()
Initialize the printing flags with default supplied by the cl::opts above.
bool shouldSkipRegions() const
Return if regions should be skipped.
OpPrintingFlags & printGenericOpForm(bool enable=true)
Always print operations in the generic form.
OpPrintingFlags & useLocalScope(bool enable=true)
Use local scope when printing the operation.
std::optional< uint64_t > getLargeResourceStringLimit() const
Return the size limit in chars for printing large resources.
OpPrintingFlags & assumeVerified(bool enable=true)
Do not verify the operation when using custom operation printers.
OpPrintingFlags & skipRegions(bool skip=true)
Skip printing regions.
OpPrintingFlags & printUniqueSSAIDs(bool enable=true)
Print unique SSA ID numbers for values, block arguments and naming conflicts across all regions.
LLVM_DEPRECATED("Use OpPrintingFlags() instead", "OpPrintingFlags()") OpPrintingFlags(std
Simple wrapper around a void* in order to express generically how to pass in op properties through AP...
This class represents a contiguous range of operand ranges, e.g.
Definition ValueRange.h:84
This class implements the operand iterators for the Operation class.
Definition ValueRange.h:43
OperationFingerPrint & operator=(const OperationFingerPrint &)=default
OperationFingerPrint(Operation *topOp, bool includeNested=true)
bool operator!=(const OperationFingerPrint &other) const
bool operator==(const OperationFingerPrint &other) const
OperationFingerPrint(const OperationFingerPrint &)=default
Impl(StringAttr name, Dialect *dialect, TypeID typeID, detail::InterfaceMap interfaceMap)
ArrayRef< StringAttr > attributeNames
A list of attribute names registered to this operation in StringAttr form.
StringAttr name
The name of the operation.
TypeID typeID
The unique identifier of the derived Op class.
ArrayRef< StringAttr > getAttributeNames() const
Impl(StringRef, Dialect *dialect, TypeID typeID, detail::InterfaceMap interfaceMap)
Dialect * dialect
The following fields are only populated when the operation is registered.
detail::InterfaceMap interfaceMap
A map of interfaces that were registered to this operation.
bool isRegistered() const
Returns true if this is a registered operation.
detail::InterfaceMap & getInterfaceMap()
void populateInherentAttrs(Operation *op, NamedAttrList &attrs) const
bool operator==(const OperationName &rhs) const
void dump() const
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
ArrayRef< StringAttr > getAttributeNames() const
Return the list of cached attribute names registered to this operation.
bool operator!=(const OperationName &rhs) const
StringRef stripDialect() const
Return the operation name with dialect name stripped, if it has one.
void setInherentAttr(Operation *op, StringAttr name, Attribute value) const
Attribute getOpPropertiesAsAttribute(Operation *op) const
Return the op properties converted to an Attribute.
bool hasTrait() const
Returns true if the operation was registered with a particular trait, e.g.
bool hasPromiseOrImplementsInterface() const
Returns true if InterfaceT has been promised by the dialect or implemented.
llvm::unique_function< bool(TypeID) const > HasTraitFn
StringAttr getIdentifier() const
Return the name of this operation as a StringAttr.
void getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) const
This hook returns any canonicalization pattern rewrites that the operation supports,...
ParseAssemblyFn getParseAssemblyFn() const
Return the static hook for parsing this operation assembly.
std::optional< Attribute > getInherentAttr(Operation *op, StringRef name) const
Lookup an inherent attribute by name, this method isn't recommended and may be removed in the future.
Dialect * getDialect() const
Return the dialect this operation is registered to if the dialect is loaded in the context,...
OperationName(StringRef name, MLIRContext *context)
StringRef getDialectNamespace() const
Return the name of the dialect this operation is registered to.
void setImpl(Impl *rhs)
std::optional< RegisteredOperationName > getRegisteredInfo() const
If this operation is registered, returns the registered information, std::nullopt otherwise.
bool mightHaveTrait() const
Returns true if the operation might have the provided trait.
llvm::unique_function< LogicalResult(Operation *) const > VerifyInvariantsFn
bool mightHaveTrait(TypeID traitID) const
bool hasInterface() const
Returns true if this operation has the given interface registered to it.
LogicalResult verifyInherentAttrs(NamedAttrList &attributes, function_ref< InFlightDiagnostic()> emitError) const
This method exists for backward compatibility purpose when using properties to store inherent attribu...
void * getAsOpaquePointer() const
Represent the operation name as an opaque pointer.
llvm::unique_function< void(const OperationName &, NamedAttrList &) const > PopulateDefaultAttrsFn
void initOpProperties(OpaqueProperties storage, OpaqueProperties init) const
Initialize the op properties.
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &)> ParseAssemblyFn
llvm::hash_code hashOpProperties(OpaqueProperties properties) const
bool isRegistered() const
Return if this operation is registered.
bool mightHaveInterface() const
Returns true if the operation might have the provided interface.
T::Concept * getInterface() const
Returns an instance of the concept object for the given interface if it was registered to this operat...
llvm::unique_function< LogicalResult(Operation *) const > VerifyRegionInvariantsFn
LogicalResult foldHook(Operation *op, ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results) const
This hook implements a generalized folder for this operation.
bool mightHaveInterface(TypeID interfaceID) const
bool hasTrait(TypeID traitID) const
LogicalResult verifyRegionInvariants(Operation *op) const
TypeID getTypeID() const
Return the unique identifier of the derived Op class, or null if not registered.
void populateDefaultAttrs(NamedAttrList &attrs) const
This hook implements the method to populate defaults attributes that are unset.
MLIRContext * getContext()
Return the context this operation is associated with.
LogicalResult setOpPropertiesFromAttribute(OperationName opName, OpaqueProperties properties, Attribute attr, function_ref< InFlightDiagnostic()> emitError) const
Define the op properties from the provided Attribute.
llvm::unique_function< LogicalResult( Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) const > FoldHookFn
LogicalResult verifyInvariants(Operation *op) const
These hooks implement the verifiers for this operation.
void destroyOpProperties(OpaqueProperties properties) const
This hooks destroy the op properties.
bool compareOpProperties(OpaqueProperties lhs, OpaqueProperties rhs) const
int getOpPropertyByteSize() const
This hooks return the number of bytes to allocate for the op properties.
void populateDefaultProperties(OpaqueProperties properties) const
Set the default values on the ODS attribute in the properties.
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
void print(raw_ostream &os) const
void copyOpProperties(OpaqueProperties lhs, OpaqueProperties rhs) const
bool hasInterface(TypeID interfaceID) const
static OperationName getFromOpaquePointer(const void *pointer)
llvm::unique_function< void(Operation *, OpAsmPrinter &, StringRef) const > PrintAssemblyFn
void attachInterface()
Attach the given models as implementations of the corresponding interfaces for the concrete operation...
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
This class contains all of the data related to a pattern, but does not contain any methods or logic f...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
This is a "type erased" representation of a registered operation.
static void insert(Dialect &dialect)
Register a new operation in a Dialect object.
static RegisteredOperationName getFromOpaquePointer(const void *pointer)
Represent the operation name as an opaque pointer.
static std::optional< RegisteredOperationName > lookup(StringRef name, MLIRContext *ctx)
Lookup the registered operation information for the given operation.
static void insert(std::unique_ptr< OperationName::Impl > ownedImpl, ArrayRef< StringRef > attrNames)
The use of this method is in general discouraged in favor of 'insert<CustomOp>(dialect)'.
Dialect & getDialect() const
Return the dialect this operation is registered to.
This class implements the result iterators for the Operation class.
Definition ValueRange.h:247
RewritePattern is the common base class for all DAG to DAG replacements.
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
static TypeID get()
Construct a type info object for the given type T.
Definition TypeID.h:245
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:37
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:387
This class implements iteration on the types of a given range of values.
Definition TypeRange.h:135
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
This class provides an efficient mapping between a given Interface type, and a particular implementat...
void insertModels()
Insert the given interface models.
T::Concept * lookup() const
Returns an instance of the concept object for the given interface if it was registered to this map,...
bool contains(TypeID interfaceID) const
Returns true if the interface map contains an interface for the given id.
void eraseOperands(unsigned start, unsigned length)
Erase the operands held by the storage within the given range.
MutableArrayRef< OpOperand > getOperands()
Get the operation operands held by the storage.
unsigned size()
Return the number of operands held in the storage.
void setOperands(Operation *owner, ValueRange values)
Replace the operands contained in the storage with the ones provided in 'values'.
OperandStorage(Operation *owner, OpOperand *trailingOperands, ValueRange values)
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:229
bool hasPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID)
Checks if a promise has been made for the interface/requestor pair.
Definition Dialect.cpp:163
void handleAdditionOfUndefinedPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID)
Checks if the given interface, which is attempting to be attached, is a promised interface of this di...
Definition Dialect.cpp:157
std::optional< NamedAttribute > getNamedAttrFromSortedRange(IteratorT first, IteratorT last, NameT name)
Get an attribute from a sorted range of named attributes.
std::pair< IteratorT, bool > findAttrSorted(IteratorT first, IteratorT last, StringRef name)
Using llvm::lower_bound requires an extra string comparison to check whether the returned iterator po...
std::pair< IteratorT, bool > findAttrUnsorted(IteratorT first, IteratorT last, NameT name)
Unsorted string search or identifier lookups are linear scans.
Attribute getAttrFromSortedRange(IteratorT first, IteratorT last, NameT name)
Get an attribute from a sorted range of named attributes.
Include the generated interface declarations.
llvm::DenseMapInfo< T, Enable > DenseMapInfo
Definition LLVM.h:122
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
inline ::llvm::hash_code hash_value(AffineExpr arg)
Make AffineExpr hashable.
Definition AffineExpr.h:247
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
Enable Bitmask enums for OperationEquivalence::Flags.
static mlir::OperationName getTombstoneKey()
static bool isEqual(mlir::OperationName lhs, mlir::OperationName rhs)
static unsigned getHashValue(mlir::OperationName val)
static mlir::RegisteredOperationName getEmptyKey()
static mlir::RegisteredOperationName getTombstoneKey()
static mlir::OperationName getFromVoidPointer(void *P)
static void * getAsVoidPointer(mlir::OperationName I)
static mlir::RegisteredOperationName getFromVoidPointer(void *P)
Structure used by default as a "marker" when no "Properties" are set on an Operation.
This class provides utilities for computing if two operations are equivalent.
static llvm::hash_code ignoreHashValue(Value)
Helper that can be used with computeHash above to ignore operation operands/result mapping.
static bool isRegionEquivalentTo(Region *lhs, Region *rhs, function_ref< LogicalResult(Value, Value)> checkEquivalent, function_ref< void(Value, Value)> markEquivalent, OperationEquivalence::Flags flags, function_ref< LogicalResult(ValueRange, ValueRange)> checkCommutativeEquivalent=nullptr)
Compare two regions (including their subregions) and return if they are equivalent.
static bool isEquivalentTo(Operation *lhs, Operation *rhs, function_ref< LogicalResult(Value, Value)> checkEquivalent, function_ref< void(Value, Value)> markEquivalent=nullptr, Flags flags=Flags::None, function_ref< LogicalResult(ValueRange, ValueRange)> checkCommutativeEquivalent=nullptr)
Compare two operations (including their regions) and return if they are equivalent.
static llvm::hash_code directHashValue(Value v)
Helper that can be used with computeHash above to ignore operation operands/result mapping.
static LogicalResult ignoreValueEquivalence(Value lhs, Value rhs)
Helper that can be used with isEquivalentTo above to consider ops equivalent even if their operands a...
static LogicalResult exactValueMatch(Value lhs, Value rhs)
Helper that can be used with isEquivalentTo above to consider ops equivalent only if their operands a...
static llvm::hash_code computeHash(Operation *op, function_ref< llvm::hash_code(Value)> hashOperands=[](Value v) { return hash_value(v);}, function_ref< llvm::hash_code(Value)> hashResults=[](Value v) { return hash_value(v);}, Flags flags=Flags::None)
Compute a hash for the given operation.
This class represents a type erased version of an operation.
virtual void initProperties(OperationName opName, OpaqueProperties storage, OpaqueProperties init)=0
virtual void populateInherentAttrs(Operation *op, NamedAttrList &attrs)=0
virtual void deleteProperties(OpaqueProperties)=0
virtual void getCanonicalizationPatterns(RewritePatternSet &, MLIRContext *)=0
virtual OperationName::ParseAssemblyFn getParseAssemblyFn()=0
virtual void printAssembly(Operation *, OpAsmPrinter &, StringRef)=0
virtual LogicalResult verifyInvariants(Operation *)=0
virtual void setInherentAttr(Operation *op, StringAttr name, Attribute value)=0
virtual LogicalResult setPropertiesFromAttr(OperationName, OpaqueProperties, Attribute, function_ref< InFlightDiagnostic()> emitError)=0
virtual void populateDefaultProperties(OperationName opName, OpaqueProperties properties)=0
virtual Attribute getPropertiesAsAttr(Operation *)=0
virtual LogicalResult foldHook(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &)=0
virtual bool compareProperties(OpaqueProperties, OpaqueProperties)=0
virtual void copyProperties(OpaqueProperties, OpaqueProperties)=0
virtual void populateDefaultAttrs(const OperationName &, NamedAttrList &)=0
virtual std::optional< Attribute > getInherentAttr(Operation *, StringRef name)=0
Implementation for properties.
virtual LogicalResult verifyInherentAttrs(OperationName opName, NamedAttrList &attributes, function_ref< InFlightDiagnostic()> emitError)=0
virtual llvm::hash_code hashProperties(OpaqueProperties)=0
virtual LogicalResult verifyRegionInvariants(Operation *)=0
Default implementation for unregistered operations.
LogicalResult foldHook(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) final
llvm::hash_code hashProperties(OpaqueProperties) final
void populateInherentAttrs(Operation *op, NamedAttrList &attrs) final
void deleteProperties(OpaqueProperties) final
LogicalResult setPropertiesFromAttr(OperationName, OpaqueProperties, Attribute, function_ref< InFlightDiagnostic()> emitError) final
void setInherentAttr(Operation *op, StringAttr name, Attribute value) final
void populateDefaultProperties(OperationName opName, OpaqueProperties properties) final
OperationName::ParseAssemblyFn getParseAssemblyFn() final
LogicalResult verifyRegionInvariants(Operation *) final
std::optional< Attribute > getInherentAttr(Operation *op, StringRef name) final
Implementation for properties.
void getCanonicalizationPatterns(RewritePatternSet &, MLIRContext *) final
Impl(StringRef, Dialect *dialect, TypeID typeID, detail::InterfaceMap interfaceMap)
void initProperties(OperationName opName, OpaqueProperties storage, OpaqueProperties init) final
void populateDefaultAttrs(const OperationName &, NamedAttrList &) final
void printAssembly(Operation *, OpAsmPrinter &, StringRef) final
LogicalResult verifyInvariants(Operation *) final
void copyProperties(OpaqueProperties, OpaqueProperties) final
LogicalResult verifyInherentAttrs(OperationName opName, NamedAttrList &attributes, function_ref< InFlightDiagnostic()> emitError) final
Attribute getPropertiesAsAttr(Operation *) final
bool compareProperties(OpaqueProperties, OpaqueProperties) final
This represents an operation in an abstracted form, suitable for use with the builder APIs.
OpaqueProperties getRawProperties()
OperationState & operator=(const OperationState &other)=delete
SmallVector< Block *, 1 > successors
Successors of this operation and their respective operands.
T & getOrAddProperties()
Get (or create) a properties of the provided type to be set on the operation on creation.
OperationState & operator=(OperationState &&other)=default
SmallVector< Value, 4 > operands
std::enable_if_t<!std::is_convertible< RangeT, ArrayRef< Type > >::value > addTypes(RangeT &&newTypes)
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addAttribute(StringAttr name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
void addRegions(MutableArrayRef< std::unique_ptr< Region > > regions)
Take ownership of a set of regions that should be attached to the Operation.
MLIRContext * getContext() const
Get the context held by this operation state.
OperationState(OperationState &&other)=default
OperationState(const OperationState &other)=delete
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
OperationState(Location location, StringRef name)
void useProperties(T &newProperties)
Attribute propertiesAttr
This Attribute is used to opaquely construct the properties of the operation.
SmallVector< Type, 4 > types
Types of the results of this operation.
Region * addRegion()
Create a region that should be attached to the operation.
LogicalResult setProperties(Operation *op, function_ref< InFlightDiagnostic()> emitError) const
Implementation of the InterfaceConcept for operation APIs that forwarded to a concrete op implementat...
std::optional< Attribute > getInherentAttr(Operation *op, StringRef name) final
Implementation for properties.
void initProperties(OperationName opName, OpaqueProperties storage, OpaqueProperties init) final
std::remove_reference_t< decltype(std::declval< ConcreteOp >().getProperties())> Properties
Implementation for "Properties".
LogicalResult setPropertiesFromAttr(OperationName opName, OpaqueProperties properties, Attribute attr, function_ref< InFlightDiagnostic()> emitError) final
void copyProperties(OpaqueProperties lhs, OpaqueProperties rhs) final
void populateDefaultAttrs(const OperationName &name, NamedAttrList &attrs) final
OperationName::ParseAssemblyFn getParseAssemblyFn() final
LogicalResult verifyInvariants(Operation *op) final
void getCanonicalizationPatterns(RewritePatternSet &set, MLIRContext *context) final
LogicalResult verifyRegionInvariants(Operation *op) final
void printAssembly(Operation *op, OpAsmPrinter &printer, StringRef name) final
void populateInherentAttrs(Operation *op, NamedAttrList &attrs) final
llvm::hash_code hashProperties(OpaqueProperties prop) final
LogicalResult foldHook(Operation *op, ArrayRef< Attribute > attrs, SmallVectorImpl< OpFoldResult > &results) final
bool compareProperties(OpaqueProperties lhs, OpaqueProperties rhs) final
Attribute getPropertiesAsAttr(Operation *op) final
LogicalResult verifyInherentAttrs(OperationName opName, NamedAttrList &attributes, function_ref< InFlightDiagnostic()> emitError) final
void populateDefaultProperties(OperationName opName, OpaqueProperties properties) final
void deleteProperties(OpaqueProperties prop) final
void setInherentAttr(Operation *op, StringAttr name, Attribute value) final