Skip to content

Arm backend: Add aten.flip support via TOSA REVERSE#20592

Merged
zingo merged 1 commit into
pytorch:mainfrom
vacu9708:flip
Jul 3, 2026
Merged

Arm backend: Add aten.flip support via TOSA REVERSE#20592
zingo merged 1 commit into
pytorch:mainfrom
vacu9708:flip

Conversation

@vacu9708

@vacu9708 vacu9708 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

TOSA REVERSE reverses a single axis, while aten.flip can take several. A multi-axis flip is a chain of single-axis reversals, so:

  • DecomposeFlipPass rewrites a multi-axis flip into single-axis flips (one dim passes through, zero dims is a no-op).
    • The quantizer annotates it as a shared-qspec op. The decompose runs after Q/DQ folding, so the chained flips inherit the shared quant params from the node metadata.
  • FlipVisitor lowers each single-axis flip to one REVERSE (axis = dim % rank).
graph TD
    src["aten.flip(x, [d0, d1, d2])"]
    src -->|DecomposeFlipPass| F0

    subgraph flips["FX graph"]
        direction LR
        F0["aten.flip [d0]"] --> F1["aten.flip [d1]"] --> F2["aten.flip [d2]"]
    end

    subgraph reverses["Serialized TOSA"]
        direction LR
        R0["REVERSE axis=d0"] --> R1["REVERSE axis=d1"] --> R2["REVERSE axis=d2"]
    end

    F0 -.FlipVisitor.-> R0
    F1 -.FlipVisitor.-> R1
    F2 -.FlipVisitor.-> R2
Loading

Changes

I referred to existing ops for each new file: op_permute.py for op_flip.py, decompose_strided_slice_copy_pass for decompose_flip_pass.py, and test_permute.py for test_flip.py.

File Change
_passes/decompose_flip_pass.py (new) DecomposeFlipPass
operators/op_flip.py (new) FlipVisitor
_passes/__init__.py export DecomposeFlipPass
_passes/arm_pass_manager.py register DecomposeFlipPass in the post-fold decompose stage
operators/__init__.py register op_flip
operator_support/tosa_profile_supported_op_lists.py add aten.flip.default to the INT and FP support lists
test/ops/test_flip.py (new) Test cases

Testing

$ pytest backends/arm/test/ops/test_flip.py -q
33 passed, 14 skipped, 7 xfailed

$ lintrunner   # new and changed files
ok No lint issues.
Test Dtype / target Ranks / dims What it verifies Result
tosa_FP FP32 1–4; single, negative, multi-axis output matches torch.flip pass
tosa_FP_reverse_count FP32 1–4; single, negative, multi-axis one TOSA REVERSE per flipped dim pass
tosa_FP_bf16 bf16 rank 4; multi-axis output matches torch.flip pass
tosa_FP_fp8 fp8 e4m3 / e5m2 rank 4; multi-axis output matches torch.flip pass
bool_tosa_FP bool rank 2; single-axis output matches torch.flip on a bool mask pass
tosa_INT INT8 1–4; single, negative, multi-axis output matches torch.flip pass
16a8w_tosa_INT INT16 (16a8w) 1–4; single, negative, multi-axis output matches torch.flip pass
u55_INT_not_delegated INT8 / U55 rank 4; single-axis flip is rejected and runs on CPU (U55 has no REVERSE) pass
u85_INT INT8 / Ethos-U85 1–4; single, negative, multi-axis runs on Ethos-U85 xfail locally (no FVP); runs in CI
vgf_no_quant, vgf_quant FP & INT / VGF 1–4; single, negative, multi-axis runs on the VGF backend skip locally (no converter); runs in CI

cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell @rascani

@vacu9708 vacu9708 requested a review from digantdesai as a code owner June 29, 2026 12:50
@pytorch-bot

pytorch-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/20592

Note: Links to docs will display an error until the docs builds have been completed.

❌ 1 New Failure, 32 Pending

As of commit 6882925 with merge base d03dee5 (image):

