MLIR 23.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 return std::nullopt;
574 }
575 void setInherentAttr(Operation *op, StringAttr name,
576 Attribute value) final {
577 if constexpr (hasProperties) {
578 auto concreteOp = cast<ConcreteOp>(op);
579 return ConcreteOp::setInherentAttr(concreteOp.getProperties(), name,
580 value);
581 }
582 llvm_unreachable(
583 "Can't call setInherentAttr on operation with empty properties");
584 }
586 if constexpr (hasProperties) {
587 auto concreteOp = cast<ConcreteOp>(op);
588 ConcreteOp::populateInherentAttrs(concreteOp->getContext(),
589 concreteOp.getProperties(), attrs);
590 }
591 }
592 LogicalResult
593 verifyInherentAttrs(OperationName opName, NamedAttrList &attributes,
595 if constexpr (hasProperties)
596 return ConcreteOp::verifyInherentAttrs(opName, attributes, emitError);
597 return success();
598 }
599 // Detect if the concrete operation defined properties.
600 static constexpr bool hasProperties = !std::is_same_v<
601 typename ConcreteOp::template InferredProperties<ConcreteOp>,
603
605 if constexpr (hasProperties)
606 return sizeof(Properties);
607 return 0;
608 }
609 void initProperties(OperationName opName, OpaqueProperties storage,
610 OpaqueProperties init) final {
611 using Properties =
612 typename ConcreteOp::template InferredProperties<ConcreteOp>;
613 if (init)
614 new (storage.as<Properties *>()) Properties(*init.as<Properties *>());
615 else
616 new (storage.as<Properties *>()) Properties();
617 if constexpr (hasProperties)
618 ConcreteOp::populateDefaultProperties(opName,
619 *storage.as<Properties *>());
620 }
622 prop.as<Properties *>()->~Properties();
623 }
624 void populateDefaultProperties(OperationName opName,
625 OpaqueProperties properties) final {
626 if constexpr (hasProperties)
627 ConcreteOp::populateDefaultProperties(opName,
628 *properties.as<Properties *>());
629 }
630
631 LogicalResult
632 setPropertiesFromAttr(OperationName opName, OpaqueProperties properties,
633 Attribute attr,
635 if constexpr (hasProperties) {
636 auto p = properties.as<Properties *>();
637 return ConcreteOp::setPropertiesFromAttr(*p, attr, emitError);
638 }
639 emitError() << "this operation has empty properties";
640 return failure();
641 }
643 if constexpr (hasProperties) {
644 auto concreteOp = cast<ConcreteOp>(op);
645 return ConcreteOp::getPropertiesAsAttr(concreteOp->getContext(),
646 concreteOp.getProperties());
647 }
648 return {};
649 }
651 if constexpr (hasProperties)
652 return *lhs.as<Properties *>() == *rhs.as<Properties *>();
653 return true;
654 }
656 *lhs.as<Properties *>() = *rhs.as<Properties *>();
657 }
658 llvm::hash_code hashProperties(OpaqueProperties prop) final {
659 if constexpr (hasProperties)
660 return ConcreteOp::computePropertiesHash(*prop.as<Properties *>());
661
662 return {};
663 }
664 };
665
666 /// Lookup the registered operation information for the given operation.
667 /// Returns std::nullopt if the operation isn't registered.
668 static std::optional<RegisteredOperationName> lookup(StringRef name,
669 MLIRContext *ctx);
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(TypeID typeID,
674 MLIRContext *ctx);
675
676 /// Register a new operation in a Dialect object.
677 /// This constructor is used by Dialect objects when they register the list
678 /// of operations they contain.
679 template <typename T>
680 static void insert(Dialect &dialect) {
681 insert(std::make_unique<Model<T>>(&dialect), T::getAttributeNames());
682 }
683 /// The use of this method is in general discouraged in favor of
684 /// 'insert<CustomOp>(dialect)'.
685 static void insert(std::unique_ptr<OperationName::Impl> ownedImpl,
686 ArrayRef<StringRef> attrNames);
687
688 /// Return the dialect this operation is registered to.
689 Dialect &getDialect() const { return *getImpl()->getDialect(); }
690
691 /// Represent the operation name as an opaque pointer. (Used to support
692 /// PointerLikeTypeTraits).
693 static RegisteredOperationName getFromOpaquePointer(const void *pointer) {
694 return RegisteredOperationName(
695 const_cast<Impl *>(reinterpret_cast<const Impl *>(pointer)));
696 }
697
698private:
700
701 /// Allow access to the constructor.
702 friend OperationName;
703};
704
705inline std::optional<RegisteredOperationName>
708 : std::optional<RegisteredOperationName>();
709}
710
711//===----------------------------------------------------------------------===//
712// Attribute Dictionary-Like Interface
713//===----------------------------------------------------------------------===//
714
715/// Attribute collections provide a dictionary-like interface. Define common
716/// lookup functions.
717namespace impl {
718
719/// Unsorted string search or identifier lookups are linear scans.
720template <typename IteratorT, typename NameT>
721std::pair<IteratorT, bool> findAttrUnsorted(IteratorT first, IteratorT last,
722 NameT name) {
723 for (auto it = first; it != last; ++it)
724 if (it->getName() == name)
725 return {it, true};
726 return {last, false};
727}
728
729/// Using llvm::lower_bound requires an extra string comparison to check whether
730/// the returned iterator points to the found element or whether it indicates
731/// the lower bound. Skip this redundant comparison by checking if `compare ==
732/// 0` during the binary search.
733template <typename IteratorT>
734std::pair<IteratorT, bool> findAttrSorted(IteratorT first, IteratorT last,
735 StringRef name) {
736 ptrdiff_t length = std::distance(first, last);
737
738 while (length > 0) {
739 ptrdiff_t half = length / 2;
740 IteratorT mid = first + half;
741 int compare = mid->getName().strref().compare(name);
742 if (compare < 0) {
743 first = mid + 1;
744 length = length - half - 1;
745 } else if (compare > 0) {
746 length = half;
747 } else {
748 return {mid, true};
749 }
750 }
751 return {first, false};
752}
753
754/// StringAttr lookups on large attribute lists will switch to string binary
755/// search. String binary searches become significantly faster than linear scans
756/// with the identifier when the attribute list becomes very large.
757template <typename IteratorT>
758std::pair<IteratorT, bool> findAttrSorted(IteratorT first, IteratorT last,
759 StringAttr name) {
760 constexpr unsigned kSmallAttributeList = 16;
761 if (std::distance(first, last) > kSmallAttributeList)
762 return findAttrSorted(first, last, name.strref());
763 return findAttrUnsorted(first, last, name);
764}
765
766/// Get an attribute from a sorted range of named attributes. Returns null if
767/// the attribute was not found.
768template <typename IteratorT, typename NameT>
769Attribute getAttrFromSortedRange(IteratorT first, IteratorT last, NameT name) {
770 std::pair<IteratorT, bool> result = findAttrSorted(first, last, name);
771 return result.second ? result.first->getValue() : Attribute();
772}
773
774/// Get an attribute from a sorted range of named attributes. Returns
775/// std::nullopt if the attribute was not found.
776template <typename IteratorT, typename NameT>
777std::optional<NamedAttribute>
778getNamedAttrFromSortedRange(IteratorT first, IteratorT last, NameT name) {
779 std::pair<IteratorT, bool> result = findAttrSorted(first, last, name);
780 return result.second ? *result.first : std::optional<NamedAttribute>();
781}
782
783} // namespace impl
784
785//===----------------------------------------------------------------------===//
786// NamedAttrList
787//===----------------------------------------------------------------------===//
788
789/// NamedAttrList is array of NamedAttributes that tracks whether it is sorted
790/// and does some basic work to remain sorted.
792public:
797 using size_type = size_t;
798
799 NamedAttrList() : dictionarySorted({}, true) {}
800 NamedAttrList(ArrayRef<NamedAttribute> attributes);
801 NamedAttrList(DictionaryAttr attributes);
803
804 template <typename Container>
805 NamedAttrList(const Container &vec)
807
808 bool operator!=(const NamedAttrList &other) const {
809 return !(*this == other);
810 }
811 bool operator==(const NamedAttrList &other) const {
812 return attrs == other.attrs;
813 }
814
815 /// Add an attribute with the specified name.
816 void append(StringRef name, Attribute attr) {
817 append(NamedAttribute(name, attr));
818 }
819
820 /// Add an attribute with the specified name.
821 void append(StringAttr name, Attribute attr) {
822 append(NamedAttribute(name, attr));
823 }
824
825 /// Append the given named attribute.
826 void append(NamedAttribute attr) { push_back(attr); }
827
828 /// Add an array of named attributes.
829 template <typename RangeT>
830 void append(RangeT &&newAttributes) {
831 append(std::begin(newAttributes), std::end(newAttributes));
832 }
833
834 /// Add a range of named attributes.
835 template <typename IteratorT,
836 typename = std::enable_if_t<std::is_convertible<
837 typename std::iterator_traits<IteratorT>::iterator_category,
838 std::input_iterator_tag>::value>>
839 void append(IteratorT inStart, IteratorT inEnd) {
840 // TODO: expand to handle case where values appended are in order & after
841 // end of current list.
842 dictionarySorted.setPointerAndInt(nullptr, false);
843 attrs.append(inStart, inEnd);
844 }
845
846 /// Replaces the attributes with new list of attributes.
847 void assign(const_iterator inStart, const_iterator inEnd);
848
849 /// Replaces the attributes with new list of attributes.
851 assign(range.begin(), range.end());
852 }
853
854 void clear() {
855 attrs.clear();
856 dictionarySorted.setPointerAndInt(nullptr, false);
857 }
858
859 bool empty() const { return attrs.empty(); }
860
861 void reserve(size_type N) { attrs.reserve(N); }
862
863 /// Add an attribute with the specified name.
864 void push_back(NamedAttribute newAttribute);
865
866 /// Pop last element from list.
867 void pop_back() { attrs.pop_back(); }
868
869 /// Returns an entry with a duplicate name the list, if it exists, else
870 /// returns std::nullopt.
871 std::optional<NamedAttribute> findDuplicate() const;
872
873 /// Return a dictionary attribute for the underlying dictionary. This will
874 /// return an empty dictionary attribute if empty rather than null.
875 DictionaryAttr getDictionary(MLIRContext *context) const;
876
877 /// Return all of the attributes on this operation.
879
880 /// Return the specified attribute if present, null otherwise.
881 Attribute get(StringAttr name) const;
882 Attribute get(StringRef name) const;
883
884 /// Return the specified named attribute if present, std::nullopt otherwise.
885 std::optional<NamedAttribute> getNamed(StringRef name) const;
886 std::optional<NamedAttribute> getNamed(StringAttr name) const;
887
888 /// If the an attribute exists with the specified name, change it to the new
889 /// value. Otherwise, add a new attribute with the specified name/value.
890 /// Returns the previous attribute value of `name`, or null if no
891 /// attribute previously existed with `name`.
892 Attribute set(StringAttr name, Attribute value);
893 Attribute set(StringRef name, Attribute value);
894
895 /// Erase the attribute with the given name from the list. Return the
896 /// attribute that was erased, or nullptr if there was no attribute with such
897 /// name.
898 Attribute erase(StringAttr name);
899 Attribute erase(StringRef name);
900
901 iterator begin() { return attrs.begin(); }
902 iterator end() { return attrs.end(); }
903 const_iterator begin() const { return attrs.begin(); }
904 const_iterator end() const { return attrs.end(); }
905
907 operator ArrayRef<NamedAttribute>() const;
908
909private:
910 /// Return whether the attributes are sorted.
911 bool isSorted() const { return dictionarySorted.getInt(); }
912
913 /// Erase the attribute at the given iterator position.
914 Attribute eraseImpl(SmallVectorImpl<NamedAttribute>::iterator it);
915
916 /// Lookup an attribute in the list.
917 template <typename AttrListT, typename NameT>
918 static auto findAttr(AttrListT &attrs, NameT name) {
919 return attrs.isSorted()
920 ? impl::findAttrSorted(attrs.begin(), attrs.end(), name)
921 : impl::findAttrUnsorted(attrs.begin(), attrs.end(), name);
922 }
923
924 // These are marked mutable as they may be modified (e.g., sorted)
925 mutable SmallVector<NamedAttribute, 4> attrs;
926 // Pair with cached DictionaryAttr and status of whether attrs is sorted.
927 // Note: just because sorted does not mean a DictionaryAttr has been created
928 // but the case where there is a DictionaryAttr but attrs isn't sorted should
929 // not occur.
930 mutable llvm::PointerIntPair<Attribute, 1, bool> dictionarySorted;
931};
932
933//===----------------------------------------------------------------------===//
934// OperationState
935//===----------------------------------------------------------------------===//
936
937/// This represents an operation in an abstracted form, suitable for use with
938/// the builder APIs. This object is a large and heavy weight object meant to
939/// be used as a temporary object on the stack. It is generally unwise to put
940/// this in a collection.
945 /// Types of the results of this operation.
948 /// Successors of this operation and their respective operands.
950 /// Regions that the op will hold.
952
953 /// This Attribute is used to opaquely construct the properties of the
954 /// operation. If we're creating an unregistered operation, the Attribute is
955 /// used as-is as the Properties storage of the operation. Otherwise, the
956 /// operation properties are constructed opaquely using its
957 /// `setPropertiesFromAttr` hook. Note that `getOrAddProperties` is the
958 /// preferred method to construct properties from C++.
960
961private:
962 OpaqueProperties properties = nullptr;
963 TypeID propertiesId;
964 llvm::function_ref<void(OpaqueProperties)> propertiesDeleter;
966 propertiesSetter;
967 friend class Operation;
968
969public:
972
976 MutableArrayRef<std::unique_ptr<Region>> regions = {});
977 OperationState(Location location, StringRef name, ValueRange operands,
978 TypeRange types, ArrayRef<NamedAttribute> attributes = {},
979 BlockRange successors = {},
980 MutableArrayRef<std::unique_ptr<Region>> regions = {});
981 OperationState(OperationState &&other) = default;
983 OperationState(const OperationState &other) = delete;
984 OperationState &operator=(const OperationState &other) = delete;
986
987 /// Get (or create) a properties of the provided type to be set on the
988 /// operation on creation.
989 template <typename T>
991 if (!properties) {
992 T *p = new T{};
993 properties = p;
994#if defined(__clang__)
995#if __has_warning("-Wdangling-assignment-gsl")
996#pragma clang diagnostic push
997// https://github.com/llvm/llvm-project/issues/126600
998#pragma clang diagnostic ignored "-Wdangling-assignment-gsl"
999#endif
1000#endif
1001 propertiesDeleter = [](OpaqueProperties prop) {
1002 delete prop.as<const T *>();
1003 };
1004 propertiesSetter = [](OpaqueProperties newProp,
1005 const OpaqueProperties prop) {
1006 *newProp.as<T *>() = *prop.as<const T *>();
1007 };
1008#if defined(__clang__)
1009#if __has_warning("-Wdangling-assignment-gsl")
1010#pragma clang diagnostic pop
1011#endif
1012#endif
1013 propertiesId = TypeID::get<T>();
1014 }
1015 assert(propertiesId == TypeID::get<T>() && "Inconsistent properties");
1016 return *properties.as<T *>();
1017 }
1018 OpaqueProperties getRawProperties() { return properties; }
1019
1020 // Set the properties defined on this OpState on the given operation,
1021 // optionally emit diagnostics on error through the provided diagnostic.
1022 LogicalResult
1025
1026 // Make `newProperties` the source of the properties that will be copied into
1027 // the operation. The memory referenced by `newProperties` must remain live
1028 // until after the `Operation` is created, at which time it may be
1029 // deallocated. Calls to `getOrAddProperties<>() will return references to
1030 // this memory.
1031 template <typename T>
1032 void useProperties(T &newProperties) {
1033 assert(!properties &&
1034 "Can't provide a properties struct when one has been allocated");
1035 properties = &newProperties;
1036#if defined(__clang__)
1037#if __has_warning("-Wdangling-assignment-gsl")
1038#pragma clang diagnostic push
1039// https://github.com/llvm/llvm-project/issues/126600
1040#pragma clang diagnostic ignored "-Wdangling-assignment-gsl"
1041#endif
1042#endif
1043 propertiesDeleter = [](OpaqueProperties) {};
1044 propertiesSetter = [](OpaqueProperties newProp,
1045 const OpaqueProperties prop) {
1046 *newProp.as<T *>() = *prop.as<const T *>();
1047 };
1048#if defined(__clang__)
1049#if __has_warning("-Wdangling-assignment-gsl")
1050#pragma clang diagnostic pop
1051#endif
1052#endif
1053 propertiesId = TypeID::get<T>();
1054 }
1055
1056 void addOperands(ValueRange newOperands);
1057
1058 void addTypes(ArrayRef<Type> newTypes) {
1059 types.append(newTypes.begin(), newTypes.end());
1060 }
1061 template <typename RangeT>
1062 std::enable_if_t<!std::is_convertible<RangeT, ArrayRef<Type>>::value>
1063 addTypes(RangeT &&newTypes) {
1064 types.append(newTypes.begin(), newTypes.end());
1065 }
1066
1067 /// Add an attribute with the specified name.
1068 void addAttribute(StringRef name, Attribute attr) {
1069 addAttribute(StringAttr::get(getContext(), name), attr);
1070 }
1071
1072 /// Add an attribute with the specified name. `name` and `attr` must not be
1073 /// null.
1074 void addAttribute(StringAttr name, Attribute attr) {
1075 assert(name && "attribute name cannot be null");
1076 assert(attr && "attribute cannot be null");
1077 attributes.append(name, attr);
1078 }
1079
1080 /// Add an array of named attributes.
1082 attributes.append(newAttributes);
1083 }
1084
1085 /// Adds a successor to the operation sate. `successor` must not be null.
1086 void addSuccessors(Block *successor) {
1087 assert(successor && "successor cannot be null");
1088 successors.push_back(successor);
1089 }
1090 void addSuccessors(BlockRange newSuccessors);
1091
1092 /// Create a region that should be attached to the operation. These regions
1093 /// can be filled in immediately without waiting for Operation to be
1094 /// created. When it is, the region bodies will be transferred.
1095 Region *addRegion();
1096
1097 /// Take a region that should be attached to the Operation. The body of the
1098 /// region will be transferred when the Operation is constructed. If the
1099 /// region is null, a new empty region will be attached to the Operation.
1100 void addRegion(std::unique_ptr<Region> &&region);
1101
1102 /// Take ownership of a set of regions that should be attached to the
1103 /// Operation.
1104 void addRegions(MutableArrayRef<std::unique_ptr<Region>> regions);
1105
1106 /// Get the context held by this operation state.
1107 MLIRContext *getContext() const { return location->getContext(); }
1108};
1109
1110//===----------------------------------------------------------------------===//
1111// OperandStorage
1112//===----------------------------------------------------------------------===//
1113
1114namespace detail {
1115/// This class handles the management of operation operands. Operands are
1116/// stored either in a trailing array, or a dynamically resizable vector.
1117class alignas(8) OperandStorage {
1118public:
1119 OperandStorage(Operation *owner, OpOperand *trailingOperands,
1120 ValueRange values);
1122
1123 /// Replace the operands contained in the storage with the ones provided in
1124 /// 'values'.
1125 void setOperands(Operation *owner, ValueRange values);
1126
1127 /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
1128 /// with the ones provided in 'operands'. 'operands' may be smaller or larger
1129 /// than the range pointed to by 'start'+'length'.
1130 void setOperands(Operation *owner, unsigned start, unsigned length,
1131 ValueRange operands);
1132
1133 /// Erase the operands held by the storage within the given range.
1134 void eraseOperands(unsigned start, unsigned length);
1135
1136 /// Erase the operands held by the storage that have their corresponding bit
1137 /// set in `eraseIndices`.
1138 void eraseOperands(const BitVector &eraseIndices);
1139
1140 /// Get the operation operands held by the storage.
1141 MutableArrayRef<OpOperand> getOperands() { return {operandStorage, size()}; }
1142
1143 /// Return the number of operands held in the storage.
1144 unsigned size() { return numOperands; }
1145
1146private:
1147 /// Resize the storage to the given size. Returns the array containing the new
1148 /// operands.
1149 MutableArrayRef<OpOperand> resize(Operation *owner, unsigned newSize);
1150
1151 /// The total capacity number of operands that the storage can hold.
1152 unsigned capacity : 31;
1153 /// A flag indicating if the operand storage was dynamically allocated, as
1154 /// opposed to inlined into the owning operation.
1155 unsigned isStorageDynamic : 1;
1156 /// The number of operands within the storage.
1157 unsigned numOperands;
1158 /// A pointer to the operand storage.
1159 OpOperand *operandStorage;
1160};
1161} // namespace detail
1162
1163//===----------------------------------------------------------------------===//
1164// OpPrintingFlags
1165//===----------------------------------------------------------------------===//
1166
1167/// Set of flags used to control the behavior of the various IR print methods
1168/// (e.g. Operation::Print).
1170public:
1172
1173 /// Enables the elision of large elements attributes by printing a lexically
1174 /// valid but otherwise meaningless form instead of the element data. The
1175 /// `largeElementLimit` is used to configure what is considered to be a
1176 /// "large" ElementsAttr by providing an upper limit to the number of
1177 /// elements.
1178 OpPrintingFlags &elideLargeElementsAttrs(int64_t largeElementLimit = 16);
1179
1180 /// Enables the printing of large element attributes with a hex string. The
1181 /// `largeElementLimit` is used to configure what is considered to be a
1182 /// "large" ElementsAttr by providing an upper limit to the number of
1183 /// elements. Use -1 to disable the hex printing.
1185 printLargeElementsAttrWithHex(int64_t largeElementLimit = 100);
1186
1187 /// Enables the elision of large resources strings by omitting them from the
1188 /// `dialect_resources` section. The `largeResourceLimit` is used to configure
1189 /// what is considered to be a "large" resource by providing an upper limit to
1190 /// the string size.
1191 OpPrintingFlags &elideLargeResourceString(int64_t largeResourceLimit = 64);
1192
1193 /// Enable or disable printing of debug information (based on `enable`). If
1194 /// 'prettyForm' is set to true, debug information is printed in a more
1195 /// readable 'pretty' form. Note: The IR generated with 'prettyForm' is not
1196 /// parsable.
1197 OpPrintingFlags &enableDebugInfo(bool enable = true, bool prettyForm = false);
1198
1199 /// Always print operations in the generic form.
1200 OpPrintingFlags &printGenericOpForm(bool enable = true);
1201
1202 /// Skip printing regions.
1203 OpPrintingFlags &skipRegions(bool skip = true);
1204
1205 /// Do not verify the operation when using custom operation printers.
1206 OpPrintingFlags &assumeVerified(bool enable = true);
1207
1208 /// Use local scope when printing the operation. This allows for using the
1209 /// printer in a more localized and thread-safe setting, but may not
1210 /// necessarily be identical to what the IR will look like when dumping
1211 /// the full module.
1212 OpPrintingFlags &useLocalScope(bool enable = true);
1213
1214 /// Print users of values as comments.
1215 OpPrintingFlags &printValueUsers(bool enable = true);
1216
1217 /// Print unique SSA ID numbers for values, block arguments and naming
1218 /// conflicts across all regions
1219 OpPrintingFlags &printUniqueSSAIDs(bool enable = true);
1220
1221 /// Print SSA IDs using their NameLoc, if provided, as prefix.
1222 OpPrintingFlags &printNameLocAsPrefix(bool enable = true);
1223
1224 /// Return if the given ElementsAttr should be elided.
1225 bool shouldElideElementsAttr(ElementsAttr attr) const;
1226
1227 /// Return if the given ElementsAttr should be printed as hex string.
1228 bool shouldPrintElementsAttrWithHex(ElementsAttr attr) const;
1229
1230 /// Return the size limit for printing large ElementsAttr.
1231 std::optional<int64_t> getLargeElementsAttrLimit() const;
1232
1233 /// Return the size limit for printing large ElementsAttr as hex string.
1235
1236 /// Return the size limit in chars for printing large resources.
1237 std::optional<uint64_t> getLargeResourceStringLimit() const;
1238
1239 /// Return if debug information should be printed.
1240 bool shouldPrintDebugInfo() const;
1241
1242 /// Return if debug information should be printed in the pretty form.
1243 bool shouldPrintDebugInfoPrettyForm() const;
1244
1245 /// Return if operations should be printed in the generic form.
1246 bool shouldPrintGenericOpForm() const;
1247
1248 /// Return if regions should be skipped.
1249 bool shouldSkipRegions() const;
1250
1251 /// Return if operation verification should be skipped.
1252 bool shouldAssumeVerified() const;
1253
1254 /// Return if the printer should use local scope when dumping the IR.
1255 bool shouldUseLocalScope() const;
1256
1257 /// Return if the printer should print users of values.
1258 bool shouldPrintValueUsers() const;
1259
1260 /// Return if printer should use unique SSA IDs.
1261 bool shouldPrintUniqueSSAIDs() const;
1262
1263 /// Return if the printer should use NameLocs as prefixes when printing SSA
1264 /// IDs
1265 bool shouldUseNameLocAsPrefix() const;
1266
1267private:
1268 /// Elide large elements attributes if the number of elements is larger than
1269 /// the upper limit.
1270 std::optional<int64_t> elementsAttrElementLimit;
1271
1272 /// Elide printing large resources based on size of string.
1273 std::optional<uint64_t> resourceStringCharLimit;
1274
1275 /// Print large element attributes with hex strings if the number of elements
1276 /// is larger than the upper limit.
1277 int64_t elementsAttrHexElementLimit = 100;
1278
1279 /// Print debug information.
1280 bool printDebugInfoFlag : 1;
1281 bool printDebugInfoPrettyFormFlag : 1;
1282
1283 /// Print operations in the generic form.
1284 bool printGenericOpFormFlag : 1;
1285
1286 /// Always skip Regions.
1287 bool skipRegionsFlag : 1;
1288
1289 /// Skip operation verification.
1290 bool assumeVerifiedFlag : 1;
1291
1292 /// Print operations with numberings local to the current operation.
1293 bool printLocalScope : 1;
1294
1295 /// Print users of values.
1296 bool printValueUsersFlag : 1;
1297
1298 /// Print unique SSA IDs for values, block arguments and naming conflicts
1299 bool printUniqueSSAIDsFlag : 1;
1300
1301 /// Print SSA IDs using NameLocs as prefixes
1302 bool useNameLocAsPrefix : 1;
1303};
1304
1305//===----------------------------------------------------------------------===//
1306// Operation Equivalency
1307//===----------------------------------------------------------------------===//
1308
1309/// This class provides utilities for computing if two operations are
1310/// equivalent.
1312 enum Flags {
1313 None = 0,
1314
1315 // When provided, the location attached to the operation are ignored.
1317
1318 // When provided, the discardable attributes attached to the operation are
1319 // ignored.
1321
1322 // When provided, the properties attached to the operation are ignored.
1324
1325 // When provided, the commutativity of the operation is ignored, and
1326 // operands are compared in an order-sensitive way.
1328
1329 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IgnoreCommutativity)
1330 };
1331
1332 /// Compute a hash for the given operation.
1333 /// The `hashOperands` and `hashResults` callbacks are expected to return a
1334 /// unique hash_code for a given Value.
1335 static llvm::hash_code computeHash(
1336 Operation *op,
1337 function_ref<llvm::hash_code(Value)> hashOperands =
1338 [](Value v) { return hash_value(v); },
1339 function_ref<llvm::hash_code(Value)> hashResults =
1340 [](Value v) { return hash_value(v); },
1341 Flags flags = Flags::None);
1342
1343 /// Helper that can be used with `computeHash` above to ignore operation
1344 /// operands/result mapping.
1345 static llvm::hash_code ignoreHashValue(Value) { return llvm::hash_code{}; }
1346 /// Helper that can be used with `computeHash` to compute the hash value
1347 /// of operands/results directly.
1348 static llvm::hash_code directHashValue(Value v) { return hash_value(v); }
1349
1350 /// Compare two operations (including their regions) and return if they are
1351 /// equivalent.
1352 ///
1353 /// * `checkEquivalent` is a callback to check if two values are equivalent.
1354 /// For two operations to be equivalent, their operands must be the same SSA
1355 /// value or this callback must return `success`.
1356 /// * `markEquivalent` is a callback to inform the caller that the analysis
1357 /// determined that two values are equivalent.
1358 /// * `checkCommutativeEquivalent` is an optional callback to check for
1359 /// equivalence across two ranges for a commutative operation. If not passed
1360 /// in, then equivalence is checked pairwise. This callback is needed to be
1361 /// able to query the optional equivalence classes.
1362 ///
1363 /// Note: Additional information regarding value equivalence can be injected
1364 /// into the analysis via `checkEquivalent`. Typically, callers may want
1365 /// values that were determined to be equivalent as per `markEquivalent` to be
1366 /// reflected in `checkEquivalent`, unless `exactValueMatch` or a different
1367 /// equivalence relationship is desired.
1368 static bool
1370 function_ref<LogicalResult(Value, Value)> checkEquivalent,
1371 function_ref<void(Value, Value)> markEquivalent = nullptr,
1372 Flags flags = Flags::None,
1373 function_ref<LogicalResult(ValueRange, ValueRange)>
1374 checkCommutativeEquivalent = nullptr);
1375
1376 /// Compare two operations and return if they are equivalent.
1377 static bool isEquivalentTo(Operation *lhs, Operation *rhs, Flags flags);
1378
1379 /// Compare two regions (including their subregions) and return if they are
1380 /// equivalent. See also `isEquivalentTo` for details.
1381 static bool isRegionEquivalentTo(
1382 Region *lhs, Region *rhs,
1383 function_ref<LogicalResult(Value, Value)> checkEquivalent,
1384 function_ref<void(Value, Value)> markEquivalent,
1386 function_ref<LogicalResult(ValueRange, ValueRange)>
1387 checkCommutativeEquivalent = nullptr);
1388
1389 /// Compare two regions and return if they are equivalent.
1390 static bool isRegionEquivalentTo(Region *lhs, Region *rhs,
1392
1393 /// Helper that can be used with `isEquivalentTo` above to consider ops
1394 /// equivalent even if their operands are not equivalent.
1395 static LogicalResult ignoreValueEquivalence(Value lhs, Value rhs) {
1396 return success();
1397 }
1398 /// Helper that can be used with `isEquivalentTo` above to consider ops
1399 /// equivalent only if their operands are the exact same SSA values.
1400 static LogicalResult exactValueMatch(Value lhs, Value rhs) {
1401 return success(lhs == rhs);
1402 }
1403};
1404
1405/// Enable Bitmask enums for OperationEquivalence::Flags.
1407
1408//===----------------------------------------------------------------------===//
1409// OperationFingerPrint
1410//===----------------------------------------------------------------------===//
1411
1412/// A unique fingerprint for a specific operation, and all of it's internal
1413/// operations (if `includeNested` is set).
1415public:
1416 OperationFingerPrint(Operation *topOp, bool includeNested = true);
1419
1420 bool operator==(const OperationFingerPrint &other) const {
1421 return hash == other.hash;
1422 }
1423 bool operator!=(const OperationFingerPrint &other) const {
1424 return !(*this == other);
1425 }
1426
1427private:
1428 std::array<uint8_t, 20> hash;
1429};
1430
1431} // namespace mlir
1432
1433namespace llvm {
1434template <>
1451template <>
1452struct DenseMapInfo<mlir::RegisteredOperationName>
1453 : public DenseMapInfo<mlir::OperationName> {
1462};
1463
1464template <>
1465struct PointerLikeTypeTraits<mlir::OperationName> {
1466 static inline void *getAsVoidPointer(mlir::OperationName I) {
1467 return const_cast<void *>(I.getAsOpaquePointer());
1468 }
1472 static constexpr int NumLowBitsAvailable =
1473 PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
1474};
1475template <>
1476struct PointerLikeTypeTraits<mlir::RegisteredOperationName>
1477 : public PointerLikeTypeTraits<mlir::OperationName> {
1481};
1482
1483} // namespace llvm
1484
1485#endif
return success()
static size_t hash(const T &value)
Local helper to compute std::hash for a value.
Definition IRCore.cpp:55
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.
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
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.
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:114
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:144
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 to compute the hash value of operands/results directly.
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