Skip to content

Refactor slice op for symbolic bounds and explicit input mode#5088

Draft
CharlieL7 wants to merge 5 commits into
developfrom
sym_slice_refactor
Draft

Refactor slice op for symbolic bounds and explicit input mode#5088
CharlieL7 wants to merge 5 commits into
developfrom
sym_slice_refactor

Conversation

@CharlieL7

Copy link
Copy Markdown
Collaborator

Motivation

  • Change slice operator's compute_shape() to be able to output symbolic shapes.
  • Also setup to handle operators with data-dependent shape functions.
  • Separated out code from my data-dependent handling prototype and Shivad's sym_slice PR.

Technical Details

Added slice_mode

  • Need a way to determine what the input to slice is for 2+ inputs. Changed slice to have a mode enum.
  • Also changed ONNX parser for slice to use flags to determine what to set the mode to.
  • Added MIGRAPHX_BIT_FLAG_ENUM to enum.hpp to have a way to create type-safe named bit flags.

Slice symbolic shapes

  • Always use 2+ input slice for handling symbolic shapes. Example:
input_shape = {2, 10}
slice(input, ends_input, starts = {0}, ends = {N}, axes = {1})
slice.compute_shape() => {2, N}
  • When slice.compute() is called, the value at ends_input is used to determine the output shape.

Slice range-based dynamic shapes

  • Keep the previous behavior of going to {0, max_of_interval} until we remove range-based dynamic shapes.

Other

  • Update tests wrt. slice changes

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.

Rework the slice operator to support symbolic (dim_like) start/end bounds
and an explicit slice_mode selecting which of starts/ends/axes are supplied
as runtime inputs (replacing the implicit get_set_attributes mechanism):

- op/slice.hpp: dim_like starts/ends, slice_mode enum, symbolic_compute_shape,
  range-based fallback for variable inputs, runtime normalization via
  normalize_starts_ends_axes, attribute-consistency check, and operator<< for
  slice_mode.
- parse_slice.cpp: set slice_mode via the new slice_input_flags bit-flag enum
  (enum.hpp); dim_like.hpp adds to_ints/to_sym_exprs/any_sym; normalize_attributes
  adds symbolic bound normalization.
- Adapt slice consumers to the dim_like/mode interface: simplify_dyn_ops,
  simplify_algebra, simplify_reshapes.
- Minimal consumer adaptation for existing multi-input slice call sites
  (parse_topk var-k, parse_nonmaxsuppression dynamic, parse_split dynamic):
  set mode=ends_input/starts_input/starts_ends_input; behavior unchanged.
- Tests: op_shape_test slice cases, ref/slice, simplify_dyn_ops_test,
  gpu/dyn_slice_lowering, onnx slice_var_input_*, enum.cpp; plus mode updates
  to topk_var_k_test, ref/nonmaxsuppression, split_dyn_input.

Extracted from the proto_data_dependent_symbolics branch. Excludes the topk
op rework, NMS symbolic rework, and bind_symbolic removal.

Co-authored-by: Cursor <[email protected]>
@CharlieL7
CharlieL7 requested a review from shivadbhavsar July 22, 2026 19:14
@CharlieL7 CharlieL7 self-assigned this Jul 22, 2026

@github-actions github-actions Bot 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.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

format.py

[format.py] reported by reviewdog 🐶

throws_shape(
migraphx::make_op("slice",
{{"starts", {0, 1, 2}}, {"axes", {0, 1, 2}}, {"mode", "ends_input"}}),
input,
ends);


[format.py] reported by reviewdog 🐶

throws_shape(
migraphx::make_op("slice",
{{"starts", {0, 1, 2}}, {"ends", {3, 4, 4}}, {"mode", "axes_input"}}),
input,
axes);


[format.py] reported by reviewdog 🐶

throws_shape(
migraphx::make_op("slice", {{"axes", {0, 1, 2}}, {"mode", "starts_ends_input"}}),
input,
starts,
ends);


[format.py] reported by reviewdog 🐶

throws_shape(
migraphx::make_op("slice", {{"ends", {3, 3, 3}}, {"mode", "starts_axes_input"}}),
input,
starts,
axes);


[format.py] reported by reviewdog 🐶

throws_shape(
migraphx::make_op("slice", {{"starts", {0, 1, 2}}, {"mode", "ends_axes_input"}}),
input,
ends,
axes);


[format.py] reported by reviewdog 🐶

mm->add_instruction(
migraphx::make_op("slice", {{"axes", {2}}, {"mode", "starts_ends_input"}}),
l0,
starts,
ends);


[format.py] reported by reviewdog 🐶

