Skip to content

Symbolic attr support for slice#5043

Open
shivadbhavsar wants to merge 10 commits into
developfrom
sym_slice
Open

Symbolic attr support for slice#5043
shivadbhavsar wants to merge 10 commits into
developfrom
sym_slice

Conversation

@shivadbhavsar

Copy link
Copy Markdown
Contributor

Motivation

For input-size based dynamic slicing, we can represent the slice size using a symbolic expression

Technical Details

Use the newly added dim-like variant to support symbolic starts and ends for slice

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.

@shivadbhavsar
shivadbhavsar requested a review from CharlieL7 July 7, 2026 18:59
@shivadbhavsar shivadbhavsar self-assigned this Jul 7, 2026
@shivadbhavsar
shivadbhavsar requested a review from causten as a code owner July 7, 2026 18:59
Copilot AI review requested due to automatic review settings July 7, 2026 18:59

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.

Pull request overview

This PR adds support for representing slice attribute bounds (starts/ends) as symbolic expressions by introducing a dim_like variant type, enabling shape inference for input-size–dependent dynamic slicing.

Changes:

  • Update op::slice to store starts/ends as std::vector<dim_like> and add a unified symbolic compute_shape path.
  • Teach ONNX parsing and attribute normalization to preserve symbolic (object-serialized) bounds while still clamping purely-concrete bounds.
  • Extend shape tests to cover non-fixed symbolic axes and symbolic start/end bounds.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
test/op_shape_test.cpp Adds shape-inference coverage for symbolic slice bounds, clamping, and negative indices.
src/simplify_reshapes.cpp Updates reshape/slice simplifications to extract concrete bounds from dim_like.
src/simplify_dyn_ops.cpp Updates dynamic-op simplifications to convert slice bounds from dim_like to int64_t where required.
src/simplify_algebra.cpp Updates algebraic rewrites that inspect slice ranges to handle dim_like bounds.
src/onnx/parse_slice.cpp Updates Slice parser to populate dim_like starts/ends (including attribute forms).
src/normalize_attributes.cpp Skips compile-time clamping for symbolic (object-encoded) bounds during attribute normalization.
src/include/migraphx/op/slice.hpp Implements symbolic shape computation for slice and migrates bounds storage to dim_like.
src/include/migraphx/dim_like.hpp Adds dim_like utilities, including to_ints() for extracting concrete bounds.

Comment on lines +292 to +300
if(input_shape.dynamic() and not input_shape.symbolic())
{
MIGRAPHX_THROW("SLICE 1_arg: slicing is not allowed on non-fixed dynamic input axis ");
}

auto new_lens = lens_calc(input_shape.max_lens(), this->starts, this->ends, this->axes);

if(not input_shape.dynamic())
return shape{input_shape.type(), new_lens, input_shape.strides()};
if(std::any_of(axes.begin(), axes.end(), [&](auto axis) {
return not input_shape.dyn_dims()[axis].is_fixed();
}))
MIGRAPHX_THROW("SLICE 1_arg: slicing is not allowed on a non-fixed input axis ");

