Skip to content
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

Allow four different rounding modes for tosa.resize #112

Draft
wants to merge 3 commits into
base: feature/fused-ops
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,8 @@ def Tosa_ResizeOp : Tosa_InferShapedTypeOp<"resize"> {
Tosa_IntArrayAttr4:$scale,
Tosa_IntArrayAttr2:$offset,
Tosa_IntArrayAttr2:$border,
Tosa_ResizeTypeAttr:$mode
Tosa_ResizeTypeAttr:$mode,
Tosa_ResizeNearestRoundingAttr:$nearest_rounding_mode
);

let results = (outs
Expand Down
8 changes: 8 additions & 0 deletions mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ def Tosa_ResizeTypeAttr : StringBasedAttr<
"::llvm::cast<StringAttr>($_self).getValue() == \"NEAREST_NEIGHBOR\"">,
"Supported resize/upsampling strategies">;

// Supported rounding modes for tosa.resize mode = NEAREST_NEIGHBOR
def Tosa_ResizeNearestRoundingAttr : StringBasedAttr<
CPred<"::llvm::cast<StringAttr>($_self).getValue() == \"ROUND_PREFER_FLOOR\" || " #
"::llvm::cast<StringAttr>($_self).getValue() == \"ROUND_PREFER_CEIL\" || " #
"::llvm::cast<StringAttr>($_self).getValue() == \"FLOOR\" || " #
"::llvm::cast<StringAttr>($_self).getValue() == \"CEIL\"">,
"Supported nearest rounding strategies">;

def Tosa_TensorTypeAttr : TypeAttrBase<"TensorType", "Tensor type attribute">;

// Tensor to buffer types.
Expand Down
41 changes: 35 additions & 6 deletions mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1663,13 +1663,42 @@ class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
}

Value pred;
if (floatingPointMode) {
auto h = b.create<arith::ConstantOp>(b.getFloatAttr(floatTy, 0.5f));
pred = b.create<arith::CmpFOp>(arith::CmpFPredicate::OGE, dval, h);
const bool isRoundPreferFloor =
op.getNearestRoundingMode() == "ROUND_PREFER_FLOOR";
// Marking as maybe_unused to avoid complains in release builds, this
// value is only used on assertions
[[maybe_unused]] const bool isRoundPreferCeil =
op.getNearestRoundingMode() == "ROUND_PREFER_CEIL";
const bool isFloor = op.getNearestRoundingMode() == "FLOOR";
const bool isCeil = op.getNearestRoundingMode() == "CEIL";

if (isFloor) {
pred = b.create<arith::ConstantOp>(b.getBoolAttr(false));
} else if (isCeil) {
pred = b.create<arith::ConstantOp>(b.getBoolAttr(true));
} else {
Value dvalDouble = b.create<arith::ShLIOp>(dval, one);
pred = b.create<arith::CmpIOp>(arith::CmpIPredicate::sge,
dvalDouble, scale);
if (floatingPointMode) {
auto h =
b.create<arith::ConstantOp>(b.getFloatAttr(floatTy, 0.5f));
if (isRoundPreferFloor) {
pred =
b.create<arith::CmpFOp>(arith::CmpFPredicate::OLT, dval, h);
} else {
assert(isRoundPreferCeil);
pred =
b.create<arith::CmpFOp>(arith::CmpFPredicate::OGE, dval, h);
}
} else {
Value dvalDouble = b.create<arith::ShLIOp>(dval, one);
if (isRoundPreferFloor) {
pred = b.create<arith::CmpIOp>(arith::CmpIPredicate::slt,
dvalDouble, scale);
} else {
assert(isRoundPreferCeil);
pred = b.create<arith::CmpIOp>(arith::CmpIPredicate::sge,
dvalDouble, scale);
}
}
}

auto offset = b.create<arith::SelectOp>(pred, one, zeroI32);
Expand Down
463 changes: 443 additions & 20 deletions mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions mlir/test/Dialect/Tosa/canonicalize.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ 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>
%resize = tosa.resize %arg0 {mode = "NEAREST_NEIGHBOR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<1x15x13x1xi8>
return %resize : tensor<1x15x13x1xi8>
}

Expand All @@ -555,7 +555,7 @@ 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>
%resize = tosa.resize %arg0 {mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 2, 2, 1, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<1x15x13x1xi8>
return %resize : tensor<1x15x13x1xi8>
}

Expand Down
4 changes: 2 additions & 2 deletions mlir/test/Dialect/Tosa/level_check.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ func.func @test_transpose_conv2d_stride_x(%arg0: tensor<1x32x32x8xf32>, %arg1: t

func.func @test_resize_scale_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
// expected-error@+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"} :
%1 = "tosa.resize"(%arg0) { scale = array<i64: 257, 1, 4, 2>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL"} :
(tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32>
return %1 : tensor<1x64x64x8xf32>
}
Expand All @@ -648,7 +648,7 @@ func.func @test_resize_scale_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8

func.func @test_resize_scale_x(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
// expected-error@+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"} :
%1 = "tosa.resize"(%arg0) { scale = array<i64: 4, 2, 257, 1>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL"} :
(tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32>
return %1 : tensor<1x64x64x8xf32>
}
Expand Down
2 changes: 1 addition & 1 deletion mlir/test/Dialect/Tosa/ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ 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>
%1 = tosa.resize %arg0 { scale = array<i64: 4, 2, 4, 2>, offset = array<i64: -1, -1>, border = array<i64: 1, 1>, mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL" } : (tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32>
return %1 : tensor<1x64x64x8xf32>
}

Expand Down
16 changes: 8 additions & 8 deletions mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ func.func @transpose_conv2d_strided(%arg0: tensor<1x5x7x1xf32>, %arg1: tensor<1x
// CHECK-LABEL: @resize_int_horizontal
func.func @resize_int_horizontal(%arg0: tensor<1x15x13x1xi8>) {
// 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 {mode = "NEAREST_NEIGHBOR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 11, 7, 89, 6>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x15x13x1xi8>) -> tensor<?x?x?x?xi8>
return
}

Expand All @@ -978,7 +978,7 @@ func.func @resize_int_horizontal(%arg0: tensor<1x15x13x1xi8>) {
// CHECK-LABEL: @resize_int_vertical
func.func @resize_int_vertical(%arg0: tensor<1x49x42x1xi16>) {
// 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 {mode = "NEAREST_NEIGHBOR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 37, 16, 219, 41>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x49x42x1xi16>) -> tensor<?x?x?x?xi16>
return
}

Expand All @@ -987,7 +987,7 @@ 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>) {
// 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 {mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 16, 1, 16, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x23x19x1xi8>) -> tensor<?x?x?x?xi32>
return
}

Expand All @@ -996,23 +996,23 @@ 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>) {
// 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 {mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 16, 2, 16, 2>, offset = array<i64: -7, -7>, border = array<i64: 7, 7>} : (tensor<1x41x26x1xi16>) -> tensor<?x?x?x?xi48>
return
}

// -----
// CHECK-LABEL: @resize_fp_horizontal
func.func @resize_fp_horizontal(%arg0: tensor<1x50x48x1xf32>) {
// 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 {mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 15, 7, 84, 47>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x50x48x1xf32>) -> tensor<?x?x?x?xf32>
return
}

// -----
// CHECK-LABEL: @resize_fp_vertical
func.func @resize_fp_vertical(%arg0: tensor<1x50x48x1xf32>) {
// 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 {mode = "NEAREST_NEIGHBOR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 127, 49, 12, 47>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x50x48x1xf32>) -> tensor<?x?x?x?xf32>
return
}

Expand All @@ -1021,7 +1021,7 @@ 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>) {
// 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 {mode = "BILINEAR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 4, 1, 4, 1>, offset = array<i64: 0, 0>, border = array<i64: 0, 0>} : (tensor<1x23x23x1xf32>) -> tensor<?x?x?x?xf32>
return
}

Expand All @@ -1030,7 +1030,7 @@ 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>) {
// 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 {mode = "NEAREST_NEIGHBOR", nearest_rounding_mode = "ROUND_PREFER_CEIL", scale = array<i64: 64, 2, 64, 2>, offset = array<i64: -31, -31>, border = array<i64: 31, 31>} : (tensor<1x50x48x1xf32>) -> tensor<?x?x?x?xf32>
return
}

Expand Down
Loading