TI MCU NNC crashes when accessing optional attributes that are None

XMLWordPrintable

    • Type: Bug
    • Resolution: Fixed
    • Priority: Medium
    • Code Generation Tools
    • CODEGEN-15610
    • MCU_NNC_2.1.1
    • MCU_NNC_2.1.2
    • default

      TI MCU NNC crashes when accessing several optional relay attributes that are None when not specified in the model. The bug exists in ti_mcu_nnc 2.1.1.LTS release, and will be fixed in 2.1.2.LTS release.

      Typical behavior of the bug

      The ti_mcu_nnc compiler will emit the following errors:

      File "lib/python3.10/site-packages/tvm/relay/backend/contrib/tinie/prepare.py", line 371, in visit_call
          out_axes.append((axes[i], output_shape[i]))
      TypeError: 'NoneType' object is not subscriptable
      
      or:
      
      File "lib/python3.10/site-packages/tvm/relay/backend/contrib/tinie/prepare.py", line 716, in is_height_only_strided_slice
          return len(slice_call.attrs.axes) == 1 and slice_call.attrs.axes[0] == haxis and \
      TypeError: object of type 'NoneType' has no len()
      

      Typical use cases that could trigger this bug

      When a user compiles a custom model with such layers without specifying optional attributes that is accessed.

      Fixes / Workarounds

      Fixes will be available in 2.1.2.LTS release.

      For workaround, user can apply the following patch before the patch release is available:

      diff --git a/python/tvm/relay/backend/contrib/tinie/prepare.py b/python/tvm/relay/backend/contrib/tinie/prepare.py
      index 468f2c47d9..7b4541a99a 100644
      --- a/python/tvm/relay/backend/contrib/tinie/prepare.py
      +++ b/python/tvm/relay/backend/contrib/tinie/prepare.py
      @@ -269,9 +269,11 @@ class CanonicalizeFloatModel(ExprMutator):
           if res_op_name == "add":
             if add_val and add_axis != -1:
               if arg0_op_name == "squeeze":
      -          new_add_axis = add_axis + len([x for x in arg0.attrs['axis'] if x < add_axis])
      -          b_add = relay.nn.bias_add(arg0.args[0], add_val, axis=new_add_axis)
      -          return relay.squeeze(b_add, axis=arg0.attrs['axis'])
      +          if arg0.attrs['axis'] is not None:
      +            new_add_axis = add_axis + len([x for x in arg0.attrs['axis'] if x < add_axis])
      +            b_add = relay.nn.bias_add(arg0.args[0], add_val, axis=new_add_axis)
      +            return relay.squeeze(b_add, axis=arg0.attrs['axis'])
      +          return relay.nn.bias_add(arg0, add_val, axis=add_axis)
               return relay.nn.bias_add(arg0, add_val, axis=add_axis)
             elif add_val and add_axis == -1 and \
                  arg0_op_name in ["nn.dense", "nn.conv2d", "nn.conv2d_transpose"]:
      @@ -353,6 +355,8 @@ class CanonicalizeFloatModel(ExprMutator):
           elif res_op_name == "transpose":
             # Rewrite transpose with layout transform semantics
             axes = res.attrs.axes
      +      if axes is None:  # axes=None means reverse order, not applicable
      +        return res
             if len(out_type.shape) == 3 and [x.value for x in axes] == [0, 2, 1]:
               return relay.layout_transform(arg0, "NWC", "NCW")
             elif len(out_type.shape) == 4 and [x.value for x in axes] == [0, 3, 1, 2]:
      @@ -713,7 +717,10 @@ class HoistPadding(ExprMutator):
             return super().visit_call(call)
       
         def is_height_only_strided_slice(self, slice_call, haxis):
      -    return len(slice_call.attrs.axes) == 1 and slice_call.attrs.axes[0] == haxis and \
      +    axes = slice_call.attrs.axes
      +    if axes is None:  # axes=None means all axes, not height-only
      +      return False
      +    return len(axes) == 1 and axes[0] == haxis and \
                  slice_call.attrs.strides[0] == 1
       
         # Hoist padding out of conv2d/max_pool2d, merge with previous height-only "strided_slice" if any
      @@ -1162,7 +1169,10 @@ class RemoveInputNormalization(ExprMutator):
               transpose2 = add.args[0]
               in_arg = transpose2.args[0]
               # can only remove input norm with transposes if they invert themselves
      -        assert list(transpose1.attrs.axes) == list(transpose2.attrs.axes), \
      +        axes1 = transpose1.attrs.axes
      +        axes2 = transpose2.attrs.axes
      +        assert (axes1 is None and axes2 is None) or \
      +               (axes1 is not None and axes2 is not None and list(axes1) == list(axes2)), \
                 "input normalization transposes must invert themselves"
             else:
               in_arg = add.args[0]
       

            Assignee:
            TI User
            Reporter:
            TI User
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:

                Connection: Intermediate to External PROD System
                EXTSYNC-6745 - TI MCU NNC crashes when accessing o...
                SYNCHRONIZED
                • Last Sync Date: