[Mlir-commits] [mlir] [mlir][Tosa] Handle empty block-scaled reshape shapes (PR #220872)
Mehdi Amini
llvmlistbot at llvm.org
Thu Sep 3 04:06:49 PDT 2026
https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/220872
Guard the inferred scale shape before accessing its last dimension, and reject rank-zero block-scaled reshape shapes before the unranked-input early exit. Preserve dynamic scale dimensions instead of applying block-size arithmetic to their sentinel.
Found by Coverity.
Assisted-by: Codex
>From aa676630f2bbc2b59bd7a1192651e01fe85f11c2 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Wed, 2 Sep 2026 15:25:24 -0700
Subject: [PATCH] [mlir][Tosa] Handle empty block-scaled reshape shapes
Guard the inferred scale shape before accessing its last dimension, and
reject rank-zero block-scaled reshape shapes before the unranked-input
early exit. Preserve dynamic scale dimensions instead of applying block-size
arithmetic to their sentinel.
Valgrind exposed the pre-fix assertion failure:
mlir-opt: llvm/ADT/SmallVector.h:318: back(): Assertion `!empty()`
failed.
#12 mlir::tosa::ReshapeBlockScaledOp::inferReturnTypes(...)
==569000== Process terminating with default action of signal 6 (SIGABRT)
==569000== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Found by Coverity.
Assisted-by: Codex
---
mlir/lib/Dialect/Tosa/IR/TosaOps.cpp | 17 ++++++++++-------
mlir/test/Dialect/Tosa/verifier.mlir | 9 +++++++++
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index 7d4d4f0d27a84..c4117d95fed11 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -3192,7 +3192,8 @@ LogicalResult tosa::ReshapeBlockScaledOp::inferReturnTypeComponents(
llvm::SmallVector<int64_t> newScaleShapeValue;
if (numInputs == 2) {
newScaleShapeValue.assign(newShapeValue.begin(), newShapeValue.end());
- if (ShapedType::isStatic(newScaleShapeValue.back()))
+ if (!newScaleShapeValue.empty() &&
+ ShapedType::isStatic(newScaleShapeValue.back()))
newScaleShapeValue.back() /= blockSize;
}
@@ -3203,7 +3204,8 @@ LogicalResult tosa::ReshapeBlockScaledOp::inferReturnTypeComponents(
for (size_t idx = 0; idx < newShapeValue.size(); idx++) {
if (ShapedType::isDynamic(newScaleShapeValue[idx])) {
newScaleShapeValue[idx] = newShapeValue[idx];
- if (idx == (newShapeValue.size() - 1))
+ if (idx + 1 == newShapeValue.size() &&
+ ShapedType::isStatic(newScaleShapeValue[idx]))
newScaleShapeValue[idx] /= blockSize;
}
}
@@ -3234,10 +3236,14 @@ llvm::LogicalResult tosa::ReshapeBlockScaledOp::verify() {
return failure();
}
+ const uint32_t blockSize = BlockSizeAttr::getBlockSizeValue(getBlockSize());
+ if (inputList.size() == 2 &&
+ cast<tosa::shapeType>(getNewValueShape().getType()).getRank() == 0)
+ return emitOpError("requires new shape to have a rank greater than 0");
+
const auto inputType = llvm::cast<ShapedType>(inputList[0].getType());
if (!inputType.hasRank())
return success();
- const uint32_t blockSize = BlockSizeAttr::getBlockSizeValue(getBlockSize());
if (inputList.size() == 2) {
if (blockSize != BlockSizeAttr::getBlockSizeValue(BlockSize::BLOCK_SIZE_32))
@@ -3302,7 +3308,7 @@ llvm::LogicalResult tosa::ReshapeBlockScaledOp::verify() {
return emitOpError("expect block size to be 1, got ") << blockSize;
}
- // Get the new value shape dimension values
+ // Get the new value shape dimension values.
SmallVector<int64_t> shapeValues;
if (!tosa::getConstShapeValues(getNewValueShape().getDefiningOp(),
shapeValues)) {
@@ -3311,9 +3317,6 @@ llvm::LogicalResult tosa::ReshapeBlockScaledOp::verify() {
}
if (inputList.size() == 2) {
- if (static_cast<int64_t>(shapeValues.size()) == 0)
- return emitOpError("requires new shape to have a rank greater than 0");
-
const int64_t lastShapeDim = shapeValues.back();
if (ShapedType::isStatic(lastShapeDim) && lastShapeDim % blockSize != 0)
return emitOpError("expect last dimension of new shape (")
diff --git a/mlir/test/Dialect/Tosa/verifier.mlir b/mlir/test/Dialect/Tosa/verifier.mlir
index 803ded01698a1..cd71fffbe9962 100644
--- a/mlir/test/Dialect/Tosa/verifier.mlir
+++ b/mlir/test/Dialect/Tosa/verifier.mlir
@@ -2268,6 +2268,15 @@ func.func @test_reshape_block_scaled_rank0_scale_input(%arg0 : tensor<64xf8E4M3F
// -----
+func.func @test_reshape_block_scaled_rank0_shape_unranked_inputs(%arg0 : tensor<*xf8E4M3FN>, %arg1 : tensor<*xf8E8M0FNU>) -> () {
+ %s = tosa.const_shape {values = dense<> : tensor<0xindex>} : () -> !tosa.shape<0>
+ // expected-error at +1 {{'tosa.reshape_block_scaled' op requires new shape to have a rank greater than 0}}
+ %0:2 = "tosa.reshape_block_scaled"(%arg0, %arg1, %s) {block_size = #tosa.block_size<BLOCK_SIZE_32> : i32} : (tensor<*xf8E4M3FN>, tensor<*xf8E8M0FNU>, !tosa.shape<0>) -> (tensor<*xf8E4M3FN>, tensor<*xf8E8M0FNU>)
+ return
+}
+
+// -----
+
func.func @test_reshape_non_block_scaled_block_size_mismatch(%arg0: tensor<13x21x3xf32>) -> tensor<1x819xf32> {
%s = tosa.const_shape {values = dense<[1, 819]> : tensor<2xindex>} : () -> !tosa.shape<2>
// expected-error at +1 {{'tosa.reshape_block_scaled' op expect block size to be 1, got 32}}
More information about the Mlir-commits
mailing list