Skip to content

[XNNPACK] Compose stacked activations in FuseActivationPass instead of overwriting - #24484

Merged
JakeStevens merged 2 commits into
pytorch:mainfrom
AxelNoun:xnnpack-compose-stacked-activations
Nov 9, 2026
Merged

JakeStevens merged 2 commits into
pytorch:mainfrom
AxelNoun:xnnpack-compose-stacked-activations

Conversation

@AxelNoun

@AxelNoun AxelNoun commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

FuseActivationPass stores the fused clamp range in node.meta. When two clamping activations follow the same op (for example Linear -> ReLU6 -> ReLU), the second fusion overwrote the first tag, so the delegate applied [0, inf) instead of [0, 6] (and [-1, 1] instead of [0, 1] for ReLU -> Hardtanh(-1, 1)), silently changing outputs.

The pass now composes the existing range with the new one (clamp of clamp), keeping the "+inf"/"-inf" string convention used by serialization. Behavior without a previously fused activation is unchanged.

Test plan: new test_activation_fusion_stacked_activations (6 cases: 5 fail before this change, all pass after). pytest backends/xnnpack/test/passes: 70 passed with this change, and no other test changes outcome. End to end through the XNNPACK runtime, the maximum absolute difference to eager for Linear followed by ReLU6, ReLU / Hardtanh(-1, 1), ReLU / ReLU, Hardtanh(-1, 1) / Hardtanh(-2, 2), Hardtanh(-1, 3) is 3.12 / 8.49 / 1.00 / 1.00 before and 0 after (run with the v1.5.1 pybindings, where the pass and its test file are identical to main).

I used Claude Code to help with this change.

cc @GregoryComer @digantdesai @cbilgin @JakeStevens @nil-is-all

When two clamping activations follow the same op, for example
Linear -> ReLU6 -> ReLU, the second fusion overwrote the OutputMinMax
tag of the first one, so the delegate applied the wrong clamp range and
silently changed the output. The pass now composes the existing range
with the new one, keeping the "+inf"/"-inf" string convention used by
serialization.
@AxelNoun
AxelNoun requested a review from digantdesai as a code owner November 3, 2026 06:43
@pytorch-bot

pytorch-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

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

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

⏳ No Failures, 1 Pending

As of commit 76b9feb with merge base ebdb936 (image):
💚 Looks good so far! There are no failures yet. 💚

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 Nov 3, 2026
@AxelNoun

AxelNoun commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@pytorchbot label "release notes: xnnpack"

@pytorch-bot pytorch-bot Bot added the release notes: xnnpack Changes to the XNNPack backend delegate label Nov 3, 2026
@executorch-triage executorch-triage Bot added the community: contribution PRs coming from community (excluding hardware partners) label Nov 3, 2026
@nil-is-all nil-is-all added the module: xnnpack Issues related to xnnpack delegation and the code under backends/xnnpack/ label Nov 9, 2026
@JakeStevens
JakeStevens merged commit 6605290 into pytorch:main Nov 9, 2026
199 checks passed
@AxelNoun
AxelNoun deleted the xnnpack-compose-stacked-activations branch November 9, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. community: contribution PRs coming from community (excluding hardware partners) module: xnnpack Issues related to xnnpack delegation and the code under backends/xnnpack/ release notes: xnnpack Changes to the XNNPack backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants