[llvm] 1d7120c - [mlir] Split out AttrDef/TypeDef and pattern constructs from OpBase.td

River Riddle via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 15 00:51:03 PDT 2022


Author: River Riddle
Date: 2022-03-15T00:18:03-07:00
New Revision: 1d7120c69a9baed2ffc74067fda202a4ee35f720

URL: https://github.com/llvm/llvm-project/commit/1d7120c69a9baed2ffc74067fda202a4ee35f720
DIFF: https://github.com/llvm/llvm-project/commit/1d7120c69a9baed2ffc74067fda202a4ee35f720.diff

LOG: [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

Added: 
    mlir/include/mlir/IR/AttrTypeBase.td
    mlir/include/mlir/IR/PatternBase.td

Modified: 
    flang/include/flang/Optimizer/Dialect/CanonicalizationPatterns.td
    flang/include/flang/Optimizer/Dialect/FIRTypes.td
    llvm/include/llvm/TableGen/Record.h
    llvm/lib/TableGen/Record.cpp
    mlir/examples/toy/Ch3/mlir/ToyCombine.td
    mlir/examples/toy/Ch4/mlir/ToyCombine.td
    mlir/examples/toy/Ch5/mlir/ToyCombine.td
    mlir/examples/toy/Ch6/mlir/ToyCombine.td
    mlir/examples/toy/Ch7/mlir/ToyCombine.td
    mlir/include/mlir/Dialect/Async/IR/AsyncTypes.td
    mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
    mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
    mlir/include/mlir/Dialect/PDL/IR/PDLTypes.td
    mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.td
    mlir/include/mlir/IR/BuiltinAttributes.td
    mlir/include/mlir/IR/BuiltinLocationAttributes.td
    mlir/include/mlir/IR/BuiltinTypes.td
    mlir/include/mlir/IR/EnumAttr.td
    mlir/include/mlir/IR/OpBase.td
    mlir/lib/Conversion/GPUToNVVM/GPUToNVVM.td
    mlir/lib/Conversion/GPUToROCDL/GPUToROCDL.td
    mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.td
    mlir/lib/Dialect/Arithmetic/IR/ArithmeticCanonicalization.td
    mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td
    mlir/lib/Dialect/Shape/IR/ShapeCanonicalization.td
    mlir/test/lib/Dialect/Test/TestAttrDefs.td
    mlir/test/lib/Dialect/Test/TestOps.td
    mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
    mlir/test/mlir-tblgen/attr-or-type-format.td
    mlir/test/mlir-tblgen/attrdefs.td
    mlir/test/mlir-tblgen/default-type-attr-print-parser.td
    mlir/test/mlir-tblgen/expect-symbol.td
    mlir/test/mlir-tblgen/op-attribute.td
    mlir/test/mlir-tblgen/op-decl-and-defs.td
    mlir/test/mlir-tblgen/rewriter-errors.td
    mlir/test/mlir-tblgen/rewriter-indexing.td
    mlir/test/mlir-tblgen/rewriter-static-matcher.td
    mlir/test/mlir-tblgen/typedefs.td
    mlir/test/python/python_test_ops.td
    mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
    mlir/tools/mlir-tblgen/OpDocGen.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/CanonicalizationPatterns.td b/flang/include/flang/Optimizer/Dialect/CanonicalizationPatterns.td
index b51748f91d928..a63a448b7ce0e 100644
--- a/flang/include/flang/Optimizer/Dialect/CanonicalizationPatterns.td
+++ b/flang/include/flang/Optimizer/Dialect/CanonicalizationPatterns.td
@@ -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"
 

diff  --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index a52abc644e725..0875f4abb8332 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -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"
 
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index a8eed1ae27cdd..cc7ad2d754993 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -1895,6 +1895,11 @@ class RecordKeeper {
   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;
 };
 

diff  --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 05ca946390c54..04717052392f0 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -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())

diff  --git a/mlir/examples/toy/Ch3/mlir/ToyCombine.td b/mlir/examples/toy/Ch3/mlir/ToyCombine.td
index ff23adf0b8f18..15477e8969cae 100644
--- a/mlir/examples/toy/Ch3/mlir/ToyCombine.td
+++ b/mlir/examples/toy/Ch3/mlir/ToyCombine.td
@@ -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:

diff  --git a/mlir/examples/toy/Ch4/mlir/ToyCombine.td b/mlir/examples/toy/Ch4/mlir/ToyCombine.td
index ff23adf0b8f18..15477e8969cae 100644
--- a/mlir/examples/toy/Ch4/mlir/ToyCombine.td
+++ b/mlir/examples/toy/Ch4/mlir/ToyCombine.td
@@ -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:

diff  --git a/mlir/examples/toy/Ch5/mlir/ToyCombine.td b/mlir/examples/toy/Ch5/mlir/ToyCombine.td
index ff23adf0b8f18..15477e8969cae 100644
--- a/mlir/examples/toy/Ch5/mlir/ToyCombine.td
+++ b/mlir/examples/toy/Ch5/mlir/ToyCombine.td
@@ -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:

diff  --git a/mlir/examples/toy/Ch6/mlir/ToyCombine.td b/mlir/examples/toy/Ch6/mlir/ToyCombine.td
index ff23adf0b8f18..15477e8969cae 100644
--- a/mlir/examples/toy/Ch6/mlir/ToyCombine.td
+++ b/mlir/examples/toy/Ch6/mlir/ToyCombine.td
@@ -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:

diff  --git a/mlir/examples/toy/Ch7/mlir/ToyCombine.td b/mlir/examples/toy/Ch7/mlir/ToyCombine.td
index ff23adf0b8f18..15477e8969cae 100644
--- a/mlir/examples/toy/Ch7/mlir/ToyCombine.td
+++ b/mlir/examples/toy/Ch7/mlir/ToyCombine.td
@@ -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:

diff  --git a/mlir/include/mlir/Dialect/Async/IR/AsyncTypes.td b/mlir/include/mlir/Dialect/Async/IR/AsyncTypes.td
index d78bd06416ea0..9d3adf28c8a79 100644
--- a/mlir/include/mlir/Dialect/Async/IR/AsyncTypes.td
+++ b/mlir/include/mlir/Dialect/Async/IR/AsyncTypes.td
@@ -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"
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
index 2dd782ba49bf2..bbe6dc51a2369 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
@@ -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"
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
index 499fe3178d73e..1604f7dd37808 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -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"
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 1338b824acf68..f29ea92db3b69 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -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>;
 

diff  --git a/mlir/include/mlir/Dialect/PDL/IR/PDLTypes.td b/mlir/include/mlir/Dialect/PDL/IR/PDLTypes.td
index 10b6130afd148..cfe3dd0b50edb 100644
--- a/mlir/include/mlir/Dialect/PDL/IR/PDLTypes.td
+++ b/mlir/include/mlir/Dialect/PDL/IR/PDLTypes.td
@@ -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"
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.td b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.td
index e91c80616bf65..94ca03808e0ba 100644
--- a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.td
+++ b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.td
@@ -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"
 

diff  --git a/mlir/include/mlir/IR/AttrTypeBase.td b/mlir/include/mlir/IR/AttrTypeBase.td
new file mode 100644
index 0000000000000..8e263b646697b
--- /dev/null
+++ b/mlir/include/mlir/IR/AttrTypeBase.td
@@ -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 
diff erent 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

diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index a9b9c2faeca45..13ef16b42b695 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -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"

diff  --git a/mlir/include/mlir/IR/BuiltinLocationAttributes.td b/mlir/include/mlir/IR/BuiltinLocationAttributes.td
index 0bb3b7a8a59a9..cc483cd7bed5d 100644
--- a/mlir/include/mlir/IR/BuiltinLocationAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinLocationAttributes.td
@@ -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.

diff  --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index d2d249bba7eb2..4c035f8fad0d5 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -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"

diff  --git a/mlir/include/mlir/IR/EnumAttr.td b/mlir/include/mlir/IR/EnumAttr.td
index 8f45d1f42ecd6..8fe6739c75f79 100644
--- a/mlir/include/mlir/IR/EnumAttr.td
+++ b/mlir/include/mlir/IR/EnumAttr.td
@@ -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

diff  --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
index e073048e24c2f..74fd7d64569ed 100644
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -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 
diff erent 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

diff  --git a/mlir/include/mlir/IR/PatternBase.td b/mlir/include/mlir/IR/PatternBase.td
new file mode 100644
index 0000000000000..c6ab1b5a91b58
--- /dev/null
+++ b/mlir/include/mlir/IR/PatternBase.td
@@ -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

diff  --git a/mlir/lib/Conversion/GPUToNVVM/GPUToNVVM.td b/mlir/lib/Conversion/GPUToNVVM/GPUToNVVM.td
index 34e5b4c708c79..dd5889bd1fabf 100644
--- a/mlir/lib/Conversion/GPUToNVVM/GPUToNVVM.td
+++ b/mlir/lib/Conversion/GPUToNVVM/GPUToNVVM.td
@@ -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"
 

diff  --git a/mlir/lib/Conversion/GPUToROCDL/GPUToROCDL.td b/mlir/lib/Conversion/GPUToROCDL/GPUToROCDL.td
index 3e81093bf46e1..92da56046e6d4 100644
--- a/mlir/lib/Conversion/GPUToROCDL/GPUToROCDL.td
+++ b/mlir/lib/Conversion/GPUToROCDL/GPUToROCDL.td
@@ -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"
 

diff  --git a/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.td b/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.td
index 573f0eb2f5d83..c2751a0a3262d 100644
--- a/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.td
+++ b/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.td
@@ -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<[{

diff  --git a/mlir/lib/Dialect/Arithmetic/IR/ArithmeticCanonicalization.td b/mlir/lib/Dialect/Arithmetic/IR/ArithmeticCanonicalization.td
index 6bab58f7320e7..d6b141e88b9a9 100644
--- a/mlir/lib/Dialect/Arithmetic/IR/ArithmeticCanonicalization.td
+++ b/mlir/lib/Dialect/Arithmetic/IR/ArithmeticCanonicalization.td
@@ -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.

diff  --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td
index f6ad2283c0629..02dcf0cb350bc 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+include "mlir/IR/PatternBase.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVOps.td"
 
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/Dialect/Shape/IR/ShapeCanonicalization.td b/mlir/lib/Dialect/Shape/IR/ShapeCanonicalization.td
index 947b28851fdf0..760b0d027add3 100644
--- a/mlir/lib/Dialect/Shape/IR/ShapeCanonicalization.td
+++ b/mlir/lib/Dialect/Shape/IR/ShapeCanonicalization.td
@@ -1,3 +1,4 @@
+include "mlir/IR/PatternBase.td"
 include "mlir/Dialect/Shape/IR/ShapeOps.td"
 include "mlir/Dialect/Tensor/IR/TensorOps.td"
 

diff  --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
index 28e5ca779926b..99ad93533c4ca 100644
--- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td
+++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
@@ -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"
 

diff  --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 68139eb555338..da1aa2ffd7106 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -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"

diff  --git a/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td b/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
index ac8e5974387f3..f1c481f00df27 100644
--- a/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
+++ b/mlir/test/mlir-tblgen/attr-or-type-format-invalid.td
@@ -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 {

diff  --git a/mlir/test/mlir-tblgen/attr-or-type-format.td b/mlir/test/mlir-tblgen/attr-or-type-format.td
index ba8df2b593f9b..eaa6ea3d32d63 100644
--- a/mlir/test/mlir-tblgen/attr-or-type-format.td
+++ b/mlir/test/mlir-tblgen/attr-or-type-format.td
@@ -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.

diff  --git a/mlir/test/mlir-tblgen/attrdefs.td b/mlir/test/mlir-tblgen/attrdefs.td
index 2393fdae71ed6..70a021ebb385b 100644
--- a/mlir/test/mlir-tblgen/attrdefs.td
+++ b/mlir/test/mlir-tblgen/attrdefs.td
@@ -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

diff  --git a/mlir/test/mlir-tblgen/default-type-attr-print-parser.td b/mlir/test/mlir-tblgen/default-type-attr-print-parser.td
index 2ec3f65188368..ac898a97d9eee 100644
--- a/mlir/test/mlir-tblgen/default-type-attr-print-parser.td
+++ b/mlir/test/mlir-tblgen/default-type-attr-print-parser.td
@@ -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.

diff  --git a/mlir/test/mlir-tblgen/expect-symbol.td b/mlir/test/mlir-tblgen/expect-symbol.td
index 809a1c79a48e7..23407311165ac 100644
--- a/mlir/test/mlir-tblgen/expect-symbol.td
+++ b/mlir/test/mlir-tblgen/expect-symbol.td
@@ -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";

diff  --git a/mlir/test/mlir-tblgen/op-attribute.td b/mlir/test/mlir-tblgen/op-attribute.td
index 241c8c6929b5c..16cc898becc7a 100644
--- a/mlir/test/mlir-tblgen/op-attribute.td
+++ b/mlir/test/mlir-tblgen/op-attribute.td
@@ -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 {

diff  --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td
index 047a237db1278..65240857856aa 100644
--- a/mlir/test/mlir-tblgen/op-decl-and-defs.td
+++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td
@@ -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"

diff  --git a/mlir/test/mlir-tblgen/rewriter-errors.td b/mlir/test/mlir-tblgen/rewriter-errors.td
index 357a1cbe6945b..f74fb7a698102 100644
--- a/mlir/test/mlir-tblgen/rewriter-errors.td
+++ b/mlir/test/mlir-tblgen/rewriter-errors.td
@@ -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 {

diff  --git a/mlir/test/mlir-tblgen/rewriter-indexing.td b/mlir/test/mlir-tblgen/rewriter-indexing.td
index 93bd1def2edde..0a94746742b4e 100644
--- a/mlir/test/mlir-tblgen/rewriter-indexing.td
+++ b/mlir/test/mlir-tblgen/rewriter-indexing.td
@@ -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";

diff  --git a/mlir/test/mlir-tblgen/rewriter-static-matcher.td b/mlir/test/mlir-tblgen/rewriter-static-matcher.td
index 9445431dee999..2907923cb28e4 100644
--- a/mlir/test/mlir-tblgen/rewriter-static-matcher.td
+++ b/mlir/test/mlir-tblgen/rewriter-static-matcher.td
@@ -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";

diff  --git a/mlir/test/mlir-tblgen/typedefs.td b/mlir/test/mlir-tblgen/typedefs.td
index 103dba3201eee..af8b70a6dfec4 100644
--- a/mlir/test/mlir-tblgen/typedefs.td
+++ b/mlir/test/mlir-tblgen/typedefs.td
@@ -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

diff  --git a/mlir/test/python/python_test_ops.td b/mlir/test/python/python_test_ops.td
index 67a0b95b05b68..958e2fce8740a 100644
--- a/mlir/test/python/python_test_ops.td
+++ b/mlir/test/python/python_test_ops.td
@@ -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"

diff  --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index c6db1c0418846..5153c6e507851 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -652,8 +652,8 @@ class DefGenerator {
 /// 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()) {
   }

diff  --git a/mlir/tools/mlir-tblgen/OpDocGen.cpp b/mlir/tools/mlir-tblgen/OpDocGen.cpp
index 79a062fd9735a..b3be48176d454 100644
--- a/mlir/tools/mlir-tblgen/OpDocGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDocGen.cpp
@@ -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;
 


        


More information about the llvm-commits mailing list