o
    8ήc5                     @   s$  d dl Z d dlZd dlZd dlmZ d dlZd dlZd dlZ	d dl
mZmZmZmZmZ d dlmZmZ d dlmZ d dl
mZmZ d dlmZmZmZmZmZmZmZmZmZ d dl m!Z! d d	l"m#Z# d
d Z$G dd de%Z&dd Z'G dd de%Z(dd Z)dd Z*dd Z+dd Z,dd Z-dS )    N)add)typesirrewritesconfigir_utils)infer_globalAbstractTemplate)	signature)utilstyping)	get_call_tablemk_unique_varcompile_to_numba_irreplace_arg_nodesguardfind_callnamerequire
find_constGuardException)NumbaValueError)OPERATORS_TO_BUILTINSc                 C   s   |dkr| | S | S Nr    )dim_sizeindex_constr   r   C/tmp/pip-target-vg8gfxp4/lib/python/numba/stencils/stencilparfor.py_compute_last_ind   s   r   c                   @   sT   e Z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S )StencilPassc                 C   s.   || _ || _|| _|| _|| _|| _|| _d S N)func_irtypemap	calltypesarray_analysis	typingctx	targetctxflags)selfr    r!   r"   r#   r$   r%   r&   r   r   r   __init__!   s   
zStencilPass.__init__c                    s  ddl m} t jj\}}g }i }| D ]\}}|D ]}t||r,|| |||< qq|s2dS  jj D ]\}	}
tt	t
|
jD ]\}ttjrtjtjrވjjdkrވjjj|v rtjj}fddttjjD }jj}t fdd|D }|D ]}t|tjrtd	q|d
}|jjj }t| j||
j|
j | j! j"\}}}|j#dd} $|	||||j%|||	}|
jd| | |
j|d d  |
_qEttjrtjtjrjjdkrt&t' jjdkrt(dj _qEq8dS )zP Finds all calls to StencilFuncs in the IR and converts them to parfor.
        r   )StencilFuncNcallc                    s   i | ]	}| j j| qS r   )valueargs.0i)stmtr   r   
<dictcomp>H   s    z#StencilPass.run.<locals>.<dictcomp>c                 3   s    | ]	} j |j V  qd S r   )r!   namer-   r'   r   r   	<genexpr>K   s    z"StencilPass.run.<locals>.<genexpr>zITuple parameters not supported for stencil kernels in parallel=True mode.outindex_offsets   )stencilnumba))numba.stencils.stencilr)   r   r    blocksitems
isinstanceappendreversedlist	enumeratebodyr   Assignr+   Expropfuncr2   dictkwsrangelenr,   tupler   	BaseTuple
ValueErrorgetget_stencil_irr$   scopelocr!   r"   options_mk_stencil_parfortargetr   r   Const)r'   r)   
call_table_stencil_callsstencil_dictcall_varname	call_listone_calllabelblockr/   rH   
input_dictin_argsarg_typemaparg_typeout_arrsf
stencil_irrtarg_to_arr_dictr6   	gen_nodesr   )r'   r0   r   run+   st   







(
zStencilPass.runc              	   C   s   |  D ]O\}}|j}|j}g }|jD ]<}	t|	tjrJ| }
t|
tjr2t|
j	tj
r2|
j	jdks4J |t|
j	j	|| |t|| q||	 q||_qdS )z
        Find return statements in the IR and replace them with a SetItem
        call of the value "returned" by the kernel into the result array.
        Returns the block labels that contained return statements.
        castN)r<   rP   rQ   rB   r=   r   ReturnpoprC   r+   rD   rE   r>   Jump)r'   r;   exit_value_varparfor_body_exit_labelr]   r^   rP   rQ   new_bodyr0   	prev_stmtr   r   r   replace_return_with_setitemg   s"   

z'StencilPass.replace_return_with_setitemc
           R         s	  g }
|j }tjdkrtd|||||| t| |d }j|j }t|j\}}t	|}t
|||jj tjdkrKtd t| t|jj|j tjdkrdtd t| j|j j |j}|j}g }t D ]}t|td|}tjj|j< || qw||||||	\}}tjdkrtd td| td	| t| g }j|}||} t|ksJ g }g }t D ]2}|| || |
||}|| |
||}|| || |t j!j"#|| ||d qt$|% d }t&||||< t|td
|} |j'j| j< g }! dkr/|d }"n(t|td|}"tj()tj j|"j< tj*+||}#t,|#|"|}$|!|$ tjdkrftd t| t&||}%du rXj|j }td}&t||&|}'tj*-|d|}(tj()tj|jj|&< |%j./t,|(|'|g td})t||)|d|j0v r|j0d }*t1j22|*}+j34|+|j'st5d|'|*},n|'d},t6|,|}-|j'j|)< |%j./t,|-|g td}.t||.|t j7jj89|j'|j|j:jj< t|td|}/tj;<t=j|/j< t>dt=|}0t,|0|/|}1|%j.|1 tj*-|/|j'j|}2t|td|}3tj?@|j'j|3j< t,|2|3|}4|%j.|4 tAdt=jB|'|3gj3jj}5t|td|}6t,t6d||6|}7|5|7 tjCj|6j< t|td|}8t,t6d||8|}9|5|9 tjj|8j< t|td|}:j3DtE};|;j|:j< t>dtE|}<t,|<|:|}=|5|= j3F|;tjCfd i }>tj*jG|:|6|6fd|d}?|>j|?< t|td|}@tjHj|@j< t,|?|@|}=|5|=  fd d!}At|jD ]+}B|@g|j }C|@g|j }D|A|;|B|||:|5||C|8d"
 |A|;|B|||:|5||D||B d#
 q|I| |%j./|5 nd|j0v r+|j0d }*t1j22|*}+j34|+|j'sxd}EtJ|Et|td$|}@j3DtE};|;j|@j< t>dtE|}<t,|<|@|}F|%j.|F j3F|;tjCfd i }>tj*jG|@dd|d}G|>j|G< t|td%|}HtjHj|Hj< t,|G|H|}=|%j.|= t6|'|*|}It|td&|}J|j'j|Jj< t,|I|J|}K|%j.|K tKtEdd|H|J|}L|%j.|L tLtjCjj j|Hj jj j'}>|>j|L< M|| | tjdkrAtd' t| tN|"| |}MtLtjCjj j|"j jj j'j|M< || j./|! || j.|M tOd(d)}Nt|td&|N}Ot,tj6d|Nd*|O|N}K|| j.|K || j.tP|O|N tQ|}|t$|%  j.R  tjdkrtd+ t| d,||gf}Pt j!j"S||%|||"||PjT}Q|
|Q |
t,|| |
S )-z> Converts a set of stencil kernel blocks to a parfor.
        r7   rS   r   z#stencil_blocks after copy_propagatez'stencil_blocks after removing dead codez$parfor_index_varz-stencil_blocks after replace stencil accesseszstart_lengths:zend_lengths:z$parfor_exit_valuez$parfor_index_tuple_varz.stencil_blocks after creating parfor index varNin_arr_shapeshapezero_valcvalz-cval type does not match stencil return type.stencil_outputz	$np_g_varnpz$np_attr_attremptyz	$none_varz$zero_index_varz$slice_func_varslice   r   rF   r,   rH   rQ   $slicec
                    s  j | tjfd i }
|| }t|ttjfsJ t|td|}tjj	|j
< t|tr;tt||||}nt|||}|| tjj||	rQ||fn||fd|d}|
j|< t|td|}tjj	|j
< t|||}|| |||< t|td|}tjtj j	|j
< tj||}t|||}|| t||}ttjj	j
 j	|j
 j	j
 jj|< || d S )Nr{   z$border_indr   r|   r}   z$border_index_tuple_var)r$   resolve_function_typer   intpr=   intr   Varr   r!   r2   rC   rU   r>   rD   r*   r"   slice2_type
containersUniTuplebuild_tupleSetItemr
   nonedtype)slice_fn_tydimrP   rQ   slice_func_varstmtsborder_indsborder_tuple_items	other_argother_firstsigsisi_var	si_assignslice_callexprborder_slice_varslice_assignborder_ind_var
tuple_calltuple_assignsetitem_callndimsrc   r'   zero_varr   r   handle_border<  sV   







