Skip to content

fix(compiler): keep stored sizes when a shape rule is incomplete - #1336

Merged
asparkhi merged 2 commits into
mainfrom
gpuep/stored-shape-merge
Oct 27, 2026
Merged

asparkhi merged 2 commits into
mainfrom
gpuep/stored-shape-merge

Conversation

@amd-mounikk

Copy link
Copy Markdown
Contributor

Summary

  • Merge a shape rule with the type already stored on the result: keep a known size, and fill ? only when the rule has a number. An unranked tensor<*xT> still takes the rule type.
  • Read Slice, Pad, Unsqueeze, reduction, and Split bounds from a constant input when the attribute is absent. A runtime tensor returns no type, so the stored shape stays.
  • Rank AveragePool (1x64x512x512, kernel 2, stride 2 becomes 1x64x256x256) and opset 7-8 Upsample from its scales attribute. An equal Split of a static axis writes the chunk size into extract_slice when that axis is still ?.

Related issue or design

Follow-up to the Gemma-4 shape regression reported on #1306. None filed separately.

Why

#1306 runs the shape rules on any ranked result that still contains a ?, then replaces the stored type. Slice and Pad, when starts/ends/pads are inputs rather than attributes, answered with a same-rank all-? type, so a stored size such as tensor<1x?x12x32xf16> became tensor<?x?x?x?xf16>. The Topaz UNet also left AveragePool and attribute-form Upsample unranked, so conversion never saw a rank.

What

  • mergeInferredType in forwardInferUnrankedResults combines the stored type with the rule result.
  • AveragePool uses the ONNX spatial formula. Upsample reads the scales attribute when there is no scales input.
  • Slice, Pad, Unsqueeze, reductions, and Split accept a constant input vector and return no type for a runtime vector.
  • SplitToStdTensor puts a constant chunk size on the extract_slice result and casts back to the declared type.

Test plan

  • pre-commit run --files on the four changed files (passed after lintrunner formatting)
  • hip-mlir-opt --hip-infer-loop-body-shapes test/lit/Dialect/hip-infer-loop-body-shapes.mlir | FileCheck
  • hip-mlir-opt test/lit/Conversion/onnx-to-hip/test_split.mlir --hip-add-context-arg --convert-onnx-to-hip | FileCheck
  • Gemma-4 and the Topaz UNet on a full session

Notes for reviewers

Drafted with Cursor assistance. I reviewed the merge rule, the constant-input fallback, and the lit checks.

The Gemma Slice case is locked as tensor<1x?x12x32xf16> when starts, ends, and axes are runtime tensors. The pool and attribute Upsample cases are in hip-infer-loop-body-shapes.mlir.

Checklist

  • The change is focused, or links a design/series explaining its scope.
  • Relevant tests were added or updated and the results are documented.
  • User-facing or design documentation was updated when needed.
  • Substantial AI assistance is disclosed, and I reviewed and understand the result.

A rule that only knows the rank was replacing a stored dimension with ?.
Merge each rule with the stored type, read constant bound inputs, and
rank AveragePool and attribute-form Upsample.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 13:45
@github-actions

Copy link
Copy Markdown

Thanks for opening a PR!

This project follows LLVM's incremental-development and AI-tool-use
guidance. See CONTRIBUTING.md
for the project workflow.

Before requesting review, please check that:

  1. The change is focused. Substantial work links the relevant issue
    or design discussion.
  2. The PR documents relevant test results and updates affected
    documentation.
  3. If AI tools provided substantial assistance, the description
    explains what was assisted and how it was validated, and commit
    trailers identify the tool. The contributor has reviewed and
    understands the result.

Reviewers are assigned through
CODEOWNERS where ownership
is configured.

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.

🟡 Changes recommended

Empty reduction axes, ceil-mode pooling boundaries, and integer-bound decoding can produce incorrect shapes or undefined behavior.

3 open issues
What changed in this PR

This PR follows up on #1306 by preserving known result dimensions during incomplete ONNX shape inference and expanding inference for additional operator forms.

Changes:

  • Merge inferred shapes with stored types without replacing known dimensions.
  • Read constant shape inputs and infer AveragePool and attribute-form Upsample shapes.
  • Refine static equal-Split slice sizes and add targeted regression tests.
