
     Ti6                       S r SSKJr  SSKrSSKrSSKJr  SS/rSSKJ	r	  SSKJ
r
JrJr  SSKrSS	KJr  \\\R"                     \\R$                     4   r\r\\   rSS
 jrSS jr    SS jrSS jr\R8                   " S S\R:                  R<                  5      5       r " S S\R:                  R@                  5      r!g)z)Implementation of an inliner for onnx_ir.    )annotationsN)Callable
InlinePassInlinePassResult)defaultdict)IterableMappingSequence)_clonerc                `    U nSnX2;   a  US-  nU  SU 3nX2;   a  M  UR                  U5        U$ )a  Generate a unique name from a name, calling-context, and set of used names.

If there is a name clash, we add a numeric suffix to the name to make
it unique. We use the same strategy to make node names unique.

TODO: We can use the callstack in generating a name for a value X in a function
that is inlined into a graph. This is not yet implemented. Using the full callstack
leads to very long and hard to read names. Some investigation is needed to find
a good naming strategy that will produce useful names for debugging.
   _)add)name	callstack
used_names	candidateis        \/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/onnx_ir/passes/common/inliner.py_make_unique_namer      sH     I	A

!	QfAaSM	 
! NN9    c                <    U u  pnU SU 3U(       a  SU 3-   $ S-   $ )z9Format an operator identifier as a human-readable string.z:::  )op_iddomainr   overloads       r   _format_function_idr   3   s2    "F(XRvHAhZ.EE"EEr   c                P   ^  SU 4S jjnT  Vs0 s H  o"U" U5      _M     sn$ s  snf )z=Create a short unambiguous abbreviation for all function ids.c                   >^^^ U u  mmm[        UUU4S jT 5       5      (       a  TS-   nOSnTS:w  a  UT-   S-   T-   $ UT-   $ )z:Create a short unambiguous abbreviation for a function id.c              3  n   >#    U  H*  oS    T:g  =(       a    US   T:H  =(       a    US   T:H  v   M,     g7f)r   r      Nr   ).0xr   r   r   s     r   	<genexpr>7_abbreviate.<locals>.id_abbreviation.<locals>.<genexpr>B   s5     Z\tv~C!A$$,C1Q483CC\s   25r   r   )any)idshort_domainr   r   r   function_idss     @@@r   id_abbreviation$_abbreviate.<locals>.id_abbreviation>   sU    !#hZ\ZZZ!C<LLr>$&,x77d""r   )r)   ir.OperatorIdentifierreturnstrr   )r+   r,   r)   s   `  r   _abbreviater1   9   s*    

# /;;l##l;;;s   #c                   0 nU R                   R                  5        Hf  u  p#UR                  5        HM  nUR                  5       nXPR                   ;   d  M$  UR	                  U[        5       5      R                  U5        MO     Mh     [        R                  " U5      n UR                  5         g! [        R                   a  nUR                  S   nUs SnA$ SnAff = f)zDetect cyclic dependencies between functions in the model.

Returns:
    A list of function ids forming a cycle if a cycle is detected, otherwise None.
r   N)	functionsitems	all_nodesop_identifier
setdefaultsetr   graphlibTopologicalSorterprepare
CycleErrorargs)	modeldependenciesfunc_idfunctionnoder   sorterecycles	            r   _detect_function_cyclesrF   M   s     MOL"__224&&(D&&(E'''7;;EB ) 5 ''5F   q	s   B/ /CCCCc                       \ rS rSr% S\S'   Srg)r   f   z dict[ir.OperatorIdentifier, int]id_countr   N)__name__
__module____qualname____firstlineno____annotations____static_attributes__r   r   r   r   r   f   s    ..r   c                  n   ^  \ rS rSrSrS
SU 4S jjjrSS jrSS jrSS jrSS jr	    SS jr
S	rU =r$ )r   k   aN  Inline model local functions to the main graph and functions and remove unused functions.

When a node calls a function defined in the model and when ``criteria`` is None or
``criteria(function)`` returns True, the function body is inlined into the graph in place
of the call node.

.. versionadded:: 0.1.16
    The ``criteria`` parameter.

Requires:
    No cyclic dependencies between functions in the model.

Attributes:
    criteria: Optional function that takes an :class:`onnx_ir.Function` and
        returns True if the it should be inlined. If None, all function calls are inlined.
