
    |hf|                     *   S r SSKJrJr  SSKrSSKrSSKJrJr  SSK	J
r
JrJr  SSKJrJr  SSKJrJr  \R"                  " \5      rS rS	 r\" S
S5      rS rS rS rS rS rS rS rS rS rS r S r!S r"S r#S r$S r%S r&S\'4S jr(SS.S jr)g) z&
Implement transformation on Numba IR
    )
namedtupledefaultdictN)compute_cfg_from_blocksfind_top_level_loops)errorsirir_utils)compute_use_defsr   )	PYVERSION_lazy_pformatc                   ^ ^ U 4S jnS nU4S jn[         R                  S5        / n[        T 5       H  n[         R                  SU5        U" U5      (       d  M(  U" U5      (       d  M7  U" U5      (       d  MF  T R	                  5       UR
                  ;  d  Mf  UR                  U5        [         R                  SU5        M     U$ )z=
Returns a list of loops that are candidate for loop lifting
c                   > [        5       nU R                   HF  n[        S TR                  U5       5       5      nU(       d  [        R	                  S5          gX-  nMH     [        U5      S:H  n[        R	                  SXA5        U$ )z)all exits must point to the same locationc              3   *   #    U  H	  u  pUv   M     g 7fN ).0x_s      O/home/james-whalen/.local/lib/python3.13/site-packages/numba/core/transforms.py	<genexpr>L_extract_loop_lifting_candidates.<locals>.same_exit_point.<locals>.<genexpr>   s     8&7da&7s   zreturn-statement in loop.F   zsame_exit_point=%s (%s))setexits
successors_loggerdebuglen)loopoutedgesksuccsokcfgs        r   same_exit_point9_extract_loop_lifting_candidates.<locals>.same_exit_point   sr    5A8cnnQ&788E 9:H  ]a/>	    c                 b    [        U R                  5      S:H  n[        R                  SU5        U$ )zthere is one entryr   zone_entry=%s)r   entriesr   r   )r   r#   s     r   	one_entry3_extract_loop_lifting_candidates.<locals>.one_entry(   s(    !#nb)	r'   c                   > [        U R                  5      [        U R                  5      -  [        U R                  5      -  n[	        TR
                  U5       Hx  nUR                   He  n[        U[        R                  5      (       d  M$  [        UR                  [        R                  5      (       d  MO  [        R                  S5            g   Mz     [        R                  S5        g)z!cannot have yield inside the loopz	has yieldFzno yieldT)r   bodyr)   r   map__getitem__
isinstancer   AssignvalueYieldr   r   )r   insidersblkinstblockss       r   cannot_yield6_extract_loop_lifting_candidates.<locals>.cannot_yield.   s    tyy>C$55DJJGv))84CdBII..!$**bhh77k2$	 ! 5 	j!r'   zfinding looplift candidatesztop-level loop: %szadd candidate: %s)r   infor   r   entry_pointr)   append)r$   r7   r%   r*   r8   
candidatesr   s   ``     r    _extract_loop_lifting_candidatesr>      s    
 
 LL./ J$S)*D1D!!ioo,t:L:LOOT\\1d#MM-t4 * r'   c                 v   X   nX   n0 nU H	  nX   Xx'   M     [        5       n	[        5       n
[        U5      nUR                  R                  5        H  nX-  n	M	     UR                  R                  5        H  nX-  n
M	     X-  n[        [        U5      U-  5      n[        [        U5      U-  U
-  5      nXV4$ )z7Find input and output variables to a block region.
    )r   r
   usemapvaluesdefmapsorted)r7   livemapcallfromreturntobody_block_idsinputsoutputs
loopblocksr!   	used_varsdef_varsdefsvsused_or_defineds                 r   find_region_inout_varsrP   H   s     FG
 J	
  IuHJ'Dkk  "	 #kk  " #*O CK/12FS\O3h>?G?r'   loop_lift_infoz%loop,inputs,outputs,callfrom,returntoc           	         [        X5      n/ nU H  nUR                  u  n[        [        UR                  5      5      n[        UR                  5      S:  a  U R                  U5      u  u  pOUn[        UR                  5      [        UR                  5      -  [        UR                  5      -  n
[        UUUUU
S9u  p[        X[UXhS9nUR                  U5        M     U$ )z0
Returns information on looplifting candidates.
r   )r7   rD   rE   rF   rG   )r   rH   rI   rE   rF   )r>   r)   nextiterr   r   r   r   r-   rP   _loop_lift_infor<   )r$   r7   rD   loops	loopinfosr   rE   an_exitrF   r   local_block_idsrH   rI   llis                 r   _loop_lift_get_candidate_infosr[   h   s     -S9EI\\
tDJJ'(tzz?Q!nnW5O]h Hdii.3t||+<<s4::N0*
 4'/D- 0 r'   c                     UR                   nUR                  n[        R                  " XVS9n[        R
                  " UU UUUS9  U$ )zJ
Transform calling block from top-level function to call the lifted loop.
scopeloc)newblockcallee
label_nextrH   rI   )r^   r_   r   Blockr	   fill_block_with_call)
liftedloopblockrH   rI   rF   r^   r_   r5   s           r   _loop_lift_modify_call_blockrg      sH     KKE
))C
((
(C!! Jr'   c                 b   XR                      nUR                  nUR                  n[        U5      S-
  n[        R
                  " [        R                  " X4S9U R                  U R                   S9X'   [        R                  " [        R                  " X4S9U R                  S9XR                  '   g)z7
Inplace transform loop blocks for use as lifted loop.
r   r]   )rf   rH   rb   )rf   rI   N)rE   r^   r_   minr	   fill_callee_prologuer   rc   rH   fill_callee_epiloguerI   rF   )loopinfor7   entry_blockr^   r_   firstblks         r   _loop_lift_prepare_loop_funcro      s     **+KE
//C 6{QH44hhU,$$F
 !) = =hhU,  !Fr'   c                   ^ SSK Jn  UR                  n[        UR                  5      [        UR
                  5      -  n	[        UR                  5      S:  a  XR                  -  n	[        U4S jU	 5       5      n
[        X5        / nU
R                  5        H!  nUR                  UR                  SS95        M#     [        US S9nUR                  nU R                  U
[!        UR"                  5      [        UR"                  5      S	US
9nU" UX4XV5      n[%        UTUR&                     UR"                  UR(                  UR*                  5      nU	 H  nTU	 M     UTUR&                  '   U$ )zi
Modify the block inplace to call to the lifted-loop.
Returns a dictionary of blocks of the lifted-loop.
r   )
LiftedLoopr   c              3   L   >#    U  H  oTU   R                  5       4v   M     g 7fr   )copy)r   r!   r7   s     r   r   +_loop_lift_modify_blocks.<locals>.<genexpr>   s     C]&)..*+]s   !$getiter)opc                 .    U R                   R                  $ r   )r_   liner   s    r   <lambda>*_loop_lift_modify_blocks.<locals>.<lambda>   s    QUUZZr'   )keyT)r7   	arg_names	arg_countforce_non_generatorr_   )numba.core.dispatcherrq   r   r   r-   r)   r   r   dictro   rA   extend
find_exprsri   r_   derivetuplerH   rg   rE   rI   rF   )func_irrl   r7   	typingctx	targetctxflagslocalsrq   r   loopblockkeysrJ   getiter_exprsr5   first_getiterloop_loc	lifted_irre   	callblockr!   s     `                r   _loop_lift_modify_blocksr      sS    1 ==D		NS%66M
4::#C]CCJ 6 M  "S^^y^9: #+?@M  Hj).x)?),X__)=37#+	  -I
 I%%AJ -Z@Q@Q9R-5__h>N>N-5->->@I 1I  !*F8r'   c                 F   [        UR                  5      S::  a  g[        UR                  5      nU R                  5       n[        5       n[        U5      nU(       a9  UR	                  5       nUR                  U5        X#U   U1-
  -  nX$-
  nU(       a  M9  [        U5      S:  $ )zReturns True if there is more than one exit in the loop.

NOTE: "common exits" refers to the situation where a loop exit has another
loop exit as its successor. In that case, we do not need to alter it.
r   F)r   r   r   post_dominatorspopadd)r$   lpinfor   pdom	processedremainnodes          r   _has_multiple_loop_exitsr      s     6<<AE D IZF
zz|ddtf$$"	 & u:>r'   c                 $   SSK Jn  [        U R                  5      nUR	                  5       R                  5        H,  n[        X#5      (       d  M  [        XR                  5      u  pM.     U R                  5         U" U 5      R                  5         U $ )z(Canonicalize loops for looplifting.
    r   )PostProcessor)numba.core.postprocr   r   r7   rV   rA   r   _fix_multi_exit_blocksr   _reset_analysis_variablesrun)r   r   r$   	loop_info_common_keys        r   _pre_looplift_transformr      ss     2
!'..
1CYY['')	#C33#9$ G[ * %%'' Nr'   c           
      z   [        U 5      n U R                  R                  5       n[        U5      n[	        XeU R
                  R                  5      n/ nU(       a)  [        R                  S[        U5      [        U S S95        U H"  n	[        X	UXX45      n
UR                  U
5        M$     U R                  US9nX4$ )z
Loop lifting transformation.

Given a interpreter `func_ir` returns a 2 tuple of
`(toplevel_interp, [loop0_interp, loop1_interp, ....])`
z+loop lifting this IR with %d candidates:
%sc                 "    U R                  5       $ r   )dump_to_stringry   s    r   rz   loop_lifting.<locals>.<lambda>  s    AQAQASr'   )	lazy_funcr7   )r   r7   rs   r   r[   variable_lifetimerD   r   r   r   r   r   r<   r   )r   r   r   r   r   r7   r$   rW   rV   rl   liftedmains               r   loop_liftingr     s     &g.G^^  "F
!&
)C.s/6/H/H/P/PRIED)n#G7ST	V )'V*3OV  >>>(D;r'   c                    ^ ^^^^^ [        T 5      mT R                  5       mU4S jmU 4S jmUU4S jnS mUUU4S jnU" 5        H  nU" U5        M     T$ )z-
Rewrite loops that have multiple backedges.
c                  <   > [        T R                  5       5      S-   $ )Nr   )maxkeys)	newblockss   r   new_block_id6canonicalize_cfg_single_backedge.<locals>.new_block_id+  s    9>>#$q((r'   c                    > SnU R                    HA  nTU   nUR                  R                  5       nU R                  U;   d  M4  US-  nUS:  d  MA    g   g)Nr   r   TF)r-   
terminatorget_targetsheader)r   countr!   r5   edgesr7   s        r   has_multiple_backedges@canonicalize_cfg_single_backedge.<locals>.has_multiple_backedges.  sU    A)CNN..0E{{e#
19  r'   c               3   ~   >#    TR                  5       R                  5        H  n T" U 5      (       d  M  U v   M     g 7fr   )rV   rA   )lpr$   r   s    r   #yield_loops_with_multiple_backedgesMcanonicalize_cfg_single_backedge.<locals>.yield_loops_with_multiple_backedges;  s/     ))+$$&B%b)) 's   -=	=c                   ^^ UU4S jn[        U [        R                  5      (       aK  [        R                  " U R                  U" U R                  5      U" U R
                  5      U R                  S9$ [        U [        R                  5      (       a/  [        R                  " U" U R                  5      U R                  S9$ U R                  5       (       a   eU $ )Nc                    > U T:X  a  T$ U $ r   r   )targetdstsrcs    r   replaceIcanonicalize_cfg_single_backedge.<locals>.replace_target.<locals>.replaceA  s    !S=C5f5r'   )condtruebrfalsebrr_   r   r_   )
r0   r   Branchr   r   r   r_   Jumpr   r   )termr   r   r   s    `` r   replace_target8canonicalize_cfg_single_backedge.<locals>.replace_target@  s    	6 dBII&&99$))$+DKK$8%,T\\%:!%+ + bgg&&77'$++"6DHHEE''))))Kr'   c                   > U R                   nT" 5       nU R                   H]  nT	U   nXR                  R                  5       ;   d  M'  UR	                  5       nT
" UR                  UU5      UR                  S'   UT	U'   M_     T	U   n[
        R                  " UR                  UR                  S9nUR                  [
        R                  " XR                  S95        UT	U'   g)z3
Add new tail block that gathers all the backedges
r]   r   N)r   r-   r   r   rs   r   rc   r^   r_   r<   r   )r   r   tailkeyblkkeyr5   newblkentryblktailblkr   r   r   s           r   rewrite_single_backedgeAcanonicalize_cfg_single_backedge.<locals>.rewrite_single_backedgeO  s     .iiFF#C3355"018#:B$*	&!   V$((X\\Brwwf++>?$	'r'   )r   rs   )	r7   r   r   r   r$   r   r   r   r   s	   `   @@@@@r    canonicalize_cfg_single_backedger   $  sR     "&
)CI)
%* 45% 6 r'   c                     [        U 5      $ )zW
Rewrite the given blocks to canonicalize the CFG.
Returns a new dictionary of blocks.
)r   r   s    r   canonicalize_cfgr   j  s    
 ,F33r'   c           
      P  ^^^^ SSK Jn  SUUUU4S jjn[        U 5      u  ppU(       d  U / 4$ UR                  U 5      R	                  5         U R
                  (       d   eU R
                  nU R                  R                  5       n	UR                  n
/ nU Hl  u  p/ n[        XU5       H  nUR                  U5        M     [        X   5        [        X	U5      u  nnUR                  X	XXU5      nUR                  U5        Mn     U(       d  U nUU4$ U R                  U	5      nUU4$ )zWith-lifting transformation

Rewrite the IR to extract all withs.
Only the top-level withs are extracted.
Returns the (the_new_ir, the_lifted_with_ir)
r   )postprocc                    > SSK JnJn  TR                  5       nU(       a  SUl        SUl        SUl        SUl        UnOUnU" U T
T	UT40 UD6$ )Nr   )
LiftedWithObjModeLiftedWithFT)r   r   r   rs   enable_loopliftenable_pyobjectforce_pyobjectno_cpython_wrapper)r   
objectmodekwargsr   r   myflagsclsr   r   r   r   s          r   dispatcher_factory(with_lifting.<locals>.dispatcher_factory{  sV    G**,&+G#&*G#%)G").G&#CC7Iy'6LVLLr'   )F)
numba.corer   find_setupwithsr   r   r   r7   rs   r$   _cfg_nodes_in_regionr<   _legalize_with_head_get_with_contextmanagermutate_with_bodyr   )r   r   r   r   r   r   r   withsvltr7   r$   sub_irs	blk_startblk_endbody_blocksr   cmkindextrasubnew_irs    ````               r   with_liftingr   r  s'    $M M" %W-NE{7#'')$$$$

#
#C^^  "F
''C G %(ADt$ BF-.0)L%%gy&1&+- 	s !&  7? '7?r'   c                 z  ^ ^^^^	 SmU 4S jm	UUUU U	4S jnTT   R                    Hp  n[        U[        R                  5      (       d  M$  UR                  nU" U5      u  pg[        US5      (       d"  [        R                  " STT   R                  S9eXg4s  $    [        R                  " STT   R                  S9e)z7Get the global object used for the context manager
    zIllegal use of context-manager.c                 &   > TR                  U 5      $ )z#Get the definition given a variable)get_definition)varr   s    r   get_var_dfn-_get_with_contextmanager.<locals>.get_var_dfn  s    %%c**r'   c                 R  > TR                  U 5      n[        U[        R                  5      (       aj  UR                  S:X  aZ  UR
                   Vs/ s H  nT" U5      PM     nnUR                   VVs0 s H  u  pEUT" U5      _M     nnnX6S.nUR                  n OSn[        R                  " [        R                  TU 5      nU[        R                  L a"  [        R                  " STT
   R                  S9eUc  [        R                  " T	UR                  S9eX4$ s  snf s  snnf )z~Return the context-manager object and extra info.

The extra contains the arguments if the context-manager is used
as a call.
call)argsr   Nz*Undefined variable used as context managerr_   )r   r0   r   Exprrv   r  kwsfuncr	   guardfind_outer_value	UNDEFINEDr   CompilerErrorr_   )var_refdfnr   r  r!   vr	  r   ctxobj_illegal_cm_msgr   r7   r   r  s            r   get_ctxmgr_obj0_get_with_contextmanager.<locals>.get_ctxmgr_obj  s     $$W-c277##&(8,/HH5HqKNHD51491k!n$C9!1EhhGE 9 97GL R\\!&&<9%)) 
 >&&CGGDD}' 69s   D3D#r   z"Unsupported context manager in user  zmalformed with-context usage)	r-   r0   r   	EnterWithcontextmanagerhasattrr   r  r_   )
r   r7   r   r  stmtr  r  r   r  r  s
   ```     @@r   r   r     s     8O+ > y!&&dBLL))))G*73MF6#566**8y)--  =  ' 

&9!!
 
r'   c                 
   [        [        5      nU R                   H  nU[        U5      ==   S-  ss'   M     UR	                  [
        R                  5      S:w  a  [        R                  " SU R                  S9eUR	                  [
        R                  S5      S:w  a  [        R                  " SU R                  S9eUR	                  [
        R                  S5        U(       a  [        R                  " SU R                  S9eg)zYGiven *blk*, the head block of the with-context, check that it doesn't
do anything else.
r   z0with's head-block must have exactly 1 ENTER_WITHr  r   z*with's head-block must have exactly 1 JUMPNz'illegal statements in with's head-block)r   intr-   typer   r   r  r   r  r_   r   Del)r5   countersr  s      r   r   r     s     3Hd! ||BLL!Q&""> 	 ||BGGQ1$""8 	
 LL""5 	 r'   c                 >   [        5       nU/nU(       a  UR                  5       n[        U R                  U5      5      nU(       aI  [	        U6 u  px[        U V	s/ s H  n	X;  d  M
  X:w  d  M  U	PM     sn	5      n
UR                  U
5        X:-  nU(       a  M  U$ s  sn	f )z;Find the set of CFG nodes that are in the given region
    )r   r   listr   zipr   )r$   region_begin
region_endregion_nodesstacktossucclistr"   r   r   nodess              r   r   r     s     5LNE
iiks+,H~HE% ,%$3 * % , -E LL!L % ,s   	B&B-Bc                    S nU R                   nU" U5      n[        X2U 5      n UR                  5        VVs/ s H  u  pEU[        U5      S   4PM     nnnU HF  u  puX%   R                  R                  5       n[        U5      S:w  d  M2  [        R                  " S5      e   U Hc  u  puX%   n	[        R                  " U R                   U	R                  R                  5       S      R                  5      (       d  MX  [        X5        Me     U VVs/ s H0  u  pEX@R                   U   R                  R                  5       S   4PM2     nnn[        U5      nX`4$ s  snnf s  snnf )zIFind all top-level with.

Returns a list of ranges for the with-regions.
c                    [        U 5      n[        5       [        5       p2U R                  5        Hr  u  pEUR                   H]  n[        R
                  " U5      (       a  UR                  U5        [        R                  " U5      (       d  ML  UR                  U5        M_     Mt     [        [        5      nUR                  USS9 GH$  n/ / pU	R                  U5        U	(       d  M!  U	R                  5       nU
R                  U5        X   R                   H  n[        R                  " U5      (       a  [        R                  " S5      e[        R                  " U5      (       a+  XS;   a&  Xx   R                  U5        UR                  U5          OP[        R                   " U5      (       d  M  UR#                  5        H  nX;  d  M
  U	R                  U5        M     M     U	(       a  GM  GM'     U$ )NT)reversezBunsupported control flow due to raise statements inside with block)r   r   itemsr-   r	   is_setup_withr   is_pop_blockr   	topo_sortr<   r   is_raiser   r  removeis_terminatorr   )r7   r$   
sus_setupssus_popslabelrf   r  setup_with_to_pop_blocks_mapsetup_blockto_visitseents               r   find_ranges$find_setupwiths.<locals>.find_ranges  s   %f-"uceH #LLNLE

))$//NN5)((..LL'	 # + (33'7$==T=BKdOOK(( E""M..D((.."("6"6!?#" "
  ,,T22u7H4AEEeL .  --d33!%!1!1!3A } ( 2 "4' / (	 C@ ,+r'   r   r   zlunsupported control flow: with-context contains branches (i.e. break/return/raise) that can leave the block )r7   consolidate_multi_exit_withsr,  r   r   r   r   r   r  r	   	is_return_rewrite_return_eliminate_nested_withs)
r   r;  r7   with_ranges_dictspwith_ranges_tupler   targetstarget_blocks
             r   r   r     so   
0,d ^^F #6* ++;WMG ,11353! T!WQZ3  5 $)&&224w<1&&F  $ $ygnn''335a8::D*F FG'	 $ (9:'8Va ^^A.99EEGJK'8  : 00AB%%55(:s   E7Ec                 l   U R                   U   nUR                  R                  5       S   nU R                   U   n[        R                  " U R                   5      nUS-   nUR
                  n[        R                  " SUS9n[        R                  " XS9n	/ / p/ UR                  [        R                  5      Qn[        U5      S:X  d   e[        / UR                  [        R                  5      Q5      S:X  d   e[        UR                  S   [        R                  5      (       d   eUS   nUR                  R                  U5      nU
R!                  UR                  SU 5        U
R#                  [        R                  " X2R
                  5      5        UR!                  UR                  US 5        UR#                  [        R                  " XbR
                  5      5        U R                   U   R                  nU	R                  R!                  U5        UR                  R%                  5         UR                  R!                  U5        UR                  R%                  5         UR                  R!                  U
5        XR                   U'   [        R&                  " U R                   5      U l        U $ )u  Rewrite a return block inside a with statement.

Arguments
---------

func_ir: Function IR
  the CFG to transform
target_block_label: int
  the block index/label of the block containing the POP_BLOCK statement


This implements a CFG transformation to insert a block between two other
blocks.

The input situation is:

┌───────────────┐
│   top         │
│   POP_BLOCK   │
│   bottom      │
└───────┬───────┘
        │
┌───────▼───────┐
│               │
│    RETURN     │
│               │
└───────────────┘

If such a pattern is detected in IR, it means there is a `return` statement
within a `with` context. The basic idea is to rewrite the CFG as follows:

┌───────────────┐
│   top         │
│   POP_BLOCK   │
│               │
└───────┬───────┘
        │
┌───────▼───────┐
│               │
│     bottom    │
│               │
└───────┬───────┘
        │
┌───────▼───────┐
│               │
│    RETURN     │
│               │
└───────────────┘

We split the block that contains the `POP_BLOCK` statement into two blocks.
Everything from the beginning of the block up to and including the
`POP_BLOCK` statement is considered the 'top' and everything below is
considered 'bottom'. Finally the jump statements are re-wired to make sure
the CFG remains valid.

r   r   Nr  r   )r7   r   r   r	   find_max_labelr_   r   Scoperc   
find_instsPopBlockr   r   r0   r-   indexr   r<   clearbuild_definitions_definitions)r   target_block_labelrF  target_block_successor_labeltarget_block_successor	max_label	new_labelnew_block_locnew_block_scope	new_blocktop_bodybottom_body
pop_blocks	pb_markerpb_isreturn_bodys                   r   r?  r?  s  s/   t >>"45L#/#:#:#F#F#H#K $^^,HI ''7IAI*..Mhht7O<I k8<**2;;78Jz?a2((123q888l''+RWW55551I##I.EOOL%%fu-.OOBGG8:J:JKL|((r23rwwy*:*:;< ..!=>CCKNN+&%%'&&{3X& !*NN9#55gnnEGNr'   c                 |    / nS n[        U 5       H'  u  p4U" X4U5      (       a  M  UR                  X445        M)     U$ )Nc                 6    U H  u  p4X:  d  M  X:  d  M    g   g)NTFr   )startendknown_rangesabs        r   within_known_range3_eliminate_nested_withs.<locals>.within_known_range  s!     DA ySW ! r'   )rC   r<   )with_rangesrb  re  rB  es        r   r@  r@    sD    L {#!!55' $ r'   r   c                     U  H7  nX   n[        U5      S:  d  M  [        X$[        R                  S9u  p%U1X'   M9     U$ )zGModify the FunctionIR to merge the exit blocks of with constructs.
    r   split_condition)r   r   r	   r.  )r   r7   r   r!   rN   commons         r   r=  r=    sI     8r7Q;4X-B-BOG xEH  Nr'   rj  c                   U R                   n[        U R                   R                  5       5      nUR                  n[	        U R                   5      S-   n[
        R                  " UR                  [
        R                  S9nUnUS-  nXsU'   [
        R                  " UR                  [
        R                  S9n	Un
US-  nXU
'   / n[        U5       GH  u  pX=   nUb/  [        UR                  5       H  u  nnU" U5      (       d  M    O   OSnUR                  SW nUR                  US nUR                  U5        UUl	        UR                  nUR                  R                  [
        R                  " [
        R                  " UUS9UR                  SUS9US95        UR                  (       a   eUR                  R                  [
        R                   " U[
        R                  S95        GM"     Ub!  UR                  R                  US   S   5        UR                  (       a   eUR                  R                  [
        R                   " U
WS95        / nU H  nUR                  U5        US-  nM     U	n[
        R                  n[        U5       GH8  u  nnUR#                  SUS9nUR#                  S	US9nUR                  R                  [
        R                  " [
        R                  " UUS9UUS95        UR                  R                  [
        R                  " [
        R$                  R'                  [(        R*                  UR-                  S5      UUS
9UUS95        US   R/                  5       u  nUR                  R                  [
        R0                  " UUUU   US95        [
        R                  " UUS9nUUUU   '   GM;     UR                  R                  [
        R                   " WUS95        X4$ )a  Modify the FunctionIR to create a single common exit node given the
original exit nodes.

Parameters
----------
func_ir :
    The FunctionIR. Mutated inplace.
exit_nodes :
    The original exit nodes. A sequence of block keys.
split_condition : callable or None
    If not None, it is a callable with the signature
    `split_condition(statement)` that determines if the `statement` is the
    splitting point (e.g. `POP_BLOCK`) in an exit node.
    If it's None, the exit node is not split.
r   r  Nr   z$cp)r2   r   r_   r   z	$cp_checkz$cp_rhs)fnlhsrhsr_   r]   )r7   ri   rA   r^   r   r   rc   unknown_loc	enumerater-   r<   r_   r1   Constget_or_defineis_terminatedr   redefiner  binopoperatoreqgetr   r   )r   
exit_nodesrk  r7   any_blkr^   rS  common_blockcommon_label
post_block
post_label
remainingsir!   r5   ptr  beforeafterr_   remain_blocksr   switch_block
match_expr	match_rhsjump_targets                             r   r   r     sx   h ^^F'..'')*GMMEGNN#a'I88GMMr~~>LLNI'<'--R^^<JJNI#: J*%i &%chh/D"4(( 0
 B#2%  ggIIBHHQC0"00C0@	
 $$$$"..AB5 &8 "  Aq!12))))RWWZS9: MY'Q	  L
..Cz*	6^^KS^9
NN9#N6	 	  IIhhqc* 	
 	  IIggmm{{		%(8i $  "		
 r
..0  IIj+}Q/?SI	
 xxe5#/}Q ? +D RWW[c:;  r'   )*__doc__collectionsr   r   loggingrx  numba.core.analysisr   r   r   r   r   r	   r
   numba.core.utilsr   r   	getLogger__name__r   r>   rP   rU   r[   rg   ro   r   r   r   r   r   r   r   r   r   r   r   r?  r@  r   r=  r   r   r'   r   <module>r     s   
 0   M + + I 5 

H
%2j8 -DFB$*,^.$8CL48v6
r6([&|hV"
 
 DH V!r'   