Skip to content

Commit 9371b6d

Browse files
committed
Arm backend: Add TOSA dialect unary elementwise node visitors
Signed-off-by: Saoirse Stewart <saoirse.stewart@arm.com>
1 parent f4a6aac commit 9371b6d

16 files changed

Lines changed: 112 additions & 36 deletions

backends/arm/_passes/aten_to_tosa_tensor_operators.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,37 @@ def rewrite_binary_operator(
8282
return None
8383

8484
return DialectNodeSpec(target, node.args, dict(node.kwargs))
85+
86+
87+
def rewrite_unary_operator(
88+
node: Node, pass_: AtenToDialectPass
89+
) -> DialectNodeSpec | None:
90+
match node.target:
91+
case exir_ops.edge.aten.abs.default:
92+
target = exir_ops.backend.tosa.ABS.default
93+
case exir_ops.edge.aten.bitwise_not.default:
94+
target = exir_ops.backend.tosa.BITWISE_NOT.default
95+
case exir_ops.edge.aten.ceil.default:
96+
target = exir_ops.backend.tosa.CEIL.default
97+
case exir_ops.edge.aten.cos.default:
98+
target = exir_ops.backend.tosa.COS.default
99+
case exir_ops.edge.aten.exp.default:
100+
target = exir_ops.backend.tosa.EXP.default
101+
case exir_ops.edge.aten.floor.default:
102+
target = exir_ops.backend.tosa.FLOOR.default
103+
case exir_ops.edge.aten.log.default:
104+
target = exir_ops.backend.tosa.LOG.default
105+
case exir_ops.edge.aten.logical_not.default:
106+
target = exir_ops.backend.tosa.LOGICAL_NOT.default
107+
case exir_ops.edge.aten.neg.default:
108+
target = exir_ops.backend.tosa.NEGATE.default
109+
case exir_ops.edge.aten.reciprocal.default:
110+
target = exir_ops.backend.tosa.RECIPROCAL.default
111+
case exir_ops.edge.aten.rsqrt.default:
112+
target = exir_ops.backend.tosa.RSQRT.default
113+
case exir_ops.edge.aten.sin.default:
114+
target = exir_ops.backend.tosa.SIN.default
115+
case _:
116+
return None
117+
118+
return DialectNodeSpec(target, node.args, dict(node.kwargs))

backends/arm/_passes/exir_to_tosa_pass.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
rewrite_argmax,
1414
rewrite_binary_operator,
1515
rewrite_rfft2,
16+
rewrite_unary_operator,
1617
)
1718
from executorch.backends.transforms.aten_to_dialect_pass import (
1819
AtenToDialectPass,
@@ -87,6 +88,26 @@ def _get_binary_operator_replacement(
8788
return rewrite_binary_operator(node, pass_)
8889

8990

91+
@register_dialect_substitutions(
92+
exir_ops.edge.aten.abs.default,
93+
exir_ops.edge.aten.bitwise_not.default,
94+
exir_ops.edge.aten.ceil.default,
95+
exir_ops.edge.aten.cos.default,
96+
exir_ops.edge.aten.exp.default,
97+
exir_ops.edge.aten.floor.default,
98+
exir_ops.edge.aten.log.default,
99+
exir_ops.edge.aten.logical_not.default,
100+
exir_ops.edge.aten.neg.default,
101+
exir_ops.edge.aten.reciprocal.default,
102+
exir_ops.edge.aten.rsqrt.default,
103+
exir_ops.edge.aten.sin.default,
104+
)
105+
def _get_unary_operator_replacement(
106+
node: Node, pass_: AtenToDialectPass
107+
) -> DialectNodeSpec | None:
108+
return rewrite_unary_operator(node, pass_)
109+
110+
90111
@register_dialect_substitutions(
91112
exir_ops.edge.aten.clamp.default,
92113
exir_ops.edge.aten.erf.default,

backends/arm/operators/__init__.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,61 +11,62 @@
1111

1212
from . import ( # noqa
1313
node_visitor,
14-
op_abs,
1514
op_amax,
1615
op_amin,
1716
op_any,
18-
op_bitwise_not,
1917
op_cat,
20-
op_ceil,
2118
op_cond_if,
22-
op_cos,
23-
op_exp,
24-
op_floor,
25-
op_log,
26-
op_logical_not,
27-
op_neg,
2819
op_permute,
29-
op_reciprocal,
3020
op_repeat,
31-
op_rsqrt,
32-
op_sin,
3321
op_sum,
3422
op_to_dim_order_copy,
23+
op_tosa_abs,
3524
op_tosa_add,
3625
op_tosa_argmax,
3726
op_tosa_avg_pool2d,
3827
op_tosa_avg_pool2d_adaptive,
3928
op_tosa_binary_ops,
29+
op_tosa_bitwise_not,
4030
op_tosa_cast_to_block_scaled,
31+
op_tosa_ceil,
4132
op_tosa_clamp,
33+
op_tosa_clz,
4234
op_tosa_conv2d,
4335
op_tosa_conv2d_block_scaled,
4436
op_tosa_conv3d,
37+
op_tosa_cos,
4538
op_tosa_custom,
4639
op_tosa_depthwise_conv2d,
4740
op_tosa_eq,
4841
op_tosa_erf,
42+
op_tosa_exp,
4943
op_tosa_fft,
44+
op_tosa_floor,
5045
op_tosa_gather,
5146
op_tosa_ge,
5247
op_tosa_gt,
5348
op_tosa_identity,
49+
op_tosa_log,
50+
op_tosa_logical_not,
5451
op_tosa_matmul,
5552
op_tosa_matmul_t_block_scaled,
5653
op_tosa_max_pool2d,
5754
op_tosa_max_pool2d_adaptive,
5855
op_tosa_maximum,
5956
op_tosa_minimum,
6057
op_tosa_mul,
58+
op_tosa_neg,
6159
op_tosa_pad,
6260
op_tosa_pow,
61+
op_tosa_reciprocal,
6362
op_tosa_rescale,
6463
op_tosa_resize,
6564
op_tosa_rshift_tensor,
65+
op_tosa_rsqrt,
6666
op_tosa_scatter,
6767
op_tosa_shapes,
6868
op_tosa_sigmoid,
69+
op_tosa_sin,
6970
op_tosa_slice,
7071
op_tosa_sub,
7172
op_tosa_table,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
@register_node_visitor
1616
class AbsVisitor(SimpleNodeVisitor):
17-
target = "aten.abs.default"
17+
target = "tosa.ABS.default"
1818

1919
@classmethod
2020
def get_config(cls) -> SimpleNodeVisitorConfig:

backends/arm/operators/op_bitwise_not.py renamed to backends/arm/operators/op_tosa_bitwise_not.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
@register_node_visitor
1919
class BitwiseNotVisitor(SimpleNodeVisitor):
20-
target = "aten.bitwise_not.default"
20+
target = "tosa.BITWISE_NOT.default"
2121
tosa_specs = INT_SPECS
2222

2323
@classmethod
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
@register_node_visitor
1919
class CeilVisitor(SimpleNodeVisitor):
20-
target = "aten.ceil.default"
20+
target = "tosa.CEIL.default"
2121
tosa_specs = FP_SPECS
2222

2323
@classmethod
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright 2026 Arm Limited and/or its affiliates.
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 tosa_serializer as ts
7+
8+
from executorch.backends.arm.operators.node_visitor import register_node_visitor
9+
from executorch.backends.arm.operators.simple_node_visitor import (
10+
SimpleNodeVisitor,
11+
SimpleNodeVisitorConfig,
12+
)
13+
from executorch.backends.arm.tosa import TosaSpecification
14+
15+
INT_SPECS = TosaSpecification.all_versions_for_profile("INT")
16+
17+
18+
@register_node_visitor
19+
class ClzVisitor(SimpleNodeVisitor):
20+
target = "tosa.CLZ.default"
21+
tosa_specs = INT_SPECS
22+
23+
@classmethod
24+
def get_config(cls) -> SimpleNodeVisitorConfig:
25+
return SimpleNodeVisitorConfig(
26+
tosa_op=ts.Op.CLZ,
27+
attr_method="ClzAttribute",
28+
num_inputs=1,
29+
input_dtypes=[ts.DType.INT32],
30+
)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
@register_node_visitor
1919
class CosVisitor(SimpleNodeVisitor):
20-
target = "aten.cos.default"
20+
target = "tosa.COS.default"
2121
tosa_specs = FP_SPECS
2222

2323
@classmethod
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
@register_node_visitor
1919
class ExpVisitor(SimpleNodeVisitor):
20-
target = "aten.exp.default"
20+
target = "tosa.EXP.default"
2121
tosa_specs = FP_SPECS
2222

2323
@classmethod
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
@register_node_visitor
1919
class FloorVisitor(SimpleNodeVisitor):
20-
target = "aten.floor.default"
20+
target = "tosa.FLOOR.default"
2121
tosa_specs = FP_SPECS
2222

2323
@classmethod

0 commit comments

Comments
 (0)