
    xKgm                         d Z ddlZddlmZ ddlmZmZ ddlmZ ddl	m
Z
mZmZmZ ddlmZ  ed	d
      Zi Zd Zd Z edd      Zd Zd Zd Zd Zd Z edd      Zd Zd Zd Zi Zd Zy)z
Utils for IR analysis
    N)reduce)
namedtupledefaultdict   )CFGraph)typeserrorsirconsts)specialuse_defs_resultzusemap,defmapc           	      T   i }i }| j                         D ]  \  }}t               x||<   }t               x||<   }|j                  D ]  }t        |      t        v rt        t        |         } ||||       2t        |t        j                        rEt        |j                  t        j                        r+t        d |j                  j                         D              }	nt        |j                  t        j                        r!t        |j                  j                  g      }	ntt        |j                  t        j                  t        j                  t        j                  t        j                   f      rd}	nt#        dt        |j                              |j$                  j                  |	vr%|j'                  |j$                  j                         |j                         D ],  }
|
j                  |vs|j'                  |
j                         .   t)        ||      S )z*
    Find variable use/def per block.
    c              3   4   K   | ]  }|j                     y wNname).0vars     W/home/alanp/www/video.onchill/myenv/lib/python3.12/site-packages/numba/core/analysis.py	<genexpr>z#compute_use_defs.<locals>.<genexpr>(   s     !M6Ls#((6L    unreachable)usemapdefmap)itemssetbodytypeir_extension_usedefs
isinstancer
   AssignvalueInst	list_varsVarr   ArgConstGlobalFreeVarAssertionErrortargetadd_use_defs_result)blocksvar_use_mapvar_def_mapoffsetir_blockuse_setdef_setstmtfuncrhs_setr   s              r   compute_use_defsr9      s   
 KK"LLN(+-Fg(+-FgMMDDz11+DJ7T7G,$		*djj"''2!!Mdjj6J6J6L!MMG

BFF3!4::??"34G

RVVRXXryy-/ZZ-9 : G(TZZ8HII;;##72KK 0 01~~'887*KK) (' " +6 ;{CC    c                     	
 d 

fd} fd} 	fd}i }|j                         D ]  }t        |         ||<    t        t              	 ||	        |||       |S )z
    Find variables that must be alive at the ENTRY of each block.
    We use a simple fix-point algorithm that iterates until the set of
    live variables is unchanged for each block.
    c                 B    t        d | j                         D              S )zFHelper function to determine if a fix-point has been reached.
        c              3   2   K   | ]  }t        |        y wr   )lenr   vs     r   r   z?compute_live_map.<locals>.fix_point_progress.<locals>.<genexpr>E   s     2\SV\s   )tuplevalues)dcts    r   fix_point_progressz,compute_live_map.<locals>.fix_point_progressB   s     2SZZ\222r:   c                 V    d} |      }||k7  r | |       |} |      }||k7  ryy)z4Helper function to run fix-point algorithm.
        Nr   )fnrC   	old_point	new_pointrD   s       r   	fix_pointz#compute_live_map.<locals>.fix_pointG   s<     	&s+	9$sG!I*3/I 9$r:   c                     D ]C  }|   |   z  }| |xx   |z  cc<   j                  |      D ]  \  }}| |xx   | |   z  cc<    E y)zGFind all variable definition reachable at the entry of a block
        N)
successors)rC   r2   used_or_definedout_blk_cfgr1   r0   s        r   	def_reachz#compute_live_map.<locals>.def_reachQ   sZ     "F)&1K4GGOK?*K!nnV4
GF+ 5	 "r:   c                     | D ];  }| |   }j                  |      D ]   \  }}||   z  }| |xx   ||   z
  z  cc<   " = y)z?Find live variables.

        Push var usage backward.
        N)predecessors)	rC   r2   	live_varsinc_blk_data	reachablerO   def_reach_mapr1   s	         r   livenessz"compute_live_map.<locals>.liveness[   sX    
 FFI"%"2"26":%g(>>	G	K,@ @@	 #; r:   )keysr   r   )rO   r/   r0   r1   rI   rP   rX   live_mapr2   rW   rD   s   ` ``     @@r   compute_live_mapr[   <   sh    3
0,A H++-{623    $Mi'h!Or:   dead_maps_resultzinternal,escaping,combinedc                    t        t              t        t              t        t              }|j                         D ]  \  }}|   ||   z  }t        fd| j	                  |      D              }t        d |j
                  j                         D              }	t        t        j                  |j                         t                     }