mm->add_instruction(
migraphx::make_op("slice", {{"axes", {2}}, {"mode", "starts_ends_input"}}),
l0,
starts,
ends);


[format.py] reported by reviewdog 🐶

mm->add_instruction(
migraphx::make_op("slice", {{"axes", {2}}, {"mode", "starts_ends_input"}}),
input,
starts,
ends);


[format.py] reported by reviewdog 🐶

mm->add_instruction(
migraphx::make_op("slice", {{"starts", {-4}}, {"mode", "ends_axes_input"}}),
input,
ends,
axes);


[format.py] reported by reviewdog 🐶

mm->add_instruction(
migraphx::make_op("slice", {{"axes", {2}}, {"mode", "starts_ends_input"}}),
input,
starts,
ends);


[format.py] reported by reviewdog 🐶

auto slice_ins = m0.add_instruction(
migraphx::make_op("slice", {{"mode", "starts_ends_axes_input"}}),
input,
input_starts,
input_ends,
input_axes);

@CharlieL7
CharlieL7 requested a review from pfultz2 July 22, 2026 19:25
@gh-app-migraphx-bot-pr-write

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

Copy link
Copy Markdown
Test Batch New Rate (5a7870) Old Rate (0c63af) Diff Status
torchvision-resnet50 64 3,274.63 3,266.06 0.26%
torchvision-resnet50_fp16 64 7,605.30 7,546.56 0.78%
torchvision-densenet121 32 2,502.87 2,482.18 0.83%
torchvision-densenet121_fp16 32 5,037.32 4,976.34 1.23%
torchvision-inceptionv3 32 2,063.00 2,057.16 0.28%
torchvision-inceptionv3_fp16 32 4,419.88 4,415.87 0.09%
cadene-inceptionv4 16 823.17 818.77 0.54%
cadene-resnext64x4 16 782.94 783.71 -0.10%
slim-mobilenet 64 8,423.72 8,356.38 0.81%
slim-nasnetalarge 64 229.45 229.42 0.01%
slim-resnet50v2 64 3,199.10 3,185.54 0.43%
bert-mrpc-onnx 8 1,168.56 1,167.46 0.09%
bert-mrpc-tf 1 490.22 486.41 0.78%
pytorch-examples-wlang-gru 1 472.74 480.59 -1.63%
pytorch-examples-wlang-lstm 1 383.83 390.19 -1.63%
torchvision-resnet50_1 1 1,035.70 1,037.04 -0.13%
cadene-dpn92_1 1 452.00 475.84 -5.01% 🔴
cadene-resnext101_1 1 364.57 365.49 -0.25%
onnx-taau-downsample 1 847.26 843.97 0.39%
dlrm-criteoterabyte 1 32.64 32.42 0.70%
dlrm-criteoterabyte_fp16 1 52.61 52.07 1.03%
agentmodel 1 9,301.29 9,645.99 -3.57%
unet_fp16 2 59.20 58.92 0.48%
resnet50v1_fp16 1 1,469.25 1,412.17 4.04%
resnet50v1_int8 1 1,715.57 1,602.24 7.07% 🔆
bert_base_cased_fp16 64 1,102.23 1,098.36 0.35%
bert_large_uncased_fp16 32 346.78 344.75 0.59%
bert_large_fp16 1 205.33 204.70 0.31%
distilgpt2_fp16 16 2,096.83 2,090.27 0.31%
yolov5s 1 560.22 560.47 -0.04%
tinyllama 1 45.97 45.79 0.41%
vicuna-fastchat 1 43.98 44.12 -0.32%
whisper-tiny-encoder 1 414.97 412.35 0.64%
whisper-tiny-decoder 1 411.00 413.51 -0.61%
llama2_7b 1 20.96 20.84 0.60%
qwen1.5-7b 1 23.65 23.52 0.56%
phi3-3.8b 1 26.89 26.73 0.58%
llama3-8b 1 21.81 21.66 0.70%
whisper-large-encoder 1 10.22 10.18 0.32%
whisper-large-decoder 1 106.87 106.43 0.41%
mistral-7b 1 23.82 23.62 0.85%
FLUX.1-schnell 1 771.38 756.55 1.96%

Regressions detected 🔴

@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
distilgpt2_fp16 🔴 FAILED: MIGraphX is not within tolerance - check verbose output
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

@CharlieL7
CharlieL7 marked this pull request as ready for review July 23, 2026 20:34
@CharlieL7
CharlieL7 requested a review from causten as a code owner July 23, 2026 20:34
Copilot AI review requested due to automatic review settings July 23, 2026 20:34
@CharlieL7
CharlieL7 marked this pull request as draft July 23, 2026 20:35

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 refactors the core slice operator to support symbolic (dim_like) bounds, introduces an explicit mode to disambiguate variable slice inputs (starts/ends/axes), and updates ONNX parsing + tests to use the new model. It also extends attribute normalization to handle symbolic bounds by producing symbolic clamp expressions when possible.

