From e21ff9d8861f5ed4a93b1c7c371536b9134158b3 Mon Sep 17 00:00:00 2001 From: Eli Amesefe Date: Sat, 11 Apr 2026 15:25:14 -0700 Subject: [PATCH] Add conv+residual tests for add/sub ifm scaling (#18754) Summary: Pull Request resolved: https://github.com/pytorch/executorch/pull/18754 Add AddConvResidual and SubConvResidual test models (conv(x) + x, conv(x) - x) that exercise non-unit ifm scales Differential Revision: D99927633 --- backends/arm/test/ops/test_add.py | 45 +++++++++++++++++++++++++++++++ backends/arm/test/ops/test_sub.py | 41 ++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/backends/arm/test/ops/test_add.py b/backends/arm/test/ops/test_add.py index d7a9d828012..be98c98ffb7 100644 --- a/backends/arm/test/ops/test_add.py +++ b/backends/arm/test/ops/test_add.py @@ -278,6 +278,51 @@ def test_add_tensor_vgf_quant(test_data: input_t1): pipeline.run() +class AddConvResidual(torch.nn.Module): + """Conv(x) + x — residual block. + + Creates non-unit IFM scales + + """ + + def __init__(self): + super().__init__() + self.conv = torch.nn.Conv2d(3, 3, 1, bias=False) + + def forward(self, x): + return self.conv(x) + x + + test_data = { + "4d_randn": lambda: (torch.randn(1, 3, 4, 4),), + } + + +@common.parametrize("test_data", AddConvResidual.test_data) +def test_add_conv_residual_tosa_INT(test_data: input_t1): + pipeline = TosaPipelineINT[input_t1]( + AddConvResidual(), test_data(), aten_op, exir_op + ) + pipeline.run() + + +@common.parametrize("test_data", AddConvResidual.test_data) +@common.XfailIfNoCorstone300 +def test_add_conv_residual_u55_INT(test_data: input_t1): + pipeline = EthosU55PipelineINT[input_t1]( + AddConvResidual(), test_data(), aten_op, exir_op + ) + pipeline.run() + + +@common.parametrize("test_data", AddConvResidual.test_data) +@common.XfailIfNoCorstone320 +def test_add_conv_residual_u85_INT(test_data: input_t1): + pipeline = EthosU85PipelineINT[input_t1]( + AddConvResidual(), test_data(), aten_op, exir_op + ) + pipeline.run() + + @common.parametrize("test_data", Add.test_data) def test_add_tensor_tosa_INT_16a8w(test_data: input_t1): """Test add operation with 16A8W quantization (16-bit activations, 8-bit diff --git a/backends/arm/test/ops/test_sub.py b/backends/arm/test/ops/test_sub.py index d0e2ce2b8d3..3da96096549 100644 --- a/backends/arm/test/ops/test_sub.py +++ b/backends/arm/test/ops/test_sub.py @@ -313,6 +313,47 @@ def test_sub_tensor_vgf_quant_2(test_data: Tuple[torch.Tensor, torch.Tensor]): pipeline.run() +class SubConvResidual(torch.nn.Module): + """conv(x) - x — residual block. Creates non-unit IFM scales""" + + def __init__(self): + super().__init__() + self.conv = torch.nn.Conv2d(3, 3, 1, bias=False) + + def forward(self, x): + return self.conv(x) - x + + test_data = { + "4d_randn": lambda: (torch.randn(1, 3, 4, 4),), + } + + +@common.parametrize("test_data", SubConvResidual.test_data) +def test_sub_conv_residual_tosa_INT(test_data: input_t1): + pipeline = TosaPipelineINT[input_t1]( + SubConvResidual(), test_data(), aten_op, exir_op + ) + pipeline.run() + + +@common.parametrize("test_data", SubConvResidual.test_data) +@common.XfailIfNoCorstone300 +def test_sub_conv_residual_u55_INT(test_data: input_t1): + pipeline = EthosU55PipelineINT[input_t1]( + SubConvResidual(), test_data(), aten_op, exir_op + ) + pipeline.run() + + +@common.parametrize("test_data", SubConvResidual.test_data) +@common.XfailIfNoCorstone320 +def test_sub_conv_residual_u85_INT(test_data: input_t1): + pipeline = EthosU85PipelineINT[input_t1]( + SubConvResidual(), test_data(), aten_op, exir_op + ) + pipeline.run() + + @common.parametrize("test_data", sub_test_data) def test_sub_tensor_16a8w_tosa_INT(test_data: input_t1): """Test sub operation with 16A8W quantization (16-bit activations, 8-bit