NEW FAILURE - The following job has failed:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 29, 2026
@github-actions github-actions Bot added ciflow/trunk module: arm Issues related to arm backend labels Jun 29, 2026
@pytorch-bot

pytorch-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

Workflows were awaiting approval. CI has now been triggered for the ciflow labels on this PR.

@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

@zingo zingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Jul 2, 2026
exir_op = "executorch_exir_dialects_edge__ops_aten_flip_default"

input_t1 = Tuple[torch.Tensor] # Input x

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice with coverage for dims=[]

@zingo

zingo commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the nice patch!
I started some extra testing that for some reason didn't get started automatically :).

@zingo

zingo commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

@claude does the new files in this PR need to be added to any buck2 files?

@claude

claude Bot commented Jul 2, 2026

Copy link
Copy Markdown

Claude finished @zingo's task in 1m 19s —— View job


Do the new files need buck2 (TARGETS) updates?

Short answer: only the test file. The two new source files are already covered by globs, but test/ops/test_flip.py must be added explicitly.

Details:

New file buck2 target Needs manual entry?
_passes/decompose_flip_pass.py _passes/TARGETSpasses uses glob(["*.py"], ...) ❌ No — picked up automatically
operators/op_flip.py operators/TARGETSops uses glob(["op_*.py", "ops_*.py"]) ❌ No — matches op_*.py
test/ops/test_flip.py test/targets.bzldefine_arm_tests uses an explicit list (ops/test_*.py are not globbed) Yes

The modified files (_passes/__init__.py, arm_pass_manager.py, operators/__init__.py, operator_support/tosa_profile_supported_op_lists.py) are all covered by existing globs, so no target changes there.

Required change

In backends/arm/test/targets.bzl, add test_flip.py to the operator test list (kept alphabetical-ish next to the other ops):

         "ops/test_exp.py",
         "ops/test_fft.py",
+        "ops/test_flip.py",

Note the passes tests are globbed (test_files += native.glob(["passes/test_*.py"])), so if there were a passes/test_decompose_flip*.py it would be automatic — but the op test list is explicit and needs this line.

Note

I made this change locally but couldn't push it — the branch's Meta CLA Check repository rule rejects pushes from this bot. Please add the one line above yourself (or let me know how you'd like to proceed).
· branch flip

@zingo zingo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks this will be Ok to merge after the backends/arm/test/targets.bzl is updated (see comments) and extra nice if you also add a test case but that can be fixed later also :)

@@ -0,0 +1,207 @@
# Copyright 2026 Arm Limited and/or its affiliates.

@zingo zingo Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be added to backends/arm/test/targets.bzl see claude comment for more info :)

flip was staged as supported (quantizer, EthosU55NotSupported,
InsertDataLayoutCastsPass) but had no lowering, so it fell back to CPU.

TOSA REVERSE reverses a single axis, while aten.flip can take several:

- DecomposeFlipPass rewrites a multi-axis flip into a chain of single-axis
  flips, run after Q/DQ folding so each inherits the shared quant params.
- FlipVisitor lowers each single-axis flip to one REVERSE (axis = dim % rank).
- aten.flip.default is added to the INT and FP support lists so it delegates.

U55 and U65 are unchanged: their TOSA subset has no REVERSE.

Signed-off-by: Youngsik Yang <vacu9708@gmail.com>

@zingo zingo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super thanks!
I approved it but lets the tests run just to make sure then you can merge. If you can't let me know and Ill merge this for you.

@zingo

zingo commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

All test passer the test-qnn-.. . Is unrelated and fails in other PRs also.

@vacu9708

vacu9708 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the quick review and for kicking off the extra CI, @zingo!

Both review points have been addressed.

  • Added ops/test_flip.py to backends/arm/test/targets.bzl.
  • Added dims=[] coverage (test_flip_empty_dims_not_delegated). An empty flip is the identity, so the partitioner treats it as a no-op (_is_noop_flip) and keeps it on CPU instead of delegating.

I don't have merge access, can you please merge it if there are no more issues?

@zingo zingo merged commit 112eb50 into pytorch:main Jul 3, 2026
488 of 489 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunk CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. module: arm Issues related to arm backend partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants