
    i|                     b    S SK Jr  S SKrS SKJr  S SKJrJr  S SKJ	r	  S SK
Jr   " S S\5      rg)	    )AnyN)EdgeOpOverload)
ExportPass
PassResult)GraphModule)Nodec                       \ rS rSrSr\" / SQ5      rS\4S jrS\	S\
4S jrS\4S jrS\4S	 jrS
\S\4S jrS\4S jrSrg)CSEPass   a  
Common Subexpression Elimination using structural hashing (value numbering).

Deduplicates operations with identical computation structure, replacing
redundant computations with references to previously computed results.

Uses recursive structural keys: two nodes are equivalent if they have the
same op and their inputs are structurally equivalent. This naturally handles
chains like item(select(select(x, 0, a), 0, b)) without special cases.

Safety is determined automatically via op schema introspection:
- For OpOverload targets (aten ops): checks _schema for mutating arguments
- For operator.* targets (SymInt arithmetic): always safe
- A small denylist covers non-deterministic ops (rand, dropout, etc.)
)z
aten::randzaten::rand_likezaten::randnzaten::randn_likezaten::randintzaten::randint_likezaten::randpermzaten::bernoullizaten::dropoutzaten::native_dropoutzaten::multinomialzaten::normalzaten::uniformreturnc                    [        USS5      S:X  a  g[        U[        R                  R                  [
        45      (       a  UR                  R                  nUR                  S5      (       d  gX R                  ;   a  gUR                  R                   H/  nUR                  c  M  UR                  R                  (       d  M/    g   gg)a  
Determine if an op target is safe for CSE.

Uses schema introspection for OpOverload targets: if no argument
has alias_info with is_write=True, the op doesn't mutate and is
safe (unless it's non-deterministic).

Python operator.* targets are always safe (pure scalar arithmetic).

__module__N	_operatorTzaten::F)getattr
isinstancetorch_ops
OpOverloadr   _schemaname
startswith
UNSAFE_OPS	arguments
alias_infois_write)selftargetschema_nameargs       ^/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/executorch/exir/passes/cse_pass.py_is_safe_targetCSEPass._is_safe_target5   s     6<.+= fuzz44nEFF ..--K
 ))(33 oo- ~~//>>-#..2I2I2I  0     graph_modulec                    UR                   n[        S UR                   5       5      n[        5       U l        UR
                  S    H5  n[        U[        5      (       d  M  U R                  R                  U5        M7     0 U l	        0 U l
        0 U l        0 U l        SU l        Sn[        UR                  5       Hl  nU R                  U5      nXpR                  ;   a;  U R                  U   nXLa&  UR!                  U5        UR#                  U5        SnM\  M^  X`R                  U'   Mn     U(       a   UR%                  5         UR'                  5         [)        X5      $ )Nc              3   H   #    U  H  oR                   S :X  d  M  Uv   M     g7f)outputN)op).0ns     r    	<genexpr>CSEPass.call.<locals>.<genexpr>`   s     FkTTX5E11ks   "	"r   FT)graphnextnodesset_output_nodesargsr   r   add	_vn_cache_safe_cache
_sig_to_vn_vn_to_node_next_vnlist_value_numberreplace_all_uses_with
erase_nodeeliminate_dead_codelintr   )	r   r$   r-   output_noder   modifiednodevn	canonicals	            r    callCSEPass.callZ   s/   ""
 FekkFF(+##A&C#t$$""&&s+ ' +-,.*,,.%D##D)B%%% ,,R0	(..y9$$T*#H )
 (,  $ & %%'JJL,11r#   c                     [        U5      nX R                  ;  a  U R                  U5      U R                  U'   U R                  U   $ )z"Cached version of _is_safe_target.)idr5   r!   )r   r   tids      r    _is_safeCSEPass._is_safe   sC    j&&&$($8$8$@DS!$$r#   c                 H    U R                   nU =R                   S-  sl         U$ )z%Allocate a fresh unique value number.   )r8   )r   rB   s     r    _new_vnCSEPass._new_vn   s    ]]	r#   rA   c                   ^  UT R                   ;   a  T R                   U   $ UR                  S:w  a  T R                  5       nOUT R                  ;   a  T R                  5       nOT R	                  UR
                  5      (       d  T R                  5       nO [        U 4S jUR                   5       5      n[        [        U 4S jUR                  R                  5        5       5      5      nUR
                  X44nUT R                  ;   a  T R                  U   nO T R                  5       nUT R                  U'    UT R                   U'   U$ ! [         a    T R                  5       n N-f = f)a
  
Assign an integer value number to a node (global value numbering).

Two nodes with the same value number are structurally equivalent
and can be deduplicated. All signature tuples are flat (contain
only ints and scalars), so hashing is O(n_args) not O(graph_depth).
call_functionc              3   F   >#    U  H  nTR                  U5      v   M     g 7fN_make_hashable)r)   ar   s     r    r+   (CSEPass._value_number.<locals>.<genexpr>   s      KA!4!4Q!7!7   !c              3   N   >#    U  H  u  pUTR                  U5      4v   M     g 7frR   rS   r)   kvr   s      r    r+   rV      s%     WCV41At22156CV   "%)r4   r(   rM   r1   rI   r   tupler2   sortedkwargsitemsr6   	TypeError)r   rA   rB   args_sig
kwargs_sigsigs   `     r    r:   CSEPass._value_number   s"    4>>!>>$''77o%BT''' Bt{{++B$  K KK"W4;;CTCTCVWW
 {{H9$//)-BB+-DOOC(  "t		  $\\^$s   BE	 E	 	E&%E&c           
        ^  [        U[        5      (       a  T R                  U5      $ [        U[        [        [
        [        [        S5      45      (       a  U$ [        U[        [        45      (       a  [        U 4S jU 5       5      $ [        U[        5      (       a,  [        [        U 4S jUR                  5        5       5      5      $ [        U[        R                  5      (       a  U$ [        U[        R                  5      (       a  [        U5      $ [        U[        R                   5      (       a  [        U5      $ [        U[        R"                  5      (       a  [        U5      $ [%        S[        U5       S35      e)u   Convert args/kwargs to a hashable form.

For Node args, returns the integer value number — keeping
all signature tuples flat and O(1) to hash.
Nc              3   F   >#    U  H  nTR                  U5      v   M     g 7frR   rS   )r)   xr   s     r    r+   )CSEPass._make_hashable.<locals>.<genexpr>   s     =A,,Q//rW   c              3   N   >#    U  H  u  pUTR                  U5      4v   M     g 7frR   rS   rY   s      r    r+   ri      s#     TD$7$7$: ;r\   zCannot make z	 hashable)r   r   r:   intfloatstrbooltyper9   r]   dictr^   r`   r   dtypedevicelayoutmemory_formatra   )r   objs   ` r    rT   CSEPass._make_hashable   s    c4  %%c**c5#tT$Z@AAJdE]++====T""T		TTUUU[[))JU\\**s8OU\\**s8OU0011s8Ol49+Y?@@r#   )r8   r1   r5   r6   r4   r7   N)__name__r   __qualname____firstlineno____doc__	frozensetr   rn   r!   r   r   rD   rI   rk   rM   r   r:   r   rT   __static_attributes__ r#   r    r
   r
      ss    $ 	
J$# #J#2 #2 #2J%$ % $$ $3 $LAS Ar#   r
   )typingr   r   "executorch.exir.dialects.edge._opsr   executorch.exir.pass_baser   r   torch.fxr   torch.fx.noder   r
   r}   r#   r    <module>r      s)      = <   yAj yAr#   