From 5e3202749ac19f95737dc15ff5db739c77c0b992 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Wed, 18 Mar 2026 16:01:49 +0100 Subject: [PATCH] [MLIR] Fix crash in FrozenRewritePatternSet when PDL lowering is skipped by debug counter (#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 Fixes #128342 Assisted-by: Claude Code --- 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 34f1442ece7e..d4cd24372efb 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( pdlModule, pdlPatterns.takeConfigs(), configMap, diff --git a/mlir/test/mlir-opt/debugcounter.mlir b/mlir/test/mlir-opt/debugcounter.mlir index 594a2183558b..e724699e705b 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