c                   > [         TU ]  5         Xl        0 U l        0 U l        0 U l        [        5       U l        [        5       U l        0 U l	        [        5       U l
        g N)super__init__criteria
_functions_function_id_abbreviations_opset_importsr8   _used_value_names_used_node_names_node_context_inlined_functions)selfrV   	__class__s     r   rU   InlinePass.__init__}   sT      EGLN'.0+.5*-%79>Aer   c                    UR                   U l        [        U R                  R                  5       5      U l        UR
                  U l        [        5       U l        [        5       U l	        0 U l
        [        5       U l        g rS   )r3   rW   r1   keysrX   opset_importsrY   r8   rZ   r[   r\   r]   )r^   r>   s     r   _resetInlinePass._reset   s[    //*5doo6J6J6L*M'#11!$ #"%%r   c                    U R                  U5        [        U5      nUb:  SR                  S U 5       5      n[        R                  R                  SU 35      eg )Nz -> c              3  8   #    U  H  n[        U5      v   M     g 7frS   )r   )r$   r@   s     r   r&   &InlinePass.requires.<locals>.<genexpr>   s     #VPUW$7$@$@PUs   z.Cyclic dependency detected between functions: )rd   rF   joinirpassesPreconditionError)r^   r>   rE   	cycle_strs       r   requiresInlinePass.requires   sY    E'.#VPU#VVI))--@L  r   c                4   U R                  U5        0 nU R                  UR                  5      u  p4UR                  5        H  u  pVUR	                  US5      U-   X%'   M     UR
                  R                  5        Hg  u  pxXpR                  ;   a  M  U R                  UR                  5      u  pXJ-  nU	R                  5        H  u  pVUR	                  US5      U-   X%'   M     Mi     U R                   H  nUR
                  U	 M     [        U[        U5      US9$ )Nr   )modifiedrI   )	rd   _inline_calls_ingraphr4   getr3   r]   r   bool)r^   r>   rI   main_id_counttotal_inlinedkvr@   rA   inner_id_countinlineds              r   callInlinePass.call   s   E57 (,'<'<U[['I$!'')DA",,q!,q0HK * "'!6!6!8G111&*&;&;HNN&K#N$M&,,.&ll1a014 / "9 ..G( /  ]0ChWWr   c                  ^ ^ UR                  5       nT R                  U   nUR                  R                  5        Hg  u  pVUT R                  ;  a  UT R                  U'   M&  T R                  U   U:w  d  M;  [        S[        U5       SU ST R                  U    SU S3	5      e   UR                  nUR                  R                  5        Vs0 s H1  nUR                  U;  d  M  UR                  c  M$  UR                  U_M3     n	nU	(       a  0 UEU	En[        S UR                  5        5       5      (       a  [        S[        U5       S35      e[        UR                  5      [        UR                  5      :  aD  [        S	[        U5       S
[        UR                  5       S[        UR                  5       S35      e0 n
[        UR                  5       H  u  pXUR                  U   '   M     [        [        UR                  5      [        UR                  5      5       H  nS XR                  U   '   M     T R                   R#                  U/ 5      n/ UQUPmSUU 4S jjn[$        R&                  " UU
UR(                  USS9nU Vs/ s H  oR+                  U5      PM     nnUR,                   Vs/ s H  nU
U   PM
     nnUU4$ s  snf s  snf s  snf )Nz'Opset mismatch when inlining function 'z': domain 'z' has version z in the model but version z in the functionc              3     #    U  HF  nUR                   [        R                  R                  [        R                  R                  1;   v   MH     g 7frS   )typerj   AttributeTypeGRAPHGRAPHS)r$   attrs     r   r&   /InlinePass._instantiate_call.<locals>.<genexpr>   s=      
+ II"**00"2B2B2I2IJJ+s   AAzLInliner does not support graph attribute parameters to functions. Function 'z' has graph attributesz'Input mismatch when inlining function 'z': call site has z% inputs but function defines at most z inputsc                  > U R                   =(       d    Sn[        UTTR                  5      U l         U R                   H9  nUc  M  UR                   =(       d    Sn[        UTTR                  5      Ul         M;     TTR
                  U '   g)zORename node/values in inlined node to ensure uniqueness in the inlined context.rB   Nval)r   r   r[   outputsrZ   r\   )rB   	node_nameoutputoutput_namenew_call_stackr^   s       r   rename,InlinePass._instantiate_call.<locals>.rename   st    		+VI))^TEZEZ[DI,,%"(++"6K"3#^T5K5K#FK ' (6Dt$r   T)attr_map	value_mapmetadata_propspost_processresolve_ref_attrs)rB   ir.Noder/   None)r6   rW   rc   r4   rY   
ValueErrorr   
attributesvaluesr   valuer(   leninputs	enumerateranger\   rt   r   Clonerr   
clone_noder   )r^   rB   call_site_idr   rA   keyr   r   r   default_attr_valuesr   r   input
call_stackr   clonernodesr   output_valuesr   s   `                  @r   _instantiate_callInlinePass._instantiate_call   s   ""$??5) #00668JC$---+0##C($$S)U2 =>QRW>X=Y Z"e>$2E2Ec2J1K L##(')9; 	 9 -1OO
 !++224
4yy
* /3zz DIItO4 	 

 >J>*=>J 
"))+
 
 
 0788NP 
 t{{c(//229:Me:T9U V!!$T[[!1 22WX[\d\k\kXlWmmtv  	!$++.HA,1hooa() /s4;;'X__)=>A,0Iooa() ? ''++D"5
4:4|4	6 	6 .."
 6>>XT""4(X>9A9I9IJ9Iv6*9IJm##u
p ?Js   K'K6KK9Kc           
     .   UR                    H7  nUR                  c  M  U R                  R                  UR                  5        M9     UR                   H  nU R                  R                  U5        M      [        [        5      nU H  nUR                  (       a%  U R                  R                  UR                  5        UR                  5       nX`R                  ;   a  XF==   S-  ss'   UR                   H7  nUR                  c  M  U R                  R                  UR                  5        M9     M     [        [        5      nSn	U GH  nUR                  5       nX`R                  ;   a  U R                  b%  U R                  U R                  U   5      (       d  MU  U R                  R                  U5        XF   S:  a  SX    3n
X==   S-  ss'   OSn
UR                  =(       d    U R                  U   U
-   nU R                  X[5      u  p[        R                   R#                  UUU/UUR                  US9  U	S-  n	M  UR$                  R'                  5        H  nUR(                  [        R*                  R,                  :X  a)  U R/                  UR1                  5       5      u  nnU	U-  n	MT  UR(                  [        R*                  R2                  :X  d  M~  UR5                  5        H  nU R/                  U5      u  nnU	U-  n	M     M     GM     XI4$ )a  Inline function calls in a graph.

Returns:
    A tuple of (id_count, inlined_count) where:
    - id_count: A dict mapping function ids to the number of calls in the graph
      (used for naming disambiguation).
    - inlined_count: The number of nodes that were actually inlined.
r   r   r   r   )insertion_point	old_nodes	new_nodes
old_values
new_values)r   r   rZ   r   initializersr   intr[   r6   rW   r   rV   r]   rX   r   rj   conveniencereplace_nodes_and_valuesr   r   r   r   r   rr   as_graphr   	as_graphs)r^   rs   r   initializerrI   rB   r   r   next_idinlined_countcall_site_prefix	call_siter   r   r   r   sub_inlinedgs                     r   rr   InlinePass._inline_calls_in  s    \\Ezz%&&**5::6 " !--K""&&{3 . 6A5EDyy%%))$))4&&(E'1$,,;;***..v{{; '  5@4DD&&(E'==,T]]4??SXCY5Z5Z''++E2 ?Q&)*7>*:';$Na'N')$ II 33E:=MM  !% 6 6t G77$(#f##||% 8  " OO224DyyB$4$4$:$::)-)>)>t}})O;%4b&6&6&=&==!%!1A-1-B-B1-ENA{)[8M "2 57 F &&r   )rX   rW   r]   r\   rY   r[   rZ   rV   rS   )rV   z$Callable[[ir.Function], bool] | Noner/   r   )r>   ir.Modelr/   r   )r>   r   r/   r   )rB   r   r   
CallSiteIdr/   NodeReplacement)rs   zir.Graphr/   z,tuple[dict[ir.OperatorIdentifier, int], int])rJ   rK   rL   rM   __doc__rU   rd   rn   r|   r   rr   rO   __classcell__)r_   s   @r   r   r   k   sI    "D D(X4K$ZE'E'	5E' E'r   )r   r0   r   	CallStackr   zset[str]r/   r0   )r   r.   r/   r0   )r+   zIterable[ir.OperatorIdentifier]r/   z dict[ir.OperatorIdentifier, str])r>   r   r/   z"list[ir.OperatorIdentifier] | None)"r   
__future__r   dataclassesr9   collections.abcr   __all__collectionsr   r   r	   r
   onnx_irrj   r   tupleNodeValuer   r0   r   listr   r   r   r1   rF   	dataclassrk   
PassResultr   InPlacePassr   r   r   r   <module>r      s    0 "   $+
, # 7 7  
 )8BHH+==>
 
	(F<1<%<(2 /ryy++ / /^'&& ^'r   