Skip to content

Create utility to rebind args/kwargs. #10987

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions backends/cadence/aot/TARGETS
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ python_library(
typing = True,
deps = [
":pass_utils",
":utils",
"//executorch/backends/cadence/aot:pass_utils",
"//executorch/exir:pass_base",
"//executorch/exir/dialects:lib",
Expand Down
29 changes: 4 additions & 25 deletions backends/cadence/aot/simplify_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
CadencePassAttribute,
register_cadence_pass,
)
from executorch.backends.cadence.aot.utils import rebind
from executorch.exir.dialects._ops import ops as exir_ops
from executorch.exir.dialects.edge._ops import EdgeOpOverload
from executorch.exir.pass_base import ExportPass, ProxyValue
from torch.fx.operator_schemas import get_signature_for_torch_op


@register_cadence_pass(CadencePassAttribute(opt_level=0))
Expand Down Expand Up @@ -117,32 +117,11 @@ class BindOptionalArgsPass(ExportPass):
def call_operator(self, op, args, kwargs, meta):
if not isinstance(op, EdgeOpOverload):
return super().call_operator(op, args, kwargs, meta)
assert callable(op)

torch_op_schemas = get_signature_for_torch_op(op._op)
if len(torch_op_schemas) == 0:
return super().call_operator(op, args, kwargs, meta)

matched_schemas = []
# Iterate through all of the schema until we find one that matches
# If one matches, populate `new_args_and_kwargs` with the new args/kwargs
# values. If none matches, `new_args_and_kwargs` will be None
for candidate_signature in torch_op_schemas:
try:
candidate_signature.bind(*args, **kwargs)
matched_schemas.append(candidate_signature)
except TypeError:
continue

if len(matched_schemas) != 1:
# Did not match any schema. Cannot normalize
return super().call_operator(op, args, kwargs, meta)

sig = matched_schemas[0]
bound_args = sig.bind(*args, **kwargs)
bound_args.apply_defaults()
if (updated_args := rebind(op, args, kwargs)) is not None:
args, kwargs = updated_args

return super().call_operator(op, bound_args.args, bound_args.kwargs, meta)
return super().call_operator(op, args, kwargs, meta)


# This class encapsulates all the functions that simplify the op's args
Expand Down
29 changes: 29 additions & 0 deletions backends/cadence/aot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
from executorch.exir import ExecutorchProgramManager, memory
from executorch.exir.dialects._ops import ops as exir_ops
from executorch.exir.dialects.edge._ops import EdgeOpOverload, EdgeOpOverloadPacket
from executorch.exir.pass_base import Argument
from tabulate import tabulate
from torch.fx.operator_schemas import get_signature_for_torch_op

from torch.utils._pytree import tree_flatten

Expand Down Expand Up @@ -308,3 +310,30 @@ def get_size(self, exir_id: int) -> int:
# Return default memory config for the backend
def get_default_memory_config() -> MemoryConfig:
return MemoryConfig(memory_sizes=[0x1000000000])


def rebind(
op: EdgeOpOverload, args: tuple[Argument, ...], kwargs: dict[str, Argument]
) -> Optional[tuple[tuple[Argument, ...], dict[str, Argument]]]:
"""Populates optional args and binds args/kwargs based on schema."""
torch_op_schemas = get_signature_for_torch_op(op._op)

matched_schemas = []
# Iterate through all of the schema until we find one that matches
# If one matches, populate `new_args_and_kwargs` with the new args/kwargs
# values. If none matches, `new_args_and_kwargs` will be None
for candidate_signature in torch_op_schemas:
try:
candidate_signature.bind(*args, **kwargs)
matched_schemas.append(candidate_signature)
except TypeError:
continue

if len(matched_schemas) != 1:
# Did not match any schema. Cannot normalize
return None

bound_args = matched_schemas[0].bind(*args, **kwargs)
bound_args.apply_defaults()

return bound_args.args, bound_args.kwargs
Loading