Skip to content

Cortex-M: lower subtraction, and stop miscompiling add with alpha - #22153

Open
rascani wants to merge 1 commit into
pytorch:mainfrom
rascani:cortex-m-sub-lowering
Open

Cortex-M: lower subtraction, and stop miscompiling add with alpha#22153
rascani wants to merge 1 commit into
pytorch:mainfrom
rascani:cortex-m-sub-lowering

Conversation

@rascani

@rascani rascani commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

quantized_add carries a multiplier per operand, so subtraction is the same kernel with the second one negated. quantize_multiplier_aot always lands in [2^30, 2^31), so the negation cannot saturate; the first requantize stage rounds asymmetrically under negation, but the second absorbs it and the int8 output is identical across 400 scale and zero-point configurations.

This exposed an existing bug. alpha scales the second operand, quantized_add has nowhere to put it, and nothing checked, so torch.add(x, y, alpha=2) computed x + y and returned wrong values silently. The quantizer now declines those nodes and they stay fp32. It has to be the quantizer: by the time the lowering runs FoldAndAnnotateQParamsPass has removed the dq nodes, so declining there would leave an fp32 add over raw int8. The lowering raises instead.

Subtraction also makes an existing overflow reachable, where the kernel's int32 left shift wraps and saturates to the opposite rail. No multiplier split avoids it - shrinking max_scale_2x buys a shift and costs the same headroom - so the lowering refuses the configuration, which needs operands that nearly cancel.

Two gaps left open: ActivationFusionPass does not fold relu into sub, and rsub with alpha is still wrong because pass drops alpha before annotation.

Authored with Claude Code.

quantized_add carries a multiplier per operand, so subtraction is the same kernel
with the second one negated. quantize_multiplier_aot always lands in
[2^30, 2^31), so the negation cannot saturate; the first requantize stage rounds
asymmetrically under negation, but the second absorbs it and the int8 output is
identical across 400 scale and zero-point configurations.

This exposed an existing bug. alpha scales the second operand, quantized_add has
nowhere to put it, and nothing checked, so torch.add(x, y, alpha=2) computed
x + y and returned wrong values silently. The quantizer now declines those nodes
and they stay fp32. It has to be the quantizer: by the time the lowering runs
FoldAndAnnotateQParamsPass has removed the dq nodes, so declining there would
leave an fp32 add over raw int8. The lowering raises instead.

Subtraction also makes an existing overflow reachable, where the kernel's int32
left shift wraps and saturates to the opposite rail. No multiplier split avoids
it -- shrinking max_scale_2x buys a shift and costs the same headroom -- so the
lowering refuses the configuration, which needs operands that nearly cancel.

Two gaps left open: ActivationFusionPass does not fold relu into sub, and rsub
with alpha is still wrong because Arm's pass drops alpha before annotation.

Authored with Claude Code.
@pytorch-bot

pytorch-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

As of commit e668893 with merge base baafd7e (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 Aug 25, 2026
@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.

@AdrianLundell AdrianLundell 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.

LGTM, but why not address the two gaps in the commit message right away? And could alpha not be folded into the qparams as well at least as long as it isn't too big?

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants