a
    .;b6                     @   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 d S Nr    )dim_sizeindex_constr   r   ;lib/python3.9/site-packages/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||r8|| |||< q8q,|sdd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rtd	q|d
}|jjj }t| j||
j|
j | j! j"\}}}|j#dd} $|	||||j%|||	}|
jd| | |
j|d d  |
_qttjrtjtjrjjdkrt&t' jjdkrt(dj _qqpd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       z#StencilPass.run.<locals>.<dictcomp>c                 3   s   | ]} j |j V  qd S r   )r!   namer-   r'   r   r   	<genexpr>K   r2   z"StencilPass.run.<locals>.<genexpr>zITuple parameters not supported for stencil kernels in parallel=True mode.outindex_offsets   )stencilnumba))Znumba.stencils.stencilr)   r   r    blocksitems
isinstanceappendreversedlist	enumeratebodyr   Assignr+   Expropfuncr3   dictkwsrangelenr,   tupler   Z	BaseTuple
ValueErrorgetget_stencil_irr$   scopelocr!   r"   options_mk_stencil_parfortargetr   r   Const)r'   r)   Z
call_table_Zstencil_callsZstencil_dictZcall_varnameZ	call_listZone_calllabelblockr/   rH   
input_dictin_argsZarg_typemapZarg_typeout_arrsf
stencil_irZrtarg_to_arr_dictr7   	gen_nodesr   )r'   r0   r   run+   sh    







(
zStencilPass.runc              	   C   s   |  D ]\}}|j}|j}g }|jD ]x}	t|	tjr| }
t|
tjrdt|
j	tj
rd|
j	jdkshJ |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<   rO   rP   rB   r=   r   ReturnpoprC   r+   rD   rE   r>   ZJump)r'   r;   exit_value_varparfor_body_exit_labelrV   rW   rO   rP   new_bodyr0   Z	prev_stmtr   r   r   replace_return_with_setitemg   s     

z'StencilPass.replace_return_with_setitemc
           H   
   C   s  g }
|j }tjdkr4td||||||| t| |d }| j|j }t|| j\}}t	|}t
|||| j| j tjdkrtd t| t|| jj|| j tjdkrtd t| | j|j j}|j}|j}g }t|D ].}t|td|}tj| j|j< || q| ||||||	\}}tjdkrTtd t| g }| j|}||}|t|ksJ t|D ]R}| || || |
||}| || |
||}|t j!j"#|| ||d qt$|% d }t&||||< t|td|}|j'| j|j< g } |dkr4|d }!nPt|td	|}!tj()tj|| j|!j< tj*+||}"t,|"|!|}#| |# tjdkrtd
 t| t&||}$|du r| j|j }td}%t||%|}&tj*-|d|}'tj()tj|j| j|%< |$j./t,|'|&|g td}(t||(|})d|j0v rr|j0d }*|j't1j22|*krft3d|'|*}+n
|'d}+t4|+|},|j'| j|(< |$j./t,|,|)|g td}-t||-|}t j5jj67|j'|j|j8| j|j< t|td|}.tj9:t;| j|.j< t<dt;|}/t,|/|.|}0|$j.|0 tj*-|.|j'j|}1t|td|}2tj=>|j'| j|2j< t,|1|2|}3|$j.|3 t?dt;j@||&|)|2g| jA| j| j}4|B|| |$j./|4 nd|j0v rp|j0d }*t1j22|*}5| jAC|5|j's
d}6tD|6t|td|}7| jAEtF}8|8| j|7j< t<dtF|}9t,|9|7|}:|$j.|: | jAG|8tjHfd i };tj*jI|7dd|d}<|;| j|<< t|td|}=tjJ| j|=j< t,|<|=|}>|$j.|> t4|'|*|}?t|td|}@|j'| j|@j< t,|?|@|}A|$j.|A tK|tFdd|=|@|}B|$j.|B tLtjH| j|j | j|=j | j|j j'};|;| j|B< | M||| tjdkrtd t| tN||!||}CtLtjH| j|j | j|!j | j|j j'| j|C< || j./|  || j.|C tOdd}Dt|td|D}Et,tj4d|Dd |E|D}A|| j.|A || j.tP|E|D tQ|}|t$|%  j.R  tjdkrtd! t| d"||gf}Ft j!j"S||$|||!||F| jT}G|
|G |
t,||| |
S )#z> Converts a set of stencil kernel blocks to a parfor.
        r8   rR   r   z#stencil_blocks after copy_propagatez'stencil_blocks after removing dead codez$parfor_index_varz-stencil_blocks after replace stencil accessesz$parfor_exit_valuez$parfor_index_tuple_varz.stencil_blocks after creating parfor index varNZin_arr_shapeshapeZzero_valcvalz-cval type does not match stencil return type.Zstencil_outputz	$np_g_varnpz$np_attr_attrfullz	$py_g_varslice   r   )rF   r,   rH   rP   z$slice_instz$cval_constz%stencil_blocks after replacing returnZstencilparfor_dummy)rP   z#stencil_blocks after adding SetItemr9   )Ur;   r   DEBUG_ARRAY_OPTprintr   dump_blocksr!   r3   Zcopy_propagateget_name_var_tableZapply_copy_propagater"   Zremove_deadr    	arg_namesndimrO   rP   rI   r   Varr   r   intpr>   _replace_stencil_accessesr#   Zget_equiv_setZ	get_shaperJ   _get_stencil_last_ind_get_stencil_start_indr:   ZparforsparforZLoopNestmaxkeysZBlockdtype
containersUniTuplerD   build_tuplerC   getattrrB   extendrQ   r   ZtypeofrL   rT   ZcoreZnpytypesZArrayZlayoutmiscZModuleri   Global	functionsZNumberClassZgen_np_callrj   r$   Zinsert_equivZcan_convertr   Zresolve_value_typerk   resolve_function_typeZnoner*   Zslice2_typeStaticSetItemr
   rf   SetItemZLocra   Zsimplify_CFGrb   ZParforr&   )Hr'   rV   rY   rZ   r\   r7   rS   return_typestencil_funcr]   r^   stencil_blocksin_arrZ
in_arr_typZin_cpsZout_cpsname_var_tablendimsrO   rP   parfor_varsr/   Z
parfor_varstart_lengthsend_lengthsZ	loopnestsZ	equiv_setZin_arr_dim_sizeslast_indZ	start_indrd   rc   Zfor_replacing_retZparfor_ind_var
tuple_calltuple_assignZ
init_blockZ
shape_nameZ	shape_varZshape_getattrZ	zero_nameZzero_varrh   Ztemp2Z
full_constZso_nameZdtype_g_np_varZ
dtype_g_npZdtype_g_np_assignZdtype_np_attr_callZdtype_attr_varZdtype_attr_assignZstmtsZcval_tymsg	slice_varZslice_fn_tyZslice_gZslice_assignedZsigZcallexprZslice_inst_varZslice_assignZcval_const_valZcval_const_varZcval_const_assignZsetitemexprZsetitem_callZ	dummy_locZret_const_varpatternry   r   r   r   rR      s   





































zStencilPass._mk_stencil_parforc                 C   s4  |}|dkr0t |td|}tj| j|j< t|tj	rRt 
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   Zstencil_const_varr   Zcompute_last_ind_varr   r   )r   rt   r   r   ru   r!   r3   r=   numbersNumberrC   rT   r>   r:   Znjitr   r   Z
Dispatcherr   rD   r*   Zget_call_typer$   r"   )r'   r   Z
end_lengthr^   rO   rP   r   r   const_assignZg_varZ
check_funcZfunc_typZg_objZg_assign
index_callindex_assignr   r   r   rw   n  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sRJ |j d }t||g ||jd d 7 }|jd jj}|S )Nr   c                 S   s   t t| dS r   )absmin)Zs_lengthr   r   r   get_start_ind  s    z9StencilPass._get_stencil_start_ind.<locals>.get_start_indr8   )r=   intr   r   r   r$   r%   r   ru   r!   r"   rJ   r;   popitemr   rB   r+   )	r'   Zstart_lengthr^   rO   rP   r   f_irrW   Zret_varr   r   r   rx     s    

