B
     \                @   s  d dl mZmZ d dlZd dlZd dlZd dlZd dlm	Z
 d dlZd dlmZ d dlm	Z	mZmZmZmZmZmZmZ d dlmZmZmZ d dlmZ d dlmZmZmZ d d	lmZm Z  d dl!Z!d a"d
d Z#d a$dd Z%dd Z&dd Z'dd Z(dd Z)dd Z*dd Z+dd Z,dd Z-dd Z.d d! Z/d"d# Z0d$d% Z1d&d' Z2d(d) Z3d*d+ Z4i Z5d,d- Z6d.d/ Z7d0d1 Z8i Z9d2d3 Z:i Z;d4d5 Z<d6d7 Z=d8d9 Z>dd:d;Z?i Z@d<d= ZAg ZBd>d? ZCeBDeC d@dA ZEg ZFdBdC ZGi ZHi ZIddDdEZJdFdG ZKdHdI ZLdJdK ZMdLdM ZNi ZOdNdO ZPi ZQddPdQZRdRdS ZSddTdUZTddVdWZUi ZVddYdZZWi ZXdd[d\ZYd]d^ ZZd_d` Z[dadb Z\dcdddedfdgdhdidjdkdldmdndodpgZ]dqdr Z^i Z_ddsdtZ`dudv Zadwdx Zbdydz Zcd{d| ZdG d}d~ d~eeZfdd Zgdd Zhdd ZidddZji ZkdeifddZldd Zmdd ZndddZodd Zpdd Zqdd Zrdd Zsdd Ztdd Zudd Zvdd Zwdd Zxdd Zydd Zzdd Z{dd Z|dd Z}dd Z~dd ZdS )    )print_functionabsolute_importN)ir)exec_)r   typestypingconfiganalysisutilscgutilsrewrites)	signatureinfer_globalAbstractTemplate)impl_ret_untracked)compute_live_mapcompute_use_defscompute_cfg_from_blocks)TypingErrorUnsupportedErrorc             C   s   | d t t }td a|S )N.   )str_unique_var_count)prefixvar r   -lib/python3.7/site-packages/numba/ir_utils.pymk_unique_var   s    r   c             C   s.   d}x$| t | }||kr|S |d7 }qW dS )zl Get a new var name with a given prefix and
        make sure it is unused in the given variable table.
    r   r   N)r   )r   	var_tableZcurr   r   r   r   get_unused_var_name&   s    r    c               C   s   t d7 a t S )Nr   )
_max_labelr   r   r   r   
next_label2   s    r"   c                s  g d}t j}t|trt|dkr>|d }t| }nt|}ttd }	rrt j	
t j||	j<  fdd|D }
tj|
 }t||	 }| |	}t j	
t j|}ttd }rt jt|j< tdt }t|| }tj|d }ttd	 }r@ttj|j< t|| }ttd
 }rxt j||j< t|}|dkrd}tj|| }t|| }tj|||gd }|r|j t |t j|gi ||< t|| }||||g S )zgenerate an array allocation with np.empty() and return list of nodes.
    size_var can be an int variable or tuple of int variables.
    r   r   z
$tuple_varc                s   g | ]}t | qS r   )convert_size_to_var).0s)locoutscopetypemapr   r   
<listcomp>K   s   zmk_alloc.<locals>.<listcomp>z	$np_g_varnpemptyz$empty_attr_attrz$np_typ_varboolZbool_r   )r   intp
isinstancetuplelenr#   r   Varr   
containersZUniTuplenameExprbuild_tupleAssignappendmiscModulenumpyGlobalgetattrget_np_ufunc_typr,   Z	functionsZNumberClassr   callget_call_typer   Contextextend)r)   	calltypeslhssize_vardtyper(   r&   ZndimsZsize_typZ	tuple_varZ	new_sizesZ
tuple_callZtuple_assigng_np_varg_npg_np_assignZempty_attr_callattr_varattr_assignZtyp_varZ	dtype_strZnp_typ_getattrZtyp_var_assignZ
alloc_callZalloc_assignr   )r&   r'   r(   r)   r   mk_alloc8   sX    



rL   c             C   sd   t | trPt|td|}|r,tj||j< tt	| |||}|
| |S t | tjs`t| S )Nz$alloc_size)r/   intr   r2   r   r   r.   r4   r7   Constr8   AssertionError)rE   r)   r(   r&   nodesZnew_sizeZsize_assignr   r   r   r#   v   s    

r#   c             C   s4   x"t jjjD ]\}}|| kr|S qW td| ddS )z7get type of the incoming function from builtin registryztype for func z
 not foundN)r   ZnpydeclregistryglobalsRuntimeError)funckvr   r   r   r>      s    r>   c             C   sx  t |td|}tt| |j< t dt|}t |||}	t| |||||\}
}t j	
||d|}| |j t tjgt| i ||< t |td|}tjtj| |j< t |||}t j	||}ttjtj||< t |td|}tjtj| |j< t |||}t |td|}tjtj| |j< t |||}t d|}t ||}|
|	||||g |_|S )zpmake a block that initializes loop range and iteration variables.
    target label in jump needs to be set.
    z$range_g_varranger   z$range_c_varz	$iter_varz$phi)r   r2   r   get_global_func_typrW   r4   r<   r7   _mk_range_argsr5   r?   r@   r   rA   r   r.   r1   	iterators	RangeTypegetiterr   range_iter64_typeZrange_state64_typeZRangeIteratorTypeJumpBlockbody)r)   startstopsteprC   r(   r&   Zg_range_varZg_rangeZg_range_assignZ	arg_nodesargsZ
range_callZrange_call_varZrange_call_assignZ	iter_callZiter_varZiter_call_assignphi_varZ
phi_assignZjump_headerZrange_blockr   r   r   mk_range_block   s2    
rg   c             C   sl  g }t |tjr|}nPt |ts$tt|td|}| rFtj| |j< t	t
||||}|| |dkr|dkr||gfS t |tjr|}	nPt |tstt|td|}	| rtj| |	j< t	t
|||	|}
||
 |dkr||	|gfS t |tjr
|}nTt |tstt|td|}| r>tj| |j< t	t
||||}|| ||	||gfS )Nz$range_stopr   r   z$range_startz$range_step)r/   r   r2   rM   rO   r   r   r.   r4   r7   rN   r8   )r)   rb   rc   rd   r(   r&   rP   Z
g_stop_varZstop_assignZg_start_varZstart_assignZ
g_step_varZstep_assignr   r   r   rZ      s<    



rZ   c             C   s6   x"t jjjD ]\}}|| kr|S qW td| dS )z2get type variable for func() from builtin registryzfunc type not found {}N)r   Z	templatesZbuiltin_registryrR   rS   format)rT   rU   rV   r   r   r   rY      s    rY   c             C   s4  t |td|}tjtjtj| |j< t j	
||}ttjtjtjtj||< t |||}t |td|}tj| |j< t j	||}	t |	||}
t |td|}tj| |j< t j	||}t |||}t |td|}tj| |j< t |||}t |dd|}t ||}||
|||g|_|S )zqmake a block that is a loop header updating iteration variables.
    target labels in branch need to be set.
    z$iternext_varz$pair_first_varz$pair_second_varz$phirX   )r   r2   r   r   r3   ZPairr.   Zbooleanr4   r5   iternextr   r^   r7   
pair_firstZpair_secondBranchr`   ra   )r)   rf   rC   r(   r&   Ziternext_varZiternext_callZiternext_assignZpair_first_varZpair_first_callZpair_first_assignZpair_second_varZpair_second_callZpair_second_assignZ	phi_b_varZphi_b_assignbranchZheader_blockr   r   r   mk_loop_header   s4    rm   c             C   sF   i }x<| D ]4}| dd dd dd}||ks6t|||< q
W |S )zXreturns a dictionary for conversion of variable names to legal
    parameter names.
    ___$r   )replacerO   )ZvarnamesZvar_mapr   new_namer   r   r   legalize_names  s    
rs   c             C   s   dd }i }t | || |S )z<create a mapping from variable names to their ir.Var objectsc             S   s   | || j < | S )N)r4   )r   namevarr   r   r   get_name_var_visit  s    
z.get_name_var_table.<locals>.get_name_var_visit)
visit_vars)blocksru   rt   r   r   r   get_name_var_table  s    rx   c             C   sB   i }x$|  D ]\}}||kr|||< qW dd }t| || dS )zCreplace variables (ir.Var to ir.Var) from dictionary (name -> name)c             S   s<   t | tjstx&| j|kr6t| j|| j | j} qW | S )N)r/   r   r2   rO   r4   r(   r&   )r   namedictr   r   r   replace_name!  s    z'replace_var_names.<locals>.replace_nameN)itemsrv   )rw   ry   Znew_namedictlrrz   r   r   r   replace_var_names  s    r~   c             C   sF   t | tjstx0| j| kr@|| j }t|j|j|j} qW | S )N)r/   r   r2   rO   r4   keysr(   r&   )r   vardictZnew_varr   r   r   replace_var_callback)  s
    
r   c             C   s<   i }x&|  D ]\}}||jkr|||< qW t| t| dS )zEreplace variables (ir.Var to ir.Var) from dictionary (name -> ir.Var)N)r{   r4   rv   r   )rw   r   Znew_vardictr|   r}   r   r   r   replace_vars1  s
    
r   c             C   s   t | t| d S )N)visit_vars_stmtr   )stmtr   r   r   r   replace_vars_stmt;  s    r   c             C   s   t | t|S )N)visit_vars_innerr   )noder   r   r   r   replace_vars_inner?  s    r   c             C   s2   x,|   D ] }x|jD ]}t||| qW q
W dS )zWgo over statements of block bodies and replace variable names with
    dictionary.
    N)valuesra   r   )rw   callbackcbdatablockr   r   r   r   rv   H  s    rv   c                s  x.t  D ]"\}}t| |r
||   d S q
W t| tjr`t| j | _t| j | _n$t| tjrt| j	 | _	nt| tj
rt| j | _nt| tjrt| j | _nt| tjrt| j | _nt| tjrt| j | _nt| tjr:td | j| j}t| }|j	| _nJt| tjrlt| j | _t| j | _nt| tjrt| j | _t| j | _t| j | _nt| tjrt| j | _t| j | _nt| tjrt| j | _t| j | _t| j | _nht| tjr\t| j | _t| j | _t| j | _n(t| tjr fdd| jD | _n d S )Nc                s   g | ]}t | qS r   )r   )r$   x)r   r   r   r   r*   ~  s    z#visit_vars_stmt.<locals>.<listcomp>)visit_vars_extensionsr{   r/   r   r7   r   targetvalueArgr4   ReturnZRaiseZ	exceptionrk   condr_   Delr2   r&   ZDelAttrattrZSetAttrZDelItemindexStaticSetItem	index_varSetItemZPrintre   )r   r   r   tfr   r   )r   r   r   r   R  sT    
r   c                s   t | tjr | S t | tr4 fdd| D S t | trVt fdd| D S t | tjrx*| j D ]}t| j|  | j|< qnW | S )Nc                s   g | ]}t | qS r   )r   )r$   n)r   r   r   r   r*     s    z$visit_vars_inner.<locals>.<listcomp>c                s   g | ]}t | qS r   )r   )r$   r   )r   r   r   r   r*     s    )	r/   r   r2   listr0   r5   Z_kwsr   r   )r   r   r   argr   )r   r   r   r     s    


r   c       
      C   s   i }x|   D ]\}}d}|jrd|jd }x8|jD ].}x(t  D ]\}}t||r@|||}	q@W q2W t|tjrt|j| |j|jd< t|tjrt|j	|j
| |j| |j|jd< |||| < qW |S )z>add an offset to all block labels and jump/branch targets
    NrX   )r{   ra   add_offset_to_labels_extensionsr/   r   r_   r   r&   rk   r   truebrfalsebr)
rw   offset
new_blocksr|   bterminstTr   f_maxr   r   r   add_offset_to_labels  s     

r   c       	      C   s   d}xx|   D ]l\}}d }|jrn|jd }xB|jD ]8}x2t  D ]&\}}t||r@||}||kr@|}q@W q2W ||kr|}qW |S )Nr   rX   )r{   ra   find_max_label_extensionsr/   )	rw   	max_labelr|   r   r   r   r   r   r   r   r   r   find_max_label  s    

r   c             C   sF   x@|   D ]4}g }x$|jD ]}t|tjs|| qW ||_q
W dS )zremove ir.Del nodesN)r   ra   r/   r   r   r8   )rw   r   new_bodyr   r   r   r   remove_dels  s    
r   c             C   sV   xP|   D ]D}g }x4|jD ]*}t|tjr:t|jtjr:q|| qW ||_q
W dS )zremove ir.Arg nodesN)r   ra   r/   r   r7   r   r   r8   )rw   r   r   r   r   r   r   remove_args  s    
r   c             C   s   t | }t| }t|| |j|j}t| \}	}
|dks>|dkrPt| |||\}}tjdkrdt	d| t
| }d}xf|  D ]Z\}}dd |j D }x"||D ]\}}||| O }qW |t|||	|||||O }q~W |S )zdead code elimination using liveness and CFG info.
    Returns True if something has been removed, or False if nothing is removed.
    Nr   z
alias map:Fc             S   s   h | ]
}|j qS r   )r4   )r$   rV   r   r   r   	<setcomp>  s    zremove_dead.<locals>.<setcomp>)r   r   r   ZusemapZdefmapget_call_tablefind_potential_aliasesr   DEBUG_ARRAY_OPTprintsetr   r{   
terminator	list_vars
successorsremove_dead_block)rw   re   func_irr)   	alias_maparg_aliasescfgZusedefsZlive_map
call_tablern   	alias_setremovedlabelr   livesZout_blk_datar   r   r   remove_dead  s$    


r   c             C   s  d}| j g}	xrt| jdd D ]Z}
t }||@ }x|D ]}||| O }q<W ||B |B }t|
tkrtt|
 }||
|||||}
|
dkrd}q"t|
tjr|
j	}|
j
}|j|krt|||rd}q"t|tjr|j|jkrd}q"t|
tjr|
j	j}||krq"t|
tjkrDtjt|
 }||
\}}||8 }||O }n0|dd |
 D O }t|
tjrt||j |	|
 q"W |	  |	| _|S )zremove dead code using liveness info.
    Mutable arguments (e.g. arrays) that are not definitely assigned are live
    after return of function.
    FNrX   Tc             S   s   h | ]
}|j qS r   )r4   )r$   rV   r   r   r   r   .  s    z$remove_dead_block.<locals>.<setcomp>)r   reversedra   r   typeremove_dead_extensionsr/   r   r7   r   r   r4   has_no_side_effectr2   r   r	   Zir_extension_usedefsr   remover8   reverse)r   r   r   r   r   r   r   r)   r   r   r   Zalias_livesZinit_alias_livesrV   Zlives_n_aliasesr   rD   rhsr4   Zdef_funcZusesZdefsr   r   r   r     sP    



r   c             C   s0   t |dkr,|dd  dtgkr,|d dkS dS )N   r   randomr   >   seedshuffleF)r1   r;   )r   r   	call_listr   r   r   remove_dead_random_call:  s     r   c       	      C   s|  t | tjr"| jdkr"| jj}||ks6|| g kr:dS || }|dtgks|tgks|dtgks|dtgks|dtgks|tj	j
gkrdS t |d tjjr|d jd	ks|d jd
krdS ddlm} ddlm} t |d |r|d j}||krdS x tD ]}|| ||rdS qW dS t | tjrH| jdkrH| jj|kS t | tjrZdS t | tjrx| jdkrxdS dS )za Returns True if this expression has no side effects that
        would prevent re-ordering.
    r?   Fr,   ZstencillogrF   Tr   Zempty_inferredZunsafe_empty_inferred)CPUDispatcher)dot_3_mv_check_argsinplace_binoprj   )r/   r   r5   oprT   r4   r;   slicenumbaZarray_analysisZ
wrap_index	extending
_Intrinsic_nameZnumba.targets.registryr   Znumba.targets.linalgr   py_funcremove_call_handlersrD   Yield)	r   r   r   	func_namer   r   r   r   r   r   r   r   r   A  sB    



r   c             C   s   t | tjr| jdkr| jj}||ks2|| g kr6dS || }|tgks`|dtgks`|dtgkrddS xtD ]}|| ||rjdS qjW dS | jdks| jdkrdS t | tj	rdS dS )z Returns True if every time this expression is evaluated it
        returns the same result.  This is not the case for things
        like calls to numpy.random.
    r?   Fr   r,   Tr]   ri   )
r/   r   r5   r   rT   r4   r   r;   is_pure_extensionsr   )r   r   r   r   r   r   r   r   r   is_purej  s&    


r   c          	      s`  |dkri }|dkr*t  fdd|D }t|j|_dddg}x|  D ]}x|jD ]}t|tkrtt| }	|	|| ||| t|t	j
r\|j}
|jj}t| rq\t|
t	jr||
jkrt||
j|| t|
t	jr|
jdks|
jdkrt||
jj|| t|
t	jrF|
jd	krF|
jd
krFt||
jj|| t|
t	jr\|
jdkr\tt||
 }|dkrvq\|\}}|tkrt| }|||
j|| |dkr||krt||
jd j|| t|t	jr\||kr\t||j|| q\W qLW t|}xV|D ]N}x&|| D ]}||  || O  < qW x|| D ]}|| ||< q<W qW ||fS )zCfind all array aliases and argument aliases to avoid remove as deadNc             3   s   | ]}t | s|V  qd S )N)is_immutable_type)r$   a)r)   r   r   	<genexpr>  s    z)find_potential_aliases.<locals>.<genexpr>ravelZ	transposeZreshapecast)getitemstatic_getitemr=   )r   ZctypesZflatr?   r;   r   )r   build_definitionsrw   _definitionsr   ra   r   alias_analysis_extensionsr/   r   r7   r   r   r4   r   r2   
_add_aliasr5   r   r   guardfind_callnamealias_func_extensionsre   copydeepcopy)rw   re   r)   r   r   r   Znp_alias_funcsZblZinstrr   exprrD   ZfdeffnameZfmodZ
alias_funcZold_alias_maprV   wr   )r)   r   r     sV    





r   c             C   sX   ||kr| |  n@||kr&t ||< | |kr8t || < ||  |  ||   | d S )N)addr   )rD   r   r   r   r   r   r   r     s    

r   c             C   sR   |d ks| |krdS ||  }t |tjtjjtjjtjjfr@dS |tj	krNdS dS )NFT)
r/   r   NumberZscalarsZ_NPDatetimeBaser3   Z	BaseTupler[   r\   string)r   r)   typr   r   r   r     s    
r   c             C   s   t | }| }t| ||}|\}}}}}	d}
t|	}x|
|krx|  D ]t}||krZqLdd ||D }|	|d   ||< x |D ]}||  |	| M  < qW || || ||  B |	|< qLW |}
t|	}q:W tjdkrt	d|	 ||	fS )zcompute copy propagation information for each block using fixed-point
     iteration on data flow equations:
     in_b = intersect(predec(B))
     out_b = gen_b | (in_b - kill_b)
    Nc             S   s   g | ]\}}|qS r   r   )r$   iZ_dr   r   r   r*     s    z"copy_propagate.<locals>.<listcomp>r   r   zcopy propagate out_copies:)
r   entry_pointinit_copy_propagate_datar   r   r   predecessorsr   r   r   )rw   r)   r   entryZc_data
gen_copies
all_copieskill_copies	in_copies
out_copiesZ	old_pointZ	new_pointr   Zpredecspr   r   r   copy_propagate  s*    




r  c                s@  t | |\}}t  x | D ]\}} || O  qW i }x| D ]\}}	t ||< xv D ]n\}
}|
|| ks|||| kr|| |
|f dd |	D }|
|f|	kr\|
|ks||kr\|| |
|f q\W qDW  fdd|  D }t ||< i }x.|  D ]"}|| || ||  B ||< q W || ||< | |||fS )zHget initial condition of copy propagation data flow for each block.
    c             S   s   h | ]\}}|qS r   r   )r$   rD   r   r   r   r   r     s    z+init_copy_propagate_data.<locals>.<setcomp>c                s   i | ]}   |qS r   )r   )r$   r|   )r   r   r   
<dictcomp>  s    z,init_copy_propagate_data.<locals>.<dictcomp>)get_block_copiesr   r{   r   r   )rw   r   r)   r   
extra_killr|   r%   r   r   gen_setrD   r   assignedr  r  r   )r   r   r     s,    

r   c             C   s  i }i }x|   D ]\}}i }t ||< x|jD ]}xt  D ]\}}	t||rF|	||\}
}x|
D ]\}}|||< qlW i }xB|  D ]6\}}||kr||kr|||< ||kr|| | qW |}||  |O  < qFW t|tjr6|jj	}t|j
tjr(|j
j	}|| || kr(|||< q6t|j
tjr|j
jdkr|j
jj	}|| }t|tjs|tjks|| | i }xJ|  D ]>\}}||kr||kr|||< ||kr|| | qW |}|| | q6W t|  }|||< qW ||fS )z2get copies generated and killed by each block
    r   )r{   r   ra   copy_propagate_extensionsr/   r   r   r7   r   r4   r   r2   r5   r   rD   r   r   r   )rw   r)   Zblock_copiesr  r   r   Zassign_dictr   r   r   r  kill_setrD   r   Znew_assign_dictr|   r}   Zin1_varZin1_typZ	block_cpsr   r   r   r  -  sX    



r  c          	      s  |dkrg }xt|   D ]f\}} fdd|| D }x6|jD ]*}	t|	tkrttt|	 }
|
|	| ||| n&t|	tjrt|	j||	_n
t	|	| t
|	|| xt  D ]\}}
t|	|r|
|	|\}}x$|D ]\}}| krֈ | ||< qW x:|   D ]*\}}||ks"|j|kr|| qW qW t|	tjrt|	jtjr|	jj}|	jj}||kr|| || kr| kr | ||< n||d g }x,|  D ] \}}|j|kr|| qW x|D ]}||d qW t|	tjrBt|	jtjsB|	jj}||d g }x,|  D ] \}}|j|kr.|| q.W x|D ]}||d qXW qBW ||   qW |S )zEapply copy propagation to IR: replace variables when copies availableNc                s   i | ]\}} | |qS r   r   )r$   r|   r}   )name_var_tabler   r   r  s  s    z(apply_copy_propagate.<locals>.<dictcomp>)r{   ra   r   apply_copy_propagate_extensionsr/   r   r7   r   r   r   fix_setitem_typer
  r   r4   popr2   r   r8   rB   )rw   r  r  r)   rC   save_copiesr   r   Zvar_dictr   r   r   r  r  rD   r   r|   r}   Zlhs_killrU   rV   r   )r  r   apply_copy_propagatei  s^    




r  c             C   s   t | tjtjfsdS || jj }||  jd }t |tjj	rLt |tjj	sPdS |j
dkr|j
dkr|j|j
d}|||  jd ||  jd f||  _dS )zCopy propagation can replace setitem target variable, which can be array
    with 'A' layout. The replaced variable can be 'C' or 'F', so we update
    setitem call type reflect this (from matrix power test)
    Nr   A)layoutr      )r/   r   r   r   r   r4   re   r   npytypesArrayr  r   )r   r)   rC   Zt_typZs_typZ	new_s_typr   r   r   r    s     
r  c             C   s\   t jdkrX| j}|dkr|n|| _| jj}td||f dd |   td || _dS )zqDebug print function IR, with an optional blocks argument
    that may differ from the IR's original blocks.
    r   Nz	IR %s: %sP   -z(----------------------------------------)r   r   rw   Zfunc_idZfunc_qualnamer   centerdump)r   titlerw   Z	ir_blocksr4   r   r   r   dprint_func_ir  s    
r  c                sF   dkrt g t  fdd      S )z{find topological order of blocks such that true branches are visited
    first (e.g. for_break test in test_dataflow).
    Nc                st   | krp |  j|  }|  jd }t|tjrB|j|jg}x"|D ]}| |fjkrH | qHW 	|  d S )NrX   )
r   Z_succsra   r/   r   rk   r   r   Z_back_edgesr8   )r   succsZ	last_instdest)_dfs_recrw   r   
post_orderseenr   r   r    s    


z!find_topo_order.<locals>._dfs_rec)r   r   r   r   )rw   r   r   )r  rw   r   r   r!  r   find_topo_order  s    r"  Tc             C   s  |dkri }|dkri }|r&t | }nt|  }xt|D ]}xt| | jD ]r}t|tjr|jj	}|j
}t|tjr|jdkrg ||jj	< t|tjr|jdkr||kr|| |j |||j
j	< ||kr|| }	||	 |j |	||j
j	< t|tjrP||kr.|| |j
 ||krP|| }	||	 |j
 t|tjr||krx|| |j
 ||kr|| }	||	 |j
 x.t D ]"\}
}t||
r|||| qW qVW q>W ||fS )zAreturns a dictionary of call variables and their references.
    Nr?   r=   )r"  r   r   r   ra   r/   r   r7   r   r4   r   r5   r   rT   r8   r   r<   FreeVarcall_table_extensionsr{   )rw   r   Zreverse_call_tableZtopological_orderingorderr   r   rD   r   Zcall_varr   r   r   r   r   r     sL    





r   c             C   s   |dkri }x|   D ]}x|jD ]}t|tjr|jj}|j}t|tjr`|j	dkr`|j
||< t|tjrt|jtr|j||< x(t
 D ]\}}t||r||| qW q"W qW |S )z>returns a dictionary of tuple variables and their values.
    Nr6   )r   ra   r/   r   r7   r   r4   r   r5   r   r{   rN   r0   tuple_table_extensions)rw   Ztuple_tabler   r   rD   r   r   r   r   r   r   get_tuple_table&  s    


r'  c             C   s.   t  }t| tjtjtjfr*|| jj |S )N)	r   r/   r   r7   r   r   r   r   r4   )r   Zwritesr   r   r   get_stmt_writes;  s    r(  c             C   s   t | }d}x*|  D ]\}}t|jd tjr|}qW |dkrT|| || i }t|dd}x|D ]}|	 ||< qjW xR| 
 D ]F}|j}t|tjr||j |_t|tjr||j |_||j |_qW i }	x$|  D ]\}
}||
 }||	|< qW |	S )zrename labels of function body blocks according to topological sort.
    The set of labels of these blocks will remain unchanged.
    rX   T)r   )r"  r{   r/   ra   r   r   r   r8   sortedr  r   r   r_   r   rk   r   r   )rw   
topo_orderreturn_labelr|   r   Z	label_mapZ
all_labelsr   r   r   rU   Z	new_labelr   r   r   rename_labelsB  s0    


r,  c                s   t  } fdd}tt|  }t }xx|D ]p} | jd }||}d}x@|D ]8\}	}
 |	 }t|jd tj	rt

||jd< qXd}qXW |r2|| q2W x|D ]
} |= qW t  t S )z@transform chains of blocks that have no loop into a single blockc                s(    |  }t |jdko&t|jd tjS )Nr   r   )r1   ra   r/   r   rk   )r   r   )rw   r   r   find_single_branchk  s    z(simplify_CFG.<locals>.find_single_branchr   TrX   F)r   r   filterr   r   ra   r   r/   r   r_   r   r   merge_adjacent_blocksr,  )rw   r   r-  Zsingle_branch_blocksZmarked_for_delr   r   r   Zdelete_blockr  qr   r   )rw   r   simplify_CFGg  s&    



r1  minmaxsumZprodZmeanr   ZstdZcumsumZcumprodZargminZargmaxZargsortZnonzeror   c                s  | j }i }t|}x|D ]}|| }g }	x|jD ]}
t|
tjrt|
jtjr|
jj	}|
j}|j
dkr<|jtkr<t |jj	 tjjr<|
j}|j}|||< |j}|j}t|td|}tjt |j	< tdt|}t|||}||_|	| |g| j|j	< tt|j}t|} | | |< |j
dkr|jj	|kr||jj	 }||}|jd t|j } fdd|j D } |jj	 !| |j	 gt"| |||< |g|j |_|	|
 q6W |	|_qW d S )Nr=   z	$np_g_varr+   r?   c                s   i | ]\}} |j  |qS r   )r4   )r$   r4   rV   )r)   r   r   r    s    z+canonicalize_array_math.<locals>.<dictcomp>)#rw   r"  ra   r/   r   r7   r   r5   r   r4   r   r   arr_mathr   r  r  r(   r&   r2   r   r9   r:   r;   r<   r8   r   r=   r>   r  rT   re   r1   kwsr@   r   )r   r)   rC   	typingctxrw   Zsaved_arr_argr*  r   r   r   r   rD   r   Zarrr(   r&   rG   rH   rI   rT   func_typZold_sigZargtypsZkwtypsr   )r)   r   canonicalize_array_math  sP    



