[mlir] Split out AttrDef/TypeDef and pattern constructs from OpBase.td

OpBase.td has formed into a huge monolith of all ODS constructs. This
commits starts to rectify that by splitting out some constructs to their
own .td files.

Differential Revision: https://reviews.llvm.org/D118636
This commit is contained in:
River Riddle 2022-01-27 21:58:31 -08:00
parent 4767e26775
commit 1d7120c69a
44 changed files with 671 additions and 580 deletions

View File

@ -15,6 +15,7 @@
#define FORTRAN_FIR_REWRITE_PATTERNS
include "mlir/IR/OpBase.td"
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/Arithmetic/IR/ArithmeticOps.td"
include "flang/Optimizer/Dialect/FIROps.td"

View File

@ -13,6 +13,7 @@
#ifndef FIR_DIALECT_FIR_TYPES
#define FIR_DIALECT_FIR_TYPES
include "mlir/IR/AttrTypeBase.td"
include "flang/Optimizer/Dialect/FIRDialect.td"
//===----------------------------------------------------------------------===//

View File

@ -1895,6 +1895,11 @@ public:
std::vector<Record *> getAllDerivedDefinitions(
ArrayRef<StringRef> ClassNames) const;
/// Get all the concrete records that inherit from specified class, if the
/// class is defined. Returns an empty vector if the class is not defined.
std::vector<Record *>
getAllDerivedDefinitionsIfDefined(StringRef ClassName) const;
void dump() const;
};

View File

@ -2736,11 +2736,10 @@ void RecordKeeper::stopBackendTimer() {
}
}
// We cache the record vectors for single classes. Many backends request
// the same vectors multiple times.
std::vector<Record *> RecordKeeper::getAllDerivedDefinitions(
StringRef ClassName) const {
std::vector<Record *>
RecordKeeper::getAllDerivedDefinitions(StringRef ClassName) const {
// We cache the record vectors for single classes. Many backends request
// the same vectors multiple times.
auto Pair = ClassRecordsMap.try_emplace(ClassName);
if (Pair.second)
Pair.first->second = getAllDerivedDefinitions(makeArrayRef(ClassName));
@ -2771,6 +2770,12 @@ std::vector<Record *> RecordKeeper::getAllDerivedDefinitions(
return Defs;
}
std::vector<Record *>
RecordKeeper::getAllDerivedDefinitionsIfDefined(StringRef ClassName) const {
return getClass(ClassName) ? getAllDerivedDefinitions(ClassName)
: std::vector<Record *>();
}
Init *MapResolver::resolve(Init *VarName) {
auto It = Map.find(VarName);
if (It == Map.end())

View File

@ -14,6 +14,7 @@
#ifndef TOY_COMBINE
#define TOY_COMBINE
include "mlir/IR/PatternBase.td"
include "toy/Ops.td"
/// Note: The DRR definition used for defining patterns is shown below:

View File

@ -14,6 +14,7 @@
#ifndef TOY_COMBINE
#define TOY_COMBINE
include "mlir/IR/PatternBase.td"
include "toy/Ops.td"
/// Note: The DRR definition used for defining patterns is shown below:

View File

@ -14,6 +14,7 @@
#ifndef TOY_COMBINE
#define TOY_COMBINE
include "mlir/IR/PatternBase.td"
include "toy/Ops.td"
/// Note: The DRR definition used for defining patterns is shown below:

View File

@ -14,6 +14,7 @@
#ifndef TOY_COMBINE
#define TOY_COMBINE
include "mlir/IR/PatternBase.td"
include "toy/Ops.td"
/// Note: The DRR definition used for defining patterns is shown below:

View File

@ -14,6 +14,7 @@
#ifndef TOY_COMBINE
#define TOY_COMBINE
include "mlir/IR/PatternBase.td"
include "toy/Ops.td"
/// Note: The DRR definition used for defining patterns is shown below:

View File

@ -13,6 +13,7 @@
#ifndef MLIR_DIALECT_ASYNC_IR_ASYNCTYPES
#define MLIR_DIALECT_ASYNC_IR_ASYNCTYPES
include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/Async/IR/AsyncDialect.td"
//===----------------------------------------------------------------------===//

View File

@ -13,6 +13,7 @@
#ifndef MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
#define MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/EmitC/IR/EmitCBase.td"
//===----------------------------------------------------------------------===//

View File

@ -14,6 +14,7 @@
#ifndef MLIR_DIALECT_EMITC_IR_EMITCTYPES
#define MLIR_DIALECT_EMITC_IR_EMITCTYPES
include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/EmitC/IR/EmitCBase.td"
//===----------------------------------------------------------------------===//

View File

@ -9,9 +9,9 @@
#ifndef LLVMIR_ATTRDEFS
#define LLVMIR_ATTRDEFS
include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
// All of the attributes will extend this class.
class LLVM_Attr<string name> : AttrDef<LLVM_Dialect, name>;

View File

@ -13,6 +13,7 @@
#ifndef MLIR_DIALECT_PDL_IR_PDLTYPES
#define MLIR_DIALECT_PDL_IR_PDLTYPES
include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/PDL/IR/PDLDialect.td"
//===----------------------------------------------------------------------===//

View File

@ -9,6 +9,7 @@
#ifndef SPARSETENSOR_ATTRDEFS
#define SPARSETENSOR_ATTRDEFS
include "mlir/IR/AttrTypeBase.td"
include "mlir/Dialect/SparseTensor/IR/SparseTensorBase.td"
include "mlir/IR/TensorEncoding.td"

View File

@ -0,0 +1,387 @@
//===-- AttrTypeBase.td - Base Attr/Type definition file ---*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the base set of constructs for defining Attribute and
// Type classes.
//
//===----------------------------------------------------------------------===//
#ifndef ATTRTYPEBASE_TD
#define ATTRTYPEBASE_TD
include "mlir/IR/OpBase.td"
//-------------------------------------------------------------------------===//
// AttrTrait definitions
//===----------------------------------------------------------------------===//
// These classes are used to define attribute specific traits.
class NativeAttrTrait<string name> : NativeTrait<name, "Attribute">;
class ParamNativeAttrTrait<string prop, string params>
: ParamNativeTrait<prop, params, "Attribute">;
class GenInternalAttrTrait<string prop> : GenInternalTrait<prop, "Attribute">;
class PredAttrTrait<string descr, Pred pred> : PredTrait<descr, pred>;
//===----------------------------------------------------------------------===//
// TypeTrait definitions
//===----------------------------------------------------------------------===//
// These classes are used to define type specific traits.
class NativeTypeTrait<string name> : NativeTrait<name, "Type">;
class ParamNativeTypeTrait<string prop, string params>
: ParamNativeTrait<prop, params, "Type">;
class GenInternalTypeTrait<string prop> : GenInternalTrait<prop, "Type">;
class PredTypeTrait<string descr, Pred pred> : PredTrait<descr, pred>;
//===----------------------------------------------------------------------===//
// Builders
//===----------------------------------------------------------------------===//
// Class for defining a custom getter.
//
// TableGen generates several generic getter methods for each attribute and type
// by default, corresponding to the specified dag parameters. If the default
// generated ones cannot cover some use case, custom getters can be defined
// using instances of this class.
//
// The signature of the `get` is always either:
//
// ```c++
// static <ClassName> get(MLIRContext *context, <other-parameters>...) {
// <body>...
// }
// ```
//
// or:
//
// ```c++
// static <ClassName> get(MLIRContext *context, <parameters>...);
// ```
//
// To define a custom getter, the parameter list and body should be passed
// in as separate template arguments to this class. The parameter list is a
// TableGen DAG with `ins` operation with named arguments, which has either:
// - string initializers ("Type":$name) to represent a typed parameter, or
// - CArg-typed initializers (CArg<"Type", "default">:$name) to represent a
// typed parameter that may have a default value.
// The type string is used verbatim to produce code and, therefore, must be a
// valid C++ type. It is used inside the C++ namespace of the parent Type's
// dialect; explicit namespace qualification like `::mlir` may be necessary if
// Types are not placed inside the `mlir` namespace. The default value string is
// used verbatim to produce code and must be a valid C++ initializer the given
// type. For example, the following signature specification
//
// ```
// AttrOrTypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg)>
// ```
//
// has an integer parameter and a float parameter with a default value.
//
// If an empty string is passed in for `body`, then *only* the builder
// declaration will be generated; this provides a way to define complicated
// builders entirely in C++. If a `body` string is provided, the `Base::get`
// method should be invoked using `$_get`, e.g.:
//
// ```
// AttrOrTypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg), [{
// return $_get($_ctxt, integerArg, floatArg);
// }]>
// ```
//
// This is necessary because the `body` is also used to generate `getChecked`
// methods, which have a different underlying `Base::get*` call.
//
class AttrOrTypeBuilder<dag parameters, code bodyCode = ""> {
dag dagParams = parameters;
code body = bodyCode;
// The context parameter can be inferred from one of the other parameters and
// is not implicitly added to the parameter list.
bit hasInferredContextParam = 0;
}
class AttrBuilder<dag parameters, code bodyCode = "">
: AttrOrTypeBuilder<parameters, bodyCode>;
class TypeBuilder<dag parameters, code bodyCode = "">
: AttrOrTypeBuilder<parameters, bodyCode>;
// A class of AttrOrTypeBuilder that is able to infer the MLIRContext parameter
// from one of the other builder parameters. Instances of this builder do not
// have `MLIRContext *` implicitly added to the parameter list.
class AttrOrTypeBuilderWithInferredContext<dag parameters, code bodyCode = "">
: TypeBuilder<parameters, bodyCode> {
let hasInferredContextParam = 1;
}
class AttrBuilderWithInferredContext<dag parameters, code bodyCode = "">
: AttrOrTypeBuilderWithInferredContext<parameters, bodyCode>;
class TypeBuilderWithInferredContext<dag parameters, code bodyCode = "">
: AttrOrTypeBuilderWithInferredContext<parameters, bodyCode>;
//===----------------------------------------------------------------------===//
// Definitions
//===----------------------------------------------------------------------===//
// Define a new attribute or type, named `name`, that inherits from the given
// C++ base class.
class AttrOrTypeDef<string valueType, string name, list<Trait> defTraits,
string baseCppClass> {
// The name of the C++ base class to use for this def.
string cppBaseClassName = baseCppClass;
// Additional, longer human-readable description of what the def does.
string description = "";
// Name of storage class to generate or use.
string storageClass = name # valueType # "Storage";
// Namespace (withing dialect c++ namespace) in which the storage class
// resides.
string storageNamespace = "detail";
// Specify if the storage class is to be generated.
bit genStorageClass = 1;
// Specify that the generated storage class has a constructor which is written
// in C++.
bit hasStorageCustomConstructor = 0;
// The list of parameters for this type. Parameters will become both
// parameters to the get() method and storage class member variables.
//
// The format of this dag is:
// (ins
// "<c++ type>":$param1Name,
// "<c++ type>":$param2Name,
// AttrOrTypeParameter<"c++ type", "param description">:$param3Name)
// AttrOrTypeParameters (or more likely one of their subclasses) are required
// to add more information about the parameter, specifically:
// - Documentation
// - Code to allocate the parameter (if allocation is needed in the storage
// class constructor)
//
// For example:
// (ins "int":$width,
// ArrayRefParameter<"bool", "list of bools">:$yesNoArray)
//
// (ArrayRefParameter is a subclass of AttrOrTypeParameter which has
// allocation code for re-allocating ArrayRefs. It is defined below.)
dag parameters = (ins);
// Custom builder methods.
// In addition to the custom builders provided here, and unless
// skipDefaultBuilders is set, a default builder is generated with the
// following signature:
//
// ```c++
// static <ClassName> get(MLIRContext *, <parameters>);
// ```
//
// Note that builders should only be provided when a def has parameters.
list<AttrOrTypeBuilder> builders = ?;
// The list of traits attached to this def.
list<Trait> traits = defTraits;
// Use the lowercased name as the keyword for parsing/printing. Specify only
// if you want tblgen to generate declarations and/or definitions of
// the printer/parser.
string mnemonic = ?;
// If 'mnemonic' specified,
// If null, generate just the declarations.
// If a non-empty code block, just use that code as the definition code.
// Error if an empty code block.
code printer = ?;
code parser = ?;
// Custom assembly format. Requires 'mnemonic' to be specified. Cannot be
// specified at the same time as either 'printer' or 'parser'. The generated
// printer requires 'genAccessors' to be true.
string assemblyFormat = ?;
// If set, generate accessors for each parameter.
bit genAccessors = 1;
// Avoid generating default get/getChecked functions. Custom get methods must
// be provided.
bit skipDefaultBuilders = 0;
// Generate the verify and getChecked methods.
bit genVerifyDecl = 0;
// Extra code to include in the class declaration.
code extraClassDeclaration = [{}];
}
// Define a new attribute, named `name`, belonging to `dialect` that inherits
// from the given C++ base class.
class AttrDef<Dialect dialect, string name, list<Trait> traits = [],
string baseCppClass = "::mlir::Attribute">
: DialectAttr<dialect, CPred<"">, /*descr*/"">,
AttrOrTypeDef<"Attr", name, traits, baseCppClass> {
// The name of the C++ Attribute class.
string cppClassName = name # "Attr";
let storageType = dialect.cppNamespace # "::" # name # "Attr";
// The underlying C++ value type
let returnType = dialect.cppNamespace # "::" # cppClassName;
// Make it possible to use such attributes as parameters for other attributes.
string cppType = dialect.cppNamespace # "::" # cppClassName;
// The call expression to convert from the storage type to the return
// type. For example, an enum can be stored as an int but returned as an
// enum class.
//
// Format: $_self will be expanded to the attribute.
//
// For example, `$_self.getValue().getSExtValue()` for `IntegerAttr val` will
// expand to `getAttrOfType<IntegerAttr>("val").getValue().getSExtValue()`.
let convertFromStorage = "$_self.cast<" # dialect.cppNamespace #
"::" # cppClassName # ">()";
// A code block used to build the value 'Type' of an Attribute when
// initializing its storage instance. This field is optional, and if not
// present the attribute will have its value type set to `NoneType`. This code
// block may reference any of the attributes parameters via
// `$_<parameter-name`. If one of the parameters of the attribute is of type
// `AttributeSelfTypeParameter`, this field is ignored.
code typeBuilder = ?;
// The predicate for when this def is used as a constraint.
let predicate = CPred<"$_self.isa<" # dialect.cppNamespace #
"::" # cppClassName # ">()">;
}
// Define a new type, named `name`, belonging to `dialect` that inherits from
// the given C++ base class.
class TypeDef<Dialect dialect, string name, list<Trait> traits = [],
string baseCppClass = "::mlir::Type">
: DialectType<dialect, CPred<"">, /*descr*/"", name # "Type">,
AttrOrTypeDef<"Type", name, traits, baseCppClass> {
// Make it possible to use such type as parameters for other types.
string cppType = dialect.cppNamespace # "::" # cppClassName;
// A constant builder provided when the type has no parameters.
let builderCall = !if(!empty(parameters),
"$_builder.getType<" # dialect.cppNamespace #
"::" # cppClassName # ">()",
"");
// The predicate for when this def is used as a constraint.
let predicate = CPred<"$_self.isa<" # dialect.cppNamespace #
"::" # cppClassName # ">()">;
}
//===----------------------------------------------------------------------===//
// Parameters
//===----------------------------------------------------------------------===//
// 'Parameters' should be subclasses of this or simple strings (which is a
// shorthand for AttrOrTypeParameter<"C++Type">).
class AttrOrTypeParameter<string type, string desc, string accessorType = ""> {
// Custom memory allocation code for storage constructor.
code allocator = ?;
// Comparator used to compare two instances for equality. By default, it uses
// the C++ equality operator.
code comparator = ?;
// The C++ type of this parameter.
string cppType = type;
// The C++ type of the accessor for this parameter.
string cppAccessorType = !if(!empty(accessorType), type, accessorType);
// The C++ storage type of of this parameter if it is a reference, e.g.
// `std::string` for `StringRef` or `SmallVector` for `ArrayRef`.
string cppStorageType = ?;
// One-line human-readable description of the argument.
string summary = desc;
// The format string for the asm syntax (documentation only).
string syntax = ?;
// The default parameter parser is `::mlir::FieldParser<T>::parse($_parser)`,
// which returns `FailureOr<T>`. Specialize `FieldParser` to support parsing
// for your type. Or you can provide a customer printer. For attributes,
// "$_type" will be replaced with the required attribute type.
string parser = ?;
// The default parameter printer is `$_printer << $_self`. Overload the stream
// operator of `AsmPrinter` as necessary to print your type. Or you can
// provide a custom printer.
string printer = ?;
// Mark a parameter as optional. The C++ type of parameters marked as optional
// must be default constructible and be contextually convertible to `bool`.
// Any `Optional<T>` and any attribute type satisfies these requirements.
bit isOptional = 0;
// Provide a default value for the parameter. Parameters with default values
// are considered optional. If a value was not parsed for the parameter, it
// will be set to the default value. Parameters equal to their default values
// are elided when printing. Equality is checked using the `comparator` field,
// which by default is the C++ equality operator. The current MLIR context is
// made available through `$_ctx`, e.g., for constructing default values for
// attributes and types.
string defaultValue = ?;
}
class AttrParameter<string type, string desc, string accessorType = "">
: AttrOrTypeParameter<type, desc, accessorType>;
class TypeParameter<string type, string desc, string accessorType = "">
: AttrOrTypeParameter<type, desc, accessorType>;
// For StringRefs, which require allocation.
class StringRefParameter<string desc = ""> :
AttrOrTypeParameter<"::llvm::StringRef", desc> {
let allocator = [{$_dst = $_allocator.copyInto($_self);}];
let printer = [{$_printer << '"' << $_self << '"';}];
let cppStorageType = "std::string";
}
// For APFloats, which require comparison.
class APFloatParameter<string desc> :
AttrOrTypeParameter<"::llvm::APFloat", desc> {
let comparator = "$_lhs.bitwiseIsEqual($_rhs)";
}
// For standard ArrayRefs, which require allocation.
class ArrayRefParameter<string arrayOf, string desc = ""> :
AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
let allocator = [{$_dst = $_allocator.copyInto($_self);}];
let cppStorageType = "::llvm::SmallVector<" # arrayOf # ">";
}
// For classes which require allocation and have their own allocateInto method.
class SelfAllocationParameter<string type, string desc> :
AttrOrTypeParameter<type, desc> {
let allocator = [{$_dst = $_self.allocateInto($_allocator);}];
}
// For ArrayRefs which contain things which allocate themselves.
class ArrayRefOfSelfAllocationParameter<string arrayOf, string desc> :
AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
let allocator = [{
llvm::SmallVector<}] # arrayOf # [{, 4> tmpFields;
for (size_t i = 0, e = $_self.size(); i < e; ++i)
tmpFields.push_back($_self[i].allocateInto($_allocator));
$_dst = $_allocator.copyInto(ArrayRef<}] # arrayOf # [{>(tmpFields));
}];
}
// An optional parameter.
class OptionalParameter<string type, string desc = ""> :
AttrOrTypeParameter<type, desc> {
let isOptional = 1;
}
// A parameter with a default value.
class DefaultValuedParameter<string type, string value, string desc = ""> :
AttrOrTypeParameter<type, desc> {
let isOptional = 1;
let defaultValue = value;
}
// This is a special parameter used for AttrDefs that represents a `mlir::Type`
// that is also used as the value `Type` of the attribute. Only one parameter
// of the attribute may be of this type.
class AttributeSelfTypeParameter<string desc,
string derivedType = "::mlir::Type"> :
AttrOrTypeParameter<derivedType, desc> {}
#endif // ATTRTYPEBASE_TD

View File

@ -14,6 +14,7 @@
#ifndef BUILTIN_ATTRIBUTES
#define BUILTIN_ATTRIBUTES
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/BuiltinDialect.td"
include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/SubElementInterfaces.td"

View File

@ -13,6 +13,7 @@
#ifndef BUILTIN_LOCATION_ATTRIBUTES_TD
#define BUILTIN_LOCATION_ATTRIBUTES_TD
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/BuiltinDialect.td"
// Base class for Builtin dialect location attributes.

View File

@ -14,6 +14,7 @@
#ifndef BUILTIN_TYPES
#define BUILTIN_TYPES
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/BuiltinDialect.td"
include "mlir/IR/BuiltinTypeInterfaces.td"
include "mlir/IR/SubElementInterfaces.td"

View File

@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
#ifndef ENUM_ATTR
#define ENUM_ATTR
#ifndef ENUMATTR_TD
#define ENUMATTR_TD
include "mlir/IR/OpBase.td"
include "mlir/IR/AttrTypeBase.td"
// A C++ enum as an attribute parameter. The parameter implements a parser and
// printer for the enum by dispatching calls to `stringToSymbol` and
@ -96,4 +96,4 @@ class EnumAttr<Dialect dialect, EnumAttrInfo enumInfo, string name = "",
let assemblyFormat = "$value";
}
#endif // ENUM_ATTR
#endif // ENUMATTR_TD

View File

@ -2005,28 +2005,6 @@ class PredTrait<string descr, Pred pred> : Trait {
Pred predicate = pred;
}
//===----------------------------------------------------------------------===//
// TypeTrait definitions
//===----------------------------------------------------------------------===//
// These classes are used to define type specific traits.
class NativeTypeTrait<string name> : NativeTrait<name, "Type">;
class ParamNativeTypeTrait<string prop, string params>
: ParamNativeTrait<prop, params, "Type">;
class GenInternalTypeTrait<string prop> : GenInternalTrait<prop, "Type">;
class PredTypeTrait<string descr, Pred pred> : PredTrait<descr, pred>;
//===----------------------------------------------------------------------===//
// AttrTrait definitions
//===----------------------------------------------------------------------===//
// These classes are used to define attribute specific traits.
class NativeAttrTrait<string name> : NativeTrait<name, "Attribute">;
class ParamNativeAttrTrait<string prop, string params>
: ParamNativeTrait<prop, params, "Attribute">;
class GenInternalAttrTrait<string prop> : GenInternalTrait<prop, "Attribute">;
class PredAttrTrait<string descr, Pred pred> : PredTrait<descr, pred>;
//===----------------------------------------------------------------------===//
// OpTrait definitions
//===----------------------------------------------------------------------===//
@ -2545,13 +2523,6 @@ class Results<dag rets> {
dag results = rets;
}
//===----------------------------------------------------------------------===//
// Common value constraints
//===----------------------------------------------------------------------===//
def HasNoUseOf: Constraint<
CPred<"$_self.use_empty()">, "has no use">;
//===----------------------------------------------------------------------===//
// Common op type constraints
//===----------------------------------------------------------------------===//
@ -2720,538 +2691,4 @@ class TCopVTEtAreSameAt<list<int> indices> : CPred<
"[this](unsigned i) { return getElementTypeOrSelf(this->getOperand(i)); "
"}))">;
//===----------------------------------------------------------------------===//
// Pattern definitions
//===----------------------------------------------------------------------===//
// Marker used to identify the delta value added to the default benefit value.
def addBenefit;
// Base class for op+ -> op+ rewrite rules. These allow declaratively
// specifying rewrite rules.
//
// A rewrite rule contains two components: a source pattern and one or more
// result patterns. Each pattern is specified as a (recursive) DAG node (tree)
// in the form of `(node arg0, arg1, ...)`.
//
// The `node` are normally MLIR ops, but it can also be one of the directives
// listed later in this section.
//
// ## Symbol binding
//
// In the source pattern, `argN` can be used to specify matchers (e.g., using
// type/attribute type constraints, etc.) and bound to a name for later use.
// We can also bind names to op instances to reference them later in
// multi-entity constraints. Operands in the source pattern can have
// the same name. This bounds one operand to the name while verifying
// the rest are all equal.
//
//
// In the result pattern, `argN` can be used to refer to a previously bound
// name, with potential transformations (e.g., using tAttr, etc.). `argN` can
// itself be nested DAG node. We can also bound names to ops to reference
// them later in other result patterns.
//
// For example,
//
// ```
// def : Pattern<(OneResultOp1:$op1 $arg0, $arg1, $arg0),
// [(OneResultOp2:$op2 $arg0, $arg1),
// (OneResultOp3 $op2 (OneResultOp4))],
// [(HasStaticShapePred $op1)]>;
// ```
//
// First `$arg0` and '$arg1' are bound to the `OneResultOp1`'s first
// and second arguments and used later to build `OneResultOp2`. Second '$arg0'
// is verified to be equal to the first '$arg0' operand.
// `$op1` is bound to `OneResultOp1` and used to check whether the result's
// shape is static. `$op2` is bound to `OneResultOp2` and used to
// build `OneResultOp3`.
//
// ## Multi-result op
//
// To create multi-result ops in result pattern, you can use a syntax similar
// to uni-result op, and it will act as a value pack for all results:
//
// ```
// def : Pattern<(ThreeResultOp ...),
// [(TwoResultOp ...), (OneResultOp ...)]>;
// ```
//
// Then `TwoResultOp` will replace the first two values of `ThreeResultOp`.
//
// You can also use `$<name>__N` to explicitly access the N-th result.
// ```
// def : Pattern<(FiveResultOp ...),
// [(TwoResultOp1:$res1__1 ...), (replaceWithValue $res1__0),
// (TwoResultOp2:$res2 ...), (replaceWithValue $res2__1)]>;
// ```
//
// Then the values generated by `FiveResultOp` will be replaced by
//
// * `FiveResultOp`#0: `TwoResultOp1`#1
// * `FiveResultOp`#1: `TwoResultOp1`#0
// * `FiveResultOp`#2: `TwoResultOp2`#0
// * `FiveResultOp`#3: `TwoResultOp2`#1
// * `FiveResultOp`#4: `TwoResultOp2`#1
class Pattern<dag source, list<dag> results, list<dag> preds = [],
dag benefitAdded = (addBenefit 0)> {
dag sourcePattern = source;
// Result patterns. Each result pattern is expected to replace one result
// of the root op in the source pattern. In the case of more result patterns
// than needed to replace the source op, only the last N results generated
// by the last N result pattern is used to replace a N-result source op.
// So that the beginning result patterns can be used to generate additional
// ops to aid building the results used for replacement.
list<dag> resultPatterns = results;
// Multi-entity constraints. Each constraint here involves multiple entities
// matched in source pattern and places further constraints on them as a
// whole.
list<dag> constraints = preds;
// The delta value added to the default benefit value. The default value is
// the number of ops in the source pattern. The rule with the highest final
// benefit value will be applied first if there are multiple rules matches.
// This delta value can be either positive or negative.
dag benefitDelta = benefitAdded;
}
// Form of a pattern which produces a single result.
class Pat<dag pattern, dag result, list<dag> preds = [],
dag benefitAdded = (addBenefit 0)> :
Pattern<pattern, [result], preds, benefitAdded>;
// Native code call wrapper. This allows invoking an arbitrary C++ expression
// to create an op operand/attribute or replace an op result.
//
// ## Placeholders
//
// If used as a DAG leaf, i.e., `(... NativeCodeCall<"...">:$arg, ...)`,
// the wrapped expression can take special placeholders listed below:
//
// * `$_builder` will be replaced by the current `mlir::PatternRewriter`.
// * `$_self` will be replaced by the defining operation in a source pattern.
// E.g., `NativeCodeCall<"Foo($_self, &$0)> I32Attr:$attr)>`, `$_self` will be
// replaced with the defining operation of the first operand of OneArgOp.
//
// If used as a DAG node, i.e., `(NativeCodeCall<"..."> <arg0>, ..., <argN>)`,
// then positional placeholders are also supported; placeholder `$N` in the
// wrapped C++ expression will be replaced by `<argN>`.
//
// ## Bind multiple results
//
// To bind multi-results and access the N-th result with `$<name>__N`, specify
// the number of return values in the template. Note that only `Value` type is
// supported for multiple results binding.
class NativeCodeCall<string expr, int returns = 1> {
string expression = expr;
int numReturns = returns;
}
class NativeCodeCallVoid<string expr> : NativeCodeCall<expr, 0>;
def ConstantLikeMatcher : NativeCodeCall<"::mlir::success("
"::mlir::matchPattern($_self->getResult(0), ::mlir::m_Constant(&$0)))">;
//===----------------------------------------------------------------------===//
// Rewrite directives
//===----------------------------------------------------------------------===//
// Directive used in result pattern to indicate that no new op are generated,
// so to replace the matched DAG with an existing SSA value.
def replaceWithValue;
// Directive used in result patterns to specify the location of the generated
// op. This directive must be used as a trailing argument to op creation or
// native code calls.
//
// Usage:
// * Create a named location: `(location "myLocation")`
// * Copy the location of a captured symbol: `(location $arg)`
// * Create a fused location: `(location "metadata", $arg0, $arg1)`
def location;
// Directive used in result patterns to specify return types for a created op.
// This allows ops to be created without relying on type inference with
// `OpTraits` or an op builder with deduction.
//
// This directive must be used as a trailing argument to op creation.
//
// Specify one return type with a string literal:
//
// ```
// (AnOp $val, (returnType "$_builder.getI32Type()"))
// ```
//
// Pass a captured value to copy its return type:
//
// ```
// (AnOp $val, (returnType $val));
// ```
//
// Pass a native code call inside a DAG to create a new type with arguments.
//
// ```
// (AnOp $val,
// (returnType (NativeCodeCall<"$_builder.getTupleType({$0})"> $val)));
// ```
//
// Specify multiple return types with multiple of any of the above.
def returnType;
// Directive used to specify the operands may be matched in either order. When
// two adjacents are marked with `either`, it'll try to match the operands in
// either ordering of constraints. Example:
//
// ```
// (TwoArgOp (either $firstArg, (AnOp $secondArg)))
// ```
// The above pattern will accept either `"test.TwoArgOp"(%I32Arg, %AnOpArg)` and
// `"test.TwoArgOp"(%AnOpArg, %I32Arg)`.
//
// Only operand is supported with `either` and note that an operation with
// `Commutative` trait doesn't imply that it'll have the same behavior than
// `either` while pattern matching.
def either;
//===----------------------------------------------------------------------===//
// Attribute and Type generation
//===----------------------------------------------------------------------===//
// Class for defining a custom getter.
//
// TableGen generates several generic getter methods for each attribute and type
// by default, corresponding to the specified dag parameters. If the default
// generated ones cannot cover some use case, custom getters can be defined
// using instances of this class.
//
// The signature of the `get` is always either:
//
// ```c++
// static <ClassName> get(MLIRContext *context, <other-parameters>...) {
// <body>...
// }
// ```
//
// or:
//
// ```c++
// static <ClassName> get(MLIRContext *context, <parameters>...);
// ```
//
// To define a custom getter, the parameter list and body should be passed
// in as separate template arguments to this class. The parameter list is a
// TableGen DAG with `ins` operation with named arguments, which has either:
// - string initializers ("Type":$name) to represent a typed parameter, or
// - CArg-typed initializers (CArg<"Type", "default">:$name) to represent a
// typed parameter that may have a default value.
// The type string is used verbatim to produce code and, therefore, must be a
// valid C++ type. It is used inside the C++ namespace of the parent Type's
// dialect; explicit namespace qualification like `::mlir` may be necessary if
// Types are not placed inside the `mlir` namespace. The default value string is
// used verbatim to produce code and must be a valid C++ initializer the given
// type. For example, the following signature specification
//
// ```
// AttrOrTypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg)>
// ```
//
// has an integer parameter and a float parameter with a default value.
//
// If an empty string is passed in for `body`, then *only* the builder
// declaration will be generated; this provides a way to define complicated
// builders entirely in C++. If a `body` string is provided, the `Base::get`
// method should be invoked using `$_get`, e.g.:
//
// ```
// AttrOrTypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg), [{
// return $_get($_ctxt, integerArg, floatArg);
// }]>
// ```
//
// This is necessary because the `body` is also used to generate `getChecked`
// methods, which have a different underlying `Base::get*` call.
//
class AttrOrTypeBuilder<dag parameters, code bodyCode = ""> {
dag dagParams = parameters;
code body = bodyCode;
// The context parameter can be inferred from one of the other parameters and
// is not implicitly added to the parameter list.
bit hasInferredContextParam = 0;
}
class AttrBuilder<dag parameters, code bodyCode = "">
: AttrOrTypeBuilder<parameters, bodyCode>;
class TypeBuilder<dag parameters, code bodyCode = "">
: AttrOrTypeBuilder<parameters, bodyCode>;
// A class of AttrOrTypeBuilder that is able to infer the MLIRContext parameter
// from one of the other builder parameters. Instances of this builder do not
// have `MLIRContext *` implicitly added to the parameter list.
class AttrOrTypeBuilderWithInferredContext<dag parameters, code bodyCode = "">
: TypeBuilder<parameters, bodyCode> {
let hasInferredContextParam = 1;
}
class AttrBuilderWithInferredContext<dag parameters, code bodyCode = "">
: AttrOrTypeBuilderWithInferredContext<parameters, bodyCode>;
class TypeBuilderWithInferredContext<dag parameters, code bodyCode = "">
: AttrOrTypeBuilderWithInferredContext<parameters, bodyCode>;
// Define a new attribute or type, named `name`, that inherits from the given
// C++ base class.
class AttrOrTypeDef<string valueType, string name, list<Trait> defTraits,
string baseCppClass> {
// The name of the C++ base class to use for this def.
string cppBaseClassName = baseCppClass;
// Additional, longer human-readable description of what the def does.
string description = "";
// Name of storage class to generate or use.
string storageClass = name # valueType # "Storage";
// Namespace (withing dialect c++ namespace) in which the storage class
// resides.
string storageNamespace = "detail";
// Specify if the storage class is to be generated.
bit genStorageClass = 1;
// Specify that the generated storage class has a constructor which is written
// in C++.
bit hasStorageCustomConstructor = 0;
// The list of parameters for this type. Parameters will become both
// parameters to the get() method and storage class member variables.
//
// The format of this dag is:
// (ins
// "<c++ type>":$param1Name,
// "<c++ type>":$param2Name,
// AttrOrTypeParameter<"c++ type", "param description">:$param3Name)
// AttrOrTypeParameters (or more likely one of their subclasses) are required
// to add more information about the parameter, specifically:
// - Documentation
// - Code to allocate the parameter (if allocation is needed in the storage
// class constructor)
//
// For example:
// (ins "int":$width,
// ArrayRefParameter<"bool", "list of bools">:$yesNoArray)
//
// (ArrayRefParameter is a subclass of AttrOrTypeParameter which has
// allocation code for re-allocating ArrayRefs. It is defined below.)
dag parameters = (ins);
// Custom builder methods.
// In addition to the custom builders provided here, and unless
// skipDefaultBuilders is set, a default builder is generated with the
// following signature:
//
// ```c++
// static <ClassName> get(MLIRContext *, <parameters>);
// ```
//
// Note that builders should only be provided when a def has parameters.
list<AttrOrTypeBuilder> builders = ?;
// The list of traits attached to this def.
list<Trait> traits = defTraits;
// Use the lowercased name as the keyword for parsing/printing. Specify only
// if you want tblgen to generate declarations and/or definitions of
// the printer/parser.
string mnemonic = ?;
// If 'mnemonic' specified,
// If null, generate just the declarations.
// If a non-empty code block, just use that code as the definition code.
// Error if an empty code block.
code printer = ?;
code parser = ?;
// Custom assembly format. Requires 'mnemonic' to be specified. Cannot be
// specified at the same time as either 'printer' or 'parser'. The generated
// printer requires 'genAccessors' to be true.
string assemblyFormat = ?;
// If set, generate accessors for each parameter.
bit genAccessors = 1;
// Avoid generating default get/getChecked functions. Custom get methods must
// be provided.
bit skipDefaultBuilders = 0;
// Generate the verify and getChecked methods.
bit genVerifyDecl = 0;
// Extra code to include in the class declaration.
code extraClassDeclaration = [{}];
}
// Define a new attribute, named `name`, belonging to `dialect` that inherits
// from the given C++ base class.
class AttrDef<Dialect dialect, string name, list<Trait> traits = [],
string baseCppClass = "::mlir::Attribute">
: DialectAttr<dialect, CPred<"">, /*descr*/"">,
AttrOrTypeDef<"Attr", name, traits, baseCppClass> {
// The name of the C++ Attribute class.
string cppClassName = name # "Attr";
let storageType = dialect.cppNamespace # "::" # name # "Attr";
// The underlying C++ value type
let returnType = dialect.cppNamespace # "::" # cppClassName;
// Make it possible to use such attributes as parameters for other attributes.
string cppType = dialect.cppNamespace # "::" # cppClassName;
// The call expression to convert from the storage type to the return
// type. For example, an enum can be stored as an int but returned as an
// enum class.
//
// Format: $_self will be expanded to the attribute.
//
// For example, `$_self.getValue().getSExtValue()` for `IntegerAttr val` will
// expand to `getAttrOfType<IntegerAttr>("val").getValue().getSExtValue()`.
let convertFromStorage = "$_self.cast<" # dialect.cppNamespace #
"::" # cppClassName # ">()";
// A code block used to build the value 'Type' of an Attribute when
// initializing its storage instance. This field is optional, and if not
// present the attribute will have its value type set to `NoneType`. This code
// block may reference any of the attributes parameters via
// `$_<parameter-name`. If one of the parameters of the attribute is of type
// `AttributeSelfTypeParameter`, this field is ignored.
code typeBuilder = ?;
// The predicate for when this def is used as a constraint.
let predicate = CPred<"$_self.isa<" # dialect.cppNamespace #
"::" # cppClassName # ">()">;
}
// Define a new type, named `name`, belonging to `dialect` that inherits from
// the given C++ base class.
class TypeDef<Dialect dialect, string name, list<Trait> traits = [],
string baseCppClass = "::mlir::Type">
: DialectType<dialect, CPred<"">, /*descr*/"", name # "Type">,
AttrOrTypeDef<"Type", name, traits, baseCppClass> {
// Make it possible to use such type as parameters for other types.
string cppType = dialect.cppNamespace # "::" # cppClassName;
// A constant builder provided when the type has no parameters.
let builderCall = !if(!empty(parameters),
"$_builder.getType<" # dialect.cppNamespace #
"::" # cppClassName # ">()",
"");
// The predicate for when this def is used as a constraint.
let predicate = CPred<"$_self.isa<" # dialect.cppNamespace #
"::" # cppClassName # ">()">;
}
// 'Parameters' should be subclasses of this or simple strings (which is a
// shorthand for AttrOrTypeParameter<"C++Type">).
class AttrOrTypeParameter<string type, string desc, string accessorType = ""> {
// Custom memory allocation code for storage constructor.
code allocator = ?;
// Comparator used to compare two instances for equality. By default, it uses
// the C++ equality operator.
code comparator = ?;
// The C++ type of this parameter.
string cppType = type;
// The C++ type of the accessor for this parameter.
string cppAccessorType = !if(!empty(accessorType), type, accessorType);
// The C++ storage type of of this parameter if it is a reference, e.g.
// `std::string` for `StringRef` or `SmallVector` for `ArrayRef`.
string cppStorageType = ?;
// One-line human-readable description of the argument.
string summary = desc;
// The format string for the asm syntax (documentation only).
string syntax = ?;
// The default parameter parser is `::mlir::FieldParser<T>::parse($_parser)`,
// which returns `FailureOr<T>`. Specialize `FieldParser` to support parsing
// for your type. Or you can provide a customer printer. For attributes,
// "$_type" will be replaced with the required attribute type.
string parser = ?;
// The default parameter printer is `$_printer << $_self`. Overload the stream
// operator of `AsmPrinter` as necessary to print your type. Or you can
// provide a custom printer.
string printer = ?;
// Mark a parameter as optional. The C++ type of parameters marked as optional
// must be default constructible and be contextually convertible to `bool`.
// Any `Optional<T>` and any attribute type satisfies these requirements.
bit isOptional = 0;
// Provide a default value for the parameter. Parameters with default values
// are considered optional. If a value was not parsed for the parameter, it
// will be set to the default value. Parameters equal to their default values
// are elided when printing. Equality is checked using the `comparator` field,
// which by default is the C++ equality operator. The current MLIR context is
// made available through `$_ctx`, e.g., for constructing default values for
// attributes and types.
string defaultValue = ?;
}
class AttrParameter<string type, string desc, string accessorType = "">
: AttrOrTypeParameter<type, desc, accessorType>;
class TypeParameter<string type, string desc, string accessorType = "">
: AttrOrTypeParameter<type, desc, accessorType>;
// For StringRefs, which require allocation.
class StringRefParameter<string desc = ""> :
AttrOrTypeParameter<"::llvm::StringRef", desc> {
let allocator = [{$_dst = $_allocator.copyInto($_self);}];
let printer = [{$_printer << '"' << $_self << '"';}];
let cppStorageType = "std::string";
}
// For APFloats, which require comparison.
class APFloatParameter<string desc> :
AttrOrTypeParameter<"::llvm::APFloat", desc> {
let comparator = "$_lhs.bitwiseIsEqual($_rhs)";
}
// For standard ArrayRefs, which require allocation.
class ArrayRefParameter<string arrayOf, string desc = ""> :
AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
let allocator = [{$_dst = $_allocator.copyInto($_self);}];
let cppStorageType = "::llvm::SmallVector<" # arrayOf # ">";
}
// For classes which require allocation and have their own allocateInto method.
class SelfAllocationParameter<string type, string desc> :
AttrOrTypeParameter<type, desc> {
let allocator = [{$_dst = $_self.allocateInto($_allocator);}];
}
// For ArrayRefs which contain things which allocate themselves.
class ArrayRefOfSelfAllocationParameter<string arrayOf, string desc> :
AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
let allocator = [{
llvm::SmallVector<}] # arrayOf # [{, 4> tmpFields;
for (size_t i = 0, e = $_self.size(); i < e; ++i)
tmpFields.push_back($_self[i].allocateInto($_allocator));
$_dst = $_allocator.copyInto(ArrayRef<}] # arrayOf # [{>(tmpFields));
}];
}
// An optional parameter.
class OptionalParameter<string type, string desc = ""> :
AttrOrTypeParameter<type, desc> {
let isOptional = 1;
}
// A parameter with a default value.
class DefaultValuedParameter<string type, string value, string desc = ""> :
AttrOrTypeParameter<type, desc> {
let isOptional = 1;
let defaultValue = value;
}
// This is a special parameter used for AttrDefs that represents a `mlir::Type`
// that is also used as the value `Type` of the attribute. Only one parameter
// of the attribute may be of this type.
class AttributeSelfTypeParameter<string desc,
string derivedType = "::mlir::Type"> :
AttrOrTypeParameter<derivedType, desc> {}
#endif // OP_BASE

View File

@ -0,0 +1,221 @@
//===-- PatternBase.td - Base pattern definition file ------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This files contains all of the base constructs for defining DRR patterns.
//
//===----------------------------------------------------------------------===//
#ifndef PATTERNBASE_TD
#define PATTERNBASE_TD
include "mlir/IR/OpBase.td"
//===----------------------------------------------------------------------===//
// Pattern definitions
//===----------------------------------------------------------------------===//
// Marker used to identify the delta value added to the default benefit value.
def addBenefit;
// Base class for op+ -> op+ rewrite rules. These allow declaratively
// specifying rewrite rules.
//
// A rewrite rule contains two components: a source pattern and one or more
// result patterns. Each pattern is specified as a (recursive) DAG node (tree)
// in the form of `(node arg0, arg1, ...)`.
//
// The `node` are normally MLIR ops, but it can also be one of the directives
// listed later in this section.
//
// ## Symbol binding
//
// In the source pattern, `argN` can be used to specify matchers (e.g., using
// type/attribute type constraints, etc.) and bound to a name for later use.
// We can also bind names to op instances to reference them later in
// multi-entity constraints. Operands in the source pattern can have
// the same name. This bounds one operand to the name while verifying
// the rest are all equal.
//
//
// In the result pattern, `argN` can be used to refer to a previously bound
// name, with potential transformations (e.g., using tAttr, etc.). `argN` can
// itself be nested DAG node. We can also bound names to ops to reference
// them later in other result patterns.
//
// For example,
//
// ```
// def : Pattern<(OneResultOp1:$op1 $arg0, $arg1, $arg0),
// [(OneResultOp2:$op2 $arg0, $arg1),
// (OneResultOp3 $op2 (OneResultOp4))],
// [(HasStaticShapePred $op1)]>;
// ```
//
// First `$arg0` and '$arg1' are bound to the `OneResultOp1`'s first
// and second arguments and used later to build `OneResultOp2`. Second '$arg0'
// is verified to be equal to the first '$arg0' operand.
// `$op1` is bound to `OneResultOp1` and used to check whether the result's
// shape is static. `$op2` is bound to `OneResultOp2` and used to
// build `OneResultOp3`.
//
// ## Multi-result op
//
// To create multi-result ops in result pattern, you can use a syntax similar
// to uni-result op, and it will act as a value pack for all results:
//
// ```
// def : Pattern<(ThreeResultOp ...),
// [(TwoResultOp ...), (OneResultOp ...)]>;
// ```
//
// Then `TwoResultOp` will replace the first two values of `ThreeResultOp`.
//
// You can also use `$<name>__N` to explicitly access the N-th result.
// ```
// def : Pattern<(FiveResultOp ...),
// [(TwoResultOp1:$res1__1 ...), (replaceWithValue $res1__0),
// (TwoResultOp2:$res2 ...), (replaceWithValue $res2__1)]>;
// ```
//
// Then the values generated by `FiveResultOp` will be replaced by
//
// * `FiveResultOp`#0: `TwoResultOp1`#1
// * `FiveResultOp`#1: `TwoResultOp1`#0
// * `FiveResultOp`#2: `TwoResultOp2`#0
// * `FiveResultOp`#3: `TwoResultOp2`#1
// * `FiveResultOp`#4: `TwoResultOp2`#1
class Pattern<dag source, list<dag> results, list<dag> preds = [],
dag benefitAdded = (addBenefit 0)> {
dag sourcePattern = source;
// Result patterns. Each result pattern is expected to replace one result
// of the root op in the source pattern. In the case of more result patterns
// than needed to replace the source op, only the last N results generated
// by the last N result pattern is used to replace a N-result source op.
// So that the beginning result patterns can be used to generate additional
// ops to aid building the results used for replacement.
list<dag> resultPatterns = results;
// Multi-entity constraints. Each constraint here involves multiple entities
// matched in source pattern and places further constraints on them as a
// whole.
list<dag> constraints = preds;
// The delta value added to the default benefit value. The default value is
// the number of ops in the source pattern. The rule with the highest final
// benefit value will be applied first if there are multiple rules matches.
// This delta value can be either positive or negative.
dag benefitDelta = benefitAdded;
}
// Form of a pattern which produces a single result.
class Pat<dag pattern, dag result, list<dag> preds = [],
dag benefitAdded = (addBenefit 0)> :
Pattern<pattern, [result], preds, benefitAdded>;
// Native code call wrapper. This allows invoking an arbitrary C++ expression
// to create an op operand/attribute or replace an op result.
//
// ## Placeholders
//
// If used as a DAG leaf, i.e., `(... NativeCodeCall<"...">:$arg, ...)`,
// the wrapped expression can take special placeholders listed below:
//
// * `$_builder` will be replaced by the current `mlir::PatternRewriter`.
// * `$_self` will be replaced by the defining operation in a source pattern.
// E.g., `NativeCodeCall<"Foo($_self, &$0)> I32Attr:$attr)>`, `$_self` will be
// replaced with the defining operation of the first operand of OneArgOp.
//
// If used as a DAG node, i.e., `(NativeCodeCall<"..."> <arg0>, ..., <argN>)`,
// then positional placeholders are also supported; placeholder `$N` in the
// wrapped C++ expression will be replaced by `<argN>`.
//
// ## Bind multiple results
//
// To bind multi-results and access the N-th result with `$<name>__N`, specify
// the number of return values in the template. Note that only `Value` type is
// supported for multiple results binding.
class NativeCodeCall<string expr, int returns = 1> {
string expression = expr;
int numReturns = returns;
}
class NativeCodeCallVoid<string expr> : NativeCodeCall<expr, 0>;
def ConstantLikeMatcher : NativeCodeCall<"::mlir::success("
"::mlir::matchPattern($_self->getResult(0), ::mlir::m_Constant(&$0)))">;
//===----------------------------------------------------------------------===//
// Rewrite directives
//===----------------------------------------------------------------------===//
// Directive used in result pattern to indicate that no new op are generated,
// so to replace the matched DAG with an existing SSA value.
def replaceWithValue;
// Directive used in result patterns to specify the location of the generated
// op. This directive must be used as a trailing argument to op creation or
// native code calls.
//
// Usage:
// * Create a named location: `(location "myLocation")`
// * Copy the location of a captured symbol: `(location $arg)`
// * Create a fused location: `(location "metadata", $arg0, $arg1)`
def location;
// Directive used in result patterns to specify return types for a created op.
// This allows ops to be created without relying on type inference with
// `OpTraits` or an op builder with deduction.
//
// This directive must be used as a trailing argument to op creation.
//
// Specify one return type with a string literal:
//
// ```
// (AnOp $val, (returnType "$_builder.getI32Type()"))
// ```
//
// Pass a captured value to copy its return type:
//
// ```
// (AnOp $val, (returnType $val));
// ```
//
// Pass a native code call inside a DAG to create a new type with arguments.
//
// ```
// (AnOp $val,
// (returnType (NativeCodeCall<"$_builder.getTupleType({$0})"> $val)));
// ```
//
// Specify multiple return types with multiple of any of the above.
def returnType;
// Directive used to specify the operands may be matched in either order. When
// two adjacents are marked with `either`, it'll try to match the operands in
// either ordering of constraints. Example:
//
// ```
// (TwoArgOp (either $firstArg, (AnOp $secondArg)))
// ```
// The above pattern will accept either `"test.TwoArgOp"(%I32Arg, %AnOpArg)` and
// `"test.TwoArgOp"(%AnOpArg, %I32Arg)`.
//
// Only operand is supported with `either` and note that an operation with
// `Commutative` trait doesn't imply that it'll have the same behavior than
// `either` while pattern matching.
def either;
//===----------------------------------------------------------------------===//
// Common value constraints
//===----------------------------------------------------------------------===//
def HasNoUseOf: Constraint<
CPred<"$_self.use_empty()">, "has no use">;
#endif // PATTERNBASE_TD

View File

@ -13,6 +13,7 @@
#ifndef MLIR_CONVERSION_GPUTONVVM_TD
#define MLIR_CONVERSION_GPUTONVVM_TD
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/GPU/GPUOps.td"
include "mlir/Dialect/LLVMIR/NVVMOps.td"

View File

@ -13,6 +13,7 @@
#ifndef MLIR_CONVERSION_GPUTOROCDL_TD
#define MLIR_CONVERSION_GPUTOROCDL_TD
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/GPU/GPUOps.td"
include "mlir/Dialect/LLVMIR/ROCDLOps.td"

View File

@ -13,6 +13,7 @@
#ifndef MLIR_CONVERSION_SHAPETOSTANDARD_TD
#define MLIR_CONVERSION_SHAPETOSTANDARD_TD
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/Shape/IR/ShapeOps.td"
def BroadcastableStringAttr : NativeCodeCall<[{

View File

@ -9,6 +9,7 @@
#ifndef ARITHMETIC_PATTERNS
#define ARITHMETIC_PATTERNS
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/Arithmetic/IR/ArithmeticOps.td"
// Add two integer attributes and create a new one with the result.

View File

@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/SPIRV/IR/SPIRVOps.td"
//===----------------------------------------------------------------------===//

View File

@ -1,3 +1,4 @@
include "mlir/IR/PatternBase.td"
include "mlir/Dialect/Shape/IR/ShapeOps.td"
include "mlir/Dialect/Tensor/IR/TensorOps.td"

View File

@ -15,6 +15,7 @@
// To get the test dialect definition.
include "TestDialect.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/SubElementInterfaces.td"

View File

@ -14,6 +14,7 @@ include "mlir/Dialect/DLTI/DLTIBase.td"
include "mlir/IR/EnumAttr.td"
include "mlir/IR/OpBase.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/PatternBase.td"
include "mlir/IR/RegionKindInterface.td"
include "mlir/IR/SymbolInterfaces.td"
include "mlir/Interfaces/CallInterfaces.td"

View File

@ -1,5 +1,6 @@
// RUN: mlir-tblgen -gen-typedef-defs -I %S/../../include -asmformat-error-is-fatal=false %s 2>&1 | FileCheck %s
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
def Test_Dialect : Dialect {

View File

@ -1,6 +1,7 @@
// RUN: mlir-tblgen -gen-attrdef-defs -I %S/../../include %s | FileCheck %s --check-prefix=ATTR
// RUN: mlir-tblgen -gen-typedef-defs -I %S/../../include %s | FileCheck %s --check-prefix=TYPE
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
/// Test that attribute and type printers and parsers are correctly generated.

View File

@ -1,6 +1,7 @@
// RUN: mlir-tblgen -gen-attrdef-decls -I %S/../../include %s | FileCheck %s --check-prefix=DECL
// RUN: mlir-tblgen -gen-attrdef-defs -I %S/../../include %s | FileCheck %s --check-prefix=DEF
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
// DECL: #ifdef GET_ATTRDEF_CLASSES

View File

@ -1,6 +1,7 @@
// RUN: mlir-tblgen -gen-attrdef-defs -I %S/../../include %s | FileCheck %s --check-prefix=ATTR
// RUN: mlir-tblgen -gen-typedef-defs -I %S/../../include %s | FileCheck %s --check-prefix=TYPE
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
/// Test that attribute and type printers and parsers are correctly generated.

View File

@ -1,6 +1,7 @@
// RUN: not mlir-tblgen -gen-rewriters -I %S/../../include %s 2>&1 | FileCheck %s
include "mlir/IR/OpBase.td"
include "mlir/IR/PatternBase.td"
def Test_Dialect : Dialect {
let name = "test";

View File

@ -2,6 +2,7 @@
// RUN: mlir-tblgen -gen-op-defs -I %S/../../include %s | FileCheck %s --check-prefix=DEF
// RUN: mlir-tblgen -print-records -I %S/../../include %s | FileCheck %s --check-prefix=RECORD
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
def Test_Dialect : Dialect {

View File

@ -4,6 +4,7 @@
// RUN: mlir-tblgen -gen-op-defs -I %S/../../include %s | FileCheck %s --check-prefix=DEFS
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"

View File

@ -7,6 +7,7 @@
// RUN: not mlir-tblgen -gen-rewriters -I %S/../../include -DERROR7 %s 2>&1 | FileCheck --check-prefix=ERROR7 %s
include "mlir/IR/OpBase.td"
include "mlir/IR/PatternBase.td"
// Check using the dialect name as the namespace
def A_Dialect : Dialect {

View File

@ -1,6 +1,7 @@
// RUN: mlir-tblgen -gen-rewriters -I %S/../../include %s | FileCheck %s
include "mlir/IR/OpBase.td"
include "mlir/IR/PatternBase.td"
def Test_Dialect : Dialect {
let name = "test";

View File

@ -1,6 +1,7 @@
// RUN: mlir-tblgen -gen-rewriters -I %S/../../include %s | FileCheck %s
include "mlir/IR/OpBase.td"
include "mlir/IR/PatternBase.td"
def Test_Dialect : Dialect {
let name = "test";

View File

@ -1,6 +1,7 @@
// RUN: mlir-tblgen -gen-typedef-decls -I %S/../../include %s | FileCheck %s --check-prefix=DECL
// RUN: mlir-tblgen -gen-typedef-defs -I %S/../../include %s | FileCheck %s --check-prefix=DEF
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
// DECL: #ifdef GET_TYPEDEF_CLASSES

View File

@ -9,6 +9,7 @@
#ifndef PYTHON_TEST_OPS
#define PYTHON_TEST_OPS
include "mlir/IR/AttrTypeBase.td"
include "mlir/Bindings/Python/Attributes.td"
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/InferTypeOpInterface.td"

View File

@ -652,8 +652,8 @@ protected:
/// A specialized generator for AttrDefs.
struct AttrDefGenerator : public DefGenerator {
AttrDefGenerator(const llvm::RecordKeeper &records, raw_ostream &os)
: DefGenerator(records.getAllDerivedDefinitions("AttrDef"), os, "Attr",
"Attribute",
: DefGenerator(records.getAllDerivedDefinitionsIfDefined("AttrDef"), os,
"Attr", "Attribute",
/*isAttrGenerator=*/true,
/*needsDialectParserPrinter=*/
!records.getAllDerivedDefinitions("DialectAttr").empty()) {
@ -662,8 +662,9 @@ struct AttrDefGenerator : public DefGenerator {
/// A specialized generator for TypeDefs.
struct TypeDefGenerator : public DefGenerator {
TypeDefGenerator(const llvm::RecordKeeper &records, raw_ostream &os)
: DefGenerator(records.getAllDerivedDefinitions("TypeDef"), os, "Type",
"Type", /*isAttrGenerator=*/false,
: DefGenerator(records.getAllDerivedDefinitionsIfDefined("TypeDef"), os,
"Type", "Type",
/*isAttrGenerator=*/false,
/*needsDialectParserPrinter=*/
!records.getAllDerivedDefinitions("DialectType").empty()) {
}

View File

@ -337,11 +337,11 @@ static void emitDialectDoc(const Dialect &dialect, ArrayRef<AttrDef> attrDefs,
static void emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
std::vector<Record *> opDefs = getRequestedOpDefinitions(recordKeeper);
std::vector<Record *> typeDefs =
recordKeeper.getAllDerivedDefinitions("DialectType");
recordKeeper.getAllDerivedDefinitionsIfDefined("DialectType");
std::vector<Record *> typeDefDefs =
recordKeeper.getAllDerivedDefinitions("TypeDef");
recordKeeper.getAllDerivedDefinitionsIfDefined("TypeDef");
std::vector<Record *> attrDefDefs =
recordKeeper.getAllDerivedDefinitions("AttrDef");
recordKeeper.getAllDerivedDefinitionsIfDefined("AttrDef");
std::set<Dialect> dialectsWithDocs;