code: def fuse_as_graphmodule(
      gm: GraphModule, nodes: NodeList, module_name: str
  ) -> Tuple[GraphModule, Tuple[Node, ...], Tuple[Node, ...]]:
      """
      Fuse nodes in graph_module into a GraphModule.
  
      Args:
          gm (GraphModule): target graph_module
  
          nodes (List[Node]): list of nodes in `gm` to fuse, where the node must be topologically sorted
  
          module_name: class name for the fused GraphModule
  
      Returns:
          fused_gm (GraphModule): fused graph module, where its node is a copy of `nodes` in `gm`
  
          original_inputs (Tuple[Node, ...]): input nodes to `nodes` in original `gm`
  
          original_outputs (Tuple[Node, ...]): consumer nodes of `nodes` in original `gm`
  
      """
  
      # assumption: nodes are already sorted in topo order
  
      for node in nodes:
          assert (
              node.graph.owning_module is gm
          ), f"{node} doesn't belong to passed in graph module {gm._get_name()}"
          assert (
              not node._erased
          ), f"{node} has been removed from owning graph"
          assert (
              node in gm.graph.nodes
          ), f"{node} is not found in graph module {gm._get_name()}"
  
      # validates partition doesn't introduce dependency circles in the graph
      assert validate_partition(
          nodes
      ), "Invalid partition, found dependency cycles"
  
      subgraph = Graph()
  
      node_to_placeholder: Dict[
          Node, Node
      ] = (
          {}
      )  # mapping of nodes from old graph to placeholder in new graph
      node_map: Dict[
          Node, Node
      ] = {}  # mapping of nodes from old graph to new graph
  
      # handles inputs through graph.node_copy's arg_transform functions
      def remap_inputs(x):
          if x.op == "get_attr":
              # TODO: do we really need copy the get_attr node into the graph?
              # do something here
              pass
  
          if x in nodes:
              # x is inside subgraph, return the copied node
              # the node should have been copied aleady, as we are copying graph in the topological order
              return node_map[x]
  
          if x not in node_to_placeholder:
              # x is not in subgraph, create a new placeholder for subgraph
              placeholder_node = subgraph.placeholder(
                  x.name, type_expr=x.type
              )
              # copy all meta fields, even if some fields might be irrelvant for the placeholder node
              placeholder_node.meta = copy.copy(x.meta)
              node_to_placeholder[x] = placeholder_node
  
          return node_to_placeholder[x]
  
      # copy nodes in topological order
      for node in nodes:
          new_node = subgraph.node_copy(node, remap_inputs)
          node_map[node] = new_node
  
      # handles outputs
      output_mapping: Dict[
          Node, Node
      ] = {}  # mapping from old output to new outputs
  
      for node in nodes:
          for user_node in node.users:
              if user_node not in nodes:
                  # external user node, need to expose as an output
                  output_mapping[node] = node_map[node]
  
      # outs contain nodes in the new subgraph
      outs = tuple(output_mapping.values())
  
      # Take care of the args of FX output node. If there's a single
      # output then the output node args is like (output_single), else
      # if there're multiple outputs then the output node args is like
      # ((output_0, output_1, ...)).
      subgraph.output(outs[0] if len(outs) == 1 else outs)
  
      # lint to ensure correctness
      subgraph.lint()
      fused_gm: GraphModule
      fused_gm, _ = lift_subgraph_as_module(
          gm, subgraph, comp_name="", class_name=module_name
      )
  
      # sub_gm's input nodes in the original module
      original_inputs: Tuple[Node, ...] = tuple(
          node_to_placeholder.keys()
      )
  
      # sub_gm's outputs node in the original module
      original_outputs: Tuple[Node, ...] = tuple(output_mapping.keys())
  
      return fused_gm, original_inputs, original_outputs
  
file_path: pytorch/torch/fx/passes/utils/fuser_utils.py
imports: import copy
  from queue import SimpleQueue
  from typing import List, Dict, Tuple
  import torch.fx
  from torch.fx.graph_module import GraphModule
  from torch.fx.graph import Graph
  from torch.fx.node import Node
  from torch.fx.passes.tools_common import NodeList, NodeSet, legalize_graph
  from torch.fx.passes.utils import lift_subgraph_as_module
  from torch.fx._compatibility import compatibility
label_desc: Use image node_id 3 for calling a global function with example usage: fuse_as_graphmodule(gm, nodes, module_name) and returns: fused_gm,  original_inputs,  original_outputs, node_to_placeholder, node_map