Skip to content

Fuse Conv with Add when the bias is the first Add input - #33819

Open
Yash Dayani (YashDayani) wants to merge 1 commit into
microsoft:mainfrom
YashDayani:fix/conv-add-fusion-reversed-inputs
Open

Yash Dayani (YashDayani) wants to merge 1 commit into
microsoft:mainfrom
YashDayani:fix/conv-add-fusion-reversed-inputs

Conversation

@YashDayani

Copy link
Copy Markdown

Description

ConvAddFusion folds a constant per-channel Add into the Conv bias, but it only looked for that constant at Add input 1. As a result, Add(bias, Conv(X, W)) was left unfused while Add(Conv(X, W), bias) was fused. Add is commutative, so both forms should fuse.

  • onnxruntime/core/optimizer/conv_add_fusion.cc: a new helper, GetAddBiasInputIndex, returns the Add input that is not the Conv output. SatisfyCondition and Apply use it instead of a hard-coded index 1.
    • SatisfyCondition already requires the Add to have exactly one input edge, and that edge comes from the Conv. So exactly one Add input is the Conv output, and the other must be a constant. Add(conv_out, conv_out) has two input edges and is still rejected.
    • The existing rank and shape checks limit the bias to [1, C, 1, 1] or [C, 1, 1], so the operand order does not change the output shape or values.
    • FinalizeNodeFusion does not depend on which Add input the Conv output uses.
  • onnxruntime/test/optimizer/graph_transform_test.cc:
    • FuseConvAddWithBiasOnEitherAddInput checks both operand orders, each with and without a Conv bias. It asserts that the Add is fused away and compares outputs against the unoptimized graph. Without this change, the two bias-first cases fail.
    • NegativeFuseConvAddWithNonConstantOtherInput checks that Add(Y, Conv(X, W)), where Y is a graph input, and Add(conv_out, conv_out) are still not fused.

Tested on macOS arm64 (Release, CPU): all ConvAdd tests pass, as do 934 tests matching GraphTransformation*:NchwcOptimizer*:QDQTransformer*:TransposeOptimizer*:*Fusion*:*Optimizer*. The changed files are formatted with the repo's pinned clang-format.

Motivation and Context

Fixes #33818. Models whose exporter emits the bias as the first Add operand kept a separate Add after every such Conv, at all optimization levels.

ConvMulFusion (conv_mul_fusion.cc) has the same limitation for Mul(scale, Conv(X, W)). I left it out of this PR to keep the change focused, and can follow up separately.

ConvAddFusion only looked for the constant bias at Add input 1, so
Add(bias, Conv(X, W)) was not fused. Add is commutative, so take the bias
from whichever Add input is not the Conv output.

Fixes microsoft#33818
Copilot AI balanced review requested due to automatic review settings November 2, 2026 17:22
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@YashDayani

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

This branch has not been deployed

No deployments
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.

[Performance] [ONNX Runtime] ConvAddFusion misses channel-bias fusion when Add inputs are reversed

2 participants