[llvm-branch-commits] [mlir] [mlir][UB] Erase ops that precede `ub.unreachable` (PR #179104)
Matthias Springer via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Feb 1 04:32:37 PST 2026
https://github.com/matthias-springer created https://github.com/llvm/llvm-project/pull/179104
Erase ops that precede `ub.unreachable` if they must progress, i.e., it's guaranteed that their next operation is reached.
Depends on #179039.
>From d5711dd0c64bd90d866bf78a3f9beb70afda2773 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Sun, 1 Feb 2026 12:29:56 +0000
Subject: [PATCH] [mlir][UB] Erase ops that precede `ub.unreachable`
---
mlir/include/mlir/Dialect/UB/IR/UBOps.td | 1 +
mlir/lib/Dialect/UB/IR/UBOps.cpp | 37 ++++++++++++++++++++++++
mlir/test/Dialect/UB/canonicalize.mlir | 25 ++++++++++++++++
3 files changed, 63 insertions(+)
diff --git a/mlir/include/mlir/Dialect/UB/IR/UBOps.td b/mlir/include/mlir/Dialect/UB/IR/UBOps.td
index 1bff39add691e..95c52db404912 100644
--- a/mlir/include/mlir/Dialect/UB/IR/UBOps.td
+++ b/mlir/include/mlir/Dialect/UB/IR/UBOps.td
@@ -84,6 +84,7 @@ def UnreachableOp : UB_Op<"unreachable", [Terminator]> {
}];
let assemblyFormat = "attr-dict";
+ let hasCanonicalizeMethod = 1;
}
#endif // MLIR_DIALECT_UB_IR_UBOPS_TD
diff --git a/mlir/lib/Dialect/UB/IR/UBOps.cpp b/mlir/lib/Dialect/UB/IR/UBOps.cpp
index 9c8ad2ddb2c6a..66dfceaffc6dd 100644
--- a/mlir/lib/Dialect/UB/IR/UBOps.cpp
+++ b/mlir/lib/Dialect/UB/IR/UBOps.cpp
@@ -59,8 +59,45 @@ Operation *UBDialect::materializeConstant(OpBuilder &builder, Attribute value,
return nullptr;
}
+//===----------------------------------------------------------------------===//
+// PoisonOp
+//===----------------------------------------------------------------------===//
+
OpFoldResult PoisonOp::fold(FoldAdaptor /*adaptor*/) { return getValue(); }
+//===----------------------------------------------------------------------===//
+// UnreachableOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult UnreachableOp::canonicalize(UnreachableOp unreachableOp,
+ PatternRewriter &rewriter) {
+ // Erase operations that precede ub.unreachable (if they must progress).
+ Block *block = unreachableOp->getBlock();
+ if (llvm::hasSingleElement(*block))
+ return rewriter.notifyMatchFailure(
+ unreachableOp, "unreachable op is the only operation in the block");
+
+ // Erase all other operations in the block. They must be dead.
+ auto it = unreachableOp->getIterator();
+ --it;
+ bool reachedBegin = false;
+ bool changed = false;
+ do {
+ Operation *op = &*it;
+ // Do not erase ops that may not progress (and ops that precede them).
+ if (!mustProgress(op))
+ break;
+ reachedBegin = it == block->begin();
+ if (!reachedBegin)
+ --it;
+ rewriter.eraseOp(op);
+ changed = true;
+ if (reachedBegin)
+ break;
+ } while (!reachedBegin);
+ return success(changed);
+}
+
#include "mlir/Dialect/UB/IR/UBOpsInterfaces.cpp.inc"
#define GET_ATTRDEF_CLASSES
diff --git a/mlir/test/Dialect/UB/canonicalize.mlir b/mlir/test/Dialect/UB/canonicalize.mlir
index c3f286e49b09b..bd8cc99449b7e 100644
--- a/mlir/test/Dialect/UB/canonicalize.mlir
+++ b/mlir/test/Dialect/UB/canonicalize.mlir
@@ -9,3 +9,28 @@ func.func @merge_poison() -> (i32, i32) {
%1 = ub.poison : i32
return %0, %1 : i32, i32
}
+
+// -----
+
+// CHECK-LABEL: func @drop_ops_before_unreachable(
+// CHECK-NEXT: arith.constant
+// CHECK-NEXT: arith.constant
+// CHECK-NEXT: arith.constant
+// CHECK-NEXT: vector.print
+// CHECK-NEXT: scf.for {{.*}} {
+// CHECK-NEXT: vector.print
+// CHECK-NEXT: }
+// CHECK-NEXT: ub.unreachable
+func.func @drop_ops_before_unreachable(%arg0: i32) {
+ %lb = arith.constant 3 : index
+ %ub = arith.constant 4 : index
+ %step = arith.constant 0 : index
+ vector.print %arg0 : i32
+ // Infinite loop that may not progress. Such ops (and everything before)
+ // is not erased.
+ scf.for %iv = %lb to %ub step %step {
+ vector.print %arg0 : i32
+ } {mustProgress = false}
+ vector.print %arg0 : i32
+ ub.unreachable
+}
More information about the llvm-branch-commits
mailing list