code: def _lower_subgraph_nodes(
      gm: torch.fx.GraphModule,
      subgraph_name: str,
      subgraph_nodes: List[torch.fx.Node],
      dumper: Callable[[str], str],
  ) -> None:
      prologue: List[torch.fx.Node] = []
      inputs: List[torch.fx.Node] = []
      body: List[torch.fx.Node] = []
      visible: Set[torch.fx.Node] = set()
  
      # Inductor requires all graph input to be tensors. When adding a container
      # node as subgraph input, add its descendant getitem nodes to the subgraph
      # prologue and add its leaf getitem nodes to the subgraph input.
      def add_input(arg: torch.fx.Node) -> None:
          stack = [arg]
          while len(stack) != 0:
              node = stack.pop()
              if _is_container_node(node):
                  # We should only prepone nodes within subgraph_nodes
                  prologue.extend(
                      user
                      for user in node.users
                      if user in subgraph_nodes
                  )
                  stack.extend(node.users)
              else:
                  if node not in visible:
                      inputs.append(node)
                      visible.add(node)
  
      for node in subgraph_nodes:
          if node.op == "get_attr":
              # Prepone get_attr to avoid having to copy
              # the attribute to the subgraph module.
              inputs.append(node)
              visible.add(node)
              continue
  
          for arg in node.all_input_nodes:
              if arg not in visible:
                  add_input(arg)
  
          if node not in prologue:
              body.append(node)
              visible.add(node)
  
      outputs: List[torch.fx.Node] = []
  
      # Inductor requires all graph output to be tensors. When adding a container
      # node as subgraph output, add its descendant getitem nodes to the subgraph
      # body and add its leaf getitem nodes to the subgraph output.
      def add_output(output: torch.fx.Node) -> None:
          stack = [output]
          while len(stack) != 0:
              node = stack.pop()
              if _is_container_node(node):
                  body.extend(node.users)
                  stack.extend(node.users)
              elif not all(user in visible for user in node.users):
                  if node not in outputs:
                      outputs.append(node)
  
      for node in body:
          if not all(user in visible for user in node.users):
              add_output(node)
  
      assert len(inputs) == len(set(inputs))
      assert len(outputs) == len(set(outputs))
  
      subgraph_module = _create_subgraph_module(inputs, body, outputs)
      readable_tag = dumper(str(subgraph_module.graph))
      setattr(gm, subgraph_name, _InductorModule(subgraph_module))
  
      insertion_point = subgraph_nodes[-1].next
      for node in prologue:
          insertion_point.prepend(node)
  
      with gm.graph.inserting_before(insertion_point):
          # Insert subgraph call
          subgraph_call = gm.graph.create_node(
              op="call_module",
              target=subgraph_name,
              args=tuple(inputs),
              kwargs={"tag": readable_tag},
          )
          # Replace parent graph nodes with their corresponding subgraph outputs
          for idx, output in enumerate(outputs):
              new_output = gm.graph.create_node(
                  op="call_function",
                  target=operator.getitem,
                  args=(subgraph_call, idx),
              )
              new_output.meta = output.meta
              output.replace_all_uses_with(new_output)
  
      # Erase lowered nodes from the parent graph
      for node in reversed(body + outputs):
          if len(node.users) == 0:
              gm.graph.erase_node(node)
  
file_path: pytorch/torch/distributed/_spmd/partial_lower.py
imports: import logging
  import operator
  from typing import Callable, List, Optional, Set, Tuple
  from functorch import make_fx
  import torch
  from torch._inductor.compile_fx import compile_fx_inner
  from torch._inductor.decomposition import select_decomp_table
label_desc: Use image node_id 3 for calling a global function with example usage: _lower_subgraph_nodes(gm, subgraph_name, subgraph_nodes, dumper) without return types