File Description
test/​lit/​Dialect/​hip-infer-loop-body-shapes.mlir Adds pooling, Upsample, and Slice shape-inference regressions.
test/​lit/​Conversion/​onnx-to-hip/​test_split.mlir Tests constant slice sizes for dynamically typed Split results.
lib/​Dialect/​Transforms/​InferLoopBodyShapesPass.cpp Preserves stored dimensions and extends operator shape rules.
lib/​Conversion/​OnnxToHip/​ReshapeConversion.cpp Refines Split slice types and casts back to declared types.

Review effort: Balanced

Comment thread lib/Dialect/Transforms/InferLoopBodyShapesPass.cpp
Comment thread lib/Dialect/Transforms/InferLoopBodyShapesPass.cpp
Comment thread lib/Dialect/Transforms/InferLoopBodyShapesPass.cpp
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

L2 Accuracy Results (EP vs CPU)

Model Combined L2 Total Elems Skipped NaN/Inf
conv_test_hybrid 1.12256E-07 64 0
GroupQueryAttention_seq256 59.2561 2621440 0
MatMulNBits_o_seq128 259.905 368640 0
QMoE_seq128 24.2583 368640 0

Threshold: 0.01 | Run: 7942 - Commit: afa8642

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Binary sizes

Baseline: run 40440689818 - 7f2f3ce (dll-sizes)

File This (MB) Main (MB) Delta (MB)
hipgpu.dll 59.32 59.31 +0.01
custom_kernels_gfx1170.dll 5.55 5.55 0.00
custom_kernels_gfx11-generic.dll 5.79 5.79 0.00

MorphiZen EP Performance Results

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 8.77 7.45 246 3 1158
GroupQueryAttention_seq128 11345.00 2.55156 1 5 229
matmul_down_seq128 508.90 3.28 116 3 274

EPContext Export Performance

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 8.82 48.31 251 3 15505

EPContext Import Performance

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 8.83 9.97 255 3 15639

OGA Benchmark Results

Model Warmup Reps Prompt Len Gen Tokens TTFT (ms) TPS Peak Mem (GB) GPU Mem (GB)
gpt-oss-20b-webgpu-int4-rtn-block-32 1 5 128 128 91.7 74.7 1.25 12.24
Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 1 5 128 128 118.6 47.7 1.15 5.23

OGA Wheel Smoke (Python benchmark_e2e.py)

Model TTFT (ms) TPS
Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 117 48.0

VLM Benchmark Results

Model TTFT (ms) TPS Output
gemma-4-E4B-it-fp16-int4-kquant-prune-logits 4005.3 7.7 This is a high-quality, outdoor photograph featuring a beautiful, fluffy white dog, likely a West Highland White Terrier or a si
Qwen3.8-27B-fp16-ve-fp16-int4-k_quant-gs128-text-dml-onnx 4922.1 14.0 The user wants a detailed description of the image. Let me carefully observe all elements before writing. Subject: A white do

TTFT / TPS vs main

Baseline: run 40440689818 - 7f2f3ce | Gate: TTFT +20% / TPS -20%

Suite Model TTFT (ms) Main Delta TPS Main Delta
oga gpt-oss-20b-webgpu-int4-rtn-block-32 91.7 90.4 +1.5% 74.7 74.9 -0.2%
oga Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 118.6 116.7 +1.6% 47.7 47.8 -0.3%
vlm gemma-4-E4B-it-fp16-int4-kquant-prune-logits 4005.3 4009.7 -0.1% 7.7 7.2 +7.1%
vlm Qwen3.8-27B-fp16-ve-fp16-int4-k_quant-gs128-text-dml-onnx 4922.1 14742.4 -66.6% 14.0 14.0 -0.1%

Run: 7942 - Commit: afa8642

A constant Slice can refine a loop input after the body was seeded.
Copy that type onto the hip.loop result and reconcile the body again,
so the verifier still sees identical v_init and result types.

Co-authored-by: Cursor <cursoragent@cursor.com>
@asparkhi
asparkhi merged commit 3c569ca into main Oct 27, 2026
11 checks passed
@asparkhi
asparkhi deleted the gpuep/stored-shape-merge branch October 27, 2026 12:46
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.

3 participants