Expected behavior
matmul(A[M,0], B[0,N]) should return an M×N matrix of zeros (sum of zero terms = 0), consistent with NumPy, PyTorch, and ONNX Runtime.
Actual behavior
The output buffer is not zeroed, so the result contains uninitialized memory (garbage values, NaN). The output is non-deterministic across runs.
Reproducer
import numpy as np
import tvm
from tvm import relax
import tvm.relax.op as R
from tvm.relax.transform import LegalizeOps
bb = relax.BlockBuilder()
a = relax.Var("a", relax.TensorStructInfo((4, 0), "float32"))
b = relax.Var("b", relax.TensorStructInfo((0, 4), "float32"))
with bb.function("main", [a, b]):
with bb.dataflow():
gv = bb.emit_output(bb.emit(R.matmul(a, b)))
bb.emit_func_output(gv)
mod = bb.finalize()
pipeline = tvm.ir.transform.Sequential([LegalizeOps()])
exe = tvm.relax.build(pipeline(mod), target="llvm")
vm = tvm.relax.VirtualMachine(exe, device=tvm.cpu())
out = vm["main"](
tvm.runtime.tensor(np.zeros((4, 0), np.float32), device=tvm.cpu()),
tvm.runtime.tensor(np.zeros((0, 4), np.float32), device=tvm.cpu()),
).numpy()
print(out)
# Non-deterministic garbage, e.g.:
# [[ 6.19e+21 3.07e-41 5.25e+21 3.07e-41]
# [ 6.19e+21 3.07e-41 5.25e+21 3.07e-41]
# [ nan -7.43e-44 nan -1.40e-44]
# [ nan 7.57e-44 nan 4.48e-44]]
print(np.zeros((4, 0)) @ np.zeros((0, 4)))
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
Scope
The same issue affects other reduction operations with a zero-size reduction axis:
# All return uninitialized memory instead of the identity element:
R.sum(X[4, 0], axis=1) # expected: zeros(4,1)
R.prod(X[4, 0], axis=1) # expected: ones(4,1)
R.matmul(A[2,3,4,0], B[2,3,0,5]) # expected: zeros(2,3,4,5) [batched]
R.nn.conv2d(X[1,0,8,8], W[4,0,3,3]) # expected: zeros(1,4,8,8) [0 in_channels]
R.einsum([A[4,0], B[0,8]], 'ik,kj->ij') # expected: zeros(4,8)
Notably, R.max and R.min over size-0 axes are handled correctly (returning -inf / +inf).
Why this matters
The garbage output propagates silently. For example:
mm = R.matmul(A[4,0], B[0,8]) # garbage
sm = R.nn.softmax(mm, axis=-1) # produces [1,0,0,...,0] instead of uniform
In dynamic-shape models, K=0 can occur naturally when a filter removes all elements. The result is silent, non-deterministic incorrect output with no crash or warning.
Environment
- TVM commit: 0b0afd8 (main, 2026-04-24)
- OS: Ubuntu 20.04
- Target: llvm (CPU)
Expected behavior
matmul(A[M,0], B[0,N])should return an M×N matrix of zeros (sum of zero terms = 0), consistent with NumPy, PyTorch, and ONNX Runtime.Actual behavior
The output buffer is not zeroed, so the result contains uninitialized memory (garbage values, NaN). The output is non-deterministic across runs.
Reproducer
Scope
The same issue affects other reduction operations with a zero-size reduction axis:
Notably,
R.maxandR.minover size-0 axes are handled correctly (returning -inf / +inf).Why this matters
The garbage output propagates silently. For example:
In dynamic-shape models, K=0 can occur naturally when a filter removes all elements. The result is silent, non-deterministic incorrect output with no crash or warning.
Environment