Skip to content

Commit e101d3d

Browse files
NXP backend: Enable sum with new Neutron flow
1 parent 3bd4748 commit e101d3d

11 files changed

Lines changed: 518 additions & 1 deletion

File tree

backends/nxp/backend/edge_helper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
QuantizePerChannel,
2222
QuantizePerTensor,
2323
SubTensor,
24+
SumDimIntList,
2425
ViewCopy,
2526
)
2627
from torch.fx import GraphModule, Node
@@ -49,6 +50,7 @@
4950
MulTensor,
5051
PermuteCopy,
5152
SubTensor,
53+
SumDimIntList,
5254
}
5355

5456

backends/nxp/backend/edge_program_converter.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
exir_ops.edge.aten.slice_copy.Tensor: SliceTensorConverter, # noqa F405
5757
exir_ops.edge.aten._softmax.default: SoftmaxConverter, # noqa F405
5858
exir_ops.edge.aten.sub.Tensor: SubTensorConverter, # noqa F405
59+
exir_ops.edge.aten.sum.dim_IntList: SumDimIntListConverter, # noqa F405
5960
exir_ops.edge.aten.tanh.default: TanhConverter, # noqa F405
6061
exir_ops.edge.aten.upsample_bilinear2d.vec: UpsampleBilinear2DConverter, # noqa F405
6162
exir_ops.edge.aten.upsample_nearest2d.vec: UpsampleNearest2DConverter, # noqa F405

backends/nxp/backend/ir/converter/node_converters/ops_converters/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
from executorch.backends.nxp.backend.ir.converter.node_converters.ops_converters.sub_tensor_converter import (
9393
SubTensorConverter,
9494
)
95+
from executorch.backends.nxp.backend.ir.converter.node_converters.ops_converters.sum_dim_int_list_converter import (
96+
SumDimIntListConverter,
97+
)
9598
from executorch.backends.nxp.backend.ir.converter.node_converters.ops_converters.tanh_converter import (
9699
TanhConverter,
97100
)
@@ -138,6 +141,7 @@
138141
"SliceTensorConverter",
139142
"SoftmaxConverter",
140143
"SubTensorConverter",
144+
"SumDimIntListConverter",
141145
"TanhConverter",
142146
"UpsampleBilinear2DConverter",
143147
"UpsampleNearest2DConverter",
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright 2026 NXP
2+
#
3+
# This source code is licensed under the BSD-style license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
6+
import torch
7+
8+
from executorch.backends.nxp.backend.ir.converter.conversion.common import OpsList
9+
from executorch.backends.nxp.backend.ir.converter.node_converter import (
10+
CustomDelegationOptions,
11+
NodeConverter,
12+
)
13+
from executorch.backends.nxp.backend.ir.converter.node_converters.shared.reduce_utils import (
14+
convert_axes_from_attribute,
15+
get_dim_and_handle_io_formats,
16+
get_reduce_node_attrs,
17+
)
18+
from executorch.backends.nxp.backend.ir.tflite_generator.builtin_options import (
19+
sum_options,
20+
)
21+
from executorch.backends.nxp.backend.neutron_target_spec import NeutronTargetSpec
22+
from torch.fx import Node
23+
from torch.nn import Parameter
24+
25+
26+
class SumDimIntListConverter(NodeConverter):
27+
28+
@staticmethod
29+
def _is_supported_on_target(
30+
node: Node,
31+
neutron_target_spec: NeutronTargetSpec,
32+
parameters_mapping: dict[str, Parameter],
33+
custom_delegation_options: CustomDelegationOptions,
34+
) -> bool:
35+
if not NodeConverter.uses_quantization_type_for_io(
36+
node,
37+
supported_types=[torch.int8, torch.uint8],
38+
input_indices=[0],
39+
output_indices=[0],
40+
):
41+
return False
42+
43+
return True
44+
45+
@staticmethod
46+
def _is_supported_in_IR(
47+
node: Node,
48+
parameters_mapping: dict[str, Parameter],
49+
custom_delegation_options: CustomDelegationOptions,
50+
) -> bool:
51+
if not NodeConverter._has_shared_q_params_if_quantized(node):
52+
return False
53+
54+
return True
55+
56+
def convert(self, node: Node):
57+
"""Convert the 'sum.dim_IntList' operator to NeutronIR 'Sum'.
58+
The ExecuTorch schema is:
59+
sum.dim_IntList(
60+
Tensor self,
61+
int[1]? dim,
62+
bool keepdim=False,
63+
*,
64+
dtype=None,
65+
) -> Tensor
66+
"""
67+
self.assert_convertible(node)
68+
69+
dim, keepdim = get_reduce_node_attrs(node)
70+
71+
t_op = self._create_tflite_op_with_io_tensors(node)
72+
t_op.builtin_options = sum_options.Sum(keepdim)
73+
74+
ops = OpsList(middle_op=t_op)
75+
dim = get_dim_and_handle_io_formats(self.builder, ops, dim, keepdim)
76+
77+
convert_axes_from_attribute(t_op, self.builder, dim)
78+
self.builder.append_operators(ops.flatten())

backends/nxp/backend/node_format_inference.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
MeanDim,
2828
PermuteCopy,
2929
QuantizePerTensor,
30+
SumDimIntList,
3031
UpsampleBilinear2D,
3132
UpsampleNearest2D,
3233
ViewCopy,
@@ -60,6 +61,7 @@ class NodeFormatInference:
6061
PermuteCopy,
6162
MeanDim,
6263
Amin,
64+
SumDimIntList,
6365
}
6466

6567
_type_changed_during_last_run: bool
@@ -136,7 +138,7 @@ def _infer_format_of_nodes(self, node: Node):
136138
self._node_inputs[node][0], DataFormat.FORMATLESS
137139
)
138140

139-
elif op_type in [MeanDim, Amin]:
141+
elif op_type in [MeanDim, Amin, SumDimIntList]:
140142
# The operator schema is:
141143
# <reduce_op>(Tensor self, int[1]? dim, bool keepdim=False, *, ScalarType? dtype=None) -> Tensor
142144
keep_dim = try_get_arg(node, 2) or False

backends/nxp/neutron_partitioner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def tag_qdq_clusters(self, nodes: list[torch.fx.Node]):
229229
exir_ops.edge.aten.slice_copy.Tensor: SliceTensorConverter, # noqa F405
230230
exir_ops.edge.aten._softmax.default: SoftmaxConverter, # noqa F405
231231
exir_ops.edge.aten.sub.Tensor: SubTensorConverter, # noqa F405
232+
exir_ops.edge.aten.sum.dim_IntList: SumDimIntListConverter, # noqa F405
232233
exir_ops.edge.aten.tanh.default: TanhConverter, # noqa F405
233234
exir_ops.edge.aten.upsample_bilinear2d.vec: UpsampleBilinear2DConverter, # noqa F405
234235
exir_ops.edge.aten.upsample_nearest2d.vec: UpsampleNearest2DConverter, # noqa F405

backends/nxp/quantizer/neutron_quantizer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
SqueezeDimsPattern,
5757
SqueezePattern,
5858
SubTensorPattern,
59+
SumDimIntListPattern,
5960
TanhInPlacePattern,
6061
TanhPattern,
6162
TransposeIntPattern,
@@ -300,6 +301,7 @@ def __init__(self, neutron_target_spec: NeutronTargetSpec, is_qat: bool = False)
300301
OpQuantizer(SqueezeDimsPattern(is_qat=is_qat), static_qconfig),
301302
OpQuantizer(SqueezePattern(is_qat=is_qat), static_qconfig),
302303
OpQuantizer(SubTensorPattern(is_qat=is_qat), static_qconfig),
304+
OpQuantizer(SumDimIntListPattern(is_qat=is_qat), static_qconfig),
303305
OpQuantizer(TanhPattern(is_qat=is_qat), static_qconfig),
304306
OpQuantizer(TanhInPlacePattern(is_qat=is_qat), static_qconfig),
305307
OpQuantizer(TransposeIntPattern(is_qat=is_qat), static_qconfig),

backends/nxp/quantizer/patterns.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,15 @@ def partition_types(self):
11411141
return [torch.ops.aten.squeeze.dims]
11421142

11431143

1144+
class SumDimIntListPattern(SharedSpecPattern):
1145+
"""
1146+
Quantizer for the `aten.sum.dim_IntList` operator.
1147+
"""
1148+
1149+
def partition_types(self):
1150+
return [torch.ops.aten.sum.dim_IntList]
1151+
1152+
11441153
class TanhPattern(QuantizationPattern):
11451154
"""
11461155
Quantizer for Tanh operator.

0 commit comments

Comments
 (0)