Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fold DyT alpha scalar into tanh LUT (#21952) - #21952

Merged
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649
Aug 24, 2026
Merged

Fold DyT alpha scalar into tanh LUT (#21952)#21952
huydhn merged 1 commit into
pytorch:mainfrom
cgreenberg:export-D116560649

Conversation

@cgreenberg

@cgreenbergcgreenberg commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary:

Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.

The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.

Reviewed By: rascani

Differential Revision: D116560649

@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ No Failures

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

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

@meta-clameta-claBot 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 19, 2026
@meta-codesync

Copy link
Copy Markdown
Contributor

@cgreenberg has exported this pull request. If you are a Meta employee, you can view the originating Diff in D116560649.

@linux-foundation-easycla

linux-foundation-easyclaBot commented Aug 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: cgreenberg / name: Charles Greenberg (0cec5b5)

@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 19, 2026
@github-actionsgithub-actionsBot added ciflow/trunk module: arm Issues related to arm backend labels Aug 19, 2026
@pytorch-bot

pytorch-botBot commented Aug 19, 2026

Copy link
Copy Markdown

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

Comment threadbackends/arm/_passes/fold_dyt_alpha_into_lut_pass.py Outdated
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUT (#21952)Fold DyT alpha scalar into tanh LUTAug 20, 2026
@zingozingo added the partner: arm For backend delegation, kernels, demo, etc. from the 3rd-party partner, Arm label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@pytorchbot label "release notes: arm"

@pytorch-botpytorch-botBot added the release notes: arm Changes to the ARM backend delegate label Aug 20, 2026
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

/easycla

@digantdesai

Copy link
Copy Markdown
Contributor

@claude review this PR.

@claude

claudeBot commented Aug 20, 2026

Copy link
Copy Markdown

Claude finished @digantdesai's task in 12m 7s —— View job


Code Review: Fold DyT alpha scalar into tanh LUT

  • Read changed files
  • Analyze the pass implementation
  • Analyze pass manager hook
  • Analyze tests
  • Post review

Reviewed all four changed files plus the surrounding machinery (op_tosa_rescale._compute_multiplier_and_shift, insert_table_ops, real_impl, arm_pass). This is a carefully-built pass with unusually strong test coverage. Overall it looks correct and well-guarded — the concerns below are minor.


Correctness — looks solid

  • SINGLE_ROUND replay is faithful._apply_tosa_rescale (fold_dyt_alpha_into_lut_pass.py:57) mirrors the serialized RESCALE path: same _compute_multiplier_and_shift, rounding = 1 << (shift-1), (centered*multiplier + rounding) >> shift, then clamp to output dtype. The comment at :65 correctly notes _compute_multiplier_and_shift asserts shift ∈ [2, 62], so shift-1 is never negative. Nice that you resisted "guarding" it.
  • The bit-exactness is genuinely verified, not asserted.test_tosa_output_is_bit_exact_after_fold compares the generated TABLE against the actual tosa_reference_model output (_tosa_reference_outputs) over every int8 code. That's the right way to pin the int32 MUL-wrap and rescale rounding, and it removes any doubt about the hand-replayed arithmetic matching the device.
  • Fails-closed guards are comprehensive: non-scalar alpha (:88, :236-238), activation-side rank views (:243), int32/int8 dtype checks, and output_rescale.output_zp != tanh_input_qargs zp (:267). test_pass_rejects_activation_side_rank_view and the DyTModule docstring on the conv-producer requirement show the edges were thought through.
  • TABLE wiring is consistent: input is the original int8 match.activation, input_qparams = activation_qargs, output_qparams = tanh_output_qargs — the LUT collapses rescale→mul→rescale→tanh into one int8→int8 map. Correct.

Minor concerns / questions

  1. Dangling alpha buffer after the fold.call() erases the tanh and relies on eliminate_dead_code() (:323) to drop the mul and rescales — but eliminate_dead_code does not remove placeholder/buffer nodes. Once the alpha Mul is gone, the alpha buffer placeholder has no users. Does a later pipeline pass (FuseEqualPlaceholdersPass, constant-folding) actually strip it, or does the exported program keep an orphaned buffer in its state_dict + graph signature? It's functionally harmless and tiny, but the PR summary says the pass "deletes the Mul and its surrounding rescales," and the alpha constant silently surviving is worth confirming. None of the tests assert the buffer is removed. Fix this →

  2. TABLE node meta["val"] is copied from the tanh, not recomputed. Unlike InsertTableOpsPass, which retraces via super().call() to refresh fake-tensor types, this pass inserts the TABLE via create_node(from_node=match.tanh, ...) and does not retrace. That copies the tanh's val. In a fully quantized graph the tanh output should already be int8, so shape/dtype line up — but it's worth a sanity check that no downstream pass expects a val produced by the TABLE fake kernel specifically (it validates table shape/dtype). If the copied val dtype ever isn't int8, serialization could be surprised.

  3. _source_qargs scale match uses math.isclose(rel_tol=1e-6) (:180) to pick the activation qargs among candidates. Fine in practice, but if two producers ever carry near-identical scales it silently selects the first. Given how much else in this pass "fails closed," consider whether an ambiguous match (>1 candidate within tolerance) should also bail rather than take the first.

Nits

  • JakeStevens' copyright comment appears addressed — the file carries Copyright (c) Meta Platforms, Inc. and affiliates. Note the rest of backends/arm/_passes/ also carries an Arm Limited line (e.g. arm_pass_manager.py, arm_pass.py); confirm with the Arm reviewers whether the dual header is expected here, since this lands in their backend.
  • The circular-import workaround (module-scope vs. in-function import of register_pass_factories_before, :331-336) is well-documented in both the code and PR body. Good.

CI

The 2 reported failures (hifi-build, vision-build) are pull_request_target fork-checkout refusals — infrastructure/security, unrelated to this change.


Nice work — the exhaustive parity test against the reference model is exactly the right safety net for a byte-exact rewrite like this. My only substantive ask is confirming the alpha buffer doesn't linger (#1).
· branch export-D116560649

@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 2 times, most recently from 2c45117 to 0afdc7fCompareAugust 20, 2026 23:46
@meta-codesyncmeta-codesyncBot changed the title Fold DyT alpha scalar into tanh LUTFold DyT alpha scalar into tanh LUT (#21952)Aug 21, 2026
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@rascani
rascani requested review from rascani and zingoAugust 21, 2026 17:09
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Differential Revision: D116560649
@cgreenberg

Copy link
Copy Markdown
ContributorAuthor

@claude review this PR

@rascanirascani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 21, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@cgreenberg
cgreenbergforce-pushed the export-D116560649 branch 3 times, most recently from 654c3cd to e45f3afCompareAugust 22, 2026 03:23
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 22, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
cgreenberg added a commit to cgreenberg/executorch that referenced this pull request Aug 24, 2026
Summary:
Dynamic Tanh (DyT) normalization computes tanh(alpha * x) with a learned scalar alpha. Quantized, that lowers to a full-tensor integer Mul followed by a tanh TABLE. This adds FoldDyTAlphaIntoLUTPass, which replays the exact TOSA SINGLE_ROUND integer arithmetic over all 256 int8 codes and folds the alpha Mul into the TABLE without approximation.
The matcher fails closed for unsupported shapes, ranges, layouts, or quantization metadata. This revision contains only the public pass implementation, tests, and package exports; pass registration is intentionally outside this public change.
Reviewed By: rascani
Differential Revision: D116560649
@huydhn
huydhn merged commit 368a849 into pytorch:mainAug 24, 2026
507 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/trunkCLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.meta-exportedmodule: armIssues related to arm backendpartner: armFor backend delegation, kernels, demo, etc. from the 3rd-party partner, Armrelease notes: armChanges to the ARM backend delegate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@cgreenberg@digantdesai@rascani@JakeStevens@zingo@huydhn