z5StencilPass._mk_stencil_parfor.<locals>.handle_borderTFz	$py_g_varz$slice_instz$cval_constz%stencil_blocks after replacing returnstencilparfor_dummy)rQ   z#stencil_blocks after adding SetItemr8   )Ur;   r   DEBUG_ARRAY_OPTprintr   dump_blocksr!   r2   copy_propagateget_name_var_tableapply_copy_propagater"   remove_deadr    	arg_namesndimrP   rQ   rI   r   r   r   r   r   r>   _replace_stencil_accessesr#   get_equiv_set	get_shaperJ   _get_stencil_last_ind_get_stencil_start_indr9   parforsparforLoopNestmaxkeysBlockr   r   r   rD   r   rC   getattrrB   extendrR   r   typeofr$   can_convertrM   rU   corenpytypesArraylayoutmiscModulerx   Global	functionsNumberClassgen_np_callry   r   resolve_value_typerz   r~   r*   r   insert_equivr   StaticSetItemr
   rr   r   Locrk   simplify_CFGrl   Parforr&   )Rr'   r]   r`   rc   re   r6   rT   return_typestencil_funcrg   rh   stencil_blocksin_arr
in_arr_typin_cpsout_cpsname_var_tablerP   rQ   parfor_varsr/   
parfor_varstart_lengthsend_lengths	loopnests	equiv_setin_arr_dim_sizes
start_inds	last_indslast_ind	start_indro   rn   for_replacing_retparfor_ind_varr   r   
init_block
shape_name	shape_varshape_getattr	zero_namerv   cval_tytemp2
full_constso_namedtype_g_np_var
dtype_g_npdtype_g_np_assigndtype_np_attr_calldtype_attr_vardtype_attr_assignr   none_varnone_assignzero_index_varzero_index_assignr   r   slice_gr   r   r   	slice_varr   r   start_tuple_itemslast_tuple_itemsmsgslice_assignedcallexprslice_inst_varcval_const_valcval_const_varcval_const_assignsetitemexprr   	dummy_locret_const_varpatternr   r   r   r   rS      s  


































8













zStencilPass._mk_stencil_parforc                 C   s2  |}|dkrt |td|}tj| j|j< t|tj	r(t 
t ||||}nt 
|||}|| t |td|}tj| j|j< t |td|}	tt}
tj|
}|| j|	j< t d|
|}t 
||	|}|| t j|	||gd|}|| jtjtjgi | j|< t 
|||}|| |S )Nr   stencil_const_varr   compute_last_ind_varr   r   )r   r   r   r   r   r!   r2   r=   numbersNumberrC   rU   r>   r9   njitr   r   
Dispatcherr   rD   r*   get_call_typer$   r"   )r'   r   
end_lengthrh   rP   rQ   r   r   const_assigng_var
check_funcfunc_typg_objg_assign
index_callindex_assignr   r   r   r     s8   




z!StencilPass._get_stencil_last_indc           	      C   s   t |trtt|dS dd }t|i | j| jtjf| j	| j
}t|jdks)J |j d }t||g ||jd d 7 }|jd jj}|S )Nr   c                 S   s   t t| dS r   )absmin)s_lengthr   r   r   get_start_ind  s   z9StencilPass._get_stencil_start_ind.<locals>.get_start_indr7   )r=   r   r  r  r   r$   r%   r   r   r!   r"   rJ   r;   popitemr   rB   r+   )	r'   start_lengthrh   rP   rQ   r  f_irr^   ret_varr   r   r   r     s   

z"StencilPass._get_stencil_start_indc              	      s  j }|d }dd |D }	d|jv r0|jd D ]
}
|
 vr"tdq fdd|jd D }ng }|j|v r;tdj|j j}|j}|j}|jdu }|rZ|dg }|dg }nd	d |jD }d
d |jD }t	
|}d}| D ]I\}}g }|jD ];}t|tjrt|jtjr|jjdv r|jjj|	v st|tjst|tjr|jj|	v rtdt|tjrt|jtjr|jjdv r|jjj|	v r|jjj|vr|jj}|dkr|g}nt|dr|j|v r||j }t	|_fdd|D }|r|t||||}|r;t|tjs%tdd |D r)tdttt||}ttt ||}d}|t||||}|dkrP|d }n(t|t!d|}t"j#$t"j%|j|j< tj&||}t|||}|'| t(fdd|D rj|jjj j)}nj|jjj }tj*|jj||}t+|j|jjj j|j j,|< ||_|'| q||_qu|r|std||fS )z Convert relative indexing in the stencil kernel to standard indexing
            by adding the loop index variables to the corresponding dimensions
            of the array index tuples.
        r   c                 S   s   g | ]}|j qS r   )r2   r.   xr   r   r   
<listcomp>&  s    z9StencilPass._replace_stencil_accesses.<locals>.<listcomp>standard_indexingz[Standard indexing requested for an array name not present in the stencil kernel definition.c                    s   g | ]} | qS r   r   r  )rg   r   r   r  -      zYThe first argument to a stencil kernel must use relative indexing, not standard indexing.Nc                 S      g | ]}|d  qS )r   r   r  r   r   r   r  D  r  c                 S   r  )r7   r   r  r   r   r   r  E  r  F)setitemstatic_setitemz?Assignments to arrays passed to stencil kernels is not allowed.)static_getitemgetitemr7   r2   c                    s   g | ]	}t  j|qS r   )_get_const_index_exprr    r.   v)r'   re   r   r   r  o  s
    c                 S   s   g | ]}t |t qS r   r=   r   r%  r   r   r   r  z  s    z<Variable stencil index only possible with known neighborhoodTz$parfor_index_ind_varc                    s   g | ]} j |j tjkqS r   )r!   r2   r   r   r%  r3   r   r   r    s    z=Stencil kernel with no accesses to relatively indexed arrays.)-r;   rR   rM   r2   r!   r   rP   rQ   neighborhoodr   get_tuple_tabler<   rB   r=   r   rC   r+   rD   rE   r   r   rT   indexhasattrbuild_definitions_definitions_add_index_offsetsr@   r   anymapr  r   r   r   r   r   r   r   r>   allr   r#  r
   r"   )r'   re   r   r`   r6   r   rg   r   r   in_arg_namesr  standard_indexedr   rP   rQ   need_to_calc_kernelr   r   tuple_tablefound_relative_indexr]   r^   rp   r0   
index_list
index_varsind_varr   r   getitem_return_typgetitem_callr   )rg   r'   re   r   r     s   

















z%StencilPass._replace_stencil_accessesc                 C   s,  t |t |ks
J tdd || D rttt||S g }g }tt |D ]}|| }	t|	trTt	|t
d|}	tj| j|	j< tt|| ||	|}
||
 || }t|trt	|t
d|}tj| j|j< tt|| |||}
||
 t|	tst| j|	j tjjr| j|j tjksJ | |	||||}|| q't|tst| j|j tjjr| j|	j tjksJ | ||	|||}|| q't	|t
d|}tj| j|j< tjtj|	||}| jtjtjtjfi | j|< t|||}|| || q'|| |S )zw Does the actual work of adding loop index variables to the
            relative index constants or variables.
        c                 S   s   g | ]}t |tqS r   r'  r%  r   r   r   r    s    z2StencilPass._add_index_offsets.<locals>.<listcomp>old_index_var
offset_varoffset_stencil_index)rJ   r1  r@   r0  r   rI   r=   r   r   r   r   r   r   r!   r2   rC   rU   r>   rz   r   	SliceType_add_offset_to_slicerD   binopoperatorr$   r~   r"   r   )r'   r7  r6   rp   rP   rQ   	out_nodesr8  r/   r<  r	  r=  	index_varr  r  r   r   r   r.    s~   










zStencilPass._add_index_offsetsc                 C   s   t |tr!d|j|j}i }t|i | |d }|g}tjf}	ndd }||g}| j|j	 }
|
tjf}	| j
jjj}t||| j| j|	| j| j}|j \}}t|| |jd jj}||jd d  |S )NzRdef f(offset):
                return slice({} + offset, {} + offset)
            fc                 S   s   t | j| | j| S r   )rz   startstop)	old_sliceoffsetr   r   r   rE    s   z+StencilPass._add_offset_to_slice.<locals>.fr  )r=   rz   formatrF  rG  execr   r   r!   r2   r    func_idrF   __globals__r   r$   r%   r"   r;   r  r   rB   r+   r   )r'   r   r=  rC  rP   rQ   f_textrE  r,   arg_typs
slice_type_globalsr  rW   r^   	new_indexr   r   r   r@    s,   




z StencilPass._add_offset_to_sliceN)__name__
__module____qualname__r(   ri   rr   rS   r   r   r   r.  r@  r   r   r   r   r       s    
<  o" Dr   c                 C   s  ddl m} ddlm}	 ddlm}
 ddlm} | j	 }t	
