[Mlir-commits] [mlir] [mlir][tosa][tosa-to-linalg] Fix resize bilinear delta computation for negative offsets (PR #184799)
Luke Hutton
llvmlistbot at llvm.org
Thu Mar 5 06:14:13 PST 2026
https://github.com/lhutton1 created https://github.com/llvm/llvm-project/pull/184799
Use floor-consistent remainder when lowering floating-point tosa.resize to linalg: compute `r = in - floor(in/scale_n)*scale_n` instead of RemSIOp. This keeps bilinear deltas in-range for negative offsets and avoids invalid interpolation weights.
>From 35d2d7b4e15d66e6da495f265ed213bce0ff9c76 Mon Sep 17 00:00:00 2001
From: Luke Hutton <luke.hutton at arm.com>
Date: Thu, 5 Mar 2026 13:56:06 +0000
Subject: [PATCH] [mlir][tosa][tosa-to-linalg] Fix resize bilinear delta
computation for negative offsets
Use floor-consistent remainder when lowering floating-point tosa.resize to linalg:
compute `r = in - floor(in/scale_n)*scale_n` instead of RemSIOp. This keeps
bilinear deltas in-range for negative offsets and avoids invalid interpolation
weights.
Change-Id: I5f0e00c651702f60898b7e26c9b99903f8ce76eb
---
mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp | 8 +++++---
.../TosaToLinalg/tosa-to-linalg-resize.mlir | 12 ++++++++----
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
index b834106b10528..76346a766f1f7 100644
--- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
+++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp
@@ -2036,10 +2036,12 @@ class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
val = arith::AddIOp::create(b, val, offset);
index = arith::FloorDivSIOp::create(b, val, scaleN);
- // rx = x % scale_n
- // dx = rx / scale_n
- Value r = arith::RemSIOp::create(b, val, scaleN);
+ // rx = x - ix * scale_n (x % scale_n, if values are positive)
+ Value scaledIndex = arith::MulIOp::create(b, index, scaleN);
+ Value r = arith::SubIOp::create(b, val, scaledIndex);
Value rFp = arith::SIToFPOp::create(b, floatTy, r);
+
+ // dx = rx / scale_n
Value scaleNfp = arith::UIToFPOp::create(b, floatTy, scaleN);
delta = arith::DivFOp::create(b, rFp, scaleNfp);
};
diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir
index 6998aee45b887..4900476b25dc5 100644
--- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir
+++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-resize.mlir
@@ -389,7 +389,8 @@ func.func @resize_nearest_fp32(%input: tensor<1x50x48x1xf32>) -> () {
// CHECK: %[[VAL_29:.*]] = arith.muli %[[Y]], %[[SCALE_Y_D]]
// CHECK: %[[Y_TEMP:.*]] = arith.addi %[[VAL_29]], %[[OFFSET_Y]]
// CHECK: %[[IY_TEMP:.*]] = arith.floordivsi %[[Y_TEMP]], %[[SCALE_Y_N]]
- // CHECK: %[[RY:.*]] = arith.remsi %[[Y_TEMP]], %[[SCALE_Y_N]]
+ // CHECK: %[[SCALED_IY:.*]] = arith.muli %[[IY_TEMP]], %[[SCALE_Y_N]]
+ // CHECK: %[[RY:.*]] = arith.subi %[[Y_TEMP]], %[[SCALED_IY]]
// CHECK: %[[RY_FP:.*]] = arith.sitofp %[[RY]]
// CHECK: %[[SCALE_Y_N_FP:.*]] = arith.uitofp %[[SCALE_Y_N]]
// CHECK: %[[D_Y:.*]] = arith.divf %[[RY_FP]], %[[SCALE_Y_N_FP]]
@@ -397,7 +398,8 @@ func.func @resize_nearest_fp32(%input: tensor<1x50x48x1xf32>) -> () {
// CHECK: %[[VAL_30:.*]] = arith.muli %[[X]], %[[SCALE_X_D]]
// CHECK: %[[X_TEMP:.*]] = arith.addi %[[VAL_30]], %[[OFFSET_X]]
// CHECK: %[[IX_TEMP:.*]] = arith.floordivsi %[[X_TEMP]], %[[SCALE_X_N]]
- // CHECK: %[[RX:.*]] = arith.remsi %[[X_TEMP]], %[[SCALE_X_N]]
+ // CHECK: %[[SCALED_IX:.*]] = arith.muli %[[IX_TEMP]], %[[SCALE_X_N]]
+ // CHECK: %[[RX:.*]] = arith.subi %[[X_TEMP]], %[[SCALED_IX]]
// CHECK: %[[RX_FP:.*]] = arith.sitofp %[[RX]]
// CHECK: %[[SCALE_X_N_FP:.*]] = arith.uitofp %[[SCALE_X_N]]
// CHECK: %[[D_X:.*]] = arith.divf %[[RX_FP]], %[[SCALE_X_N_FP]]
@@ -456,7 +458,8 @@ func.func @resize_bilinear_fp(%input: tensor<1x23x24x1xf32>) -> () {
// CHECK: %[[VAL_29:.*]] = arith.muli %[[Y]], %[[SCALE_Y_D]]
// CHECK: %[[Y_TEMP:.*]] = arith.addi %[[VAL_29]], %[[OFFSET_Y]]
// CHECK: %[[I_Y:.*]] = arith.floordivsi %[[Y_TEMP]], %[[SCALE_Y_N]]
- // CHECK: %[[RY:.*]] = arith.remsi %[[Y_TEMP]], %[[SCALE_Y_N]]
+ // CHECK: %[[SCALED_IY:.*]] = arith.muli %[[I_Y]], %[[SCALE_Y_N]]
+ // CHECK: %[[RY:.*]] = arith.subi %[[Y_TEMP]], %[[SCALED_IY]]
// CHECK: %[[RY_FP:.*]] = arith.sitofp %[[RY]]
// CHECK: %[[SCALE_Y_N_FP:.*]] = arith.uitofp %[[SCALE_Y_N]]
// CHECK: %[[D_Y:.*]] = arith.divf %[[RY_FP]], %[[SCALE_Y_N_FP]]
@@ -464,7 +467,8 @@ func.func @resize_bilinear_fp(%input: tensor<1x23x24x1xf32>) -> () {
// CHECK: %[[VAL_30:.*]] = arith.muli %[[X]], %[[SCALE_X_D]]
// CHECK: %[[X_TEMP:.*]] = arith.addi %[[VAL_30]], %[[OFFSET_X]]
// CHECK: %[[I_X:.*]] = arith.floordivsi %[[X_TEMP]], %[[SCALE_X_N]]
- // CHECK: %[[RX:.*]] = arith.remsi %[[X_TEMP]], %[[SCALE_X_N]]
+ // CHECK: %[[SCALED_IX:.*]] = arith.muli %[[I_X]], %[[SCALE_X_N]]
+ // CHECK: %[[RX:.*]] = arith.subi %[[X_TEMP]], %[[SCALED_IX]]
// CHECK: %[[RX_FP:.*]] = arith.sitofp %[[RX]]
// CHECK: %[[SCALE_X_N_FP:.*]] = arith.uitofp %[[SCALE_X_N]]
// CHECK: %[[D_X:.*]] = arith.divf %[[RX_FP]], %[[SCALE_X_N_FP]]
More information about the Mlir-commits
mailing list