diff --git a/mlir/include/mlir/Dialect/GPU/GPUOps.td b/mlir/include/mlir/Dialect/GPU/GPUOps.td
--- a/mlir/include/mlir/Dialect/GPU/GPUOps.td
+++ b/mlir/include/mlir/Dialect/GPU/GPUOps.td
@@ -28,6 +28,8 @@
 
 def GPU_Dialect : Dialect {
   let name = "gpu";
+  let hasOperationAttrVerify = 1;
+
   let extraClassDeclaration = [{
     /// Get the name of the attribute used to annotate the modules that contain
     /// kernel modules.
@@ -57,9 +59,6 @@
     /// Returns the numeric value used to identify the private memory address
     /// space.
     static unsigned getPrivateAddressSpace() { return 5; }
-
-    LogicalResult verifyOperationAttribute(Operation *op,
-                                           NamedAttribute attr) override;
   }];
 }
 
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
@@ -19,17 +19,12 @@
 def LLVM_Dialect : Dialect {
   let name = "llvm";
   let cppNamespace = "LLVM";
+  let hasRegionArgAttrVerify = 1;
   let extraClassDeclaration = [{
     ~LLVMDialect();
     llvm::LLVMContext &getLLVMContext();
     llvm::Module &getLLVMModule();
 
-    /// Verify a region argument attribute registered to this dialect.
-    /// Returns failure if the verification failed, success otherwise.
-    LogicalResult verifyRegionArgAttribute(Operation *op, unsigned regionIdx,
-                                           unsigned argIdx,
-                                           NamedAttribute argAttr) override;
-
   private:
     friend LLVMType;
 
diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
--- a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
@@ -47,6 +47,10 @@
 
   let cppNamespace = "spirv";
   let hasConstantMaterializer = 1;
+  let hasOperationAttrVerify = 1;
+  let hasRegionArgAttrVerify = 1;
+  let hasRegionResultAttrVerify = 1;
+
   let extraClassDeclaration = [{
     //===------------------------------------------------------------------===//
     // Type
@@ -65,23 +69,6 @@
     /// Returns the attribute name to use when specifying decorations on results
     /// of operations.
     static std::string getAttributeName(Decoration decoration);
-
-    /// Provides a hook for verifying SPIR-V dialect attributes attached to the
-    /// given op.
-    LogicalResult verifyOperationAttribute(Operation *op,
-                                           NamedAttribute attribute) override;
-
-    /// Provides a hook for verifying SPIR-V dialect attributes attached to the
-    /// given op's region argument.
-    LogicalResult verifyRegionArgAttribute(Operation *op, unsigned regionIndex,
-                                           unsigned argIndex,
-                                           NamedAttribute attribute) override;
-
-    /// Provides a hook for verifying SPIR-V dialect attributes attached to the
-    /// given op's region result.
-    LogicalResult verifyRegionResultAttribute(
-        Operation *op, unsigned regionIndex, unsigned resultIndex,
-        NamedAttribute attribute) override;
   }];
 }
 
diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -260,6 +260,16 @@
 
   // If this dialect overrides the hook for materializing constants.
   bit hasConstantMaterializer = 0;
+
+  // If this dialect overrides the hook for verifying operation attributes.
+  bit hasOperationAttrVerify = 0;
+
+  // If this dialect overrides the hook for verifying region argument
+  // attributes.
+  bit hasRegionArgAttrVerify = 0;
+
+  // If this dialect overrides the hook for verifying region result attributes.
+  bit hasRegionResultAttrVerify = 0;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/TableGen/Dialect.h b/mlir/include/mlir/TableGen/Dialect.h
--- a/mlir/include/mlir/TableGen/Dialect.h
+++ b/mlir/include/mlir/TableGen/Dialect.h
@@ -49,6 +49,15 @@
   // Returns if this dialect has a constant materializer or not.
   bool hasConstantMaterializer() const;
 
+  /// Returns if this dialect has an operation attribute verifier.
+  bool hasOperationAttrVerify() const;
+
+  /// Returns if this dialect has a region argument attribute verifier.
+  bool hasRegionArgAttrVerify() const;
+
+  /// Returns if this dialect has a region result attribute verifier.
+  bool hasRegionResultAttrVerify() const;
+
   // Returns whether two dialects are equal by checking the equality of the
   // underlying record.
   bool operator==(const Dialect &other) const;
diff --git a/mlir/lib/TableGen/Dialect.cpp b/mlir/lib/TableGen/Dialect.cpp
--- a/mlir/lib/TableGen/Dialect.cpp
+++ b/mlir/lib/TableGen/Dialect.cpp
@@ -58,6 +58,18 @@
   return def->getValueAsBit("hasConstantMaterializer");
 }
 
+bool tblgen::Dialect::hasOperationAttrVerify() const {
+  return def->getValueAsBit("hasOperationAttrVerify");
+}
+
+bool tblgen::Dialect::hasRegionArgAttrVerify() const {
+  return def->getValueAsBit("hasRegionArgAttrVerify");
+}
+
+bool tblgen::Dialect::hasRegionResultAttrVerify() const {
+  return def->getValueAsBit("hasRegionResultAttrVerify");
+}
+
 bool Dialect::operator==(const Dialect &other) const {
   return def == other.def;
 }
diff --git a/mlir/test/lib/TestDialect/CMakeLists.txt b/mlir/test/lib/TestDialect/CMakeLists.txt
--- a/mlir/test/lib/TestDialect/CMakeLists.txt
+++ b/mlir/test/lib/TestDialect/CMakeLists.txt
@@ -6,6 +6,7 @@
 set(LLVM_TARGET_DEFINITIONS TestOps.td)
 mlir_tablegen(TestOps.h.inc -gen-op-decls)
 mlir_tablegen(TestOps.cpp.inc -gen-op-defs)
+mlir_tablegen(TestOpsDialect.h.inc -gen-dialect-decls)
 mlir_tablegen(TestOpEnums.h.inc -gen-enum-decls)
 mlir_tablegen(TestOpEnums.cpp.inc -gen-enum-defs)
 mlir_tablegen(TestPatterns.inc -gen-rewriters)
diff --git a/mlir/test/lib/TestDialect/TestDialect.h b/mlir/test/lib/TestDialect/TestDialect.h
--- a/mlir/test/lib/TestDialect/TestDialect.h
+++ b/mlir/test/lib/TestDialect/TestDialect.h
@@ -29,23 +29,7 @@
 
 namespace mlir {
 
-class TestDialect : public Dialect {
-public:
-  /// Create the dialect in the given `context`.
-  TestDialect(MLIRContext *context);
-
-  /// Get the canonical string name of the dialect.
-  static StringRef getDialectName() { return "test"; }
-
-  LogicalResult verifyOperationAttribute(Operation *op,
-                                         NamedAttribute namedAttr) override;
-  LogicalResult verifyRegionArgAttribute(Operation *op, unsigned regionIndex,
-                                         unsigned argIndex,
-                                         NamedAttribute namedAttr) override;
-  LogicalResult verifyRegionResultAttribute(Operation *op, unsigned regionIndex,
-                                            unsigned resultIndex,
-                                            NamedAttribute namedAttr) override;
-};
+#include "TestOpsDialect.h.inc"
 
 #define GET_OP_CLASSES
 #include "TestOps.h.inc"
diff --git a/mlir/test/lib/TestDialect/TestDialect.cpp b/mlir/test/lib/TestDialect/TestDialect.cpp
--- a/mlir/test/lib/TestDialect/TestDialect.cpp
+++ b/mlir/test/lib/TestDialect/TestDialect.cpp
@@ -128,7 +128,7 @@
 //===----------------------------------------------------------------------===//
 
 TestDialect::TestDialect(MLIRContext *context)
-    : Dialect(getDialectName(), context) {
+    : Dialect(getDialectNamespace(), context) {
   addOperations<
 #define GET_OP_LIST
 #include "TestOps.cpp.inc"
diff --git a/mlir/test/lib/TestDialect/TestOps.td b/mlir/test/lib/TestDialect/TestOps.td
--- a/mlir/test/lib/TestDialect/TestOps.td
+++ b/mlir/test/lib/TestDialect/TestOps.td
@@ -17,13 +17,16 @@
 include "mlir/Interfaces/InferTypeOpInterface.td"
 include "mlir/Interfaces/SideEffects.td"
 
-def TEST_Dialect : Dialect {
+def Test_Dialect : Dialect {
   let name = "test";
   let cppNamespace = "";
+  let hasOperationAttrVerify = 1;
+  let hasRegionArgAttrVerify = 1;
+  let hasRegionResultAttrVerify = 1;
 }
 
 class TEST_Op<string mnemonic, list<OpTrait> traits = []> :
-    Op<TEST_Dialect, mnemonic, traits>;
+    Op<Test_Dialect, mnemonic, traits>;
 
 //===----------------------------------------------------------------------===//
 // Test Types
diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp
--- a/mlir/tools/mlir-tblgen/DialectGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectGen.cpp
@@ -101,6 +101,32 @@
                                          ::mlir::Location loc) override;
 )";
 
+/// The code block for the operation attribute verifier hook.
+static const char *const opAttrVerifierDecl = R"(
+    /// Provides a hook for verifying dialect attributes attached to the given
+    /// op.
+    ::mlir::LogicalResult verifyOperationAttribute(
+        ::mlir::Operation *op, ::mlir::NamedAttribute attribute) override;
+)";
+
+/// The code block for the region argument attribute verifier hook.
+static const char *const regionArgAttrVerifierDecl = R"(
+    /// Provides a hook for verifying dialect attributes attached to the given
+    /// op's region argument.
+    ::mlir::LogicalResult verifyRegionArgAttribute(
+        ::mlir::Operation *op, unsigned regionIndex, unsigned argIndex,
+        ::mlir::NamedAttribute attribute) override;
+)";
+
+/// The code block for the region result attribute verifier hook.
+static const char *const regionResultAttrVerifierDecl = R"(
+    /// Provides a hook for verifying dialect attributes attached to the given
+    /// op's region result.
+    ::mlir::LogicalResult verifyRegionResultAttribute(
+        ::mlir::Operation *op, unsigned regionIndex, unsigned resultIndex,
+        ::mlir::NamedAttribute attribute) override;
+)";
+
 /// Generate the declaration for the given dialect class.
 static void emitDialectDecl(Dialect &dialect,
                             iterator_range<DialectFilterIterator> dialectAttrs,
@@ -120,6 +146,12 @@
   // Add the decls for the various features of the dialect.
   if (dialect.hasConstantMaterializer())
     os << constantMaterializerDecl;
+  if (dialect.hasOperationAttrVerify())
+    os << opAttrVerifierDecl;
+  if (dialect.hasRegionArgAttrVerify())
+    os << regionArgAttrVerifierDecl;
+  if (dialect.hasRegionResultAttrVerify())
+    os << regionResultAttrVerifierDecl;
   if (llvm::Optional<StringRef> extraDecl = dialect.getExtraClassDeclaration())
     os << *extraDecl;