code: def _register_dequant_promotion_pass(
      pattern, pass_number, dtype=torch.float32
  ):
      @register_freezing_graph_pattern(
          pattern,
          extra_check=_is_valid_dequant_promotion_pattern(dtype),
          pass_number=pass_number,
      )
      def dequant_promotion(match: Match, *args, **kwargs):
          # Dequant_promotion will transform
          # graph 1:
          #            quant
          #      + - - - | - - - +
          #      |    dequant    |
          #      |    /     \    |
          #      |  node1  node2 |
          #      + - | - - - | - +
          #        quant   quant
          # into:
          # graph 2:
          #            quant
          #      + - - / - \ - - +
          #      |dequant dequant|
          #      |    |      |   |
          #      | node1 node2   |
          #      + - | - - - | - +
          #        quant   quant
          # In graph 1, the dequant node is shared by node1 and node2,
          # as a result, neither node1 nor node2 could form an int8
          # fusion pattern.
          # After this transformation, the graph 2 could hit the int8
          # fusion pattern: dequant-node-quant, respectively for
          # node1 and node2.
          assert dtype in [torch.float32, torch.bfloat16]
  
          def clone_to_new_node(graph, source_node, user_node):
              # Clone the source_node to a new node
              # Replace user_node's input from source_node to new_node
              assert (
                  source_node.op == "call_function"
              ), "clone_to_new_node only support node.op call_function"
              with graph.inserting_before(user_node):
                  new_node = graph.call_function(
                      source_node.target,
                      args=source_node.args,
                      kwargs=source_node.kwargs,
                  )
                  new_node.meta = copy.copy(source_node.meta)
                  user_node.replace_input_with(source_node, new_node)
              return new_node
  
          # Find the start node and end node of a dequant pattern
          # * End node should be the match.output_node()
          # * Start node should be the node of dtype convert to float32
          dequant_pattern_end_node = match.output_node()
          assert dequant_pattern_end_node.target in [
              aten.mul.Tensor,
              prims.convert_element_type.default,
              aten.reshape.default,
          ]
  
          # For a dequant pattern, we should expect see the node list as:
          # * OPT(aten.reshape.default)
          # * OPT(prims.convert_element_type.default) (to_bf16)
          # * aten.mul
          # * aten.sub
          # * prims.convert_element_type.default (to_fp32)
          def _find_first_node_in_dequant_pattern(_node):
              if (
                  _node.target is prims.convert_element_type.default
                  and _node.args[1] == torch.float32
              ):
                  # For a dequant pattern, we expect the start node is a to_fp32 node
                  return _node
              else:
                  assert (
                      len(_node.args) >= 1
                  ), "In in dequant pattern, each node should have more than 1 arg."
                  return _find_first_node_in_dequant_pattern(
                      _node.args[0]
                  )
  
          dequant_pattern_start_node = (
              _find_first_node_in_dequant_pattern(
                  dequant_pattern_end_node
              )
          )
  
          # Clone the dequant pattern for each user node
          graph = match.graph
          user_node_list = list(dequant_pattern_end_node.users)
          for user_node in user_node_list[1:]:
              _source_node = dequant_pattern_end_node
              _user_node = user_node
              while _source_node != dequant_pattern_start_node.args[0]:
                  _user_node = clone_to_new_node(
                      graph, _source_node, _user_node
                  )
                  _source_node = _source_node.args[0]
  
          counters["inductor"]["dequant_promotion_matcher_count"] += 1
          counters["inductor"][
              "dequant_promotion_matcher_nodes"
          ] += len(match.nodes)
  
imports: import copy
  import functools
  import itertools
  import math
  import operator
  from typing import Any, Tuple
  import torch
  from torch._dynamo.utils import counters
  from torch.fx.experimental.symbolic_shapes import has_free_symbols
  from ..lowering import lowerings, require_channels_last
  from ..pattern_matcher import Arg, CallFunction, filter_nodes, KeywordArg, ListOf, Match
  from ..utils import pad_listlike
  from .freezing_patterns import register_freezing_graph_pattern
  from .post_grad import register_lowering_pattern
label_desc: Use image node_id 26 for calling a global function with example usage: _register_dequant_promotion_pass(pattern, pass_number, dtype) and returns: new_node, _node, _find_first_node_in_dequant_pattern