r9  c       	      C   s@  |dkrt  }x*|  D ]}x|jD ]}t|tjrR||jj|j	jf t|tj
rt||jj|jjf t|tjr|jj}|j}t|tjr|jdkr||jj|j	jf t|tjr|jdkr|j	}|dkst|r|jj}||jj|f x,t D ] \}}t||r||| qW q*W qW |S )z8returns a set of arrays accessed and their indices.
    Nr   r   )r   r   ra   r/   r   r   r   r   r4   r   r   r   r7   r   r5   r   is_slice_indexarray_accesses_extensionsr{   )	rw   Zaccessesr   r   rD   r   r   r   r   r   r   r   get_array_accesses  s,    r<  c             C   s8   t | trdS t | tr4x| D ]}t |trdS qW dS )z0see if index is a slice index or has slice in itTF)r/   r   r0   )r   r   r   r   r   r:    s    



r:  c       	      C   s   t | }t }xt|  D ]}||kr*q| | }t||}xt|dkrPP |d d }||krfP t||}t||}t|dks|d d |krP | | }|j  | j|j7  _| |= |	| |}qBW qW d S )Nr   r   )
r   r   r   r   r   r1   r   ra   r  r   )	rw   r   r   r   r   r  r"   ZpredsZ
next_blockr   r   r   r/    s.    

r/  c             C   sp   i }x\|D ]T\}}| ds
|j dr
|j|kr
td|}|||j< ||j}|||< q
W t| | dS )zS
    restores variable names of user variables after applying copy propagation
    rp   z${}N)
startswithr4   r   rh   r  r~   )rw   r  r)   Zrename_dictr   r   rr   r   r   r   r   restore_copy_var_names  s    

r>  c             C   sz   t | j t| j|\}}t| j}t| j||||}t| j|| t| j| j| | t| j| _t	j
dkrvt| d d S )Nr   zafter simplify)r   rw   r  rx   r  r>  r   	arg_namesr1  r   r   r  )r   r)   rC   Zin_cpsZout_cpsr  r  r   r   r   simplify  s    


r@  c               @   s   e Zd ZdS )GuardExceptionN)__name__
__module____qualname__r   r   r   r   rA  ,  s   rA  c             C   s   | st dS )z?
    Raise GuardException if the given condition is False.
    N)rA  )r   r   r   r   require/  s    rE  c             O   s$   y
| ||S  t k
r   dS X dS )z
    Run a function with given set of arguments, and guard against
    any GuardException raised by the function by returning None,
    or the expected return results if no such exception was raised.
    N)rA  )rT   re   kwargsr   r   r   r   6  s    
r   c             K   s,   y| j |f|S  tk
r&   tY nX dS )zm
    Same as func_ir.get_definition(name), but raise GuardException if
    exception KeyError is caught.
    N)get_definitionKeyErrorrA  )r   r4   rF  r   r   r   rG  A  s    rG  c             C   s   |dkrt t}x~|  D ]r}xl|jD ]b}t|tjrh|jj	}|
|g }|g kr\|||< ||j t|tkr(tt| }||| q(W qW |S )zBuild the definitions table of the given blocks by scanning
    through all blocks and instructions, useful when the definitions
    table is out-of-sync.
    Will return a new definition table if one is not passed.
    N)collectionsdefaultdictr   r   ra   r/   r   r7   r   r4   getr8   r   r   build_defs_extensions)rw   Zdefinitionsr   r   r4   Z
definitionr   r   r   r   r   K  s    
r   c             C   s  t t|tjo|jdk |j}|| |}g }d}xt|tjtjfrTdddg}d}	x&|D ]}
t|j	|
r^t
|j	|
}	P q^W |	st||	 |j	}t|tjjr|j}t|dr&|j}tt|	r|t
t|	kr|dg7 }nBttj|	r|t
tj|	kr|ddg7 }n|dk	rP|| n*|jj}|d	kr<d
}|dkrP|| P q6t|tjr|jdkr|j	}||j |r|j|kr||j }t|tjs|d |fS || |}q6|dk	rdt||fS tq6W |d dt|dd fS )az  Try to find a call expression's function and module names and return
    them as strings for unbounded calls. If the call is a bounded call, return
    the self object instead of module name. Raise GuardException if failed.

    Providing typemap can make the call matching more accurate in corner cases
    such as bounded call on an object which is inside another object.
    r?   Nr4   r   rB  rC  r;   r   Zbuiltin_function_or_methodZbuiltinmoduler=   r   r   r   )rE  r/   r   r5   r   rT   r<   r#  hasattrr   r=   rA  r8   r   r   r   Z_defnrC  r;   r   	__class__rB  r   r4   r   r:   joinr   )r   r   r)   Zdefinition_findercalleeZ
callee_defZattrsobjr   r   keyZdef_valmod_name
class_namer   r   r   r   r   d  s^    










r   c             C   sN   t t|tj t| |}t t|tj dddg}t |j|k |j|jfS )zCheck if a variable is constructed via build_tuple or
    build_list or build_set, and return the sequence and the
    operator, or raise GuardException otherwise.
    Note: only build_tuple is immutable, so use with care.
    r6   Z
build_listZ	build_set)rE  r/   r   r2   rG  r5   r   r{   )r   r   var_defZ	build_opsr   r   r   find_build_sequence  s    

rW  c             C   s0   t t|tj t| |}t t|tj |jS )zvCheck if a variable is defined as constant, and return
    the constant value, or raise GuardException otherwise.
    )rE  r/   r   r2   rG  rN   r   )r   r   rV  r   r   r   
find_const  s    
rX  c             C   s  ddl m} t| dr| j}n t| dr0| j}ntd| t||}t|j	 t
|j	td |_	t|j	 }	|	at|j	}
i }x |
 D ]\}}t|||< qW t|j	| |r||||d\}}}dd	 |D }x|D ]}|| qW || || |S )
a  
    Compile a function or a make_function node to Numba IR.

    Rename variables and
    labels to avoid conflict if inlined somewhere else. Perform type inference
    if typingctx and other typing inputs are available and update typemap and
    calltypes.
    r   )compilercode__code__zfunction type not recognized {}r   Nc             S   s   g | ]}| d r|qS )zarg.)r=  )r$   Zvnamer   r   r   r*     s    z'compile_to_numba_ir.<locals>.<listcomp>)r   rY  rN  rZ  r[  NotImplementedErrorrh   get_ir_of_coder   rw   r   r!   r3  r   rx   r{   r   r~   Ztype_inference_stager  update)Zmk_funcglblsr7  Zarg_typsr)   rC   rY  rZ  f_irr   r   Znew_var_dictr4   r   Z	f_typemapZf_return_typeZf_calltypesr?  r   r   r   r   compile_to_numba_ir  s2    








