code: def _qnn_conv2d_legalize_hexagon(attrs, inputs, types):
      """Legalize qnn.conv2d op for vrmpy tensorization.
  
      If the inputs are signed or unsigned int8 and data/kernel layouts are NCHW/OIHW, then the input
      and output channels are padded to be a multiple of 4 and 32 respectively.
      """
      data_layout = attrs["data_layout"]
      kernel_layout = attrs["kernel_layout"]
  
      if data_layout != "NCHW" or kernel_layout != "OIHW":
          return None
  
      data_tensor, kernel_tensor = types[0], types[1]
  
      if "int8" in data_tensor.dtype and "int8" in kernel_tensor.dtype:
          in_channel = data_tensor.shape[1].value
          out_channel = kernel_tensor.shape[0].value
          ic_modified = False
          oc_modified = False
          (
              data,
              kernel,
              data_zp,
              kernel_zp,
              data_scale,
              kernel_scale,
          ) = inputs
  
          if in_channel % IN_CHANNEL_VECTOR_LENGTH != 0:
              new_in_channel = helper_align_up(
                  in_channel, IN_CHANNEL_VECTOR_LENGTH
              )
              diff = new_in_channel - in_channel
              pad_width = ((0, 0), (0, diff), (0, 0), (0, 0))
              data = relay.nn.pad(data, pad_width=pad_width)
              kernel = relay.nn.pad(kernel, pad_width=pad_width)
              ic_modified = True
  
          new_out_channel = out_channel
          if out_channel % OUT_CHANNEL_VECTOR_LENGTH != 0:
              new_out_channel = helper_align_up(
                  out_channel, OUT_CHANNEL_VECTOR_LENGTH
              )
              diff = new_out_channel - out_channel
              kernel = relay.nn.pad(
                  kernel, pad_width=((0, diff), (0, 0), (0, 0), (0, 0))
              )
              oc_modified = True
  
              # Pad kernel zero point by 'diff' elements of 0 if it is not scalar
              kernel_zp_tensor = types[3]
              if len(kernel_zp_tensor.shape) != 0:
                  assert isinstance(kernel_zp, relay.Constant)
                  padded_kernel_zp_np = np.append(
                      kernel_zp.data.numpy(), [0] * diff
                  )
                  kernel_zp = relay.const(padded_kernel_zp_np)
  
              # Pad kernel scale by 'diff' elements of 1.0 if it is not scalar
              kernel_scale_tensor = types[5]
              if len(kernel_scale_tensor.shape) != 0:
                  assert isinstance(kernel_scale, relay.Constant)
                  padded_kernel_scale_np = np.append(
                      kernel_scale.data.numpy(), [1.0] * diff
                  )
                  kernel_scale = relay.const(padded_kernel_scale_np)
  
          if ic_modified is True or oc_modified is True:
              new_attrs = dict(attrs)
              if oc_modified:
                  new_attrs["channels"] = new_out_channel
                  out = relay.qnn.op.conv2d(
                      data,
                      kernel,
                      data_zp,
                      kernel_zp,
                      data_scale,
                      kernel_scale,
                      **new_attrs,
                  )
                  output_tensor = types[6]
                  original_out_shape = list(output_tensor.shape)
                  out = relay.strided_slice(
                      out, begin=[0, 0, 0, 0], end=original_out_shape
                  )
              else:
                  out = relay.qnn.op.conv2d(
                      data,
                      kernel,
                      data_zp,
                      kernel_zp,
                      data_scale,
                      kernel_scale,
                      **new_attrs,
                  )
  
              return out
  
      return None
  
imports: import numpy
  from scipy import special
  import tvm
  from tvm import relay
  from tvm._ffi.base import TVMError
  from tvm.relay.qnn.op.canonicalizations import create_integer_lookup_op
  from ....target.x86 import target_has_features
  from ....topi.utils import is_target
  from ..None import op
label_desc: Use image node_id 24 for calling a global function with example usage: _qnn_conv2d_legalize_hexagon(attrs, inputs, types) and returns: None, None, out