diff --git a/backends/xnnpack/test/ops/avgpool2d.py b/backends/xnnpack/test/ops/avgpool2d.py index b471fd914c2..72e0b9c7d22 100644 --- a/backends/xnnpack/test/ops/avgpool2d.py +++ b/backends/xnnpack/test/ops/avgpool2d.py @@ -29,17 +29,22 @@ def forward(self, x): return self.avgPool(x) def _test_argpool2d(self, inputs): - ( - Tester(self.AvgPool2d(), inputs) - .export() - .check_count({"torch.ops.aten.avg_pool2d.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_avg_pool2d_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.AvgPool2d(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.avg_pool2d.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_avg_pool2d_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_avgpool2d(self): inputs = (torch.randn(1, 1, 10, 10).to(torch.float16),) @@ -54,36 +59,45 @@ def test_fp32_avgpool2d_ceil_mode_unsupported(self): The XNNPACK backend does not support ceil mode. """ inputs = (torch.randn(1, 1, 10, 10),) - ( - Tester(self.AvgPool2d(ceil_mode=True), inputs) - .export() - .check_count({"torch.ops.aten.avg_pool2d.default": 1}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + for legacy in (True, False): + tester = Tester(self.AvgPool2d(ceil_mode=True), inputs) + tester.export() + tester.check_count({"torch.ops.aten.avg_pool2d.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) def test_fp32_avgpool2d_count_include_pad_unsupported(self): """ The XNNPACK backend does not support count_include_pad=True. """ inputs = (torch.randn(1, 1, 10, 10),) - ( - Tester(self.AvgPool2d(count_include_pad=True), inputs) - .export() - .check_count({"torch.ops.aten.avg_pool2d.default": 1}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + for legacy in (True, False): + tester = Tester(self.AvgPool2d(count_include_pad=True), inputs) + tester.export() + tester.check_count({"torch.ops.aten.avg_pool2d.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) def test_fp32_avgpool2d_divisor_override(self): """ The XNNPACK backend does not support divisor overrides not equal to the pooling region. """ inputs = (torch.randn(1, 1, 10, 10),) - ( - Tester(self.AvgPool2d(divisor_override=5), inputs) - .export() - .check_count({"torch.ops.aten.avg_pool2d.default": 1}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + for legacy in (True, False): + tester = Tester(self.AvgPool2d(divisor_override=5), inputs) + tester.export() + tester.check_count({"torch.ops.aten.avg_pool2d.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) diff --git a/backends/xnnpack/test/ops/bilinear2d.py b/backends/xnnpack/test/ops/bilinear2d.py index bf89e2196f7..a126569f77e 100644 --- a/backends/xnnpack/test/ops/bilinear2d.py +++ b/backends/xnnpack/test/ops/bilinear2d.py @@ -78,43 +78,72 @@ def forward(self, x): "executorch_exir_dialects_edge__ops_aten_clamp_default", } + @unittest.skip('Expected to not find "aten_index_Tensor"') + def test_fp32_static_resize_bilinear2d_legacy(self): + example_inputs = (torch.randn(2, 3, 4, 5),) + tester = Tester(self.StaticResizeBilinear2dModule(), example_inputs) + tester.export() + tester.to_edge() + tester.partition() + tester.check_not(self.ops) + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() + def test_fp32_static_resize_bilinear2d(self): example_inputs = (torch.randn(2, 3, 4, 5),) - ( - Tester(self.StaticResizeBilinear2dModule(), example_inputs) - .export() - .to_edge_transform_and_lower() - .check_not(self.ops) - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() + tester = Tester(self.StaticResizeBilinear2dModule(), example_inputs) + tester.export() + tester.to_edge_transform_and_lower() + tester.check_not(self.ops) + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() + + @unittest.skip('Expected to not find "aten_index_Tensor"') + def test_fp32_static_resize_bilinear2d_with_align_corners_legacy(self): + example_inputs = (torch.randn(2, 3, 4, 5),) + tester = Tester( + self.StaticResizeBilinear2dModuleWithAlignCorners(), example_inputs ) + tester.export() + tester.to_edge() + tester.partition() + tester.check_not(self.ops) + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp32_static_resize_bilinear2d_with_align_corners(self): example_inputs = (torch.randn(2, 3, 4, 5),) - ( - Tester(self.StaticResizeBilinear2dModuleWithAlignCorners(), example_inputs) - .export() - .to_edge_transform_and_lower() - .check_not(self.ops) - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() + tester = Tester( + self.StaticResizeBilinear2dModuleWithAlignCorners(), example_inputs ) + tester.export() + tester.to_edge_transform_and_lower() + tester.check_not(self.ops) + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp32_static_resize_bilinear2d_antialiased(self): # Check bilinear2d_aa is not partitioned example_inputs = (torch.randn(2, 3, 4, 5),) - ( - Tester(self.Bilinear2dAntiAlias(), example_inputs) - .export() - .to_edge_transform_and_lower() - .check_count( + for legacy in (True, False): + tester = Tester(self.Bilinear2dAntiAlias(), example_inputs) + tester.export() + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count( { "executorch_exir_dialects_edge__ops_aten__upsample_bilinear2d_aa_default": 2 } ) - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) diff --git a/backends/xnnpack/test/ops/bmm.py b/backends/xnnpack/test/ops/bmm.py index 1c6235e5f7e..9db9a8ed935 100644 --- a/backends/xnnpack/test/ops/bmm.py +++ b/backends/xnnpack/test/ops/bmm.py @@ -19,17 +19,20 @@ def forward(self, x, y): return torch.bmm(x, y) def _test_bmm(self, inputs): - ( - Tester(self.BMM(), inputs) - .export() - .check_count({"torch.ops.aten.bmm.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_bmm_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.BMM(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.bmm.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_bmm_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_bmm(self): inputs = ( diff --git a/backends/xnnpack/test/ops/ceil.py b/backends/xnnpack/test/ops/ceil.py index 6dbebf36502..197dc0fe8fb 100644 --- a/backends/xnnpack/test/ops/ceil.py +++ b/backends/xnnpack/test/ops/ceil.py @@ -20,17 +20,20 @@ def forward(self, x): return z def _test_ceil(self, inputs): - ( - Tester(self.Ceil(), inputs) - .export() - .check_count({"torch.ops.aten.ceil.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_ceil_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Ceil(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.ceil.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_ceil_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_ceil(self): inputs = ( diff --git a/backends/xnnpack/test/ops/clamp.py b/backends/xnnpack/test/ops/clamp.py index 9fb8935553e..1921dbc80c9 100644 --- a/backends/xnnpack/test/ops/clamp.py +++ b/backends/xnnpack/test/ops/clamp.py @@ -22,17 +22,20 @@ def forward(self, x): return z + z def _test_clamp(self, module, inputs): - ( - Tester(module, inputs) - .export() - .check_count({"torch.ops.aten.clamp.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_clamp_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + tester.check_count({"torch.ops.aten.clamp.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_clamp_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_clamp(self): inputs = (torch.randn(1, 4, 122, 122).to(torch.float16) * 2,) @@ -56,21 +59,24 @@ def test_fp32_clamp_upper(self): def test_qs8_clamp(self): inputs = (torch.randn(1, 4, 122, 122),) - ( - Tester(self.Clamp(min_val=-1, max_val=1), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.clamp.default": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Clamp(min_val=-1, max_val=1), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.clamp.default": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_clamp_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/conv1d.py b/backends/xnnpack/test/ops/conv1d.py index 833ad69da68..65c05c756e0 100644 --- a/backends/xnnpack/test/ops/conv1d.py +++ b/backends/xnnpack/test/ops/conv1d.py @@ -10,11 +10,17 @@ from executorch.backends.xnnpack.partition.config.xnnpack_config import ( ConfigPrecisionType, ) -from executorch.backends.xnnpack.partition.xnnpack_partitioner import XnnpackPartitioner +from executorch.backends.xnnpack.partition.xnnpack_partitioner import ( + XnnpackFloatingPointPartitioner, + XnnpackPartitioner, +) from executorch.backends.xnnpack.test.test_xnnpack_utils import randomize_bn from executorch.backends.xnnpack.test.tester import RunPasses, Tester -from executorch.backends.xnnpack.test.tester.tester import ToEdgeTransformAndLower +from executorch.backends.xnnpack.test.tester.tester import ( + Partition, + ToEdgeTransformAndLower, +) from executorch.exir.passes.constant_prop_pass import constant_prop_pass @@ -95,26 +101,39 @@ def _test_conv1d( quantized=False, dynamic_shape=None, passes=None, + partitioner=None, stage=None, skip_to_executorch=False, ): - tester = ( - ( + for legacy in (True, False): + tester = ( Tester(module, inputs, dynamic_shape).quantize() if quantized - else Tester(module, inputs) + else Tester(module, inputs, dynamic_shape) ) - .export() - .run_passes(passes) - .check_count({"torch.ops.aten.conv1d.default": conv_count}) - .to_edge_transform_and_lower(stage) - .check_not(["executorch_exir_dialects_edge__ops_aten_convolution_default"]) - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - ) - # For some tests we want to skip to_executorch because otherwise it will require the - # quantized operators to be loaded and we don't want to do that in the test. - if not skip_to_executorch: - tester.to_executorch().serialize().run_method_and_compare_outputs() + tester.export() + tester.check_count({"torch.ops.aten.conv1d.default": conv_count}) + if legacy: + tester.to_edge() + tester.check_count( + { + "executorch_exir_dialects_edge__ops_aten_convolution_default": conv_count + } + ) + tester.run_passes(passes) + tester.partition(partitioner) + else: + tester.run_passes(passes) + tester.to_edge_transform_and_lower(stage) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_convolution_default"] + ) + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + + # For some tests we want to skip to_executorch because otherwise it will require the + # quantized operators to be loaded and we don't want to do that in the test. + if not skip_to_executorch: + tester.to_executorch().serialize().run_method_and_compare_outputs() def test_fp16_conv1d(self): inputs = (torch.randn(2, 2, 4).to(torch.float16),) @@ -129,20 +148,32 @@ def test_fp16_conv1d(self): def test_fp32_conv1d(self): inputs = (torch.randn(2, 2, 4),) dynamic_shapes = ({0: torch.export.Dim("batch", min=2, max=10)},) - self._test_conv1d(self.Conv1d(), inputs, 1, dynamic_shape=dynamic_shapes) + self._test_conv1d( + self.Conv1d(), + inputs, + 1, + dynamic_shape=dynamic_shapes, + ) def test_fp32_conv1d_batchnorm_seq(self): inputs = (torch.randn(2, 2, 4),) dynamic_shapes = ({0: torch.export.Dim("batch", min=2, max=10)},) self._test_conv1d( - self.Conv1dBatchNormSequential(), inputs, 2, dynamic_shape=dynamic_shapes + self.Conv1dBatchNormSequential(), + inputs, + 2, + dynamic_shape=dynamic_shapes, ) def test_qs8_conv1d(self): inputs = (torch.randn(2, 2, 4),) dynamic_shapes = ({0: torch.export.Dim("batch", min=2, max=10)},) self._test_conv1d( - self.Conv1d(), inputs, 1, quantized=True, dynamic_shape=dynamic_shapes + self.Conv1d(), + inputs, + 1, + quantized=True, + dynamic_shape=dynamic_shapes, ) def test_qs8_conv1d_batchnorm_seq(self): @@ -165,6 +196,7 @@ def test_qs8_conv1d_with_floating_point_partitioner(self): 1, quantized=True, dynamic_shape=dynamic_shapes, + partitioner=Partition(XnnpackFloatingPointPartitioner()), stage=ToEdgeTransformAndLower( partitioners=[ XnnpackPartitioner(config_precisions=ConfigPrecisionType.FP32) diff --git a/backends/xnnpack/test/ops/conv2d.py b/backends/xnnpack/test/ops/conv2d.py index 95b22bb3f8a..b2ab3ae8476 100644 --- a/backends/xnnpack/test/ops/conv2d.py +++ b/backends/xnnpack/test/ops/conv2d.py @@ -9,6 +9,7 @@ from typing import Optional import torch + from executorch.backends.xnnpack.test.test_xnnpack_utils import randomize_bn from executorch.backends.xnnpack.test.tester import Quantize, Tester from torch.ao.quantization.quantizer.xnnpack_quantizer import ( @@ -155,27 +156,32 @@ def _test( conv_count=1, dtype: torch.dtype = torch.float, ): - tester = Tester(m.eval(), m.get_inputs()) - - if quant_config is not None: - tester = tester.quantize(Quantize(quantization_config=quant_config)) - tester.check(["torch.ops.quantized_decomposed"]) - - ( - tester.export() - .check_count({"torch.ops.aten.conv2d": conv_count}) - .to_edge_transform_and_lower() - .check_not(["executorch_exir_dialects_edge__ops_aten_convolution_default"]) - .check_not( - [ - "executorch_exir_dialects_edge__ops__native_batch_norm_legit_no_training_default" - ] - ) - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .to_executorch() - .serialize() - .run_method_and_compare_outputs(qtol=1) - ) + for legacy in (True, False): + if quant_config is not None: + tester = Tester(m.eval(), m.get_inputs()) + tester = tester.quantize(Quantize(quantization_config=quant_config)) + tester.check(["torch.ops.quantized_decomposed"]) + tester.export() + tester.check_count({"torch.ops.aten.conv2d": conv_count}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_convolution_default"] + ) + tester.check_not( + [ + "executorch_exir_dialects_edge__ops__native_batch_norm_legit_no_training_default" + ] + ) + tester.check_count( + {"torch.ops.higher_order.executorch_call_delegate": 1} + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs(qtol=1) def test_fp16_conv2d(self) -> None: for has_bias in (True, False): diff --git a/backends/xnnpack/test/ops/div.py b/backends/xnnpack/test/ops/div.py index 9bca5feed48..f2ba21ff072 100644 --- a/backends/xnnpack/test/ops/div.py +++ b/backends/xnnpack/test/ops/div.py @@ -28,17 +28,20 @@ def forward(self, x): return z def _test_div(self, inputs): - ( - Tester(self.Div(), inputs) - .export() - .check_count({"torch.ops.aten.div.Tensor": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_div_Tensor"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Div(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.div.Tensor": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_div_Tensor"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_div(self): # Adding 4 to move distribution away from 0, 4 Std Dev should be far enough @@ -56,14 +59,17 @@ def test_fp32_div(self): def test_fp32_div_single_input(self): # Adding 4 to move distribution away from 0, 4 Std Dev should be far enough inputs = (torch.randn(1) + 4,) - ( - Tester(self.DivSingleInput(), inputs) - .export() - .check_count({"torch.ops.aten.div.Tensor": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_div_Tensor"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.DivSingleInput(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.div.Tensor": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_div_Tensor"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/elu.py b/backends/xnnpack/test/ops/elu.py index f976c29d799..85033fe6b20 100644 --- a/backends/xnnpack/test/ops/elu.py +++ b/backends/xnnpack/test/ops/elu.py @@ -24,21 +24,24 @@ def forward(self, x): return torch.nn.functional.elu(x, alpha=1.2) def _test_elu(self, inputs): - ( - Tester(self.ELU(), inputs) - .export() - .check_count({"torch.ops.aten.elu.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.ELU(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.elu.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_elu_default", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("PyTorch Pin Update Required") def _test_fp16_elu(self): @@ -53,43 +56,49 @@ def _test_fp32_elu(self): @unittest.skip("Update Quantizer to quantize Elu") def _test_qs8_elu(self): inputs = (torch.randn(1, 3, 4, 4),) - ( - Tester(self.ELU(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.elu.default": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.ELU(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.elu.default": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_elu_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("Update Quantizer to quantize Elu") def _test_qs8_elu_functional(self): inputs = (torch.randn(1, 3, 4, 4),) - ( - Tester(self.ELU(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.elu.default": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.ELU(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.elu.default": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_elu_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/floor.py b/backends/xnnpack/test/ops/floor.py index dfbe7fb18c0..f5d82cf7b46 100644 --- a/backends/xnnpack/test/ops/floor.py +++ b/backends/xnnpack/test/ops/floor.py @@ -20,17 +20,20 @@ def forward(self, x): return z def _test_floor(self, inputs): - ( - Tester(self.Floor(), inputs) - .export() - .check_count({"torch.ops.aten.floor.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_floor_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Floor(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.floor.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_floor_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_floor(self): inputs = ( diff --git a/backends/xnnpack/test/ops/hardswish.py b/backends/xnnpack/test/ops/hardswish.py index 899a119ed44..7645006e043 100644 --- a/backends/xnnpack/test/ops/hardswish.py +++ b/backends/xnnpack/test/ops/hardswish.py @@ -24,21 +24,24 @@ def forward(self, x): return torch.nn.functional.hardswish(x) def _test_hardswish(self, inputs): - ( - Tester(self.Hardswish(), inputs) - .export() - .check_count({"torch.ops.aten.hardswish.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Hardswish(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.hardswish.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_hardswish_default", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_hardswish(self): inputs = (torch.randn(1, 3, 3).to(torch.float16),) @@ -50,18 +53,21 @@ def test_fp32_hardswish(self): def test_fp32_hardswish_functional(self): inputs = (torch.randn(1, 3, 3),) - ( - Tester(self.HardswishFunctional(), inputs) - .export() - .check_count({"torch.ops.aten.hardswish.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.HardswishFunctional(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.hardswish.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_hardswish_default", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/hardtanh.py b/backends/xnnpack/test/ops/hardtanh.py index e35e840e3c3..7718e944ae8 100644 --- a/backends/xnnpack/test/ops/hardtanh.py +++ b/backends/xnnpack/test/ops/hardtanh.py @@ -25,56 +25,75 @@ def forward(self, x): def test_fp32_hardtanh(self): inputs_sets = [torch.randn(2, 3, 4), torch.randn(7, 5, 2), torch.randn(2, 9)] for input in inputs_sets: - ( - Tester(self.HardTanh(), (input,)) - .export() - .check_count({"torch.ops.aten.hardtanh.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_hardtanh_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.HardTanh(), (input,)) + tester.export() + tester.check_count({"torch.ops.aten.hardtanh.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count( + {"torch.ops.higher_order.executorch_call_delegate": 1} + ) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_hardtanh_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp32_hardtanh_bound(self): inputs_sets = [torch.randn(2, 3, 4), torch.randn(7, 5, 2), torch.randn(2, 9)] for input in inputs_sets: - ( - Tester(self.HardTanh(-2.0, 2.0), (input,)) - .export() - .check_count({"torch.ops.aten.hardtanh.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_hardtanh_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.HardTanh(-2.0, 2.0), (input,)) + tester.export() + tester.check_count({"torch.ops.aten.hardtanh.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count( + {"torch.ops.higher_order.executorch_call_delegate": 1} + ) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_hardtanh_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_hardtanh(self): inputs_sets = [torch.randn(2, 3, 2), torch.randn(2, 1, 2), torch.randn(2, 3)] for input in inputs_sets: - ( - Tester(self.HardTanh(), (input,)) - .quantize() - .export() - .check_node_count( + for legacy in (True, False): + tester = Tester(self.HardTanh(), (input,)) + tester.quantize() + tester.export() + tester.check_node_count( { # Expect three quantize ops - one for input, hardtanh, and add. torch.ops.quantized_decomposed.quantize_per_tensor.default: 3, torch.ops.aten.hardtanh.default: 1, } ) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count( + {"torch.ops.higher_order.executorch_call_delegate": 1} + ) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_hardtanh_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/leaky_relu.py b/backends/xnnpack/test/ops/leaky_relu.py index 32f73486977..b59dcfa51e7 100644 --- a/backends/xnnpack/test/ops/leaky_relu.py +++ b/backends/xnnpack/test/ops/leaky_relu.py @@ -26,21 +26,24 @@ def forward(self, x): return torch.nn.functional.leaky_relu(x) def _test_leaky_relu(self, module, inputs): - ( - Tester(module, inputs) - .export() - .check_count({"torch.ops.aten.leaky_relu.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + tester.check_count({"torch.ops.aten.leaky_relu.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_leaky_relu_default", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_leaky_relu(self): inputs = (torch.randn(1, 3, 3).to(torch.float16),) @@ -54,21 +57,24 @@ def test_fp32_leaky_relu(self): def test_fp32_leaky_relu_functional(self): inputs = (torch.randn(1, 3, 3),) - ( - Tester(self.LeakyReLUFunctional(), inputs) - .export() - .check_count({"torch.ops.aten.leaky_relu.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.LeakyReLUFunctional(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.leaky_relu.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_leaky_relu_default", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("T172863987 - Missing quantizer support.") def _test_qs8_leaky_relu(self): diff --git a/backends/xnnpack/test/ops/lstm.py b/backends/xnnpack/test/ops/lstm.py index bfc6113c417..32b9b30e151 100644 --- a/backends/xnnpack/test/ops/lstm.py +++ b/backends/xnnpack/test/ops/lstm.py @@ -24,40 +24,58 @@ def __init__(self, input_size, hidden_size, out_size): self.linear2 = torch.nn.Linear(hidden_size, out_size) def forward(self, x): - x, hs = self.lstm(x) + x, _ = self.lstm(x) x = self.linear(x[:, -1, :]) x = self.linear2(x) return torch.nn.functional.log_softmax(x, dim=1) def test_fp32_lstm(self): - ( - Tester(self.LSTMLinear(32, 32, 10), (torch.rand(1, 32, 32),)) - .export() - .to_edge_transform_and_lower() - .check_not(["executorch_exir_dialects_edge__ops_aten_addmm_default"]) - .check_not( - ["p_lstm_weight", "p_lstm_bias"] - ) # These Should be Consumed by Delegate - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.LSTMLinear(32, 32, 10), (torch.rand(1, 32, 32),)) + tester.export() + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_addmm_default"] + ) + tester.check_not( + ["p_lstm_weight", "p_lstm_bias"] + ) # These Should be Consumed by Delegate + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp32_lstm_force_dynamic_linear(self): - ( - Tester(self.LSTMLinear(32, 32, 10), (torch.rand(1, 32, 32),)) - .export() - .to_edge_transform_and_lower( - ToEdgeTransformAndLower( - partitioners=[XnnpackPartitioner(force_fp32_dynamic_linear=True)] - ) + tester = Tester(self.LSTMLinear(32, 32, 10), (torch.rand(1, 32, 32),)) + tester.export() + tester.to_edge_transform_and_lower( + ToEdgeTransformAndLower( + partitioners=[XnnpackPartitioner(force_fp32_dynamic_linear=True)] ) - .check_not(["executorch_exir_dialects_edge__ops_aten_addmm_default"]) - # Weights are supplied as input to linears - .check(["p_lstm_weight_hh_l0", "p_lstm_weight_ih_l0"]) - # Biases are owned by delegates - .check_not(["p_lstm_bias"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() ) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_addmm_default"]) + # Weights are supplied as input to linears + tester.check(["p_lstm_weight_hh_l0", "p_lstm_weight_ih_l0"]) + # Biases are owned by delegates + tester.check_not(["p_lstm_bias"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() + + @unittest.skip('Expected to not find "aten_addmm_default"') + def test_fp32_lstm_force_dynamic_linear_legacy(self): + tester = Tester(self.LSTMLinear(32, 32, 10), (torch.rand(1, 32, 32),)) + tester.export() + tester.to_edge() + tester.partition() + tester.check_not(["executorch_exir_dialects_edge__ops_aten_addmm_default"]) + # Weights are supplied as input to linears + tester.check(["p_lstm_weight_hh_l0", "p_lstm_weight_ih_l0"]) + # Biases are owned by delegates + tester.check_not(["p_lstm_bias"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/max_dim.py b/backends/xnnpack/test/ops/max_dim.py index c660a5a6d26..cf5d2058e77 100644 --- a/backends/xnnpack/test/ops/max_dim.py +++ b/backends/xnnpack/test/ops/max_dim.py @@ -24,27 +24,33 @@ def forward(self, x): return (max_values_1, max_values_2) def _test_max_dim(self, inputs): - ( - Tester(self.Max(), inputs) - .export() - .check_count({"torch.ops.aten.max.dim": 2}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - .check_count({"executorch_exir_dialects_edge__ops_aten_max_dim": 2}) - ) + for legacy in (True, False): + tester = Tester(self.Max(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.max.dim": 2}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) + tester.check_count({"executorch_exir_dialects_edge__ops_aten_max_dim": 2}) def _test_max_dim_no_indicies(self, inputs): - ( - Tester(self.MaxNoIndices(), inputs) - .export() - .check_count({"torch.ops.aten.max.dim": 2}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_max_dim"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.MaxNoIndices(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.max.dim": 2}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_max_dim"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_max_dim_with_indicies(self): inputs = (torch.randn(16, 3, 12, 12).to(torch.float16),) diff --git a/backends/xnnpack/test/ops/maximum.py b/backends/xnnpack/test/ops/maximum.py index 30dfa5503a9..268a5602fed 100644 --- a/backends/xnnpack/test/ops/maximum.py +++ b/backends/xnnpack/test/ops/maximum.py @@ -19,17 +19,22 @@ def forward(self, x, y): return torch.maximum(x, y) def _test_maximum(self, inputs): - ( - Tester(self.Maximum(), inputs) - .export() - .check_count({"torch.ops.aten.maximum.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_maximum_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Maximum(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.maximum.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_maximum_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_maximum(self): inputs = ( @@ -50,14 +55,19 @@ def test_fp32_maximum_broadcast(self): torch.randn(2, 3, 4), torch.randn(2, 1, 4), ) - ( - Tester(self.Maximum(), inputs) - .export() - .check_count({"torch.ops.aten.maximum.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_maximum_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Maximum(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.maximum.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_maximum_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/mean_dim.py b/backends/xnnpack/test/ops/mean_dim.py index 3bac5f3239c..d814ea153b6 100644 --- a/backends/xnnpack/test/ops/mean_dim.py +++ b/backends/xnnpack/test/ops/mean_dim.py @@ -22,17 +22,20 @@ def forward(self, x): return z def _test_mean_dim(self, inputs): - ( - Tester(self.MeanDim((-1, -2)), inputs) - .export() - .check_count({"torch.ops.aten.mean.dim": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_mean_dim"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.MeanDim((-1, -2)), inputs) + tester.export() + tester.check_count({"torch.ops.aten.mean.dim": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_mean_dim"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_mean_dim(self): inputs = (torch.randn(1, 5, 4, 4).to(torch.float16),) @@ -48,48 +51,57 @@ def test_fp32_mean_dim_unsupported(self): we expect it to fail to partition when dim=(3). """ inputs = (torch.randn(1, 5, 4, 4),) - ( - Tester(self.MeanDim((3)), inputs) - .export() - .check_count({"torch.ops.aten.mean.dim": 1}) - .to_edge_transform_and_lower() - .check_count({"executorch_exir_dialects_edge__ops_aten_mean_dim": 1}) - ) + for legacy in (True, False): + tester = Tester(self.MeanDim((3)), inputs) + tester.export() + tester.check_count({"torch.ops.aten.mean.dim": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"executorch_exir_dialects_edge__ops_aten_mean_dim": 1}) def test_fp32_mean_dim_unsupported_3d(self): """ XNNPack mean.dim implementation only supports 4D tensors. """ inputs = (torch.randn(1, 5, 4),) - ( - Tester(self.MeanDim((-1, -2)), inputs) - .export() - .check_count({"torch.ops.aten.mean.dim": 1}) - .to_edge_transform_and_lower() - .check_count({"executorch_exir_dialects_edge__ops_aten_mean_dim": 1}) - ) + for legacy in (True, False): + tester = Tester(self.MeanDim((-1, -2)), inputs) + tester.export() + tester.check_count({"torch.ops.aten.mean.dim": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"executorch_exir_dialects_edge__ops_aten_mean_dim": 1}) def test_qs8_mean_dim(self): inputs = (torch.randn(1, 5, 4, 4),) - ( - Tester(self.MeanDim((-1, -2)), inputs) - .quantize() - .export() - .check_node_count( + for legacy in (True, False): + tester = Tester(self.MeanDim((-1, -2)), inputs) + tester.quantize() + tester.export() + tester.check_node_count( { torch.ops.aten.mean.dim: 1, torch.ops.quantized_decomposed.quantize_per_tensor.default: 3, } ) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_mean_dim", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs(qtol=1) - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs(qtol=1) diff --git a/backends/xnnpack/test/ops/minimum.py b/backends/xnnpack/test/ops/minimum.py index 406ac8485e5..3b64e51ff07 100644 --- a/backends/xnnpack/test/ops/minimum.py +++ b/backends/xnnpack/test/ops/minimum.py @@ -19,17 +19,22 @@ def forward(self, x, y): return torch.minimum(x, y) def _test_minimum(self, inputs): - ( - Tester(self.Minimum(), inputs) - .export() - .check_count({"torch.ops.aten.minimum.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_minimum_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Minimum(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.minimum.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_minimum_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_minimum(self): inputs = ( diff --git a/backends/xnnpack/test/ops/multiply.py b/backends/xnnpack/test/ops/multiply.py index db50bc5dd44..73b6a9fc196 100644 --- a/backends/xnnpack/test/ops/multiply.py +++ b/backends/xnnpack/test/ops/multiply.py @@ -32,17 +32,20 @@ def forward(self, x, y): return torch.nn.functional.relu(z) def _test_mul(self, inputs): - ( - Tester(self.Mul(), inputs) - .export() - .check_count({"torch.ops.aten.mul.Tensor": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_mul_Tensor"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Mul(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.mul.Tensor": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_mul_Tensor"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_mul(self): inputs = ( @@ -57,90 +60,102 @@ def test_fp32_mul(self): def test_qs8_mul(self): inputs = (torch.randn(1, 1, 4, 4), torch.randn(1, 1, 4, 1)) - ( - Tester(self.Mul(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.mul.Tensor": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Mul(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.mul.Tensor": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_mul_Tensor", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_mul2(self): inputs = (torch.randn(1, 1, 4, 4),) - ( - Tester(self.Mul2(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.mul.Tensor": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Mul2(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.mul.Tensor": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_mul_Tensor", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_mul_functional(self): inputs = (torch.randn(1, 1, 4, 4), torch.randn(1, 1, 4, 4)) - ( - Tester(self.MulFunctional(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.mul.Tensor": 3}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.MulFunctional(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.mul.Tensor": 3}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_mul_Tensor", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_mul_relu(self): inputs = (torch.randn(1, 1, 4, 4), torch.randn(1, 1, 4, 4)) - ( - Tester(self.MulRelu(), inputs) - .quantize() - .export() - .check_count( + for legacy in (True, False): + tester = Tester(self.MulRelu(), inputs) + tester.quantize() + tester.export() + tester.check_count( { "torch.ops.aten.mul.Tensor": 1, "torch.ops.aten.relu.default": 1, } ) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_mul_Tensor", "executorch_exir_dialects_edge__ops_aten_relu_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/negate.py b/backends/xnnpack/test/ops/negate.py index 4d158612e97..18b3865c80c 100644 --- a/backends/xnnpack/test/ops/negate.py +++ b/backends/xnnpack/test/ops/negate.py @@ -20,17 +20,20 @@ def forward(self, x): return z def _test_negate(self, inputs): - ( - Tester(self.Negate(), inputs) - .export() - .check_count({"torch.ops.aten.neg.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_neg_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Negate(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.neg.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_neg_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_negate(self): inputs = ( diff --git a/backends/xnnpack/test/ops/permute.py b/backends/xnnpack/test/ops/permute.py index b348fc8af6d..aa9db2100a7 100644 --- a/backends/xnnpack/test/ops/permute.py +++ b/backends/xnnpack/test/ops/permute.py @@ -32,17 +32,22 @@ def forward(self, x): return z def _test_permute(self, inputs): - ( - Tester(self.Permute([0, 2, 3, 1]), inputs) - .export() - .check_count({"torch.ops.aten.permute.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_permute_copy_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Permute([0, 2, 3, 1]), inputs) + tester.export() + tester.check_count({"torch.ops.aten.permute.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_permute_copy_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_permute(self): inputs = (torch.randn(1, 1, 4, 4).to(torch.float16),) @@ -54,64 +59,75 @@ def test_fp32_permute(self): def test_fp32_permute_copy(self): inputs = (torch.randn(1, 1, 4, 4),) - ( - Tester(self.PermuteCopy([0, 2, 3, 1]), inputs) - .export() - .check_count({"torch.ops.aten.permute_copy.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_permute_copy_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.PermuteCopy([0, 2, 3, 1]), inputs) + tester.export() + tester.check_count({"torch.ops.aten.permute_copy.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_permute_copy_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_permute(self): inputs = (torch.randn(1, 1, 4, 4),) - ( - Tester(self.Permute([0, 2, 3, 1]), inputs) - .quantize() - .export() - .check_node_count( + for legacy in (True, False): + tester = Tester(self.Permute([0, 2, 3, 1]), inputs) + tester.quantize() + tester.export() + tester.check_node_count( { torch.ops.aten.permute.default: 1, torch.ops.quantized_decomposed.quantize_per_tensor.default: 3, } ) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_permute_copy_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_permute_copy(self): inputs = (torch.randn(1, 1, 4, 4),) - ( - Tester(self.PermuteCopy([0, 2, 3, 1]), inputs) - .quantize() - .export() - .check_node_count( + for legacy in (True, False): + tester = Tester(self.PermuteCopy([0, 2, 3, 1]), inputs) + tester.quantize() + tester.export() + tester.check_node_count( { torch.ops.aten.permute_copy.default: 1, torch.ops.quantized_decomposed.quantize_per_tensor.default: 3, } ) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_permute_copy_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/pow.py b/backends/xnnpack/test/ops/pow.py index ac902ae44be..b2cf20afbea 100644 --- a/backends/xnnpack/test/ops/pow.py +++ b/backends/xnnpack/test/ops/pow.py @@ -21,17 +21,22 @@ def forward(self, x): return z def _test_pow2(self, inputs): - ( - Tester(self.Pow(2), inputs) - .export() - .check_count({"torch.ops.aten.pow.Tensor_Scalar": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_pow_Tensor_Scalar"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Pow(2), inputs) + tester.export() + tester.check_count({"torch.ops.aten.pow.Tensor_Scalar": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_pow_Tensor_Scalar"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_pow2(self): inputs = (torch.randn(20).to(torch.float16),) @@ -50,10 +55,13 @@ def test_fp32_pow_unsupported(self): """ inputs = (torch.randn(5),) - ( - Tester(self.Pow(3), inputs) - .export() - .check_count({"torch.ops.aten.pow.Tensor_Scalar": 1}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + for legacy in (True, False): + tester = Tester(self.Pow(3), inputs) + tester.export() + tester.check_count({"torch.ops.aten.pow.Tensor_Scalar": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) diff --git a/backends/xnnpack/test/ops/prelu.py b/backends/xnnpack/test/ops/prelu.py index f73648dfa25..97158af1e99 100644 --- a/backends/xnnpack/test/ops/prelu.py +++ b/backends/xnnpack/test/ops/prelu.py @@ -21,19 +21,22 @@ def forward(self, x): return a def _test_prelu(self, module, inputs): - ( - Tester(module, inputs) - .export() - .check_count({"torch.ops.aten.prelu.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + tester.check_count({"torch.ops.aten.prelu.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( ["executorch_exir_dialects_edge__ops_aten__prelu_kernel_default"] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("XNNPACK Expects FP16 inputs but FP32 weights") def _test_fp16_prelu(self): diff --git a/backends/xnnpack/test/ops/quantize_per_tensor.py b/backends/xnnpack/test/ops/quantize_per_tensor.py index c2117987536..7ca7416e075 100644 --- a/backends/xnnpack/test/ops/quantize_per_tensor.py +++ b/backends/xnnpack/test/ops/quantize_per_tensor.py @@ -21,20 +21,23 @@ def forward(self, x): ) inputs = (torch.randn(1, 1, 4, 4),) - ( - Tester(Quant(), inputs) - .export() - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(Quant(), inputs) + tester.export() + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_quantized_decomposed_quantize_per_tensor_default" ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_dequantize_per_tenstor(self): class Dequant(torch.nn.Module): @@ -51,17 +54,20 @@ def forward(self, x): ), ) - ( - Tester(Dequant(), inputs) - .export() - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(Dequant(), inputs) + tester.export() + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_quantized_decomposed_dequantize_per_tensor_default" ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/relu.py b/backends/xnnpack/test/ops/relu.py index 8672b1d3e4e..2d71b9b4004 100644 --- a/backends/xnnpack/test/ops/relu.py +++ b/backends/xnnpack/test/ops/relu.py @@ -22,14 +22,17 @@ def forward(self, x): def test_fp32_relu(self): inputs = (torch.randn(8),) - ( - Tester(self.Relu(), inputs) - .export() - .check_count({"torch.ops.aten.relu.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_relu_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Relu(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.relu.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_relu_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/sdpa.py b/backends/xnnpack/test/ops/sdpa.py index de5c7174ab5..c168a1da391 100644 --- a/backends/xnnpack/test/ops/sdpa.py +++ b/backends/xnnpack/test/ops/sdpa.py @@ -61,20 +61,23 @@ def get_input_tensors(mask_rank: int, dtype: torch.dtype = torch.float32): def _test(self, module, inputs, atol=1e-03, rtol=1e-03): module = module.eval() - ( - Tester(module, inputs) - .export() - .to_edge_transform_and_lower( - ToEdgeTransformAndLower([XnnpackPartitioner(configs=[SDPAConfig])]) - ) - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower( + ToEdgeTransformAndLower([XnnpackPartitioner(configs=[SDPAConfig])]) + ) + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( ["executorch_exir_dialects_edge__ops_aten_bmm_default"], ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs(atol=atol, rtol=rtol) - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs(atol=atol, rtol=rtol) def test_fp16_sdpa_mask2d(self): """ diff --git a/backends/xnnpack/test/ops/sigmoid.py b/backends/xnnpack/test/ops/sigmoid.py index a9acd4df6db..dc6b9fa26f1 100644 --- a/backends/xnnpack/test/ops/sigmoid.py +++ b/backends/xnnpack/test/ops/sigmoid.py @@ -21,17 +21,22 @@ def forward(self, x): return z def _test_sigmoid(self, inputs): - ( - Tester(self.Sigmoid(), inputs) - .export() - .check_count({"torch.ops.aten.sigmoid.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_sigmoid_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Sigmoid(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.sigmoid.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_sigmoid_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_sigmoid(self): inputs = (torch.randn(4).to(torch.float16),) diff --git a/backends/xnnpack/test/ops/slice_copy.py b/backends/xnnpack/test/ops/slice_copy.py index 8ff37368578..bbc8ae7856d 100644 --- a/backends/xnnpack/test/ops/slice_copy.py +++ b/backends/xnnpack/test/ops/slice_copy.py @@ -12,23 +12,27 @@ class TestSliceCopy(unittest.TestCase): def _test_slice_copy(self, module, inputs, copy_count=1, edge_copy_count=1): - ( - Tester(module, inputs) - .export() - .check_count({"torch.ops.aten.slice.Tensor": copy_count}) - .to_edge() - .check_count( - { - "executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor": edge_copy_count - } + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + tester.check_count({"torch.ops.aten.slice.Tensor": copy_count}) + if legacy: + tester.to_edge() + tester.check_count( + { + "executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor": edge_copy_count + } + ) + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor"] ) - .partition() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_slice_copy(self): class SliceCopy(torch.nn.Module): @@ -77,13 +81,16 @@ def forward(self, x): module = Slice() inputs = (torch.randn(5, 5, 5),) - ( - Tester(module, inputs) - .export() - .check_count({"torch.ops.aten.slice.Tensor": 3}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + tester.check_count({"torch.ops.aten.slice.Tensor": 3}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) def test_fp32_slice_copy_dim_0(self): """ @@ -96,13 +103,16 @@ def forward(self, x): module = Slice() inputs = (torch.randn(5, 5, 5),) - ( - Tester(module, inputs) - .export() - .check_count({"torch.ops.aten.slice.Tensor": 3}) - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + for legacy in (True, False): + tester = Tester(module, inputs) + tester.export() + tester.check_count({"torch.ops.aten.slice.Tensor": 3}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) def test_fp32_static_slice_with_dynamic_dim(self): """ @@ -114,16 +124,19 @@ def forward(self, x): return x[1:3, -2:, :-1] inputs = (torch.randn(5, 5, 5),) - ( - Tester( + for legacy in (True, False): + tester = Tester( SliceCopy(), inputs, dynamic_shapes=({2: torch.export.Dim("dim_2", min=4, max=100)},), ) - .export() - .to_edge_transform_and_lower() - .check_not(["torch.ops.higher_order.executorch_call_delegate"]) - ) + tester.export() + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_not(["torch.ops.higher_order.executorch_call_delegate"]) # Note: Slice ends up as slice_copy later in the process, but during quantization, # it's still slice, which isn't supported by the XNNPACK quantizer. @@ -136,20 +149,25 @@ def forward(self, x): return z inputs = (torch.randn(5, 5, 5),) - ( - Tester(SliceCopy(), inputs) - .quantize() - .export() - .check_node_count( + for legacy in (True, False): + tester = Tester(SliceCopy(), inputs) + tester.quantize() + tester.export() + tester.check_node_count( { "aten::slice.Tensor": 3, "quantized_decomposed::quantize_per_tensor": 3, } ) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_slice_copy_Tensor"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/softmax.py b/backends/xnnpack/test/ops/softmax.py index cc544a28a28..e0c2b935982 100644 --- a/backends/xnnpack/test/ops/softmax.py +++ b/backends/xnnpack/test/ops/softmax.py @@ -25,17 +25,24 @@ def _test_softmax(self, inputs): valid_dims = [len(inputs[0]) - 1, -1] for dim in valid_dims: - ( - Tester(self.Softmax(dim), inputs) - .export() - .check_count({"torch.ops.aten.softmax": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten__softmax_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Softmax(dim), inputs) + tester.export() + tester.check_count({"torch.ops.aten.softmax": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count( + {"torch.ops.higher_order.executorch_call_delegate": 1} + ) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten__softmax_default"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_softmax(self): inputs = (torch.rand((3, 5, 7)).to(torch.float16),) @@ -55,11 +62,16 @@ def test_fp32_softmax_unsupported(self): invalid_dims = range(len(inputs) - 1) for dim in invalid_dims: - ( - Tester(self.Softmax(dim), inputs) - .export() - .check_count({"torch.ops.aten.softmax": 1}) - .to_edge_transform_and_lower() + for legacy in (True, False): + tester = Tester(self.Softmax(dim), inputs) + tester.export() + tester.check_count({"torch.ops.aten.softmax": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() # Should not be delegated - .check(["executorch_exir_dialects_edge__ops_aten__softmax_default"]) - ) + tester.check( + ["executorch_exir_dialects_edge__ops_aten__softmax_default"] + ) diff --git a/backends/xnnpack/test/ops/sqrt.py b/backends/xnnpack/test/ops/sqrt.py index eaeb3b9f700..032079ff288 100644 --- a/backends/xnnpack/test/ops/sqrt.py +++ b/backends/xnnpack/test/ops/sqrt.py @@ -21,17 +21,20 @@ def forward(self, x): return z def _test_sqrt(self, inputs): - ( - Tester(self.Sqrt(), inputs) - .export() - .check_count({"torch.ops.aten.sqrt.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_sqrt_default"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Sqrt(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.sqrt.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_sqrt_default"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_sqrt(self): inputs = (torch.randn(20).to(torch.float16),) diff --git a/backends/xnnpack/test/ops/square.py b/backends/xnnpack/test/ops/square.py index 32a19639343..84a18551177 100644 --- a/backends/xnnpack/test/ops/square.py +++ b/backends/xnnpack/test/ops/square.py @@ -24,17 +24,22 @@ def _test_square(self, inputs): Note that torch.square maps to aten.pow.Tensor_Scalar. The pow visitor has logic to emit the appropriate XNNPACK square op when the exponent is 2. """ - ( - Tester(self.Square(), inputs) - .export() - .check_count({"torch.ops.aten.square.default": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_pow_Tensor_Scalar"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Square(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.square.default": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( + ["executorch_exir_dialects_edge__ops_aten_pow_Tensor_Scalar"] + ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_square(self): inputs = (torch.randn(20).to(torch.float16),) diff --git a/backends/xnnpack/test/ops/static_constant_pad.py b/backends/xnnpack/test/ops/static_constant_pad.py index a0a74e3840b..2e836ebacc6 100644 --- a/backends/xnnpack/test/ops/static_constant_pad.py +++ b/backends/xnnpack/test/ops/static_constant_pad.py @@ -84,19 +84,22 @@ def forward(self, x): return z def _test_static_constant_pad_functional(self, inputs): - ( - Tester(self.StaticConstantPadFunctional(), inputs) - .export() - .check_count({"torch.ops.aten.pad.default": 8}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.StaticConstantPadFunctional(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.pad.default": 8}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( ["executorch_exir_dialects_edge__ops_aten_constant_pad_nd_default"] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_static_constant_pad_functional(self): inputs = ( @@ -129,42 +132,48 @@ def forward(self, x): return z + z inputs = (torch.randn(size=(1, 2)),) - ( - Tester(Pad(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.pad.default": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(Pad(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.pad.default": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_constant_pad_nd_default" "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_qs8_static_constant_pad_2d(self): inputs = (torch.randn(size=(5, 4, 3, 2)),) - ( - Tester(self.StaticConstantPad2d(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.pad.default": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.StaticConstantPad2d(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.pad.default": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_constant_pad_nd_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() diff --git a/backends/xnnpack/test/ops/sub.py b/backends/xnnpack/test/ops/sub.py index fb3d3d3f948..b52eb59abbe 100644 --- a/backends/xnnpack/test/ops/sub.py +++ b/backends/xnnpack/test/ops/sub.py @@ -28,17 +28,20 @@ def forward(self, x): return z def _test_sub(self, inputs): - ( - Tester(self.Sub(), inputs) - .export() - .check_count({"torch.ops.aten.sub.Tensor": 1}) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not(["executorch_exir_dialects_edge__ops_aten_sub_Tensor"]) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + for legacy in (True, False): + tester = Tester(self.Sub(), inputs) + tester.export() + tester.check_count({"torch.ops.aten.sub.Tensor": 1}) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not(["executorch_exir_dialects_edge__ops_aten_sub_Tensor"]) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() def test_fp16_sub(self): inputs = ( @@ -54,68 +57,77 @@ def test_fp32_sub(self): @unittest.skip("T171957656 - Quantized sub not implemented.") def _test_qs8_sub(self): inputs = (torch.randn(1, 1, 4, 4), torch.randn(1, 1, 4, 4)) - ( - Tester(self.Sub(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.sub.Tensor": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Sub(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.sub.Tensor": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_sub_Tensor", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("T171957656 - Quantized sub not implemented.") def _test_qs8_sub2(self): inputs = (torch.randn(1, 1, 4, 4),) - ( - Tester(self.Sub2(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.sub.Tensor": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Sub2(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.sub.Tensor": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_sub_Tensor", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("T171957656 - Quantized sub not implemented.") def _test_qs8_sub3(self): inputs = (torch.randn(1, 1, 4, 4), torch.randn(1, 1, 4, 1)) - ( - Tester(self.Sub(), inputs) - .quantize() - .export() - .check_count({"torch.ops.aten.sub.Tensor": 1}) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + for legacy in (True, False): + tester = Tester(self.Sub(), inputs) + tester.quantize() + tester.export() + tester.check_count({"torch.ops.aten.sub.Tensor": 1}) + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_sub_Tensor", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs() @unittest.skip("T171957656 - Quantized sub not implemented.") def _test_qs8_sub_relu(self): @@ -125,27 +137,30 @@ def forward(self, x, y): return torch.nn.functional.relu(z) inputs = (torch.randn(1, 1, 4, 4), torch.randn(1, 1, 4, 4)) - ( - Tester(self.Sub(), inputs) - .quantize() - .export() - .check_count( + for legacy in (True, False): + tester = Tester(self.Sub(), inputs) + tester.quantize() + tester.export() + tester.check_count( { "torch.ops.aten.sub.Tensor": 1, "torch.ops.aten.relu.default": 1, } ) - .check(["torch.ops.quantized_decomposed"]) - .to_edge_transform_and_lower() - .check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) - .check_not( + tester.check(["torch.ops.quantized_decomposed"]) + if legacy: + tester.to_edge() + tester.partition() + else: + tester.to_edge_transform_and_lower() + tester.check_count({"torch.ops.higher_order.executorch_call_delegate": 1}) + tester.check_not( [ "executorch_exir_dialects_edge__ops_aten_sub_Tensor", "executorch_exir_dialects_edge__ops_aten_relu_default", "torch.ops.quantized_decomposed", ] ) - .to_executorch() - .serialize() - .run_method_and_compare_outputs() - ) + tester.to_executorch() + tester.serialize() + tester.run_method_and_compare_outputs()