z"StencilPass._get_stencil_start_indc              	      s  j }|d }dd |D }	d|jv r`|jd D ]}
|
 vr0tdq0 fdd|jd D }ng }|j|v rvtdj|j j}|j}|j}|jdu }|r|dg }|dg }n d	d |jD }d
d |jD }t	
|}d}| D ]\}}g }|jD ]}t|tjr@t|jtjr@|jjdv r@|jjj|	v sjt|tjs\t|tjrr|jj|	v rrt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 }|r6|t||||}|rt|tjs^tdd |D rftdttt||}ttt ||}d}|t||||}|dkr|d }nPt|t!d|}t"j#$t"j%|j|j< tj&||}t|||}|'| t(fdd|D r0j|jjj j)}nj|jjj }tj*|jj||}t+|j|jjj j|j j,|< ||_|'| q||_q|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   )r3   r.   xr   r   r   
<listcomp>  r2   z9StencilPass._replace_stencil_accesses.<locals>.<listcomp>Zstandard_indexingz[Standard indexing requested for an array name not present in the stencil kernel definition.c                    s   g | ]} | qS r   r   r   )r]   r   r   r     r2   zYThe first argument to a stencil kernel must use relative indexing, not standard indexing.Nc                 S   s   g | ]}|d  qS )r   r   r   r   r   r   r     r2   c                 S   s   g | ]}|d  qS )r8   r   r   r   r   r   r     r2   F)setitemZstatic_setitemz?Assignments to arrays passed to stencil kernels is not allowed.)Zstatic_getitemgetitemr8   r3   c                    s   g | ]}t  j|qS r   )_get_const_index_exprr    r.   v)r'   r\   r   r   r     s   c                 S   s   g | ]}t |t qS r   r=   r   r   r   r   r   r     r2   z<Variable stencil index only possible with known neighborhoodTz$parfor_index_ind_varc                    s   g | ]} j |j tjkqS r   )r!   r3   r   ru   r   r4   r   r   r     s   z=Stencil kernel with no accesses to relatively indexed arrays.)-r;   rQ   rL   r3   r!   rs   rO   rP   Zneighborhoodr   Zget_tuple_tabler<   rB   r=   r   rC   r+   rD   rE   r   r   rS   indexhasattrZbuild_definitionsZ_definitions_add_index_offsetsr@   rt   anymapr   rz   r   r   r}   r~   ru   r   r>   allr|   r   r
   r"   )r'   r\   r   rY   r7   r   r]   r   r   Zin_arg_namesr   Zstandard_indexedr   rO   rP   Zneed_to_calc_kernelr   r   Ztuple_tableZfound_relative_indexrV   rW   re   r0   
index_list
index_varsZind_varr   r   Zgetitem_return_typZgetitem_callr   )r]   r'   r\   r   rv     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rt	|t
d|}	tj| j|	j< tt|| ||	|}
||
 || }t|trt	|t
d|}tj| j|j< tt|| |||}
||
 t|	ts&t| j|	j tjjr\| j|j tjks>J | |	||||}|| qNt|tst| j|j tjjr| j|	j tjksJ | ||	|||}|| qNt	|t
d|}tj| j|j< tjtj|	||}| jtjtjtjfi | j|< t|||}|| || qN|| |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   4  r2   z2StencilPass._add_index_offsets.<locals>.<listcomp>old_index_var
offset_varZoffset_stencil_index)rJ   r   r@   r   r   rI   r=   r   r   rt   r   r   ru   r!   r3   rC   rT   r>   rk   r   Z	SliceType_add_offset_to_slicerD   binopoperatorr$   r   r"   r   )r'   r   r7   re   rO   rP   	out_nodesr   r/   r   r   r   	index_varr   r   r   r   r   r   ,  s~    







zStencilPass._add_index_offsetsc                 C   s   t |trBd|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   )rk   startstop)Z	old_sliceoffsetr   r   r   r   |  s    z+StencilPass._add_offset_to_slice.<locals>.fr   )r=   rk   formatr   r   execr   ru   r!   r3   r    Zfunc_idrF   __globals__r   r$   r%   r"   r;   r   r   rB   r+   r   )r'   r   r   r   rO   rP   Zf_textr   r,   Zarg_typsZ
slice_typeZ_globalsr   rU   rW   Z	new_indexr   r   r   r   p  s,    




