
    ȅi                     J   S r SSKrSSKrSSKr\R                  R
                  R                  \R                  R
                  R                  1rS\R                  R                  S\4S jrS\R                  R                  S\S\\R                  R                     S\4S jrg)	a  
DCE pass for unused extra outputs in HOP subgraphs.

When enable_side_effects_with_extra_outputs is True, HOPs like invoke_subgraph,
checkpoint (tag_activation_checkpoint), and autograd.Function (autograd_function_apply)
return all intermediate tensors/symints as extra outputs to support side effects.
However, many of these extra outputs may not actually be used in the parent graph.

Special handling for autograd_function_apply:
- The forward subgraph MUST return (output, saved_values, ...) where indices 0 and 1
  are always required by the runtime
- Only indices 2+ (extra intermediates) can be removed by DCE

This pass removes unused extra outputs by:
1. Identifying which outputs of HOP calls are actually used
2. Removing unused outputs from the subgraph's output node
3. Updating the HOP call to reflect the new output arity
4. Updating getitem indices to account for removed outputs
    Ngmreturnc                 0   Sn[         R                  " [        5      nU R                  R                   H  nUR
                  S:X  d  M  UR                  [        ;   d  M+  UR                  S   n[        U[        R                  R                  5      (       d  Me  UR
                  S:X  d  Mw  UR                  n[        U[        5      (       d   eX%   R                  U5        M     UR                  5        H  u  pV[!        XU5      (       d  M  SnM     U(       a*  U R                  R#                  5         U R%                  5         U HM  n['        X5      n[        U[        R                  R(                  5      (       d  M9  [+        U5      (       d  MK  SnMO     U$ )a  
Remove unused extra outputs from HOP calls recursively.

Processes graphs top-down: first DCE the current graph's HOP outputs,
then recursively process nested subgraphs. This ensures that when we
process a nested subgraph, the parent has already removed unused getitems,
so the nested subgraph sees the correct usage information.

Args:
    gm: The GraphModule to optimize

Returns:
    True if any modifications were made, False otherwise
Fcall_functionr   get_attrT)collectionsdefaultdictlistgraphnodesoptarget_HOPS_WITH_EXTRA_OUTPUTSargs
isinstancetorchfxNodestrappenditems_dce_subgraphlint	recompilegetattrGraphModuledce_hop_extra_outputs)r   modifiedsubgraph_to_nodesnodesubgraph_attrsubgraph_name	hop_nodessubgraphs           Y/home/james-whalen/.local/lib/python3.13/site-packages/torch/_dynamo/dce_extra_outputs.pyr   r   #   s0    H
 9D8O8OPT8U77o%$++9Q*Q IIaLM=%((--88!$$
2 - 4 4!-5555!077=  %6$;$;$= I66H %> 


 +2-h 4 455$X..	 + O    r"   r#   c           	      	  ^^ [        X5      n[        U[        R                  R                  5      (       d  g[        5       mSnU H  n[        UR                  5       H  nUR                  S:X  d  M  UR                  [        R                  :X  d  M5  [        [        UR                  5      5      S:  d  MY  UR                  S   n[        U[        5      (       d   eTR                  U5        M     M     [!        S UR"                  R$                   5       5      n[        UR                  S   5      n	U(       a1  [        U	5      S:  a"  TR                  S5        TR                  S5        [        T5      [        U	5      :  d  [        T5      S:X  a  g0 n
/ nSn['        [        U	5      5       H'  nUT;   d  M  XU'   UR)                  X   5        US-  nM)     UR"                  R+                  U5         UR"                  R-                  [/        U5      5      nSSS5        UR1                  W5        UR"                  R3                  U5        U GH  n[        UR                  5       GHL  nUR                  S:X  d  M  UR                  [        R                  :X  d  M6  UR                  S   n[        U[        5      (       d   eX;  aA  [        [        UR                  5      5      S:X  d   eU R"                  R3                  U5        M  X   nU R"                  R+                  U5         U R"                  R5                  [        R                  UR                  S   U4S9nUR6                  R9                  5       Ul        SSS5        UR1                  W5        U R"                  R3                  U5        GMO     S	UR6                  ;   d  GM}  UR6                  S	   m[        T[.        [        45      (       d   e[/        UU4S
 j['        [        U	5      5       5       5      nUUR6                  S	'   GM     UR"                  R;                  5         UR=                  5         g! , (       d  f       GNM= f! , (       d  f       N= f)z:
DCE a single subgraph by removing unused output indices.
Fr   r      c              3   H   #    U  H  oR                   S :X  d  M  Uv   M     g7f)outputN)r   ).0ns     r%   	<genexpr> _dce_subgraph.<locals>.<genexpr>x   s     K"6Q$$(:Jqq"6s   "	"   N)r   example_valuec              3   >   >#    U  H  nUT;   d  M  TU   v   M     g 7f)N )r+   old_idxold_exampleused_indicess     r%   r-   r.      s'       6Gl* %G$6s   
T)r   r   r   r   r   setr
   usersr   r   operatorgetitemlenr   intaddnextr   r   ranger   inserting_beforer*   tuplereplace_all_uses_with
erase_noder   metacopyr   r   )r   r"   r#   r$   is_autograd_fwdhop_nodeuseridxoutput_nodeold_outputs
old_to_newnew_outputsnew_idxr3   new_output_nodenew_getitemnew_exampler4   r5   s                    @@r%   r   r   Y   s    r)Hh 4 455 !UL O(Dww/)dkkX=M=M.MtDJJ'(1,))A,C%c3//// $$S) )  K(.."6"6KKK{''*+K 3{+q0 <C,,L0AQ0F "$JKG[)*l"")w{34qLG	 + 
	(	(	5"..//k0BC 
6%%o6NNk*(Dww/)dkkX=M=M.M))A,!'3////,tDJJ/0A555HH''-$-XX..t4"$(("8"8 ((		!g/F #9 #K (,yy~~'7K$ 5 **;7##D)% )* hmm+"--8KkE4=9999  $S%56  K
 .9HMM/*? B NNS 
6	5$ 54s   4%Q)AQ1
Q.1
Q?)__doc__r   r8   r   opshigher_orderinvoke_subgraphtag_activation_checkpointr   r   r   boolr   r   r
   r   r   r2   r&   r%   <module>rW      s   (   
 
II**	II44 3ehh22 3t 3lbb-0b=A%((--=Pb	br&   