Skip to content

Honor Reshape allowzero in symbolic_shape_infer#28470

Open
1fanwang wants to merge 1 commit into
microsoft:mainfrom
1fanwang:fix/symbolic-shape-infer-reshape-allowzero
Open

Honor Reshape allowzero in symbolic_shape_infer#28470
1fanwang wants to merge 1 commit into
microsoft:mainfrom
1fanwang:fix/symbolic-shape-infer-reshape-allowzero

Conversation

@1fanwang
Copy link
Copy Markdown

symbolic_shape_infer.py::_infer_Reshape reads the shape input but ignores the allowzero attribute introduced in opset 14. Under default allowzero=0, a zero in shape means "copy the corresponding input dim", so reshape([0, 8, 2] → [0, 0, 4]) correctly resolves to [0, 8, 4] for a non-empty input but should stay [0, 0, 4] for a zero-size input. Under allowzero=1, zeros are literal regardless of input shape.

Today the inferrer treats zero in shape as copy-from-input unconditionally. So a shape produced by reshape(allowzero=1, shape=[0, 0, 4]) is reported as [N, 8, 4] instead of [0, 0, 4], propagating wrong dims through every downstream op the tool inspects. The shape is consumed by quantization preprocessing, optimum, and several converters — they all see wrong tensor shapes silently.

The fix reads the allowzero attribute and short-circuits the copy-from-input substitution when it's 1. The -1 deferred-dim path is updated to handle the edge case where allowzero=1 makes the divisor zero (the reference C++ runtime errors in this case; the inferrer should too rather than silently divide-by-zero).

The C++ optimizer side of the same gap is being addressed by Copilot bot's #28455; this PR is the symbolic-inference side.

Tests

Four new cases in TestSymbolicShapeInferenceForOperators:

  • allowzero=1 literal zeros preserved (the issue's reproducer shape)
  • allowzero=1 with -1 deferred-dim erroring instead of silently dividing by zero
  • allowzero=0 legacy path unchanged (copy-from-input still works)
  • allowzero=0 with a -1 and a 0 in the shape (combined case)

Related: #28449 / #28455 cover the C++ optimizer surface of the same allowzero gap; this PR is the Python tool's surface.

The Python symbolic_shape_infer tool was treating every 0 in a Reshape
shape input as "copy the corresponding input dim", which is only valid
when allowzero=0. With allowzero=1 (opset 14+), a 0 in the shape tensor
means a literal zero dim — used for legitimately zero-element tensors
in dynamic-shape models exported from frameworks like PyTorch.

Read the allowzero attribute and skip the copy-from-input path when it
is set, so the explicit zero is preserved. Also guard the deferred-dim
(-1) computation against a non_deferred_size of 0, which can happen
when a literal 0 is combined with -1 (invalid per spec, but should not
crash inference).

Without this fix, e.g. Reshape(input=[4,2,0], shape=[0,0,4], allowzero=1)
infers as [4,2,4] instead of [0,0,4], which then mis-shapes every
downstream op when the model is processed by quantization, optimum,
or any tool that consumes symbolic_shape_infer output.
@1fanwang
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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.

1 participant