[Mlir-commits] [mlir] [mlir][UB] Add `ub.unreachable` operation (PR #169872)
Matthias Springer
llvmlistbot at llvm.org
Fri Nov 28 02:13:54 PST 2025
https://github.com/matthias-springer updated https://github.com/llvm/llvm-project/pull/169872
>From a47b28cf95f5fca857184f05f0c3840b24e470d5 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Fri, 28 Nov 2025 04:25:38 +0000
Subject: [PATCH 1/2] [mlir][UB] Add `ub.unreachable` operation
---
mlir/include/mlir/Dialect/UB/IR/UBOps.td | 20 +++++++++++
mlir/lib/Conversion/UBToLLVM/UBToLLVM.cpp | 35 +++++++++++++++----
mlir/lib/Conversion/UBToSPIRV/UBToSPIRV.cpp | 14 +++++++-
mlir/test/Conversion/UBToLLVM/ub-to-llvm.mlir | 6 ++++
.../Conversion/UBToSPIRV/ub-to-spirv.mlir | 15 ++++++++
mlir/test/Dialect/UB/ops.mlir | 6 ++++
6 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/mlir/include/mlir/Dialect/UB/IR/UBOps.td b/mlir/include/mlir/Dialect/UB/IR/UBOps.td
index c400a2ef2cc7a..8a354da2db10c 100644
--- a/mlir/include/mlir/Dialect/UB/IR/UBOps.td
+++ b/mlir/include/mlir/Dialect/UB/IR/UBOps.td
@@ -66,4 +66,24 @@ def PoisonOp : UB_Op<"poison", [ConstantLike, Pure]> {
let hasFolder = 1;
}
+//===----------------------------------------------------------------------===//
+// UnreachableOp
+//===----------------------------------------------------------------------===//
+
+def UnreachableOp : UB_Op<"unreachable", [Terminator]> {
+ let summary = "Unreachable operation.";
+ let description = [{
+ The `unreachable` operation has no defined semantics. This operation
+ indicates that its enclosing basic block is not reachable.
+
+ Example:
+
+ ```
+ ub.unreachable
+ ```
+ }];
+
+ let assemblyFormat = "attr-dict";
+}
+
#endif // MLIR_DIALECT_UB_IR_UBOPS_TD
diff --git a/mlir/lib/Conversion/UBToLLVM/UBToLLVM.cpp b/mlir/lib/Conversion/UBToLLVM/UBToLLVM.cpp
index 9921a06778dd7..feb04899cb33d 100644
--- a/mlir/lib/Conversion/UBToLLVM/UBToLLVM.cpp
+++ b/mlir/lib/Conversion/UBToLLVM/UBToLLVM.cpp
@@ -23,8 +23,11 @@ namespace mlir {
using namespace mlir;
-namespace {
+//===----------------------------------------------------------------------===//
+// PoisonOpLowering
+//===----------------------------------------------------------------------===//
+namespace {
struct PoisonOpLowering : public ConvertOpToLLVMPattern<ub::PoisonOp> {
using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;
@@ -32,13 +35,8 @@ struct PoisonOpLowering : public ConvertOpToLLVMPattern<ub::PoisonOp> {
matchAndRewrite(ub::PoisonOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override;
};
-
} // namespace
-//===----------------------------------------------------------------------===//
-// PoisonOpLowering
-//===----------------------------------------------------------------------===//
-
LogicalResult
PoisonOpLowering::matchAndRewrite(ub::PoisonOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const {
@@ -60,6 +58,29 @@ PoisonOpLowering::matchAndRewrite(ub::PoisonOp op, OpAdaptor adaptor,
return success();
}
+//===----------------------------------------------------------------------===//
+// UnreachableOpLowering
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct UnreachableOpLowering
+ : public ConvertOpToLLVMPattern<ub::UnreachableOp> {
+ using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;
+
+ LogicalResult
+ matchAndRewrite(ub::UnreachableOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override;
+};
+} // namespace
+LogicalResult
+
+UnreachableOpLowering::matchAndRewrite(
+ ub::UnreachableOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const {
+ rewriter.replaceOpWithNewOp<LLVM::UnreachableOp>(op);
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// Pass Definition
//===----------------------------------------------------------------------===//
@@ -93,7 +114,7 @@ struct UBToLLVMConversionPass
void mlir::ub::populateUBToLLVMConversionPatterns(
const LLVMTypeConverter &converter, RewritePatternSet &patterns) {
- patterns.add<PoisonOpLowering>(converter);
+ patterns.add<PoisonOpLowering, UnreachableOpLowering>(converter);
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Conversion/UBToSPIRV/UBToSPIRV.cpp b/mlir/lib/Conversion/UBToSPIRV/UBToSPIRV.cpp
index 244d214cba196..3831387816eaf 100644
--- a/mlir/lib/Conversion/UBToSPIRV/UBToSPIRV.cpp
+++ b/mlir/lib/Conversion/UBToSPIRV/UBToSPIRV.cpp
@@ -40,6 +40,17 @@ struct PoisonOpLowering final : OpConversionPattern<ub::PoisonOp> {
}
};
+struct UnreachableOpLowering final : OpConversionPattern<ub::UnreachableOp> {
+ using Base::Base;
+
+ LogicalResult
+ matchAndRewrite(ub::UnreachableOp op, OpAdaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ rewriter.replaceOpWithNewOp<spirv::UnreachableOp>(op);
+ return success();
+ }
+};
+
} // namespace
//===----------------------------------------------------------------------===//
@@ -75,5 +86,6 @@ struct UBToSPIRVConversionPass final
void mlir::ub::populateUBToSPIRVConversionPatterns(
const SPIRVTypeConverter &converter, RewritePatternSet &patterns) {
- patterns.add<PoisonOpLowering>(converter, patterns.getContext());
+ patterns.add<PoisonOpLowering, UnreachableOpLowering>(converter,
+ patterns.getContext());
}
diff --git a/mlir/test/Conversion/UBToLLVM/ub-to-llvm.mlir b/mlir/test/Conversion/UBToLLVM/ub-to-llvm.mlir
index 6c0b111d4c2c5..0fe63f5a3a89f 100644
--- a/mlir/test/Conversion/UBToLLVM/ub-to-llvm.mlir
+++ b/mlir/test/Conversion/UBToLLVM/ub-to-llvm.mlir
@@ -17,3 +17,9 @@ func.func @check_poison() {
%3 = ub.poison : !llvm.ptr
return
}
+
+// CHECK-LABEL: @check_unrechable
+func.func @check_unrechable() {
+// CHECK: llvm.unreachable
+ ub.unreachable
+}
diff --git a/mlir/test/Conversion/UBToSPIRV/ub-to-spirv.mlir b/mlir/test/Conversion/UBToSPIRV/ub-to-spirv.mlir
index f497eb3bc552c..edbe8b8001bba 100644
--- a/mlir/test/Conversion/UBToSPIRV/ub-to-spirv.mlir
+++ b/mlir/test/Conversion/UBToSPIRV/ub-to-spirv.mlir
@@ -19,3 +19,18 @@ func.func @check_poison() {
}
}
+
+// -----
+
+// No successful test because the dialect conversion framework does not convert
+// unreachable blocks.
+
+module attributes {
+ spirv.target_env = #spirv.target_env<
+ #spirv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Shader], []>, #spirv.resource_limits<>>
+} {
+func.func @check_unrechable() {
+// expected-error at +1{{cannot be used in reachable block}}
+ spirv.Unreachable
+}
+}
diff --git a/mlir/test/Dialect/UB/ops.mlir b/mlir/test/Dialect/UB/ops.mlir
index 724b6b4caac5d..730c1bd1380b8 100644
--- a/mlir/test/Dialect/UB/ops.mlir
+++ b/mlir/test/Dialect/UB/ops.mlir
@@ -38,3 +38,9 @@ func.func @poison_tensor() -> tensor<8x?xf64> {
%0 = ub.poison : tensor<8x?xf64>
return %0 : tensor<8x?xf64>
}
+
+// CHECK-LABEL: func @unreachable()
+// CHECK: ub.unreachable
+func.func @unreachable() {
+ ub.unreachable
+}
>From e0ec74421b1f0c07ce3d06f57b7ed90f631a0090 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Fri, 28 Nov 2025 19:13:45 +0900
Subject: [PATCH 2/2] Update mlir/include/mlir/Dialect/UB/IR/UBOps.td
Co-authored-by: Mehdi Amini <joker.eph at gmail.com>
---
mlir/include/mlir/Dialect/UB/IR/UBOps.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/UB/IR/UBOps.td b/mlir/include/mlir/Dialect/UB/IR/UBOps.td
index 8a354da2db10c..891591e4f9331 100644
--- a/mlir/include/mlir/Dialect/UB/IR/UBOps.td
+++ b/mlir/include/mlir/Dialect/UB/IR/UBOps.td
@@ -73,7 +73,7 @@ def PoisonOp : UB_Op<"poison", [ConstantLike, Pure]> {
def UnreachableOp : UB_Op<"unreachable", [Terminator]> {
let summary = "Unreachable operation.";
let description = [{
- The `unreachable` operation has no defined semantics. This operation
+ The `unreachable` operation triggers immediate undefined behavior if executed. This operation
indicates that its enclosing basic block is not reachable.
Example:
More information about the Mlir-commits
mailing list