Skip to content

Commit f2bc17c

Browse files
committed
Update (base update)
[ghstack-poisoned]
2 parents 3dd8111 + b1dd46a commit f2bc17c

7 files changed

Lines changed: 47 additions & 49 deletions

File tree

backends/mlx/passes.py

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -99,49 +99,8 @@ def call(self, exported_program) -> ExportedProgramPassResult:
9999
}
100100
if ops_to_inplace:
101101
reinplace_pass(exported_program, ops_to_inplace=ops_to_inplace)
102-
self._resync_output_specs(exported_program)
103102
return ExportedProgramPassResult(exported_program, True)
104103

105-
@staticmethod
106-
def _resync_output_specs(exported_program) -> None:
107-
"""Re-sync graph-signature output names after reinplace.
108-
109-
``reinplace_pass`` rewrites an output-producing node (e.g. the final
110-
``exp`` -> ``exp_``) via ``replace_all_uses_with`` + erase, but does not
111-
update ``graph_signature.output_specs``. Output order is preserved, so we
112-
positionally re-sync each spec's argument name to the current output node
113-
arg; otherwise ``ExportedProgram.validate()`` (run by the pass manager)
114-
raises a SpecViolationError.
115-
116-
This positional pairing is only valid because reinplace does a 1:1
117-
``replace_all_uses_with`` + erase and never drops, adds, or reorders
118-
outputs. We assert ``len(output_specs) == len(out_args)`` so that a
119-
future change violating that invariant fails loudly here instead of
120-
silently mis-pairing names (``zip`` would otherwise truncate). Specs
121-
whose ``arg`` is not a named tensor (e.g. ``ConstantArgument``) carry no
122-
``name`` and are skipped by the ``getattr`` guard below.
123-
"""
124-
out_node = next(
125-
n for n in reversed(exported_program.graph.nodes) if n.op == "output"
126-
)
127-
out_args = out_node.args[0]
128-
if not isinstance(out_args, (tuple, list)):
129-
out_args = (out_args,)
130-
output_specs = exported_program.graph_signature.output_specs
131-
assert len(output_specs) == len(out_args), (
132-
"reinplace changed graph output count: "
133-
f"{len(output_specs)} output_specs vs {len(out_args)} output args. "
134-
"Positional output-spec re-sync assumes a 1:1, order-preserving "
135-
"rewrite."
136-
)
137-
for spec, arg in zip(output_specs, out_args):
138-
if (
139-
isinstance(arg, torch.fx.Node)
140-
and getattr(spec.arg, "name", None) is not None
141-
and spec.arg.name != arg.name
142-
):
143-
spec.arg.name = arg.name
144-
145104

146105
@dataclass
147106
class RMSNormMatch(PatternMatch):

backends/vulkan/test/op_tests/utils/aten_types.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
OPT_MEMORY_FORMAT = "::std::optional<at::MemoryFormat>"
2727
OPT_SCALAR_TYPE = "::std::optional<at::ScalarType>"
2828
STRING = "std::string_view"
29-
OLD_STRING = "c10::string_view"
3029
TWO_TENSOR_TUPLE = "::std::tuple<at::Tensor,at::Tensor>"
3130
THREE_TENSOR_TUPLE = "::std::tuple<at::Tensor,at::Tensor,at::Tensor>"
3231
TENSOR_VECTOR = "::std::vector<at::Tensor>"

backends/vulkan/test/op_tests/utils/gen_computegraph.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
BOOL,
1717
DOUBLE,
1818
INT,
19-
OLD_STRING,
2019
OPT_AT_DOUBLE_ARRAY_REF,
2120
OPT_AT_INT_ARRAY_REF,
2221
OPT_AT_TENSOR,
@@ -122,7 +121,9 @@ def __init__(
122121
ctype = cpp.argumenttype_type(
123122
arg.type, mutable=arg.is_write, binds=arg.name
124123
)
125-
cpp_type = ctype.cpp_type(strip_ref=True)
124+
cpp_type = ctype.cpp_type(strip_ref=True).replace(
125+
"c10::string_view", STRING
126+
)
126127

127128
self.args.append(
128129
ATenArg(name=arg.name, cpp_type=cpp_type, default=arg.default)
@@ -494,7 +495,7 @@ def create_value_for( # noqa: C901
494495
or ref.src_cpp_type == OPT_MEMORY_FORMAT
495496
):
496497
ret_str += "add_none(); \n"
497-
elif ref.src_cpp_type == STRING or ref.src_cpp_type == OLD_STRING:
498+
elif ref.src_cpp_type == STRING:
498499
ret_str += f"add_string(std::string({ref.src_cpp_name})); \n"
499500
elif ref.src_cpp_type == TWO_TENSOR_TUPLE:
500501
ret_str += f"add_value_list({{{ref.name}_first, {ref.name}_second}}); \n"

backends/vulkan/test/op_tests/utils/gen_correctness_base.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
BOOL,
1616
DOUBLE,
1717
INT,
18-
OLD_STRING,
1918
OPT_AT_DOUBLE_ARRAY_REF,
2019
OPT_AT_INT_ARRAY_REF,
2120
OPT_AT_TENSOR,
@@ -156,7 +155,7 @@ def call_data_gen_fn(self, arg: Argument, data: Any, terminate: bool = True) ->
156155

157156
def create_input_data(self, arg: Argument, data: Any) -> str: # noqa: C901
158157
ctype = cpp.argumenttype_type(arg.type, mutable=arg.is_write, binds=arg.name)
159-
cpp_type = ctype.cpp_type(strip_ref=True)
158+
cpp_type = ctype.cpp_type(strip_ref=True).replace("c10::string_view", STRING)
160159

161160
# Short cut exit for TENSORLIST, because it needs multiple lines of
162161
# construction, deviates from the rest.
@@ -218,7 +217,7 @@ def create_input_data(self, arg: Argument, data: Any) -> str: # noqa: C901
218217
ret_str += "std::nullopt;"
219218
else:
220219
ret_str += f"{str(data)};"
221-
elif cpp_type == STRING or cpp_type == OLD_STRING:
220+
elif cpp_type == STRING:
222221
ret_str += f'std::string_view("{data}");'
223222
elif (
224223
cpp_type == OPT_SCALAR_TYPE

exir/passes/reinplace.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,4 +507,26 @@ def reinplace_pass( # noqa: C901
507507
continue
508508

509509
seen_nodes.update(node.all_input_nodes)
510+
511+
# Reinplace rewrites may rename output nodes (e.g. aten_relu_default →
512+
# aten_relu__default) but replace_all_uses_with does not update the
513+
# graph signature. Fix output_specs to match the actual output node args.
514+
output_node = next((n for n in ep.graph.nodes if n.op == "output"), None)
515+
if output_node is not None:
516+
out_args = output_node.args[0]
517+
if not isinstance(out_args, (tuple, list)):
518+
out_args = (out_args,)
519+
output_specs = ep.graph_signature.output_specs
520+
assert len(output_specs) == len(out_args), (
521+
f"reinplace: output spec count changed: "
522+
f"{len(output_specs)} specs vs {len(out_args)} output args"
523+
)
524+
for spec, arg in zip(output_specs, out_args):
525+
if (
526+
isinstance(arg, torch.fx.Node)
527+
and getattr(spec.arg, "name", None) is not None
528+
and spec.arg.name != arg.name
529+
):
530+
spec.arg.name = arg.name
531+
510532
return ep

exir/tests/test_reinplace_pass.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,25 @@ def forward(
326326
# kernels in the other tests in this file.
327327
edge.to_executorch()
328328

329+
def test_output_specs_updated_after_reinplace(self) -> None:
330+
"""reinplace_pass must update graph_signature.output_specs to match
331+
the renamed output nodes (e.g. relu -> relu_)."""
332+
333+
class M(torch.nn.Module):
334+
def forward(self, x: torch.Tensor) -> torch.Tensor:
335+
return torch.relu(x + 1.0)
336+
337+
ep = export(M(), (torch.randn(4),), strict=True)
338+
edge_program = to_edge(ep).exported_program()
339+
340+
custom_set = {edge_ops.edge.aten.relu.default}
341+
ep = reinplace_pass(edge_program, ops_to_inplace=custom_set)
342+
343+
output_node = next(n for n in ep.graph.nodes if n.op == "output")
344+
actual_names = [arg.name for arg in output_node.args[0] if hasattr(arg, "name")]
345+
spec_names = [s.arg.name for s in ep.graph_signature.output_specs]
346+
self.assertEqual(actual_names, spec_names)
347+
329348
def test_broadcasting_self_not_reinplaced(self) -> None:
330349
"""An op whose mutated arg (self) broadcasts up to a larger output
331350
must NOT be reinplaced: the in-place form cannot grow self

exir/verification/bindings.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include <c10/core/ScalarType.h>
1414
#include <c10/macros/Macros.h>
1515
#include <c10/util/C++17.h>
16-
#include <c10/util/Optional.h>
1716
#include <pybind11/pybind11.h>
1817
#include <pybind11/stl.h>
1918
#include <torch/extension.h> // @manual=//caffe2:torch_extension

0 commit comments

Comments
 (0)