[Mlir-commits] [mlir] [MLIR] Prevent CF to SCF transform from erasing blocks still in use (PR #206310)
Martin P
llvmlistbot at llvm.org
Wed Jul 1 04:23:34 PDT 2026
https://github.com/pechy updated https://github.com/llvm/llvm-project/pull/206310
>From 6a37fc159eead0e85f6821867d741a2d4c2423c2 Mon Sep 17 00:00:00 2001
From: Martin Petracek <martin at petracek.net>
Date: Mon, 29 Jun 2026 23:27:05 +0700
Subject: [PATCH] [MLIR] Verify that all blocks are reachable before CFG to SCF
transform
CFG to SCF transform cannot handle unreachable code. Properly verify
that all blocks are reachable and document this limitation in the pass
description.
Fixes #206086
---
mlir/include/mlir/Transforms/CFGToSCF.h | 7 ++++---
mlir/lib/Transforms/Utils/CFGToSCF.cpp | 7 ++++++-
.../ControlFlowToSCF/unreachable-blocks.mlir | 18 ++++++++++++++++++
3 files changed, 28 insertions(+), 4 deletions(-)
create mode 100644 mlir/test/Conversion/ControlFlowToSCF/unreachable-blocks.mlir
diff --git a/mlir/include/mlir/Transforms/CFGToSCF.h b/mlir/include/mlir/Transforms/CFGToSCF.h
index 517e116f3c58e..2ca019ddfe23d 100644
--- a/mlir/include/mlir/Transforms/CFGToSCF.h
+++ b/mlir/include/mlir/Transforms/CFGToSCF.h
@@ -149,9 +149,10 @@ class CFGToSCFInterface {
/// Otherwise a single control flow graph operation branching to one block
/// per return-like operation kind remains.
///
-/// The transformation currently requires that all control flow graph operations
-/// have no side effects, implement the BranchOpInterface and does not have any
-/// operation produced successor operands.
+/// The transformation currently requires that the region has no unreachable
+/// blocks and that all control flow graph operations have no side effects,
+/// implement the BranchOpInterface and does not have any operation produced
+/// successor operands.
/// Returns failure if any of the preconditions are violated or if any of the
/// methods of `interface` failed. The IR is left in an unspecified state.
///
diff --git a/mlir/lib/Transforms/Utils/CFGToSCF.cpp b/mlir/lib/Transforms/Utils/CFGToSCF.cpp
index 0cc6bb43ddd38..2cda4a26543bd 100644
--- a/mlir/lib/Transforms/Utils/CFGToSCF.cpp
+++ b/mlir/lib/Transforms/Utils/CFGToSCF.cpp
@@ -1234,8 +1234,13 @@ static ReturnLikeExitCombiner createSingleExitBlocksForReturnLike(
/// Returns failure if any precondition is violated.
static LogicalResult
checkTransformationPreconditions(Region ®ion, CFGToSCFInterface &interface) {
+ llvm::df_iterator_default_set<Block *, 16> reachable;
+ // Find all blocks reachable from the entry.
+ for (Block *block : depth_first_ext(®ion.front(), reachable))
+ (void)block;
+
for (Block &block : region.getBlocks())
- if (block.hasNoPredecessors() && !block.isEntryBlock())
+ if (!reachable.contains(&block))
return block.front().emitOpError(
"transformation does not support unreachable blocks");
diff --git a/mlir/test/Conversion/ControlFlowToSCF/unreachable-blocks.mlir b/mlir/test/Conversion/ControlFlowToSCF/unreachable-blocks.mlir
new file mode 100644
index 0000000000000..4317e5a5a8102
--- /dev/null
+++ b/mlir/test/Conversion/ControlFlowToSCF/unreachable-blocks.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt --lift-cf-to-scf -verify-diagnostics -split-input-file %s
+
+// Verify that --lift-cf-to-scf does not crash when it encounters an
+// unreachable blocks (dead code). Instead it should emit a clean error.
+// See: https://github.com/llvm/llvm-project/issues/206086
+
+module {
+ func.func @single_return_statement(%arg0: i32) -> i32 {
+ return %arg0 : i32
+ ^bb1: // pred: ^bb1
+ // expected-error at below {{'arith.constant' op transformation does not support unreachable blocks}}
+ %true = arith.constant true
+ cf.cond_br %true, ^bb2, ^bb1
+ ^bb2: // pred: ^bb1
+ return %arg0 : i32
+ }
+}
+
More information about the Mlir-commits
mailing list