[Mlir-commits] [mlir] [mlir] Report block argument removal from runRegionDCE (PR #232211)
Hideto Ueno
llvmlistbot at llvm.org
Thu Oct 15 18:49:23 PDT 2026
https://github.com/uenoku updated https://github.com/llvm/llvm-project/pull/232211
>From 9947331ca17c66a83a434936c3194c88c31c48a6 Mon Sep 17 00:00:00 2001
From: Hideto Ueno <uenoku.tokotoko at gmail.com>
Date: Thu, 15 Oct 2026 00:08:22 -0700
Subject: [PATCH 1/3] [mlir] Report block argument removal from runRegionDCE
runRegionDCE reports whether it changed the IR, but deleteDeadness did not
include dead non-entry block arguments in its change flag. Track their removal
so callers detect argument-only changes.
---
mlir/lib/Transforms/Utils/RegionUtils.cpp | 7 +++-
mlir/unittests/Transforms/CMakeLists.txt | 3 ++
mlir/unittests/Transforms/RegionUtils.cpp | 47 +++++++++++++++++++++++
3 files changed, 55 insertions(+), 2 deletions(-)
create mode 100644 mlir/unittests/Transforms/RegionUtils.cpp
diff --git a/mlir/lib/Transforms/Utils/RegionUtils.cpp b/mlir/lib/Transforms/Utils/RegionUtils.cpp
index cc90df06918000..9cc20b54f8d849 100644
--- a/mlir/lib/Transforms/Utils/RegionUtils.cpp
+++ b/mlir/lib/Transforms/Utils/RegionUtils.cpp
@@ -473,8 +473,11 @@ static LogicalResult deleteDeadness(RewriterBase &rewriter,
// The entry block has an unknown contract with their enclosing block, so
// skip it.
for (Block &block : llvm::drop_begin(region.getBlocks(), 1)) {
- block.eraseArguments(
- [&](BlockArgument arg) { return !liveMap.wasProvenLive(arg); });
+ block.eraseArguments([&](BlockArgument arg) {
+ bool isDead = !liveMap.wasProvenLive(arg);
+ erasedAnything |= isDead;
+ return isDead;
+ });
}
}
return success(erasedAnything);
diff --git a/mlir/unittests/Transforms/CMakeLists.txt b/mlir/unittests/Transforms/CMakeLists.txt
index dc5920087b505e..8fbf18fc7e53bd 100644
--- a/mlir/unittests/Transforms/CMakeLists.txt
+++ b/mlir/unittests/Transforms/CMakeLists.txt
@@ -1,8 +1,11 @@
add_mlir_unittest(MLIRTransformsTests
Canonicalizer.cpp
DialectConversion.cpp
+ RegionUtils.cpp
)
mlir_target_link_libraries(MLIRTransformsTests
PRIVATE
+ MLIRControlFlowDialect
+ MLIRFuncDialect
MLIRParser
MLIRTransforms)
diff --git a/mlir/unittests/Transforms/RegionUtils.cpp b/mlir/unittests/Transforms/RegionUtils.cpp
new file mode 100644
index 00000000000000..2828785b9a5fca
--- /dev/null
+++ b/mlir/unittests/Transforms/RegionUtils.cpp
@@ -0,0 +1,47 @@
+//===- RegionUtils.cpp - Region utility unit tests ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Transforms/RegionUtils.h"
+#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Parser/Parser.h"
+#include "gtest/gtest.h"
+
+using namespace mlir;
+
+namespace {
+TEST(RegionUtilsTest, ReportsDeadBlockArgumentRemoval) {
+ MLIRContext context;
+ context.getOrLoadDialect<cf::ControlFlowDialect>();
+ context.getOrLoadDialect<func::FuncDialect>();
+
+ auto module = parseSourceString<ModuleOp>(R"mlir(
+ func.func @f(%arg0: i32) {
+ cf.br ^bb1(%arg0 : i32)
+ ^bb1(%unused: i32):
+ return
+ }
+ )mlir",
+ &context);
+ ASSERT_TRUE(module);
+
+ func::FuncOp func = module->lookupSymbol<func::FuncOp>("f");
+ ASSERT_TRUE(func);
+ Region ®ion = func.getBody();
+ ASSERT_EQ(region.getBlocks().size(), 2u);
+ ASSERT_EQ(region.back().getNumArguments(), 1u);
+
+ IRRewriter rewriter(&context);
+ EXPECT_TRUE(
+ succeeded(runRegionDCE(rewriter, func.getOperation()->getRegions())));
+ EXPECT_EQ(region.back().getNumArguments(), 0u);
+ EXPECT_EQ(region.front().getTerminator()->getNumOperands(), 0u);
+}
+} // namespace
>From ebbb69246c122086842dc3976ed97ca219f07498 Mon Sep 17 00:00:00 2001
From: Hideto Ueno <uenoku.tokotoko at gmail.com>
Date: Thu, 15 Oct 2026 00:26:50 -0700
Subject: [PATCH 2/3] [mlir] Keep region DCE regression test self-contained
Define a local test branch operation instead of linking the Func and ControlFlow dialect libraries. This preserves a CFG regression test for runRegionDCE's change result without adding dialect dependencies to the unit-test target.
---
mlir/unittests/Transforms/CMakeLists.txt | 2 -
mlir/unittests/Transforms/RegionUtils.cpp | 57 +++++++++++++++++------
2 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/mlir/unittests/Transforms/CMakeLists.txt b/mlir/unittests/Transforms/CMakeLists.txt
index 8fbf18fc7e53bd..c0129be9b13fd3 100644
--- a/mlir/unittests/Transforms/CMakeLists.txt
+++ b/mlir/unittests/Transforms/CMakeLists.txt
@@ -5,7 +5,5 @@ add_mlir_unittest(MLIRTransformsTests
)
mlir_target_link_libraries(MLIRTransformsTests
PRIVATE
- MLIRControlFlowDialect
- MLIRFuncDialect
MLIRParser
MLIRTransforms)
diff --git a/mlir/unittests/Transforms/RegionUtils.cpp b/mlir/unittests/Transforms/RegionUtils.cpp
index 2828785b9a5fca..c7f6286c9dc6a6 100644
--- a/mlir/unittests/Transforms/RegionUtils.cpp
+++ b/mlir/unittests/Transforms/RegionUtils.cpp
@@ -7,41 +7,72 @@
//===----------------------------------------------------------------------===//
#include "mlir/Transforms/RegionUtils.h"
-#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/PatternMatch.h"
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Parser/Parser.h"
#include "gtest/gtest.h"
using namespace mlir;
namespace {
+class TestBranchOp
+ : public Op<TestBranchOp, OpTrait::VariadicOperands, OpTrait::ZeroResults,
+ OpTrait::OneSuccessor, OpTrait::IsTerminator,
+ BranchOpInterface::Trait> {
+public:
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestBranchOp)
+
+ using Op::Op;
+
+ static StringRef getOperationName() { return "test.br"; }
+ static ArrayRef<StringRef> getAttributeNames() { return {}; }
+
+ SuccessorOperands getSuccessorOperands(unsigned index) {
+ assert(index == 0 && "invalid successor index");
+ return SuccessorOperands(MutableOperandRange(getOperation()));
+ }
+};
+
+class TestDialect : public Dialect {
+public:
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDialect)
+
+ static StringRef getDialectNamespace() { return "test"; }
+
+ explicit TestDialect(MLIRContext *context)
+ : Dialect(getDialectNamespace(), context, TypeID::get<TestDialect>()) {
+ addOperations<TestBranchOp>();
+ allowUnknownOperations();
+ }
+};
+
TEST(RegionUtilsTest, ReportsDeadBlockArgumentRemoval) {
MLIRContext context;
- context.getOrLoadDialect<cf::ControlFlowDialect>();
- context.getOrLoadDialect<func::FuncDialect>();
+ context.getOrLoadDialect<TestDialect>();
auto module = parseSourceString<ModuleOp>(R"mlir(
- func.func @f(%arg0: i32) {
- cf.br ^bb1(%arg0 : i32)
+ "test.container"() ({
+ ^bb0(%arg0: i32):
+ "test.br"(%arg0)[^bb1] : (i32) -> ()
^bb1(%unused: i32):
- return
- }
+ "test.br"(%unused)[^bb1] : (i32) -> ()
+ }) : () -> ()
)mlir",
&context);
ASSERT_TRUE(module);
- func::FuncOp func = module->lookupSymbol<func::FuncOp>("f");
- ASSERT_TRUE(func);
- Region ®ion = func.getBody();
+ Operation *container = &module->getBody()->front();
+ Region ®ion = container->getRegion(0);
ASSERT_EQ(region.getBlocks().size(), 2u);
ASSERT_EQ(region.back().getNumArguments(), 1u);
IRRewriter rewriter(&context);
- EXPECT_TRUE(
- succeeded(runRegionDCE(rewriter, func.getOperation()->getRegions())));
+ EXPECT_TRUE(succeeded(runRegionDCE(rewriter, container->getRegions())));
EXPECT_EQ(region.back().getNumArguments(), 0u);
EXPECT_EQ(region.front().getTerminator()->getNumOperands(), 0u);
+ EXPECT_EQ(region.back().getTerminator()->getNumOperands(), 0u);
}
} // namespace
>From 5189b3f8304d3ccec9a0b0a1e4055592aa23a214 Mon Sep 17 00:00:00 2001
From: Hideto Ueno <uenoku.tokotoko at gmail.com>
Date: Thu, 15 Oct 2026 18:47:26 -0700
Subject: [PATCH 3/3] Remove a test for now
---
mlir/unittests/Transforms/CMakeLists.txt | 1 -
mlir/unittests/Transforms/RegionUtils.cpp | 78 -----------------------
2 files changed, 79 deletions(-)
delete mode 100644 mlir/unittests/Transforms/RegionUtils.cpp
diff --git a/mlir/unittests/Transforms/CMakeLists.txt b/mlir/unittests/Transforms/CMakeLists.txt
index c0129be9b13fd3..dc5920087b505e 100644
--- a/mlir/unittests/Transforms/CMakeLists.txt
+++ b/mlir/unittests/Transforms/CMakeLists.txt
@@ -1,7 +1,6 @@
add_mlir_unittest(MLIRTransformsTests
Canonicalizer.cpp
DialectConversion.cpp
- RegionUtils.cpp
)
mlir_target_link_libraries(MLIRTransformsTests
PRIVATE
diff --git a/mlir/unittests/Transforms/RegionUtils.cpp b/mlir/unittests/Transforms/RegionUtils.cpp
deleted file mode 100644
index c7f6286c9dc6a6..00000000000000
--- a/mlir/unittests/Transforms/RegionUtils.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- RegionUtils.cpp - Region utility unit tests ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Transforms/RegionUtils.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/IR/Dialect.h"
-#include "mlir/IR/OpDefinition.h"
-#include "mlir/IR/PatternMatch.h"
-#include "mlir/Interfaces/ControlFlowInterfaces.h"
-#include "mlir/Parser/Parser.h"
-#include "gtest/gtest.h"
-
-using namespace mlir;
-
-namespace {
-class TestBranchOp
- : public Op<TestBranchOp, OpTrait::VariadicOperands, OpTrait::ZeroResults,
- OpTrait::OneSuccessor, OpTrait::IsTerminator,
- BranchOpInterface::Trait> {
-public:
- MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestBranchOp)
-
- using Op::Op;
-
- static StringRef getOperationName() { return "test.br"; }
- static ArrayRef<StringRef> getAttributeNames() { return {}; }
-
- SuccessorOperands getSuccessorOperands(unsigned index) {
- assert(index == 0 && "invalid successor index");
- return SuccessorOperands(MutableOperandRange(getOperation()));
- }
-};
-
-class TestDialect : public Dialect {
-public:
- MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDialect)
-
- static StringRef getDialectNamespace() { return "test"; }
-
- explicit TestDialect(MLIRContext *context)
- : Dialect(getDialectNamespace(), context, TypeID::get<TestDialect>()) {
- addOperations<TestBranchOp>();
- allowUnknownOperations();
- }
-};
-
-TEST(RegionUtilsTest, ReportsDeadBlockArgumentRemoval) {
- MLIRContext context;
- context.getOrLoadDialect<TestDialect>();
-
- auto module = parseSourceString<ModuleOp>(R"mlir(
- "test.container"() ({
- ^bb0(%arg0: i32):
- "test.br"(%arg0)[^bb1] : (i32) -> ()
- ^bb1(%unused: i32):
- "test.br"(%unused)[^bb1] : (i32) -> ()
- }) : () -> ()
- )mlir",
- &context);
- ASSERT_TRUE(module);
-
- Operation *container = &module->getBody()->front();
- Region ®ion = container->getRegion(0);
- ASSERT_EQ(region.getBlocks().size(), 2u);
- ASSERT_EQ(region.back().getNumArguments(), 1u);
-
- IRRewriter rewriter(&context);
- EXPECT_TRUE(succeeded(runRegionDCE(rewriter, container->getRegions())));
- EXPECT_EQ(region.back().getNumArguments(), 0u);
- EXPECT_EQ(region.front().getTerminator()->getNumOperands(), 0u);
- EXPECT_EQ(region.back().getTerminator()->getNumOperands(), 0u);
-}
-} // namespace
More information about the Mlir-commits
mailing list