Repository navigation
fix(compiler): keep stored sizes when a shape rule is incomplete - #1336
Conversation
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>
|
Thanks for opening a PR! This project follows LLVM's incremental-development and AI-tool-use Before requesting review, please check that:
Reviewers are assigned through |
There was a problem hiding this comment.
🟡 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
L2 Accuracy Results (EP vs CPU)
Threshold: 0.01 | Run: 7942 - Commit: |
Binary sizesBaseline: run 40440689818 -
MorphiZen EP Performance Results
EPContext Export Performance
EPContext Import Performance
OGA Benchmark Results
OGA Wheel Smoke (Python benchmark_e2e.py)
VLM Benchmark Results
TTFT / TPS vs mainBaseline: run 40440689818 -
Run: 7942 - Commit: |
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>

Summary
?only when the rule has a number. An unrankedtensor<*xT>still takes the rule type.1x64x512x512, kernel 2, stride 2 becomes1x64x256x256) and opset 7-8 Upsample from itsscalesattribute. An equal Split of a static axis writes the chunk size intoextract_slicewhen that axis is still?.Related issue or design
Follow-up to the Gemma-4 shape regression reported on #1306. None filed separately.
Why
#1306runs 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 astensor<1x?x12x32xf16>becametensor<?x?x?x?xf16>. The Topaz UNet also leftAveragePooland attribute-formUpsampleunranked, so conversion never saw a rank.What
mergeInferredTypeinforwardInferUnrankedResultscombines the stored type with the rule result.scalesattribute when there is no scales input.SplitToStdTensorputs a constant chunk size on theextract_sliceresult and casts back to the declared type.Test plan
pre-commit run --fileson 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 | FileCheckhip-mlir-opt test/lit/Conversion/onnx-to-hip/test_split.mlir --hip-add-context-arg --convert-onnx-to-hip | FileCheckNotes 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 inhip-infer-loop-body-shapes.mlir.Checklist