[AIMIGRAPHX-1215] add runtime symbol resolution op - #5085
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new resolve_sym_expr runtime operator to evaluate symbolic dimension expressions from concrete runtime dimension values, enabling dynamic-shape lowering patterns (e.g., feeding symbolic slice bounds as runtime inputs).
Changes:
- Added
op::resolve_sym_expr(reflected attributesexprs/symbols) that returns a tuple of evaluated int64 scalars. - Added reference and shape tests for
resolve_sym_expr, plus an integration-style ref test demonstrating use with dynamic multi-inputslice. - Registered the new operator in the build system.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/include/migraphx/op/resolve_sym_expr.hpp |
New operator implementation for runtime symbol expression evaluation. |
src/CMakeLists.txt |
Registers resolve_sym_expr in register_migraphx_ops(). |
test/ref/resolve_sym_expr.cpp |
New ref tests covering single/multi-symbol evaluation behavior. |
test/op_shape_test.cpp |
New shape tests (valid shape + bad input arity) for the operator. |
test/ref/slice.cpp |
New ref test demonstrating resolve_sym_expr feeding a runtime slice bound. |
Regressions detected 🔴 * No develop baseline was found for this PR's branch point; compared against the latest available develop run instead. |
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #5085 +/- ##
===========================================
- Coverage 93.26% 93.25% -0.01%
===========================================
Files 623 624 +1
Lines 32969 33027 +58
===========================================
+ Hits 30747 30799 +52
- Misses 2222 2228 +6
🚀 New features to boost your workflow:
|
CharlieL7
left a comment
There was a problem hiding this comment.
Design looks good. I have questions about some things.
| {{"expressions", | ||
| migraphx::value::array{migraphx::to_value(n - migraphx::sym::lit(1))}}}), | ||
| x); | ||
| mm->add_instruction(migraphx::make_op("slice", {{"axes", {2}}, {"starts", {0}}}), x, end_vals); |
There was a problem hiding this comment.
This is using the range-based compute_shape() of slice. Where the compute_shape() of slice would output the {0, max_interval} shape. To use the symbolic version you would need to add {"ends", {expr(n - 1)}} to the attributes.
There was a problem hiding this comment.
Thats true, but I need your PR to go in before I can do that I think
| #include "test.hpp" | ||
| #include "rob.hpp" | ||
|
|
||
| struct can_eval_finalize_passthrough |
There was a problem hiding this comment.
What's the reason for this logic?
There was a problem hiding this comment.
just a test to make sure const-folding doesnt try and fold an on op that requires finalization. This is just a dummy op testing that logic.
For the eval expr op, calling eval before finalize is problematic because the input_shape attribute does not exist yet
| MIGRAPHX_THROW("EVAL_EXPR_FROM_SHAPE: input shapes not captured; op was not finalized"); | ||
|
|
||
| std::unordered_map<sym::expr, std::size_t> values; | ||
| for(std::size_t i = 0; i < input_shapes.size(); ++i) |
There was a problem hiding this comment.
Can you use for(const auto&[input_shape, arg]:views::zip(input_shapes, args)) instead?
| if(not input_shape.symbolic()) | ||
| continue; | ||
| const auto& dims = input_shape.dyn_dims(); | ||
| for(std::size_t axis = 0; axis < dims.size(); ++axis) |
There was a problem hiding this comment.
same here, you can use for(const auto&[dim, len]:views::zip(dims, lens))
| { | ||
| auto s = as_symbol(x); | ||
| if(seen_variables.insert(s).second) | ||
| result.push_back(std::move(s)); |
There was a problem hiding this comment.
Do you need to push_back here? You could copy it to the vector after the traversal is finished: return {seen_variables.bgin(), seen_variables.end()}
Motivation
For dynamic shapes, the runtime needs to be able to evaluate symbols using concrete input dimensions to be able to compute dynamic ops (eg. slice)
Technical Details
Attributes (
std::vector<sym::expr>, reflected directly):expressions— symbolic expressions to evaluate.Inputs: one tensor whose original compile-time shape contains the referenced root symbols as direct dimensions.
At runtime, each direct symbolic dimension is bound to the corresponding concrete input lens:
Output: one packed
int64vector of shape{expressions.size()}. Elementiiseval(expressions[i]), unclamped.Implementation:
compute_shaperequires one input, verifies every referenced root symbol appears as a direct input dimension, and returnsint64_type, {expressions.size()}.computereads the original input shape fromdyn_output::input_shapesand the concrete dimensions from the runtime argument shape.eval_uint.Restriction: compound input dimensions are not inverted. For example, an input dimension
N/2cannot be used to recoverN;Nmust appear directly on an input axis.Example:
expressions=[N, H/2, W/2], compile-time input{N,3,H,W}, runtime input{7,3,10,12}→[7,5,6].Usage
Changelog Category
Add a
CHANGELOG.mdentry for any option other thanNot ApplicableFollow the LLVM AI Tool Use Policy for contributions using AI.