Skip to content

Add fused int8 LSTM support to the Cortex-M (CMSIS-NN) backend#21024

Draft
rascani wants to merge 1 commit into
pytorch:mainfrom
rascani:cortex-m-lstm
Draft

Add fused int8 LSTM support to the Cortex-M (CMSIS-NN) backend#21024
rascani wants to merge 1 commit into
pytorch:mainfrom
rascani:cortex-m-lstm

Conversation

@rascani

@rascani rascani commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Lower a single-layer, unidirectional nn.LSTM to a fused cortex_m::quantized_lstm op backed by CMSIS-NN's arm_lstm_unidirectional_s8. Instead of decomposing the LSTM into primitives, aten.lstm.input is preserved through to_edge, boundary-quantized (int8 input/output activations, weights kept in float), and fused in a single pass. The per-gate CMSIS parameters -- Q3.12 gate accumulator, Q0.15 activations, and a power-of-two int16 cell state -- are derived ahead of time from the boundary scales and the float gate weights.

Suggested review order: passes/lstm_params.py (the ahead-of-time parameter derivation plus an int8 reference, checked against a float LSTM in test/test_lstm_params.py); then ops/operators.py and ops/op_quantized_lstm.cpp (the op definition and its CMSIS kernel); then quantizer/quantizer.py (LstmBoundaryQuantizer, which annotates only the activation boundaries) and the fusion substitution in passes/aten_to_cortex_m_pass.py. Configurations outside the supported scope (multi-layer, bidirectional, projection, non-zero initial state, or models that consume h_n/c_n) are left unfused and fail lowering with a clear error rather than silently miscompiling.

Test plan

Verified with the dialect and Corstone-300 FVP tests in test/ops/test_lstm.py.

This change was authored with Claude Code.

Lower a single-layer, unidirectional nn.LSTM to a fused cortex_m::quantized_lstm
op backed by CMSIS-NN's arm_lstm_unidirectional_s8. Instead of decomposing the
LSTM into primitives, aten.lstm.input is preserved through to_edge,
boundary-quantized (int8 input/output activations, weights kept in float), and
fused in a single pass. The per-gate CMSIS parameters -- Q3.12 gate accumulator,
Q0.15 activations, and a power-of-two int16 cell state -- are derived ahead of
time from the boundary scales and the float gate weights.

Suggested review order: passes/lstm_params.py (the ahead-of-time parameter
derivation plus an int8 reference, checked against a float LSTM in
test/test_lstm_params.py); then ops/operators.py and ops/op_quantized_lstm.cpp
(the op definition and its CMSIS kernel); then quantizer/quantizer.py
(LstmBoundaryQuantizer, which annotates only the activation boundaries) and the
fusion substitution in passes/aten_to_cortex_m_pass.py. Configurations outside
the supported scope (multi-layer, bidirectional, projection, non-zero initial
state, or models that consume h_n/c_n) are left unfused and fail lowering with a
clear error rather than silently miscompiling.

Verified with the dialect and Corstone-300 FVP tests in test/ops/test_lstm.py.

This change was authored with Claude Code.
@pytorch-bot

pytorch-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

❗ 2 Merge Blocking SEVs

There is 2 active merge blocking SEVs. Please view them below:

If you must merge, use @pytorchbot merge -f.

✅ No Failures

As of commit ef6ec90 with merge base c2b273e (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 Jul 17, 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.

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.

1 participant