Skip to content

Add fuse_consecutive_mul pass - #5

Open
take-cheeze wants to merge 1 commit into
claude/initializers-non-constants-option-fun941from
claude/onnx-optimizer-passes-tx9y3n-fuse-mul
Open

Add fuse_consecutive_mul pass#5
take-cheeze wants to merge 1 commit into
claude/initializers-non-constants-option-fun941from
claude/onnx-optimizer-passes-tx9y3n-fuse-mul

Conversation

@take-cheeze

Copy link
Copy Markdown
Member

Implements the fuse_consecutive_mul pass from the docs/proposed_passes design draft. Split out of #4 so each pass is reviewed on its own.

Base branch: like #4, this is stacked on claude/initializers-non-constants-option-fun941 so its diff shows only the new pass. Retarget to main once that branch merges.

What it does

Folds Mul(Mul(X, C1), C2) -> Mul(X, C1 * C2) when C1/C2 are constants (initializers or Constant nodes) and the inner Mul feeds only the outer one. The combined scale is materialised with numpy-style broadcasting, so the rewrite is numerically identical (X * C1 * C2 at every position). Covers e.g. PoolFormer's LayerScale, exported as a per-channel (C,1,1) scale times a scalar factor. Conservatively limited to FLOAT/DOUBLE constants; other dtypes are left to constant folding.

Registered as a default Fuse pass, so it runs in the default fuse set.

Tests

Adds unit tests — scalar and per-channel fuse cases, plus no-fuse guards (inner Mul with multiple uses, non-constant operand) — with onnxruntime numeric-equivalence checks.


Generated by Claude Code

Folds Mul(Mul(X, C1), C2) -> Mul(X, C1 * C2) when C1/C2 are constants
(initializers or Constant nodes) and the inner Mul feeds only the outer
one. The combined scale is materialised with numpy-style broadcasting, so
the rewrite is numerically identical (X * C1 * C2 at every position).
Covers e.g. PoolFormer's LayerScale, a per-channel (C,1,1) scale times a
scalar factor. Conservatively limited to FLOAT/DOUBLE constants; other
dtypes are left to constant folding.

Registered as a default Fuse pass. Adds unit tests for the fuse cases
(scalar, per-channel) and the no-fuse guards (inner multiple-use,
non-constant operand) with onnxruntime numeric-equivalence checks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V63N6PXYEgNEe1BWbKi6cU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants