-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[mlir][tosa] Make TOSA RESIZE's scale, offset, border as Input #124956
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-mlir-linalg Author: Hsiangkai Wang (Hsiangkai) ChangesMove the Add the verifier of the Patch is 56.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124956.diff 13 Files Affected:
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..adc9dc0ceff616 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,81 @@ 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..5d45835002e383 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,101 @@ 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 +684,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::getCons...
[truncated]
|
@llvm/pr-subscribers-mlir-tosa Author: Hsiangkai Wang (Hsiangkai) ChangesMove the Add the verifier of the Patch is 56.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124956.diff 13 Files Affected:
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..adc9dc0ceff616 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,81 @@ 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..5d45835002e383 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,101 @@ 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 +684,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::getCons...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Hsiangkai, LGTM modulo formatting! (I authored part of this so won't explicitly approve)
Thanks @Hsiangkai for the patch. Could we pause merging this before we have a companion TF patch ready to fix RESIZE? cc @Tai78641 here as he was the original author who updated this. |
No problem. After you are ready, please help me to merge it. |
Yes, We just got the TF merge access. We will land some previous patches soon (tensorflow/tensorflow#86307). Once we finished those, we then can work on the Resize TF patch. Thanks for being patient! |
Hi @Hsiangkai , i have the TF patches ready. Could you rebase this patch then I will take another look to merge it. Thanks for waiting! |
Done. Thanks for your review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comments. Thank you @Hsiangkai
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@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…124956) 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@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/52/builds/6106 Here is the relevant piece of the build log for the reference
|
Some of the error_if checks were missed in this PR: llvm#124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Change-Id: Ic09e0e601b5a110953ae04779ffa4dc6d5476418
Some of the error_if checks were missed in this PR: #124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
Some of the error_if checks were missed in this PR: llvm/llvm-project#124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
Some of the error_if checks were missed in this PR: llvm#124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Change-Id: Ic09e0e601b5a110953ae04779ffa4dc6d5476418
Some of the error_if checks were missed in this PR: #124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
Some of the error_if checks were missed in this PR: llvm#124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
Some of the error_if checks were missed in this PR: llvm/llvm-project#124956 Add back those tests to check suitable sizes for Resize Signed-off-by: Luke Hutton <luke.hutton@arm.com> Co-authored-by: Luke Hutton <luke.hutton@arm.com>
Move the
scale
,offset
, andborder
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.