|
|	z  }
||
z
  }||<   ||z
  }|j                         D ]  \  }}|||   z  }|xx   ||z
  z  cc<    |r|	||<    t        t        j                  j                         t                     }t        t        j                  j                         t                     }t        t        j                  j                         t                     }t        t        j                  |j                         t                     }||z  |z  }||z
  }|r-| j                         sndj                  |      }t        |      t        fd|D              }t        |      S )z
    Compute the end-of-live information for variables.
    `live_map` contains a mapping of block offset to all the living
    variables at the ENTRY of the block.
    c              3   2   K   | ]  \  }}||   f  y wr   r   )r   rM   rU   rZ   s      r   r   z$compute_dead_maps.<locals>.<genexpr>   s(      !O7M^We #*8G+<!=7Ms   c              3   4   K   | ]  }|j                     y wr   r   r?   s     r   r   z$compute_dead_maps.<locals>.<genexpr>   s      !K*IQ "#*Ir   z#liveness info missing for vars: {0}c              3   8   K   | ]  }||   |   z  f  y wr   r   )r   kescaping_dead_mapinternal_dead_maps     r   r   z$compute_dead_maps.<locals>.<genexpr>   s/      %# )!,/@/CCD#s   )internalescapingcombined)r   r   r   dictrK   
terminatorr%   r   operatoror_rB   exit_pointsformatRuntimeError_dead_maps_result)rO   r/   rZ   r1   exit_dead_mapr2   r3   cur_live_setoutgoing_live_mapterminator_livesetcombined_livesetinternal_setescaping_live_setrM   new_live_setall_varsinternal_dead_varsescaping_dead_varsexit_dead_vars	dead_varsmissing_varsmsgrf   rb   rc   s     `                    @@r   compute_dead_mapsr~   v   s4    $C(#C($M"LLN  '+f*==  !O7:~~f7M!O O ! !K*2*=*=*G*G*I!K K "(,,0A0H0H0J"%%) 	.. $&66$0&!(<7%6%<%<%>!G\'+g*>>Lg&*;l*JJ& &? !$6M&!; +@ hllHOO$5su=H.?.F.F.H #'.?.F.F.H #'HLL-*>*>*@#%HN#&88>IIi'L 7>>|LCs## %#% %H &7&7&.0 0r:   c                     t        t              fd}d} |       }||k7  rO|D ];  }|   ||   z  }|||   z  }| j                  |      D ]  \  }	}
|	xx   |z  cc<    = |} |       }||k7  rOS )z
    Compute the live variables at the beginning of each block
    and at each yield point.
    The ``var_def_map`` and ``var_dead_map`` indicates the variable defined
    and deleted at each block, respectively.
    c                  R    t        t        t         j                                     S r   )rA   mapr>   rB   )block_entry_varss   r   rD   z2compute_live_variables.<locals>.fix_point_progress   s    S.557899r:   N)r   r   rK   )rO   r/   r1   var_dead_maprD   rG   rH   r2   availsuccrU   r   s              @r   compute_live_variablesr      s     #3': I"$I y
  F$V,{6/BBE\&))E"~~f5e &%/&  6  	&(	 y
  r:   c                 4   t               }| D ]  }|j                  |        | j                         D ]8  \  }}|j                  }|j	                         D ]  }|j                  ||        : |j                  t        |              |j                          |S r   )	r   add_noder   rh   get_targetsadd_edgeset_entry_pointminprocess)r/   rO   ra   btermr,   s         r   compute_cfg_from_blocksr      s    
)CQ  1||&&(FLLF# ) 
 F$KKMJr:   c              #     K   t               }| j                         j                         D ]c  }t        |j                        t        |j                        z  t        |j
                        z  }|j                  |j                         ||z  }e | j                         j                         D ]  }|j                  |vst        | |       ! yw)zK
    A generator that yields toplevel loops given a control-flow-graph
    N)	r   loopsrB   r   entriesexitsdiscardheader_fix_loop_exit)rO   blocks_in_looploopinsiderss       r   find_top_level_loopsr      s      UN		""$tyy>C$55DJJG%(" %
 		""$;;n, d++ %s   B>CCc                    | j                         }t        t        j                  |j                  D cg c]  }||   	 c}|j                        }|r/|j
                  |j                  |z
  z  }|j                  ||      S |S c c}w )zg
    Fixes loop.exits for Py3.8+ bytecode CFG changes.
    This is to handle `break` inside loops.
    )r   r   )post_dominatorsr   ri   and_r   r   _replace)rO   r   postdomsr   r   r   s         r   r   r   
  s}     ""$H"jj)j!j)

E
 yy4::--}}5t}44 	*s   B
	nullifiedz!condition, taken_br, rewrite_stmtc                   +,-./0 ddl m/m0m}m} d+/0fd}-fd.+.fd}+.fd}+.fd} G d d	t
              ,,fd
}+dkD  r4t        dj                  dd             t        | j                                t               }	t               }
| j                  j                         D ]  \  }}|j                  D ]z  }t        |t        j                        st        |j                   t        j"                        sC|j                   j$                  dk(  s]||	|j                   <   ||
|j                   <   |   ||       }g }|D ]  \  -}}g }t        |t        j"                        r|j$                  dk(  r|}|j&                  |j(                  fD ]  } ,       } 0/| |      }t        |t        j*                        r ||j,                        }|}n!	  || |      }|t/        j0                  d      }t        |,      rq|j3                  |        t5        |      dk(  s |-||g| \  }}|s|j3                  t7        ||d              ,       }	  /| -j8                        } || |j:                  d         }|t/        j0                  d      }t        |,      re |-||      \  }}|sv|j3                  t7        ||d              |D cg c]  }|j<                   }}|D ]  \  }}}||v s|j                  D ]  }t        |t        j                        s|j                   |u s-||j-                  |         }|j>                  sN|j@                  }t        jB                  ||jD                        |_        | jF                  |jH                  jJ                     }|j-                  |      } |j                   || <     tM        | j                        }!|!jO                         }"|	j                         D ]O  \  }#}||"v r|!jQ                  |      D cg c]  }|d   	 }$}tS        |$      tS        |#jT                        k7  sOt5        |$      dk(  r6|#jT                  j-                  |$d         }%|#jV                  |%   |
|#   _        g }&g }'tY        |#jV                  |#jT                        D ],  \  }(})|)|"v r|&j3                  |(       |'j3                  |)       . |#jV                  j[                          |#jV                  j]                  |&       |#jT                  j[                          |#jT                  j]                  |'       R |"D ]  }*| j                  |*=  |rt_        j`                  |       | _1        +dkD  r5t        dj                  dd             t        | j                                yy# |$ r Y w xY w# |$ r Y ?w xY wc c}w c c}w )z
    Removes dead branches based on constant inference from function args.
    This directly mutates the IR.

    func_ir is the IR
    called_args are the actual arguments with which the function is called
    r   )get_definitionguard
find_constGuardExceptionc                    g }| j                   j                         D ]  }|j                  d   }t        |t        j
                        s-|} 	| |j                  j                        }|Pt        |dd       dk(  sa 	| |j                        }|xt        |t        j                        s|j                  t        u s 	| |j                  d         }||j                  |||f        |S )Nopcallr   )r/   rB   r   r!   r
   Branchcondr   getattrr7   r)   r#   boolargsappend)
func_irbranchesblkbranch_or_jumpbranchpredfunction	conditionr   r   s
           r   find_branchesz(dead_branch_prune.<locals>.find_branches0  s    >>((*C XXb\N."))4'^Wfkk6F6FG#dD(AV(K$^WdiiHH ,"8RYY7$NNd2$).'499Q<$P	$0$OOVY,DE + r:   c                     | rj                   nj                  }t        j                  |j                        }||j
                  d<   |j                   k(  rdS dS )Nlocr   r   r   )truebrfalsebrr
   Jumpr   r   )take_truebrr   keepjmpr   s       r   do_prunez#dead_branch_prune.<locals>.do_pruneB  sK     +v}}ggd

+FMM)q0q0r:   c                 T   |\  }}t        |t        j                        }t        |t        j                        }|s|r[	 |j                  ||      }dkD  r6|r| j
                  n| j                  }	t        d|	z  | |||j                          ||      }
d|
fS y# t        $ r Y yw xY wNFNr   
Pruning %sT)r!   r   NoneTyperF   	Exceptionr   r   print)r   r   r   condslhs_condrhs_condlhs_nonerhs_noner   killtakenDEBUGr   s              r   prune_by_typez(dead_branch_prune.<locals>.prune_by_typeI  s     #(h7h7x#'ll8X> qy)4v~~&--lT)68Xll$[#.E;  #"#s    B 	B'&B'c                     |\  }}	 |j                  ||      }	dkD  r6|r| j                  n| j                  }t	        d|z  | |||j                           
||      }d|fS # t        $ r Y yw xY wr   )rF   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   s            r   prune_by_valuez)dead_branch_prune.<locals>.prune_by_value\  s    "(	#,,x:K 19%06>>fmmD,%vx9<<Pc*U{  		s   A" "	A.-A.c                 N   	 t        |t        j                  t        j                  t        j                  f      st        d      t        |j                        }dkD  r*|r| j                  n| j                  }t        d|z  | |        ||      }d|fS # t
        $ r Y yw xY w)NzExpected constant Numba IR noder   r   r   T)r!   r
   r(   r*   r)   	TypeErrorr   r#   r   r   r   )r   r   r   r   r   r   r   r   s         r   prune_by_predicatez-dead_branch_prune.<locals>.prune_by_predicateh  s    	 dRXXrzz299$EF ABBtzz*K 19%06>>fmmD,%vt4c*U{  		s   AB 	B$#B$c                       e Zd Zy)"dead_branch_prune.<locals>.UnknownN)__name__
__module____qualname__r   r:   r   Unknownr   w  s    r:   r   c                    |    }t        |t        j                        r|S t        |t        j                        r?|j                  }t        |t        j                        r|S |t        j                  d      S t        |d              S )zC
        Resolves an input arg to a constant (if possible)
        noneliteral_type)r!   r   r   Omittedr#   r   )input_arg_idxinput_arg_tyvalr   called_argss      r   resolve_input_arg_constz2dead_branch_prune.<locals>.resolve_input_arg_constz  sz     #=1 lENN3 lEMM2$$C#u~~.
~~f--
 |^WY??r:   r   beforeP   -phibinopNr      TFr   after)2numba.core.ir_utilsr   r   r   r   objectr   centerdumprg   r/   r   r   r!   r
   r"   r#   Exprr   lhsrhsr'   indexr   r   r   r>   r   r   r   r   rewrite_stmttaken_brr(   r   _definitionsr,   r   r   
dead_nodesrR   r   incoming_blocksincoming_valueszipclearextendr   ConstantInference_consts)1r   r   r   r   r   r   r   r   r   phi2lblphi2asgnlblr   r6   branch_infonullified_conditionsr   const_condspruneargresolved_constarg_def
prune_statr   	pred_callxdeadcondrN   r   nullified_info
branch_bitdefnsrepl_idxnew_cfgdead_blocksr   new_incomingidx
ic_val_tmp
ic_blk_tmpic_valic_blkdeadr   r   r   r   r   r   s1    `                                         @@@@@@r   dead_branch_pruner  #  sK   5 5 E$1&
& @. qyhoob#&'gllnfGvHNN((*SHHD$		*djj"''2tzz}}7M*-GDJJ'+/HTZZ(	  +  (K"-	3i)illg.E"E!y}}5!(=grvv.%<W]]%KN)E)3GS)A)1-2^^F-CN ".':&&~6% 6* ;1$$)&)S$O;$O!
E(//	)U:>1@ A %YN*7FKK@	!+GY^^A5F!G!)%*^^F%;N ng6$6vy#$N!
E(//	)U:?1A B_ #.B &::%9%9H:#48XXa+4%9(..:N%ON &22%3%<%<
"$((:155"A ' 4 4QXX]] C#(;;t#4*+''h  $^ &gnn5G$$&K MMOS+&-&:&:3&?@&?!&?@|C$7$7 88< A% ))//Q@&)&9&9#&>#  

&)#*=*=*-*=*='?NFF, "))&1"))&1'? ##))+##**:6##))+##**:65 $: NN4    227;qygnnR%&glln O * , " 2 ;n As1    W#A W%W&/W+WWW#"W#c                   	
 d}|dkD  r]t        d| j                  j                  z   j                  dd             t        dj                  dd             | j	                          
fd	fd	}	fd
}ddlmm | j                  j                         D ]i  }|j                  D ]X  	t        	t        j                        s	j                  
t        
t        j                        sE |
| |        |
| |       Z k |dkD  r7t        dj                  dd             | j	                          t        d       yy)aP  
    This rewrites values known to be constant by their semantics as ir.Const
    nodes, this is to give branch pruning the best chance possible of killing
    branches. An example might be rewriting len(tuple) as the literal length.

    func_ir is the IR
    called_args are the actual arguments with which the function is called
    r   r   zrewrite_semantic_constants: r   r   r   *c                     t        j                  ||j                        |_        | j                  |j
                  j                     }|j                        }|j                  ||<   y)zr
        Rewrites the stmt as a ir.Const new_val and fixes up the entries in
        func_ir._definitions
        N)r
   r(   r   r#   r   r,   r   r   )r   r6   new_valr  r  r   s        r   rewrite_statementz5rewrite_semantic_constants.<locals>.rewrite_statementU  sP    
 XXgtxx0
$$T[[%5%56;;s#**hr:   c                 "   t        | dd       dk(  r~| j                  dk(  rn || j                        }t        |t        j
                        r?||j                     }t        |t        j                        r ||j                         y y y y y )Nr   r   ndim)
r   attrr#   r!   r
   r'   r   r   Arrayr$  )	r   r   r   r  argtyr   r   r"  r6   s	        r   rewrite_array_ndimz6rewrite_semantic_constants.<locals>.rewrite_array_ndim_  s    3d#y0xx6!Cgrvv.'6E!%5)'4D 6 / " 1r:   c                 f   t        | dd       dk(  r || j                        }|t        |t        j                        rt        |dd       t
        u r| j                  \  } ||      }t        |t        j                        r?||j                     }t        |t        j                        r 	|
|j                         y y t        |t        j                        rL|j                  dk(  r<|j                  }t        |t        j                        r 	|
|j                         y y y y y y y y )Nr   r   r#   typed_getitem)r   r7   r!   r
   r)   r>   r   r'   r   r   	BaseTuplecountr   r   dtype)r   r   r   r7   r	  r  r'  r   r   r"  r6   s          r   rewrite_tuple_lenz5rewrite_semantic_constants.<locals>.rewrite_tuple_leni  s   3d#v-#((;D Zbii%@D'40C7=grvv.'6E!%9)'4E : "''2jjO3#MME!%9)'4E : 4 3 8 &A  .r:   )r   r   r   zP--------------------------------------------------------------------------------N)r   func_id	func_namer   r   r   r   r   r/   rB   r   r!   r
   r"   r#   r   )r   r   r   r(  r.  r   r   r   r"  r6   r   s         @@@@@r   rewrite_semantic_constantsr1  D  s     Eqy-(()*0&S/	;hoob#&'%EF& :~~$$&HHD$		*jjc277+&sG[A%c7K@  ' qygnnR%&h r:   c                    ddl m} t               }i }| j                  j	                         D ]  }|j                  d      D ]  }|j                  |j                  | |j                        }t        |t        j                  t        j                  f      r|j                  }n|j                  |j                  | |      }|t        j                   u s|j"                  \  }	| j                  |	      }
t        |
t        j$                        s|
j&                  }|j)                  |       |j+                  ||j,                            |D ]  }||   }t        |t.        j0                        xr |j2                  du }|r||   }t5        j6                  ||      t        |t.        j8                  t.        j0                  f      r{||   }t5        j6                  ||       y)a3  An analysis to find `numba.literally` call inside the given IR.
    When an unsatisfied literal typing request is found, a `ForceLiteralArg`
    exception is raised.

    Parameters
    ----------

    func_ir : numba.ir.FunctionIR

    argtypes : Sequence[numba.types.Type]
        The argument types.
    r   )ir_utilsr   )r   Nr   )
numba.corer3  r   r/   rB   
find_exprsr   r   r7   r!   r
   r)   r*   r#   resolve_func_from_moduler   	literallyr   r'   r   r-   
setdefaultr   r   InitialValueinitial_valuer	   ForceLiteralArgLiteral)r   argtypesr3  marked_args	first_locr   assignr   fnobjr	  defargargindexpos	query_argdo_raiser   s                   r   find_literally_callsrG    s    $%KI~~$$&nnn/F..!8!8'6;;OC#		2::67		 x'H'H'.5))) //4fbff-%||HOOH-((6::> 0 '" SM	y%*<*<= 4++t3 	C.C((#>>)emmU5G5G%HIC.C((#>> r:   c                     t               }| j                         D ]@  }|j                  D ]/  }t        |      t        v st        t        |         } |||       1 B |S )a  
    Analyzes a dictionary of blocks to find variables that must be
    stack allocated with alloca.  For each statement in the blocks,
    determine if that statement requires certain variables to be
    stack allocated.  This function uses the extension point
    ir_extension_use_alloca to allow other IR node types like parfors
    to register to be processed by this analysis function.  At the
    moment, parfors are the only IR node types that may require
    something to be stack allocated.
    )r   rB   r   r   ir_extension_use_alloca)r/   use_alloca_varsr3   r6   r7   s        r   must_use_allocarK    sY     eOMMOMMDDz44.tDz:T?+	 " $ r:   ) __doc__ri   	functoolsr   collectionsr   r   controlflowr   r4  r   r	   r
   r   
numba.miscr   r.   r    r9   r[   rn   r~   r   r   r   r   r   r  r1  rG  rI  rK  r   r:   r   <module>rQ     s      /   0 0  /A   "DJ4n 13OP E0P&Z, * {$GH	^B	DN-?`  r:   