code: def _q_multiply_shift_per_axis_hexagon(op):
      """
      Implementation of q_multiply_shift_per_axis through hexagon intrinsics vmpyewuh and vmpyowh when
      q == 31.
      """
      arg_x = op.args[0]
      arg_fractional_bits = op.args[4]
      arg_is_lshift_required = op.args[5]
      arg_is_rshift_required = op.args[6]
  
      # Don't use this intrinsic if we are not multiplying q31 numbers
      if arg_fractional_bits.value != 31:
          return op
  
      x_lanes = get_lanes(arg_x.dtype)
      if x_lanes % 32 != 0 or not is_power_of_2(x_lanes // 32):
          return op
  
      # Don't use this intrinsic when we need do both: left and right shifts.
      # For now it is not clear how to implement this case through vector HVX instructions without
      # accuracy drop.
      if arg_is_rshift_required.value and arg_is_lshift_required.value:
          return op
  
      # pylint: disable=unused-argument
      def intrinsic_impl_32(
          x,
          y,
          left_shift,
          right_shift,
          fractional_bits,
          is_lshift_required,
          is_rshift_required,
      ):
          lowered_dtype = "int32x32"
  
          # Case 1: do the left shift
          shifted_x = x << left_shift
          mul_e_1 = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vmpyewuh.128B",
              tvm.tir.const(2, "uint32"),
              shifted_x,
              y,
          )
          left_shift_out = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vmpyowh.rnd.sacc.128B",
              tvm.tir.const(3, "uint32"),
              mul_e_1,
              shifted_x,
              y,
          )
  
          # Case 2: do the right shift
          mul_e_2 = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vmpyewuh.128B",
              tvm.tir.const(2, "uint32"),
              x,
              y,
          )
          mul_o_2 = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vmpyowh.sacc.128B",
              tvm.tir.const(3, "uint32"),
              mul_e_2,
              x,
              y,
          )
          fixup = 1 << (right_shift - 1)
          round_mul = mul_o_2 + fixup
          right_shift_out = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vasrwv.128B",
              tvm.tir.const(2, "uint32"),
              round_mul,
              right_shift,
          )
  
          # Case 3: do neither right nor left shift
          mul_e_3 = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vmpyewuh.128B",
              tvm.tir.const(2, "uint32"),
              x,
              y,
          )
          no_shift_out = tvm.tir.call_llvm_intrin(
              lowered_dtype,
              "llvm.hexagon.V6.vmpyowh.rnd.sacc.128B",
              tvm.tir.const(3, "uint32"),
              mul_e_3,
              x,
              y,
          )
  
          return tvm.tir.Select(
              tvm.tir.Not(
                  tvm.tir.Or(is_lshift_required, is_rshift_required)
              ),
              no_shift_out,
              tvm.tir.Select(
                  is_lshift_required, left_shift_out, right_shift_out
              ),
          )
  
      return _adapt_to_highest_lanes(
          *op.args, intrinsic=intrinsic_impl_32, intrinsic_lanes=32
      )
  
file_path: tvm/python/tvm/topi/hexagon/tensor_intrin.py
imports: import tvm
  from tvm.ir import register_intrin_lowering
  from tvm import te
label_desc: Use image node_id 6 for calling a global function with example usage: _q_multiply_shift_per_axis_hexagon(op) and returns: _adapt_to_highest_lanes, op, op, op, tvm