Skip to content

[AIRADSW-732] Fix reshape layout propagation - #5096

Open
ivarusic-amd wants to merge 4 commits into
developfrom
fix/reshape-layout-singleton-strides
Open

[AIRADSW-732] Fix reshape layout propagation#5096
ivarusic-amd wants to merge 4 commits into
developfrom
fix/reshape-layout-singleton-strides

Conversation

@ivarusic-amd

Copy link
Copy Markdown
Contributor

Motivation

Prevent gpu::propagate_reshape_layout from producing layouts that cause downstream reshape_lazy operations to fail with an unpacked-axis error.

Technical Details

  • Validate the proposed layout before modifying the graph.
  • Simulate shape propagation through downstream instructions.
  • Keep the original gpu::contiguous path when propagation is unsafe.
  • Add regression tests for singleton dimensions and downstream reshape

A potential follow-up is to traverse only dependent instructions to reduce compile-time overhead.This adds traversal and topological-ordering complexity, may not improve dense graphs.

Changelog Category

Add a CHANGELOG.md entry for any option other than Not Applicable

    • Added: New functionality.
    • Changed: Changes to existing functionality.
    • Removed: Functionality or support that has been removed. (Compared to a previous release)
    • Optimized: Component performance that has been optimized or improved.
    • Resolved Issues: Known issues from a previous version that have been resolved.
    • Not Applicable: This PR is not to be included in the changelog.

Follow the LLVM AI Tool Use Policy for contributions using AI.

@ivarusic-amd
ivarusic-amd requested a review from causten as a code owner July 27, 2026 12:06
@ivarusic-amd ivarusic-amd added bugfix Fixes a bug found in the code. Windows Related changes for Windows Environments UAI labels Jul 27, 2026
ivarusic-amd and others added 3 commits July 27, 2026 05:12
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

@pfultz2 pfultz2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prevents us from propagating the shape because another reshape_lazy downstream is not contiguous.

A much simpler approach is to not lower reshape -> reshape_lazy until after eliminate_contiguous. And remove the propagate_reshape_layout pass and replace it with a lower_reshape pass.

// Singleton dimensions can make a stride order ambiguous. In that case,
// find_permutation may produce a packed shape different from relayout that cannot
// alias the reshape output. Keep the standardizing contiguous instead.
auto reshaped = reshape_dims(layout_shape, rl->get_shape().sym_dims(), {.lazy = true});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you applying the reshape to the output?


auto layout_op = make_op("layout", {{"permutation", find_permutation(*relayout)}});
auto layout_shape = layout_op.compute_shape({s});
// Singleton dimensions can make a stride order ambiguous. In that case,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a singleton dimension?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think she means one dim here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

// find_permutation may produce a packed shape different from relayout that cannot
// alias the reshape output. Keep the standardizing contiguous instead.
auto reshaped = reshape_dims(layout_shape, rl->get_shape().sym_dims(), {.lazy = true});
if(not reshaped or not can_propagate_shape(m, rl, *reshaped))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it throws an error downstream, then this wont propagate the shape, which it should be.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the current fix was intentionally conservative: if propagating the new shape would invalidate a downstream operation, it retains the original contiguous path instead of failing compilation. This was preventing the regression; but i see the problem with it now

@gh-app-migraphx-bot-pr-write

Copy link
Copy Markdown
Test Batch New Rate (430088) Old Rate (49f842)* Diff Status
torchvision-resnet50 64 3,264.06 3,264.99 -0.03%
torchvision-resnet50_fp16 64 7,538.54 7,543.26 -0.06%
torchvision-densenet121 32 2,482.64 2,481.97 0.03%
torchvision-densenet121_fp16 32 5,001.31 4,973.87 0.55%
torchvision-inceptionv3 32 2,056.42 2,056.79 -0.02%
torchvision-inceptionv3_fp16 32 4,419.84 4,410.23 0.22%
cadene-inceptionv4 16 821.88 818.54 0.41%
cadene-resnext64x4 16 783.61 783.25 0.05%
slim-mobilenet 64 8,387.87 8,354.09 0.40%
slim-nasnetalarge 64 228.77 229.45 -0.30%
slim-resnet50v2 64 3,180.65 3,185.97 -0.17%
bert-mrpc-onnx 8 1,167.40 1,166.61 0.07%
bert-mrpc-tf 1 496.81 493.90 0.59%
pytorch-examples-wlang-gru 1 503.16 475.08 5.91% 🔆
pytorch-examples-wlang-lstm 1 379.00 379.26 -0.07%
torchvision-resnet50_1 1 1,042.29 1,034.33 0.77%
cadene-dpn92_1 1 454.17 443.17 2.48%
cadene-resnext101_1 1 364.96 365.51 -0.15%
onnx-taau-downsample 1 844.12 849.29 -0.61%
dlrm-criteoterabyte 1 32.42 32.43 -0.03%
dlrm-criteoterabyte_fp16 1 51.80 52.12 -0.62%
agentmodel 1 9,213.02 9,423.56 -2.23%
unet_fp16 2 58.81 58.72 0.16%
resnet50v1_fp16 1 1,395.13 1,365.56 2.17%
resnet50v1_int8 1 1,720.69 1,661.41 3.57%
bert_base_cased_fp16 64 1,097.84 1,098.85 -0.09%
bert_large_uncased_fp16 32 345.56 345.36 0.06%
bert_large_fp16 1 205.54 205.27 0.13%
distilgpt2_fp16 16 2,090.72 2,095.46 -0.23%
yolov5s 1 557.45 559.47 -0.36%
tinyllama 1 45.83 45.76 0.15%
vicuna-fastchat 1 44.13 43.96 0.38%
whisper-tiny-encoder 1 411.75 412.60 -0.21%
whisper-tiny-decoder 1 408.33 410.66 -0.57%
llama2_7b 1 20.83 20.82 0.02%
qwen1.5-7b 1 23.58 23.50 0.34%
phi3-3.8b 1 26.77 26.68 0.35%
llama3-8b 1 21.76 21.73 0.13%
whisper-large-encoder 1 10.18 10.14 0.32%
whisper-large-decoder 1 107.52 107.31 0.20%
mistral-7b 1 23.75 23.75 0.00%
FLUX.1-schnell 1 767.50 804.98 -4.66%

Check flagged results 🔆

* No develop baseline was found for this PR's branch point; compared against the latest available develop run instead.

@gh-app-migraphx-bot-pr-write

Copy link
Copy Markdown
Test Status Result
bert-mrpc-onnx PASSED: MIGraphX meets tolerance
bert-mrpc-tf PASSED: MIGraphX meets tolerance
pytorch-examples-wlang-gru PASSED: MIGraphX meets tolerance
pytorch-examples-wlang-lstm PASSED: MIGraphX meets tolerance
dlrm-criteoterabyte PASSED: MIGraphX meets tolerance
agentmodel PASSED: MIGraphX meets tolerance
unet PASSED: MIGraphX meets tolerance
resnet50v1 PASSED: MIGraphX meets tolerance
bert_base_cased_fp16 PASSED: MIGraphX meets tolerance
bert_large_uncased_fp16 🔴 FAILED: MIGraphX is not within tolerance - check verbose output
bert_large PASSED: MIGraphX meets tolerance
yolov5s PASSED: MIGraphX meets tolerance
tinyllama PASSED: MIGraphX meets tolerance
vicuna-fastchat PASSED: MIGraphX meets tolerance
whisper-tiny-encoder PASSED: MIGraphX meets tolerance
whisper-tiny-decoder PASSED: MIGraphX meets tolerance
llama2_7b PASSED: MIGraphX meets tolerance
qwen1.5-7b PASSED: MIGraphX meets tolerance
phi3-3.8b PASSED: MIGraphX meets tolerance
llama3-8b PASSED: MIGraphX meets tolerance
whisper-large-encoder PASSED: MIGraphX meets tolerance
whisper-large-decoder PASSED: MIGraphX meets tolerance
mistral-7b PASSED: MIGraphX meets tolerance
FLUX.1-schnell PASSED: MIGraphX meets tolerance

@TedThemistokleous TedThemistokleous left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few comments. Feel free to reach out

shapes.emplace(&ins,
ins.get_operator().compute_shape(input_shapes, ins.module_inputs()));
}
catch(const exception&)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So catching any exception here? We should look for a specific exception instead of doing a catch all

@ivarusic-amd ivarusic-amd Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no specific exception type for the different compute_shape failures; that's the reason why. Agree

std::back_inserter(input_shapes),
[&](instruction_ref input) {
auto iter = shapes.find(&*input);
return iter == shapes.end() ? input->get_shape() : iter->second;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rewrite this to remove the find? We're doing a search and if that fails you're still searching O(n) here. The de reference and reference looks really odd here too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, i though average would be O(1).. I will change it

@ivarusic-amd

ivarusic-amd commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

This prevents us from propagating the shape because another reshape_lazy downstream is not contiguous.

A much simpler approach is to not lower reshape -> reshape_lazy until after eliminate_contiguous. And remove the propagate_reshape_layout pass and replace it with a lower_reshape pass.

Hi @pfultz2 , I tried your approach locally by leaving reshape generic through eliminate_contiguous, then lowering it in a new lower_reshape pass.
The pass uses direct reshape_lazy when valid, otherwise a layout copy, with a standard contiguous copy as fallback. This removes propagate_reshape_layout and downstream shape simulation.
Is this what you had in mind? It did work for this specific model we had problem with/ but need some additional testing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fixes a bug found in the code. UAI Windows Related changes for Windows Environments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants