Skip to content

Add fuse_consecutive_squeeze_unsqueeze pass#315

Merged
take-cheeze merged 1 commit into
onnx:mainfrom
take-cheeze:claude/onnx-optimizer-pass-315-cutd99
Jul 22, 2026
Merged

Add fuse_consecutive_squeeze_unsqueeze pass#315
take-cheeze merged 1 commit into
onnx:mainfrom
take-cheeze:claude/onnx-optimizer-pass-315-cutd99

Conversation

@take-cheeze

Copy link
Copy Markdown
Member

PyTorch-to-ONNX export frequently emits a Squeeze immediately followed by an inverse Unsqueeze (or the reverse). When both operators touch exactly the same set of axes they cancel each other out, but no existing pass removed the pair -- fuse_consecutive_squeezes/fuse_consecutive_unsqueezes only handle same-op chains.

This adds a Nop pass that eliminates a Squeeze/Unsqueeze pair when their axes match, rewiring the pair's consumers to the original input. Axes are read from either the attribute (opset <= 12) or the input tensor (opset

= 13), and negative axes are normalized against the shared outer rank,
recovered from whichever value carries shape information.

Fixes onnxsim/onnxsim#315

Claude-Session: https://claude.ai/code/session_01Qp39CpZJVZ2wkXuy5Ghwyw

PyTorch-to-ONNX export frequently emits a Squeeze immediately followed by
an inverse Unsqueeze (or the reverse). When both operators touch exactly
the same set of axes they cancel each other out, but no existing pass
removed the pair -- fuse_consecutive_squeezes/fuse_consecutive_unsqueezes
only handle same-op chains.

This adds a Nop pass that eliminates a Squeeze/Unsqueeze pair when their
axes match, rewiring the pair's consumers to the original input. Axes are
read from either the attribute (opset <= 12) or the input tensor (opset
>= 13), and negative axes are normalized against the shared outer rank,
recovered from whichever value carries shape information.

Fixes onnxsim/onnxsim#315

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qp39CpZJVZ2wkXuy5Ghwyw
Signed-off-by: take-cheeze <takechi101010@gmail.com>
@take-cheeze
take-cheeze requested review from a team as code owners July 22, 2026 04:59
@take-cheeze
take-cheeze force-pushed the claude/onnx-optimizer-pass-315-cutd99 branch from 7e5b7a4 to 66e5a3f Compare July 22, 2026 05:00
@justinchuby
justinchuby requested a review from Copilot July 22, 2026 21:43

Copilot AI 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.

Pull request overview

Adds a new ONNX optimizer Nop pass to remove redundant adjacent Squeeze/Unsqueeze (and Unsqueeze/Squeeze) pairs when they operate on the same axes, improving exported-model cleanliness (notably from PyTorch-to-ONNX) and reducing unnecessary ops.

Changes:

  • Introduces fuse_consecutive_squeeze_unsqueeze pass to bypass canceling Squeeze/Unsqueeze pairs (including negative-axis normalization).
  • Registers the new pass in the global pass registry.
  • Adds unit tests covering fuse/no-fuse behavior for opset >= 13 (axes-as-input) scenarios.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
onnxoptimizer/test/optimizer_test.py Adds tests validating elimination of canceling Squeeze/Unsqueeze pairs and ensuring mismatched axes are not fused.
onnxoptimizer/passes/fuse_consecutive_squeeze_unsqueeze.h Implements the new optimization pass that detects and removes canceling adjacent Squeeze/Unsqueeze pairs.
onnxoptimizer/pass_registry.h Wires the new pass into the optimizer registry so it can be invoked by name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2887 to +2894
def test_fuse_consecutive_squeeze_unsqueeze(self): # type: () -> None
# Squeeze followed by an inverse Unsqueeze cancels out, leaving only the
# trailing consumer (Relu) fed directly by the input.
nodes = [
helper.make_node("Squeeze", ["X", "axes"], ["Y"]),
helper.make_node("Unsqueeze", ["Y", "axes"], ["Z"]),
helper.make_node("Relu", ["Z"], ["W"]),
]
Comment on lines +29 to +31
#include "onnxoptimizer/pass.h"
#include "onnxoptimizer/passes/logging.h"
#include "onnxoptimizer/passes/pass_util.h"
@take-cheeze
take-cheeze merged commit 07437f0 into onnx:main Jul 22, 2026
29 checks passed
@take-cheeze
take-cheeze deleted the claude/onnx-optimizer-pass-315-cutd99 branch July 22, 2026 22:49
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.

Consecutive squeeze unsqueeze layers could be simplified

4 participants