14 #ifndef MLIR_IR_OPERATIONSUPPORT_H
15 #define MLIR_IR_OPERATIONSUPPORT_H
24 #include "llvm/ADT/BitmaskEnum.h"
25 #include "llvm/ADT/PointerUnion.h"
26 #include "llvm/ADT/STLFunctionalExtras.h"
27 #include "llvm/Support/PointerLikeTypeTraits.h"
28 #include "llvm/Support/TrailingObjects.h"
40 class MutableOperandRangeRange;
43 struct OperationState;
45 class OpAsmParserResult;
48 class OperandRangeRange;
55 class RewritePatternSet;
59 template <
typename ValueRangeT>
213 template <
template <
typename T>
class Trait>
215 return hasTrait(TypeID::get<Trait>());
222 template <
template <
typename T>
class Trait>
243 StringRef defaultDialect)
const {
280 template <
typename T>
287 template <
typename... Models>
293 template <
typename T>
304 template <
typename T>
334 void print(raw_ostream &os)
const;
342 const_cast<Impl *
>(
reinterpret_cast<const Impl *
>(pointer)));
355 Impl *
impl =
nullptr;
385 template <
typename ConcreteOp>
392 return ConcreteOp::getFoldHookFn()(op, attrs, results);
396 ConcreteOp::getCanonicalizationPatterns(set, context);
400 return ConcreteOp::parse;
404 ConcreteOp::populateDefaultAttrs(
name, attrs);
407 StringRef
name)
final {
408 ConcreteOp::getPrintAssemblyFn()(op, printer,
name);
411 return ConcreteOp::getVerifyInvariantsFn()(op);
414 return ConcreteOp::getVerifyRegionInvariantsFn()(op);
420 static std::optional<RegisteredOperationName>
lookup(StringRef name,
426 template <
typename T>
428 insert(std::make_unique<
Model<T>>(&dialect), T::getAttributeNames());
432 static void insert(std::unique_ptr<OperationName::Impl> ownedImpl,
445 const_cast<Impl *
>(
reinterpret_cast<const Impl *
>(pointer)));
452 friend OperationName;
455 inline std::optional<RegisteredOperationName>
458 : std::optional<RegisteredOperationName>();
470 template <
typename IteratorT,
typename NameT>
473 for (
auto it = first; it != last; ++it)
474 if (it->getName() == name)
476 return {last,
false};
483 template <
typename IteratorT>
486 ptrdiff_t length = std::distance(first, last);
489 ptrdiff_t half = length / 2;
490 IteratorT mid = first + half;
491 int compare = mid->getName().strref().compare(name);
494 length = length - half - 1;
501 return {first,
false};
507 template <
typename IteratorT>
510 constexpr
unsigned kSmallAttributeList = 16;
511 if (std::distance(first, last) > kSmallAttributeList)
518 template <
typename IteratorT,
typename NameT>
520 std::pair<IteratorT, bool> result =
findAttrSorted(first, last, name);
521 return result.second ? result.first->getValue() :
Attribute();
526 template <
typename IteratorT,
typename NameT>
527 std::optional<NamedAttribute>
529 std::pair<IteratorT, bool> result =
findAttrSorted(first, last, name);
530 return result.second ? *result.first : std::optional<NamedAttribute>();
555 template <
typename Container>
560 return !(*
this == other);
563 return attrs == other.attrs;
578 template <
typename RangeT>
580 append(std::begin(newAttributes), std::end(newAttributes));
584 template <
typename IteratorT,
585 typename = std::enable_if_t<std::is_convertible<
586 typename std::iterator_traits<IteratorT>::iterator_category,
587 std::input_iterator_tag>::value>>
588 void append(IteratorT inStart, IteratorT inEnd) {
591 dictionarySorted.setPointerAndInt(
nullptr,
false);
592 attrs.append(inStart, inEnd);
600 assign(range.begin(), range.end());
603 bool empty()
const {
return attrs.empty(); }
629 std::optional<NamedAttribute>
getNamed(StringRef name)
const;
630 std::optional<NamedAttribute>
getNamed(StringAttr name)
const;
655 bool isSorted()
const {
return dictionarySorted.getInt(); }
658 Attribute eraseImpl(SmallVectorImpl<NamedAttribute>::iterator it);
661 template <
typename AttrListT,
typename NameT>
662 static auto findAttr(AttrListT &attrs, NameT name) {
663 return attrs.isSorted()
669 mutable SmallVector<NamedAttribute, 4> attrs;
674 mutable llvm::PointerIntPair<Attribute, 1, bool> dictionarySorted;
704 MutableArrayRef<std::unique_ptr<Region>>
regions = {});
708 MutableArrayRef<std::unique_ptr<Region>>
regions = {});
713 types.append(newTypes.begin(), newTypes.end());
715 template <
typename RangeT>
716 std::enable_if_t<!std::is_convertible<RangeT, ArrayRef<Type>>::value>
718 types.append(newTypes.begin(), newTypes.end());
747 void addRegion(std::unique_ptr<Region> &®ion);
791 unsigned size() {
return numOperands; }
799 unsigned capacity : 31;
802 unsigned isStorageDynamic : 1;
804 unsigned numOperands;
882 std::optional<int64_t> elementsAttrElementLimit;
885 bool printDebugInfoFlag : 1;
886 bool printDebugInfoPrettyFormFlag : 1;
889 bool printGenericOpFormFlag : 1;
892 bool skipRegionsFlag : 1;
895 bool assumeVerifiedFlag : 1;
898 bool printLocalScope : 1;
901 bool printValueUsersFlag : 1;
1001 return hash == other.hash;
1004 return !(*
this == other);
1008 std::array<uint8_t, 20> hash;
1045 struct PointerLikeTypeTraits<
mlir::OperationName> {
1052 static constexpr
int NumLowBitsAvailable =
1053 PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
1056 struct PointerLikeTypeTraits<
mlir::RegisteredOperationName>
1057 :
public PointerLikeTypeTraits<mlir::OperationName> {
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This is the implementation of the MLIRContext class, using the pImpl idiom.
MLIRContext is the top-level object for a collection of MLIR operations.
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.
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.
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)
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
NamedAttrList & operator=(const SmallVectorImpl< NamedAttribute > &rhs)
NamedAttrList(std::nullopt_t none)
NamedAttribute represents a combination of a name and an Attribute value.
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 an operand of an operation.
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 shouldAssumeVerified() const
Return if operation verification should be skipped.
OpPrintingFlags & printValueUsers()
Print users of values as comments.
bool shouldUseLocalScope() const
Return if the printer should use local scope when dumping the IR.
OpPrintingFlags & skipRegions()
Skip printing regions.
bool shouldPrintDebugInfoPrettyForm() const
Return if debug information should be printed in the pretty form.
bool shouldPrintValueUsers() const
Return if the printer should print users of values.
bool shouldPrintGenericOpForm() const
Return if operations should be printed in the generic form.
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 & 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 & assumeVerified()
Do not verify the operation when using custom operation printers.
OpPrintingFlags(std::nullopt_t)
OpPrintingFlags & printGenericOpForm()
Always print operations in the generic form.
OpPrintingFlags & useLocalScope()
Use local scope when printing the operation.
A unique fingerprint for a specific operation, and all of it's internal operations.
bool operator!=(const OperationFingerPrint &other) const
OperationFingerPrint & operator=(const OperationFingerPrint &)=default
OperationFingerPrint(Operation *topOp)
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.
ArrayRef< StringAttr > getAttributeNames() const
TypeID typeID
The unique identifier of the derived Op class.
Dialect * getDialect() const
detail::InterfaceMap & getInterfaceMap()
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.
StringAttr getName() const
bool operator==(const OperationName &rhs) const
llvm::unique_function< LogicalResult(Operation *) const > VerifyInvariantsFn
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
bool operator!=(const OperationName &rhs) const
StringRef stripDialect() const
Return the operation name with dialect name stripped, if it has one.
ArrayRef< StringAttr > getAttributeNames() const
Return the list of cached attribute names registered to this operation.
llvm::unique_function< ParseResult(OpAsmParser &, OperationState &)> ParseAssemblyFn
bool hasTrait() const
Returns true if the operation was registered with a particular trait, e.g.
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,...
OperationName(Impl *impl)
ParseAssemblyFn getParseAssemblyFn() const
Return the static hook for parsing this operation assembly.
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.
llvm::unique_function< LogicalResult(Operation *) const > VerifyRegionInvariantsFn
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.
bool mightHaveTrait(TypeID traitID) const
bool hasInterface() const
Returns true if this operation has the given interface registered to it.
llvm::unique_function< void(Operation *, OpAsmPrinter &, StringRef) const > PrintAssemblyFn
T::Concept * getInterface() const
Returns an instance of the concept object for the given interface if it was registered to this operat...
bool isRegistered() const
Return if this operation is registered.
bool mightHaveInterface() const
Returns true if the operation might have the provided interface.
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
void * getAsOpaquePointer() const
Represent the operation name as an opaque pointer.
LogicalResult verifyRegionInvariants(Operation *op) const
TypeID getTypeID() const
Return the unique identifier of the derived Op class, or null if not registered.
MLIRContext * getContext()
Return the context this operation is associated with.
void populateDefaultAttrs(NamedAttrList &attrs) const
This hook implements the method to populate defaults attributes that are unset.
llvm::unique_function< LogicalResult(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) const > FoldHookFn
LogicalResult verifyInvariants(Operation *op) const
These hooks implement the verifiers for this operation.
llvm::unique_function< void(const OperationName &, NamedAttrList &) const > PopulateDefaultAttrsFn
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
void print(raw_ostream &os) const
bool hasInterface(TypeID interfaceID) const
static OperationName getFromOpaquePointer(const void *pointer)
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.
This class represents success/failure for parsing-like operations that find it important to chain tog...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
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.
ParseResult parseAssembly(OpAsmParser &parser, OperationState &result) const
Use the specified object to parse this ops custom assembly format.
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 provides an efficient unique identifier for a specific C++ type.
This class provides an abstraction over the various different ranges of value types.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
This class provides an efficient mapping between a given Interface type, and a particular implementat...
void insertModels()
Insert the given interface models.
bool contains(TypeID interfaceID) const
Returns true if the interface map contains an interface for the given id.
T::Concept * lookup() const
Returns an instance of the concept object for the given interface if it was registered to this map,...
This class handles the management of operation operands.
MutableArrayRef< OpOperand > getOperands()
Get the operation operands held by the storage.
void eraseOperands(unsigned start, unsigned length)
Erase the operands held by the storage within the given range.
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)
Include the generated interface declarations.
std::optional< NamedAttribute > getNamedAttrFromSortedRange(IteratorT first, IteratorT last, NameT name)
Get an attribute from a sorted range of named attributes.
Attribute getAttrFromSortedRange(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.
@ Type
An inlay hint that for a type annotation.
int compare(const Fraction &x, const Fraction &y)
Three-way comparison between two fractions.
This header declares functions that assit transformations in the MemRef dialect.
llvm::function_ref< Fn > function_ref
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
inline ::llvm::hash_code hash_value(AffineExpr arg)
Make AffineExpr hashable.
llvm::hash_code hash_value(OperationName arg)
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
Enable Bitmask enums for OperationEquivalence::Flags.
static mlir::OperationName getTombstoneKey()
static mlir::OperationName getEmptyKey()
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)
This class represents an efficient way to signal success or failure.
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)
Compare two regions (including their subregions) 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.
static bool isEquivalentTo(Operation *lhs, Operation *rhs, function_ref< LogicalResult(Value, Value)> checkEquivalent, function_ref< void(Value, Value)> markEquivalent=nullptr, Flags flags=Flags::None)
Compare two operations (including their regions) and return if they are equivalent.
This class represents a type erased version of an operation.
virtual void getCanonicalizationPatterns(RewritePatternSet &, MLIRContext *)=0
virtual OperationName::ParseAssemblyFn getParseAssemblyFn()=0
virtual void printAssembly(Operation *, OpAsmPrinter &, StringRef)=0
virtual bool hasTrait(TypeID)=0
virtual LogicalResult verifyInvariants(Operation *)=0
virtual LogicalResult foldHook(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &)=0
virtual void populateDefaultAttrs(const OperationName &, NamedAttrList &)=0
virtual ~InterfaceConcept()=default
virtual LogicalResult verifyRegionInvariants(Operation *)=0
Default implementation for unregistered operations.
LogicalResult foldHook(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) final
OperationName::ParseAssemblyFn getParseAssemblyFn() final
bool hasTrait(TypeID) final
LogicalResult verifyRegionInvariants(Operation *) final
void getCanonicalizationPatterns(RewritePatternSet &, MLIRContext *) final
void populateDefaultAttrs(const OperationName &, NamedAttrList &) final
void printAssembly(Operation *, OpAsmPrinter &, StringRef) final
LogicalResult verifyInvariants(Operation *) final
This represents an operation in an abstracted form, suitable for use with the builder APIs.
void addRegions(MutableArrayRef< std::unique_ptr< Region >> regions)
Take ownership of a set of regions that should be attached to the Operation.
SmallVector< Block *, 1 > successors
Successors of this operation and their respective operands.
SmallVector< Value, 4 > operands
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.
std::enable_if_t<!std::is_convertible< RangeT, ArrayRef< Type > >::value > addTypes(RangeT &&newTypes)
void addSuccessors(Block *successor)
void addTypes(ArrayRef< Type > newTypes)
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
OperationState(Location location, StringRef name)
MLIRContext * getContext() const
Get the context held by this operation state.
SmallVector< Type, 4 > types
Types of the results of this operation.
Region * addRegion()
Create a region that should be attached to the operation.
Implementation of the InterfaceConcept for operation APIs that forwarded to a concrete op implementat...
bool hasTrait(TypeID id) 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
LogicalResult foldHook(Operation *op, ArrayRef< Attribute > attrs, SmallVectorImpl< OpFoldResult > &results) final