code: def _optimize_graph(
      graph: _C.Graph,
      operator_export_type: _C_onnx.OperatorExportTypes,
      _disable_torch_constant_prop: bool = False,
      fixed_batch_size: bool = False,
      params_dict=None,
      dynamic_axes=None,
      input_names=None,
      module=None,
  ):
      if params_dict is None:
          params_dict = {}
  
      # Inline everything
      _C._jit_pass_inline(graph)
  
      # Remove fork/wait nodes
      _C._jit_pass_inline_fork_wait(graph)
      _C._jit_pass_lint(graph)
      if GLOBALS.autograd_inlining:
          _C._jit_pass_onnx_autograd_function_process(graph)
      _C._jit_pass_lower_all_tuples(graph)
  
      # we now record some ops like ones/zeros
      # into a trace where we previously recorded constants.
      # use constant prop to maintain our current level of onnx support
      # without implementing symbolics for all of them
      if _disable_torch_constant_prop is False:
          _C._jit_pass_constant_propagation(graph)
  
      _split_tensor_list_constants(graph, graph)
      # run dce to eliminate dead parts of the graph that might have been
      # left behind by things like symbolic_override
      _C._jit_pass_dce(graph)
      _C._jit_pass_lint(graph)
  
      # CSE should improve perf when Autocast is used with disabled cache
      # Autocast is disabled due to a limitation on tracer as described at https://github.com/pytorch/pytorch/issues/84092
      # Must run before _C._jit_pass_erase_number_types to prevent type substitution
      if _C._jit_pass_cse(graph):
          _C._jit_pass_onnx_lint(graph)
  
      _C._jit_pass_canonicalize_graph_fuser_ops(graph)
      _C._jit_pass_lint(graph)
      _C._jit_pass_peephole(graph, True)
      _C._jit_pass_fuse_addmm(graph)
      _C._jit_pass_lint(graph)
  
      _C._jit_pass_peephole(graph, True)
      _C._jit_pass_lower_all_tuples(graph)
      # in _jit_pass_onnx, symbolic functions are called for each node for conversion.
      # However, there are nodes that cannot be converted without additional context.
      # For example, the number of outputs from split (and whether it is static or dynamic) is unknown
      # until the point where it is unpacked by listUnpack node.
      # This pass does a preprocess, and prepares the nodes such that enough context can be received
      # by the symbolic function.
      _C._jit_pass_onnx_remove_inplace_ops_for_onnx(graph, module)
      _C._jit_pass_onnx_preprocess(graph)
  
      # onnx does not support tuples, so try to remove them
      _C._jit_pass_lint(graph)
  
      # onnx only supports tensors, but 1 / 2 = 0.5 and tensor(1) / tensor(2) = 0
      _C._jit_pass_prepare_division_for_onnx(graph)
  
      _C._jit_pass_onnx_remove_print(graph)
      _C._jit_pass_onnx_preprocess_caffe2(graph)
  
      symbolic_helper._quantized_ops.clear()
      # Unpack quantized weights for conv and linear ops and insert into graph.
      _C._jit_pass_onnx_unpack_quantized_weights(
          graph, params_dict, symbolic_helper.is_caffe2_aten_fallback()
      )
      if symbolic_helper.is_caffe2_aten_fallback():
          # Insert permutes before and after each conv op to ensure correct order.
          _C._jit_pass_onnx_quantization_insert_permutes(
              graph, params_dict
          )
  
          # Find consecutive permutes that are no-ops and remove them.
          _C._jit_pass_custom_pattern_based_rewrite_graph(
              textwrap.dedent(
                  """\
                  graph(%Pi):
                      %Pq = quantized::nhwc2nchw(%Pi)
                      %Pr = quantized::nchw2nhwc(%Pq)
                      return (%Pr)"""
              ),
              textwrap.dedent(
                  """\
                  graph(%Ri):
                      return (%Ri)"""
              ),
              graph,
          )
  
      # onnx only supports tensors, so we turn all out number types into tensors
      _C._jit_pass_erase_number_types(graph)
      if GLOBALS.onnx_shape_inference:
          input_names = [] if input_names is None else input_names
          dynamic_axes = {} if dynamic_axes is None else dynamic_axes
          _C._jit_pass_onnx_set_dynamic_input_shape(
              graph, dynamic_axes, input_names
          )
      _C._jit_pass_onnx_lint(graph)
  
      graph = _C._jit_pass_onnx(graph, operator_export_type)
      _C._jit_pass_onnx_lint(graph)
      _C._jit_pass_lint(graph)
  
      _C._jit_pass_onnx_scalar_type_analysis(
          graph, True, GLOBALS.export_onnx_opset_version
      )
      _C._jit_pass_lint(graph)
  
      _C._jit_pass_onnx_peephole(
          graph, GLOBALS.export_onnx_opset_version, fixed_batch_size
      )
      _C._jit_pass_lint(graph)
  
      # graph is not a valid jit graph anymore because types have been replaced
      # (e.g. int with Tensor), so it now contains operators that don't actually
      # exist. We can't run normal dead code elimination because it'd fail trying
      # to look up if an operator has side effects, but we can run a dead code
      # elimination variant that doesn't need to look up if an op has side effects.
      _C._jit_pass_dce_allow_deleting_nodes_with_side_effects(graph)
      _C._jit_pass_lint(graph)
      graph = _C._jit_pass_canonicalize(graph)
      _C._jit_pass_lint(graph)
      if GLOBALS.onnx_shape_inference:
          try:
              _C._jit_pass_onnx_graph_shape_type_inference(
                  graph, params_dict, GLOBALS.export_onnx_opset_version
              )
          except RuntimeError as exc:
              if (
                  _C_onnx._CAFFE2_ATEN_FALLBACK
                  and exc.args[0]
                  == "ScalarType UNKNOWN_SCALAR is an unexpected tensor scalar type!"
              ):
                  # Caffe2 builds can have UNKNOWN_SCALAR for some tensors
                  pass
  
      return graph
  
imports: from __future__ import annotations
  import contextlib
  import copy
  import inspect
  import io
  import re
  import textwrap
  import typing
  import warnings
  from typing import Any, Callable, cast, Collection, Dict, List, Mapping, Optional, Sequence, Set, Tuple, Type, Union
  import torch
  import torch._C._onnx
  import torch.jit._trace
  import torch.serialization
  from torch import _C
  from torch.onnx import _constants, _exporter_states, errors, symbolic_caffe2, symbolic_helper
  from torch.onnx._globals import GLOBALS
  from torch.onnx._internal import _beartype, diagnostics, jit_utils, onnx_proto_utils, registration
label_desc: Use image node_id 9 for calling a global function with example usage: _optimize_graph(graph, operator_export_type, _disable_torch_constant_prop, fixed_batch_size, params_dict, dynamic_axes, input_names, module) and returns: graph