Repository navigation
Description
Expected behavior
According to the ONNX specification for BitShift (opset 11+), when the direction attribute is omitted, it should default to "LEFT" (or b"LEFT"), converting the node to a relax.op.left_shift operation without crashing.
Actual behavior
When importing an ONNX model with a BitShift node that does not have an explicit direction attribute, from_onnx raises an AttributeError:
Error converting operator BitShift, with inputs: [x, y]
Traceback (most recent call last):
File "repro.py", line 15, in <module>
mod = from_onnx(model)
File "python/tvm/relax/frontend/onnx/onnx_frontend.py", line 6864, in from_onnx
return g.from_onnx(graph, opset)
File "python/tvm/relax/frontend/onnx/onnx_frontend.py", line 6406, in from_onnx
self._construct_nodes(graph)
File "python/tvm/relax/frontend/onnx/onnx_frontend.py", line 6606, in _construct_nodes
op = self._convert_operator(op_name, inputs, attr, self.opset)
File "python/tvm/relax/frontend/onnx/onnx_frontend.py", line 6703, in _convert_operator
sym = op_function(self.bb, inputs, attrs, [self._nodes, self._params])
File "python/tvm/relax/frontend/onnx/onnx_frontend.py", line 917, in _impl_v11
direction = attr.get("direction", "LEFT").decode("ascii")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'decode'. Did you mean: 'encode'?
Environment
- TVM Version: 0.28.dev0 (commit
cbb1e12feonmain) - ONNX Version: 1.23.2
- Python Version: 3.12.2
- Operating System: Linux x86_64
Steps to reproduce
import onnx
from onnx import helper, TensorProto
from tvm.relax.frontend.onnx import from_onnx
# BitShift node with omitted direction attribute
node = helper.make_node("BitShift", inputs=["x", "y"], outputs=["z"])
graph = helper.make_graph(
[node],
"bitshift_graph",
[
helper.make_tensor_value_info("x", TensorProto.UINT32, [2, 2]),
helper.make_tensor_value_info("y", TensorProto.UINT32, [2, 2]),
],
[helper.make_tensor_value_info("z", TensorProto.UINT32, [2, 2])],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 11)])
mod = from_onnx(model)Root Cause Analysis
In python/tvm/relax/frontend/onnx/onnx_frontend.py:
@classmethod
def _impl_v11(cls, bb, inputs, attr, params):
direction = attr.get("direction", "LEFT").decode("ascii")In ONNX protobuf, string attributes are delivered as bytes. Throughout onnx_frontend.py (e.g., lines 2084, 3344, 3888, 4440, 5537), default values for string attributes are always passed as byte literals (e.g. attr.get("mode", b"constant").decode("utf-8")).
In BitShift, however, the fallback value was supplied as a Python string "LEFT". When direction is not in attr, attr.get("direction", "LEFT") returns "LEFT", and calling "LEFT".decode("ascii") fails with AttributeError because strings in Python 3 cannot be decoded.
Proposed Fix
Change the fallback default from "LEFT" to b"LEFT":
diff --git a/python/tvm/relax/frontend/onnx/onnx_frontend.py b/python/tvm/relax/frontend/onnx/onnx_frontend.py
--- a/python/tvm/relax/frontend/onnx/onnx_frontend.py
+++ b/python/tvm/relax/frontend/onnx/onnx_frontend.py
@@ -914,7 +914,7 @@ class BitShift(BitwiseBase):
@classmethod
def _impl_v11(cls, bb, inputs, attr, params):
- direction = attr.get("direction", "LEFT").decode("ascii")
+ direction = attr.get("direction", b"LEFT").decode("ascii")
if direction == "LEFT":
cls.numpy_op = _np.left_shift
cls.relax_op = relax.op.left_shiftTriage
- needs-triage
- relax:frontend
Activity