Skip to content
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
44 changes: 41 additions & 3 deletions backends/arm/scripts/docgen/generate_vgf_op_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
from pathlib import Path
from typing import cast, Iterable, Mapping, Protocol, Sequence

import torch


DEFAULT_OUTPUT = Path("docs/source/backends/arm-vgf/VGF_op_support.md")
TEST_ROOT = Path("backends/arm/test")
Expand Down Expand Up @@ -237,6 +239,18 @@
# higher-level PyTorch APIs. These are what should appear in the published page.
# Unknown operators fall back to a conservative ``torch.<aten-name>`` spelling.
PYTORCH_API_ALIASES: dict[str, tuple[str, ...]] = {
# Internal / higher-order operators with explicit public API spellings.
"torch.ops.aten._assert_scalar.default": ("torch._assert_scalar",),
"torch.ops.aten.t_copy.default": (
"torch.t",
"torch.Tensor.t",
),
"torch.ops.aten.transpose_copy.int": (
"torch.transpose",
"torch.Tensor.transpose",
),
"torch.ops.higher_order.cond": ("torch.cond",),
"torch.ops.higher_order.while_loop": ("torch.while_loop",),
# Arithmetic and comparisons.
"torch.ops.aten.add.Tensor": ("torch.add", "+"),
"torch.ops.aten.add.Scalar": ("torch.add", "+"),
Expand Down Expand Up @@ -777,6 +791,12 @@ def _normalize_pytorch_op_name( # noqa: C901
return None

original = text

# Higher-order operators are not ATen operators. Preserve their namespace
# instead of rewriting torch.ops.higher_order.* as torch.ops.aten.*.
if text.startswith("torch.ops.higher_order."):
return text

if text.startswith(generated_prefix):
text = _edge_generated_name_to_aten(text.removeprefix(generated_prefix))

Expand Down Expand Up @@ -847,14 +867,29 @@ def _split_exported_op(exported_op: str) -> tuple[str, str] | None:
return name, overload


def _torch_api_exists(api: str) -> bool:
"""Return whether a dotted torch API exists and is callable."""

if not api.startswith("torch."):
return False

obj: object = torch
for part in api.split(".")[1:]:
if not hasattr(obj, part):
return False
obj = getattr(obj, part)

return callable(obj)


def _fallback_pytorch_api_aliases(exported_op: str) -> tuple[str, ...]:
split = _split_exported_op(exported_op)
if split is None:
return (exported_op,)
return ()

name, _overload = split
public_name = name.removeprefix("_").removesuffix("_")
return (f"torch.{public_name}",)
candidate = f"torch.{name}"
return (candidate,) if _torch_api_exists(candidate) else ()


def _pytorch_api_aliases(exported_op: str) -> tuple[str, ...]:
Expand Down Expand Up @@ -2033,6 +2068,9 @@ def _public_rows_from_exact_rows(
) -> list[PublicCoverage]:
public_rows: dict[str, PublicCoverage] = {}
for exact in exact_rows.values():
if not exact.pytorch_apis:
continue

key = _api_key(exact.pytorch_apis)
row = public_rows.setdefault(
key,
Expand Down
29 changes: 29 additions & 0 deletions backends/arm/scripts/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ DOCGEN_OUTPUTS=(
"docs/source/backends/arm-vgf/tutorials/vgf-getting-started.md"
)

VGF_OP_SUPPORT_SCRIPT="backends/arm/scripts/docgen/generate_vgf_op_support.py"
VGF_OP_SUPPORT_OUTPUT="docs/source/backends/arm-vgf/VGF_op_support.md"

RUN_DOCGEN=0

is_docgen_trigger_file() {
Expand Down Expand Up @@ -70,6 +73,31 @@ run_docgen_check() {
fi
}

run_vgf_op_support_checks() {
echo -e "${INFO} Generating VGF operator support documentation"

if ! python "$VGF_OP_SUPPORT_SCRIPT"; then
echo -e "${ERROR} Failed to generate VGF operator support documentation"
FAILED=1
elif ! git diff --quiet HEAD -- "$VGF_OP_SUPPORT_OUTPUT"; then
echo -e "${ERROR} VGF operator support documentation is out of date." >&2
echo -e "${INFO} Review and commit the regenerated operator support list before pushing."
git diff HEAD -- "$VGF_OP_SUPPORT_OUTPUT"
FAILED=1
else
echo -e "${SUCCESS} VGF operator support documentation OK"
fi

echo -e "${INFO} Checking VGF operator support coverage"

if ! python "$VGF_OP_SUPPORT_SCRIPT" --check; then
echo -e "${ERROR} VGF operator support coverage check failed" >&2
FAILED=1
else
echo -e "${SUCCESS} VGF operator support coverage OK"
fi
}

run_public_api_validator() {
if ! backends/arm/scripts/public_api_manifest/validate_all_public_api_manifests.sh; then
echo -e "${ERROR} Arm public API manifest validation failed"
Expand Down Expand Up @@ -318,6 +346,7 @@ else
echo -e "${INFO} Skipping Arm docgen (no public API inputs changed)"
fi

run_vgf_op_support_checks
run_public_api_validator

if [[ $FAILED ]]; then
Expand Down
Loading
Loading