z StencilPass._add_offset_to_sliceN)__name__
__module____qualname__r(   r_   rf   rR   rw   rx   rv   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 rhtdddlm}	 |	j}|	|| 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 s 0    Y  t |t! }t"|# }t$|# }tj%&| tj'dkr|t(d t)| i }|jj* D ].\}}t+,|t-||}|||< |||j.< qt/|| tj'dkrt(d t)| |jj* D ]\}}|||< qi }|0 D ]}|j1D ]t}t2|t+j3rt2|j4t+j5rtj'dkrjt(d||j4j6|j4j.|j4j6|v  ||j4j6 j.||j4j.< ||j4j6 |_4qqtj'dkrt(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_stager6   z6Cannot use the reserved word 'out' in stencil kernels.zbefore-inferenceNr   )r    r!   r"   ZliftedZlifted_fromr,   r   Zhtml_outputr8   zInitial stencil_blockszAfter replace_varsrX   r]   zAfter replace arg with arr)9Znumba.core.cpur   Znumba.core.registryr   Znumba.core.annotationsr   Znumba.core.typed_passesr   Z	kernel_ircopydeepcopyr;   r   rq   rL   Ztarget_contextZnested_contextDummyPipeliner   Zrewrite_registryZapplystater$   r%   r    r,   r!   r   r"   ZTypeAnnotationr   ZHTMLZadd_offset_to_labelsZ
next_labelr   r{   rz   Z_the_max_labelupdatern   ro   rp   r<   r   rt   r   r3   Zreplace_varsvaluesrB   r=   rC   r+   ZArgr   Zremove_delsZget_return_type)r[   r$   r,   rO   rP   rX   r!   r"   r   r   r   r   Zstencil_func_irr   r   r%   tprU   Z	min_labelZ	max_labelZvar_dictr   typZnew_varr*   Zcall_typr]   rW   r0   r   r   r   rN     s    
&





rN   c                   @   s   e Zd Zdd ZdS )r   c                 C   sP   ddl m} | | _|| j_|| j_|| j_|| j_d | j_d | j_d | j_	d S )Nr   )	StateDict)
Znumba.core.compilerr   r   r$   r%   r,   r    r!   r   r"   )r'   r$   r%   r,   r   r   r   r   r   r(     s    zDummyPipeline.__init__N)r   r   r   r(   r   r   r   r   r     s   r   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)r\   r    r   	const_valr   r   r   r     s    r   c                 C   sr   t t|tj tt| ||}|dur*|S t| |}tt| ||}|durP|S tt	| ||}|durj|S t
dS )zWinner constant inference function that calls constant, unary and binary
    cases.
    N)r   r=   r   rt   r   _get_const_two_irsr   Zget_definition_get_const_unary_expr_get_const_binary_exprr   )r\   r    r   	var_const	index_defr   r   r   r     s     r   c                 C   s8   t t| |}|dur|S t t||}|dur0|S tdS )zWget constant in either of two IRs if available
    otherwise, throw GuardException
    N)r   r   r   )Zir1Z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
    Zunaryz{}{})r   r=   r   rD   rE   r+   r   r   fnevalr   )r\   r    r   Z	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
    r   z{}{}{})r   r=   r   rD   rE   r   ZlhsZrhsr   r   r   r   )r\   r    r   Zarg1Zarg2rE   r   r   r   r   )  s
    
r   ).r   r   r   Zpytypesr   r   Znumpyri   Znumba.parfors.parforr:   Z
numba.corer   r   r   r   Znumba.core.typing.templatesr   r	   Znumba.core.typingr
   r   r   Znumba.core.ir_utilsr   r   r   r   r   r   r   r   r   Znumba.core.errorsr   Znumba.core.utilsr   r   objectr   rN   r   r   r   r   r   r   r   r   r   r   <module>   s4   ,    nX