apache / apache/tvm

[Bug] Relax ONNX Slice crashes on negative-step empty result

Open
#19,532 0 comments 0 reactions 0 assignees View on GitHub
needs-triage type: bug
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.