[Mlir-commits] [mlir] [mlir] Add `allowUnverifiableIR` option to pattern rewrite drivers. (PR #225428)

Ingo Müller llvmlistbot at llvm.org
Wed Sep 23 01:55:22 PDT 2026


https://github.com/ingomueller-net updated https://github.com/llvm/llvm-project/pull/225428

>From 9c14e63b2aac42bc59509ca9484e24538ec51d3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ingo=20M=C3=BCller?= <ingomueller at google.com>
Date: Tue, 22 Sep 2026 17:04:04 +0200
Subject: [PATCH] [mlir] Add `allowUnverifiableIR` option to pattern rewrite
 drivers.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Previously, compiling with
`-DMLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS=ON` unconditionally enabled
two kinds of checks: (1) pattern rewriter API contracts, which are
mandatory for correctness, and (2) intermediate IR verifiability, which
is a best practice. However, some passes consciously operate on or
produce temporarily unverifiable intermediate IR, across cooperating
patterns or across phases within the pass. Until now, CI targets, thus,
had the choice to not enable the API checks or deal with noise due to
failing checks for verifiability.

This PR adds an `allowUnverifiableIR` option (default `false`) across
applicable rewrite drivers, which allows to opt out of the verifiability
check in the place where the necessary information is present:

- **GreedyPatternRewriteDriver**: Via `GreedyRewriteConfig`
  (`isUnverifiableIRAllowed()`, `setAllowUnverifiableIR()`).
- **WalkPatternRewriteDriver**: `bool allowUnverifiableIR = false`
  parameter in `walkAndApplyPatterns`.

If unverifiable IR is allowed, `verify()` calls are skipped even if the
expensive checks are enabled while preserving mandatory rewriter API
checks. If the expensive checks are disabled (the default), then no
check are done (as before this PR).

The PR does *not* modify the dialect conversion driver because it
doesn't do IR verification as part of the expensive checks.

Assisted-by: Gemini 3.8 Flash / Antigravity
Signed-off-by: Ingo Müller <ingomueller at google.com>
---
 mlir/docs/PatternRewriter.md                  |  3 +-
 mlir/include/mlir-c/Rewrite.h                 | 19 ++++++++--
 .../Transforms/GreedyPatternRewriteDriver.h   | 11 ++++++
 .../Transforms/WalkPatternRewriteDriver.h     |  9 ++++-
 mlir/lib/Bindings/Python/Rewrite.cpp          | 22 +++++++++---
 mlir/lib/CAPI/Transforms/Rewrite.cpp          | 16 +++++++--
 .../Utils/GreedyPatternRewriteDriver.cpp      | 22 ++++++++----
 .../Utils/WalkPatternRewriteDriver.cpp        | 13 +++++--
 mlir/test/CAPI/rewrite.c                      |  8 +++++
 ...-pattern-driver-allow-unverifiable-ir.mlir | 35 +++++++++++++++++++
 mlir/test/lib/Dialect/Test/TestPatterns.cpp   | 14 ++++++--
 mlir/test/python/rewrite.py                   | 13 +++++++
 12 files changed, 163 insertions(+), 22 deletions(-)
 create mode 100644 mlir/test/Transforms/test-pattern-driver-allow-unverifiable-ir.mlir

diff --git a/mlir/docs/PatternRewriter.md b/mlir/docs/PatternRewriter.md
index 39605c7acb7fe0..e9a220f1de63be 100644
--- a/mlir/docs/PatternRewriter.md
+++ b/mlir/docs/PatternRewriter.md
@@ -97,7 +97,8 @@ Additionally, there are some best practices that patterns are advised to follow:
 
 **Note:** These restrictions and best practices can be checked at runtime by
 building with `-DMLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS=ON` (ideally paired
-with ASan).
+with ASan). Rewrite drivers can opt out of the verifiability checks by setting
+`allowUnverifiableIR` to `true`.
 
 
 ### Application Recursion
diff --git a/mlir/include/mlir-c/Rewrite.h b/mlir/include/mlir-c/Rewrite.h
index 0e5562477d4f43..1ed8355bba6e8c 100644
--- a/mlir/include/mlir-c/Rewrite.h
+++ b/mlir/include/mlir-c/Rewrite.h
@@ -416,6 +416,12 @@ mlirGreedyRewriteDriverConfigSetRegionSimplificationLevel(
 MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigEnableConstantCSE(
     MlirGreedyRewriteDriverConfig config, bool enable);
 
+/// Sets whether to allow unverifiable IR during greedy rewriting.
+/// Note: Verifiability is only actually checked if the build option
+/// `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS` is enabled.
+MLIR_CAPI_EXPORTED void mlirGreedyRewriteDriverConfigSetAllowUnverifiableIR(
+    MlirGreedyRewriteDriverConfig config, bool allow);
+
 /// Gets the maximum number of iterations for the greedy rewrite driver.
 MLIR_CAPI_EXPORTED int64_t mlirGreedyRewriteDriverConfigGetMaxIterations(
     MlirGreedyRewriteDriverConfig config);
@@ -446,11 +452,20 @@ mlirGreedyRewriteDriverConfigGetRegionSimplificationLevel(
 MLIR_CAPI_EXPORTED bool mlirGreedyRewriteDriverConfigIsConstantCSEEnabled(
     MlirGreedyRewriteDriverConfig config);
 
+/// Gets whether unverifiable IR is allowed during greedy rewriting.
+/// Note: Verifiability is only actually checked if the build option
+/// `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS` is enabled.
+MLIR_CAPI_EXPORTED bool mlirGreedyRewriteDriverConfigIsUnverifiableIRAllowed(
+    MlirGreedyRewriteDriverConfig config);
+
 /// Applies the given patterns to the given op by a fast walk-based pattern
 /// rewrite driver.
+/// Note: If `allowUnverifiableIR` is set to true, the IR is allowed to be in an
+/// unverifiable state. Verifiability is only actually checked if the build
+/// option `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS` is enabled.
 MLIR_CAPI_EXPORTED void
-mlirWalkAndApplyPatterns(MlirOperation op,
-                         MlirFrozenRewritePatternSet patterns);
+mlirWalkAndApplyPatterns(MlirOperation op, MlirFrozenRewritePatternSet patterns,
+                         bool allowUnverifiableIR);
 
 /// Apply a partial conversion on the given operation.
 MLIR_CAPI_EXPORTED MlirLogicalResult mlirApplyPartialConversion(
diff --git a/mlir/include/mlir/Transforms/GreedyPatternRewriteDriver.h b/mlir/include/mlir/Transforms/GreedyPatternRewriteDriver.h
index 7fef17d806ef3b..df71983b85fdb2 100644
--- a/mlir/include/mlir/Transforms/GreedyPatternRewriteDriver.h
+++ b/mlir/include/mlir/Transforms/GreedyPatternRewriteDriver.h
@@ -161,6 +161,16 @@ class GreedyRewriteConfig {
     return *this;
   }
 
+  /// Whether to allow unverifiable IR during pattern rewrites.
+  ///
+  /// Note: Verifiability is only actually checked if the build option
+  /// `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS` is enabled.
+  bool isUnverifiableIRAllowed() const { return allowUnverifiableIR; }
+  GreedyRewriteConfig &setAllowUnverifiableIR(bool allow = true) {
+    allowUnverifiableIR = allow;
+    return *this;
+  }
+
 private:
   Region *scope = nullptr;
   bool useTopDownTraversal = false;
@@ -173,6 +183,7 @@ class GreedyRewriteConfig {
   bool fold = true;
   bool cseConstants = true;
   bool cseBetweenIterations = false;
+  bool allowUnverifiableIR = false;
 };
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h b/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h
index 7d5c1d5cebb26c..cac2e2a4677be5 100644
--- a/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h
+++ b/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h
@@ -30,9 +30,16 @@ namespace mlir {
 /// The driver will skip unreachable blocks.
 ///
 /// Note: Does not apply patterns to the given operation itself.
+/// Note: If `allowUnverifiableIR` is set to true, the IR is allowed to be in an
+/// unverifiable state. Verifiability is only actually checked if the build
+/// option `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS` is enabled.
 void walkAndApplyPatterns(Operation *op,
                           const FrozenRewritePatternSet &patterns,
-                          RewriterBase::Listener *listener = nullptr);
+                          RewriterBase::Listener *listener = nullptr,
+                          bool allowUnverifiableIR = false);
+void walkAndApplyPatterns(Operation *op,
+                          const FrozenRewritePatternSet &patterns,
+                          bool allowUnverifiableIR);
 
 } // namespace mlir
 
diff --git a/mlir/lib/Bindings/Python/Rewrite.cpp b/mlir/lib/Bindings/Python/Rewrite.cpp
index f799dd33aa71e2..b4b2ef17bace4f 100644
--- a/mlir/lib/Bindings/Python/Rewrite.cpp
+++ b/mlir/lib/Bindings/Python/Rewrite.cpp
@@ -483,6 +483,10 @@ class PyGreedyRewriteConfig {
     mlirGreedyRewriteDriverConfigEnableConstantCSE(get(), enable);
   }
 
+  void setAllowUnverifiableIR(bool allow) {
+    mlirGreedyRewriteDriverConfigSetAllowUnverifiableIR(get(), allow);
+  }
+
   int64_t getMaxIterations() {
     return mlirGreedyRewriteDriverConfigGetMaxIterations(get());
   }
@@ -513,6 +517,10 @@ class PyGreedyRewriteConfig {
     return mlirGreedyRewriteDriverConfigIsConstantCSEEnabled(get());
   }
 
+  bool isUnverifiableIRAllowed() {
+    return mlirGreedyRewriteDriverConfigIsUnverifiableIRAllowed(get());
+  }
+
 private:
   std::shared_ptr<void> config;
   static void customDeleter(void *c) {
@@ -730,7 +738,11 @@ void populateRewriteSubmodule(nb::module_ &m) {
       .def_prop_rw("enable_constant_cse",
                    &PyGreedyRewriteConfig::isConstantCSEEnabled,
                    &PyGreedyRewriteConfig::enableConstantCSE,
-                   "Enable or disable constant CSE");
+                   "Enable or disable constant CSE")
+      .def_prop_rw("allow_unverifiable_ir",
+                   &PyGreedyRewriteConfig::isUnverifiableIRAllowed,
+                   &PyGreedyRewriteConfig::setAllowUnverifiableIR,
+                   "Allow unverifiable IR during greedy rewriting");
 
   nb::class_<PyConversionConfig>(m, "ConversionConfig")
       .def(nb::init<>(), "Create a conversion config with defaults")
@@ -779,10 +791,12 @@ void populateRewriteSubmodule(nb::module_ &m) {
           "results.")
       .def(
           "walk_and_apply_patterns",
-          [](PyOperationBase &op, PyFrozenRewritePatternSet &set) {
-            mlirWalkAndApplyPatterns(op.getOperation(), set.get());
+          [](PyOperationBase &op, PyFrozenRewritePatternSet &set,
+             bool allowUnverifiableIR) {
+            mlirWalkAndApplyPatterns(op.getOperation(), set.get(),
+                                     allowUnverifiableIR);
           },
-          "op"_a, "set"_a,
+          "op"_a, "set"_a, "allow_unverifiable_ir"_a = false,
           "Applies the given patterns to the given op by a fast walk-based "
           "driver.")
       .def(
diff --git a/mlir/lib/CAPI/Transforms/Rewrite.cpp b/mlir/lib/CAPI/Transforms/Rewrite.cpp
index e54c7dcd7271aa..1550f481d74971 100644
--- a/mlir/lib/CAPI/Transforms/Rewrite.cpp
+++ b/mlir/lib/CAPI/Transforms/Rewrite.cpp
@@ -402,6 +402,11 @@ void mlirGreedyRewriteDriverConfigEnableConstantCSE(
   unwrap(config)->enableConstantCSE(enable);
 }
 
+void mlirGreedyRewriteDriverConfigSetAllowUnverifiableIR(
+    MlirGreedyRewriteDriverConfig config, bool allow) {
+  unwrap(config)->setAllowUnverifiableIR(allow);
+}
+
 int64_t mlirGreedyRewriteDriverConfigGetMaxIterations(
     MlirGreedyRewriteDriverConfig config) {
   return unwrap(config)->getMaxIterations();
@@ -457,6 +462,11 @@ bool mlirGreedyRewriteDriverConfigIsConstantCSEEnabled(
   return unwrap(config)->isConstantCSEEnabled();
 }
 
+bool mlirGreedyRewriteDriverConfigIsUnverifiableIRAllowed(
+    MlirGreedyRewriteDriverConfig config) {
+  return unwrap(config)->isUnverifiableIRAllowed();
+}
+
 MlirLogicalResult
 mlirApplyPatternsAndFoldGreedily(MlirModule op,
                                  MlirFrozenRewritePatternSet patterns,
@@ -474,8 +484,10 @@ mlirApplyPatternsAndFoldGreedilyWithOp(MlirOperation op,
 }
 
 void mlirWalkAndApplyPatterns(MlirOperation op,
-                              MlirFrozenRewritePatternSet patterns) {
-  mlir::walkAndApplyPatterns(unwrap(op), *unwrap(patterns));
+                              MlirFrozenRewritePatternSet patterns,
+                              bool allowUnverifiableIR) {
+  mlir::walkAndApplyPatterns(unwrap(op), *unwrap(patterns),
+                             allowUnverifiableIR);
 }
 
 MlirLogicalResult
diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
index b71194e783ba06..863a11689a066a 100644
--- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
+++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
@@ -56,8 +56,10 @@ namespace {
 /// This struct stores finger prints of ops to determine whether the IR has
 /// changed or not.
 struct ExpensiveChecks : public RewriterBase::ForwardingListener {
-  ExpensiveChecks(RewriterBase::Listener *driver, Operation *topLevel)
-      : RewriterBase::ForwardingListener(driver), topLevel(topLevel) {}
+  ExpensiveChecks(RewriterBase::Listener *driver, Operation *topLevel,
+                  bool allowUnverifiableIR)
+      : RewriterBase::ForwardingListener(driver), topLevel(topLevel),
+        allowUnverifiableIR(allowUnverifiableIR) {}
 
   /// Compute finger prints of the given op and its nested ops.
   void computeFingerPrints(Operation *topLevel) {
@@ -80,7 +82,7 @@ struct ExpensiveChecks : public RewriterBase::ForwardingListener {
       return;
 
     // Make sure that the IR still verifies.
-    if (failed(verify(topLevel)))
+    if (!allowUnverifiableIR && failed(verify(topLevel)))
       llvm::report_fatal_error("IR failed to verify after pattern application");
 
     // Pattern application success => IR must have changed.
@@ -125,7 +127,7 @@ struct ExpensiveChecks : public RewriterBase::ForwardingListener {
       return;
 
     // Make sure that the IR still verifies.
-    if (failed(verify(topLevel)))
+    if (!allowUnverifiableIR && failed(verify(topLevel)))
       llvm::report_fatal_error("IR failed to verify after folding");
   }
 
@@ -170,6 +172,9 @@ struct ExpensiveChecks : public RewriterBase::ForwardingListener {
 
   /// Finger print of the top-level operation.
   std::optional<OperationFingerPrint> topLevelFingerPrint;
+
+  /// Whether to allow unverifiable IR during pattern rewrites.
+  bool allowUnverifiableIR = false;
 };
 #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
 
@@ -423,7 +428,8 @@ GreedyPatternRewriteDriver::GreedyPatternRewriteDriver(
       , expensiveChecks(
           /*driver=*/this,
           /*topLevel=*/config.getScope() ? config.getScope()->getParentOp()
-                                         : nullptr)
+                                         : nullptr,
+          /*allowUnverifiableIR=*/config.isUnverifiableIRAllowed())
 // clang-format on
 #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
 {
@@ -945,7 +951,8 @@ mlir::applyPatternsGreedily(Region &region,
     config.setScope(&region);
 
 #if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
-  if (failed(verify(config.getScope()->getParentOp())))
+  if (!config.isUnverifiableIRAllowed() &&
+      failed(verify(config.getScope()->getParentOp())))
     llvm::report_fatal_error(
         "greedy pattern rewriter input IR failed to verify");
 #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
@@ -1075,7 +1082,8 @@ LogicalResult mlir::applyOpPatternsGreedily(
   }
 
 #if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
-  if (config.getScope() && failed(verify(config.getScope()->getParentOp())))
+  if (!config.isUnverifiableIRAllowed() && config.getScope() &&
+      failed(verify(config.getScope()->getParentOp())))
     llvm::report_fatal_error(
         "greedy pattern rewriter input IR failed to verify");
 #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
diff --git a/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp
index 0aec6e7e7d9208..2ebba995413ade 100644
--- a/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp
+++ b/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp
@@ -118,9 +118,10 @@ struct ErasedOpsListener final : RewriterBase::ForwardingListener {
 
 void walkAndApplyPatterns(Operation *op,
                           const FrozenRewritePatternSet &patterns,
-                          RewriterBase::Listener *listener) {
+                          RewriterBase::Listener *listener,
+                          bool allowUnverifiableIR) {
 #if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
-  if (failed(verify(op)))
+  if (!allowUnverifiableIR && failed(verify(op)))
     llvm::report_fatal_error("walk pattern rewriter input IR failed to verify");
 #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
 
@@ -241,10 +242,16 @@ void walkAndApplyPatterns(Operation *op,
       {op});
 
 #if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
-  if (failed(verify(op)))
+  if (!allowUnverifiableIR && failed(verify(op)))
     llvm::report_fatal_error(
         "walk pattern rewriter result IR failed to verify");
 #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
 }
 
+void walkAndApplyPatterns(Operation *op,
+                          const FrozenRewritePatternSet &patterns,
+                          bool allowUnverifiableIR) {
+  walkAndApplyPatterns(op, patterns, nullptr, allowUnverifiableIR);
+}
+
 } // namespace mlir
diff --git a/mlir/test/CAPI/rewrite.c b/mlir/test/CAPI/rewrite.c
index 60f5dca31b9ef7..7f1e0a3262c2df 100644
--- a/mlir/test/CAPI/rewrite.c
+++ b/mlir/test/CAPI/rewrite.c
@@ -542,6 +542,10 @@ void testGreedyRewriteDriverConfig(MlirContext ctx) {
   // Test config creation and destruction
   MlirGreedyRewriteDriverConfig config = mlirGreedyRewriteDriverConfigCreate();
 
+  // CHECK: DefaultAllowUnverifiableIR: 0
+  fprintf(stderr, "DefaultAllowUnverifiableIR: %d\n",
+          mlirGreedyRewriteDriverConfigIsUnverifiableIRAllowed(config));
+
   // Test all configuration setters
   mlirGreedyRewriteDriverConfigSetMaxIterations(config, 5);
   mlirGreedyRewriteDriverConfigSetMaxNumRewrites(config, 100);
@@ -552,6 +556,7 @@ void testGreedyRewriteDriverConfig(MlirContext ctx) {
   mlirGreedyRewriteDriverConfigSetRegionSimplificationLevel(
       config, MLIR_GREEDY_SIMPLIFY_REGION_LEVEL_NORMAL);
   mlirGreedyRewriteDriverConfigEnableConstantCSE(config, false);
+  mlirGreedyRewriteDriverConfigSetAllowUnverifiableIR(config, true);
 
   // Test all configuration getters and verify values
   // CHECK: MaxIterations: 5
@@ -575,6 +580,9 @@ void testGreedyRewriteDriverConfig(MlirContext ctx) {
   // CHECK: ConstantCSEEnabled: 0
   fprintf(stderr, "ConstantCSEEnabled: %d\n",
           mlirGreedyRewriteDriverConfigIsConstantCSEEnabled(config));
+  // CHECK: AllowUnverifiableIR: 1
+  fprintf(stderr, "AllowUnverifiableIR: %d\n",
+          mlirGreedyRewriteDriverConfigIsUnverifiableIRAllowed(config));
 
   // CHECK: Config test completed successfully
   fprintf(stderr, "Config test completed successfully\n");
diff --git a/mlir/test/Transforms/test-pattern-driver-allow-unverifiable-ir.mlir b/mlir/test/Transforms/test-pattern-driver-allow-unverifiable-ir.mlir
new file mode 100644
index 00000000000000..f6778129d93b2c
--- /dev/null
+++ b/mlir/test/Transforms/test-pattern-driver-allow-unverifiable-ir.mlir
@@ -0,0 +1,35 @@
+// Tests interactions between `allowUnverifiableIR` rewriter option and
+// `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS` compile time option for both
+// greedy and walk-based pattern rewriters. All RUN lines use an unverifiable
+// input and either print it successfully or fail with a crash.
+
+// Check that in both drivers, if `allow-unverifiable-ir=true`, the driver does
+// not verify IR, independently of the compile time option.
+// RUN: mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false \
+// RUN:   --test-greedy-patterns="allow-unverifiable-ir=true" | FileCheck %s
+// RUN: mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false \
+// RUN:   --test-walk-pattern-rewrite-driver="allow-unverifiable-ir=true" | FileCheck %s
+
+// If the expensive checks are *disabled* at compile time, the driver does not
+// verify IR even if `allow-unverifiable-ir=false` (or default).
+// RUN: %if !mlir-expensive-checks %{ mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-greedy-patterns="allow-unverifiable-ir=false" | FileCheck %s %}
+// RUN: %if !mlir-expensive-checks %{ mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-greedy-patterns | FileCheck %s %}
+// RUN: %if !mlir-expensive-checks %{ mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-walk-pattern-rewrite-driver="allow-unverifiable-ir=false" | FileCheck %s %}
+// RUN: %if !mlir-expensive-checks %{ mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-walk-pattern-rewrite-driver | FileCheck %s %}
+
+// If the expensive checks are *enabled* at compile time and
+// `allow-unverifiable-ir=false` (or default), the driver fails.
+// RUN: %if mlir-expensive-checks %{ not --crash mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-greedy-patterns="allow-unverifiable-ir=false" 2>&1 | FileCheck %s --check-prefix=ERR-GREEDY %}
+// RUN: %if mlir-expensive-checks %{ not --crash mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-greedy-patterns 2>&1 | FileCheck %s --check-prefix=ERR-GREEDY %}
+// RUN: %if mlir-expensive-checks %{ not --crash mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-walk-pattern-rewrite-driver="allow-unverifiable-ir=false" 2>&1 | FileCheck %s --check-prefix=ERR-WALK %}
+// RUN: %if mlir-expensive-checks %{ not --crash mlir-opt %s --mlir-very-unsafe-disable-verifier-on-parsing --verify-each=false --test-walk-pattern-rewrite-driver 2>&1 | FileCheck %s --check-prefix=ERR-WALK %}
+
+// ERR-GREEDY: LLVM ERROR: greedy pattern rewriter input IR failed to verify
+// ERR-WALK: LLVM ERROR: walk pattern rewriter input IR failed to verify
+
+// CHECK-LABEL: sym_name = "test_allow_unverifiable_ir"
+// CHECK: "test.unverifiable_op"() {test.invalid_attr} : () -> ()
+func.func @test_allow_unverifiable_ir() {
+  "test.unverifiable_op"() {test.invalid_attr} : () -> ()
+  return
+}
diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index fbc5ab76d9ba1e..2898afcdc60538 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -495,7 +495,8 @@ struct TestGreedyPatternDriver
     config.setUseTopDownTraversal(useTopDownTraversal)
         .setMaxIterations(this->maxIterations)
         .enableFolding(this->fold)
-        .enableConstantCSE(this->cseConstants);
+        .enableConstantCSE(this->cseConstants)
+        .setAllowUnverifiableIR(this->allowUnverifiableIR);
     (void)applyPatternsGreedily(getOperation(), std::move(patterns), config);
   }
 
@@ -512,6 +513,10 @@ struct TestGreedyPatternDriver
   Option<bool> cseConstants{
       *this, "cse-constants", llvm::cl::desc("Whether to CSE constants"),
       llvm::cl::init(GreedyRewriteConfig().isConstantCSEEnabled())};
+  Option<bool> allowUnverifiableIR{
+      *this, "allow-unverifiable-ir",
+      llvm::cl::desc("Whether to allow unverifiable IR"),
+      llvm::cl::init(GreedyRewriteConfig().isUnverifiableIRAllowed())};
 };
 
 struct DumpNotifications : public RewriterBase::Listener {
@@ -747,13 +752,18 @@ struct TestWalkPatternDriver final
 
     DumpNotifications dumpListener;
     walkAndApplyPatterns(getOperation(), std::move(patterns),
-                         dumpNotifications ? &dumpListener : nullptr);
+                         dumpNotifications ? &dumpListener : nullptr,
+                         allowUnverifiableIR);
   }
 
   Option<bool> dumpNotifications{
       *this, "dump-notifications",
       llvm::cl::desc("Print rewrite listener notifications"),
       llvm::cl::init(false)};
+  Option<bool> allowUnverifiableIR{
+      *this, "allow-unverifiable-ir",
+      llvm::cl::desc("Whether to allow unverifiable IR"),
+      llvm::cl::init(false)};
 };
 
 } // namespace
diff --git a/mlir/test/python/rewrite.py b/mlir/test/python/rewrite.py
index 1cd3e70d3dfce6..0053aa26b3a1f7 100644
--- a/mlir/test/python/rewrite.py
+++ b/mlir/test/python/rewrite.py
@@ -88,12 +88,21 @@ def constant_1_to_2(op, rewriter):
         # CHECK: return %0 : i64
         print(module)
 
+        with InsertionPoint(module.body), Location.unknown():
+            arith.constant(IntegerType.get_signless(64), 1)
+            Operation.create("builtin.unrealized_conversion_cast")
+        walk_and_apply_patterns(module, frozen, allow_unverifiable_ir=True)
+        # CHECK: "arith.constant"() <{value = 2 : i64}> : () -> i64
+        # CHECK: "builtin.unrealized_conversion_cast"() : () -> ()
+        print(module)
+
 
 # CHECK-LABEL: TEST: testGreedyRewriteConfigCreation
 @run
 def testGreedyRewriteConfigCreation():
     # Test basic config creation and destruction
     config = GreedyRewriteConfig()
+    assert not config.allow_unverifiable_ir
     # CHECK: Config created successfully
     print("Config created successfully")
 
@@ -111,6 +120,7 @@ def testGreedyRewriteConfigGetters():
     config.strictness = GreedyRewriteStrictness.EXISTING_AND_NEW_OPS
     config.region_simplification_level = GreedySimplifyRegionLevel.AGGRESSIVE
     config.enable_constant_cse = True
+    config.allow_unverifiable_ir = True
 
     # Test all getter methods and print results
     # CHECK: max_iterations: 5
@@ -134,6 +144,9 @@ def testGreedyRewriteConfigGetters():
     # CHECK: cse_enabled: True
     cse_enabled = config.enable_constant_cse
     print(f"cse_enabled: {cse_enabled}")
+    # CHECK: allow_unverifiable_ir: True
+    allow_unverifiable_ir = config.allow_unverifiable_ir
+    print(f"allow_unverifiable_ir: {allow_unverifiable_ir}")
 
 
 # CHECK-LABEL: TEST: testGreedyRewriteStrictnessEnum



More information about the Mlir-commits mailing list