[Mlir-commits] [mlir] [mlir][tosa] Make TOSA RESIZE's scale, offset, border as Input (PR #124956)
Hsiangkai Wang
llvmlistbot at llvm.org
Thu Jan 30 01:19:32 PST 2025
https://github.com/Hsiangkai updated https://github.com/llvm/llvm-project/pull/124956
>From 85498989fc75f49112dd135b5f224492280b1c82 Mon Sep 17 00:00:00 2001
From: Hsiangkai Wang <hsiangkai.wang at arm.com>
Date: Wed, 29 Jan 2025 16:51:16 +0000
Subject: [PATCH] [mlir][tosa] Make TOSA RESIZE's scale, offset, border as
Input
Move the `scale`, `offset`, and `border` parameters of the RESIZE operator
in the MLIR TOSA dialect from attributes to inputs and update lit tests
appropriately.
Add the verifier of the `tosa::ResizeOp` operation.
Co-authored-by: Tai Ly <tai.ly at arm.com>
Co-authored-by: Luke Hutton <luke.hutton at arm.com>
---
mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td | 7 +-
.../mlir/Dialect/Tosa/Utils/ConversionUtils.h | 3 +
.../Conversion/TosaToLinalg/TosaToLinalg.cpp | 117 ++-------------
.../Dialect/Tosa/IR/TosaCanonicalizations.cpp | 19 ++-
mlir/lib/Dialect/Tosa/IR/TosaOps.cpp | 95 +++++++++++-
.../Tosa/Transforms/TosaValidation.cpp | 121 ++++++++++++++-
.../Dialect/Tosa/Utils/ConversionUtils.cpp | 18 +++
.../TosaToLinalg/tosa-to-linalg-resize.mlir | 140 ++++++++----------
mlir/test/Dialect/Tosa/canonicalize.mlir | 10 +-
mlir/test/Dialect/Tosa/invalid.mlir | 60 ++++++++
mlir/test/Dialect/Tosa/level_check.mlir | 22 ++-
mlir/test/Dialect/Tosa/ops.mlir | 5 +-
mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir | 40 ++++-
13 files changed, 444 insertions(+), 213 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
index 850b85236a4c7f..54f9033c585f14 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
@@ -1853,9 +1853,9 @@ def Tosa_ResizeOp : Tosa_InferShapedTypeOp<"resize"> {
let arguments = (ins
Tosa_Tensor4D:$input,
- Tosa_IntArrayAttr4:$scale,
- Tosa_IntArrayAttr2:$offset,
- Tosa_IntArrayAttr2:$border,
+ Rank4TosaShape:$scale,
+ Rank2TosaShape:$offset,
+ Rank2TosaShape:$border,
Tosa_ResizeTypeAttr:$mode
);
@@ -1864,6 +1864,7 @@ def Tosa_ResizeOp : Tosa_InferShapedTypeOp<"resize"> {
);
let hasFolder = 1;
+ let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
index 78a8828855437e..85eb467a71a3a6 100644
--- a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
+++ b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
@@ -237,6 +237,9 @@ SmallVector<int64_t> convertFromMlirShape(ArrayRef<int64_t> shape);
bool getConstShapeValue(Operation *op,
llvm::SmallVector<int64_t> &result_shape);
+// returns a small vector of int64_t values that attr contains
+SmallVector<int64_t> convertFromIntAttr(const DenseElementsAttr &attr,
+ const int rank);
} // namespace tosa
} // namespace mlir
diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
index b0eb2d6cbc30b6..1ff9d291005274 100644
--- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
+++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
@@ -1378,7 +1378,10 @@ class ResizeUnaryConverter : public OpRewritePattern<tosa::ResizeOp> {
return success();
}
- ArrayRef<int64_t> scale = op.getScale();
+ SmallVector<int64_t> scale;
+ if (!tosa::getConstShapeValue(op.getScale().getDefiningOp(), scale)) {
+ return failure();
+ }
// Collapse the unit width and height away.
SmallVector<ReassociationExprs, 4> reassociationMap(2);
@@ -1440,105 +1443,6 @@ class ResizeUnaryConverter : public OpRewritePattern<tosa::ResizeOp> {
}
};
-// TOSA resize with width or height of 1 may be broadcasted to a wider
-// dimension. This is done by materializing a new tosa.resize without
-// the broadcasting behavior, and an explicit broadcast afterwards.
-class MaterializeResizeBroadcast : public OpRewritePattern<tosa::ResizeOp> {
-public:
- using OpRewritePattern<tosa::ResizeOp>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(tosa::ResizeOp op,
- PatternRewriter &rewriter) const final {
- Location loc = op.getLoc();
- ImplicitLocOpBuilder builder(loc, rewriter);
- auto input = op.getInput();
- auto inputTy = dyn_cast<RankedTensorType>(input.getType());
- auto resultTy = dyn_cast<RankedTensorType>(op.getType());
-
- if (!inputTy || !resultTy)
- return rewriter.notifyMatchFailure(op,
- "requires ranked input/output types");
-
- auto batch = inputTy.getDimSize(0);
- auto channels = inputTy.getDimSize(3);
- auto inputH = inputTy.getDimSize(1);
- auto inputW = inputTy.getDimSize(2);
- auto outputH = resultTy.getDimSize(1);
- auto outputW = resultTy.getDimSize(2);
-
- if ((inputH != 1 || outputH == 1) && (inputW != 1 || outputW == 1))
- return rewriter.notifyMatchFailure(
- op, "tosa.resize has no broadcasting behavior");
-
- // For any dimension that is broadcastable we generate a width of 1
- // on the output.
- llvm::SmallVector<int64_t> resizeShape;
- resizeShape.push_back(batch);
- resizeShape.push_back(inputH == 1 ? 1 : outputH);
- resizeShape.push_back(inputW == 1 ? 1 : outputW);
- resizeShape.push_back(channels);
-
- auto resizeTy = resultTy.clone(resizeShape);
- auto resize =
- builder.create<tosa::ResizeOp>(resizeTy, input, op->getAttrs());
-
- // Collapse an unit result dims.
- SmallVector<ReassociationExprs, 4> reassociationMap(2);
- reassociationMap[0].push_back(builder.getAffineDimExpr(0));
- reassociationMap.back().push_back(builder.getAffineDimExpr(1));
- if (inputH != 1)
- reassociationMap.push_back({});
- reassociationMap.back().push_back(builder.getAffineDimExpr(2));
- if (inputW != 1)
- reassociationMap.push_back({});
- reassociationMap.back().push_back(builder.getAffineDimExpr(3));
-
- llvm::SmallVector<int64_t> collapseShape = {batch};
- if (inputH != 1)
- collapseShape.push_back(outputH);
- if (inputW != 1)
- collapseShape.push_back(outputW);
- collapseShape.push_back(channels);
-
- auto collapseTy = resultTy.clone(collapseShape);
- Value collapse = builder.create<tensor::CollapseShapeOp>(collapseTy, resize,
- reassociationMap);
-
- // Broadcast the collapsed shape to the output result.
- llvm::SmallVector<Value> outputDynSize;
- if (inputTy.isDynamicDim(0))
- outputDynSize.push_back(builder.create<tensor::DimOp>(input, 0));
- if (inputTy.isDynamicDim(3))
- outputDynSize.push_back(builder.create<tensor::DimOp>(input, 3));
-
- SmallVector<utils::IteratorType> iterators(resultTy.getRank(),
- utils::IteratorType::parallel);
- Value empty = builder.create<tensor::EmptyOp>(
- resultTy.getShape(), resultTy.getElementType(), outputDynSize);
-
- SmallVector<AffineExpr, 4> inputExprs{rewriter.getAffineDimExpr(0)};
- if (inputH != 1)
- inputExprs.push_back(rewriter.getAffineDimExpr(1));
- if (inputW != 1)
- inputExprs.push_back(rewriter.getAffineDimExpr(2));
- inputExprs.push_back(rewriter.getAffineDimExpr(3));
-
- auto inputMap = AffineMap::get(resultTy.getRank(), /*symbolCount=*/0,
- inputExprs, rewriter.getContext());
-
- auto outputMap = rewriter.getMultiDimIdentityMap(resultTy.getRank());
- rewriter.replaceOpWithNewOp<linalg::GenericOp>(
- op, resultTy, ValueRange{collapse}, ValueRange{empty},
- ArrayRef<AffineMap>{inputMap, outputMap}, iterators,
- [=](OpBuilder &b, Location loc, ValueRange args) {
- Value value = args[0];
- b.create<linalg::YieldOp>(loc, value);
- });
-
- return success();
- }
-};
-
class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
public:
using OpRewritePattern<tosa::ResizeOp>::OpRewritePattern;
@@ -1595,9 +1499,14 @@ class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
Value inY = b.create<arith::IndexCastOp>(b.getI32Type(), y);
Value inX = b.create<arith::IndexCastOp>(b.getI32Type(), x);
- ArrayRef<int64_t> offset = op.getOffset();
- ArrayRef<int64_t> border = op.getBorder();
- ArrayRef<int64_t> scale = op.getScale();
+ SmallVector<int64_t> scale, offset, border;
+ if (!tosa::getConstShapeValue(op.getScale().getDefiningOp(), scale) ||
+ !tosa::getConstShapeValue(op.getOffset().getDefiningOp(), offset) ||
+ !tosa::getConstShapeValue(op.getBorder().getDefiningOp(), border)) {
+ return rewriter.notifyMatchFailure(
+ op, "tosa.resize scale/offset/border should have compile time "
+ "constant values.");
+ }
Value yScaleN, yScaleD, xScaleN, xScaleD;
yScaleN = b.create<arith::ConstantOp>(b.getI32IntegerAttr(scale[0]));
@@ -2607,8 +2516,6 @@ void mlir::tosa::populateTosaToLinalgConversionPatterns(
/*benefit=*/100);
patterns->add<ResizeUnaryConverter>(patterns->getContext(),
/*benefit=*/200);
- patterns->add<MaterializeResizeBroadcast>(patterns->getContext(),
- /*benefit=*/300);
patterns->add<
// clang-format off
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
index ddfcde6de14f14..b52bb51a1c7cf5 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
@@ -955,9 +955,22 @@ OpFoldResult PadOp::fold(FoldAdaptor adaptor) {
// Fold away cases where a tosa.resize operation returns a copy
// of the input image.
OpFoldResult ResizeOp::fold(FoldAdaptor adaptor) {
- ArrayRef<int64_t> offset = getOffset();
- ArrayRef<int64_t> border = getBorder();
- ArrayRef<int64_t> scale = getScale();
+ auto scaleAttr =
+ llvm::dyn_cast_if_present<DenseElementsAttr>(adaptor.getScale());
+ auto offsetAttr =
+ llvm::dyn_cast_if_present<DenseElementsAttr>(adaptor.getOffset());
+ auto borderAttr =
+ llvm::dyn_cast_if_present<DenseElementsAttr>(adaptor.getBorder());
+ if (!scaleAttr || !offsetAttr || !borderAttr) {
+ return {};
+ }
+
+ auto scale = tosa::convertFromIntAttr(scaleAttr, /* rank = */ 4);
+ auto offset = tosa::convertFromIntAttr(offsetAttr, /* rank = */ 2);
+ auto border = tosa::convertFromIntAttr(borderAttr, /* rank = */ 2);
+ if (scale.size() != 4 || offset.size() != 2 || border.size() != 2) {
+ return {};
+ }
// Check unit scaling.
if (scale[0] != scale[1] || scale[2] != scale[3]) {
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index ae4e09a1e324c6..ac676055be4bcb 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -1451,9 +1451,14 @@ LogicalResult tosa::ResizeOp::inferReturnTypeComponents(
(inputWidth == ShapedType::kDynamic))
return failure();
- llvm::ArrayRef<int64_t> scaleInt = adaptor.getScale();
- llvm::ArrayRef<int64_t> offsetInt = adaptor.getOffset();
- llvm::ArrayRef<int64_t> borderInt = adaptor.getBorder();
+ SmallVector<int64_t> scaleInt, offsetInt, borderInt;
+ if (!tosa::getConstShapeValue(adaptor.getScale().getDefiningOp(), scaleInt) ||
+ !tosa::getConstShapeValue(adaptor.getOffset().getDefiningOp(),
+ offsetInt) ||
+ !tosa::getConstShapeValue(adaptor.getBorder().getDefiningOp(),
+ borderInt)) {
+ return failure();
+ }
// Compute the output shape based on attributes: scale, offset, and border.
outputShape[1] =
@@ -1470,6 +1475,90 @@ LogicalResult tosa::ResizeOp::inferReturnTypeComponents(
return success();
}
+LogicalResult tosa::ResizeOp::verify() {
+ const Value input = getInput();
+ const Value output = getOutput();
+ const RankedTensorType inputType =
+ llvm::dyn_cast<RankedTensorType>(input.getType());
+ const RankedTensorType outputType =
+ llvm::dyn_cast<RankedTensorType>(output.getType());
+
+ if (!inputType)
+ return emitOpError("expect a ranked input tensor");
+ if (!outputType)
+ return emitOpError("expect a ranked output tensor");
+
+ const int64_t oh = outputType.getDimSize(1);
+ const int64_t ow = outputType.getDimSize(2);
+ const int64_t ih = inputType.getDimSize(1);
+ const int64_t iw = inputType.getDimSize(2);
+
+ SmallVector<int64_t> scaleValues;
+ SmallVector<int64_t> offsetValues;
+ SmallVector<int64_t> borderValues;
+ if (!tosa::getConstShapeValue(getScale().getDefiningOp(), scaleValues) ||
+ !tosa::getConstShapeValue(getOffset().getDefiningOp(), offsetValues) ||
+ !tosa::getConstShapeValue(getBorder().getDefiningOp(), borderValues)) {
+ // Skip following checks if shape is not constant
+ return success();
+ }
+
+ if (llvm::any_of(scaleValues, [](int64_t s) { return s <= 0; }))
+ return emitOpError("expect all scale values to be > 0, got ")
+ << scaleValues;
+
+ const int64_t scaleYN = scaleValues[0];
+ const int64_t scaleYD = scaleValues[1];
+ const int64_t scaleXN = scaleValues[2];
+ const int64_t scaleXD = scaleValues[3];
+
+ const int64_t offsetY = offsetValues[0];
+ const int64_t offsetX = offsetValues[1];
+
+ const int64_t borderY = borderValues[0];
+ const int64_t borderX = borderValues[1];
+
+ auto idivCheck = [](const int64_t lhs,
+ const int64_t rhs) -> std::optional<int64_t> {
+ if (lhs % rhs != 0)
+ return std::nullopt;
+ return lhs / rhs;
+ };
+
+ if (ih != ShapedType::kDynamic) {
+ const std::optional<int64_t> calculatedOutHeightMinusOne =
+ idivCheck((ih - 1) * scaleYN - offsetY + borderY, scaleYD);
+ if (!calculatedOutHeightMinusOne.has_value())
+ return emitOpError("expected (input_height - 1) * scale_y_n - offset_y + "
+ "border_y ")
+ << "to be wholly divisible by scale_y_d, got ((" << ih
+ << " - 1) * " << scaleYN << " - " << offsetY << " + " << borderY
+ << ") / " << scaleYD;
+ const int64_t calculatedOutHeight = calculatedOutHeightMinusOne.value() + 1;
+ if (oh != ShapedType::kDynamic && calculatedOutHeight != oh)
+ return emitOpError("calculated output height did not match expected: ")
+ << "calculated=" << calculatedOutHeight << ", expected=" << oh;
+ }
+
+ if (iw != ShapedType::kDynamic) {
+ const int64_t scaledInWidth = (iw - 1) * scaleXN - offsetX + borderX;
+ const std::optional<int64_t> calculatedOutWidthMinusOne =
+ idivCheck(scaledInWidth, scaleXD);
+ if (!calculatedOutWidthMinusOne.has_value())
+ return emitOpError("expected (input_width - 1) * scale_x_n - offset_x + "
+ "border_x ")
+ << "to be wholly divisible by scale_x_d, got ((" << iw
+ << " - 1) * " << scaleXN << " - " << offsetX << " + " << borderX
+ << ") / " << scaleXD;
+ const int64_t calculatedOutWidth = calculatedOutWidthMinusOne.value() + 1;
+ if (ow != ShapedType::kDynamic && calculatedOutWidth != ow)
+ return emitOpError("calculated output width did not match expected: ")
+ << "calculated=" << calculatedOutWidth << ", expected=" << ow;
+ }
+
+ return success();
+}
+
LogicalResult tosa::ScatterOp::inferReturnTypeComponents(
MLIRContext *context, ::std::optional<Location> location,
ScatterOp::Adaptor adaptor,
diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
index a49870687fdc60..b6a39a8635fd28 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
@@ -18,6 +18,7 @@
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/Tosa/IR/TosaOps.h"
+#include "mlir/Dialect/Tosa/Utils/ConversionUtils.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Matchers.h"
@@ -119,6 +120,9 @@ struct TosaValidation : public tosa::impl::TosaValidationBase<TosaValidation> {
// check variable read/write data types against variable declarations
LogicalResult applyVariableCheck(Operation *op);
+ // check error if conditions
+ LogicalResult applyErrorIfCheck(Operation *op);
+
private:
void populateConstantOperandChecks() {
constCheckers.emplace_back(checkConstantOperandPad);
@@ -383,11 +387,14 @@ struct TosaValidation : public tosa::impl::TosaValidationBase<TosaValidation> {
// Resize op: level check max scales
bool levelCheckResize(Operation *op) {
if (auto resize = dyn_cast<tosa::ResizeOp>(op)) {
- auto scale = resize.getScale();
- int16_t scaleYN = scale[0];
- int16_t scaleYD = scale[1];
- int16_t scaleXN = scale[2];
- int16_t scaleXD = scale[3];
+ SmallVector<int64_t> scale;
+ if (!tosa::getConstShapeValue(resize.getScale().getDefiningOp(), scale)) {
+ return false;
+ }
+ const int64_t scaleYN = scale[0];
+ const int64_t scaleYD = scale[1];
+ const int64_t scaleXN = scale[2];
+ const int64_t scaleXD = scale[3];
if (!levelCheckScale(op, scaleYN / scaleYD,
"scale_y_n/scale_y_d <= MAX_SCALE") ||
!levelCheckScale(op, scaleXN / scaleXD,
@@ -519,6 +526,106 @@ LogicalResult TosaValidation::applyVariableCheck(Operation *op) {
return success();
}
+bool checkErrorIfResize(Operation *op) {
+ if (auto resize = dyn_cast<tosa::ResizeOp>(op)) {
+ const Value input = resize.getInput();
+ const Value output = resize.getOutput();
+ const RankedTensorType inputType =
+ llvm::dyn_cast<RankedTensorType>(input.getType());
+ const RankedTensorType outputType =
+ llvm::dyn_cast<RankedTensorType>(output.getType());
+
+ if (!inputType || !outputType) {
+ op->emitOpError("expect ranked input/output tensor");
+ return false;
+ }
+
+ // Ensure the image size is supported by GPU APIs and that for integer
+ // implementations, position * stride does not overflow int32_t.
+ if (inputType.hasStaticShape() && outputType.hasStaticShape()) {
+ const SmallVector<int64_t, 4> sizes = {
+ outputType.getDimSize(1), outputType.getDimSize(2),
+ inputType.getDimSize(1), inputType.getDimSize(2)};
+ const int64_t *maxDim = llvm::max_element(sizes);
+ if (maxDim != sizes.end() && *maxDim >= 16384) {
+ op->emitOpError("expect input/output height/width dims to be < 16384, ")
+ << "got [OH, OW, IH, IW] = " << sizes;
+ return false;
+ }
+ }
+
+ SmallVector<int64_t> scale;
+ if (!tosa::getConstShapeValue(resize.getScale().getDefiningOp(), scale)) {
+ return false;
+ }
+
+ const int64_t scaleYN = scale[0];
+ const int64_t scaleYD = scale[1];
+ const int64_t scaleXN = scale[2];
+ const int64_t scaleXD = scale[3];
+
+ // Ensure scale values don't overflow int32 accumulator
+ if (scaleYN > (1 << 11) || scaleXN > (1 << 11)) {
+ op->emitOpError("expect all scale numerator values to be <= (1 << 11), "
+ "got scale_y_n=")
+ << scaleYN << ", scale_x_n=" << scaleXN;
+ return false;
+ }
+
+ if (scaleYD >= 16 * scaleYN || scaleXD >= 16 * scaleXN) {
+ op->emitOpError("expect a downscale ratio larger than 1/16, got y=")
+ << scaleYN << "/" << scaleYD << ", x=" << scaleXN << "/" << scaleXD;
+ return false;
+ }
+
+ SmallVector<int64_t> offset;
+ SmallVector<int64_t> border;
+ if (!tosa::getConstShapeValue(resize.getOffset().getDefiningOp(), offset) ||
+ !tosa::getConstShapeValue(resize.getBorder().getDefiningOp(), border)) {
+ return false;
+ }
+
+ const int64_t offsetY = offset[0];
+ const int64_t offsetX = offset[1];
+ const int64_t borderY = border[0];
+ const int64_t borderX = border[1];
+
+ // Set a consistent lower limit of 1/16 downscale to simplify
+ // implementations
+ if (offsetY < -scaleYN || offsetY >= 16 * scaleYN) {
+ op->emitOpError(
+ "expect offsetY / scaleYNumerator to be in range [-1, 16), got ")
+ << offsetY << "/" << scaleYN;
+ return false;
+ }
+ if (offsetX < -scaleXN || offsetX >= 16 * scaleXN) {
+ op->emitOpError(
+ "expect offsetX / scaleXNumerator to be in range [-1, 16), got ")
+ << offsetX << "/" << scaleXN;
+ return false;
+ }
+ if (borderY < -16 * scaleYN || borderY >= scaleYN) {
+ op->emitOpError(
+ "expect borderY / scaleYNumerator to be in range [-16, 1), got ")
+ << borderY << "/" << scaleYN;
+ return false;
+ }
+ if (borderX < -16 * scaleXN || borderX >= scaleXN) {
+ op->emitOpError(
+ "expect borderX / scaleXNumerator to be in range [-16, 1), got ")
+ << borderX << "/" << scaleXN;
+ return false;
+ }
+ }
+ return true;
+}
+
+LogicalResult TosaValidation::applyErrorIfCheck(Operation *op) {
+ if (!checkErrorIfResize(op))
+ return failure();
+ return success();
+}
+
bool TosaValidation::isValidElementType(Type type) {
if (isa<FloatType>(type)) {
if (!isEnabledProfile(TosaProfileEnum::MainInference))
@@ -582,6 +689,10 @@ void TosaValidation::runOnOperation() {
// do variable type checks
if (failed(applyVariableCheck(op)))
signalPassFailure();
+
+ // do error if checks
+ if (StrictOperationSpecAlignment && failed(applyErrorIfCheck(op)))
+ signalPassFailure();
});
}
} // namespace
diff --git a/mlir/lib/Dialect/Tosa/Utils/ConversionUtils.cpp b/mlir/lib/Dialect/Tosa/Utils/ConversionUtils.cpp
index 62b0bc1857e395..69d02f9bc37c0c 100644
--- a/mlir/lib/Dialect/Tosa/Utils/ConversionUtils.cpp
+++ b/mlir/lib/Dialect/Tosa/Utils/ConversionUtils.cpp
@@ -193,3 +193,21 @@ bool mlir::tosa::getConstShapeValue(Operation *op,
// for undefined op, return false.
return false;
}
+
+// returns a small vector of int64_t values that attr contains
+SmallVector<int64_t>
+mlir::tosa::convertFromIntAttr(const DenseElementsAttr &attr, const int rank) {
+ if (attr.isSplat()) {
+ int64_t v = attr.getSplatValue<APInt>().getSExtValue();
+ return SmallVector<int64_t>(rank, v);
+ }
+
+ if (auto int_array_attr = llvm::dyn_cast<DenseIntElementsAttr>(attr)) {
+ SmallVector<int64_t> vec;
+ for (APInt val : int_array_attr.getValues<APInt>()) {
+ vec.push_back(val.getSExtValue());
+ }
+ return vec;
+ }
+ return {};
+}
diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir
index d42d0a46692d47..ad9f03d1c1d608 100644
--- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir
+++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir
@@ -2,7 +2,10 @@
// CHECK-LABEL: @unary_resize_nearest_fp32
func.func @unary_resize_nearest_fp32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32> {
- %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32>
+ %scale = tosa.const_shape { value = dense<[2, 2, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<3x1x1x7xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x1x7xf32>
// CHECK: return %arg0
return %resize : tensor<3x1x1x7xf32>
}
@@ -11,7 +14,10 @@ func.func @unary_resize_nearest_fp32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x
// CHECK-LABEL: @unary_resize_nearest_fp16
func.func @unary_resize_nearest_fp16(%arg0 : tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16> {
- %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16>
+ %scale = tosa.const_shape { value = dense<[2, 2, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<3x1x1x7xf16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x1x7xf16>
// CHECK: return %arg0
return %resize : tensor<3x1x1x7xf16>
}
@@ -20,7 +26,10 @@ func.func @unary_resize_nearest_fp16(%arg0 : tensor<3x1x1x7xf16>) -> tensor<3x1x
// CHECK-LABEL: @unary_resize_bilinear_fp32
func.func @unary_resize_bilinear_fp32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32> {
- %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf32>) -> tensor<3x1x1x7xf32>
+ %scale = tosa.const_shape { value = dense<[2, 2, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<3x1x1x7xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x1x7xf32>
// CHECK: return %arg0
return %resize : tensor<3x1x1x7xf32>
}
@@ -29,7 +38,10 @@ func.func @unary_resize_bilinear_fp32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1
// CHECK-LABEL: @unary_resize_bilinear_fp16
func.func @unary_resize_bilinear_fp16(%arg0 : tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16> {
- %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf16>) -> tensor<3x1x1x7xf16>
+ %scale = tosa.const_shape { value = dense<[2, 2, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<3x1x1x7xf16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x1x7xf16>
// CHECK: return %arg0
return %resize : tensor<3x1x1x7xf16>
}
@@ -38,71 +50,22 @@ func.func @unary_resize_bilinear_fp16(%arg0 : tensor<3x1x1x7xf16>) -> tensor<3x1
// CHECK-LABEL: @unary_resize_nearest_i8
func.func @unary_resize_nearest_i8(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi8> {
- %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi8>
+ %scale = tosa.const_shape { value = dense<[2, 1, 3, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<3x1x1x7xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x1x7xi8>
// CHECK: return %arg0
return %resize : tensor<3x1x1x7xi8>
}
// -----
-// CHECK-LABEL: @broadcast_resize_nearest_f32
-func.func @broadcast_resize_nearest_f32(%arg0 : tensor<3x1x1x7xf32>) -> tensor<3x1x5x7xf32> {
- // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %arg0
- // CHECK-NEXT{literal}: [[0], [1, 2, 3]] : tensor<3x1x1x7xf32> into tensor<3x7xf32>
- // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x1x5x7xf32>
- // CHECK: %[[GENERIC:.+]] = linalg.generic
- // CHECK-SAME: indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel", "parallel"]}
- // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xf32>) outs(%[[EMPTY]] : tensor<3x1x5x7xf32>)
- // CHECK: ^bb0(%[[IN:.+]]: f32, %[[OUT:.+]]: f32):
- // CHECK: linalg.yield %[[IN]] : f32
- %resize = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xf32>) -> tensor<3x1x5x7xf32>
-
- // CHECK: return %[[GENERIC]]
- return %resize : tensor<3x1x5x7xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @broadcast_resize_bilinear_i8
-func.func @broadcast_resize_bilinear_i8(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x4x5x7xi32> {
- // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %arg0
- // CHECK-SAME{literal}: [[0], [1, 2, 3]] : tensor<3x1x1x7xi8> into tensor<3x7xi8>
- // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x7xi32>
- // CHECK: %[[RESIZE:.+]] = linalg.generic
- // CHECK-SAME: {indexing_maps = [#map, #map], iterator_types = ["parallel", "parallel"]}
- // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xi8>) outs(%[[EMPTY]] : tensor<3x7xi32>)
- // CHECK: ^bb0(%[[IN:.+]]: i8, %[[OUT:.+]]: i32):
- // CHECK: %[[EXT:.+]] = arith.extsi %[[IN]] : i8 to i32
- // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : i32
- // CHECK: %[[MUL:.+]] = arith.muli %[[EXT]], %[[C2]] : i32
- // CHECK-DAG: %[[C3:.+]] = arith.constant 3 : i32
- // CHECK: %[[OUT:.+]] = arith.muli %[[MUL]], %[[C3]] : i32
- // CHECK: linalg.yield %[[OUT]] : i32
- // CHECK: } -> tensor<3x7xi32>
- // CHECK: %[[EXPAND:.+]] = tensor.expand_shape %1
- // CHECK-SAME{literal}: [[0], [1, 2, 3]] : tensor<3x7xi32> into tensor<3x1x1x7xi32>
- // CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %expanded
- // CHECK-SAME{literal}:[[0], [1, 2, 3]] : tensor<3x1x1x7xi32> into tensor<3x7xi32>
- // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x4x5x7xi32>
- // CHECK: %[[BROADCAST:.+]] = linalg.generic
- // CHECK-SAME: indexing_maps = [#map1, #map2], iterator_types = ["parallel", "parallel", "parallel", "parallel"]}
- // CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xi32>) outs(%[[EMPTY]] : tensor<3x4x5x7xi32>) {
- // CHECK: ^bb0(%[[IN:.+]]: i32, %[[OUT:.+]]: i32):
- // CHECK: linalg.yield %[[IN]] : i32
- %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xi8>) -> tensor<3x4x5x7xi32>
-
- // CHECK: return %[[BROADCAST]]
- return %resize : tensor<3x4x5x7xi32>
-}
-
-// -----
-
// CHECK-LABEL: @unary_resize_bilinear_i32
func.func @unary_resize_bilinear_i32(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi32> {
// CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape %arg0
// CHECK-SAME{literal}: [[0], [1, 2, 3]] : tensor<3x1x1x7xi8> into tensor<3x7xi8>
// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x7xi32>
- // CHECK: %[[GENERIC:.+]] = linalg.generic
+ // CHECK: %[[GENERIC:.+]] = linalg.generic
// CHECK-SAME: indexing_maps = [#map, #map]
// CHECK-SAME: iterator_types = ["parallel", "parallel"]}
// CHECK-SAME: ins(%[[COLLAPSE]] : tensor<3x7xi8>) outs(%[[EMPTY]] : tensor<3x7xi32>) {
@@ -111,12 +74,15 @@ func.func @unary_resize_bilinear_i32(%arg0 : tensor<3x1x1x7xi8>) -> tensor<3x1x1
// CHECK-DAG: %[[C2:.+]] = arith.constant 2 : i32
// CHECK: %[[MUL0:.+]] = arith.muli %[[EXT]], %[[C2]] : i32
// CHECK-DAG: %[[C1:.+]] = arith.constant 2 : i32
- // CHECK: %4 = arith.muli %3, %[[C1]] : i32
- // CHECK: linalg.yield %4 : i32
+ // CHECK: %7 = arith.muli %6, %[[C1]] : i32
+ // CHECK: linalg.yield %7 : i32
// CHECK: } -> tensor<3x7xi32>
// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %[[GENERIC:.+]]
// CHECK-SAME{literal} [[0], [1, 2, 3]] : tensor<3x7xi32> into tensor<3x1x1x7xi32>
- %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 2, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x1x7xi8>) -> tensor<3x1x1x7xi32>
+ %scale = tosa.const_shape { value = dense<[2, 1, 2, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<3x1x1x7xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x1x7xi32>
// CHECK: return %[[EXPAND]]
return %resize : tensor<3x1x1x7xi32>
@@ -184,7 +150,10 @@ func.func @resize_nearest_int(%arg0: tensor<1x15x13x1xi8>) -> () {
// CHECK: linalg.yield %[[EXTRACT]]
// Round to the nearest index.
- %0 = "tosa.resize"(%arg0) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 11, 7, 89, 6>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<1x23x179x1xi8>
+ %scale = tosa.const_shape { value = dense<[11, 7, 89, 6]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x15x13x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x23x179x1xi8>
return
}
@@ -193,7 +162,7 @@ func.func @resize_nearest_int(%arg0: tensor<1x15x13x1xi8>) -> () {
// CHECK-LABEL: @resize_bilinear_int
// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]:
func.func @resize_bilinear_int(%arg0: tensor<1x19x20x1xi8>) {
- // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x304x320x1xi48>
+ // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x289x305x1xi48>
// CHECK: %[[GENERIC:.+]] = linalg.generic
// CHECK: %[[IDX_0:.+]] = linalg.index 0
// CHECK: %[[IDX_1:.+]] = linalg.index 1
@@ -285,7 +254,10 @@ func.func @resize_bilinear_int(%arg0: tensor<1x19x20x1xi8>) {
// CHECK: linalg.yield %[[RESULT]]
// Round to the nearest index.
- %0 = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 16, 1, 16, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x19x20x1xi8>) -> tensor<1x304x320x1xi48>
+ %scale = tosa.const_shape { value = dense<[16, 1, 16, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x19x20x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x289x305x1xi48>
return
}
@@ -349,7 +321,10 @@ func.func @resize_nearest_fp32(%input: tensor<1x50x48x1xf32>) -> () {
// CHECK: %[[EXTRACT:.+]] = tensor.extract %arg0[%[[IDX0]], %[[IDY]], %[[IDX]], %[[IDX3]]]
// CHECK: linalg.yield %[[EXTRACT]]
- %output = "tosa.resize"(%input) {mode = "NEAREST_NEIGHBOR", scale = array<i64: 64, 2, 64, 2>, offset = array<i64: -31, -31>, border = array<i64: 31, 31>} : (tensor<1x50x48x1xf32>) -> tensor<1x1600x1536x1xf32>
+ %scale = tosa.const_shape { value = dense<[64, 2, 64, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-31, -31]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[31, 31]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %output = tosa.resize %input, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x50x48x1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x1600x1536x1xf32>
return
}
@@ -357,7 +332,7 @@ func.func @resize_nearest_fp32(%input: tensor<1x50x48x1xf32>) -> () {
// CHECK-LABEL: @resize_bilinear_fp
func.func @resize_bilinear_fp(%input: tensor<1x23x24x1xf32>) -> () {
- // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x92x96x1xf32>
+ // CHECK: %[[INIT:.+]] = tensor.empty() : tensor<1x89x93x1xf32>
// CHECK: %[[GENERIC:.+]] = linalg.generic
// CHECK: %[[IDX_0:.+]] = linalg.index 0
// CHECK: %[[IDX_1:.+]] = linalg.index 1
@@ -441,7 +416,10 @@ func.func @resize_bilinear_fp(%input: tensor<1x23x24x1xf32>) -> () {
// CHECK: linalg.yield %[[RESULT]]
// Round by bilinear interpolation
- %output = "tosa.resize"(%input) {mode = "BILINEAR", scale = array<i64: 4, 1, 4, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x23x24x1xf32>) -> tensor<1x92x96x1xf32>
+ %scale = tosa.const_shape { value = dense<[4, 1, 4, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %output = tosa.resize %input, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x23x24x1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x89x93x1xf32>
return
}
@@ -455,7 +433,10 @@ func.func @resize_dyn(%input: tensor<?x2x2x1xi8>) -> () {
// CHECK: %[[BATCH:.+]] = tensor.dim %arg0, %[[C0]]
// CHECK: %[[INIT:.+]] = tensor.empty(%[[BATCH]]) : tensor<?x4x4x1xi32>
// CHECK: %[[GENERIC:.+]] = linalg.generic
- %output = "tosa.resize"(%input) { scale = array<i64: 4, 2, 4, 2>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR" } : (tensor<?x2x2x1xi8>) -> (tensor<?x4x4x1xi32>)
+ %scale = tosa.const_shape { value = dense<[4, 2, 4, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-1, -1]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[1, 1]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %output = tosa.resize %input, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<?x2x2x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> (tensor<?x4x4x1xi32>)
return
}
@@ -463,14 +444,17 @@ func.func @resize_dyn(%input: tensor<?x2x2x1xi8>) -> () {
// CHECK-LABEL: @resize_bilinear_int48
func.func @resize_bilinear_int48(%arg0: tensor<1x19x19x1xi16>) {
- %0 = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 16, 1, 16, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x19x19x1xi16>) -> tensor<1x289x289x1xi48>
+ %scale = tosa.const_shape { value = dense<[16, 1, 16, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x19x19x1xi16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x289x289x1xi48>
return
}
// -----
// CHECK-LABEL: skip_interpolate_bilinear_i8
-func.func @skip_interpolate_bilinear_i8(%arg0 : tensor<3x1x2x7xi8>) -> tensor<3x1x5x7xi32> {
+func.func @skip_interpolate_bilinear_i8(%arg0 : tensor<3x1x2x7xi8>) -> tensor<3x1x4x7xi32> {
// CHECK: %[[GENERIC:.+]] = linalg.generic
// CHECK: %[[BATCH:.+]] = linalg.index 0
// CHECK: %[[CHANNEL:.+]] = linalg.index 3
@@ -486,14 +470,17 @@ func.func @skip_interpolate_bilinear_i8(%arg0 : tensor<3x1x2x7xi8>) -> tensor<3x
// CHECK: %[[ADD:.+]] = arith.addi %[[MUL0]], %[[MUL1]]
// CHECK: %[[RES:.+]] = arith.muli %[[ADD]], %[[C2]]
// CHECK: linalg.yield %[[RES]]
- %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x2x7xi8>) -> tensor<3x1x5x7xi32>
+ %scale = tosa.const_shape { value = dense<[2, 1, 3, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<3x1x2x7xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x4x7xi32>
// CHECK: return %[[GENERIC]]
- return %resize : tensor<3x1x5x7xi32>
+ return %resize : tensor<3x1x4x7xi32>
}
// CHECK-LABEL: skip_interpolate_bilinear_f32
-func.func @skip_interpolate_bilinear_f32(%arg0 : tensor<3x1x2x7xf32>) -> tensor<3x1x5x7xf32> {
+func.func @skip_interpolate_bilinear_f32(%arg0 : tensor<3x1x2x7xf32>) -> tensor<3x1x4x7xf32> {
// CHECK: %[[GENERIC:.+]] = linalg.generic
// CHECK: %[[BATCH:.+]] = linalg.index 0 : index
// CHECK: %[[CHANNEL:.+]] = linalg.index 3 : index
@@ -505,8 +492,11 @@ func.func @skip_interpolate_bilinear_f32(%arg0 : tensor<3x1x2x7xf32>) -> tensor<
// CHECK: %[[MUL1:.+]] = arith.mulf %[[EXTRACT1]], %[[DX]]
// CHECK: %[[ADD:.+]] = arith.addf %[[MUL0]], %[[MUL1]]
// CHECK: linalg.yield %[[ADD]]
- %resize = "tosa.resize"(%arg0) {mode = "BILINEAR", scale = array<i64: 2, 1, 3, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<3x1x2x7xf32>) -> tensor<3x1x5x7xf32>
+ %scale = tosa.const_shape { value = dense<[2, 1, 3, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<3x1x2x7xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<3x1x4x7xf32>
// CHECK: return %[[GENERIC]]
- return %resize : tensor<3x1x5x7xf32>
+ return %resize : tensor<3x1x4x7xf32>
}
diff --git a/mlir/test/Dialect/Tosa/canonicalize.mlir b/mlir/test/Dialect/Tosa/canonicalize.mlir
index 62b260ec0d4337..5959ec66748edf 100644
--- a/mlir/test/Dialect/Tosa/canonicalize.mlir
+++ b/mlir/test/Dialect/Tosa/canonicalize.mlir
@@ -709,7 +709,10 @@ func.func @single_bit_reshape() -> tensor<1xi1> {
// CHECK-LABEL: @fold_resize_nearest
func.func @fold_resize_nearest(%arg0 : tensor<1x15x13x1xi8>) -> tensor<1x15x13x1xi8> {
// CHECK: return %arg0
- %resize = tosa.resize %arg0 {mode = "NEAREST_NEIGHBOR" , scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<1x15x13x1xi8>
+ %scale = tosa.const_shape { value = dense<[2, 2, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x15x13x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x15x13x1xi8>
return %resize : tensor<1x15x13x1xi8>
}
@@ -718,7 +721,10 @@ func.func @fold_resize_nearest(%arg0 : tensor<1x15x13x1xi8>) -> tensor<1x15x13x1
// CHECK-LABEL: @fold_resize_bilinear
func.func @fold_resize_bilinear(%arg0 : tensor<1x15x13x1xi8>) -> tensor<1x15x13x1xi8> {
// CHECK: return %arg0
- %resize = tosa.resize %arg0 {mode = "BILINEAR" , scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<1x15x13x1xi8>
+ %scale = tosa.const_shape { value = dense<[2, 2, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %resize = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x15x13x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x15x13x1xi8>
return %resize : tensor<1x15x13x1xi8>
}
diff --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir
index cbca8983cc4d2f..a24ae4f15396cf 100644
--- a/mlir/test/Dialect/Tosa/invalid.mlir
+++ b/mlir/test/Dialect/Tosa/invalid.mlir
@@ -1057,3 +1057,63 @@ func.func @test_sub_with_unequal_result_ranks(%arg0: tensor<1x21x3xf32>, %arg1:
%0 = tosa.sub %arg0, %arg1 : (tensor<1x21x3xf32>, tensor<13x21x3xf32>) -> tensor<1x13x21x3xf32>
return %0 : tensor<1x13x21x3xf32>
}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_scale_values
+func.func @test_resize_invalid_scale_values(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
+ %scale = tosa.const_shape { value = dense<[2, 0, -1, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect all scale values to be > 0, got 2, 0, -1, 2}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
+ return %1 : tensor<?x?x?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_wholly_divisible_height
+func.func @test_resize_invalid_wholly_divisible_height(%arg0: tensor<1x8x8x8xf32>) -> tensor<1x8x8x8xf32> {
+ %scale = tosa.const_shape { value = dense<[1, 3, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expected (input_height - 1) * scale_y_n - offset_y + border_y to be wholly divisible by scale_y_d, got ((8 - 1) * 1 - 0 + 0) / 3}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x8x8x8xf32>
+ return %1 : tensor<1x8x8x8xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_output_height
+func.func @test_resize_invalid_output_height(%arg0: tensor<1x8x8x8xf32>) -> tensor<1x9x8x8xf32> {
+ %scale = tosa.const_shape { value = dense<[2, 1, 1, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op calculated output height did not match expected: calculated=15, expected=9}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x9x8x8xf32>
+ return %1 : tensor<1x9x8x8xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_wholly_divisible_width
+func.func @test_resize_invalid_wholly_divisible_width(%arg0: tensor<1x8x8x8xf32>) -> tensor<1x8x8x8xf32> {
+ %scale = tosa.const_shape { value = dense<[1, 1, 1, 3]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expected (input_width - 1) * scale_x_n - offset_x + border_x to be wholly divisible by scale_x_d, got ((8 - 1) * 1 - 0 + 0) / 3}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x8x8x8xf32>
+ return %1 : tensor<1x8x8x8xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_output_width
+func.func @test_resize_invalid_output_width(%arg0: tensor<1x8x8x8xf32>) -> tensor<1x8x9x8xf32> {
+ %scale = tosa.const_shape { value = dense<[1, 1, 2, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op calculated output width did not match expected: calculated=15, expected=9}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x8x9x8xf32>
+ return %1 : tensor<1x8x9x8xf32>
+}
diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir
index 0fe35d88f0e73a..9c3f26e54d4242 100644
--- a/mlir/test/Dialect/Tosa/level_check.mlir
+++ b/mlir/test/Dialect/Tosa/level_check.mlir
@@ -674,20 +674,26 @@ func.func @test_transpose_conv2d_stride_x(%arg0: tensor<1x32x32x8xf32>, %arg1: t
// -----
-func.func @test_resize_scale_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
+func.func @test_resize_scale_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x7970x64x8xf32> {
+ %scale = tosa.const_shape { value = dense<[257, 1, 4, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-1, -1]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[1, 1]> : tensor<2xindex> } : () -> !tosa.shape<2>
// expected-error at +1 {{'tosa.resize' op failed level check: scale_y_n/scale_y_d <= MAX_SCALE}}
- %1 = "tosa.resize"(%arg0) { scale = array<i64: 257, 1, 4, 2>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR"} :
- (tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32>
- return %1 : tensor<1x64x64x8xf32>
+ %1 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} :
+ (tensor<1x32x32x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x7970x64x8xf32>
+ return %1 : tensor<1x7970x64x8xf32>
}
// -----
-func.func @test_resize_scale_x(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
+func.func @test_resize_scale_x(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x7970x8xf32> {
+ %scale = tosa.const_shape { value = dense<[4, 2, 257, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-1, -1]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[1, 1]> : tensor<2xindex> } : () -> !tosa.shape<2>
// expected-error at +1 {{'tosa.resize' op failed level check: scale_x_n/scale_x_d <= MAX_SCALE}}
- %1 = "tosa.resize"(%arg0) { scale = array<i64: 4, 2, 257, 1>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR"} :
- (tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32>
- return %1 : tensor<1x64x64x8xf32>
+ %1 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} :
+ (tensor<1x32x32x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x64x7970x8xf32>
+ return %1 : tensor<1x64x7970x8xf32>
}
// -----
diff --git a/mlir/test/Dialect/Tosa/ops.mlir b/mlir/test/Dialect/Tosa/ops.mlir
index be23dd6d3b49f7..44c10561d15692 100644
--- a/mlir/test/Dialect/Tosa/ops.mlir
+++ b/mlir/test/Dialect/Tosa/ops.mlir
@@ -633,7 +633,10 @@ func.func @test_scatter(%arg0: tensor<13x21x3xf32>, %arg1: tensor<13x26xi32>, %a
// -----
// CHECK-LABEL: resize
func.func @test_resize(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
- %1 = tosa.resize %arg0 { scale = array<i64: 4, 2, 4, 2>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR" } : (tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32>
+ %scale = tosa.const_shape { value = dense<[4, 2, 4, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-1, -1]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[1, 1]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %1 = tosa.resize %arg0, %scale, %offset, %border { mode = "BILINEAR" } : (tensor<1x32x32x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x64x64x8xf32>
return %1 : tensor<1x64x64x8xf32>
}
diff --git a/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir b/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir
index 7f335cc4a4d627..f0e03efb5c5513 100644
--- a/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir
@@ -1005,8 +1005,11 @@ func.func @transpose_conv2d_strided(%arg0: tensor<1x5x7x1xf32>, %arg1: tensor<1x
// CHECK-LABEL: @resize_int_horizontal
func.func @resize_int_horizontal(%arg0: tensor<1x15x13x1xi8>) {
+ %scale = tosa.const_shape { value = dense<[11, 7, 89, 6]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x23x179x1xi8>
- %0 = tosa.resize %arg0 {mode = "NEAREST_NEIGHBOR", scale = array<i64: 11, 7, 89, 6>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<?x?x?x?xi8>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x15x13x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xi8>
return
}
@@ -1014,8 +1017,11 @@ func.func @resize_int_horizontal(%arg0: tensor<1x15x13x1xi8>) {
// CHECK-LABEL: @resize_int_vertical
func.func @resize_int_vertical(%arg0: tensor<1x49x42x1xi16>) {
+ %scale = tosa.const_shape { value = dense<[37, 16, 219, 41]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x112x220x1xi16>
- %0 = tosa.resize %arg0 {mode = "NEAREST_NEIGHBOR", scale = array<i64: 37, 16, 219, 41>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x49x42x1xi16>) -> tensor<?x?x?x?xi16>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x49x42x1xi16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xi16>
return
}
@@ -1023,8 +1029,11 @@ func.func @resize_int_vertical(%arg0: tensor<1x49x42x1xi16>) {
// CHECK-LABEL: @resize_int_power_of_two_upscale
func.func @resize_int_power_of_two_upscale(%arg0: tensor<1x23x19x1xi8>) {
+ %scale = tosa.const_shape { value = dense<[16, 1, 16, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x353x289x1xi32>
- %0 = tosa.resize %arg0 {mode = "BILINEAR", scale = array<i64: 16, 1, 16, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x23x19x1xi8>) -> tensor<?x?x?x?xi32>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x23x19x1xi8>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xi32>
return
}
@@ -1032,24 +1041,33 @@ func.func @resize_int_power_of_two_upscale(%arg0: tensor<1x23x19x1xi8>) {
// CHECK-LABEL: @resize_int_power_of_two_upscale_offsetted
func.func @resize_int_power_of_two_upscale_offsetted(%arg0: tensor<1x41x26x1xi16>) {
+ %scale = tosa.const_shape { value = dense<[16, 2, 16, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-7, -7]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[7, 7]> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x328x208x1xi48>
- %0 = tosa.resize %arg0 {mode = "BILINEAR", scale = array<i64: 16, 2, 16, 2>, offset = array<i64: -7, -7>, border = array<i64: 7, 7>} : (tensor<1x41x26x1xi16>) -> tensor<?x?x?x?xi48>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x41x26x1xi16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xi48>
return
}
// -----
// CHECK-LABEL: @resize_fp_horizontal
func.func @resize_fp_horizontal(%arg0: tensor<1x50x48x1xf32>) {
+ %scale = tosa.const_shape { value = dense<[15, 7, 84, 47]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x106x85x1xf32>
- %0 = tosa.resize %arg0 {mode = "BILINEAR", scale = array<i64: 15, 7, 84, 47>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x50x48x1xf32>) -> tensor<?x?x?x?xf32>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x50x48x1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
return
}
// -----
// CHECK-LABEL: @resize_fp_vertical
func.func @resize_fp_vertical(%arg0: tensor<1x50x48x1xf32>) {
+ %scale = tosa.const_shape { value = dense<[127, 49, 12, 47]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x128x13x1xf32>
- %0 = tosa.resize %arg0 {mode = "NEAREST_NEIGHBOR", scale = array<i64: 127, 49, 12, 47>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x50x48x1xf32>) -> tensor<?x?x?x?xf32>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x50x48x1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
return
}
@@ -1057,8 +1075,11 @@ func.func @resize_fp_vertical(%arg0: tensor<1x50x48x1xf32>) {
// CHECK-LABEL: @resize_fp_power_of_two_upscale
func.func @resize_fp_power_of_two_upscale(%arg0: tensor<1x23x23x1xf32>) {
+ %scale = tosa.const_shape { value = dense<[4, 1, 4, 1]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<0> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x89x89x1xf32>
- %0 = tosa.resize %arg0 {mode = "BILINEAR", scale = array<i64: 4, 1, 4, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x23x23x1xf32>) -> tensor<?x?x?x?xf32>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "BILINEAR"} : (tensor<1x23x23x1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
return
}
@@ -1066,8 +1087,11 @@ func.func @resize_fp_power_of_two_upscale(%arg0: tensor<1x23x23x1xf32>) {
// CHECK-LABEL: @resize_fp_power_of_two_upscale_offsetted
func.func @resize_fp_power_of_two_upscale_offsetted(%arg0: tensor<1x50x48x1xf32>) {
+ %scale = tosa.const_shape { value = dense<[64, 2, 64, 2]> : tensor<4xindex> } : () -> !tosa.shape<4>
+ %offset = tosa.const_shape { value = dense<[-31, -31]> : tensor<2xindex> } : () -> !tosa.shape<2>
+ %border = tosa.const_shape { value = dense<[31, 31]> : tensor<2xindex> } : () -> !tosa.shape<2>
// CHECK: -> tensor<1x1600x1536x1xf32>
- %0 = tosa.resize %arg0 {mode = "NEAREST_NEIGHBOR", scale = array<i64: 64, 2, 64, 2>, offset = array<i64: -31, -31>, border = array<i64: 31, 31>} : (tensor<1x50x48x1xf32>) -> tensor<?x?x?x?xf32>
+ %0 = tosa.resize %arg0, %scale, %offset, %border {mode = "NEAREST_NEIGHBOR"} : (tensor<1x50x48x1xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
return
}
More information about the Mlir-commits
mailing list