[Mlir-commits] [mlir] [MLIR] Fix crash in FrozenRewritePatternSet when PDL lowering is skipped by debug counter (PR #186159)

Mehdi Amini llvmlistbot at llvm.org
Thu Mar 12 08:53:18 PDT 2026


https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/186159

When using --mlir-debug-counter=pass-execution-skip=N, the MLIR debug counter can skip the internal PDL-to-PDLInterp lowering pass that runs inside FrozenRewritePatternSet's constructor. This caused an assertion failure in PDLByteCode::Generator::generate() because the PDL module wasn't properly converted to the interpreter dialect.

The fix adds a check after the PDL lowering pipeline runs to verify that the expected matcher function symbol was produced. If the symbol is absent (e.g., because the lowering was skipped by a debug counter), bytecode generation is skipped entirely and PDL patterns are not applied. This allows debug counter bisection to work without crashing.

Fixes #131441

Assisted-by: Claude Code

>From 007885a4c63ad5fd9f6f3b51543efdb5e52aa02d Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 28 Feb 2026 09:57:38 -0800
Subject: [PATCH] [MLIR] Fix crash in FrozenRewritePatternSet when PDL lowering
 is skipped by debug counter

When using --mlir-debug-counter=pass-execution-skip=N, the MLIR debug
counter can skip the internal PDL-to-PDLInterp lowering pass that runs
inside FrozenRewritePatternSet's constructor. This caused an assertion
failure in PDLByteCode::Generator::generate() because the PDL module
wasn't properly converted to the interpreter dialect.

The fix adds a check after the PDL lowering pipeline runs to verify that
the expected matcher function symbol was produced. If the symbol is absent
(e.g., because the lowering was skipped by a debug counter), bytecode
generation is skipped entirely and PDL patterns are not applied. This
allows debug counter bisection to work without crashing.

Fixes #131441
---
 mlir/lib/Rewrite/FrozenRewritePatternSet.cpp | 10 ++++++++++
 mlir/test/mlir-opt/debugcounter.mlir         |  6 ++++++
 2 files changed, 16 insertions(+)

diff --git a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
index 34f1442ece7e6..d4cd24372efbc 100644
--- a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
+++ b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
@@ -18,6 +18,7 @@ using namespace mlir;
 #if MLIR_ENABLE_PDL_IN_PATTERNMATCH
 #include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
 #include "mlir/Dialect/PDL/IR/PDLOps.h"
+#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
 
 static LogicalResult
 convertPDLToPDLInterp(ModuleOp pdlModule,
@@ -134,6 +135,15 @@ FrozenRewritePatternSet::FrozenRewritePatternSet(
     llvm::report_fatal_error(
         "failed to lower PDL pattern module to the PDL Interpreter");
 
+  // Verify that the PDL module was actually lowered to the interpreter
+  // dialect. If the lowering pass was skipped (e.g., by a debug counter
+  // via --mlir-debug-counter), the matcher function will not be present and
+  // we skip bytecode construction. PDL patterns will not be applied in this
+  // case.
+  if (!pdlModule.lookupSymbol(
+          pdl_interp::PDLInterpDialect::getMatcherFunctionName()))
+    return;
+
   // Generate the pdl bytecode.
   impl->pdlByteCode = std::make_unique<detail::PDLByteCode>(
       pdlModule, pdlPatterns.takeConfigs(), configMap,
diff --git a/mlir/test/mlir-opt/debugcounter.mlir b/mlir/test/mlir-opt/debugcounter.mlir
index 594a2183558b5..e724699e705b3 100644
--- a/mlir/test/mlir-opt/debugcounter.mlir
+++ b/mlir/test/mlir-opt/debugcounter.mlir
@@ -3,6 +3,7 @@
 
 // RUN: mlir-opt %s -mlir-debug-counter=unique-tag-for-my-action-skip=-1 -mlir-print-debug-counter --pass-pipeline="builtin.module(func.func(canonicalize))" --mlir-disable-threading 2>&1 | FileCheck %s --check-prefix=CHECK-UNKNOWN-TAG
 // RUN: mlir-opt %s -mlir-debug-counter=pass-execution-skip=1 -mlir-print-debug-counter --pass-pipeline="builtin.module(func.func(canonicalize))" --mlir-disable-threading 2>&1 | FileCheck %s --check-prefix=CHECK-PASS
+// RUN: mlir-opt %s -mlir-debug-counter=pass-execution-skip=1 -test-dialect-conversion-pdll 2>&1 | FileCheck %s --check-prefix=CHECK-PDL-SKIP
 
 func.func @foo() {
     return
@@ -13,3 +14,8 @@ func.func @foo() {
 
 // CHECK-PASS: DebugCounter counters:
 // CHECK-PASS: pass-execution                  : {1,1,-1}
+
+// Regression test for https://github.com/llvm/llvm-project/issues/131441
+// When --mlir-debug-counter skips the internal PDL lowering pass, the
+// FrozenRewritePatternSet should handle it gracefully (no crash).
+// CHECK-PDL-SKIP-LABEL: func @foo



More information about the Mlir-commits mailing list