ra  c             C   s  t |j}ddd t|D }ddd t|D }ddd t|jD }d|||f }i }t|| | tjdkrtjd	k rt|j	}t |d
kr|d
 dkrd|d
< t
|j|j|j|j|j|j|j|jt||j|j|j|j|j|j}|d  }	||	_|j|	_d
dlm}
 |
|	}G dd dt}tj !d||| i }tj"#|tj$j%&d|}|'  d
dlm(} |)|}|'  |S )z.
    Compile a code object to get its IR.
    
c             S   s   g | ]}d | qS )z  c_%d = Noner   )r$   r   r   r   r   r*     s    z"get_ir_of_code.<locals>.<listcomp>,c             S   s   g | ]}d | qS )zc_%dr   )r$   r   r   r   r   r*     s    c             S   s   g | ]}d | qS )zx_%dr   )r$   r   r   r   r   r*     s    z3def g():
%s
  def f(%s):
    return (%s)
  return f)r   )r      r   z.0Z	implicit0g)rY  c               @   s   e Zd Zdd ZdS )z%get_ir_of_code.<locals>.DummyPipelinec             S   s.   d | _ d | _d | _|| _d | _d | _d | _d S )N)r7  Z	targetctxre   r   r)   Zreturn_typerC   )selfr`  r   r   r   __init__  s    z.get_ir_of_code.<locals>.DummyPipeline.__init__N)rB  rC  rD  rg  r   r   r   r   DummyPipeline  s   rh  zbefore-inferenceF)postproc)*r1   co_freevarsrP  rW   co_argcountr   r
   Z	PYVERSIONr   co_varnamespytypesCodeTypeco_kwonlyargcount
co_nlocalsco_stacksizeco_flagsco_code	co_constsco_namesr0   co_filenameco_nameco_firstlineno	co_lnotabco_cellvarsr[  rB  r   rY  Zrun_frontendobjectr   Zrewrite_registryZapplyZinline_closurecallZInlineClosureCallPassZtargetsZcpuZParallelOptionsrunri  ZPostProcessor)r_  ZfcodeZnfreeZfunc_envZfunc_cloZfunc_argZ	func_textr&   rl  r   rY  r   rh  ZswappedZinline_passri  Z	post_procr   r   r   r]    sX    



	
r]  c             C   sP   xJ| j D ]@}t|tjrt|jtjr|jj}|t|k s>t|| |_qW dS )z,
    Replace ir.Arg(...) with variables
    N)	ra   r/   r   r7   r   r   r   r1   rO   )r   re   r   idxr   r   r   replace_arg_nodes,  s    r~  c             C   s   x|   D ]}g }xt|jD ]\}}t|tjr|d t|jksHtt|j	||j
|j|< |jt||j
 xX|D ]}|jj|j	jkr||j	j	|_	q|W qt|tjrt|j	tjr|j	jdkr|| qW q
W dS )zN
    Return return statement by assigning directly to target, and a jump.
    r   r   N)r   	enumeratera   r/   r   r   r1   rO   r7   r   r&   r8   r_   r   r4   r5   r   )rw   r   r+  r   Zcastsr   r   r   r   r   r   replace_returns7  s    
&r  c                s   |d j }|d j}t|td|}	tjt |	j	< t
dt|}
t|
|	|}tj|	| |}t|td|}t|}| |j	< t|||}tj||d|} fdd|D }|||i }|||< t|||}|||gS )Nr   z	$np_g_varr+   z$np_attr_attrr   c                s   g | ]} |j  qS r   )r4   )r$   r   )r)   r   r   r*   Z  s    zgen_np_call.<locals>.<listcomp>)r(   r&   r   r2   r   r   r9   r:   r;   r4   r<   r7   r5   r=   r>   r?   r@   )Zfunc_as_strrT   rD   re   r7  r)   rC   r(   r&   rG   rH   rI   Znp_attr_callrJ   Zfunc_var_typrK   Znp_callZ	arg_typesr8  Z	np_assignr   )r)   r   gen_np_callI  s"    


r  c             C   s>   x8|   D ],\}}t|d x|jD ]}td| q$W q
W d S )N:z    )r{   r   ra   )rw   r   r   r   r   r   r   dump_blocks`  s    
r  c             C   s   t | pt| S )z8stmt is getitem assignment or setitem (and static cases))
is_getitem
is_setitem)r   r   r   r   is_get_setitemf  s    r  c             C   s&   t | tjo$t | jtjo$| jjdkS )z6true if stmt is a getitem or static_getitem assignment)r   r   )r/   r   r7   r   r5   r   )r   r   r   r   r  k  s    r  c             C   s   t | tjtjfS )z/true if stmt is a SetItem or StaticSetItem node)r/   r   r   r   )r   r   r   r   r  q  s    r  c             C   sH   t | r$| jjdkr| jjS | jjS t| rDt| tjr>| jS | jS dS )z?get index variable for getitem/setitem nodes (and static cases)r   N)	r  r   r   r   r   r  r/   r   r   )r   r   r   r   index_var_of_get_setitemu  s    r  c             C   s^   t | r(| jjdkr|| j_qZ|| j_n2t| rLt| tjrD|| _qZ|| _nt	d
| d S )Nr   z0getitem or setitem node expected but received {})r  r   r   r   r   r  r/   r   r   
ValueErrorrh   )r   Z	new_indexr   r   r   set_index_var_of_get_setitem  s    

