[Mlir-commits] [mlir] [mlir][sparse] Fix crash in sparse_tensor.new with unsupported element type (PR #183898)
Mehdi Amini
llvmlistbot at llvm.org
Sat Feb 28 03:14:54 PST 2026
https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/183898
sparse_tensor.new with an element type not supported by the sparse tensor runtime library (e.g. `index`) would call primaryTypeEncoding(), which hits an llvm_unreachable("Unknown primary type"). The runtime library only supports fixed-width types (f64/f32/f16/bf16, i64/i32/i16/i8, and complex<f32/f64>); platform-dependent types such as `index` have no corresponding PrimaryType encoding.
Fix by adding an isValidPrimaryType() helper and checking it in SparseTensorNewConverter::matchAndRewrite() before calling genReader(), so the conversion fails gracefully instead of crashing.
Fixes #180310
>From 7a5dd5c37015681aeb0e7f90ad12df0e8b83be37 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 28 Feb 2026 03:03:29 -0800
Subject: [PATCH] [mlir][sparse] Fix crash in sparse_tensor.new with
unsupported element type
sparse_tensor.new with an element type not supported by the sparse tensor
runtime library (e.g. `index`) would call primaryTypeEncoding(), which
hits an llvm_unreachable("Unknown primary type"). The runtime library
only supports fixed-width types (f64/f32/f16/bf16, i64/i32/i16/i8, and
complex<f32/f64>); platform-dependent types such as `index` have no
corresponding PrimaryType encoding.
Fix by adding an isValidPrimaryType() helper and checking it in
SparseTensorNewConverter::matchAndRewrite() before calling genReader(),
so the conversion fails gracefully instead of crashing.
Fixes #180310
---
.../Transforms/SparseTensorConversion.cpp | 3 +++
.../SparseTensor/Transforms/Utils/CodegenUtils.cpp | 12 ++++++++++++
.../SparseTensor/Transforms/Utils/CodegenUtils.h | 5 +++++
.../Dialect/SparseTensor/conversion_invalid.mlir | 14 ++++++++++++++
4 files changed, 34 insertions(+)
create mode 100644 mlir/test/Dialect/SparseTensor/conversion_invalid.mlir
diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp
index 0e88d31dae8e8..c9bcefe92de79 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp
@@ -383,6 +383,9 @@ class SparseTensorNewConverter : public OpConversionPattern<NewOp> {
const auto stt = getSparseTensorType(op);
if (!stt.hasEncoding())
return failure();
+ // Verify that the element type is supported by the runtime library.
+ if (!isValidPrimaryType(stt.getElementType()))
+ return rewriter.notifyMatchFailure(op, "unsupported element type");
// Construct the `reader` opening method calls.
SmallVector<Value> dimSizesValues;
Value dimSizesBuffer;
diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.cpp
index f57f7f7fc0946..ffc898c9933c3 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.cpp
@@ -99,6 +99,18 @@ StringRef mlir::sparse_tensor::overheadTypeFunctionSuffix(Type tp) {
return overheadTypeFunctionSuffix(overheadTypeEncoding(tp));
}
+bool mlir::sparse_tensor::isValidPrimaryType(Type elemTp) {
+ if (elemTp.isF64() || elemTp.isF32() || elemTp.isF16() || elemTp.isBF16() ||
+ elemTp.isInteger(64) || elemTp.isInteger(32) || elemTp.isInteger(16) ||
+ elemTp.isInteger(8))
+ return true;
+ if (auto complexTp = dyn_cast<ComplexType>(elemTp)) {
+ Type elt = complexTp.getElementType();
+ return elt.isF64() || elt.isF32();
+ }
+ return false;
+}
+
PrimaryType mlir::sparse_tensor::primaryTypeEncoding(Type elemTp) {
if (elemTp.isF64())
return PrimaryType::kF64;
diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.h b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.h
index 1c10dd5566184..98e351a371ac1 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.h
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.h
@@ -60,6 +60,11 @@ StringRef overheadTypeFunctionSuffix(OverheadType ot);
/// Converts an overhead storage type to its function-name suffix.
StringRef overheadTypeFunctionSuffix(Type overheadTp);
+/// Returns true if the given type is a valid sparse tensor element type
+/// supported by the runtime library (i.e., maps to a PrimaryType).
+/// Use this to guard calls to primaryTypeEncoding() with invalid types.
+bool isValidPrimaryType(Type elemTp);
+
/// Converts a primary storage type to its internal type-encoding.
PrimaryType primaryTypeEncoding(Type elemTp);
diff --git a/mlir/test/Dialect/SparseTensor/conversion_invalid.mlir b/mlir/test/Dialect/SparseTensor/conversion_invalid.mlir
new file mode 100644
index 0000000000000..456c1898a9311
--- /dev/null
+++ b/mlir/test/Dialect/SparseTensor/conversion_invalid.mlir
@@ -0,0 +1,14 @@
+// RUN: mlir-opt %s --sparse-tensor-conversion -verify-diagnostics -split-input-file
+
+// Regression test for https://github.com/llvm/llvm-project/issues/180310:
+// sparse_tensor.new with an unsupported element type (e.g. index) must not
+// crash with llvm_unreachable in primaryTypeEncoding; the conversion should
+// fail gracefully.
+
+#sparse = #sparse_tensor.encoding<{ map = (d0) -> (d0 : compressed) }>
+
+func.func @new_index_elem_type(%arg0: index) {
+ // expected-error at +1 {{failed to legalize operation 'sparse_tensor.new'}}
+ %0 = sparse_tensor.new %arg0 : index to tensor<?xindex, #sparse>
+ return
+}
More information about the Mlir-commits
mailing list