Changes:

  • Add op::slice::slice_mode / mode attribute to explicitly define what each trailing slice input represents, and update ONNX parsers/tests accordingly.
  • Refactor slice bounds to dim_like so compute_shape() can produce symbolic output shapes when bounds are symbolic.
  • Extend normalize_attributes() to symbolically clamp dim_like bounds (when use_len normalization is requested).

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/simplify_dyn_ops_test.cpp Updates simplify-dyn-ops slice folding tests to set the new mode attribute.
test/ref/slice.cpp Updates ref backend slice tests to use mode for multi-input slice variants.
test/ref/nonmaxsuppression.cpp Updates NMS ref test to set mode for the dynamic slice on outputs.
test/op_shape_test.cpp Updates/extends slice shape inference tests for symbolic and variable-input modes.
test/onnx/parse/topk_var_k_test.cpp Updates TopK var-K ONNX parse test to use mode for dynamic slicing.
test/onnx/parse/split_dyn_input.cpp Updates dynamic split ONNX parse test to set slice mode consistently.
test/onnx/parse/slice_var_input_static1.cpp Updates slice var-input static ONNX test to set mode.
test/onnx/parse/slice_var_input_static0.cpp Updates slice var-input static ONNX test to set mode.
test/onnx/parse/slice_var_input_dyn1.cpp Updates slice var-input dynamic ONNX test to set mode.
test/onnx/parse/slice_var_input_dyn0.cpp Updates slice var-input dynamic ONNX test to set mode.
test/onnx/parse/slice_var_input_default_steps.cpp Updates default-steps slice var-input ONNX test to set mode.
test/gpu/dyn_slice_lowering.cpp Updates GPU lowering test to set slice mode for runtime inputs.
src/simplify_reshapes.cpp Adjusts reshape simplifications to account for dim_like bounds (but needs guarding for symbolic bounds).
src/simplify_dyn_ops.cpp Refactors constant-input slice folding using mode, and prevents folding when bounds aren’t concrete.
src/simplify_algebra.cpp Updates algebraic rewrites that inspect slice bounds to use dim_like (but needs guarding for symbolic bounds).
src/onnx/parse_topk.cpp Updates TopK parser to set slice mode for the dynamic output slice.
src/onnx/parse_split.cpp Updates Split parser to set slice mode for dynamic split slices.
src/onnx/parse_slice.cpp Refactors Slice parser to build op::slice with dim_like bounds and a mode vector.
src/onnx/parse_nonmaxsuppression.cpp Updates NMS parser to set slice mode for the dynamic output slice.
src/normalize_attributes.cpp Adds symbolic normalization path for dim_like bounds (clamp/index normalization).
src/include/migraphx/op/slice.hpp Implements slice_mode, dim_like bounds, and symbolic compute-shape behavior.
src/include/migraphx/dim_like.hpp Adds helpers (to_ints, to_sym_exprs, any_sym) for working with dim_like vectors.
Comments suppressed due to low confidence (2)

src/simplify_reshapes.cpp:866

  • std::get<int64_t> on op::slice::{starts,ends} will throw if the slice uses symbolic bounds. This pass should skip such slices instead of throwing.
            auto sop           = any_cast<op::slice>(sins->get_operator());
            size_t slice_start = std::get<int64_t>(sop.starts.front());
            size_t slice_len   = std::get<int64_t>(sop.ends.front()) - slice_start;

src/simplify_algebra.cpp:1400

  • get_splits() now sorts/compares starts/ends via to_ints(...)/std::get<int64_t>(...), but it only checks vector sizes—not that the bounds are actually concrete ints. With symbolic bounds (dim_like holding dynamic_dimension), these conversions will throw. Tighten is_static_slice to also require non-symbolic bounds.
    std::sort(result.begin(), result.end(), [&](auto x, auto y) {
        return to_ints(get_start(x)) < to_ints(get_start(y));
    });
    if(std::any_of(get_start(result.front()).begin(),
                   get_start(result.front()).end(),
                   [&](const auto& i) { return std::get<int64_t>(i) != 0; }))