auto dds = input_shape.dyn_dims();
for(auto axis : this->axes)
{
dds[axis] = input_shape.symbolic()
? shape::dynamic_dimension{sym::lit(new_lens[axis])}
: shape::dynamic_dimension{new_lens[axis], new_lens[axis]};
auto new_lens = lens_calc(input_shape.max_lens(), to_ints(starts), to_ints(ends), axes);
auto dds = input_shape.dyn_dims();
Comment thread src/simplify_dyn_ops.cpp
Comment thread src/simplify_reshapes.cpp
Comment thread src/simplify_reshapes.cpp
Comment thread src/simplify_algebra.cpp
Comment thread src/onnx/parse_slice.cpp
Comment thread src/onnx/parse_slice.cpp
Comment thread src/simplify_reshapes.cpp
Comment thread src/simplify_algebra.cpp
@gh-app-migraphx-bot-pr-write

gh-app-migraphx-bot-pr-write Bot commented Jul 7, 2026

Copy link
Copy Markdown
Test Batch New Rate (13dc8f) Old Rate (1a5bb6)* Diff Status
torchvision-resnet50 64 1,625.07 3,265.81 -50.24% 🔴
torchvision-resnet50_fp16 64 2,800.78 7,548.56 -62.90% 🔴
torchvision-densenet121 32 934.39 2,481.85 -62.35% 🔴
torchvision-densenet121_fp16 32 4,650.41 4,975.40 -6.53% 🔴
torchvision-inceptionv3 32 2,026.18 2,060.05 -1.64%
torchvision-inceptionv3_fp16 32 4,420.73 4,414.40 0.14%
cadene-inceptionv4 16 387.69 584.00 -33.62% 🔴
cadene-resnext64x4 16 320.82 782.84 -59.02% 🔴
slim-mobilenet 64 4,337.25 7,190.62 -39.68% 🔴
slim-nasnetalarge 64 140.90 222.84 -36.77% 🔴
slim-resnet50v2 64 2,089.40 2,017.65 3.56%
bert-mrpc-onnx 8 1,168.50 1,168.85 -0.03%
bert-mrpc-tf 1 434.23 487.56 -10.94% 🔴
pytorch-examples-wlang-gru 1 236.40 477.33 -50.47% 🔴
pytorch-examples-wlang-lstm 1 452.60 387.83 16.70% 🔆
torchvision-resnet50_1 1 407.79 1,038.23 -60.72% 🔴
cadene-dpn92_1 1 443.62 449.51 -1.31%
cadene-resnext101_1 1 365.71 365.36 0.10%
onnx-taau-downsample 1 772.36 844.73 -8.57% 🔴
dlrm-criteoterabyte 1 0.99 17.44 -94.32% 🔴
dlrm-criteoterabyte_fp16 1 51.16 31.21 63.95% 🔆
agentmodel 1 8,480.25 5,880.42 44.21% 🔆
unet_fp16 2 56.28 52.15 7.93% 🔆
resnet50v1_fp16 1 300.06 1,385.99 -78.35% 🔴
resnet50v1_int8 1 1,646.21 1,657.40 -0.68%
bert_base_cased_fp16 64 1,098.19 1,022.83 7.37% 🔆
bert_large_uncased_fp16 32 345.74 339.30 1.90%
bert_large_fp16 1 79.72 205.64 -61.24% 🔴
distilgpt2_fp16 16 2,091.79 2,086.12 0.27%
yolov5s 1 558.24 560.85 -0.47%
tinyllama 1 45.81 45.80 0.01%
vicuna-fastchat 1 43.82 44.03 -0.46%
whisper-tiny-encoder 1 412.34 328.75 25.43% 🔆
whisper-tiny-decoder 1 326.30 214.20 52.33% 🔆
llama2_7b 1 20.83 14.70 41.72% 🔆
qwen1.5-7b 1 23.58 23.49 0.42%
phi3-3.8b 1 26.83 26.78 0.20%
llama3-8b 1 21.68 21.70 -0.09%
whisper-large-encoder 1 10.18 8.77 16.06% 🔆
whisper-large-decoder 1 107.50 109.89 -2.17%
mistral-7b 1 23.72 23.65 0.27%
FLUX.1-schnell 1 789.47 172.94 356.51% 🔆

Regressions detected 🔴

* 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

gh-app-migraphx-bot-pr-write Bot commented Jul 7, 2026

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
distilgpt2_fp16 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

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.18405% with 16 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/normalize_attributes.cpp 85.71% 7 Missing ⚠️
src/include/migraphx/op/slice.hpp 91.67% 3 Missing ⚠️
src/include/migraphx/dim_like.hpp 84.62% 2 Missing ⚠️
src/onnx/parse_slice.cpp 87.50% 2 Missing ⚠️
src/simplify_algebra.cpp 90.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #5043      +/-   ##
===========================================
- Coverage    92.90%   92.88%   -0.02%     
===========================================
  Files          603      603              
  Lines        32526    32624      +98     
===========================================
+ Hits         30217    30301      +84     
- Misses        2309     2323      +14     
Files with missing lines Coverage Δ
src/simplify_dyn_ops.cpp 99.38% <100.00%> (+0.02%) ⬆️
src/simplify_reshapes.cpp 97.98% <100.00%> (-0.17%) ⬇️
src/include/migraphx/dim_like.hpp 87.50% <84.62%> (-12.50%) ⬇️
src/onnx/parse_slice.cpp 96.10% <87.50%> (-2.40%) ⬇️
src/simplify_algebra.cpp 97.47% <90.00%> (-0.06%) ⬇️
src/include/migraphx/op/slice.hpp 95.72% <91.67%> (+0.07%) ⬆️
src/normalize_attributes.cpp 93.06% <85.71%> (-3.79%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread test/op_shape_test.cpp
Comment on lines +5332 to +5343
TEST_CASE(slice_sym_non_fixed_axis)
{
// Slicing on a non-fixed symbolic axis is rejected (same contract as range).
auto n = var("n", {1, 8});
migraphx::shape sin{migraphx::shape::float_type, {dd{lit(4)}, dd{n}, dd{lit(8)}}};
throws_shape(migraphx::make_op("slice", {{"axes", {1}}, {"starts", {0}}, {"ends", {2}}}), sin);
// Slicing a non-fixed symbolic axis is allowed: the bounds are trusted to be valid at
// runtime, so the extent is just ends - starts (no clamping). The other symbol is kept.
auto n = var("n", {1, 8});
auto m = var("m", {1, 8});
std::unordered_map<se, std::size_t> sym_map = {{n, 5}, {m, 3}};
migraphx::shape sin{migraphx::shape::float_type, {dd{n}, dd{m}}};
auto op = migraphx::make_op("slice", {{"axes", {0}}, {"starts", {0}}, {"ends", {2}}});
migraphx::shape sout{migraphx::shape::float_type, {dd{lit(2)}, dd{m}}, sin.dyn_strides()};
expect_shape(sout, op, sin);
EXPECT(sout.to_static(sym_map) == op.compute_shape({sin.to_static(sym_map)}));

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 doesn't look correct. If the starts and ends are not normalized, we can't use the ends - starts. If both starts and ends are positive, we can compute a bound. But if the starts is negative it gets a lot more uncertain.

if(input_shape.dynamic() and std::any_of(axes.begin(), axes.end(), [&](auto axis) {
return not input_shape.dyn_dims()[axis].is_fixed();
}))
if(input_shape.dynamic() and not input_shape.symbolic())

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 handle this differently for ranged-based dynamics: #5015

Comment thread test/op_shape_test.cpp
Comment on lines +5413 to +5414
// The sliced extent (ends - starts) must be non-negative across the whole variable
// range, so each var range is chosen to keep end >= start.

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'm not sure this is a good assumption. It's basically stating that starts and ends must be valid for the whole range of possible values. What happens when the valid slices are a subset of the possibilities: starts = var("s" , {0, 4}), ends = var("e", {2, 8})?

Comment thread src/include/migraphx/op/slice.hpp Outdated
if(std::holds_alternative<shape::dynamic_dimension>(d))
return std::get<shape::dynamic_dimension>(d).sym_expr;
return sym::lit(std::get<int64_t>(d));
}

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.

Based on our recent conversation, I think this compute_shape() needs to be able to take in the symbolic map at eval time to resolve the dim_like attribute?

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