diff --git a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td --- a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td +++ b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td @@ -74,15 +74,17 @@ } def SparseTensor_ConvertOp : SparseTensor_Op<"convert", - [NoSideEffect, SameOperandsAndResultType]>, + [NoSideEffect, SameOperandsAndResultElementType]>, Arguments<(ins AnyTensor:$source)>, Results<(outs AnyTensor:$dest)> { string summary = "Converts between different tensor types"; string description = [{ Converts one sparse or dense tensor type to another tensor type. The rank - and dimensions of the source and destination types must match, but the sparse - encoding of these types can obviously be different. The name `convert` was - preferred over `cast`, since the operation may incur a non-trivial cost. + of the source and destination types must match exactly, and the dimension + sizes must either match exactly or relax from a static to a dynamic size. + The sparse encoding of the two types can obviously be completely different. + The name `convert` was preferred over `cast`, since the operation may incur + a non-trivial cost. When converting between two different sparse tensor types, only explicitly stored values are moved from one underlying sparse storage format to diff --git a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp --- a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp +++ b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp @@ -237,7 +237,8 @@ static LogicalResult verify(ConvertOp op) { if (auto tp1 = op.source().getType().dyn_cast()) { if (auto tp2 = op.dest().getType().dyn_cast()) { - assert(tp1.getRank() == tp2.getRank()); + if (tp1.getRank() != tp2.getRank()) + return op.emitError("unexpected conversion mismatch in rank"); auto shape1 = tp1.getShape(); auto shape2 = tp2.getShape(); // Accept size matches between the source and the destination type diff --git a/mlir/test/Dialect/SparseTensor/invalid.mlir b/mlir/test/Dialect/SparseTensor/invalid.mlir --- a/mlir/test/Dialect/SparseTensor/invalid.mlir +++ b/mlir/test/Dialect/SparseTensor/invalid.mlir @@ -160,9 +160,19 @@ // ----- +#DCSR = #sparse_tensor.encoding<{dimLevelType = ["compressed", "compressed"]}> + +func @sparse_convert_rank_mismatch(%arg0: tensor<10x10xf64, #DCSR>) -> tensor { + // expected-error@+1 {{unexpected conversion mismatch in rank}} + %0 = sparse_tensor.convert %arg0 : tensor<10x10xf64, #DCSR> to tensor + return %0 : tensor +} + +// ----- + #CSR = #sparse_tensor.encoding<{dimLevelType = ["dense", "compressed"]}> -func @sparse_convert_mismatch(%arg0: tensor<10x?xf32>) -> tensor<10x10xf32, #CSR> { +func @sparse_convert_dim_mismatch(%arg0: tensor<10x?xf32>) -> tensor<10x10xf32, #CSR> { // expected-error@+1 {{unexpected conversion mismatch in dimension 1}} %0 = sparse_tensor.convert %arg0 : tensor<10x?xf32> to tensor<10x10xf32, #CSR> return %0 : tensor<10x10xf32, #CSR>