content: # mypy: disallow-untyped-decorators=False
  
  import logging
  import operator
  from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
  
  import numpy as np
  import torch
  from tensorrt import ITensor as TRTTensor
  from torch.fx.node import Argument, Node, Target
  from torch_tensorrt import ENABLED_FEATURES
  from torch_tensorrt._features import needs_not_tensorrt_rtx
  from torch_tensorrt._utils import is_tensorrt_version_supported
  from torch_tensorrt.dynamo._settings import CompilationSettings
  from torch_tensorrt.dynamo._SourceIR import SourceIR
  from torch_tensorrt.dynamo.conversion import impl
  from torch_tensorrt.dynamo.conversion._ConversionContext import ConversionContext
  from torch_tensorrt.dynamo.conversion._ConverterRegistry import (
      dynamo_tensorrt_converter,
      has_static_shapes_in_args,
  )
  from torch_tensorrt.dynamo.conversion.converter_utils import (
      args_bounds_check,
      enforce_tensor_types,
      get_positive_dim,
      is_only_operator_on_placeholder,
  )
  from torch_tensorrt.dynamo.utils import DYNAMIC_DIM
  
  _LOGGER: logging.Logger = logging.getLogger(__name__)
  
  
  def get_ir(target: Target) -> SourceIR:
      target_module = getattr(target, "__module__", "None")
      if any(
          target_module.startswith(prefix)
          for prefix in ("torch.ops.aten", "torch._ops.aten")
      ):
          return SourceIR.ATEN
      elif any(
          target_module.startswith(prefix)
          for prefix in ("torch.ops.prims", "torch._ops.prims")
      ):
          return SourceIR.PRIM
      elif target_module.startswith("torch.nn"):
          return SourceIR.NN
  
      return SourceIR.UNKNOWN
  
  
  def one_user_validator(
      node: Node, settings: Optional[CompilationSettings] = None
  ) -> bool:
      # Validate only one user, which is a getitem node that accesses the first element in the list
      return (
          len(node.users) == 1
          and list(node.users)[0].target == operator.getitem
          and list(node.users)[0].args[1] == 0
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.native_batch_norm.default,
      capability_validator=one_user_validator,
      supports_dynamic_shapes=True,
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten.batch_norm.default, supports_dynamic_shapes=True
  )
  @dynamo_tensorrt_converter(torch.ops.aten.batch_norm, supports_dynamic_shapes=True)
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_batch_norm(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.normalization.batch_norm(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          weight=args[1],
          bias=args[2],
          running_mean=args[3],
          running_var=args[4],
          training=args[5],
          momentum=args[6],
          eps=args[7],
          cudnn_enabled=args_bounds_check(args, 8, True),
          return_mean_rstd=(target == torch.ops.aten.native_batch_norm.default),
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten._native_batch_norm_legit_no_training.default,
      capability_validator=one_user_validator,
      supports_dynamic_shapes=True,
  )
  def aten_ops_batch_norm_legit_no_training(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.normalization.batch_norm(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          weight=args[1],
          bias=args[2],
          running_mean=args[3],
          running_var=args[4],
          training=False,
          momentum=args[5],
          eps=args[6],
          cudnn_enabled=False,
          return_mean_rstd=(
              target == torch.ops.aten._native_batch_norm_legit_no_training.default
          ),
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten._native_batch_norm_legit.no_stats,
      capability_validator=one_user_validator,
      supports_dynamic_shapes=True,
  )
  def aten_ops_batch_norm_legit_no_stats(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.normalization.batch_norm(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          weight=args[1],
          bias=args[2],
          training=False,
          momentum=args[4],
          eps=args[5],
          return_mean_rstd=True,
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.native_layer_norm.default,
      supports_dynamic_shapes=True,
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_native_layer_norm(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.normalization.native_layer_norm(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          normalized_shape=args[1],
          weight=args_bounds_check(args, 2),
          bias=args_bounds_check(args, 3),
          eps=args[4],
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.native_group_norm.default,
      capability_validator=one_user_validator,
      supports_dynamic_shapes=True,
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_native_group_norm(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.normalization.native_group_norm(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          weight=args_bounds_check(args, 1),
          bias=args_bounds_check(args, 2),
          N=args[3],
          C=args[4],
          HxW=args[5],
          group=args[6],
          eps=args[7],
      )
  
  
  def parse_cat_args(
      args: Tuple[Argument, ...], kwargs: Dict[str, Any]
  ) -> Tuple[List[Any], int]:
      """
      Process inputs for torch.ops.aten.cat.default.
  
      Handles these valid patterns:
        1. args = ((t1, t2, ...), dim)
        2. args = ((t1, t2, ...),), kwargs = {dim: X} with optional dim in kwargs
  
      Returns:
          (input_tensors, dim)
          input_tensors: tuple of tensor arguments
          dim: integer concatenation dimension (default 0)
      """
  
      if len(args) > 1 and isinstance(args[0], (list, tuple)):
          input_tensors = list(args[0])
          dim = args_bounds_check(args, 1, 0)
  
      else:
          # If single arg is itself a tuple/list, unwrap it
          if len(args) == 1 and isinstance(args[0], (list, tuple)):
              input_tensors = list(args[0])
          else:
              input_tensors = list(args)
  
          dim = kwargs.get("dim", 0)
  
      return input_tensors, dim
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.cat.default,
      supports_dynamic_shapes=True,
  )
  def aten_ops_cat(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      inputs, dim = parse_cat_args(args, kwargs)
      return impl.cat.cat(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=inputs,
          dim=dim,
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.embedding.default,
      supports_dynamic_shapes=True,
  )
  def aten_ops_embedding(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.embedding.embedding(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[1],
          weight=args[0],
      )
  
  
  def embedding_bag_validator(
      node: Node, settings: Optional[CompilationSettings] = None
  ) -> bool:
      # Embedding bag op is not refitable
      if settings and not settings.immutable_weights:
          return False
  
      if not one_user_validator(node):
          return False
      meta = node.args[1].meta
      indices = meta.get("tensor_meta")
      if indices is None:
          indices = meta.get("val")
      if indices is None:
          return False
      return len(indices.shape) == 1  # currently only support 1D indices
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.embedding_bag.default,
      capability_validator=embedding_bag_validator,
      supports_dynamic_shapes=True,
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten._embedding_bag.default,
      capability_validator=embedding_bag_validator,
      supports_dynamic_shapes=True,
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
          1: (TRTTensor,),
      }
  )
  def aten_ops_embedding_bag(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.embedding.embedding_bag(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          weight=args[0],
          indices=args[1],
          offsets=args[2],
          mode=args_bounds_check(args, 4, 0),
          per_sample_weights=args_bounds_check(args, 6, None),
          include_last_offset=args_bounds_check(args, 7, False),
      )
  
  
  @dynamo_tensorrt_converter(operator.mod, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.fmod.Scalar, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.fmod.Tensor, supports_dynamic_shapes=True)
  def aten_ops_fmod(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.elementwise.fmod(ctx, target, SourceIR.ATEN, name, args[0], args[1])
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.grid_sampler, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.grid_sampler_2d, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(
      torch.ops.aten.grid_sampler.default, supports_dynamic_shapes=True
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten.grid_sampler_2d.default, supports_dynamic_shapes=True
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
          1: (TRTTensor,),
      }
  )
  def aten_ops_grid(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.grid.grid(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          grid=args[1],
          interpolation_mode=args[2],
          padding_mode=args[3],
          align_corners=args[4],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.relu.default, supports_dynamic_shapes=True)
  def aten_ops_relu(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.relu(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.sigmoid.default, supports_dynamic_shapes=True)
  def aten_ops_sigmoid(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.sigmoid(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
      )
  
  
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  @dynamo_tensorrt_converter(torch.ops.aten.sym_size.int, supports_dynamic_shapes=True)
  def aten_ops_symsize_int(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.shape.shape(ctx, target, SourceIR.ATEN, name, args[0], args[1])
  
  
  def index_dtype_validator(
      node: Node, settings: Optional[CompilationSettings] = None
  ) -> bool:
      index = node.args[1]
      for ind in index:
          if ind is not None:
              val = ind.meta.get("val")
              if val is not None and val.dtype not in (
                  torch.int32,
                  torch.int64,
                  torch.bool,
              ):
                  return False
      return True
  
  
  def index_nonbool_validator(
      node: Node, settings: Optional[CompilationSettings] = None
  ) -> bool:
      # for thor and tensorrt_rtx, we don't support boolean indices, due to nonzero op not supported
      if ENABLED_FEATURES.tensorrt_rtx:
          index = node.args[1]
          for ind in index:
              if ind is not None:
                  val = ind.meta.get("val")
                  if val is not None and val.dtype == torch.bool:
                      return False
      return True
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.index.Tensor,
      capability_validator=lambda node, settings: index_dtype_validator(node, settings)
      and index_nonbool_validator(node, settings),
      supports_dynamic_shapes=True,
      requires_output_allocator=True,
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_index(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.select.index(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args[1],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.tanh.default, supports_dynamic_shapes=True)
  def aten_ops_tanh(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.tanh(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.leaky_relu.default, supports_dynamic_shapes=True
  )
  def aten_ops_leaky_relu(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.leaky_relu(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args_bounds_check(args, 1, 0.01),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.elu.default, supports_dynamic_shapes=True)
  def aten_ops_elu(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.elu(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          alpha=args_bounds_check(args, 1, 1.0),
          beta=args_bounds_check(args, 2, None),
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.softplus.default, supports_dynamic_shapes=True
  )
  def aten_ops_softplus(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.softplus(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          beta=args_bounds_check(args, 1, 1),
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.hardsigmoid.default, supports_dynamic_shapes=True
  )
  def aten_ops_hard_sigmoid(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.hard_sigmoid(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          alpha=args_bounds_check(args, 1, 1 / 6),
          beta=args_bounds_check(args, 2, 1 / 2),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.gelu.default, supports_dynamic_shapes=True)
  def aten_ops_gelu(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.activation.gelu(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          kwargs.get("approximate", "none"),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.matmul, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.matmul.default, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.dot.default, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.mm.default, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.mv.default, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.bmm.default, supports_dynamic_shapes=True)
  def aten_ops_matmul(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.matmul.matrix_multiply(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args[1],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.rsqrt.default, supports_dynamic_shapes=True)
  def aten_ops_rsqrt(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.elementwise.rsqrt(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.neg.default, supports_dynamic_shapes=True)
  def aten_ops_neg(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.unary.neg(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
      )
  
  
  try:
      import modelopt.torch.quantization as mtq  # noqa: F401
  
      assert torch.ops.tensorrt.quantize_op.default
  except Exception as e:
      _LOGGER.warning(
          "Unable to import quantization op. Please install modelopt library (https://github.com/NVIDIA/TensorRT-Model-Optimizer?tab=readme-ov-file#installation) to add support for compiling quantized models"
      )
  else:
  
      @dynamo_tensorrt_converter(
          torch.ops.tensorrt.quantize_op.default, supports_dynamic_shapes=True
      )
      def aten_ops_quantize_op(
          ctx: ConversionContext,
          target: Target,
          args: Tuple[Argument, ...],
          kwargs: Dict[str, Argument],
          name: str,
      ) -> Union[TRTTensor, Sequence[TRTTensor]]:
          return impl.quantize.quantize(
              ctx,
              target,
              SourceIR.ATEN,
              name,
              args[0],
              args[1],
              args[2],
              args[3],
          )
  
  
  if is_tensorrt_version_supported("10.8.0"):
      try:
          import modelopt.torch.quantization as mtq  # noqa: F401
  
          assert torch.ops.tensorrt.dynamic_block_quantize_op.default
      except Exception as e:
          _LOGGER.warning(
              "Unable to import quantize op. Please install modelopt library (https://github.com/NVIDIA/TensorRT-Model-Optimizer?tab=readme-ov-file#installation) to add support for compiling quantized models"
          )
      else:
  
          @dynamo_tensorrt_converter(
              torch.ops.tensorrt.dynamic_block_quantize_op.default,
              supports_dynamic_shapes=True,
          )
          def aten_ops_dynamic_block_quantize_op(
              ctx: ConversionContext,
              target: Target,
              args: Tuple[Argument, ...],
              kwargs: Dict[str, Argument],
              name: str,
          ) -> Union[TRTTensor, Sequence[TRTTensor]]:
              return impl.dynamic_block_quantize.quantize(
                  ctx,
                  target,
                  SourceIR.ATEN,
                  name,
                  args[0],
                  args[1],
                  args[2],
                  args[3],
                  args[4],
                  args[5],
                  args[6],
              )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.squeeze.dim, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.squeeze.dims, supports_dynamic_shapes=True)
  def aten_ops_squeeze(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.squeeze.squeeze(ctx, target, SourceIR.ATEN, name, args[0], args[1])
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.erf.default, supports_dynamic_shapes=True)
  def aten_ops_erf(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.unary.erf(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.unsqueeze.default, supports_dynamic_shapes=True
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_unsqueeze(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.unsqueeze.unsqueeze(ctx, target, SourceIR.ATEN, name, args[0], args[1])
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten._softmax.default, supports_dynamic_shapes=True
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_softmax(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.normalization.softmax(
          ctx, target, SourceIR.ATEN, name, args[0], args[1], args[2]
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.split.Tensor,
      capability_validator=has_static_shapes_in_args([1]),
      supports_dynamic_shapes=True,
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten.split.sizes,
      capability_validator=has_static_shapes_in_args([1]),
      supports_dynamic_shapes=True,
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten.split_with_sizes.default,
      capability_validator=has_static_shapes_in_args([1]),
      supports_dynamic_shapes=True,
  )
  def aten_ops_split(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.split.split(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input=args[0],
          split_size_or_sections=args[1],
          dim=args_bounds_check(args, 2, 0),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.where.self, supports_dynamic_shapes=True)
  def aten_ops_where(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.condition.where(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[1],
          args[2],
          args[0],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.clamp.default, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.clamp.Tensor, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.clip.default, supports_dynamic_shapes=True)
  @dynamo_tensorrt_converter(torch.ops.aten.clip.Tensor, supports_dynamic_shapes=True)
  def aten_ops_clamp(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.elementwise.clamp(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          input_val=args[0],
          min_val=args_bounds_check(args, 1),
          max_val=args_bounds_check(args, 2),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.gather.default)
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
          2: (TRTTensor,),
      }
  )
  def aten_ops_gather(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.select.gather(
          ctx, target, SourceIR.ATEN, name, args[0], args[1], args[2]
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.scatter.src)
  @dynamo_tensorrt_converter(torch.ops.aten.scatter.value)
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
          2: (TRTTensor,),
      }
  )
  def aten_ops_scatter(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.select.scatter(
          ctx, target, SourceIR.ATEN, name, args[0], args[1], args[2], args[3]
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.select.int, supports_dynamic_shapes=True)
  def aten_ops_select(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.select.select(
          ctx, target, SourceIR.ATEN, name, args[0], args[1], args[2]
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.index_put.default,
      capability_validator=lambda node, settings: index_dtype_validator(node, settings)
      and index_nonbool_validator(node, settings),
      supports_dynamic_shapes=True,
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
          2: (TRTTensor,),
      }
  )
  def aten_ops_index_put(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.select.index_put_converter(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args[1],
          args[2],
          args_bounds_check(args, 3, False),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.slice.Tensor, supports_dynamic_shapes=True)
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_slice(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.slice.slice_op(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args_bounds_check(args, 1, replacement=0),
          args_bounds_check(args, 2, replacement=None),
          args_bounds_check(args, 3, replacement=None),
          args_bounds_check(args, 4, replacement=1),
      )
  
  
  def refit_validator(node: Node, settings: Optional[CompilationSettings] = None) -> bool:
      # cumsum op is not refitable
      if settings and not settings.immutable_weights:
          return False
      return True
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.cumsum.default,
      capability_validator=refit_validator,
      supports_dynamic_shapes=True,
  )
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_cumsum(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.slice.cumsum(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args[1],
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.tile.default, supports_dynamic_shapes=True)
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_tile(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.slice.tile(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args[1],
      )
  
  
  def zero_output_validator(
      node: Node, settings: Optional[CompilationSettings] = None
  ) -> bool:
      if 0 in node.args[1]:
          _LOGGER.debug(
              f"We do not support output tensor {node.args[1]} tensors with zero-sized dimensions for this operation."
          )
          return False
      else:
          return True
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.as_strided.default,
      capability_validator=zero_output_validator,
  )
  def aten_ops_as_strided(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.slice.as_strided(
          ctx,
          target,
          source_ir=SourceIR.ATEN,
          name=name,
          input=args[0],
          size=args[1],
          stride=args[2],
          storage_offset=args_bounds_check(args, 3, None),
      )
  
  
  @dynamo_tensorrt_converter(torch.ops.aten.permute.default, supports_dynamic_shapes=True)
  @enforce_tensor_types(
      {
          0: (TRTTensor,),
      }
  )
  def aten_ops_permute(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.permutation.permute(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          args[1],
      )
  
  
  def to_copy_dtype_validator(
      placeholder_only: bool, settings: Optional[CompilationSettings] = None
  ) -> Callable[[Node, CompilationSettings], bool]:
      """Return validator for to_copy node with placeholder restrictions"""
  
      def validate_dtype(to_copy_node: Node) -> bool:
          """Returns true if the to_copy node can be converted to TRT
  
          Based on data type being casted to
          """
          allowed_casts = {
              torch.float,
              torch.int32,
              torch.int64,
              torch.bool,
              torch.int8,
              torch.float16,
              torch.bfloat16,
          }
  
          # Validate input node has convertible kwargs
          if "dtype" in to_copy_node.kwargs:
              if to_copy_node.kwargs["dtype"] in allowed_casts:
                  return True
              else:
                  _LOGGER.debug(
                      f"_to_copy converter rejected node {to_copy_node} with dtype {to_copy_node.kwargs['dtype']}"
                  )
                  return False
          else:
              _LOGGER.debug(
                  f"_to_copy converter rejected node {to_copy_node} with kwargs {to_copy_node.kwargs}"
              )
              return False
  
      def validator(
          to_copy_node: Node, settings: Optional[CompilationSettings] = None
      ) -> bool:
          """Returns true if the to_copy node can be converted to TRT
          and the placeholder restriction is satisfied
          """
          # The placeholder restriction is satsfied if placeholder_only is the same
          # truth value as is_only_operator_on_placeholder(to_copy_node)
          return validate_dtype(to_copy_node) and (
              (not placeholder_only) ^ is_only_operator_on_placeholder(to_copy_node)
          )
  
      return validator
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.clone.default,
      capability_validator=lambda node, settings: not is_only_operator_on_placeholder(
          node, settings
      ),
      supports_dynamic_shapes=True,
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten._to_copy.default,
      capability_validator=to_copy_dtype_validator(placeholder_only=False),
      supports_dynamic_shapes=True,
  )
  def aten_ops_clone_copy_dtype(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      return impl.cast.to_copy(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          kwargs.get("dtype", args[0].dtype),
          force_layer=False,  # force_layer=False results in better performance
      )
  
  
  @dynamo_tensorrt_converter(
      torch.ops.aten.clone.default,
      capability_validator=is_only_operator_on_placeholder,
  )
  @dynamo_tensorrt_converter(
      torch.ops.aten._to_copy.default,
      capability_validator=to_copy_dtype_validator(placeholder_only=True),
  )
  def aten_ops_clone_copy_placeholder(
      ctx: ConversionContext,
      target: Target,
      args: Tuple[Argument, ...],
      kwargs: Dict[str, Argument],
      name: str,
  ) -> Union[TRTTensor, Sequence[TRTTensor]]:
      # For clone or copy nodes where the input is also the output,
      # we need to force cast to ensure a layer is added to the TRT engine
      # since TRT engine inputs cannot also be TRT engine outputs
      return impl.cast.to_copy(
          ctx,
          target,
          SourceIR.ATEN,
          name,
          args[0],
          kwargs.get("dtype", args[0].dtype),
          force_layer=True,
      )
  
  
  