class_docstr: Helper class to simplify split-cat pattern. In simple cases, both split and cat node can be removed in a "split->cat"
  pattern. However, there are various cases where they can't and we need to simplify split/ add transforms before cat.
  Some such cases are:
      1. Final node has additional args (not coming from the initial split)
      2. Shuffling of args between split/cat
      3. Some final nodes are non-(cat/stack)
      4. Split-dim != cat-dim (but equal split)
  
  Note that any combination of the above cases can happen.
  
  To deal with 1, 2, & 3 - we iterate over all users of split. And figure out common "ranges" that can be merged.
  Then, we simplify the split accordingly. In the best case, split can be entirely removed.
  
  To deal with 4, we add some transformations (unflatten + movedim) (See `get_transform_params`).
  
  Finally, depending on final node being cat or stack, unsqueeze/flatten needs to be added.
class_docstr_tok: ["Helper","class","to","simplify","split-cat","pattern",".","In","simple","cases",",","both","split","and","cat","node","can","be","removed","in","a","``","split-",">","cat","''","pattern",".","However",",","there","are","various","cases","where","they","ca","n't","and","we","need","to","simplify","split\/","add","transforms","before","cat",".","Some","such","cases","are",":","1",".","Final","node","has","additional","args","(","not","coming","from","the","initial","split",")","2",".","Shuffling","of","args","between","split\/cat","3",".","Some","final","nodes","are","non-","(","cat\/stack",")","4",".","Split-dim","!","=","cat-dim","(","but","equal","split",")","Note","that","any","combination","of","the","above","cases","can","happen",".","To","deal","with","1",",","2",",","&","3","-","we","iterate","over","all","users","of","split",".","And","figure","out","common","``","ranges","''","that","can","be","merged",".","Then",",","we","simplify","the","split","accordingly",".","In","the","best","case",",","split","can","be","entirely","removed",".","To","deal","with","4",",","we","add","some","transformations","(","unflatten","+","movedim",")","(","See","`","get_transform_params","`",")",".","Finally",",","depending","on","final","node","being","cat","or","stack",",","unsqueeze\/flatten","needs","to","be","added","."]
docstr: Returns list of inputs to the following user nodes, in order. The outer list represents the user node. The inner
  list represents the inputs to that particular node. This list can either contain
    - a tuple representing the ranges of get_items that should go into the cat (closed interval)
    - torch.fx.Node representing "other" inputs (which are not coming from our split)
docstr_tok: ["Returns","list","of","inputs","to","the","following","user","nodes",",","in","order",".","The","outer","list","represents","the","user","node",".","The","inner","list","represents","the","inputs","to","that","particular","node",".","This","list","can","either","contain","-","a","tuple","representing","the","ranges","of","get_items","that","should","go","into","the","cat","(","closed","interval",")","-","torch.fx.Node","representing","``","other","''","inputs","(","which","are","not","coming","from","our","split",")"]
code: def get_user_input_list(
      self, split_node: torch.fx.Node, next_users: List[torch.fx.Node]
  ) -> List[List[Union[torch.fx.Node, _Range]]]:
      """
      Returns list of inputs to the following user nodes, in order. The outer list represents the user node. The inner
      list represents the inputs to that particular node. This list can either contain
        - a tuple representing the ranges of get_items that should go into the cat (closed interval)
        - torch.fx.Node representing "other" inputs (which are not coming from our split)
      """
      user_inputs_list: List[List[Union[torch.fx.Node, _Range]]] = []
      for user in next_users:
          if user.target in {torch.cat, torch.stack}:
              user_inputs_list.append(
                  self.get_merged_user_inputs(split_node, user)
              )
          else:
              user_inputs_list.append(
                  self.get_non_cat_node_input(split_node, user)
              )
      return user_inputs_list
  
imports: import itertools
  import logging
  import operator
  from typing import Any, Callable, List, Optional, Sequence, Set, Tuple, Union
  from typing_extensions import TypeAlias
  import torch
  from torch._dynamo.utils import counters
  from ..pattern_matcher import Arg, CallFunction, CallFunctionVarArgs, CallMethodVarArgs, config_flag, FailedMatch, get_arg_value, Ignored, KeywordArg, ListOf, Match, MatchContext, MULTIPLE, PatternExpr, register_graph_pattern, RepeatedExpr
  from .pre_grad import merge_getitem_cat_pass, merge_splits_pass, normalization_pass, split_cat_pass, unbind_stack_pass
label_desc: Use image node_id 2 for calling the SplitCatSimplifier obj's underlying member method code with example usage: obj.get_user_input_list(split_node, next_users) and returns: user_inputs_list