Skip to content

Commit 4113e2d

Browse files
apullinfacebook-github-bot
authored andcommitted
Cache param/buffer/constant names in RemovePermutesAroundElementwiseTosaOps (#22164)
Summary: `RemovePermutesAroundElementwiseTosaOps._is_constant` called `is_param_node()` for every node reached during recursive `visit()` walk. Each `is_param_node` rebuilds immutable dict over full input_specs via uncached graph_signature properties. This made pass O(nodes * inputs). Precompute the union of param/buffer/lifted-constant placeholder names once per pass invocation in `call()` and use O(1) set membership. Refreshing it at invocation time tracks the current `ExportedProgram` when a pass instance is reused. Semantics unchanged. Differential Revision: D114224782
1 parent ff679f5 commit 4113e2d

2 files changed

Lines changed: 40 additions & 5 deletions

File tree

backends/arm/_passes/remove_permutes_around_elementwise_tosa_ops.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55

66
import torch
77

8-
from executorch.backends.arm._passes.arm_pass_utils import is_param_node
98
from executorch.backends.arm._passes.insert_table_ops import TableOps
109
from executorch.backends.transforms.remove_permutes_around_elementwise_ops import (
1110
RemovePermutesAroundElementwiseOps,
1211
)
1312
from executorch.exir import ExportedProgram
1413
from executorch.exir.dialects._ops import ops as exir_ops
14+
from executorch.exir.pass_base import PassResult
1515

1616

1717
class RemovePermutesAroundElementwiseTosaOps(RemovePermutesAroundElementwiseOps):
@@ -25,10 +25,22 @@ def __init__(self, exported_program: ExportedProgram) -> None:
2525
}
2626
)
2727
self.exported_program = exported_program
28+
self._constant_input_names: set[str] = set()
29+
30+
def call(self, graph_module: torch.fx.GraphModule) -> PassResult:
31+
# The ARM pass manager updates exported_program before each invocation.
32+
gs = self.exported_program.graph_signature
33+
self._constant_input_names = (
34+
set(gs.inputs_to_parameters)
35+
| set(gs.inputs_to_buffers)
36+
| set(gs.inputs_to_lifted_tensor_constants)
37+
)
38+
return super().call(graph_module)
2839

2940
def _is_constant(self, node: torch.fx.Node) -> bool:
30-
# Override fragile string match check with exported program check
31-
return super()._is_constant(node) or is_param_node(self.exported_program, node)
41+
# get_attr nodes are handled by super()._is_constant; set membership
42+
# here is equivalent to is_param_node for placeholder inputs.
43+
return super()._is_constant(node) or node.name in self._constant_input_names
3244

3345
def permute_subgraph(self, subgraph) -> bool:
3446
# TABLE lookup inputs are already tied to the table layout.

backends/arm/test/passes/test_remove_permutes_around_elementwise_tosa_ops.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
ERF_TARGET = exir_ops.edge.aten.erf.default
3030

3131

32-
def _fake_exported_program() -> ExportedProgram:
32+
def _fake_exported_program(*constant_input_names: str) -> ExportedProgram:
3333
return cast(
3434
ExportedProgram,
3535
SimpleNamespace(
3636
graph_signature=SimpleNamespace(
3737
inputs_to_buffers={},
3838
inputs_to_lifted_tensor_constants={},
39-
inputs_to_parameters={},
39+
inputs_to_parameters={name: name for name in constant_input_names},
4040
)
4141
),
4242
)
@@ -50,6 +50,29 @@ def _count_nodes(graph_module: torch.fx.GraphModule, target) -> int:
5050
)
5151

5252

53+
def test_constant_input_cache_refreshes_for_reused_pass() -> None:
54+
first_graph = torch.fx.Graph()
55+
first_constant = first_graph.placeholder("first_constant")
56+
first_constant.meta["val"] = torch.randn(1)
57+
first_graph.output(first_constant)
58+
59+
second_graph = torch.fx.Graph()
60+
second_constant = second_graph.placeholder("second_constant")
61+
second_constant.meta["val"] = torch.randn(1)
62+
second_graph.output(second_constant)
63+
64+
remove_permutes = RemovePermutesAroundElementwiseTosaOps(
65+
_fake_exported_program("first_constant")
66+
)
67+
remove_permutes.call(torch.fx.GraphModule({}, first_graph))
68+
assert remove_permutes._is_constant(first_constant)
69+
70+
remove_permutes.exported_program = _fake_exported_program("second_constant")
71+
remove_permutes.call(torch.fx.GraphModule({}, second_graph))
72+
assert remove_permutes._is_constant(second_constant)
73+
assert not remove_permutes._is_constant(first_constant)
74+
75+
5376
def test_extra_permutable_ops_makes_op_permutable() -> None:
5477
"""Ops in extra_permutable_ops are permutable in the base pass."""
5578

0 commit comments

Comments
 (0)