[Mlir-commits] [mlir] [mlir][tosa] Prevent creation of `tosa.concat_shape` for scalar shape values (PR #176120)

Luke Hutton llvmlistbot at llvm.org
Wed Feb 4 06:39:33 PST 2026


https://github.com/lhutton1 updated https://github.com/llvm/llvm-project/pull/176120

>From e3e11df18d2b891baaffd259ae63f46d088c726e Mon Sep 17 00:00:00 2001
From: Luke Hutton <luke.hutton at arm.com>
Date: Wed, 14 Jan 2026 14:27:20 +0000
Subject: [PATCH] [mlir][tosa] Prevent creation of `tosa.concat_shape` for
 scalar shape values

Updates `tosa.concat_shape` inline with the following specification change:
https://github.com/arm/tosa-specification/pull/30.

Change-Id: I2f353a48169382cf08ca96eeb556f1f9019fbdad
---
 mlir/lib/Dialect/Tosa/IR/TosaOps.cpp    |  9 ++++++++
 mlir/test/Dialect/Tosa/level_check.mlir | 28 -------------------------
 mlir/test/Dialect/Tosa/ops.mlir         | 10 ---------
 mlir/test/Dialect/Tosa/verifier.mlir    | 19 +++++++++++++++++
 4 files changed, 28 insertions(+), 38 deletions(-)

diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index 5438cd73aef54..b841a4b088c39 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -4913,6 +4913,15 @@ LogicalResult tosa::ConcatShapeOp::verify() {
       cast<tosa::shapeType>(getResult().getType());
   const int64_t outputRank = outShapeType.getRank();
   const Operation::operand_range inputList = getInput();
+
+  if (inputList.size() == 0)
+    return emitOpError("requires at least one input shape");
+
+  if (llvm::any_of(inputList, [](Value v) {
+        return cast<tosa::shapeType>(v.getType()).getRank() == 0;
+      }))
+    return emitOpError("requires all inputs shapes have a rank greater than 0");
+
   const int64_t inputsRank =
       llvm::accumulate(inputList, 0, [](int64_t acc, const Value &input) {
         const tosa::shapeType inShapeType =
diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir
index 216f05a484927..739af6bcac2d8 100644
--- a/mlir/test/Dialect/Tosa/level_check.mlir
+++ b/mlir/test/Dialect/Tosa/level_check.mlir
@@ -1693,34 +1693,6 @@ func.func @test_dim(%arg0: tensor<1x2x3x4x5x6x7x8xi32>) -> !tosa.shape<1> {
 
 // -----
 
-func.func @test_concat_shape_invalid_list_size() {
-  %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
-  // expected-error at +1 {{'tosa.concat_shape' op failed level check: length(tensor_list_shape(input)) <= MAX_TENSOR_LIST_SIZE (64), got 65}}
-  %1 = tosa.concat_shape %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0, %0, %0, %0, %0, %0, %0, %0,
-                         %0 :
-                         (
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>,
-                          !tosa.shape<0>
-                         ) -> !tosa.shape<0>
-  return
-}
-
-// -----
-
 func.func @test_exp2_shape_invalid_rank() -> !tosa.shape<17> {
   %0 = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
   // expected-error at +1 {{'tosa.exp2_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
diff --git a/mlir/test/Dialect/Tosa/ops.mlir b/mlir/test/Dialect/Tosa/ops.mlir
index 44cfd5cfc9400..56811891e8f95 100644
--- a/mlir/test/Dialect/Tosa/ops.mlir
+++ b/mlir/test/Dialect/Tosa/ops.mlir
@@ -1499,16 +1499,6 @@ func.func @test_concat_shape() -> !tosa.shape<5> {
   return %3 : !tosa.shape<5>
 }
 
-// -----
-// CHECK-LABEL: test_concat_shape_rank_0
-func.func @test_concat_shape_rank_0() -> !tosa.shape<0> {
-  %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
-  %1 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
-  %2 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
-  %3 = tosa.concat_shape %0, %1, %2 : (!tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>) -> !tosa.shape<0>
-  return %3 : !tosa.shape<0>
-}
-
 // -----
 // CHECK-LABEL: test_slice_shape
 func.func @test_slice_shape() -> !tosa.shape<3> {
diff --git a/mlir/test/Dialect/Tosa/verifier.mlir b/mlir/test/Dialect/Tosa/verifier.mlir
index 742bae3847da5..3621c25005862 100644
--- a/mlir/test/Dialect/Tosa/verifier.mlir
+++ b/mlir/test/Dialect/Tosa/verifier.mlir
@@ -1284,6 +1284,25 @@ func.func @test_concat_shape_rank_mismatch() -> !tosa.shape<4> {
 
 // -----
 
+func.func @test_concat_shape_no_inputs() -> !tosa.shape<0> {
+  // expected-error at +1 {{'tosa.concat_shape' op requires at least one input shape}}
+  %0 = tosa.concat_shape {} : () -> !tosa.shape<0>
+  return %0 : !tosa.shape<0>
+}
+
+// -----
+
+func.func @test_concat_shape_rank_0() -> !tosa.shape<0> {
+  %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
+  %1 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
+  %2 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
+  // expected-error at +1 {{'tosa.concat_shape' op requires all inputs shapes have a rank greater than 0}}
+  %3 = tosa.concat_shape %0, %1, %2 : (!tosa.shape<0>, !tosa.shape<0>, !tosa.shape<0>) -> !tosa.shape<0>
+  return %3 : !tosa.shape<0>
+}
+
+// -----
+
 func.func @test_slice_shape_negative_start() -> !tosa.shape<3> {
   %0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6>
   %1 = "tosa.const"() {values = dense<-1> : tensor<1xi32>} : () -> tensor<1xi32>



More information about the Mlir-commits mailing list