Comment thread src/onnx/parse_slice.cpp
Comment on lines +104 to +105
// ONNX Slice can have up to 5 inputs, we first check the 5th one
// to decide whether MIGX can handle this slice.
Comment on lines +196 to 200
if(contains(mode, slice_mode::axes))
{
// all 4 inputs (data, inputs_starts, input_ends, input_axes)
std::transform(dds.begin(), dds.end(), dds.begin(), [](const auto& dd) {
return shape::dynamic_dimension{0, dd.get_interval().max};
});
Comment thread src/simplify_reshapes.cpp
Comment on lines 663 to +667
auto op = any_cast<op::slice>(ins->get_operator());
for(std::size_t i = 0; i < op.axes.size(); i++)
{
result[op.axes[i]] = std::make_pair(op.starts[i], op.ends[i]);
result[op.axes[i]] =
std::make_pair(std::get<int64_t>(op.starts[i]), std::get<int64_t>(op.ends[i]));
Comment thread src/simplify_reshapes.cpp
Comment on lines +1824 to +1829
std::transform(op.ends.begin(),
op.ends.end(),
op.starts.begin(),
result.begin(),
[](const auto& e, const auto& s) {
return std::get<int64_t>(e) - std::get<int64_t>(s);
Comment thread src/simplify_algebra.cpp
Comment on lines +208 to 212
if(std::max(std::get<int64_t>(sop.starts.front()),
std::get<int64_t>(slice_op.starts.front())) <
std::min(std::get<int64_t>(sop.ends.front()),
std::get<int64_t>(slice_op.ends.front())))
return true;
Comment thread src/onnx/parse_slice.cpp
slice_desc construct_slice_desc(const onnx_parser& parser,
onnx_parser::node_info info,
std::vector<instruction_ref> args) const
slice_desc handle_sd_inputs(const onnx_parser& parser, onnx_parser::node_info info, std::vector<instruction_ref> args) const

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.

[format.py] reported by reviewdog 🐶

Suggested change
slice_desc handle_sd_inputs(const onnx_parser& parser, onnx_parser::node_info info, std::vector<instruction_ref> args) const
slice_desc handle_sd_inputs(const onnx_parser& parser,
onnx_parser::node_info info,
std::vector<instruction_ref> args) const

Comment thread test/fuse_pointwise.cpp
mm->add_instruction(migraphx::make_op("slice", {{"axes", {1}}}), add1, starts1, ends1);
auto s1 = mm->add_instruction(
migraphx::make_op("slice",
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

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.

[format.py] reported by reviewdog 🐶

Suggested change
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

Comment thread test/fuse_pointwise.cpp
ends0);
auto s2 = mm->add_instruction(
migraphx::make_op("slice",
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

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.

[format.py] reported by reviewdog 🐶

Suggested change
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

Comment thread test/fuse_pointwise.cpp
mm->add_instruction(migraphx::make_op("slice", {{"axes", {1}}}), add1, starts1, ends1);
auto s1 = mm->add_instruction(
migraphx::make_op("slice",
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

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.

[format.py] reported by reviewdog 🐶

Suggested change
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

Comment thread test/fuse_pointwise.cpp
ends0);
auto s2 = mm->add_instruction(
migraphx::make_op("slice",
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

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.

[format.py] reported by reviewdog 🐶

Suggested change
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),
{{"axes", {1}}, {"mode", migraphx::value::array{"starts", "ends"}}}),

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.61993% with 20 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 93.62% 6 Missing ⚠️
src/onnx/parse_slice.cpp 92.50% 3 Missing ⚠️
src/include/migraphx/dim_like.hpp 87.50% 2 Missing ⚠️
src/simplify_algebra.cpp 90.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #5088      +/-   ##
===========================================
- Coverage    92.90%   92.87%   -0.04%     
===========================================
  Files          603      603              
  Lines        32526    32587      +61     
===========================================
+ Hits         30217    30262      +45     
- Misses        2309     2325      +16     
Files with missing lines Coverage Δ
src/onnx/parse_nonmaxsuppression.cpp 75.00% <100.00%> (+2.27%) ⬆️
src/onnx/parse_split.cpp 100.00% <100.00%> (ø)
src/onnx/parse_topk.cpp 100.00% <100.00%> (ø)
src/simplify_dyn_ops.cpp 99.32% <100.00%> (-0.04%) ⬇️
src/simplify_reshapes.cpp 97.98% <100.00%> (-0.17%) ⬇️
src/include/migraphx/dim_like.hpp 89.47% <87.50%> (-10.53%) ⬇️
src/simplify_algebra.cpp 97.47% <90.00%> (-0.06%) ⬇️
src/onnx/parse_slice.cpp 95.56% <92.50%> (-2.95%) ⬇️
src/include/migraphx/op/slice.hpp 95.42% <93.62%> (-0.23%) ⬇️
src/normalize_attributes.cpp 93.06% <85.71%> (-3.79%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

2 participants