class_docstr: Performs Value Range Analysis on LoopBody's fx graph by calling BoundVars.run()
  It exposes the ranges of the nodes in the `bounds` variable
  
  Note. A current limitation of this analysis is that it just works on a per-loop basis.
  We should be able to propagate the bounds between across the whole graph. This may benefit
  the case a bounded variable is returned by a kernel and fed into another.
class_docstr_tok: ["Performs","Value","Range","Analysis","on","LoopBody","'s","fx","graph","by","calling","BoundVars.run","(",")","It","exposes","the","ranges","of","the","nodes","in","the","`","bounds","`","variable","Note",".","A","current","limitation","of","this","analysis","is","that","it","just","works","on","a","per-loop","basis",".","We","should","be","able","to","propagate","the","bounds","between","across","the","whole","graph",".","This","may","benefit","the","case","a","bounded","variable","is","returned","by","a","kernel","and","fed","into","another","."]
code: def get_bounds(self) -> Dict[torch.fx.Node, ValueRanges]:
      submodules = self.swap_submodules(self.loop_body.submodules)
  
      # Initialize the environment with the unbounded variables
      for node in self.unbounded_vars:
          # we need to evaluate masked_subblock to recurse, and we need to set indirect values
          if not isinstance(node.target, str) or (
              "masked_subblock" not in node.target
              and "set_indirect" not in node.target
          ):
              self._bounds[node] = ValueRanges.unknown()
  
      with V.set_ops_handler(ValueRangeAnalysis()):
          interpreter = InterpreterShim(
              self.loop_body.root_block.graph, submodules
          )
          interpreter.run(V.get_ops_handler(), initial_env=self._bounds)
      return self._bounds
  
file_path: pytorch/torch/_inductor/bounds.py
imports: import operator
  from functools import partial
  from typing import Any, Callable, Dict
  from sympy import Expr
  import torch
  from torch.utils._sympy.value_ranges import bound_sympy, ValueRangeAnalysis, ValueRanges
  from .ir import InterpreterShim, LoopBody, LoopBodyBlock
  from .utils import cache_on_self, dominated_nodes
  from .virtualized import V
label_desc: Use image node_id 2 for calling the BoundVars obj's underlying member method code with example usage: obj.get_bounds() and returns: self