[Bug] Relax ONNX Slice crashes on negative-step empty result
- Dominant language
- Python
- Stars
- 13.7k
- Forks
- 4k
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 112
Description
### Expected behavior
TVM Relax should handle ONNX `Slice` with a negative step consistently with ONNX Runtime.
For this case:
```
X shape: [10]
starts = [0]
ends = [5]
axes = [0]
steps = [-1]
```
ONNX Runtime returns an empty tensor:
`ORT shape: (0,) value: []`
TVM should either produce the same empty result or otherwise preserve ONNX Slice semantics.
### Actual behavior
TVM Relax crashes while importing/legalizing/building the ONNX model:
```
ORT shape: (0,) value: []
TVM crashed: Check failed: (strides[i] < 0 ? (end_i <= begin_i) : (begin_i <= end_i)) is false: : Input [Begin=0, End=5] is invalid for axis=0
```
The issue appears for a valid ONNX Slice pattern with steps=[-1] that produces an empty result in ONNX Runtime.
### Environment
TVM: 0.14 environment / Relax ONNX frontend
ONNX Runtime: 1.23
Python: 3.11
Target: llvm
OS: Linux
### Steps to reproduce
```
import numpy as np
import onnx
from onnx import helper, TensorProto
import onnxruntime as ort
import tvm
from tvm import relax
from tvm.relax.frontend.onnx import from_onnx
x_info = helper.make_tensor_value_info("X", TensorProto.FLOAT, [10])
y_info = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None])
starts = helper.make_tensor("starts", TensorProto.INT64, [1], [0])
ends = helper.make_tensor("ends", TensorProto.INT64, [1], [5])
axes = helper.make_tensor("axes", TensorProto.INT64, [1], [0])
steps = helper.make_tensor("steps", TensorProto.INT64, [1], [-1])
node = helper.make_node(
"Slice",
["X", "starts", "ends", "axes", "steps"],
["Y"],
)
graph = helper.make_graph(
[node],
"g",
[x_info],
[y_info],
initializer=[starts, ends, axes, steps],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 17)])
model.ir_version = 9
onnx.checker.check_model(model)
x = np.arange(10, dtype=np.float32)
ort_out = ort.InferenceSession(
model.SerializeToString(),
providers=["CPUExecutionProvider"],
).run(None, {"X": x})[0]
print("ORT shape:", ort_out.shape, "value:", ort_out.tolist())
mod = from_onnx(model)
mod = relax.transform.LegalizeOps()(mod)
ex = relax.build(mod, tvm.target.Target("llvm"))
dev = tvm.cpu(0)
vm = relax.VirtualMachine(ex, dev)
tvm_out = vm["main"](tvm.runtime.tensor(x, device=dev)).numpy()
print("TVM shape:", tvm_out.shape, "value:", tvm_out.tolist())
```
### Triage
* needs-triage
Contributor guide
No contributing guide indexed for this repository
Research direction
Run the supplied reproducer through the Relax ONNX frontend entry point, from_onnx, then inspect relax.transform.LegalizeOps and the Slice legalization path where the invalid Begin/End check is raised. Done means the negative-step case imports, legalizes, builds, and returns an empty tensor matching ONNX Runtime without crashing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100