|j}||_t|j}d|v r4tdddlm}	 |	j}|	||I t||||}tjd|j ||jj|jj|jj|jjd	\|j_|j_|j_}|
j|jj|jj|jjd
d	|jj|jjtjd W d	   n1 sw   Y  t |t! }t"|# }t$|# }tj%&| tj'dkrt(d t)| i }|jj* D ]\}}t+,|t-||}|||< |||j.< qt/|| tj'dkrt(d t)| |jj* D ]\}}|||< qi }|0 D ]A}|j1D ]:}t2|t+j3rBt2|j4t+j5rBtj'dkr0t(d||j4j6|j4j.|j4j6|v  ||j4j6 j.||j4j.< ||j4j6 |_4q	qtj'dkrZt(d| t(d t)| t7| ||_|| 8|d |fS )z'get typed IR from stencil bytecode
    r   )
CPUContext)
cpu_target)type_annotations)type_inference_stager5   z6Cannot use the reserved word 'out' in stencil kernels.zbefore-inferenceNr   )r    r!   r"   liftedlifted_fromr,   r   html_outputr7   zInitial stencil_blockszAfter replace_varsr_   rg   zAfter replace arg with arr)9numba.core.cpurV  numba.core.registryrW  numba.core.annotationsrX  numba.core.typed_passesrY  	kernel_ircopydeepcopyr;   r   r   rM   target_contextnested_contextDummyPipeliner   rewrite_registryapplystater$   r%   r    r,   r!   r   r"   TypeAnnotationr   HTMLadd_offset_to_labels
next_labelr  r   r   _the_max_labelupdater   r   r   r<   r   r   r   r2   replace_varsvaluesrB   r=   rC   r+   Argr*  remove_delsget_return_type)rd   r$   r,   rP   rQ   r_   r!   r"   rV  rW  rX  rY  stencil_func_irr   r   r%   tprW   	min_label	max_labelvar_dictr&  typnew_varr*   call_typrg   r^   r0   r   r   r   rO   	  s   









rO   c                   @   s   e Zd Zdd ZdS )rf  c                 C   sP   ddl m} | | _|| j_|| j_|| j_|| j_d | j_d | j_d | j_	d S )Nr   )	StateDict)
numba.core.compilerr}  ri  r$   r%   r,   r    r!   r   r"   )r'   r$   r%   r,   r  r}  r   r   r   r(   b  s   zDummyPipeline.__init__N)rS  rT  rU  r(   r   r   r   r   rf  a  s    rf  c                 C   s   t t| ||}|dur|S |S )z
    infer index_var as constant if it is of a expression form like c-1 where c
    is a constant in the outer function.
    index_var is assumed to be inside stencil kernel
    N)r   _get_const_index_expr_inner)re   r    rD  	const_valr   r   r   r$  n  s   r$  c                 C   sn   t t|tj tt| ||}|dur|S t| |}tt| ||}|dur(|S tt	| ||}|dur5|S t
)zWinner constant inference function that calls constant, unary and binary
    cases.
    N)r   r=   r   r   r   _get_const_two_irsr   get_definition_get_const_unary_expr_get_const_binary_exprr   )re   r    rD  	var_const	index_defr   r   r   r  z  s    r  c                 C   s4   t t| |}|dur|S t t||}|dur|S t)zWget constant in either of two IRs if available
    otherwise, throw GuardException
    N)r   r   r   )ir1ir2varr  r   r   r   r    s   r  c                 C   sF   t t|tjo|jdk |j}t| ||}t|j }t	d
||S )zQevaluate constant unary expr if possible
    otherwise, raise GuardException
    unaryz{}{})r   r=   r   rD   rE   r+   r  r   fnevalrJ  )re   r    r  	inner_varr  rE   r   r   r   r    s
   
r  c                 C   sR   t t|tjo|jdk t| ||j}t| ||j}t|j	 }t
d|||S )zRevaluate constant binary expr if possible
    otherwise, raise GuardException
    rA  z{}{}{})r   r=   r   rD   rE   r  lhsrhsr   r  r  rJ  )re   r    r  arg1arg2rE   r   r   r   r    s
   
r  ).r  rb  r   pytypesrB  r   numpyrx   numba.parfors.parforr9   
numba.corer   r   r   r   numba.core.typing.templatesr   r	   numba.core.typingr
   r   r   numba.core.ir_utilsr   r   r   r   r   r   r   r   r   numba.core.errorsr   numba.core.utilsr   r   objectr   rO   rf  r$  r  r  r  r  r   r   r   r   <module>   s8   ,     nX