diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp index 798fc360d8439..33b71b320b490 100644 --- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp +++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp @@ -2250,31 +2250,85 @@ LogicalResult tosa::SliceOp::inferReturnTypeComponents( } LogicalResult tosa::SliceOp::verify() { - if (verifySameElementTypes(*this, /* inType = */ getInput1().getType(), - /* outType = */ getOutput().getType()) + const Value input = getInput1(); + const Value output = getOutput(); + if (verifySameElementTypes(*this, /* inType = */ input.getType(), + /* outType = */ output.getType()) .failed()) return failure(); - const ShapeAdaptor inputShape(getInput1().getType()); + const Value start = getStart(); + const Value size = getSize(); + const ShapeAdaptor inputShape(input.getType()); + const ShapeAdaptor outputShape(output.getType()); + if (inputShape.hasRank()) { const auto inputRank = inputShape.getRank(); - const ShapeAdaptor outputShape(getOutput().getType()); if (outputShape.hasRank() && inputRank != outputShape.getRank()) return emitOpError( "expect input1 and output to have the same ranks, got ") << inputRank << " and " << outputShape.getRank(); const auto startShapeRank = - llvm::cast(getStart().getType()).getRank(); + llvm::cast(start.getType()).getRank(); if (inputRank != startShapeRank) return emitOpError("length of start is not equal to rank of input shape"); const auto sizeShapeRank = - llvm::cast(getSize().getType()).getRank(); + llvm::cast(size.getType()).getRank(); if (inputRank != sizeShapeRank) return emitOpError("length of size is not equal to rank of input shape"); } + constexpr int64_t kInferableDimSize = -1; + + SmallVector startValues; + tosa::getConstShapeValues(start.getDefiningOp(), startValues); + if (startValues.size()) { + if (llvm::any_of(startValues, [](const int64_t v) { + return v < 0 && v != kInferableDimSize; + })) + return emitOpError("start values must be non-negative, got [") + << startValues << "]"; + } + + SmallVector sizeValues; + if (!tosa::getConstShapeValues(size.getDefiningOp(), sizeValues)) + return success(); + + if (llvm::any_of(sizeValues, [](const int64_t v) { + return v <= 0 && v != kInferableDimSize; + })) + return emitOpError("size values must be > 0, got [") << sizeValues << "]"; + if (outputShape.hasRank()) { + SmallVector outputDims; + outputShape.getDims(outputDims); + const bool hasNoInferableDims = llvm::all_of( + sizeValues, [](const int64_t v) { return v != kInferableDimSize; }); + if (hasNoInferableDims && + failed(verifyCompatibleShape(outputDims, sizeValues))) + return emitOpError("expected output shape to match size values, got ") + << output.getType() << " vs [" << sizeValues << "]"; + } + + if (inputShape.hasRank() && startValues.size()) { + SmallVector inputDims; + inputShape.getDims(inputDims); + for (const auto &[index, vals] : + llvm::enumerate(llvm::zip_equal(startValues, sizeValues, inputDims))) { + const auto &[start, size, inputDim] = vals; + if (start == kInferableDimSize || size == kInferableDimSize || + ShapedType::isDynamic(inputDim)) + continue; + if (start + size > inputDim) + return emitOpError("start + size must be less than or equal to input " + "dimension size, got start=") + << start << ", size=" << size + << " vs input dim size=" << inputDim << " at dimension " + << index; + } + } + return success(); } diff --git a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor-invalid.mlir b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor-invalid.mlir index 61dcb574e03a8..3e7c72c974bbf 100644 --- a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor-invalid.mlir +++ b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor-invalid.mlir @@ -2,9 +2,9 @@ // CHECK-LABEL: @slice_resultType_unranked func.func @slice_resultType_unranked(%arg0: tensor) -> (tensor<*xf32>) { - %0 = tosa.const_shape {values = dense<2> : tensor<1xindex>} : () -> !tosa.shape<1> - %1 = tosa.const_shape {values = dense<0> : tensor<1xindex>} : () -> !tosa.shape<1> + %size = tosa.const_shape {values = dense<2> : tensor<1xindex>} : () -> !tosa.shape<1> + %start = tosa.const_shape {values = dense<0> : tensor<1xindex>} : () -> !tosa.shape<1> // expected-error@+1 {{failed to legalize operation 'tosa.slice'}} - %2 = tosa.slice %arg0, %0, %1 : (tensor, !tosa.shape<1>, !tosa.shape<1>) -> tensor<*xf32> + %2 = tosa.slice %arg0, %start, %size : (tensor, !tosa.shape<1>, !tosa.shape<1>) -> tensor<*xf32> return %2 : tensor<*xf32> } diff --git a/mlir/test/Dialect/Tosa/availability.mlir b/mlir/test/Dialect/Tosa/availability.mlir index 6ef8b3e6133be..d87a041648630 100644 --- a/mlir/test/Dialect/Tosa/availability.mlir +++ b/mlir/test/Dialect/Tosa/availability.mlir @@ -545,11 +545,11 @@ func.func @test_reverse(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { // ----- // CHECK-LABEL: slice func.func @test_slice(%arg0: tensor<13x21x3xf32>) -> tensor<4x11x1xf32> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // CHECK: profiles: [ [pro_int, pro_fp] ] // CHECK: extensions: [ [fp8e4m3, fp8e5m2, bf16, int64] ] - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> return %2 : tensor<4x11x1xf32> } diff --git a/mlir/test/Dialect/Tosa/canonicalize.mlir b/mlir/test/Dialect/Tosa/canonicalize.mlir index 81e537babf9ab..2e5ddfb0b3a2c 100644 --- a/mlir/test/Dialect/Tosa/canonicalize.mlir +++ b/mlir/test/Dialect/Tosa/canonicalize.mlir @@ -1094,7 +1094,7 @@ func.func @canonicalize_cross_concat_inputs(%arg0 : tensor<1x12x12xf32>, %arg1 : // CHECK-LABEL: @canonicalize_concat_slice_on_non_concat_axis // CHECK-SAME: %[[VAL_0:.*]]: tensor<1x12x12xf32>, %[[VAL_1:.*]]: tensor<1x12x12xf32> -// CHECK-DAG: %[[VAL_2:.*]] = tosa.const_shape {values = dense<[1, 3, 0]> : tensor<3xindex>} +// CHECK-DAG: %[[VAL_2:.*]] = tosa.const_shape {values = dense<[0, 3, 0]> : tensor<3xindex>} // CHECK-DAG: %[[VAL_3:.*]] = tosa.const_shape {values = dense<[1, 3, 12]> : tensor<3xindex>} // CHECK-DAG: %[[VAL_4:.*]] = tosa.const_shape {values = dense<0> : tensor<3xindex>} // CHECK-DAG: %[[VAL_5:.*]] = tosa.const_shape {values = dense<[1, 6, 12]> : tensor<3xindex>} @@ -1105,10 +1105,11 @@ func.func @canonicalize_concat_slice_on_non_concat_axis(%arg0 : tensor<1x12x12xf %0 = tosa.concat %arg0, %arg1 {axis = 2 : i32} : (tensor<1x12x12xf32>, tensor<1x12x12xf32>) -> tensor<1x12x24xf32> %1 = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> %2 = tosa.const_shape {values = dense<[1, 6, 12]> : tensor<3xindex>} : () -> !tosa.shape<3> - %3 = tosa.const_shape {values = dense<[1, 3, 12]> : tensor<3xindex>} : () -> !tosa.shape<3> - %4 = tosa.slice %0, %1, %2 : (tensor<1x12x24xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x6x12xf32> - %5 = tosa.slice %0, %3, %3 : (tensor<1x12x24xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x3x12xf32> - return %4, %5 : tensor<1x6x12xf32>, tensor<1x3x12xf32> + %3 = tosa.const_shape {values = dense<[0, 3, 12]> : tensor<3xindex>} : () -> !tosa.shape<3> + %4 = tosa.const_shape {values = dense<[1, 3, 12]> : tensor<3xindex>} : () -> !tosa.shape<3> + %5 = tosa.slice %0, %1, %2 : (tensor<1x12x24xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x6x12xf32> + %6 = tosa.slice %0, %3, %4 : (tensor<1x12x24xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x3x12xf32> + return %5, %6 : tensor<1x6x12xf32>, tensor<1x3x12xf32> } // ----- @@ -1137,14 +1138,14 @@ func.func @canonicalize_pad_slice_overlap(%arg0: tensor) -> tenso // CHECK-DAG: %[[SLICE_SIZE:.*]] = tosa.const_shape {values = dense<[1, 14, 10, 3]> : tensor<4xindex>} // CHECK-NOT: tosa.pad // CHECK: %[[SLICED:.*]] = tosa.slice %arg0, %[[SLICE_START]], %[[SLICE_SIZE]] -func.func @canonicalize_pad_slice_inside(%arg0: tensor<1x16x16x3xf32>) -> tensor<1x14x14x3xf32> { +func.func @canonicalize_pad_slice_inside(%arg0: tensor<1x16x16x3xf32>) -> tensor<1x14x10x3xf32> { %pad_const = "tosa.const"() <{values = dense<0.000000e+00> : tensor<1xf32>}> : () -> tensor<1xf32> %padding = tosa.const_shape {values = dense<[0, 0, 0, 0, 2, 2, 0, 0]> : tensor<8xindex>} : () -> !tosa.shape<8> %padded = tosa.pad %arg0, %padding, %pad_const : (tensor<1x16x16x3xf32>, !tosa.shape<8>, tensor<1xf32>) -> tensor<1x16x20x3xf32> %start = tosa.const_shape {values = dense<[0, 1, 4, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> %size = tosa.const_shape {values = dense<[1, 14, 10, 3]> : tensor<4xindex>} : () -> !tosa.shape<4> - %sliced = tosa.slice %padded, %start, %size : (tensor<1x16x20x3xf32>, !tosa.shape<4>, !tosa.shape<4>) -> tensor<1x14x14x3xf32> - return %sliced : tensor<1x14x14x3xf32> + %sliced = tosa.slice %padded, %start, %size : (tensor<1x16x20x3xf32>, !tosa.shape<4>, !tosa.shape<4>) -> tensor<1x14x10x3xf32> + return %sliced : tensor<1x14x10x3xf32> } // ----- diff --git a/mlir/test/Dialect/Tosa/invalid_extension.mlir b/mlir/test/Dialect/Tosa/invalid_extension.mlir index 2fa1fe71148d1..16190bb69411c 100644 --- a/mlir/test/Dialect/Tosa/invalid_extension.mlir +++ b/mlir/test/Dialect/Tosa/invalid_extension.mlir @@ -213,11 +213,11 @@ func.func @test_reverse(%arg0: tensor<13x21x3xbf16>) -> tensor<13x21x3xbf16> { // ----- func.func @test_slice(%arg0: tensor<13x21x3xbf16>) -> tensor<4x11x1xbf16> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op illegal: requires [bf16] but not enabled in target}} - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xbf16>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xbf16> - return %2 : tensor<4x11x1xbf16> + %0 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xbf16>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xbf16> + return %0 : tensor<4x11x1xbf16> } // ----- diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir index 739af6bcac2d8..d9de2e0d37c25 100644 --- a/mlir/test/Dialect/Tosa/level_check.mlir +++ b/mlir/test/Dialect/Tosa/level_check.mlir @@ -1004,7 +1004,7 @@ func.func @test_tensor_size_valid(%arg0: tensor<1x536870911xf32>) { func.func @test_slice_tensor_size_invalid(%arg0: tensor<1x536870912xf32>) { %0 = tosa.const_shape {values = dense<0> : tensor<2xindex>} : () -> !tosa.shape<2> - %1 = tosa.const_shape {values = dense<536870912> : tensor<2xindex>} : () -> !tosa.shape<2> + %1 = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> // expected-error@+1 {{'tosa.slice' op failed level check: operand tensor size (in bytes) <= (1 << MAX_LOG2_SIZE - 1)}} %2= tosa.slice %arg0, %0, %1 : (tensor<1x536870912xf32>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x1xf32> return diff --git a/mlir/test/Dialect/Tosa/ops.mlir b/mlir/test/Dialect/Tosa/ops.mlir index 56811891e8f95..1a5eed735294a 100644 --- a/mlir/test/Dialect/Tosa/ops.mlir +++ b/mlir/test/Dialect/Tosa/ops.mlir @@ -722,18 +722,18 @@ func.func @test_reverse(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { // ----- // CHECK-LABEL: slice func.func @test_slice(%arg0: tensor<13x21x3xf32>) -> tensor<4x11x1xf32> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> return %2 : tensor<4x11x1xf32> } // ----- // CHECK-LABEL: slice_size func.func @test_slice_size(%arg0: tensor<13x21x3xf32>) -> tensor<7x11x1xf32> { - %0 = tosa.const_shape {values = dense<[-1, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<7x11x1xf32> + %size = tosa.const_shape {values = dense<[7, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<7x11x1xf32> return %2 : tensor<7x11x1xf32> } @@ -1121,9 +1121,9 @@ func.func @test_reverse_f8E5M2(%arg0: tensor<13x21x3xf8E5M2>) -> tensor<13x21x3x // ----- // CHECK-LABEL: slice_f8E5M2 func.func @test_slice_f8E5M2(%arg0: tensor<13x21x3xf8E5M2>) -> tensor<4x11x1xf8E5M2> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xf8E5M2>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf8E5M2> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf8E5M2>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf8E5M2> return %2 : tensor<4x11x1xf8E5M2> } @@ -1266,9 +1266,9 @@ func.func @test_reverse_f8E4M3FN(%arg0: tensor<13x21x3xf8E4M3FN>) -> tensor<13x2 // ----- // CHECK-LABEL: slice_f8E4M3FN func.func @test_slice_f8E4M3FN(%arg0: tensor<13x21x3xf8E4M3FN>) -> tensor<4x11x1xf8E4M3FN> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xf8E4M3FN>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf8E4M3FN> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf8E4M3FN>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf8E4M3FN> return %2 : tensor<4x11x1xf8E4M3FN> } diff --git a/mlir/test/Dialect/Tosa/profile_all_unsupported.mlir b/mlir/test/Dialect/Tosa/profile_all_unsupported.mlir index 09e96eca776e2..d1e61345ff313 100644 --- a/mlir/test/Dialect/Tosa/profile_all_unsupported.mlir +++ b/mlir/test/Dialect/Tosa/profile_all_unsupported.mlir @@ -215,11 +215,11 @@ func.func @test_reverse(%arg0: tensor<13x21x3xi1>) -> tensor<13x21x3xi1> { // ----- func.func @test_slice(%arg0: tensor<13x21x3xi1>) -> tensor<4x11x1xi1> { // expected-error@+1 {{'tosa.const_shape' op illegal: requires any of [pro_int, pro_fp] but not enabled in target}} - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.const_shape' op illegal: requires any of [pro_int, pro_fp] but not enabled in target}} - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op illegal: requires any of [pro_int, pro_fp] but not enabled in target}} - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xi1>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi1> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xi1>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi1> return %2 : tensor<4x11x1xi1> } @@ -283,12 +283,12 @@ func.func @test_reverse(%arg0: tensor<13x21x3xi1>) -> tensor<13x21x3xi1> { // ----- func.func @test_slice(%arg0: tensor<13x21x3xi1>) -> tensor<4x11x1xi1> { // expected-error@+1 {{'tosa.const_shape' op illegal: requires any of [pro_int, pro_fp] but not enabled in target}} - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.const_shape' op illegal: requires any of [pro_int, pro_fp] but not enabled in target}} - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op illegal: requires any of [pro_int, pro_fp] but not enabled in target}} - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xi1>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi1> - return %2 : tensor<4x11x1xi1> + %0 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xi1>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi1> + return %0 : tensor<4x11x1xi1> } // ----- diff --git a/mlir/test/Dialect/Tosa/profile_pro_fp_unsupported.mlir b/mlir/test/Dialect/Tosa/profile_pro_fp_unsupported.mlir index 15aad410c6f44..d7330cb763fc0 100644 --- a/mlir/test/Dialect/Tosa/profile_pro_fp_unsupported.mlir +++ b/mlir/test/Dialect/Tosa/profile_pro_fp_unsupported.mlir @@ -280,10 +280,10 @@ func.func @test_reverse(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { // ----- func.func @test_slice(%arg0: tensor<13x21x3xf32>) -> tensor<4x11x1xf32> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op illegal: requires [pro_fp] but not enabled in target}} - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> return %2 : tensor<4x11x1xf32> } diff --git a/mlir/test/Dialect/Tosa/profile_pro_int_unsupported.mlir b/mlir/test/Dialect/Tosa/profile_pro_int_unsupported.mlir index 48e79e4000d56..cb760956fbd68 100644 --- a/mlir/test/Dialect/Tosa/profile_pro_int_unsupported.mlir +++ b/mlir/test/Dialect/Tosa/profile_pro_int_unsupported.mlir @@ -212,10 +212,10 @@ func.func @test_reverse(%arg0: tensor<13x21x3xi8>) -> tensor<13x21x3xi8> { // ----- func.func @test_slice(%arg0: tensor<13x21x3xi8>) -> tensor<4x11x1xi8> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // expected-error@+1 {{'tosa.slice' op illegal: requires [pro_int] but not enabled in target}} - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xi8>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi8> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xi8>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi8> return %2 : tensor<4x11x1xi8> } diff --git a/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir b/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir index 0deb31dab1c6f..b6ddcdeb45668 100644 --- a/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir +++ b/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir @@ -592,42 +592,6 @@ func.func @test_slice_size_minus_one(%arg0 : tensor) -> () { // ----- -// CHECK-LABEL: @test_slice_size_out_of_bound -func.func @test_slice_size_out_of_bound(%arg0 : tensor<8x8x8x?xi32>) -> () { - // CHECK: %[[START:.+]] = tosa.const_shape - // CHECK: %[[SIZE:.+]] = tosa.const_shape - // CHECK: %[[VAL:.+]] = tosa.slice %arg0, %[[START]], %[[SIZE]] : (tensor<8x8x8x?xi32>, !tosa.shape<4>, !tosa.shape<4>) -> tensor - // this checks following - // dim 0: size=0 => inferred output dim is ? - // dim 1: size=-2 => inferred output dim is ? - // dim 3: start+size out of bound because size too big: inferred output dim is ? - // dim 4: size=4, input dim=? => inferred output dim is 4 - %start = tosa.const_shape {values = dense<[0, 0, 0, 0]> : tensor<4xindex>} : () -> !tosa.shape<4> - %size = tosa.const_shape {values = dense<[0, -2, 9, 4]> : tensor<4xindex>} : () -> !tosa.shape<4> - %2= tosa.slice %arg0, %start, %size : (tensor<8x8x8x?xi32>, !tosa.shape<4>, !tosa.shape<4>) -> tensor - return -} - -// ----- - -// CHECK-LABEL: @test_slice_start_out_of_bound -func.func @test_slice_start_out_of_bound(%arg0 : tensor<8x8x8x?xi32>) -> () { - // CHECK: %[[START:.+]] = tosa.const_shape - // CHECK: %[[SIZE:.+]] = tosa.const_shape - // CHECK: %[[VAL:.+]] = tosa.slice %arg0, %[[START]], %[[SIZE]] : (tensor<8x8x8x?xi32>, !tosa.shape<4>, !tosa.shape<4>) -> tensor - // this checks following - // dim 0: start=-1 => inferred output dim is ? - // dim 1: start=8 => inferred output dim is ? - // dim 2: start+size out of bound: inferred output dim is ? - // dim 3: start=8000000, size=4, input dim=? => inferred output dim is 4 - %start = tosa.const_shape {values = dense<[-1, 8, 6, 8000000]> : tensor<4xindex>} : () -> !tosa.shape<4> - %size = tosa.const_shape {values = dense<[1, 1, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4> - %2= tosa.slice %arg0, %start, %size : (tensor<8x8x8x?xi32>, !tosa.shape<4>, !tosa.shape<4>) -> tensor - return -} - -// ----- - // CHECK-LABEL: @test_slice_dynamic func.func @test_slice_dynamic(%arg0 : tensor<10x?x2xf32>) -> () { // CHECK: %0 = tosa.const_shape {values = dense<[1, 0, 0]> : tensor<3xindex>} diff --git a/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir b/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir index 1034ee67f65e2..706213c394fb0 100644 --- a/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir +++ b/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir @@ -112,7 +112,7 @@ func.func @test_f64_slice(%arg0: tensor<13x21x3xf64>) -> tensor<4x11x1xf64> { %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // COMMON: %[[SLICE:.*]] = tosa.slice %{{.*}}, %{{.*}}, %{{.*}} : (tensor<13x21x3xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf32> - %0 = tosa.slice %arg0, %size, %start : (tensor<13x21x3xf64>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf64> + %0 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xf64>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xf64> // DEFAULT: %[[OUT:.*]] = tosa.cast %[[SLICE]] : (tensor<4x11x1xf32>) -> tensor<4x11x1xf64> // DEFAULT: return %[[OUT]] : tensor<4x11x1xf64> // FUNCBOUND: return %[[SLICE]] : tensor<4x11x1xf32> diff --git a/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir b/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir index 42e63346d8c33..6a7bab74272ed 100644 --- a/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir +++ b/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir @@ -115,10 +115,10 @@ func.func @test_reverse(%arg0: tensor<13x21x3xi64>) -> tensor<13x21x3xi64> { // CHECK-LABEL: test_slice func.func @test_slice(%arg0: tensor<13x21x3xi64>) -> tensor<4x11x1xi64> { - %0 = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> - %1 = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[4, 11, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + %start = tosa.const_shape {values = dense<[6, 8, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> // COMMON: tosa.slice %{{.*}}, %{{.*}}, %{{.*}} : (tensor<13x21x3xi32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi32> - %2 = tosa.slice %arg0, %0, %1 : (tensor<13x21x3xi64>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi64> + %2 = tosa.slice %arg0, %start, %size : (tensor<13x21x3xi64>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<4x11x1xi64> return %2 : tensor<4x11x1xi64> } diff --git a/mlir/test/Dialect/Tosa/verifier.mlir b/mlir/test/Dialect/Tosa/verifier.mlir index 3621c25005862..80d5bca039909 100644 --- a/mlir/test/Dialect/Tosa/verifier.mlir +++ b/mlir/test/Dialect/Tosa/verifier.mlir @@ -170,6 +170,56 @@ func.func @test_scalar_slice(%arg0: tensor) -> tensor { // ----- +func.func @test_slice_invalid_start_values(%arg0: tensor<4x31x31xf32>) { + %start = tosa.const_shape {values = dense<[-2, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + // expected-error@+1 {{'tosa.slice' op start values must be non-negative, got [-2, 0, 0]}} + %1 = tosa.slice %arg0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x1x1xf32> + return +} + +// ----- + +func.func @test_slice_invalid_size_values(%arg0: tensor<4x31x31xf32>) { + %start = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[1, 0, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> + // expected-error@+1 {{'tosa.slice' op size values must be > 0, got [1, 0, 1]}} + %1 = tosa.slice %arg0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor + return +} + +// ----- + +func.func @test_slice_output_shape_mismatch(%arg0: tensor<4x5x6xf32>) { + %start = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[1, 2, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> + // expected-error@+1 {{'tosa.slice' op expected output shape to match size values, got 'tensor<1x2x4xf32>' vs [1, 2, 3]}} + %1 = tosa.slice %arg0, %start, %size : (tensor<4x5x6xf32>, !tosa.shape<3>, !tosa.shape<3>) -> tensor<1x2x4xf32> + return +} + +// ----- + +func.func @test_slice_invalid_start_plus_size(%arg0: tensor) { + %start = tosa.const_shape {values = dense<[-1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2> + %size = tosa.const_shape {values = dense<[3, 2]> : tensor<2xindex>} : () -> !tosa.shape<2> + // expected-error@+1 {{'tosa.slice' op start + size must be less than or equal to input dimension size, got start=1, size=2 vs input dim size=2 at dimension 1}} + %1 = tosa.slice %arg0, %start, %size : (tensor, !tosa.shape<2>, !tosa.shape<2>) -> tensor + return +} + +// ----- + +func.func @test_slice_output_shape_mismatch_dynamic(%arg0: tensor) { + %start = tosa.const_shape {values = dense<[0, 0, 0]> : tensor<3xindex>} : () -> !tosa.shape<3> + %size = tosa.const_shape {values = dense<[1, 2, 3]> : tensor<3xindex>} : () -> !tosa.shape<3> + // expected-error@+1 {{'tosa.slice' op expected output shape to match size values, got 'tensor' vs [1, 2, 3]}} + %1 = tosa.slice %arg0, %start, %size : (tensor, !tosa.shape<3>, !tosa.shape<3>) -> tensor + return +} + +// ----- + func.func @test_depthwise_conv2d_invalid_padding(%arg0: tensor<1x4x4x4xf32>, %arg1: tensor<1x1x8x4xf32>, %arg2: tensor<8xf32>, %arg3: tensor<1xf32>, %arg4: tensor<1xf32>) -> tensor<1x4x4x8xf32> { // expected-error@+1 {{'tosa.depthwise_conv2d' op expect all padding values to be >= 0, got 0, 0, -1, 0}} %0 = tosa.depthwise_conv2d %arg0, %arg1, %arg2, %arg3, %arg4 {acc_type = f32, dilation = array, pad = array, stride = array, local_bound = true}