r  c             C   sj   t | tsdS | j}t|dks,|d tkr0dS t| ds>dS t| dd}t |tsXdS tdd |D S )	z check if c is a namedtuple classFr   r   _make_fieldsNc             s   s   | ]}t |tV  qd S )N)r/   r   )r$   r   r   r   r   r     s    z&is_namedtuple_class.<locals>.<genexpr>)r/   r   	__bases__r1   r0   rN  r=   all)cbasesZfieldsr   r   r   is_namedtuple_class  s    


r  c                s   | j  | j}tj||d} j|d}| tj|||d  fdd|D }tjj||d|d}	 j|d}
| tj|
|	|d xHt	|D ]<\}} 
|}tjj|
|d|d	}| tj|||d qW | tj||d
 | S )zFill *newblock* to call *callee* with arguments listed in *inputs*.
    The returned values are unwraped into variables in *outputs*.
    The block would then jump to *label_next*.
    )r   r&   )r&   )r   r   r&   c                s   g | ]}  |qS r   )	get_exact)r$   r4   )r(   r   r   r*     s    z(fill_block_with_call.<locals>.<listcomp>r   )rT   re   r6  r&   N)r   r   r   r&   )r   r&   )r(   r&   r   rN   	make_tempr8   r7   r5   r?   r  r  r   r_   )ZnewblockrQ  
label_nextinputsoutputsr&   fnZfnvarre   ZcallexprZcallresr   r'   r   r   r   )r(   r   fill_block_with_call  s     


r  c                sx   | j }| j  fddt|D }x<t||D ].\}}tj|| d}| tj|| d q.W | tj| d | S )z
    Fill a new block *block* that unwraps arguments using names in *inputs* and
    then jumps to *label_next*.

    Expected to use with *fill_block_with_call()*
    c                s    g | ]\}}t j|| d qS ))r4   r   r&   )r   r   )r$   r   rU   )r&   r   r   r*     s   z(fill_callee_prologue.<locals>.<listcomp>)r(   r4   r&   )r   r   r&   )r   r&   )	r(   r&   r  zipr   r2   r8   r7   r_   )r   r  r  r(   re   ZanameZavalZtmpr   )r&   r   fill_callee_prologue  s    
r  c                sh   | j  | j} fdd|D }tjj||d} j|d}| tj|||d | tj||d | S )z
    Fill a new block *block* to prepare the return values.
    This block is the last block of the function.

    Expected to use with *fill_block_with_call()*
    c                s   g | ]} j |d qS ))r4   )r  )r$   r4   )r(   r   r   r*     s    z(fill_callee_epilogue.<locals>.<listcomp>)r{   r&   )r&   )r   r   r&   )r   r&   )	r(   r&   r   r5   r6   r  r8   r7   r   )r   r  r&   ZvalsZtupexprtupr   )r(   r   fill_callee_epilogue  s    r  c             C   sp   |  |}t|tjr|jS t|tjrh|jdkrht| |j}yt||j	}|S  t
k
rf   tY nX tdS )zhCheck if a variable is a global value, and return the value,
    or raise GuardException otherwise.
    r=   N)rG  r/   r   r<   r   r5   r   find_global_valuer=   r   rH  rA  )r   r   Zdfnprev_valvalr   r   r   r    s    

r  c             C   s`  g }x"| j  D ]}x
|tjD ]}t|jtjr|jjdkr|j}t	|dd}|dk	rt	|dddk	rzd}d}q|j
}d| }nd}d}d	||f }t||jjt|jtjtjfr(|j}t	|d
d}|dkrq(d}	t|tjr|tjtjhk}	|	st	|dddk}	|	r(||j q(W qW t|dkr\d}ddd |D }
t||
 dS )a&  
    Helper function to walk IR and raise if it finds op codes
    that are unsupported. Could be extended to cover IR sequences
    as well as op codes. Intended use is to call it as a pipeline
    stage just prior to lowering to prevent LoweringErrors for known
    unsupported features.
    Zmake_functionrZ  NZclosurez$<creating a function from a closure> z(%s) z<could not ascertain use case>zNumba encountered the use of a language feature it does not support in this context: %s (op code: make_function not supported). If the feature is explicitly supported it is likely that the result of the expression %sis being used in an unsupported manner.r   Fr   Zgdb_internalr   a  Calling either numba.gdb() or numba.gdb_init() more than once in a function is unsupported (strange things happen!), use numba.gdb_breakpoint() to create additional breakpoints instead.

Relevant documentation is available here:
http://numba.pydata.org/numba-doc/latest/user/troubleshoot.html/troubleshoot.html#using-numba-s-direct-gdb-bindings-in-nopython-mode

Conflicting calls found at:
 %srb  c             S   s   g | ]}|  qS r   )Z	strformat)r$   r   r   r   r   r*   ?  s    z0raise_on_unsupported_feature.<locals>.<listcomp>)rw   r   Z
find_instsr   r7   r/   r   r5   r   r=   rw  r   r&   r<   r#  rm  FunctionTyper   ZgdbZgdb_initr8   r1   rP  )r   Z	gdb_callsZblkr   r  rZ  Zuser   msgfoundZbufr   r   r   raise_on_unsupported_feature  sD    

r  )NNN)NN)N)N)N)NNT)N)N)N)NNNN)Z
__future__r   r   r;   r   rm  rI  operatorZllvmliter   Zlirr   Z	numba.sixr   r   r   r	   r
   r   r   Znumba.typing.templatesr   r   r   Znumba.targets.imputilsr   Znumba.analysisr   r   r   Znumba.errorsr   r   r   r   r   r!   r    r"   rL   r#   r>   rg   rZ   rY   rm   rs   rx   r~   r   r   r   r   r   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r8   r   r   r   r   r   r   r   r   r  r   r
  r  r  r  r  r  r"  r$  r   r&  r'  r(  r,  r1  r5  r9  r;  r<  r:  r/  r>  r@  	ExceptionrA  rE  r   rG  r   rL  r   rW  rX  ra  r]  r~  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   r   <module>   s   (>%'%


3
<
' 
>%%9
A


2
%
6

 

C	 
.@