U
    ¿|e1O ã                   @   sì  d Z ddlZddlZddlZddl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mZmZmZ ddlmZ ddlZddlmZ ddlmZ ddlmZ ddlZdd	lmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z% dd
lm&Z&m'Z' ddl(m)Z)m*Z* ddl+m,Z,m-Z- ddl.m/Z/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_m`Z`maZa ddlbmcZcmdZdmeZemfZf ddlgmhZh ddlimjZjmkZk ddllmmZm ddlnmoZompZpmqZqmrZrmsZsmtZt ddl3muZu ddlZddlvZvddlvZwddlxmyZy ddlzZddl{m|Z| dZ}ej~e}dd�Zdd„ Z€dZ�dd„ Z‚eue‚ƒ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.d/„ Z‹d0d1„ ZŒd2d3„ Z�d4d5„ ZŽd6d7„ Z�d8d9„ Z�d:d;„ Z‘d<d=„ Z’d>d?„ Z“d@dA„ Z”dBdC„ dDdC„ e†e‡e†e‡eŽe�e�e‘e’e�e“e”dEœZ•dFdG„ Z–dHe–iZ—e4dIdJ„ ƒZ˜e4dKdL„ ƒZ™e4dMdN„ ƒZše4dOdP„ ƒZ›edQdRdSgƒZœeœdNešƒeœdPe›ƒeœdLe™ƒeœdJe˜ƒeœdLe™ƒeœdJe˜ƒdTœZ�G dUdV„ dVe„ƒZžG dWdX„ dXejŸej ƒZ¡dYdZ„ Z¢e¢eyj£e¡< G d[d\„ d\e„ƒZ¤G d]d^„ d^e„ƒZ¥d_d`„ Z¦G dadb„ dbƒZ§G dcdd„ ddƒZ¨dedf„ Z©G dgdh„ dhƒZªdÿdidj„Z«dkdl„ Z¬G dmdn„ dnƒZ­G dodp„ dpƒZ®G dqdr„ drƒZ¯dsdt„ Z°G dudv„ dve§ƒZ±G dwdx„ dxe§ƒZ²G dydz„ dze§ƒ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�„ Z¾d‘d’„ Z¿d“d”„ ZÀd•d–„ ZÁed—d˜d™dšgd›dœ�ZÂ�d d�dž„ZÃdŸd „ ZÄd¡d¢„ ZÅd£d¤„ ZÆd¥d¦„ ZÇd§d¨„ ZÈd©dª„ ZÉd«d¬„ ZÊeÊe%jËe¡< �dd­d®„ZÌeÌe jÍe¡< d¯d°„ ZÎeÎe jÏe¡< d±d²„ ZÐeÐe!jÑe¡< �dd³d´„ZÒ�ddµd¶„ZÓd·d¸„ ZÔd¹dº„ ZÕd»d¼„ ZÖd½d¾„ Z×ed¿dÀdÁdÂgƒZØdÃdÄ„ ZÙdÅdÆ„ ZÚdÇdÈ„ ZÛ�ddÉdÊ„ZÜdËdÌ„ ZÝdÍdÎ„ ZÞdÏdÐ„ ZßdÑdÒ„ Zàeße%jáe¡< dÓdÔ„ ZâdÕdÖ„ Zãd×dØ„ Zäeäe%jåe¡< dÙdÚ„ Zæ�ddÛdÜ„Zç�ddÝdÞ„Zèdßdà„ Zéeée%jêe¡< dádâ„ Zëeëe%jìe¡< �ddãdä„Zídådæ„ Zîdçdè„ Zïdédê„ Zð�ddëdì„Zñeñe%jòe¡< �d	dídî„Zóeóe%jôe¡< �d
dïdð„Zõeõe%jöe¡< dñdò„ Z÷e÷e%jøe¡< dódô„ Zùeùe%júe¡< dõdö„ Zûeûe#jüe¡< �dd÷dø„Zýeýe%jþe¡< edùdú„ ƒZÿe/eƒG dûdü„ düe0ƒƒ�Z dýdþ„ �ZdS (  aË  
This module transforms data-parallel operations such as Numpy calls into
'Parfor' nodes, which are nested loops that can be parallelized.
It also implements optimizations such as loop fusion, and extends the rest of
compiler analysis and optimizations to support Parfors.
This is similar to ParallelAccelerator package in Julia:
https://github.com/IntelLabs/ParallelAccelerator.jl
'Parallelizing Julia with a Non-invasive DSL', T. Anderson et al., ECOOP'17.
é    N)Úreduce)ÚdefaultdictÚOrderedDictÚ
namedtuple)Úcontextmanager)Úmake_dataclass)Úir)Úimpl_ret_untracked)ÚtypesÚtypingÚutilsÚerrorsr   ÚanalysisÚpostprocÚrewritesÚ	typeinferÚconfigÚir_utils)ÚprangeÚpndindex)Údatetime_minimumÚdatetime_maximum)Úas_dtypeÚnumpy_version)Úinfer_globalÚAbstractTemplate)ÚStencilPass)Úregister_jitableÚlower_builtin)+Úmk_unique_varÚ
next_labelÚmk_allocÚget_np_ufunc_typÚmk_range_blockÚmk_loop_headerÚget_name_var_tableÚreplace_varsÚreplace_vars_innerÚ
visit_varsÚvisit_vars_innerÚremove_deadÚcopy_propagateÚget_block_copiesÚapply_copy_propagateÚdprint_func_irÚfind_topo_orderÚget_stmt_writesÚrename_labelsÚget_call_tableÚsimplifyÚsimplify_CFGÚhas_no_side_effectÚcanonicalize_array_mathÚadd_offset_to_labelsÚfind_callnameÚfind_build_sequenceÚguardÚrequireÚGuardExceptionÚcompile_to_numba_irÚget_definitionÚbuild_definitionsÚreplace_arg_nodesÚreplace_returnsÚ
is_getitemÚ
is_setitemÚis_get_setitemÚindex_var_of_get_setitemÚset_index_var_of_get_setitemÚfind_potential_aliasesÚreplace_var_namesÚtransfer_scope)Úcompute_use_defsÚcompute_live_mapÚcompute_dead_mapsÚcompute_cfg_from_blocks)ÚCFGraph)ÚnpydeclÚ	signature)ÚFunction)Úrandom_int_argsÚrandom_1arg_sizeÚrandom_2arg_sizelastÚrandom_3arg_sizelastÚrandom_callsÚassert_equiv)Úoverload)Úarray_analysis)ÚstencilparforéP   F)ÚwidthÚdrop_whitespacec                 C   s&   |   ¡ D ]}dd„ t |¡D ƒ qd S )Nc                 S   s   g | ]}t |ƒ‘qS © ©Úprint©Ú.0Úyr^   r^   úQ/var/www/website-v5/atlas_env/lib/python3.8/site-packages/numba/parfors/parfor.pyÚ
<listcomp>k   s     z!print_wrapped.<locals>.<listcomp>)Ú
splitlinesÚ_txtwrapperÚwrap)ÚxÚlr^   r^   rd   Úprint_wrappedi   s    rk   c                   C   s   d S ©Nr^   r^   r^   r^   rd   Úinit_pranger   s    rm   c                  C   s   dd„ } | S )Nc                   S   s   d S rl   r^   r^   r^   r^   rd   Úno_opw   s    z#init_prange_overload.<locals>.no_opr^   )rn   r^   r^   rd   Úinit_prange_overloadu   s    ro   c                   @   s   e Zd Zdd„ ZdS )Úinternal_prangec                 G   s   t |Ž S rl   )Úrange)ÚclsÚargsr^   r^   rd   Ú__new__}   s    zinternal_prange.__new__N)Ú__name__Ú
__module__Ú__qualname__rt   r^   r^   r^   rd   rp   {   s   rp   c                 C   sR   |j dkrdd„ }n:|j dkrFt|jtjtjfƒr<dd„ }qNdd„ }ndd„ }|S )Nr   c                 S   s   | d S ©Nr^   r^   ©Úin_arrr^   r^   rd   Úmin_1…   s    z min_parallel_impl.<locals>.min_1é   c                 S   sR   t jj ¡  tt| ƒƒ t jj | j	¡}t jj 
t| ƒ¡D ]}t|| | ƒ}q:|S rl   )ÚnumbaÚparforsÚparforrm   Úmin_checkerÚlenÚcpythonÚbuiltinsÚget_type_max_valueÚdtyperp   r   ©rz   ÚvalÚir^   r^   rd   r{   Š   s    c                 S   sR   t jj ¡  tt| ƒƒ t jj | j	¡}t jj 
t| ƒ¡D ]}t|| | ƒ}q:|S rl   )r}   r~   r   rm   r€   r�   r‚   rƒ   r„   r…   rp   Úminr†   r^   r^   rd   r{   ’   s    c                 S   sL   t jj ¡  tt| ƒƒ t jj | j	¡}t  
| j¡D ]}t|| | ƒ}q4|S rl   )r}   r~   r   rm   r€   r�   r‚   rƒ   r„   r…   r   Úshaper‰   r†   r^   r^   rd   r{   š   s    ©ÚndimÚ
isinstancer…   r
   Ú
NPDatetimeÚNPTimedelta)Úreturn_typeÚargr{   r^   r^   rd   Úmin_parallel_impl�   s    




r’   c                 C   sR   |j dkrdd„ }n:|j dkrFt|jtjtjfƒr<dd„ }qNdd„ }ndd„ }|S )Nr   c                 S   s   | d S rx   r^   ry   r^   r^   rd   Úmax_1¥   s    z max_parallel_impl.<locals>.max_1r|   c                 S   sR   t jj ¡  tt| ƒƒ t jj | j	¡}t jj 
t| ƒ¡D ]}t|| | ƒ}q:|S rl   )r}   r~   r   rm   Úmax_checkerr�   r‚   rƒ   Úget_type_min_valuer…   rp   r   r†   r^   r^   rd   r“   ª   s    c                 S   sR   t jj ¡  tt| ƒƒ t jj | j	¡}t jj 
t| ƒ¡D ]}t|| | ƒ}q:|S rl   )r}   r~   r   rm   r”   r�   r‚   rƒ   r•   r…   rp   Úmaxr†   r^   r^   rd   r“   ²   s    c                 S   sL   t jj ¡  tt| ƒƒ t jj | j	¡}t  
| j¡D ]}t|| | ƒ}q4|S rl   )r}   r~   r   rm   r”   r�   r‚   rƒ   r•   r…   r   rŠ   r–   r†   r^   r^   rd   r“   º   s    r‹   )r�   r‘   r“   r^   r^   rd   Úmax_parallel_impl£   s    




r—   c                 C   sx   t jj ¡  tt| ƒƒ |  ¡ }t jj 	|j
¡}tj d|¡}t jj t|ƒ¡D ] }tj ||| ¡}t||ƒ}qP|jS ©Nr   )r}   r~   r   rm   Úargmin_checkerr�   Úravelr‚   rƒ   r„   r…   r   Ú
IndexValuerp   r‰   Úindex©rz   ÚAÚinit_valÚivalrˆ   Z	curr_ivalr^   r^   rd   Úargmin_parallel_implÃ   s    r¡   c                 C   sx   t jj ¡  tt| ƒƒ |  ¡ }t jj 	|j
¡}tj d|¡}t jj t|ƒ¡D ] }tj ||| ¡}t||ƒ}qP|jS r˜   )r}   r~   r   rm   Úargmax_checkerr�   rš   r‚   rƒ   r•   r…   r   r›   rp   r–   rœ   r�   r^   r^   rd   Úargmax_parallel_implÎ   s    r£   c                 C   sP   t jj ¡  | jd }|jd }d}t jj |¡D ]}|| | ||  7 }q2|S r˜   )r}   r~   r   rm   rŠ   rp   )ÚaÚbrj   ÚmÚsrˆ   r^   r^   rd   Údotvv_parallel_implÙ   s    

r¨   c                 C   s^   t jj ¡  | j}|j\}}t || j¡}t jj |¡D ] }|| | ||d d …f  7 }q8|S rl   )	r}   r~   r   rm   rŠ   ÚnpÚzerosr…   rp   )r¤   r¥   rj   r¦   ÚnÚcrˆ   r^   r^   rd   Údotvm_parallel_implä   s    
r­   c           	      C   st   t jj ¡  | j\}}|j}t || j¡}t jj |¡D ]6}d}t	|ƒD ]}|| ||f ||  7 }qH|||< q8|S r˜   )
r}   r~   r   rm   rŠ   r©   Úemptyr…   rp   rq   )	r¤   r¥   r¦   r«   rj   r¬   rˆ   r§   Újr^   r^   rd   Údotmv_parallel_implõ   s    

r°   c                 C   sX   t |tjjƒrTt |tjjƒrT|j|j  kr4dkr<n ntS |jdkrT|jdkrTtS d S )Nr|   é   )r�   r
   ÚnpytypesÚArrayrŒ   r¨   r°   )r�   ÚatypZbtypr^   r^   rd   Údot_parallel_impl  s    ÿrµ   c                    sD   | dƒ‰ |j dkrdd„ }n$|j dkr4‡ fdd„}n‡ fdd„}|S )Nr   c                 S   s   | d S rx   r^   ry   r^   r^   rd   Úsum_1  s    z sum_parallel_impl.<locals>.sum_1r|   c                    s8   t jj ¡  ˆ }t jj t| ƒ¡D ]}|| | 7 }q"|S rl   ©r}   r~   r   rm   rp   r�   r†   ©Úzeror^   rd   r¶     s
    c                    s2   t jj ¡  ˆ }t  | j¡D ]}|| | 7 }q|S rl   ©r}   r~   r   rm   r   rŠ   r†   r¸   r^   rd   r¶     s
    ©rŒ   )r�   r‘   r¶   r^   r¸   rd   Úsum_parallel_impl  s    


r¼   c                    sD   | dƒ‰ |j dkrdd„ }n$|j dkr4‡ fdd„}n‡ fdd„}|S )Nr|   r   c                 S   s   | d S rx   r^   ry   r^   r^   rd   Úprod_1)  s    z"prod_parallel_impl.<locals>.prod_1c                    s8   t jj ¡  ˆ }t jj t| ƒ¡D ]}|| | 9 }q"|S rl   r·   r†   ©Úoner^   rd   r½   ,  s
    c                    s2   t jj ¡  ˆ }t  | j¡D ]}|| | 9 }q|S rl   rº   r†   r¾   r^   rd   r½   3  s
    r»   )r�   r‘   r½   r^   r¾   rd   Úprod_parallel_impl%  s    


rÀ   c                    sD   | dƒ‰ |j dkrdd„ }n$|j dkr4‡ fdd„}n‡ fdd„}|S )Nr   c                 S   s   | d S rx   r^   ry   r^   r^   rd   Úmean_1A  s    z"mean_parallel_impl.<locals>.mean_1r|   c                    s@   t jj ¡  ˆ }t jj t| ƒ¡D ]}|| | 7 }q"|t| ƒ S rl   r·   r†   r¸   r^   rd   rÁ   D  s
    c                    s8   t jj ¡  ˆ }t  | j¡D ]}|| | 7 }q|| j S rl   )r}   r~   r   rm   r   rŠ   Úsizer†   r¸   r^   rd   rÁ   K  s
    r»   )r�   r‘   rÁ   r^   r¸   rd   Úmean_parallel_impl<  s    


rÃ   c                 C   s4   |j dkrdd„ }n|j dkr(dd„ }ndd„ }|S )Nr   c                 S   s   dS r˜   r^   ry   r^   r^   rd   Úvar_1U  s    z var_parallel_impl.<locals>.var_1r|   c                 S   s`   |   ¡ }tjj ¡  d}tjj t| ƒ¡D ](}| | | }|t |t 	|¡ ¡7 }q*|t| ƒ S r˜   )
Úmeanr}   r~   r   rm   rp   r�   r©   ÚrealÚconj©rz   r¦   Zssdrˆ   r‡   r^   r^   rd   rÄ   X  s    c                 S   sX   |   ¡ }tjj ¡  d}t | j¡D ](}| | | }|t |t 	|¡ ¡7 }q$|| j
 S r˜   )rÅ   r}   r~   r   rm   r   rŠ   r©   rÆ   rÇ   rÂ   rÈ   r^   r^   rd   rÄ   c  s    r»   )r�   r‘   rÄ   r^   r^   rd   Úvar_parallel_implS  s    




rÉ   c                 C   s   dd„ }|S )Nc                 S   s   |   ¡ d S )Ng      à?)Úvarry   r^   r^   rd   Ústd_1p  s    z std_parallel_impl.<locals>.std_1r^   )r�   r‘   rË   r^   r^   rd   Ústd_parallel_implo  s    rÌ   c                    s¤   t | jƒ‰ ‡ fdd„}‡ fdd„}‡ fdd„}tdd„ |D ƒƒrJd	d
„ }ndd
„ }t|ƒdkrb|S t|ƒdkrr|S t|ƒdkr‚|S t|ƒdkr’|S td |¡ƒ‚d S )Nc                    s   t  d| dˆ ¡S )Nr   r|   ©r©   Úarange)Ústop©r…   r^   rd   Úarange_1w  s    z&arange_parallel_impl.<locals>.arange_1c                    s   t  | |dˆ ¡S ©Nr|   rÍ   ©ÚstartrÏ   rÐ   r^   rd   Úarange_2z  s    z&arange_parallel_impl.<locals>.arange_2c                    s   t  | ||ˆ ¡S rl   rÍ   )rÔ   rÏ   ÚsteprÐ   r^   rd   Úarange_3}  s    z&arange_parallel_impl.<locals>.arange_3c                 s   s   | ]}t |tjƒV  qd S rl   )r�   r
   ÚComplex©rb   r¤   r^   r^   rd   Ú	<genexpr>€  s     z'arange_parallel_impl.<locals>.<genexpr>c           
      S   sx   t jj ¡  ||  | }t |j¡}t |j¡}tt	t
||ƒdƒƒ}t ||¡}t jj |¡D ]}	| |	|  ||	< q^|S r˜   )r}   r~   r   rm   ÚmathÚceilrÆ   ÚimagÚintr–   r‰   r©   r®   rp   )
rÔ   rÏ   rÖ   r…   Znitems_cÚnitems_rZnitems_iÚnitemsÚarrrˆ   r^   r^   rd   Úarange_4�  s    z&arange_parallel_impl.<locals>.arange_4c           	      S   sd   t jj ¡  t ||  | ¡}tt|dƒƒ}t 	||¡}| }t jj 
|¡D ]}| ||  ||< qJ|S r˜   )r}   r~   r   rm   rÛ   rÜ   rÞ   r–   r©   r®   rp   )	rÔ   rÏ   rÖ   r…   rß   rà   rá   r‡   rˆ   r^   r^   rd   râ   Œ  s    r|   r±   é   é   zparallel arange with types {})r   r…   Úanyr�   Ú
ValueErrorÚformat)r�   rs   rÑ   rÕ   r×   râ   r^   rÐ   rd   Úarange_parallel_implt  s     


rè   c                    sP   t | jƒ‰ dd„ }‡ fdd„}t|ƒdkr.|S t|ƒdkr>|S td |¡ƒ‚d S )Nc                 S   s   t  | |d¡S )Né2   )r©   ÚlinspacerÓ   r^   r^   rd   Ú
linspace_2¤  s    z*linspace_parallel_impl.<locals>.linspace_2c                    s\   t jj ¡  t |ˆ ¡}|d }||  }| |d< t jj |¡D ]}| |||   ||< q>|S )Nr|   r   )r}   r~   r   rm   r©   r®   rp   )rÔ   rÏ   Únumrá   ÚdivÚdeltarˆ   rÐ   r^   rd   Ú
linspace_3§  s    z*linspace_parallel_impl.<locals>.linspace_3r±   rã   zparallel linspace with types {})r   r…   r�   ræ   rç   )r�   rs   rë   rï   r^   rÐ   rd   Úlinspace_parallel_impl¡  s    

rð   c                 C   s   t S rl   )r¡   ©Úrr¤   r^   r^   rd   Ú<lambda>¹  ó    ró   c                 C   s   t S rl   )r£   rñ   r^   r^   rd   ró   º  rô   )©ÚargminÚnumpy©Úargmaxr÷   ©r‰   r÷   ©r–   r÷   ©Úaminr÷   ©Úamaxr÷   )Úsumr÷   )Úprodr÷   )rÅ   r÷   )rÊ   r÷   )Ústdr÷   )Údotr÷   )rÎ   r÷   )rê   r÷   c                 C   s    |j dkrdd„ }ndd„ }|S )z¦Parallel implementation of ndarray.fill.  The array on
       which to operate is retrieved from get_call_name and
       is passed along with the value to fill.
    r|   c                 S   s0   t jj ¡  t jj t| ƒ¡D ]}|| |< qd S rl   r·   r†   r^   r^   rd   Úfill_1Ï  s    
z"fill_parallel_impl.<locals>.fill_1c                 S   s*   t jj ¡  t  | j¡D ]}|| |< qd S rl   rº   r†   r^   r^   rd   r  Õ  s    
r»   )r�   rá   r‡   r  r^   r^   rd   Úfill_parallel_implÉ  s    

r  Úfillc                 C   s   | dkrt dƒ‚d S )Nr   zDzero-size array to reduction operation maximum which has no identity©ræ   ©Zarr_sizer^   r^   rd   r”   à  s    r”   c                 C   s   | dkrt dƒ‚d S )Nr   zDzero-size array to reduction operation minimum which has no identityr  r  r^   r^   rd   r€   æ  s    r€   c                 C   s   | dkrt dƒ‚d S )Nr   z*attempt to get argmin of an empty sequencer  r  r^   r^   rd   r™   ì  s    r™   c                 C   s   | dkrt dƒ‚d S )Nr   z*attempt to get argmax of an empty sequencer  r  r^   r^   rd   r¢   ñ  s    r¢   Úchecker_implÚnameÚfunc)rõ   rø   rú   rû   rü   rþ   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚLoopNestzÆThe LoopNest class holds information of a single loop including
    the index variable (of a non-negative integer value), and the
    range variable, e.g. range(r) is 0 to r-1 with step size 1.
    c                 C   s   || _ || _|| _|| _d S rl   )Úindex_variablerÔ   rÏ   rÖ   )Úselfr  rÔ   rÏ   rÖ   r^   r^   rd   Ú__init__	  s    zLoopNest.__init__c                 C   s   d  | j| j| j| j¡S )Nz3LoopNest(index_variable = {}, range = ({}, {}, {})))rç   r  rÔ   rÏ   rÖ   ©r  r^   r^   rd   Ú__repr__  s       ÿzLoopNest.__repr__c                 C   sb   g }|  | j¡ t| jtjƒr*|  | j¡ t| jtjƒrD|  | j¡ t| jtjƒr^|  | j¡ |S rl   )Úappendr  r�   rÔ   r   ÚVarrÏ   rÖ   )r  Úall_usesr^   r^   rd   Ú	list_vars  s    zLoopNest.list_varsN)ru   rv   rw   Ú__doc__r  r  r  r^   r^   r^   rd   r    s   r  c                       sV   e Zd ZdZdeƒ dœ‡ fdd„
Zdd„ Zdd	„ Zddd„Zddd„Z	dd„ Z
‡  ZS )ÚParforr   F)Úno_sequential_loweringÚracesc	                   s´   t t| ƒjd|d� t| ƒj| _t| ƒ jd7  _|| _|| _|| _|| _	d | _
|| _t|ƒdksft‚|g| _|| _|	| _|
| _g | _i | _d | _tjr°d}t| | j||¡ƒ d S )Nr   )ÚopÚlocr|   z9Parallel for-loop #{} is produced from pattern '{}' at {})Úsuperr  r  ÚtypeÚ
id_counterÚidÚ
loop_nestsÚ
init_blockÚ	loop_bodyÚ	index_varÚparamsÚ	equiv_setr�   ÚAssertionErrorÚpatternsÚflagsr  r  ÚredvarsÚreddictÚlowererr   ÚDEBUG_ARRAY_OPT_STATSr`   rç   )r  r   r!  r"  r  r#  r%  Úpatternr(  r  r  Úfmt©Ú	__class__r^   rd   r  #  s6    
þ  ÿzParfor.__init__c                 C   s,   dt | jƒ t| jƒ t| jƒ t| jƒ S )Nzid=)Ústrr  Úreprr   r"  r#  r  r^   r^   rd   r  U  s
    ÿÿzParfor.__repr__c                 C   sf   g }| j  ¡ D ] \}}|jD ]}|| ¡ 7 }qq| jD ]}|| ¡ 7 }q6| jjD ]}|| ¡ 7 }qP|S )zslist variables used (read/written) in this parfor by
        traversing the body and combining block uses.
        )r"  ÚitemsÚbodyr  r   r!  )r  r  rj   r¥   ÚstmtÚloopr^   r^   rd   r  Y  s    

zParfor.list_varsNc                 C   s8   |dk	r| j j}|| j _| j  |¡}|dk	r4|| j _|S )zvget the shape classes for a given variable.
        If a typemap is specified then use it for type resolution
        N)r%  ÚtypemapÚget_shape_classes)r  rÊ   r7  Zsave_typemapÚresr^   r^   rd   r8  j  s    
zParfor.get_shape_classesc                 C   sÚ   |pt j}td | j¡ dd¡|d� td| j|d� td| j|d� td| j|d� | j	D ]}t||d� q\td|d� | j
 |¡ t| j ¡ ƒD ]$\}}td	|f |d� | |¡ q”td
 | j¡ dd¡|d� d S )Nzbegin parfor {}é   ú-)Úfilezindex_var = z	params = zraces = zinit block:z	label %s:zend parfor {})ÚsysÚstdoutr`   rç   r  Úcenterr#  r$  r  r   r!  ÚdumpÚsortedr"  r3  )r  r<  ÚloopnestÚoffsetÚblockr^   r^   rd   r@  |  s    

zParfor.dumpc                 C   s|   | j dkrd}t|ƒ‚| j D ]Z}| |¡}|dkr>d}t|ƒ‚t|tjƒr|jtjkrd}t	 
|||jtjf | j¡‚qdS )z?
        Check that Parfors params are of valid types.
        Nz?Cannot run parameter validation on a Parfor with params not setzDCannot validate parameter %s, there is no type information availablea˜  Use of a tuple (%s) of length %d in a parallel region exceeds the maximum supported tuple size.  Since Generalized Universal Functions back parallel regions and those do not support tuples, tuples passed to parallel regions are unpacked if their size is below a certain threshold, currently configured to be %d. This threshold can be modified using the Numba environment variable NUMBA_PARFOR_MAX_TUPLE_SIZE.)r$  ræ   Úgetr�   r
   Ú	BaseTupleÚcountr   ÚPARFOR_MAX_TUPLE_SIZEr   ÚUnsupportedParforsErrorr  )r  r7  ÚmsgÚpÚtyr^   r^   rd   Úvalidate_params‹  s     


ÿþzParfor.validate_params)N)N)ru   rv   rw   r  Úsetr  r  r  r8  r@  rM  Ú__classcell__r^   r^   r/  rd   r    s   ô2

r  c                 C   sT   |j }t| ƒ}|j dd¡}| ||¡ t| |ƒ |jd | _|rL||jd< g g fS )z/Recursive array analysis for parfor nodes.
    r   N)Úfunc_irÚwrap_parfor_blocksÚ
equiv_setsrE  ÚrunÚunwrap_parfor_blocksr%  )r   r%  r7  rY   rP  Zparfor_blocksZbackup_equivsetr^   r^   rd   Ú_analyze_parfor¨  s    

rU  c                   @   sÖ   e Zd ZdZdd„ Zdd„ Zedd„ ƒZejdd„ ƒZd1d
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!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd2d+d,„Zd-d.„ Zd/d0„ Zd	S )3ÚParforDiagnosticsz…Holds parfor diagnostic info, this is accumulated throughout the
    PreParforPass and ParforPass, also in the closure inlining!
    c                 C   s>   d | _ tƒ | _d| _ttƒ| _ttƒ| _g | _i | _	d| _
d S )NZ__numba_parfor_gufuncF)r  ÚdictÚreplaced_fnsÚinternal_namer   ÚlistÚfusion_infoÚnested_fusion_infoÚfusion_reportsÚ
hoist_infoÚ	has_setupr  r^   r^   rd   r  ¾  s    

zParforDiagnostics.__init__c                 C   s\   || _ | j jj| _| j j| _|| _| j| jkr6d| _nd| j| jf | _|  	¡ | _
d| _d S )NzInternal parallel functionzFunction %s, %sT)rP  Úfunc_idÚfunc_qualnamer
  r  ÚlineÚfusion_enabledrY  ÚpurposeÚget_parforsÚinitial_parforsr_  )r  rP  rc  r^   r^   rd   ÚsetupË  s    

zParforDiagnostics.setupc                 C   s   | j S rl   ©Z
_has_setupr  r^   r^   rd   r_  Ú  s    zParforDiagnostics.has_setupc                 C   s
   || _ d S rl   rh  )r  Ústater^   r^   rd   r_  Þ  s    Nc                 C   s   t |  ¡ ƒS rl   )r�   re  ©r  Úblocksr^   r^   rd   Úcount_parforsâ  s    zParforDiagnostics.count_parforsc                 C   s    t |ƒ}|  ||¡ t|ƒ d S rl   )rQ  Ú_get_parforsrT  )r  r   Úparfors_listrk  r^   r^   rd   Ú_get_nested_parforså  s    z%ParforDiagnostics._get_nested_parforsc                 C   sB   |  ¡ D ]4\}}|jD ]$}t|tƒr| |¡ |  ||¡ qqd S rl   )r3  r4  r�   r  r  ro  )r  rk  rn  ÚlabelÚblkr5  r^   r^   rd   rm  ê  s
    


zParforDiagnostics._get_parforsc                 C   s   g }|   | jj|¡ |S rl   )rm  rP  rk  )r  rn  r^   r^   rd   re  ñ  s    zParforDiagnostics.get_parforsc                 C   sv   g }| j  ¡ D ]b\}}| dg ¡}|D ]H}t|jtjƒr&|jjdkr&tt	| j
|jƒ}|d k	r&|dkr&| |¡ q&q|S )NÚhoistedÚcall)r®   r÷   )r^  r3  rE  r�   Úvaluer   ÚExprr  r:   r8   rP  r  )r  ZallocsÚpf_idÚdatar5  Úinstrs  r^   r^   rd   Úhoisted_allocationsö  s    z%ParforDiagnostics.hoisted_allocationsc                 C   sô   t  |¡}|i krg tƒ fS tƒ }| ¡ D ]}|D ]}| |¡ q2q*t| ¡ ƒ}|| }|dkrftƒ }tƒ }ttt| ¡ ƒ |¡ƒd ƒD ]<}| 	|¡}	|	dk	rª|	||< qŠ|	g kr¾| |¡ qŠg ||< qŠg }
t
| ¡ ƒD ]}|
 || ¡ qØ|
|fS )zf
        compute adjacency list of the fused loops
        and find the roots in of the lists
        Nr|   )ÚcopyÚdeepcopyrN  ÚvaluesÚaddÚkeysrq   r–   ÚunionrE  rA  r  )r  Ú_ar¤   ZvtxÚvri   Zpotential_rootsÚrootsZ	not_rootsr‡   rj   r^   r^   rd   Úcompute_graph_info  s.    

"


z$ParforDiagnostics.compute_graph_infoc                    s(   ‡ fdd„‰ ˆ |||ddƒ\}}||fS )z»
        Computes the number of fused and serialized loops
        based on a fusion adjacency list `fadj` and a nested
        parfors adjacency list `nadj` for the root, `root`
        c                    s\   || D ]J}|d7 }|| g kr2|t | | ƒ7 }qˆ | ||||ƒ\}}||7 }|}q||fS rÒ   ©r�   )ÚfadjÚnadjÚrootÚnfusedÚnserialÚkÚnfÚns©Ú
count_rootr^   rd   rŽ  0  s    z/ParforDiagnostics.get_stats.<locals>.count_rootr   r^   )r  r…  r†  r‡  rˆ  r‰  r^   r�  rd   Ú	get_stats*  s    
zParforDiagnostics.get_statsc                 C   sB   g }|  || ¡ || D ]"}|| g kr|  |  ||¡¡ q|S )zf
        returns a list of nodes reachable in an adjacency list from a
        specified root
        )ÚextendÚreachable_nodes)r  Úadjr‡  ZfusersrŠ  r^   r^   rd   r‘  =  s    z!ParforDiagnostics.reachable_nodesc              	   C   s®  || d }|j d }td|jjd ƒ}| jjj}|  | j¡\}}|  | j¡\}	}
||	g}t	|t
ƒ�rª|d dk�rª|d d }|j|krštd|jd ƒS g }|D ]B}|r¢|| D ]}| |  ||¡¡ q²|r¢tdt|ƒd ƒ  S q¢|j ¡ D ]6}|jD ]*}|jj|krútd|jjd ƒ    S qúqð| jj ¡ D ]t}zV|j |¡}t|d ddƒD ]4}|j| }t	|tƒ�sVtd|jjd ƒ} �qŒ�qVW n tk
�r¤   Y nX �q4|S )zX
        pd_id - the parfors id
        parfors_simple - the simple parfors map
        r   r|   Úinternalr±   éÿÿÿÿ)r'  r–   r  rb  rP  Úfilenamerƒ  r\  r[  r�   Útupler  Úsort_pf_by_liner‰   r"  r|  r4  rk  rœ   rq   r  ræ   )r  rv  Úparfors_simpleÚpfr-  rb  r•  r†  Únrootsr…  ÚfrootsZgraphsZreported_locÚtmpr’  rŠ  rq  r5  Úidxrˆ   r^   r^   rd   r—  I  sD    






z!ParforDiagnostics.sort_pf_by_linec           	      C   sê   t ƒ }t| jdd„ d�D ]Ì}|jd }|jd }|j}t|tƒr¸|d dkr¸|d dkrŒd tt	|d	 d ƒƒ¡}|d	 d }d
|df }n,|d dkržd}n|d dkr°d}nds¸t
‚d}|rÔt||j||f ƒ |||f||j< q|S )Nc                 S   s   | j jS rl   )r  rb  ©ri   r^   r^   rd   ró   ‡  rô   z6ParforDiagnostics.get_parfors_simple.<locals>.<lambda>©Úkeyr   r   r|   r“  Ú.r±   z%s %sz(internal parallel version)Úuserzuser defined pranger   zinternal pndindexz5Parallel for-loop #%s: is produced from %s:
    %s
 
)rW  rA  rf  r'  r  r�   r–  ÚjoinÚreversedrZ  r&  rk   r  )	r  Úprint_loop_searchr˜  r™  Z	r_patternr-  r  Zreplfnr.  r^   r^   rd   Úget_parfors_simpleƒ  s*    


z$ParforDiagnostics.get_parfors_simplec                 C   s   |   | j¡\}}|   | j¡\}}t|ƒt|ƒkr>t|ƒ}|}nt|ƒ}|}tt|ƒ|ƒD ]}| g ¡ qXtƒ }	|r’|D ]}
||
 g krv|	 |
¡ qv||	A }i }|D ]}|  ||¡}d||f||< q¢i }|	D ]}|  ||¡}d||f||< qÊ| 	¡ }| 
|¡ |S )NÚfuseÚnest)rƒ  r[  r\  r�   rq   r  rN  r}  r—  rz  Úupdate)r  r˜  r…  r›  r†  Ú_nrootsÚlimrœ  ri   rš  rò   Z	all_rootsZfroots_linesrb  Znroots_linesÚ	all_linesr^   r^   rd   Úget_all_lines   s4    
zParforDiagnostics.get_all_linesc                 C   sÞ  | j jj}|  ¡ }| j jj}zt |¡ ¡ }W n t	k
rF   d }Y nX |�rÒ|�rÒt
dd„ |D ƒƒ}ttƒ}| ¡ D ]8\}	}
||	 d j|krv|  |	|¡}||  t|	ƒ¡ qvt
dgdd„ | ¡ D ƒ ƒ}|d|tt|ƒƒd    }g }| d¡ | d| ¡ | |d d	 ¡ d
}t
d| j jjd ƒ}t||ƒD ]ˆ\}}| |d ¡}|d k	�rfdd |¡ }nd}| d¡}t|ƒ}|�r–| |d ||¡}n| |d ||¡}| |||d …  ¡ �q8td |¡ƒ ntdƒ d S )Nc                 S   s   g | ]}t |ƒ‘qS r^   r„  ©rb   ri   r^   r^   rd   re   Õ  s     z4ParforDiagnostics.source_listing.<locals>.<listcomp>r|   c                 S   s   g | ]}t |ƒ‘qS r^   r„  r®  r^   r^   rd   re   Þ  s     r±   Ú
zParallel loop listing for %sr;  z	|loop #IDz{0:{1}}| {2}r   ú#ú, Ú ú zNo source available)rP  r  r•  rl  r`  r  ÚinspectÚ	getsourcerf   ÚOSErrorr–   r   rZ  r3  r—  r  r1  r|  r�   rb  Ú	enumeraterE  r£  Ústriprç   r`   )r  r˜  Úpurpose_strr•  rG  Ú	func_nameÚlinesZ	src_widthZmap_line_to_pfrŠ  r�  Z
match_lineZmax_pf_per_liner\   Únewlinesr.  ZlstartÚnorb  Zpf_idsZpfstrÚstrippedZsrclenrj   r^   r^   rd   Úsource_listingÌ  sF    





z ParforDiagnostics.source_listingc                    s  d‰t ˆƒ‰ ˆ ˆj¡\}}ˆ ˆj¡\}}t |ƒt |ƒkrJt |ƒ}|}nt |ƒ}|}tt |ƒ|ƒD ]}| g ¡ qd‡ ‡‡fdd„}	‡ ‡‡fdd„}
d}g }t| ¡ ƒD ]V\}}|\}}}|dkrÜ||krþ|
d||d|ƒ}q¨|d	krö|	|||||ƒ}q¨ds¨t‚q¨d S )
Nú+--c                    sN   ‡‡ ‡‡‡fdd„‰ || g krJt d| ƒ ˆ | ||dƒ tdƒ |d }|S )Nc              	      sÞ   t ˆ | d dˆ|df  ƒ || D ]²}|| g krÆg }| ˆ |d  d dˆ|df  ¡ | | g kr¬|ˆkr¬ˆ | |¡}|D ](}| ˆ |d  d dˆ|df  ¡ q‚ˆ |¡ t d |¡ƒ q&ˆ| |||d ƒ q&d S )Nr³  ú%s%s %sú
(parallel)r|   r¯  )rk   r  r‘  r£  )Úfadj_Únadj_ÚnrootÚdepthrŠ  rJ  Úfusedrˆ   )ÚfacÚprint_gÚreportedr  Úswordr^   rd   rÉ  	  s    $&
zHParforDiagnostics.print_unoptimised.<locals>.print_nest.<locals>.print_gúParallel region %s:r   r¯  r|   ©rk   r`   ©rÃ  rÄ  ZtherootrÊ  Ú	region_id©rÈ  r  rË  )rÉ  rÊ  rd   Ú
print_nest  s    z7ParforDiagnostics.print_unoptimised.<locals>.print_nestc                    s˜   g }t d| ƒ | ˆ | d dˆ|df  ¡ || g krvtˆ ||¡ƒ}|D ]$}| ˆ | d dˆ|df  ¡ qP|d }t d |¡ƒ tdƒ |S )NrÌ  r³  rÁ  rÂ  r|   r¯  )rk   r  rA  r‘  r£  r`   )rL  rv  r’  rÆ  rÏ  rJ  rÇ  rŠ  rÐ  r^   rd   Ú
print_fuse  s     "z7ParforDiagnostics.print_unoptimised.<locals>.print_fuser   r§  Úfr¨  )	r�   rƒ  r[  r\  rq   r  rA  r3  r&  )r  r»  r…  r›  r†  rª  r«  rœ  ri   rÑ  rÒ  rÏ  rÊ  rb  ÚinfoÚopt_tyrv  r’  r^   rÐ  rd   Úprint_unoptimisedø  s.    
z#ParforDiagnostics.print_unoptimisedc                    s˜  d‰t ˆƒ‰ ˆ ˆj¡\}}ˆ ˆj¡\}}t |ƒt |ƒkrJt |ƒ}|}nt |ƒ}|}tt |ƒ|ƒD ]}| g ¡ qdtƒ ‰‡ ‡‡‡fdd„}	‡ ‡‡‡fdd„}
d}g }t| ¡ ƒD ]X\}}|\}}}|dkræ||krä|
d||d|ƒ}q²|d	k�r|	|||||ƒ}q²ds²t	‚q²ˆ�rŒtˆ ¡ ƒD ]j\}}d
}|d }|d }|d }|dk�rl|d7 }t
||||||f ƒ n|d7 }t
||||f ƒ �qnt
dƒ d S )NrÀ  c                    st   ‡‡ ‡‡‡‡‡fdd„‰ || g krpt dˆ ƒ t dˆ|df ƒ |dddœˆˆ< ˆ | ||dƒ td	ƒ ˆd ‰ˆS )
Nc                    sæ   || D ]Ø}ˆ | d dˆ|df  }|| g kr®g }| | g krz|ˆkrzt ˆ | |¡ƒ}|d7 }|d dd„ |D ƒ¡7 }|d7 }ˆ |¡ t|ƒ ˆˆ d	  t|ƒ7  < nt|d ƒ ˆ| |||d
 ƒ ˆˆ d  d
7  < qd S )Nr³  rÁ  z(serialú, fused with loop(s): r±  c                 S   s   g | ]}t |ƒ‘qS r^   ©r1  r®  r^   r^   rd   re   V  s     zZParforDiagnostics.print_optimised.<locals>.print_nest.<locals>.print_g.<locals>.<listcomp>ú)rÇ  r|   Ú
serialized)rA  r‘  r£  r  rk   r�   )rÃ  rÄ  rÅ  rÆ  rŠ  rJ  rÇ  )rÈ  rÉ  rÏ  rÊ  r  ÚsummaryrË  r^   rd   rÉ  N  s    
zFParforDiagnostics.print_optimised.<locals>.print_nest.<locals>.print_grÌ  rÁ  rÂ  r   ©r‡  rÇ  rÚ  r|   r¯  rÍ  rÎ  ©rÈ  r  rÛ  rË  )rÉ  rÏ  rÊ  rd   rÑ  M  s    z5ParforDiagnostics.print_optimised.<locals>.print_nestc                    sž   t d| ƒ ˆ | d dˆ|df  }g }|| g krftˆ ||¡ƒ}|d7 }|d dd„ |D ƒ¡7 }|t|ƒd	d
œˆ|< |d7 }t |ƒ tdƒ |d }|S )NrÌ  r³  rÁ  z	(parallelr×  r±  c                 S   s   g | ]}t |ƒ‘qS r^   rØ  r®  r^   r^   rd   re   p  s     zIParforDiagnostics.print_optimised.<locals>.print_fuse.<locals>.<listcomp>r   rÜ  rÙ  r¯  r|   )rk   rA  r‘  r£  r�   r`   )rL  rv  r’  rÆ  rÏ  rJ  rÇ  rÝ  r^   rd   rÒ  i  s    z5ParforDiagnostics.print_optimised.<locals>.print_fuser   r§  rÓ  r¨  z5
 
Parallel region %s (loop #%s) had %s loop(s) fusedr‡  rÇ  rÚ  zE and %s loop(s) serialized as part of the larger parallel loop (#%s).r¡  z&Parallel structure is already optimal.)r�   rƒ  r[  r\  rq   r  rW  rA  r3  r&  rk   )r  r»  r…  r›  r†  rª  r«  rœ  ri   rÑ  rÒ  rÏ  rÊ  rb  rÔ  rÕ  rv  r’  rŠ  r�  rJ  r‡  rÇ  rÚ  r^   rÝ  rd   Úprint_optimised9  sH    



z!ParforDiagnostics.print_optimisedc                 C   s  d}t dƒ | j ¡ D ]ô\}}| dg ¡}|D ]Ú}t|jtjƒr.z¬|jj}|dkrêd}|j	}t
|||f ƒ ztj |j¡}	W n" tk
r    tj |j¡}	Y nX t |	¡}
|
rÞ|jrÞt
d|
|jdk rÊdn|jd	   ¡  ƒ t
d
ƒ d}W q. ttfk
�r   Y q.X q.q|�st
dƒ d S )NFzAllocation hoisting:rr  r®   z¸The memory allocation derived from the instruction at %s is hoisted out of the parallel loop labelled #%s (it will be performed before the loop is executed and reused inside the loop):z   Allocation:: r±   r   r|   z0    - numpy.empty() is used for the allocation.
TzNo allocation hoisting found)r`   r^  r3  rE  r�   rt  r   ru  Úattrr  rk   ÚosÚpathÚrelpathr•  ræ   ÚabspathÚ	linecacheÚgetlinesrb  r¸  ÚKeyErrorÚAttributeError)r  Úfoundrv  rw  r5  rx  rß  rJ  r  rá  r»  r^   r^   rd   Úallocation_hoist™  s2    

(
z"ParforDiagnostics.allocation_hoistc                 C   s¼   t dƒ t dƒ d}| jr¤| j ¡ D ]~\}}| dd ¡}| dd ¡}|sZ|sZt d| ƒ q$t d| ƒ |r„t dƒ d	d
„ |D ƒ d}|r$t dƒ dd
„ |D ƒ d}q$|s°tdƒ tdƒ d S )Nr²  zInstruction hoisting:Frr  Únot_hoistedzloop #%s has nothing to hoist.z	loop #%s:z  Has the following hoisted:c                 S   s   g | ]}t d | ƒ‘qS )ú    %sr_   ra   r^   r^   rd   re   Ç  s     z7ParforDiagnostics.instruction_hoist.<locals>.<listcomp>Tz   Failed to hoist the following:c                 S   s    g | ]\}}t d ||f ƒ‘qS )z
    %s: %sr_   ©rb   ri   rc   r^   r^   rd   re   Ë  s     zNo instruction hoisting foundzP--------------------------------------------------------------------------------)r`   r^  r3  rE  rk   )r  Zhoist_info_printedrv  rw  rr  rê  r^   r^   rd   Úinstruction_hoist¸  s,    z#ParforDiagnostics.instruction_hoistr|   c               	      sö  ˆ j stdƒ‚ˆ jjj}ˆ jj}ˆ j|kr4d}d}nd||f }d}d}d}d}d}	d}
d}d}d}d}d}|dkr~d}d}ntd	ƒ‚|d
kr’d}|dkržd}|dkr®d}	d}
|dkrÂd}d}d}|dkrÒ|sÒd S tdƒ tt	d ƒ td|  
t	d¡ƒ tt	d ƒ tdƒ |�r$td 
t	d¡ƒ ˆ  |¡}ˆ  ¡ }|�rTtd| ƒ tdt	 ƒ ˆ jjj}ztj |¡}W n" tk
�r�   tj |¡}Y nX |�r¤ˆ  ||¡ d‰ˆ  ¡ }dd„ |D ƒ}t|ƒ}|�sÒ|	�rt�sötd 
t	d¡ƒ d}t|ƒ nd}t|ƒ tt	d ƒ |dk�râ‡ ‡fdd„}|�r`ˆ jD ],}|\}}}td||f ƒ td| ƒ �q2ˆ ji k�rˆ|	�rˆtd ƒ |ˆ jd!d"ƒ |	�rÖˆ j�rœd#}nd$}td% ||d& d'd„ |D ƒ¡¡ƒ tt	d ƒ tdƒ |
�r*ˆ ji k�r*td( 
t	d¡ƒ td)ƒ d*}d+}|ˆ j||ƒ tt	d ƒ tdƒ ˆ  |¡}|�r`td, 
t	d¡ƒ ˆ  |¡ tt	d ƒ |�rŒtd- 
t	d¡ƒ ˆ  |¡ tt	d ƒ tdƒ tt	d ƒ tdƒ |�s´|�rÄtd. 
d/d¡ƒ |�rÒˆ   ¡  |�ròˆ  !¡  ntd0 ||¡ƒ d S )1Nzself.setup has not been calledzInternal parallel functions r“  z Function %s, %s r¢  F)r|   r±   rã   rä   Tz1Report level unknown, should be one of 1, 2, 3, 4)r±   rã   rä   )rã   rä   rã   rä   z
 ú=z% Parallel Accelerator Optimizing: %s r²  zLooking for parallel loopsr;  z
Found %s parallel loops.rÀ  c                 S   s   g | ]
}|j ‘qS r^   )r  r®  r^   r^   rd   re   #  s     z*ParforDiagnostics.dump.<locals>.<listcomp>z Fusing loops zPAttempting fusion of parallel loops (combines loops with similar properties)...
z+Performing sequential lowering of loops...
r”  c                    s8   t ˆƒ‰ ‡ ‡‡‡‡fdd„}ˆ | ¡\‰}|ˆ|ƒ d S )Nc                    sF   ‡‡‡ ‡fdd„‰ |D ]*}t dˆ|ˆf ƒ ˆ ˆ|dƒ t dƒ qd S )Nc                    sL   | | D ]>}t ˆ | d dˆ|ˆf  ƒ | | g krˆ| ||d ƒ qd S )Nr³  rÁ  r|   ©rk   )r’  r‡  rÆ  rŠ  )rÈ  Únode_msgrÉ  rË  r^   rd   rÉ  6  s    zYParforDiagnostics.dump.<locals>.dump_graph_indented.<locals>.print_graph.<locals>.print_grÁ  r|   r²  rï  )r’  r‚  rò   )rÈ  rj   rð  Úroot_msgrË  )rÉ  rd   Úprint_graph5  s
    zHParforDiagnostics.dump.<locals>.dump_graph_indented.<locals>.print_graph)r�   rƒ  )r¤   rñ  rð  rò  r‚  ©r  rË  )rÈ  rj   rð  rñ  rd   Údump_graph_indented3  s    
z3ParforDiagnostics.dump.<locals>.dump_graph_indentedz#  Trying to fuse loops #%s and #%s:rë  z
 
Fused loop summary:
z&has the following loops fused into it:z(fused)z4Following the attempted fusion of parallel for-loopsúWith fusion disabledzL
{} there are {} parallel for-loop(s) (originating from loops labelled: {}).r±  c                 S   s   g | ]}d | ‘qS )z#%sr^   r®  r^   r^   rd   re   U  s     z Optimising loop nests zNAttempting loop nest rewrites (optimising for the largest parallel loops)...
 zis a parallel loopz--> rewritten as a serial loopz Before Optimisation z After Optimisation zLoop invariant code motionr[   z+Function %s, %s, has no parallel for-loops.)"r_  ÚRuntimeErrorrP  r`  ra  r  rY  ræ   rk   Ú
_termwidthr?  r¦  rl  r•  rà  rá  râ  rã  r¿  re  r�   Úsequential_parfor_loweringr]  r[  rc  rç   r£  r\  r­  r`   rÖ  rÞ  ré  rí  ) r  Úlevelr
  rb  r¹  rd  r¥  Zprint_source_listingZprint_fusion_searchZprint_fusion_summaryZprint_loopnest_rewriteZprint_pre_optimisedZprint_post_optimisedZprint_allocation_hoistZprint_instruction_hoistZprint_internalr˜  rG  r•  rá  r~   Ú
parfor_idsÚ	n_parforsrJ  rô  ÚreportÚl1Úl2Úafter_fusionrñ  rð  r¬  r^   ró  rd   r@  Ñ  sê    







  ÿ



zParforDiagnostics.dumpc                 C   s   d}|t | jƒ7 }|S )NzParforDiagnostics:
)r2  rX  ©r  rò   r^   r^   rd   Ú__str__�  s    zParforDiagnostics.__str__c                 C   s   d}|S )NrV  r^   r   r^   r^   rd   r  †  s    zParforDiagnostics.__repr__)N)r|   )ru   rv   rw   r  r  rg  Úpropertyr_  Úsetterrl  ro  rm  re  ry  rƒ  r�  r‘  r—  r¦  r­  r¿  rÖ  rÞ  ré  rí  r@  r  r  r^   r^   r^   rd   rV  º  s6   


(:,,A`
 1rV  c                   @   s.   e Zd ZdZi dfdd„Zdd„ Zdd„ ZdS )	ÚPreParforPasszwPreprocessing for the Parfor pass. It mostly inlines parallel
    implementations of numpy functions if available.
    Nc	           	      C   sL   || _ || _|| _|| _|| _|| _|| _|d kr6t}|| _dddœ| _	d S )Nr   )Úreplaced_funcÚreplaced_dtype)
rP  r7  Ú	calltypesÚ	typingctxÚ	targetctxÚoptionsÚswappedÚswap_functions_mapÚreplace_functions_mapÚstats)	r  rP  r7  r  r  r	  r
  r  r  r^   r^   rd   r  �  s    þzPreParforPass.__init__c                 C   s@   t | j| j| j| jƒ | jjr,|  | jj¡ t	| jjƒ| j_dS )z(Run pre-parfor processing pass.
        N)
r6   rP  r7  r  r  r
  r÷   Ú_replace_parallel_functionsrk  r4   r  r^   r^   rd   rS  ¡  s    
 ÿzPreParforPass.runc              	      sÒ  ˆj ‰ddlm‰ t| ¡ ƒ‰ˆ�rÎˆ ¡ \}‰ tˆ jƒD �]Ž\‰}t|t	j
ƒr:|j}ˆj|j ‰|j‰tˆt	jƒr¸ˆjdkr¸‡ ‡‡‡‡‡‡‡fdd„}t|ƒr¶ˆjd  d7  <  qq:tˆt	jƒr:ˆjdkr:ˆjd	kr:ˆjˆjj }t|tjjƒr:|j}ˆ j}|j}	t	 |td
ƒ|	¡}
tj t¡ˆj|
j< t	 dt|	¡}t	 
||
|	¡}t |ƒ}|dk�r^d}t	 |tdƒ|	¡}t !|¡ˆj|j< t	 
t	 "||	¡||	¡}t	 |tdƒ|	¡}t#tjƒ}t$j%j &|¡}| 'ˆj(ˆj|j fi ¡ tj) &|¡ˆj|j< t	j *|
d	|	¡}t	 
|||	¡}t	 |tdƒ|	¡}tj +|¡ˆj|j< t	j ,||gd|	¡}t	 
|||	¡}t-ˆj|j ˆj|j ƒˆj.|< ||_ˆ j /d|¡ ˆ j /d|¡ ˆ j /d|¡ ˆ j /d|¡ ˆjd  d7  <  qq:qdS )z½
        Replace functions with their parallel implementation in
        replace_functions_map if available.
        The implementation code is inlined to enable more optimization.
        r   )Úinline_closure_callrs  c                     s¸  t ˆjˆjƒ} tˆjˆƒ}ˆj |d ¡}|d kr�t|ƒdkr�t|d tj	ƒr�tˆj
|d j tjjƒr�t |d d ¡}|d k	r�ˆj d|d ¡ t|d k	ƒ t‡fdd„ˆjD ƒƒ}z|ˆf|žŽ }W n   d }Y nX t|d k	ƒ t ˆjjjj¡}t|d< t|d< t|d< t |d ¡}|d k	�r0|j||j< ˆˆj|ˆ ˆ|ˆjˆj|ˆj
ˆjˆƒ\}}t|d	d
�}	|	D ]H}
|
 ¡ D ]8\}}|d dk�rv||j | ˆ j!ˆ j"gˆ|<  �qj�qv�qjdS )Nr±   r|   r   c                 3   s   | ]}ˆ j |j V  qd S rl   )r7  r
  r®  r  r^   rd   rÚ   Í  s     zRPreParforPass._replace_parallel_functions.<locals>.replace_func.<locals>.<genexpr>r}   r©   rÛ   F)Útopological_orderingrp   T)#r>   rP  r  r8   r  rE  r�   r�   r   r  r7  r
  r
   r²   r³   Úreplace_functions_ndarrayrs   Úinsertr;   r–  rz  r`  Ú__globals__r}   r÷   rÛ   Úreplace_functions_checkers_mapr  r	  r  r2   r3  ru   r4  r  )Úfunc_defÚcallnameZ	repl_funcÚtypsÚnew_funcÚgÚcheckÚ
new_blocksÚ_Ú
call_tablers  rŠ  r�  ©rD  Úexprrˆ   r  Úlhs_typr  r  Ú	work_listr^   rd   Úreplace_func½  sb    
ÿþÿý
ÿ
       þz?PreParforPass._replace_parallel_functions.<locals>.replace_funcr  r|   Úgetattrr…   ú	$np_g_varr©   ÚboolÚbool_z$np_typ_varz$dtype_attr_varz
$dtype_varr^   r  N)0r  Únumba.core.inline_closurecallr  rZ  r3  Úpopr·  r4  r�   r   ÚAssignÚtargetr7  r
  rt  ru  r  r:   r  rß  r
   r²   r³   r…   Úscoper  r  r   ÚmiscÚModuler÷   ÚGlobalr1  ÚStringLiteralÚConstÚfind_templater}   ÚcorerQ   Úget_call_typer  Ú	functionsr$  ÚDTypers  rP   r  r  )r  rk  rp  ÚinstrÚlhsr#  Útypr…   r,  r  Úg_np_varÚg_npÚg_np_assignÚ	dtype_strÚtyp_varÚtyp_var_assignZdtype_attr_varÚtempZtfuncZdtype_attr_getattrZdtype_attr_assignZ	dtype_varZdtype_getattrZdtype_assignr^   r  rd   r  «  s‚    -ÿ	
  ÿÿ
  ÿ

 
ÿ
z)PreParforPass._replace_parallel_functions)ru   rv   rw   r  r  rS  r  r^   r^   r^   rd   r  ‹  s    ÿ

r  c                 C   s*   t jjjjjD ]}|j| kr|  S qd S rl   )r}   r3  r   Ú	templatesÚbuiltin_registryr5  r   )r  Úftr^   r^   rd   r2  *  s    
r2  c                   @   s   e Zd ZdZeƒ fdd„ZdS )ÚParforPassStateszCThis class encapsulates all internal states of the ParforPass.
    c                 C   s˜   || _ || _|| _|| _|| _|| _|| _|
| _|
j| _	|
j
| _
|
j| _t | j| j | j| j¡| _tj t|j ¡ ƒ¡ || _|	| _d|	kr”i |	d< d S )Nr~   )rP  r7  r  r  r	  r�   r
  ÚdiagnosticsrX  Úswapped_fnsr[  r\  rY   ÚArrayAnalysisr   Ú_the_max_labelr©  r–   rk  r~  r(  Úmetadata)r  rP  r7  r  r�   r  r	  r
  r(  rI  rE  r^   r^   rd   r  4  s,       ÿzParforPassStates.__init__N)ru   rv   rw   r  rV  r  r^   r^   r^   rd   rD  0  s   þrD  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚConvertInplaceBinopú0Parfor subpass to convert setitem on Arrays
    c                 C   s   || _ g | _dS ©zV
        Parameters
        ----------
        pass_states : ParforPassStates
        N©Úpass_statesÚ	rewritten©r  rN  r^   r^   rd   r  Q  s    zConvertInplaceBinop.__init__c              	   C   s  | j }t|ƒ}|D ]þ}|| }g }|j |¡}|jD ]Ô}t|tjƒrè|j}	|j	}
t|
tj
ƒrè|
jdkrè|
j}|
j}|
j}|j|j }|j|j }t|tjjƒrèt|tjjƒrè|  |||
j||¡}| j t||dd�¡ |t ||	|¡g}t|tƒrþ| |¡ q4| |¡ q4||_qd S )NÚinplace_binop©ÚoldÚnewÚreason)rN  r/   rY   Úget_equiv_setr4  r�   r   r*  r+  rt  ru  r  r  r8  Úrhsr7  r
  r
   r²   r³   Ú_inplace_binop_to_parforÚimmutable_fnrO  r  rW  rZ  r�  )r  rk  rN  Ú
topo_orderrp  rD  Únew_bodyr%  r7  r8  r   r  r+  rt  Ú
target_typÚ	value_typÚ	new_instrr^   r^   rd   rS  Z  sD    
   ÿÿÿ
zConvertInplaceBinop.runc              	   C   s  | j }|j}|j|j }|j}	t ||¡}
|j|j }| |¡}t|j|||ƒ\}}t	ƒ }t ||¡}t
|j|||ƒ\}}t |tdƒ|¡}|j|j|j< tj |||¡}t|j||ƒ|j|< |j t |||¡¡ t |tdƒ|¡}|	|j|j< tj |||¡}t|	||ƒ|j|< |j t |||¡¡ t |tdƒ|¡}|	|j|j< tj ||||¡}|j t |||¡¡ | j j |	|j¡}t|||ƒ|j|< t ||||¡}ttj|||	ƒ|j|< |j |¡ t||
i |||d|jƒ}||i|_tjdk�rtdƒ |  ¡  |S )úûgenerate parfor from setitem node with a boolean or slice array indices.
        The value can be either a scalar or an array variable, and if a boolean index
        is used for the latter case, the same index must be used for the value too.
        ú
$value_varz$target_varú$expr_out_var)rQ  r²  r|   zparfor from inplace_binop)!rN  r,  r7  r
  r…   r   ÚBlockÚ	get_shapeÚ_mk_parfor_loopsr    Ú_make_index_varr  r   ru  ÚgetitemrP   r  r4  r  r*  Úbinopr  Úunify_pairsÚSetItemr
   Únoner  r(  r"  r   ÚDEBUG_ARRAY_OPTr`   r@  )r  r%  r  r  r+  rt  rN  r,  Úarr_typÚel_typr!  r]  Ú	size_varsÚ
index_varsÚ	loopnestsÚ
body_labelÚ
body_blockr#  Úindex_var_typÚ	value_varÚgetitem_callÚ
target_varÚexpr_out_varZ
binop_exprZunified_typeÚsetitem_noder   r^   r^   rd   rX    sz    
   ÿ  ÿ
  ÿ
  ÿ
   ÿ
 ÿ
z,ConvertInplaceBinop._inplace_binop_to_parforc                 C   s   t j}| jj |t|ƒi ¡S rl   ©Úoperatorrf  rN  r  Úresolve_function_typer–  ©r  rs   Úfntyr^   r^   rd   Ú_type_getitem¿  s    z!ConvertInplaceBinop._type_getitemN)ru   rv   rw   r  r  rS  rX  r~  r^   r^   r^   rd   rJ  N  s
   	%@rJ  c                 C   s   t | tjƒr| jS | jS rl   )r�   r   ri  rœ   r#  rž  r^   r^   rd   Úget_index_varÄ  s    r  c                   @   s2   e Zd ZdZdd„ Zdd„ Zddd„Zd	d
„ ZdS )ÚConvertSetItemPassrK  c                 C   s   || _ g | _dS rL  rM  rP  r^   r^   rd   r  Ë  s    zConvertSetItemPass.__init__c              
   C   s<  | j }t|ƒ}|D �]"}|| }g }|j |¡}|jD �]ö}t|tjtjfƒ�r$|j	}	|j
}
t|ƒ}|j}|j|
j }|j|j }|j|j }t|tjjƒ�r$t|tjjƒ�r‚t|jtjƒ�r‚|j|jk�r‚t|tjƒ�r|  ||	|
||¡}| j t||dd�¡ |}nxt|tjjƒ�r$tt|j|jƒ}t|tjƒ�r$|jdk�r$|jj|jk�r$|  ||	|
||j¡}| j t||dd�¡ |}n¢|  |¡}t|tj!ƒ�r´t"t#t$dd„ |jƒƒƒ}nt|tj%j&ƒ�rÊd}nd}|d k	�r$t|tjjƒ�rô||jk�r$| j||	|
|||d	�}| j t||d
d�¡ |}| |¡ q6||_qd S )NZmasked_assign_broadcast_scalarrR  rf  Zmasked_assign_arrayc                 S   s   t | tjjƒS rl   )r�   r
   r-  Ú	SliceTyperž  r^   r^   rd   ró     rô   z(ConvertSetItemPass.run.<locals>.<lambda>r|   r   )rŠ   Úslice)'rN  r/   rY   rV  r4  r�   r   ÚStaticSetItemri  r  r+  r  rt  r7  r
  r
   r²   r³   r…   ÚBooleanrŒ   ÚNumberÚ_setitem_to_parforrO  r  rW  r:   r>   rP  ru  r  rœ   rc  rF  r�   rZ  Úfilterr-  r�  )r  rk  rN  rZ  rp  rD  r[  r%  r7  r  r+  rœ   rt  r\  Ú	index_typr]  r^  Zval_defrŠ   Zsliced_dimsr^   r^   rd   rS  Ô  s¨    
ÿ
þ   ÿÿÿÿÿþ   ÿÿÿ
þ

ÿþ    ÿÿÿzConvertSetItemPass.runNc           #   	   C   s  | j }|j}|j|j }	|	j}
|j|j }t ||¡}|rÆt|tj	ƒsVt|tj
ƒsVt‚|}t |tdƒ|¡}tj |||¡}tj |	|¡j}||j|j< |  |	|f¡|j|< | t |||¡¡ |}n t|tjƒsÖt‚| |¡}|j}g }g }|D ]B}t |tdƒ|¡}| |¡ tj|j|j< | t|d|dƒ¡ qòtƒ }t ||¡}t|j|||ƒ\}}t||i |||d|jƒ}|�rŽ||i|_ |}d}nŠtƒ }t ||¡}tƒ }t ||¡}||||||i|_ t |tdƒ|¡}||j|j< tj |||¡}|j! "t |||¡t #||||¡g¡ |j|j } t| tj$j%ƒ�r�t |tdƒ|¡}!| j|j|!j< tj |||¡}t&| j| |ƒ|j|< |j! t ||!|¡¡ n|}!t '|||!|¡}"t&tj(|j|j ||
ƒ|j|"< |j! |"¡ |�rè|j! t )||¡¡ t*j+dk�rt,d	ƒ | -¡  |S )
r_  z$subarrÚparfor_indexr   r|   )Úsetitemr²  Nz	$mask_varr`  zparfor from setitem).rN  r,  r7  r
  r…   r   rb  r�   r
   rF  r�  r&  r  r   ru  rf  r   Ú	arraydeclZget_array_index_typeÚresultr~  r  r  r*  ÚArrayCompatiblerc  Úuintpr  r    re  r  r(  r"  r4  r�  ÚBranchr²   r³   rP   ri  rj  ÚJumpr   rk  r`   r@  )#r  r%  r  r+  rœ   rt  rŠ   rN  r,  rl  rm  rˆ  r!  rn  Z
subarr_varru  Z
subarr_typZbool_typrp  ro  Úsize_varr#  rq  rr  rs  r   Z
true_blockÚ	end_labelÚ
true_labelÚ	end_blockÚmask_varÚmask_valr]  rt  rx  r^   r^   rd   r†  &  s®    
ÿ

   ÿ ÿ
  þþ  ÿ
 
  ÿ
z%ConvertSetItemPass._setitem_to_parforc                 C   s   t j}| jj |t|ƒi ¡S rl   ry  r|  r^   r^   rd   r~  „  s    z ConvertSetItemPass._type_getitem)N)ru   rv   rw   r  r  rS  r†  r~  r^   r^   r^   rd   r€  È  s
   	R
^r€  c           
      C   sª   t |ƒ}|j}|dks|r‚t |tdƒ|¡}tj tj|¡| |j	< tj
 t|ƒ|¡}t |||¡}	|j |	¡ |tj tj|¡fS |dkr˜|d tjfS tjd|d�‚dS )aå   When generating a SetItem call to an array in a parfor, the general
    strategy is to generate a tuple if the array is more than 1 dimension.
    If it is 1 dimensional then you can use a simple variable.  This routine
    is also used when converting pndindex to parfor but pndindex requires a
    tuple even if the iteration space is 1 dimensional.  The pndindex use of
    this function will use force_tuple to make the output index a tuple even
    if it is one dimensional.
    r|   z$parfor_index_tuple_varr   z,Parfor does not handle arrays of dimension 0©r  N)r�   r  r   r  r   r
   Ú
containersÚUniTuplerŽ  r
  ru  Úbuild_tuplerZ  r*  r4  r  r   ÚUnsupportedRewriteError)
r7  r,  ro  rr  Úforce_tupleÚndimsr  Ú	tuple_varÚ
tuple_callÚtuple_assignr^   r^   rd   re  ‰  s,    	ÿÿ ÿ
þre  c                 C   sV   g }g }|D ]@}t  |tdƒ|¡}| |¡ tj| |j< | t|d|dƒ¡ q||fS )zN
    Create loop index variables and build LoopNest objects for a parfor.
    r‰  r   r|   )r   r  r   r  r
   rŽ  r
  r  )r7  rn  r,  r  rp  ro  r‘  r#  r^   r^   rd   rd  ¦  s    
rd  c                   @   sP   e Zd 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S )ÚConvertNumpyPassz]
    Convert supported Numpy functions, as well as arrayexpr nodes, to
    parfor nodes.
    c                 C   s   || _ g | _d S rl   rM  rP  r^   r^   rd   r  ¸  s    zConvertNumpyPass.__init__c              	   C   s  | j }t|ƒ}g }|D ]ò}|| }g }|j |¡}|jD ]È}	t|	tjƒrö|	j}
|	j	}| j j
|j }|  |¡rêt| j|
ƒrª|  |||
¡}|d k	rê| j t|	|dd�¡ |}	n@t|
tjƒrê|
jdkrê|  |||
|¡}| j t|	|dd�¡ |}	| |j¡ | |	¡ q8||_qd S )NZnumpy_allocatorrR  Ú	arrayexpr)rN  r/   rY   rV  r4  r�   r   r*  rt  r+  r7  r
  Ú_is_C_or_F_orderr:   Ú_is_supported_npycallÚ_numpy_to_parforrO  r  rW  ru  r  Ú_arrayexpr_to_parfor)r  rk  rN  rZ  Ú
avail_varsrp  rD  r[  r%  r7  r   r8  r!  r^  r^   r^   rd   rS  ¼  sL    

ý   ÿýzConvertNumpyPass.runc                 C   s`   t |tjjƒr"|jdko |jdkS |tkrX| jj| }t |tjjƒoV|jdkoV|jdkS dS d S )NÚCr   F©	r�   r
   r²   r³   ÚlayoutrŒ   r1  rN  r7  ©r  Zarr_namer9  r^   r^   rd   Ú_is_C_orderâ  s    ÿþzConvertNumpyPass._is_C_orderc                 C   st   t |tjjƒr,|jdks"|jdko*|jdkS |tkrl| jj| }t |tjjƒoj|jdksb|jdkoj|jdkS dS d S )Nr¨  ÚFr   Fr©  r«  r^   r^   rd   r£  í  s    ÿþz!ConvertNumpyPass._is_C_or_F_orderc                 C   s‚  | j }|j}|j}|j}|j|j }	|	j}
| |¡}t|j|||ƒ\}}t	 
||¡}t|j|j|j|t|ƒ|
|||j|j ƒ	|_tƒ }t	 
||¡}t	 |tdƒ|¡}|
|j|j< t|j|||ƒ\}}|j t|j|j|j|j|||||||ƒ¡ d t|jƒ¡f}t||i ||||d |jƒ}t	 ||||¡}ttj|j|j ||
ƒ|j|< |j |¡ ||i|_ t!j"dk�r~t#dƒ | $¡  |S )zegenerate parfor from arrayexpr node, which is essentially a
        map with recursive tree.
        ra  zarray expression {}r   r|   zparfor from arrayexpr)%rN  r,  r  r   r7  r
  r…   rc  rd  r   rb  r!   r  r  r–  r4  r    r  r   re  r�  Ú_arrayexpr_tree_to_irrP  rç   Úrepr_arrayexprr  r(  ri  rP   r
   rj  r  r"  r   rk  r`   r@  )r  r%  r8  r¢  r§  rN  r,  r  r   rl  rm  rn  ro  rp  r!  rq  rr  rw  r#  rs  Úpatr   rx  r^   r^   rd   r¦  ø  sx    
     
ü   ÿõÿ 
  ÿ

z%ConvertNumpyPass._arrayexpr_to_parforc                 C   sN   t | jj|ƒ\}}t|tƒr&| d¡s*dS |dkr6dS |dkrJ|tkrJdS dS )zLcheck if we support parfor translation for
        this Numpy call.
        r÷   F©rª   ÚonesTúnumpy.random)r8   rN  rP  r�   r1  Ú
startswithrV   )r  r   Ú	call_nameÚmod_namer^   r^   rd   r¤  2  s    z&ConvertNumpyPass._is_supported_npycallc                 C   s`   t | jj|ƒ\}}|j}t|jƒ}|dks2|dkrF|  ||||||¡S tjd|› �|j	d�‚d S )Nr±  r³  zparfor translation failed for r—  )
r8   rN  rP  rs   rW  ÚkwsÚ_numpy_map_to_parforr   r›  r  )r  r%  r8  r   rµ  r¶  rs   r·  r^   r^   rd   r¥  @  s    
 ÿz!ConvertNumpyPass._numpy_to_parforc                 C   s  | j }|j}|j}	|j|j }
|
j}| |¡}|dkrLtjdkrHt	dƒ dS t
|j|||	ƒ\}}t ||	¡}t|j|j|j|t|ƒ|||	|j|j ƒ	|_tƒ }t ||	¡}t |tdƒ|	¡}||j|j< t|j|||ƒ\}}|dkröt |dƒ|	¡}n‚|dk�rt |dƒ|	¡}nf|tk�rjt||ƒ t||jƒ\}}|j |¡ |j|jj  t ¡ ||¡|j|< |}ntd  |¡ƒ‚t !|||	¡}|j "|¡ t #||||	¡}t$t%j&|j|j ||ƒ|j|< |j "|¡ t'||i |	||d	  |¡d
f|j(ƒ}||i|_)tjdk�rt	dƒ | *¡  |S )z8generate parfor from Numpy calls that are maps.
        Nr|   z3Could not convert numpy map to parfor, unknown sizera  rª   r   r²  z,Map of numpy.{} to parfor is not implementedú{} functionzNumPy mappingzgenerated parfor for numpy map:)+rN  r,  r  r7  r
  r…   rc  r   rk  r`   rd  r   rb  r!   r  r  r–  r4  r    r  r   re  r1  rV   Ú_remove_size_argÚ_get_call_arg_typesr)  r  r4  r   ÚContextÚNotImplementedErrorrç   r*  r  ri  rP   r
   rj  r  r(  r"  r@  )r  r%  rµ  r8  rs   r·  r   rN  r,  r  rl  rm  rn  ro  rp  r!  rq  rr  rw  r#  rs  rt  Únew_arg_typsÚnew_kw_typesZvalue_assignrx  r   r^   r^   rd   r¸  K  s�    

     
ü   ÿ


 ÿ  ÿ
ÿ 
  ÿ
þ
z%ConvertNumpyPass._numpy_map_to_parforN)ru   rv   rw   r  r  rS  r¬  r£  r¦  r¤  r¥  r¸  r^   r^   r^   rd   r¡  ³  s   &:r¡  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚConvertReducePassz:
    Find reduce() calls and convert them to parfors.
    c                 C   s   || _ g | _d S rl   rM  rP  r^   r^   rd   r  ”  s    zConvertReducePass.__init__c              	   C   sÂ   | j }t|ƒ}|D ]ª}|| }g }|j |¡}|jD ]€}d }	t|tjƒrª|j}
|j	}|j
}tt|j|ƒ}|dksx|dkrŒt| j|||j|
ƒ}	|	rª| j t|	|dd�¡ |	}| |¡ q4||_qd S )N)r   rƒ   )r   Ú
_functoolsr   )rT  rS  rU  )rN  r/   rY   rV  r4  r�   r   r*  r  r+  rt  r:   r8   rP  Ú_reduce_to_parforrs   rO  r  rW  )r  rk  rN  rZ  rp  rD  r[  r%  r7  r   r  r8  r   r  r^   r^   rd   rS  ˜  s<    
ÿ
 ÿýzConvertReducePass.runc              
      sÞ  | j }|j}|d }|d }t|j|jƒ}	d}
d}tt|j|j|	ƒ}|rT|\}}
}}|d }| |dkrl|n|
¡}|dkr~dS t	|j|||ƒ\‰ }ˆ }|r¸t
dƒ‚t‡ fdd„|D ƒƒ‰ |}t ||¡}|j t |||¡¡ tƒ }|  |||ˆ ||¡\}}|�rt
dƒ‚|d }|
dk	�rœt| ¡ ƒ}t| ¡ ƒ}t ||¡}|||< t |tdƒ|¡}||j|j< tj |
||¡}|j t |||¡t ||||¡g¡ t||||||d	 |¡d
f|jƒ}tj dk�rÚt!dƒ | "¡  |S )zy
        Convert a reduce call to a parfor.
        The call arguments should be (call_name, array, init_value).
        r   r|   Nr±   Úunreachablec                 3   s   | ]}|r|nˆ d  V  qdS ©r   Nr^   r®  ©ro  r^   rd   rÚ   Õ  s     z6ConvertReducePass._reduce_to_parfor.<locals>.<genexpr>ú	$mask_valr¹  Ú	reductionzparfor from reduction)#rN  r,  r>   rP  r
  r:   Ú
_find_maskr7  rc  rd  r&  r–  r   rb  r4  r  r*  r    Ú_mk_reduction_bodyr‰   r~  r–   r  r   ru  rf  r�  r�  r  rç   r(  r   rk  r`   r@  )r  r%  r8  rs   r  rN  r,  rµ  rz   Úarr_defr•  Úmask_indicesZmask_query_resultÚmask_typrŸ   rn  rp  Z
mask_indexÚacc_varr!  rq  r#  r"  r“  Úfalse_labelrr  Úmaskr–  r   r^   rÅ  rd   rÂ  ·  sp        ÿ
þ ÿþz#ConvertReducePass._reduce_to_parforc                 C   sH  ddl m} | j}t|j|ƒ}	||j|	ƒ}
|j|j }|j}t 	||¡}t
|j|||ƒ\}}t |tdƒ|¡}||j|j< tj |||¡}t|||ƒ|j|< | t |||¡¡ t|
|jjjj|j|j||f|j|jƒ}|j}tƒ }t 	||¡}|||< t|j ¡ ƒ}|j| }|j |j¡ |j|_t|||gƒ t |||ƒ ||fS )zZ
        Produce the body blocks for a reduction function indicated by call_name.
        r   )Úcheck_reduce_funcz$val)!r(  rÐ  rN  r>   rP  r7  r
  r…   r   rb  re  r  r   ru  rf  rP   r  r  r*  r=   r`  r  r  r  r	  rk  r    r‰   r~  r4  r�  r@   rA   )r  rµ  r,  r  ro  rz   rÍ  rÐ  rN  Úreduce_funcÚfcoderl  Zin_typrr  r#  Zindex_var_typeZtmp_varru  Zreduce_f_irr"  r’  r”  Zfirst_reduce_labelZfirst_reduce_blockr^   r^   rd   rÉ  ú  sR       ÿ  ÿ

ú
z$ConvertReducePass._mk_reduction_bodyN)ru   rv   rw   r  r  rS  rÂ  rÉ  r^   r^   r^   rd   rÀ  �  s
   CrÀ  c                   @   sP   e Zd 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S )ÚConvertLoopPassz*Build Parfor nodes from prange loops.
    c                 C   s   || _ g | _d S rl   rM  rP  r^   r^   rd   r  )	  s    zConvertLoopPass.__init__c           :         sr  | j ‰
tˆ ƒ\}}tˆ ƒ}tˆ ƒ}t|ˆ |j|jƒ‰| ¡ ‰	‡	fdd„ˆ	 ¡ D ƒ}g }t	|dd„ d�D �]\‰}t
ˆjƒdksft
ˆjƒdkrŽqftˆjƒd }	ˆ |	 jD �]Â}
t|
tjƒr¦t|
jtjƒr¦|
jjdkr¦|  |
jjj|¡r¦‡ ‡fd	d„ˆjD ƒ}|
jj}|  |
jjj|¡\}}ˆ ˆj jd d
… }d ‰t|ƒD ]H\}}t|tjƒ�r8t|jtjƒ�r8|jjdk�r8|jj‰|} �q‚�q8ˆd k	�s�t‚|d |… ||d d …  }tdˆ ˆj iˆ
jƒ\}}|d }t ‡fdd„|D ƒƒ‰ˆ !ˆ¡ ˆ |	 j"}|
j#}ˆ
j$ %ˆj¡}t &||¡}|  'ˆ |	 ||¡|_‡ fdd„|D ƒ‰t(ƒ }t &||¡ˆ|< t ƒ }|D ]}| )|j| ¡}�q^t ƒ }ˆjD ]}| )ˆ| ¡}�q‚| *|¡}| *‡
fdd„|D ƒ¡}|D ]6}ˆ| jd
 }t|tj+ƒ�r¾|jˆjk�r¾||_�q¾‡‡fdd„‰d }d } ‡‡‡‡
fdd„}!d}"|dk�r<| ,|d ¡�s@t‚t-|!|d ƒ}#|#�rb|#\}$}}%} n|d }$t|$tj.ƒ�s|t‚ˆ
j|$j }&t|&t/j0ƒ�rÎt .|t1dƒ|¡‰t/j2ˆ
jˆj< t3ˆd|$dƒg‰	ˆg‰n,| 4| d k�rà|$n|¡}'t5ˆ
j|'||ƒ\‰‰	t
ˆ	ƒdk�st‚ˆ}(| �r,t6‡fdd„| D ƒƒ‰ˆt7ˆ ¡ ƒ })t &||¡}*t8ˆ
j|ˆ|*dd�\‰}+|*j|)j },|,|)_| �r‚|(d }-nˆ}-|d k	�rxtdƒ‚t(ƒ }.t9ˆ|.t7ˆ ¡ ƒ d ƒ‰ˆ ¡ }/t7|/ƒ}0t:|/ƒ}1t &||¡}*|*ˆ|.< t .|t1dƒ|¡}2|%ˆ
j|2j< tj ;||-|¡}3|*j <t |3|2|¡t =|2|0|1|¡g¡ �n<d}4d}5|d }6t
|ƒdk�rj|d }4|d }6t
|ƒdk�r|d }4|d }6zˆ
j> ?|d ¡}5W n& t@k
�rÂ   tAjBd|
j#d �‚Y nX t|5tjCƒ�sâtAjBd!|
j#d �‚|5j}5|5dk�rtAjBd"|
j#d �‚t .|t1dƒ|¡‰t|4tDƒ�r2|4dk�r2t/j2}+n
t/jE}+d#}"t3ˆ|4|6|5ƒg‰	|+ˆ
jˆj< t7ˆ ¡ ƒ}7|ˆ|7 j ˆ|7 _‡fd$d„ˆD ƒ}8tFˆ|8ƒ |"�r¨|  Gˆˆˆ¡ tHˆ	|ˆ|| �r¼|-nˆ|d%||fˆ
jI|d&�	}9|9gˆ ˆj _ˆ ˆj j <|¡ ˆ ˆj j Jt +tˆjƒd |¡¡ | jK JtLˆ|9d'd(�¡ |D ]}|ˆjk�r2ˆ  M|¡ �q2tNjOdkr¦tPd)ƒ |9 Q¡  q¦qfd S )*Nc                    s"   g | ]}ˆ | t ˆ | jƒf‘qS r^   )r�   r4  )rb   rŠ  )Úloopsr^   rd   re   5	  s     z'ConvertLoopPass.run.<locals>.<listcomp>c                 S   s   | d S rÒ   r^   )Útupr^   r^   rd   ró   8	  rô   z%ConvertLoopPass.run.<locals>.<lambda>rŸ  r|   r   rs  c                    s"   g | ]}|ˆ kr|ˆj kr|‘qS r^   )Úheader©rb   rj   )rk  r6  r^   rd   re   G	  s     
ÿr”  Ú
pair_firstc                 3   s   | ]\}}|ˆ kr|V  qd S rl   r^   )rb   Útr�  )Ú
loop_indexr^   rd   rÚ   e	  s      z&ConvertLoopPass.run.<locals>.<genexpr>c                    s   i | ]}|ˆ | “qS r^   r^   r×  ©rk  r^   rd   Ú
<dictcomp>n	  s      z'ConvertLoopPass.run.<locals>.<dictcomp>c                    s$   h | ]}t ˆ j| tjjƒs|’qS r^   )r�   r7  r
   r-  r.  r®  )rN  r^   rd   Ú	<setcomp>�	  s    ÿz&ConvertLoopPass.run.<locals>.<setcomp>c                     sî   t   ˆ¡} ˆ  ¡ D ]>}| tj¡D ],}t|jtjƒr"|jj| kr"|  	|j
j¡ q"qg }g }ˆ  ¡ D ]‚}|jD ]v}tdd„ | ¡ D ƒƒ}|| @ rl| | ¡ršqltt|tjƒƒ |j}tt|tjƒoÆ|jdkƒ | |jj¡ | |¡ qlqb||fS )z˜find expressions that involve getitem using the
                        index variable. Return both the arrays and expressions.
                        c                 s   s   | ]}|j V  qd S rl   ©r
  r®  r^   r^   rd   rÚ   ™	  s     zCConvertLoopPass.run.<locals>.find_indexed_arrays.<locals>.<genexpr>©rf  Ústatic_getitem)rz  r|  Ú
find_instsr   r*  r�   rt  r  r
  r}  r+  r4  rN  r  Úissubsetr;   ru  r  r  )ÚindicesrD  rx  ÚarrsÚexprsÚlvr   )r"  Úloop_index_varsr^   rd   Úfind_indexed_arrays‹	  s.    

ÿ

ÿz0ConvertLoopPass.run.<locals>.find_indexed_arraysc           	         s¾   t ˆj| ƒ}t|o0t|tjƒo0|jdko0|jdkƒ |j}t	j
‡fdd„ˆjD ƒŽ }ˆ ƒ \}}t|jgt|ƒkƒ t|j|kƒ t ˆj|jƒ}tˆjˆj|ƒ}tdƒ‚|D ]}|d |_qª|S )zƒFind the case where size_var is defined by A[M].shape,
                        where M is a boolean array.
                        r$  rŠ   c                    s   g | ]}ˆ | ‘qS r^   r^   r×  )Úlive_mapr^   rd   re   ¯	  s     zDConvertLoopPass.run.<locals>.find_mask_from_size.<locals>.<listcomp>rÃ  r   )r>   rP  r;   r�   r   ru  r  rß  rt  rN  r  Úexitsr
  rZ  rÈ  r7  r&  )	r‘  Zsize_defZarr_varÚ	live_varsZ
index_arrsZindex_exprsrÊ  rŒ  r   )rè  ré  r6  rN  r^   rd   Úfind_mask_from_size§	  s"    ÿÿ
z0ConvertLoopPass.run.<locals>.find_mask_from_sizeTr   r‰  c                 3   s   | ]}|r|nˆ d  V  qdS rÄ  r^   r®  rÅ  r^   rd   rÚ   á	  s   ÿ)rœ  rÃ  rÆ  r±   rã   z,Only known step size is supported for pranger—  z/Only constant step size is supported for prangez4Only constant step size of 1 is supported for prangeFc                    s   i | ]
}|ˆ “qS r^   r^   ©rb   r�  )r#  r^   rd   rÜ  3
  s      r   )r  r6  )Zold_looprT  rU  zparfor from loop)RrN  r2   rM   rJ   rK   ÚusemapÚdefmaprÔ  r~  rA  r�   Úentriesrê  rZ  r4  r�   r   r*  rt  ru  r  Ú_is_parallel_loopr  r
  rs   Ú_get_loop_kindrÖ  r·  r+  r&  r,   r7  rN  r}  r,  r  rY   rV  rb  Ú_get_prange_init_blockr    r  Úintersectionr�  Z	has_shaper:   r  r
   ÚIntegerr   rŽ  r  rc  rd  r–  r‰   re  r7   r–   rf  r�  r�  rP  r>   ræ  r   r›  r1  rÞ   Úintpr&   Ú_replace_loop_access_indicesr  r(  r  rO  rW  r)  r   rk  r`   r@  ):r  rk  r  r  ÚcfgÚusedefsZsized_loopsZmoved_blocksr§   Úentryrx  Zbody_labelsrs   Z	loop_kindZloop_replacingZheader_bodyZhbir5  Zli_indexZcpsr,  r  r%  r!  r’  ZbodydefsÚblZ
exit_livesr  rj   Ú	last_instr•  rË  rì  Zunsigned_indexrŒ  rz   rÌ  Z
in_arr_typrn  Z
orig_indexÚfirst_body_blockrr  rs  r4  Zorig_index_varrq  Úlabelsr“  rÎ  rÏ  r–  rÔ   rÖ   r‘  Úfirst_body_labelZindex_var_mapr   r^   )rk  rè  r#  ro  ré  r6  r"  rÚ  rç  rÔ  rN  rd   rS  -	  s’   ÿ
þý	ÿÿ
þ
ÿ


 ÿ


ÿ

ÿÿ   ÿÿ   þ


ÿþ
þþ
þ
  ÿ
 ü$ý
zConvertLoopPass.runc                 C   sh   ||krdS || }t |ƒdkof|d dkpf|d tkpf|d dkpf|d tkpf|d dkpf|d tkS )NFr   r   rp   r   )r�   r   rp   r   ©r  Úfunc_varr  rs  r^   r^   rd   rñ  T
  s    $
ÿ
ÿ
þ
þz!ConvertLoopPass._is_parallel_loopc                 C   s¦   | j }||kst‚|| }t|ƒdks*t‚d}|d dksF|d tkr†z$d|j| d |j| d ff}W q¢ tk
r‚   d}Y q¢X n|d dksž|d tkr¢d}|S )	z(see if prange is user prange or internalr   )r¢  r²  rp   r“  r”  )r“  )r²  r²  r   )r   r²  )rN  r&  r�   rp   rF  ræ  r   )r  r  r  rN  rs  Úkindr^   r^   rd   rò  ]
  s    $zConvertLoopPass._get_loop_kindc                 C   sT  d}d}g }t |jƒD ]€\}}t|tjƒrZt|jtjƒrZ|jjdkrZ|  |jj	j
|¡rZ|}t|tjƒrt|jtjƒr|jjdkr|  |jj	j
|¡r|}q|dk�rP|dk�rPdd„ |D ƒ}	g }
tt|d |ƒƒD ]H}|j| }dd„ | ¡ D ƒ}|	|@ �r|	|O }	|
 |¡ qÐ| |¡ qÐ| ¡  |
 ¡  |jd|… |
 |j|d d…  |_|S )z–
        If there is init_prange, find the code between init_prange and prange
        calls. Remove the code from entry_block and return it.
        r”  rs  c                 S   s   h | ]
}|j ’qS r^   rÞ  rí  r^   r^   rd   rÝ  †
  s     z9ConvertLoopPass._get_prange_init_block.<locals>.<setcomp>r|   c                 S   s   h | ]
}|j ’qS r^   rÞ  rí  r^   r^   rd   rÝ  Š
  s     N)r·  r4  r�   r   r*  rt  ru  r  Ú_is_prange_initr  r
  rñ  r¤  rq   r  r  Úreverse)r  Úentry_blockr  Zprange_argsZinit_call_indZprange_call_indZ	init_bodyrˆ   rx  Zarg_related_varsZsaved_nodesÚ	inst_varsr^   r^   rd   ró  q
  sD    
ÿþ
ÿþ

ÿÿz&ConvertLoopPass._get_prange_init_blockc                 C   s8   ||krdS || }t |ƒdko6|d dkp6|d tkS )NFr   rm   )r�   rm   r   r^   r^   rd   r  ˜
  s    zConvertLoopPass._is_prange_initc              	      s–  |  |j¡ t|ƒ� t|ƒ}W 5 Q R X |d }tƒ }|D �]L}|| }|jD �]6}	t|	tjƒrþt|	j	tj
ƒrþ||kr¬|	j	j|kr¬|	jj|kr¬|  |	jj¡ |  |	jj¡ nR|j‰ ‡ fdd„}
|
|	jjƒt|
|ƒkrþ|
|	jjƒ|
|	j	jƒkrþtjd|	jjd�‚t|	ƒ�rlt|	ƒ}|dk�rqNtt| jj|dd�}|j|k�sR|dk	�r\|j|k�r\t|	|ƒ t| j|||ƒ t|	tƒrN|  |	j||¡ qNq:||8 }dS )	zš
        Replace array access indices in a loop body with a new index.
        index_set has all the variables that are equivalent to loop index.
        r   c                    s:   ddl m} zˆ  | ¡jW S  |jk
r4   |  Y S X d S )Nr   )r   )Ú
numba.corer   Ú	get_exactÚunversioned_nameÚNotDefinedError)r
  r   ©r,  r^   rd   Úunver¾
  s
    z;ConvertLoopPass._replace_loop_access_indices.<locals>.unverz Overwrite of parallel loop indexr—  NT)Úlhs_only)r}  r
  Údummy_return_in_loop_bodyr/   rN  r4  r�   r   r*  rt  r  r+  r,  Úmapr   r›  r  rD   rE   r:   r>   rN  rP  rF   Ú_replace_multi_dim_indr  r÷  r"  )r  r"  Ú	index_setÚ	new_indexrþ  Úfirst_labelZadded_indicesrj   rD  r5  r  rœ   Zind_defr^   r  rd   r÷  ž
  sX    

ÿ
ÿ.þ


 ÿÿþ

ÿ
z,ConvertLoopPass._replace_loop_access_indicesc                    sr   | j }t|dk	ƒ tt|j|j tjtjfƒƒ t|j	|ƒ}tt|t
jƒoR|jdkƒ ‡ ‡fdd„|jD ƒ|_dS )zq
        replace individual indices in multi-dimensional access variable, which
        is a build_tuple
        Nrš  c                    s   g | ]}|j ˆ krˆn|‘qS r^   rÞ  rí  ©r  r  r^   rd   re   ñ
  s   ÿz:ConvertLoopPass._replace_multi_dim_ind.<locals>.<listcomp>)rN  r;   r�   r7  r
  r
   ÚTupler™  r>   rP  r   ru  r  r3  )r  Zind_varr  r  rN  Zind_def_noder^   r  rd   r  ä
  s    
ÿÿÿz&ConvertLoopPass._replace_multi_dim_indN)ru   rv   rw   r  r  rS  rñ  rò  ró  r  r÷  r  r^   r^   r^   rd   rÓ  &	  s     )	'FrÓ  c                 C   sŽ  t t|tjƒo|jdkƒ |j}|j}| |j }| |j }|j}t t|t	j
jƒƒ t|t	j
jƒr†t|jt	jƒr†||jkr†|||jdfS t|t	jƒ�r†t||ƒ\}}	t |	dko¶t|ƒ|kƒ d}
g }d}|D ]˜}| |j }t|t	j
jƒ�rt|jt	jƒ�r|}|j}| d¡ qÊt|t	j
jƒ�rDt|jt	jƒ�rD|}|j}| d¡ qÊt|t	jƒrÊ|
d7 }
| |¡ qÊt |�ov|
|d kƒ ||||fS t‚dS )zächeck if an array is of B[...M...], where M is a
    boolean array, and other indices (if available) are ints.
    If found, return B, M, M's type, and a tuple representing mask indices.
    Otherwise, raise GuardException.
    rf  Nrš  r   r|   )r;   r�   r   ru  r  rt  rœ   r
  rŒ   r
   r²   r³   r…   r„  rF  r9   r�   r  rõ  r<   )r7  rP  rÊ  rt  rœ   r]  rˆ  rŒ   Úseqr  Zcount_constsrË  r•  ÚindrÌ  r^   r^   rd   rÈ  õ
  sN    

ÿþ
ÿÿrÈ  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )Ú
ParforPasszÍParforPass class is responsible for converting NumPy
    calls in Numba intermediate representation to Parfors, which
    will lower into either sequential or parallel loops during lowering
    stage.
    c                 C   s*   | j  | jj¡ tj t | jj¡¡ d S rl   )rY   rS  rP  rk  r   rH  r©  Úfind_max_labelr  r^   r^   rd   Ú_pre_run.  s    ÿzParforPass._pre_runc                 C   sà   |   ¡  | jjr:t| j| j| j| j| j| j	| j
ƒ}| ¡  | jjrTt| ƒ | jj¡ | jjrnt| ƒ | jj¡ | jjrˆt| ƒ | jj¡ | jjr¢t| ƒ | jj¡ | jjr¼t| ƒ | jj¡ | j | j| jj¡ t| jdƒ dS )zgrun parfor conversion pass: replace Numpy calls
        with Parfors when possible and optimize the IR.zafter parfor passN)r  r
  Ústencilr   rP  r7  r  rY   r  r	  r(  rS  rŠ  r€  rk  r÷   r¡  rÇ  rÀ  r   rÓ  rQ  rJ  rE  rg  Úfusionr.   )r  Zstencil_passr^   r^   rd   rS  5  s,    
  ýzParforPass.runc                 C   s   t | j| j|ƒS )zôcheck if an array is of B[...M...], where M is a
        boolean array, and other indices (if available) are ints.
        If found, return B, M, M's type, and a tuple representing mask indices.
        Otherwise, raise GuardException.
        )rÈ  r7  rP  )r  rÊ  r^   r^   rd   rÈ  P  s    zParforPass._find_maskc                 C   s   t | j|||ƒS )zV
        Create loop index variables and build LoopNest objects for a parfor.
        )rd  r7  )r  rn  r,  r  r^   r^   rd   rd  X  s    zParforPass._mk_parfor_loopsN)ru   rv   rw   r  r  rS  rÈ  rd  r^   r^   r^   rd   r  &  s
   r  c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚParforFusionPassz=ParforFusionPass class is responsible for fusing parfors
    c                 C   sl  t | jjƒ}t| j| j| j| jd ƒ t| j| j| j| jd ƒ | jj�rh|dk�rht	| jjƒ| j_
tƒ | j_| j | jj¡ t| jj| jj| jƒ\}}|D ] }t| j||j| jƒ\|_|_qœt| j| jj| jdd� t| jdƒ |  | j| jj| j| j¡ t| jdƒ t| j| jj| jƒ t| jdƒ |  | j| jj| j| j¡ t| jdƒ t| j| j| j| jd ƒ d	S )
zrun parfor fusion passr~   r±   F)Úup_directionzafter maximize fusion downzafter first fusezafter maximize fusion upzafter fusionN)Úsimplify_parfor_body_CFGrP  rk  r3   r7  r  rI  r
  r  r?   Ú_definitionsrW  rY   rR  rS  Úget_parfor_paramsr\  Úget_parfor_reductionsr$  r)  r*  Úmaximize_fusionr.   Úfuse_parfors)r  rû  r  r~   rK  r^   r^   rd   rS  d  sH    
þýÿýýzParforFusionPass.runc                 C   sF  |  ¡ D �]6\}}| |¡}d}|rd}g }	d}
|
t|jƒd k �r(|j|
 }|j|
d  }t|tƒrøt|tƒrø| |¡}||_||_t|||| jd ||ƒ\}}| j	j
 |¡ |d k	rød}| j	j|j  |jg¡ |	 |¡ |  ||||¡ |
d7 }
q0|	 |¡ t|tƒ�r|  ||||¡ |
d7 }
q0|	 |jd ¡ |	|_q qd S )NTFr   r|   r~   r±   r”  )r3  rV  r�   r4  r�   r  r%  Útry_fuserI  rE  r]  r  r[  r  r�  Úfuse_recursive_parfor)r  rY   rk  rP  r7  rp  rD  r%  Zfusion_happenedr[  rˆ   r5  Ú	next_stmtZ
fused_nodeZfuse_reportr^   r^   rd   r$  ™  sD    


  ÿ



zParforFusionPass.fuse_parforsc                 C   sf   t |ƒ}t| j|| jƒ t| jd|ƒ t | j| j| j| j¡}| 	||¡ |  
||||¡ t|ƒ d S )Nz$after recursive maximize fusion down)rQ  r#  rP  r7  r.   rY   rG  r  r  rS  r$  rT  )r  r   r%  rP  r7  rk  Zarr_analysisr^   r^   rd   r&  ½  s     ÿz&ParforFusionPass.fuse_recursive_parforN)ru   rv   rw   r  rS  r$  r&  r^   r^   r^   rd   r  _  s   5$r  c                   @   s   e Zd ZdZdd„ ZdS )ÚParforPreLoweringPasszSParforPreLoweringPass class is responsible for preparing parfors for lowering.
    c                 C   s¶  t | jji i | jƒ t| jdƒ t| j| j| j| jd ƒ t| jdƒ tj	dkrpt
dt| j ¡ ƒƒ t
d| jƒ tj	dk�r¾| jj ¡ D �]2\}}g }|j}|jD �]}| |¡ t|tjƒr¢|j}|j}|j}| j|j }	t
d|j|	t|	ƒƒ |	tjk�st|	tjƒr¢t |td	ƒ|¡}
t |j¡| j|
j< t |j|¡}t ||
|¡}| |¡ t |
gd
|¡}t tj!| j|
j ƒ| j|< | |¡ t |gd
|¡}t tj!|	ƒ| j|< | |¡ q¢||_qˆ| jj"�rÜt#| jj$| j%| jƒ t&�rþt'| j(| j| j| j| jƒ n´t)| jj| j*j+| j,ƒ\}}|D ]"}t-| j||j.| jƒ\|_/|_0�q|D ]}| 1| j¡ �qDtj2�r²| jj3j4}t5|ƒ}|dk�r¤| j*j+�rŠdnd}t
d 6||||¡ƒ nt
d 6|¡ƒ d
S )zrun parfor prelowering passzafter push call varsr~   zafter optimizationr|   zvariable types: zcall types: rã   zAdding print for assignment to Ústr_varNr   úAfter fusionrõ  z0{}, function {} has {} parallel for-loop(s) #{}.zFunction {} has no Parfor.)7Úpush_call_varsrP  rk  r7  r.   r3   r  rI  r   rk  r`   rA  r3  r,  r4  r  r�   r   r*  r  r+  rt  r
  r  r
   Únumber_domainÚLiteralr  r   r0  r1  ÚPrintrP   rj  Úis_generatorÚfix_generator_typesÚgenerator_infor�   rø  Úlower_parfor_sequentialr  r!  r
  r  r\  r"  r$  r)  r*  rM  r,  r`  ra  r�   rç   )r  Úblock_labelrD  Ú	new_blockr,  r5  r  r8  rW  r!  r)  Z	lhs_constZ
str_assignZ	str_printÚir_printrú  r~   rK  r
  rû  rÿ  r^   r^   rd   rS  Í  sŒ    




ÿ    ÿþý

ÿ   þzParforPreLoweringPass.runN)ru   rv   rw   r  rS  r^   r^   r^   rd   r(  È  s   r(  c                 C   sè   t |jƒ}| dd¡ t| ¡ ƒ|_| tt kr6g |_| tkrVt	|jƒdkrV|j ¡  | t
krvt	|jƒdkrv|j ¡  | dkrÄt	|jƒdkr–|j ¡  t	|jƒdkrÄ|j ¡ }|j ¡  |j |¡ | dkrät	|jƒdkrä|j ¡  dS )	z%remove size argument from args or kwsrÂ   r²  rã   r±   Úrandinträ   Ú
triangularN)rW  r·  r)  r–  r3  rS   rR   rs   rU   r�   rT   r  )rµ  r   r·  Zdt_argr^   r^   rd   rº    s,    






rº  c                 C   sN   g }| j D ]}| ||j ¡ q
i }| jD ]\}}||j ||< q*t|ƒ|fS rl   )rs   r  r
  r·  r–  )r   r7  r¾  r‘   r¿  r
  r^   r^   rd   r»  C  s    
r»  c           !         sz  ˆ |j  }|j}|j}g }t|tƒ�rž|\}}g }|D ]J}t |tdƒ|¡}|ˆ |j < |t| |ˆ |||||||	|
ƒ7 }| 	|¡ q6|t
jk�rRˆ |d j  }t|ƒdk�rˆ |d j  }| |||fi ¡}tj ||d |d |¡}|tjk�r0t|d |d |ˆ ƒ\}}n$| ||fi ¡}tj ||d |¡}|||< |j}| 	t |||¡¡ tjD �]@}t||ƒ�rXtˆ ||
|d�}t |t|ƒ|¡}ˆ | ˆ |j < t |  |¡¡}t|tjƒ�r*|jdk�r*|jdk�r*t |tdƒ|¡}tj  t!¡ˆ |j < t "d	t!|¡}t |||¡}tj #|d|¡}| 	|¡ tj $||d
|¡}ˆ |j   %|t‡ fdd„|D ƒƒi ¡}|||< |j}| 	t |||¡¡ | 	t |||¡¡ �qXn˜t|tjƒ�rˆ |j  } t| tj&ƒ�ræ| j'}t(||||	|||ˆ ||ƒ
}n| }|}| 	t |||¡¡ n2t|tj)ƒ�r6t* +¡  ,|j-¡}| 	t |||¡¡ t|ƒdk�r^t.j/d|d›d�|jd�‚ˆ  0|j d¡ |ˆ |j < |S )z�generate IR from array_expr's expr tree recursively. Assign output to
    expr_out_var and returns the whole IR as a list of Assign nodes.
    z$arg_out_varr   r±   r|   r—  r$  Úsqrtz$math_g_varrÛ   r^   c                 3   s   | ]}ˆ |j  V  qd S rl   rÞ  rÙ   ©r7  r^   rd   rÚ   ˜  s     z(_arrayexpr_tree_to_ir.<locals>.<genexpr>z.Don't know how to translate array expression 'rò   ú'N)1r
  r,  r  r�   r–  r   r  r   r®  r  rO   Zsupported_array_operatorsr�   r{  ru  rg  rz  ÚtruedivÚ_gen_np_divideÚunaryr�   r*  rY   Z	MAP_TYPESÚ_find_func_varrz  r{  r>   r  rß  r
   r-  r.  rÛ   r/  r$  rs  r4  r³   r…   Ú_gen_arrayexpr_getitemr1  r   r¼  Úresolve_value_typert  r   r›  r)  )!rP  r  r7  r  r%  r!  rw  r   Úparfor_index_tuple_varÚall_parfor_indicesr§  rm  r,  r  Úout_irr  Zarr_expr_argsZarg_varsr‘   Zarg_out_varZel_typ1Zel_typ2Úfunc_typÚir_exprÚTZfunc_var_namer  Zfunc_var_defZ
g_math_varZg_mathZg_math_assignZcall_typÚvar_typr^   r9  rd   r®  O  sÄ    

öÿÿ   ÿ
&

  ÿ
öþ
r®  c                 C   sÞ   | j }| j}t |tdƒ|¡}tj t¡||j	< t 
dt|¡}t |||¡}tj |d|¡}	t |tdƒ|¡}
ttjƒ}|||
j	< t |	|
|¡}tj |
| |gd|¡}| t ¡ || j	 ||j	 gi ¡}| ||g¡ ||fS )z‰generate np.divide() instead of / for array_expr to get numpy error model
    like inf for division by zero (test_division_by_zero).
    r%  r©   Údividez	$div_attrr^   )r,  r  r   r  r   r
   r-  r.  r÷   r
  r/  r*  ru  r$  r"   rH  rs  r4  r   r¼  r�  )Úarg1Úarg2rC  r7  r,  r  r:  r;  r<  Zdiv_attr_callÚattr_varÚfunc_var_typÚattr_assignZdiv_callrD  r^   r^   rd   r<  À  s&    

  ÿr<  c
               	      sR  |j }
|}||j }||j j}t|ƒ}ˆ  |¡p4g }‡ fdd„|D ƒ}|dkrút |jtdƒ|
¡}t	j
j|jddd�}|||j< t dtj||g|||¡}|j |¡ |}t d|j ¡}t |jtd	ƒ|
¡}t	j||j< t |||
¡}|	 |¡ |}�n(|dk�r|d
 }�ntdd„ |D ƒƒ�r"|| }t |jtdƒ|
¡}t	j t	j|¡||j< t d|j ¡}t |jtd	ƒ|
¡}t	j||j< t |||
¡}|	 |¡ g }tt|ƒƒD ]>}|| }|| }|dk�rÖ| |¡ n| |||  ¡ �q¬tt|ƒƒ}tj ||
¡}t |||
¡}|	 |¡ |}tj |||
¡}t |||j ||j ƒ||< |S )a  if there is implicit dimension broadcast, generate proper access variable
    for getitem. For example, if indices are (i1,i2,i3) but shape is (c1,0,c3),
    generate a tuple with (i1,0,i3) for access.  Another example: for (i1,i2,i3)
    and (c1,c2) generate (i2,i3).
    c                    s   g | ]}ˆ   |¡‘qS r^   )Zget_equiv_constr®  ©r%  r^   rd   re   ï  s     z*_gen_arrayexpr_getitem.<locals>.<listcomp>r   z$ravelr|   r¨  )r…   rŒ   rª  rš   z$const_ind_0r”  c                 S   s   g | ]}|d k	‘qS rl   r^   r®  r^   r^   rd   re     s     z$parfor_index_tuple_var_bcast)!r  r
  rŒ   r�   rc  r   r  r,  r   r
   r²   r³   r…   r   Úgen_np_callr÷   rš   r4  r�  r1  rŽ  r*  r  rå   r˜  r™  r¤  rq   rZ  ru  rš  rf  rP   ) r%  rÊ   rA  rB  rm  r  r  r7  r!  rC  r  r#  rG  r�  Znum_indicesrn  Zsize_constsZ	ravel_varZ	ravel_typÚstmtsÚ
const_nodeÚ	const_varÚconst_assignZ
ind_offsetrž  ro  rˆ   r‘  Z
size_constrŸ  r   rE  r^   rN  rd   r?  Ù  sh    




ÿÿ


ÿr?  c                 C   s@   |D ](}| | }t |tƒr|j|kr|  S qtjd|d�‚dS )zAfind variable in typemap which represents the function func.
    zufunc call variable not foundr—  N)r�   rQ   Ú
typing_keyr   r›  )r7  r  r§  r  r�  rÙ  r^   r^   rd   r>  &  s
    
r>  c           
   
   C   s¦   t j t  |j¡¡ d}i }tt|j ¡ ƒƒj}|j 	¡ D ]*\}}	t
||	|||||d�\}}|	||< q:||_|r|t|jƒ|_t|dƒ t||||d ƒ t|dƒ d S )NFr  z after parfor sequential loweringr~   z after parfor sequential simplify)r   rH  r©  r  rk  ÚnextÚiterr|  r,  r3  Ú_lower_parfor_sequential_blockr1   r.   r3   )
r  rP  r7  r  rI  Úparfor_foundr  r,  r3  rD  r^   r^   rd   r2  1  s*         þ


r2  c              
   C   s  t |jƒ}|dk�rúd}|j| }|jj}	t ||	¡}
|jd |… |
_|j|d d … |_tƒ }|
j t ||	¡¡ t	|j|ƒ||< |
|| < tƒ } t
|jƒ}t|ƒD ]È}|j| }tƒ }tƒ }t||j|j|j|||	ƒ}||jd _|jd j}|||< t|||||	ƒ}|j|jd _|||< |dk�rL|jj t ||	¡¡ | |jd _n||| jd _||jd _|}q¤t|j ¡ ƒ}|j| j t ||	¡¡ t|j ¡ ƒ}||jd _|j ¡ D ]2\}}t|||||||d�\}}t	||ƒ||< �qºt |jƒ}q
| |fS )Nr”  Tr|   éþÿÿÿr   r  )Ú_find_first_parforr4  r!  r  r   rb  r    r  r�  rI   r�   r   rq   r#   rÔ   rÏ   rÖ   r+  r$   r  ÚfalsebrÚtruebrr–   r"  r~  r‰   r3  rW  )r3  rD  r  r7  r  rX  r,  rˆ   rx  r  Ú
prev_blockZ
init_labelr�  rB  Zrange_labelZheader_labelÚrange_blockÚphi_varÚheader_blockZprev_header_labelÚbody_last_labelÚbody_first_labelrj   r¥   r^   r^   rd   rW  E  sz    




ù ÿ

ÿ     þ
rW  c                 C   s.   t | ƒD ] \}}t|tƒr|js|  S qdS ©Nr”  )r·  r�   r  r  ©r4  rˆ   rx  r^   r^   rd   rZ  Œ  s    
rZ  c                 C   sÔ   t ƒ }g }t ƒ }t| ƒ\}}t| ƒ}|D ]¢}	| |	 }
t|
jƒD ]~\}}t |
j|
j¡}|
jd|… |_td|iƒj	d }||O }t
||||ƒ}t|
j||jƒ\|_|_| |j¡ | |¡ q>|||	 O }q(||fS )zfind variables used in body of parfors from outside and save them.
    computed as live variables at entry of first block.
    Nr   )rN  rJ   r/   Ú_find_parforsr4  r   rb  r,  r  rï  Úget_parfor_params_innerÚ#_combine_params_races_for_ssa_namesr  r$  r}  r  r  )rk  Úoptions_fusionr[  rú  r~   Úpre_defsr  Zall_defsrZ  rp  rD  rˆ   r   Zdummy_blockÚbefore_defsr$  r^   r^   rd   r!  “  s6    	   ÿ  ÿr!  c                    s`   ‡fdd„‰t |ƒ}ttˆ|ƒƒ}|D ],‰ t‡ ‡fdd„|D ƒƒrN| ˆ ¡ q& qTq&||B |fS )z§Returns `(params|races1, races1)`, where `races1` contains all variables
    in `races` are NOT referring to the same unversioned (SSA) variables in
    `params`.
    c                    s.   zˆ   | ¡jW S  tjk
r(   |  Y S X d S rl   )r  r	  r   r
  )rŠ  r  r^   rd   Ú	unversion»  s    z6_combine_params_races_for_ssa_names.<locals>.unversionc                 3   s   | ]}ˆˆ ƒ|kV  qd S rl   r^   )rb   Úpv)Úrvrk  r^   rd   rÚ   Æ  s     z6_combine_params_races_for_ssa_names.<locals>.<genexpr>)rN  rZ  r  rå   Údiscard)r,  r$  r  Zraces1Zunver_paramsr^   )rm  r,  rk  rd   rg  ¶  s    rg  c                 C   sÂ   t | ƒ}t|ƒ}t|ƒ}t|||j|jƒ}t|||ƒ\}}	t|ƒ}
|
dkr€tj	rr|rXdnd}t
d || j|
|¡ƒ t|ƒ|| j< t| ƒ t| ¡ ƒ}|d }|d }|j| |B }|| |@ }|S )Nr   r*  rõ  z2{}, parallel for-loop {} has nested Parfor(s) #{}.r|   )rQ  rM   rJ   rK   rî  rï  r!  r�   r   r,  r`   rç   r  rZ  rT  rA  r~  )r   ri  rh  r[  rk  rø  rù  ré  rú  r  rû  rÿ  Zkeylistr!  Zfirst_non_init_blockrj  r$  r^   r^   rd   rf  Î  s2    ÿ   þrf  c                 c   s*   t | ƒD ]\}}t|tƒr||fV  qd S rl   )r·  r�   r  rd  r^   r^   rd   re  è  s    
re  c                 C   s|   t | j ¡ ƒ}g }| j ¡ D ]B}|jD ]6}t|tjtjfƒr&t	|ƒj
| jj
kr&| |jj
¡ q&qtt|ƒt|ƒ@ ƒ}t|ƒS )zhget arrays that are written to inside the parfor and need to be passed
    as parameters to gufunc.
    )r–   r"  r~  r|  r4  r�   r   rƒ  ri  r  r
  r#  r  r+  rZ  rN  rA  )r   Úparfor_paramsÚ
last_labelÚoutputsrq  r5  r^   r^   rd   Úget_parfor_outputsî  s    
ÿrr  Ú_RedVarInforŸ   Úreduce_nodesÚredopT)Úfrozenc	                 C   s8  |dkri }|dkrg }|dkr(t tƒ}|dkr8t tƒ}|dkrDi }t|ƒ}	t|	ƒ}
|
dd… }
t|ƒ t|
ƒD �]}t|j| jƒD �]}t|t	j
ƒ�rj|jj|ks´|jj|k�rj|j}|j}|j|krÎ|n||j }g }t|t	jƒrò|jg}n"t|t	jƒ�rdd„ |j ¡ D ƒ}||  |¡ |D ]}|||< �q&t |¡}|j|k�r\||j ||j< ||  |¡ t|tƒr†t| |||||d||ƒ	 q†qp| ¡ D ]–\}}|j}||k�r˜||k�r˜||  ¡  t||| | ƒ}|dk	�r˜| |¡ t||ƒ tt|ƒ}|dk	�r|\}}nd}d}t|||d�||< �q˜||fS )z‚find variables that are updated using their previous values and an array
    item accessed with parfor index, e.g. s = s+A[i]
    Nr|   c                 S   s   g | ]
}|j ‘qS r^   rÞ  rí  r^   r^   rd   re   ,  s     z)get_parfor_reductions.<locals>.<listcomp>)rŸ   rt  ru  )r   rZ  rQ  r/   rT  r¤  r"  r4  r�   r   r*  r+  r
  rt  r  ru  r  r�  rz  r{  r  r  r"  r3  r  Úget_reduce_nodesÚ%check_conflicting_reduction_operatorsr:   Úget_reduction_initrs  )rP  r   ro  r  Z
reductionsZreduce_varnamesZ
param_usesZparam_nodesZvar_to_paramrk  rZ  rp  r5  r8  rW  Z	cur_paramÚ	used_varsr�  Zstmt_cpÚparamÚ
param_namert  Zgri_outrŸ   ru  r^   r^   rd   r"    s~    
ÿ
þ



    ÿ





ýr"  c                 C   sn   d}|D ]`}t |tjƒrt |jtjƒr|jjdkr|dkrD|jj}q||jjkrd| j }t 	||j
¡‚qdS )zÿIn prange, a user could theoretically specify conflicting
       reduction operators.  For example, in one spot it is += and
       another spot *=.  Here, we raise an exception if multiple
       different reduction operators are used in one prange.
    NrQ  zCReduction variable %s has multiple conflicting reduction operators.)r�   r   r*  rt  ru  r  Úfnr	  r   r›  r  )r{  ÚnodesZfirst_red_funcÚnoderJ  r^   r^   rd   rx  Y  s    ÿ
þ
ÿrx  c                 C   sŠ   t t| ƒdkƒ ttdd„ | ƒƒd j}t t|tjƒo>|jdkƒ |j	t
jksZ|j	t
jkrdd|j	fS |j	t
jks||j	t
jkr†d|j	fS dS )z^
    Get initial value for known reductions.
    Currently, only += and *= are supported.
    r|   c                 S   s   t | jtjƒS rl   )r�   rt  r   ru  rž  r^   r^   rd   ró   t  rô   z$get_reduction_init.<locals>.<lambda>r”  rQ  r   )NN)r;   r�   rZ  r‡  rt  r�   r   ru  r  r}  rz  ÚiaddÚisubÚimulÚitruediv)r~  Zacc_exprr^   r^   rd   ry  l  s    

ÿ
ry  c                 C   sŽ   | j dks| j dkrh| jtjks,| jtjkr:t d| j¡‚tjtj	tj
tjtjtjtjtjg}| j|kS | j dkrŠtt|| ƒ}|dkrŠdS dS )NrQ  rg  zÑParallel floordiv reductions are not supported. If all divisors are integers then a floordiv reduction can in some cases be parallelized as a multiply reduction followed by a floordiv of the resulting product.rs  ))r–   rƒ   )r‰   rƒ   )r   únumba.np.npdatetime_helpers)r   r„  TF)r  r}  rz  Ú	ifloordivÚfloordivr   ÚNumbaValueErrorr  r€  r�  r‚  rƒ  r}  ÚsubÚmulr;  r:   r8   )ri   rP  Zsuppsr  r^   r^   rd   Úsupported_reduction}  s(    üù

rŠ  c                    s–  d}i ‰ d‡ ‡fdd„	‰| j ‰| j}t|ƒD �]b\}}|j}|j}|ˆ |j < t|tjƒrj|j ˆ krjˆ|ƒ}t|tjƒr,t	‡fdd„| 
¡ D ƒƒ}	ˆ|	kr,|d t|ƒk rÐt||d  tjƒrÐ||d  jj|ksê|j|krêtd|›d	�ƒ‚t||ƒ�std| d
 ƒ‚‡fdd„t|ƒD ƒ}
‡fdd„|
D ƒ}t|ƒdk�s@t‚dd„ |
D ƒ}
t|
ƒ}t |jˆd |j¡||d < t||ƒ ||d… } �q’q,|S )z¯
    Get nodes that combine the reduction variable with a sentinel variable.
    Recognizes the first node that combines the reduction variable with another
    variable.
    NTc                    s:   ˆ   | jd ¡}t|tjƒr"ˆ|ƒS |s.|d kr2| S |S d S rl   )rE  r
  r�   r   r  )rÊ   Zvaronlyr‡   )ÚdefsÚlookupr^   rd   rŒ  ¢  s    z get_reduce_nodes.<locals>.lookupc                 3   s   | ]}ˆ |d ƒj V  qdS )TNrÞ  rí  ©rŒ  r^   rd   rÚ   ±  s     z#get_reduce_nodes.<locals>.<genexpr>r|   zUse of reduction variable z? other than in a supported reduction function is not permitted.z& in an unsupported reduction function.c                    s   g | ]}|j ˆ |d ƒf‘qS ©TrÞ  r®  r�  r^   rd   re   Ã  s     z$get_reduce_nodes.<locals>.<listcomp>c                    s   g | ]\}}|j ˆ kr|‘qS r^   rÞ  rì  rÞ  r^   rd   re   Ä  s     
 c                 S   s"   g | ]\}}||j kr||f‘qS r^   rÞ  rì  r^   r^   rd   re   Æ  s     
 z#initr   )T)r
  r	  r·  r+  rt  r�   r   r  ru  rN  r  r�   r*  ræ   rŠ  Úget_expr_argsr&  rW  r,  r  r'   )Zreduction_noder~  rP  rt  r	  rˆ   r5  r8  rW  Zin_varsrs   Znon_red_argsZreplace_dictr^   )r‹  rŒ  r
  rd   rw  ™  sH    
$ÿþ
ÿÿ
rw  c                 C   sB   | j dkr| j| jgS | j dkr0dd„ | jD ƒS td | ¡ƒ‚dS )z-
    Get arguments of an expression node
    )rg  rQ  rs  c                 S   s   g | ]}|‘qS r^   r^   rí  r^   r^   rd   re   Õ  s     z!get_expr_args.<locals>.<listcomp>zget arguments for expression {}N)r  r8  rW  rs   r½  rç   )r   r^   r^   rd   r�  Î  s
    

r�  c                 C   s    | j D ]”}|d dkr|d d }tt|ƒƒD ](}t|| tjƒr.t|| ||ƒ||< q.|d d }tt|ƒƒD ](}t|| tjƒrpt|| ||ƒ||< qpqd S )Nr   r  r|   )r'  rq   r�   r�   r   r  r)   )r   ÚcallbackÚcbdatar-  Úleft_lengthsrˆ   Úright_lengthsr^   r^   rd   Úvisit_parfor_pattern_varsØ  s     
 ÿ
 ÿr”  c                 C   sÌ   t jdkr&td| ƒ tdt| ¡ ƒƒ | jD ]n}t|j||ƒ|_t|j	t
jƒr^t|j	||ƒ|_	t|jt
jƒr|t|j||ƒ|_t|jt
jƒr,t|j||ƒ|_q,td| ji||ƒ t| ||ƒ t| j||ƒ d S )Nr|   zvisiting parfor vars for:zcbdata: r”  )r   rk  r`   rA  r3  r   r)   r  r�   rÔ   r   r  rÏ   rÖ   r(   r!  r”  r"  )r   r�  r‘  rj   r^   r^   rd   Úvisit_vars_parforç  s    


r•  c                 C   s"  |dkrt ƒ }|dkrt ƒ }t| ƒ}t|ƒ\}}t|ƒ}t| ¡ ƒ}t| ƒ | ¡ }| ¡ | }	| 	¡  
¡ D ]}
|	|
j8 }	ql|D ]@}||	kr®| || | ¡ | || ¡ q€| || | ¡ q€dd„ | jD ƒ}|dd„ | jD ƒO }|dd„ | jD ƒO }| || ¡ |t| ƒO }tj||d�S )zzlist variables written in this parfor by recursively
    calling compute_use_defs() on body and combining block defs.
    Nc                 S   s"   h | ]}t |jtjƒr|jj’qS r^   ©r�   rÔ   r   r  r
  r×  r^   r^   rd   rÝ  "  s     ÿ zparfor_defs.<locals>.<setcomp>c                 S   s"   h | ]}t |jtjƒr|jj’qS r^   ©r�   rÏ   r   r  r
  r×  r^   r^   rd   rÝ  %  s     ÿ c                 S   s"   h | ]}t |jtjƒr|jj’qS r^   ©r�   rÖ   r   r  r
  r×  r^   r^   rd   rÝ  (  s     ÿ )rî  rï  )rN  rQ  rJ   rM   r–   r~  rT  rZ  Ú
dominatorsrÔ  r|  r4  r©  r   Úget_parfor_pattern_varsr   Ú_use_defs_result)r   Úuse_setÚdef_setrk  Úusesr‹  rø  rp  rZ  Zdefinitely_executedr6  rp  Ú	loop_varsr^   r^   rd   Úparfor_defsý  s<    ÿÿÿr   c                 C   s0   |t | jƒO }t| ƒ}|t |¡O }t| ƒ dS )zx
    Reduction variables for parfors and the reduction variables within
    nested parfors must be stack allocated.
    N)rN  r)  rQ  r   Úmust_use_allocarT  )r   Z
alloca_setrk  r^   r^   rd   Ú_parfor_use_alloca4  s    r¢  c                 C   s<  t | ƒ}t|ƒ}t|ƒ}t|||j|jƒ}t||||jƒ}dd„ | jD ƒ}|dd„ | jD ƒO }|dd„ | jD ƒO }|dd„ | jD ƒO }tƒ }| 	¡ D ]h}	|j
|	  |M  < |j
|	  |8  < ||j
|	 O }|j|	  |M  < |j|	  |8  < ||j|	 O }q”G dd„ dtƒ}
t |
|ƒ¡}| |j
|j¡ t| ƒ ||B S )z~insert dels in parfor. input: dead variable set right after parfor.
    returns the variables for which del was inserted.
    c                 S   s"   h | ]}t |jtjƒr|jj’qS r^   r–  r×  r^   r^   rd   rÝ  O  s     ÿ z%parfor_insert_dels.<locals>.<setcomp>c                 S   s"   h | ]}t |jtjƒr|jj’qS r^   r—  r×  r^   r^   rd   rÝ  R  s     ÿ c                 S   s"   h | ]}t |jtjƒr|jj’qS r^   r˜  r×  r^   r^   rd   rÝ  U  s     ÿ c                 S   s   h | ]}|j j’qS r^   ©r  r
  r×  r^   r^   rd   rÝ  X  s     c                   @   s   e Zd Zdd„ ZdS )z'parfor_insert_dels.<locals>.DummyFuncIRc                 S   s
   || _ d S rl   rÛ  rj  r^   r^   rd   r  i  s    z0parfor_insert_dels.<locals>.DummyFuncIR.__init__N)ru   rv   rw   r  r^   r^   r^   rd   ÚDummyFuncIRg  s   r¤  )rQ  rM   rJ   rK   rî  rï  rL   r   rN  r~  r“  ÚescapingÚobjectr   ÚPostProcessorÚ_patch_var_delsrT  )r   Zcurr_dead_setrk  rø  rù  ré  Zdead_maprŸ  Údead_setrp  r¤  Ú	post_procr^   r^   rd   Úparfor_insert_delsD  s8    ÿÿÿr«  c           
      C   sN   t |ƒ\}}t|| j|| ƒ\}}| ¡ D ] }d}	|	r(t| |||||ƒ}	q0q(dS )zm
    Reorder statements to maximize parfor fusion. Push all parfors up or down
    so they are adjacent.
    TN)r2   rG   Ú	arg_namesr|  Úmaximize_fusion_inner)
rP  rk  r7  r  r  r  Ú	alias_mapÚarg_aliasesrD  Úorder_changedr^   r^   rd   r#  u  s$    üúr#  c                 C   sˆ   d}d}|t |jƒd k r„|j| }|j|d  }	|rHt||	| |||ƒnt|	|| |||ƒ}
|
rz|	|j|< ||j|d < d}|d7 }q|S )NFr   r±   r|   T)r�   r4  Ú_can_reorder_stmts)rP  rD  r  r®  r¯  r  r°  rˆ   r5  r'  Zcan_reorderr^   r^   rd   r­  �  s0    
þ
  ÿ   ÿþ

r­  c                 C   sF   t ƒ }| D ]6}||kr$| || ¡}||kr6| |¡}| |¡ q
|S rl   )rN  r  r}  )Zthe_setr®  r¯  Úretrˆ   r^   r^   rd   Úexpand_aliases¡  s    
r³  c           
      C   s¾   t | tƒrºt |tƒsºt |tjƒsºt |tjƒrJt|jtƒ |ƒsJtt	||jƒrºt
dd„ |  ¡ D ƒ||ƒ}t
t| ƒ||ƒ}t
dd„ | ¡ D ƒ||ƒ}t
t|ƒ||ƒ}	t||@ |	|@ B ƒdkrºdS dS )zw
    Check dependencies to determine if a parfor can be reordered in the IR block
    with a non-parfor statement.
    c                 S   s   h | ]
}|j ’qS r^   rÞ  rí  r^   r^   rd   rÝ  »  s     z%_can_reorder_stmts.<locals>.<setcomp>c                 S   s   h | ]
}|j ’qS r^   rÞ  rí  r^   r^   rd   rÝ  ¿  s     r   TF)r�   r  r   r.  r*  r5   rt  rN  r:   Úis_assert_equivr³  r  Úget_parfor_writesr0   r�   )
r5  r'  rP  r  r®  r¯  Zstmt_accessesZstmt_writesZnext_accessesZnext_writesr^   r^   rd   r±  «  sD    

ÿ
þ
ýüû ÿ ÿ ÿ ÿÿÿr±  c                 C   s   t | |ƒ\}}|dkS )NrW   )r8   )rP  r   rº  r¶  r^   r^   rd   r´  È  s    r´  c                 C   sl   t | tƒst‚tƒ }| j ¡ }| j|d< | ¡ D ]6}|jD ]*}| 	t
|ƒ¡ t |tƒr:| 	t|ƒ¡ q:q0|S rc  )r�   r  r&  rN  r"  rz  r!  r|  r4  r©  r0   rµ  )r   Úwritesrk  rD  r5  r^   r^   rd   rµ  Í  s    



rµ  ÚFusionReportÚfirstÚsecondÚmessagec                    sÊ  t d|d|ƒ d}|j|jkrBt dƒ d}t|j|j|ƒ}d|fS t|jƒt|jƒkr®t dƒ d}d}||jt|jƒf }	||jt|jƒf }
t|j|j||	|
f ƒ}d|fS t|jƒ}‡ fd	d
„}‡fdd„}t|ƒD ]¼}|j| }|j| }||j|jƒ�r||j|jƒ�r||j	|j	ƒsØt d|ƒ d}|d||jƒ||jƒ||j	ƒf 7 }|d||jƒ||jƒ||j	ƒf 7 }t|j|j|| ƒ}d|f  S qØt
|jƒ|_t|||ƒ\}}}}|�sÔt||||||ƒd }nd}|�sä|�rt dƒ d}t|j|j||j|jf ƒ}d|fS t|jƒ}tƒ }|j ¡ D ]}||O }�q.|t|jƒO }t|jƒ}td|jiƒjd }|j ¡ D ]}||O }�qt| |¡�sÀt dƒ d}t|j|j||j|jf ƒ}d|fS t||ƒS )zItry to fuse parfors and return a fused parfor, otherwise return None
    ztry_fuse: trying to fuse 
r¯  Nz$try_fuse: parfors different lowerersz!- fusion failed: lowerer mismatchz/try_fuse: parfors number of dimensions mismatchz4- fusion failed: number of loops mismatched, %s, %s.z(parallel loop #%s has a nest of %s loopsc                    s   | |kpˆ   | |¡S rl   )Úis_equiv)ri   rc   rN  r^   rd   r»  ÷  s    ztry_fuse.<locals>.is_equivc                    s>   t | tjƒs| S | j} dˆ kr:| ˆ d kr:ˆ d |  }|S | S )z.get original variable name by user if possibleÚvar_rename_map)r�   r   r  r
  )r�  Zuser_varname)rI  r^   rd   Úget_user_varnameú  s    z"try_fuse.<locals>.get_user_varnamez/try_fuse: parfor dimension correlation mismatchz7- fusion failed: loop dimension mismatched in axis %s. zslice(%s, %s, %s) != zslice(%s, %s, %s)r   Tz1try_fuse: parfor cross iteration dependency foundzK- fusion failed: cross iteration dependency found between loops #%s and #%sz)try_fuse: parfor2 depends on parfor1 bodyzT- fusion failed: parallel loop %s has a dependency on the body of parallel loop %s. )Údprintr+  r·  r  r�   r   rq   rÔ   rÏ   rÖ   r?   rk  r   Úhas_cross_iter_deprJ   r"  rN  rï  r|  r)  r!  rî  Ú
isdisjointÚfuse_parfors_inner)r%  Úparfor1Úparfor2rI  rP  r7  rü  rJ  r.  rý  rþ  r�  r»  r½  rˆ   Znest1Znest2Zp1_cross_depZp1_ipZp1_iaZ	p1_non_iaZp2_cross_depZp1_body_usedefsZp1_body_defsr‹  Z
p2_usedefsZp2_usesrž  r^   )r%  rI  rd   r%  Û  s†    



ÿþ
 ÿ ÿ
ÿ


ÿr%  c                 C   sV  | j j |j j¡ t|j ¡ ƒ}|j| j}t| j ¡ ƒ}t| j ¡ ƒ}| j| j |¡ | j |j¡ | j |¡ t	| j
ƒ}|jj| ji}t|ƒD ]}| j
| j||j
| jj< q”t| j|ƒ t| |d�}	t|	ƒ}	t| |	ƒ tdd„ | ¡ D ƒƒ}
t| j|
ƒ | j |j¡ tj�r*td |j| j¡ƒ d}| |j| j¡}t| j|j|ƒ}| |fS )N)Úentry_labelc                 s   s   | ]}|j V  qd S rl   rÞ  r®  r^   r^   rd   rÚ   \  s     z%fuse_parfors_inner.<locals>.<genexpr>z1Parallel for-loop #{} is fused into for-loop #{}.zE- fusion succeeded: parallel for-loop #{} is fused into for-loop #{}.)r!  r4  r�  r‰   r"  r~  r–   r©  r)  r�   r   r#  r
  rq   r  r&   rQ  r1   rT  rN  r|  Úremove_duplicate_definitionsr'  r   r,  r`   rç   r  r·  )rÂ  rÃ  Zparfor2_first_labelZparfor2_first_blockZparfor1_first_labelZparfor1_last_labelr�  Z
index_dictrˆ   rk  ÚnamesetrJ  rü  r^   r^   rd   rÁ  ?  s<    
ÿ
 ÿrÁ  c           	      C   sp   |   ¡ D ]b\}}|j}g }tƒ }|D ]>}t|tjƒrX|jj}||krX||krNq$| |¡ | 	|¡ q$||_qdS )zsRemove duplicated definition for variables in the given nameset, which
    is often a result of parfor fusion.
    N)
r3  r4  rN  r�   r   r*  r+  r
  r}  r  )	rk  rÆ  rp  rD  r4  r[  Zdefinedrx  r
  r^   r^   rd   rÅ  j  s    
rÅ  c              	      sø  dd„ | j D ƒ‰tƒ }|d kr"i }|d kr0tƒ }|d kr>tƒ }dd„ ‰ ‡ ‡‡‡fdd„}| j ¡ D �]†}|jD �]x}	t|	tjtjfƒrÌtˆ|	j	j
 tjjƒrn||	j|	j	j
||||ƒrnd|||f    S qnqnt|	tjƒrnt|	jtjƒ�r|	jj
ˆk�rèˆ |	j	j
¡ qnqnt|	jtjƒrn|	jj}
|
dk�rttˆ|	jjj
 tjjƒrn||	jj|	jjj
||||ƒrnd|||f    S qnn<|
d	k�r°t‡fd
d„|	j ¡ D ƒƒ�r°d|||f    S dd„ |	j ¡ D ƒ}ˆ |¡�rÚ| |¡sn| |	j	j
¡ qnqbd|||fS )Nc                 S   s   h | ]}|j j’qS r^   r£  r×  r^   r^   rd   rÝ  ’  s     z%has_cross_iter_dep.<locals>.<setcomp>c                 S   sr   t | tƒrt| ƒ} d| kr4||kr&dS | |¡ dS ||kr@dS | |¡ t| ƒ}||krf| ||< dS || | kS )aA  Returns True if there is a reason to prevent fusion based
           on the rules described above.
           new_position will be a list or tuple of booleans that
           says whether the index in that spot is a parfor index
           or not.  array_accessed is the array on which the access
           is occurring.TF)r�   rZ  r–  r}  r�   )Znew_positionÚarray_accessedÚindex_positionsÚindexed_arraysÚnon_indexed_arraysZnpsizer^   r^   rd   Úadd_check_position´  s    


z.has_cross_iter_dep.<locals>.add_check_positionc           
         sÌ   t | tjƒrºt ˆ| j tjƒr€ttˆ| ƒ}|dk	rz|\}}t‡ ‡fdd„|D ƒƒrt‡fdd„|D ƒ}	ˆ|	||||ƒS dS q¸dS q¾| jˆkršˆd||||ƒS | jˆ kr¨dS ˆd||||ƒS ndS t	 
d¡‚dS )	zÅLooks at the indices of a getitem or setitem to see if there
           is a reason that they would prevent fusion.
           Returns True if fusion should be prohibited, False otherwise.
        Nc                    s    g | ]}|j ˆkp|j ˆ k‘qS r^   rÞ  r®  )Úderived_from_indicesrã  r^   rd   re   ù  s   ÿ
z;has_cross_iter_dep.<locals>.check_index.<locals>.<listcomp>c                    s   g | ]}|j ˆ k‘qS r^   rÞ  r®  )rã  r^   rd   re   ü  s     TrŽ  )FzjSome code path in the parfor fusion cross-iteration dependency checker check_index didn't return a result.)r�   r   r  r
  r
   rF  r:   r9   Úallr   ÚInternalError)
Z
stmt_indexrÇ  rÈ  rÉ  rÊ  rÌ  Zfbs_resZind_seqr  Znew_index_positions©rË  rP  rã  r7  )rÌ  rd   Úcheck_indexæ  sD    
ÿü
ü
üz'has_cross_iter_dep.<locals>.check_indexTrß  rs  c                    s    g | ]}t ˆ |j tjjƒ‘qS r^   )r�   r
  r
   r²   r³   r®  r9  r^   rd   re   V  s   ÿz&has_cross_iter_dep.<locals>.<listcomp>c                 S   s   g | ]
}|j ‘qS r^   rÞ  r®  r^   r^   rd   re   [  s     F)r   rN  r"  r|  r4  r�   r   ri  rƒ  r+  r
  r
   r²   r³   rœ   r*  rt  r  r}  ru  r  rå   r  rÀ  )r   rP  r7  rÈ  rÉ  rÊ  rÌ  rÐ  r¥   r5  r  Úrhs_varsr^   rÏ  rd   r¿  ~  sh    2Gû
û
ÿ
ÿr¿  c                  G   s   t jdkrt| Ž  d S rÒ   )r   rk  r`   )r§   r^   r^   rd   r¾  h  s    
r¾  c                 C   s`   t ƒ }| jD ]N}|d dkr|d d }|d d }|| D ]}t|tjƒr<| |j¡ q<q|S )z: get the variables used in parfor pattern information
    r   r  r|   )rN  r'  r�   r   r  r}  r
  )r   Úoutr-  r’  r“  r�  r^   r^   rd   rš  l  s    
rš  c           #   	   C   sü  t | jƒ� t| jƒ}W 5 Q R X |d }i }	t| j| j| j||	|ƒ t|	 ¡ ƒ}
|D ]Ž}||krdqV| j| jD ]r}t|t	j
ƒr®t|jt	jƒr®|jjdkr®|jjj| jjkr®qptdd„ | ¡ D ƒƒ}||
@ }|D ]}|	 |d¡ qÐqpqV|D ]4}||krøqê| j| }|	 ¡ }t|j| j|||ƒ qê| j ¡ }t| ¡ ƒ}t|||ƒ\}}t	 |t	 dd¡¡}|| j |¡ t|ƒ}t|ƒ}t|||j|jƒ}t| ¡ ƒ}| ¡ D ]ì\}}g }dd	„ |j ¡ D ƒ}| |¡D ]\}}||| O }�qÊt |jƒD ]Ž}||@ } | D ]}!|||! O }�qüt|t	j!t	j"fƒ�rXt#|ƒj| jjk�rX|j$j|k�rX|j$j|k�rX�qì|d
d	„ | ¡ D ƒO }| |¡ �qì| %¡  ||_�q | |j¡ || j ¡  t&| |||||ƒ t'| j(jƒdk}"| j )¡ D ]}|"t'|jƒdkM }"�qÔ|"�rødS | S )z7 remove dead code inside parfor including get/sets
    r   rf  c                 s   s   | ]}|j V  qd S rl   rÞ  rí  r^   r^   rd   rÚ   ˜  s     z%remove_dead_parfor.<locals>.<genexpr>NÚparfors_dummyr”  c                 S   s   h | ]
}|j ’qS r^   rÞ  rí  r^   r^   rd   rÝ  ·  s     z%remove_dead_parfor.<locals>.<setcomp>c                 S   s   h | ]
}|j ’qS r^   rÞ  rí  r^   r^   rd   rÝ  Å  s     )*r  r"  r/   Ú_update_parfor_get_setitemsr4  r#  rN  r~  r�   r   r*  rt  ru  r  rœ   r
  r  r)  rz  r–   Ú_add_liveness_return_blockr�  ÚLocr  rM   rJ   rK   rî  rï  r3  Ú
terminatorÚ
successorsr¤  rƒ  ri  r  r+  r  Úremove_dead_parfor_recursiver�   r!  r|  )#r   ÚlivesÚlives_n_aliasesr¯  r®  rP  r7  rþ  r  Zfirst_block_saved_valuesZ
saved_arrsrj   r5  ÚvarnamesZrm_arrsr¤   rD  Úsaved_valuesrk  rp  Úreturn_labelrž  Újumprø  rù  ré  Ú	alias_setrp  r[  Zin_livesÚout_blkÚ_dataÚalias_livesr�  Úis_emptyr^   r^   rd   Úremove_dead_parforz  s¢    
 ü
ÿþ
 ÿ
ÿ
þ
ý

     ÿrå  c           	      C   s  | D ]ú}t |tjtjfƒrht|ƒj|jkrh|jj|krh| |jjg ¡D ]}| |d¡ qF|j	||jj< qt |tj
ƒrÂt |j	tjƒrÂ|j	}|jdkrÂt |jtjƒrÂ|jj|jkrÂ| |j	j|¡|_	q| ¡ D ]2}| |jd¡ | |jg ¡D ]}| |d¡ qêqÊqdS )zS
    replace getitems of a previously set array in a block of parfor loop body
    Nrf  )r�   r   rƒ  ri  r  r
  r+  rE  r)  rt  r*  ru  r  rœ   r  r  )	Z
block_bodyr#  r®  rÝ  rÚ  r5  ÚwrW  r�  r^   r^   rd   rÔ  à  s*    ÿ
þrÔ  c              	   C   sþ   | j  ¡ }t| ¡ ƒ}|dks"t‚t| ¡ ƒ}t|||ƒ\}	}
|| j}t 	|t
dƒt dd¡¡}tj||j< t |||	t dd¡¡}|| j |¡ | j|d< |d j t |t dd¡¡¡ t||||||ƒ | |
j¡ |d j ¡  || j ¡  dS )zIcreate a dummy function from parfor and call remove dead recursively
    r   z$branchcondrÓ  r”  N)r"  rz  r‰   r~  r&  r–   rÕ  r,  r   r  r   rÖ  r
   Úbooleanr
  r�  r4  r  r!  r�  r*   r)  )r   rÚ  r¯  r®  rP  r7  rk  rý  rp  rÞ  rž  r,  Z
branchcondÚbranchr^   r^   rd   rÙ    s"    


 rÙ  c                    s¼   t |  ¡ ƒ}|d }| | j‰ | | j‰t ˆˆ ¡| |< t ˆtdƒˆ ¡}tj	 
tjd¡||j< ‡ ‡fdd„|D ƒ}tj |ˆ ¡}| | j t ||ˆ ¡¡ | | j t |ˆ ¡¡ ||fS )Nr|   z
$tuple_varr±   c                    s   g | ]}t  ˆ|ˆ ¡‘qS r^   )r   r  rí  ©r  r,  r^   rd   re   ;  s     z._add_liveness_return_block.<locals>.<listcomp>)r–   r~  r  r,  r   rb  r  r   r
   r˜  r™  rŽ  r
  ru  rš  r4  r  r*  ÚReturn)rk  rÚ  r7  rp  rÞ  rž  rë  rŸ  r^   ré  rd   rÕ  .  s    

 ÿ
rÕ  c                 C   s(   t | ƒ}t ||||||¡ t| ƒ d S rl   )rQ  r   rG   rT  )r   rs   r7  rP  r®  r¯  rk  r^   r^   rd   Úfind_potential_aliases_parforB  s         ÿrë  c           	   
   C   sÖ   d}|   ¡ D ]Ä}|jD ]¸}t|tƒr|d7 }|}|jt|j ¡ ƒ }|j}t 	dd¡}t 
|tdƒ|¡}|j t t d|¡||¡¡ |j t ||¡¡ t|jƒ|_|jt|j ¡ ƒ }|j ¡  t|jƒ qq|S )z%simplify CFG of body loops in parforsr   r|   rÓ  r”  ú$const)r|  r4  r�   r  r"  r–   r~  r,  r   rÖ  r  r   r  r*  r1  rê  r4   r)  r  )	rk  rû  rD  r5  r   Z
last_blockr,  r  Úconstr^   r^   rd   r  K  s"    


r  c                 C   s”   | j  ¡ }|dkrt| ¡ ƒ}|dks*t‚| j|d< |d j t 	||d j
¡¡ | ¡ D ]4}t|jƒdksx|jd jsZ|j t 	||j
¡¡ qZ|S )z5wrap parfor blocks for analysis/optimization like CFGNr   r”  )r"  rz  r‰   r~  r&  r!  r4  r  r   r�  r  r|  r�   Úis_terminator)r   rÄ  rk  rD  r^   r^   rd   rQ  c  s    

rQ  c                 C   s–   |dk	r$t | ¡ ƒ}| |¡ || _t | j ¡ ƒ}t| jjd tjƒsJt	‚| jj ¡  | j 
¡ D ]0}t|jd tjƒr`|jd j|kr`|j ¡  q`dS )zb
    unwrap parfor blocks after analysis/optimization.
    Allows changes to the parfor loop.
    Nr”  )r‰   r~  r)  r"  r�   r!  r4  r   r�  r&  r|  r+  )r   rk  Zinit_block_labelrÿ  rD  r^   r^   rd   rT  s  s    
ÿrT  c                 C   s¤   t | ƒ}t||ƒ\}}t||ƒ\}}t| ƒ |d }| j ¡ D ]&}|dd„ || D ƒO }||| O }q>t| j ¡ ƒ}	||	 |d @ }
tjdkrœt	d|
d|ƒ |
|fS )z&find copies generated/killed by parforr   c                 S   s   h | ]\}}|’qS r^   r^   )rb   rj   rò   r^   r^   rd   rÝ  œ  s     z$get_copies_parfor.<locals>.<setcomp>r|   zcopy propagate parfor gens:Úkill_set)
rQ  r+   r,   rT  r"  r~  r–   r   rk  r`   )r   r7  rk  Úin_copies_parforÚout_copies_parforZin_gen_copiesZin_extra_killrï  rp  rp  Zgensr^   r^   rd   Úget_copies_parfor�  s    
rò  c                 C   s  t | jƒD ],\}}|d dkr
dt|d |ƒf| j|< q
| jD ].}t|j|ƒ|_t|j|ƒ|_t|j|ƒ|_q>t| ƒ}	g }
| ¡ D ](\}}|
 	t
 ||| t
 dd¡¡¡ q‚|
|	d j |	d _t|	|ƒ\}}t|	|||||ƒ t| ƒ |	d jt|
ƒd… |	d _dS )z*apply copy propagate recursively in parforr   r  r|   Údummyr”  N)r·  r'  r'   r   rÔ   rÏ   rÖ   rQ  r3  r  r   r*  rÖ  r4  r+   r-   rT  r�   )r   Úvar_dictÚname_var_tabler7  r  Úsave_copiesrˆ   r-  rj   rk  Zassign_listÚlhs_namerW  rð  rñ  r^   r^   rd   Úapply_copies_parfor«  s0    ÿ

ÿ
 ÿrø  c              
      s  |   ¡ D ]ô}g }tƒ ‰ i }|jD ]˜}‡ ‡‡fdd„}	|s‚t|tƒr‚|jjD ]}
|	|
ƒ qJ|j ¡ }t|ˆˆ|dd� | 	|¡ q n|	|ƒ | 
¡ D ]}|t|jˆˆˆ |ƒ7 }q’| 	|¡ q ||_t|ƒdkr| ¡ D ]\}}|| ||< qÔd|i}t||ƒ qdS )zŸpush call variables to right before their call site.
    assuming one global/getattr is created for each call site and control flow
    doesn't change it.
    c                    s„   t | tjƒr€| j}| j}t |tjƒr<| ˆ|j< ˆ  |j¡ nDt |tjƒr€|j	dkr€|jjˆksj|jjˆkr€| ˆ|j< ˆ  |j¡ d S )Nr$  )
r�   r   r*  rt  r+  r/  r
  r}  ru  r  )r5  rW  r8  ©Ú
block_defsÚsaved_getattrsÚsaved_globalsr^   rd   Úprocess_assignÞ  s    

ÿ
z&push_call_vars.<locals>.process_assignT)Únestedr   N)r|  rN  r4  r�   r  r!  r"  rz  r+  r  r  Ú_get_saved_call_nodesr
  r�   r3  rH   )rk  rü  rû  r7  rþ  rD  r[  Úrename_dictr5  rý  r§   Zpblocksr�  rŠ  Ztemp_blocksr^   rù  rd   r+  Í  s8    




  ÿr+  c                 C   s~   g }| |krr| |ks| |krrdd„ }| |krF|||  d|||ƒ d} q| |kr|||  d|||ƒ ||  j j j} q| ¡  |S )al   Implement the copying of globals or getattrs for the purposes noted in
        push_call_vars.  We make a new var and assign to it a copy of the
        global or getattr.  We remember this new assignment node and add an
        entry in the renaming dictionary so that for this block the original
        var name is replaced by the new var name we created.
    c                 S   sn   t | tjƒst‚t | jjt|ƒ| jj¡}t t	 
| j¡|| j¡}| |¡ | | jj¡ |jj|| jj< d S rl   )r�   r   r*  r&  r  r+  r,  r   r  rz  r{  rt  r  r}  r
  )ÚobjZvar_baser~  rú  r   Zrenamed_varZrenamed_assignr^   r^   rd   Úrename_global_or_getattr  s    
þþ
z7_get_saved_call_nodes.<locals>.rename_global_or_getattrz$push_global_to_blockZ_PA_DONEz$push_getattr_to_block)rt  r
  r  )Úfnamerü  rû  rú  r   r~  r  r^   r^   rd   rÿ    s*    ÿ
  ÿ
  ÿrÿ  c                 C   sÒ   t | tƒr‚| d }t |tƒs2t|dƒr.|j}nd}| d }t|ƒdkrZd |t|d ƒ¡S d| d }d | dd	„ |D ƒ¡¡S nLt | t	j
jjƒr°| j}| d
¡rªd| S |S nt | t	j
jjƒrÊt| jƒS dS dS )zMExtract operators from arrayexpr to represent it abstractly as a string.
    r   ru   r  r|   z({}({}))r³  z({})c                 S   s   g | ]}t |ƒ‘qS r^   )r¯  r®  r^   r^   rd   re   6  s     z"repr_arrayexpr.<locals>.<listcomp>ú$z'%s' (temporary variable)N)r�   r–  r1  Úhasattrru   r�   rç   r¯  r£  r}   r3  r   r  r
  r´  r1  r2  rt  )r¢  Zoprrs   r
  r^   r^   rd   r¯  &  s&    




r¯  c                 C   s,   g }| j D ]}| || ¡ q
t|ƒ|_dS )z›postproc updates generator_info with live variables after transformations
    but generator variables have types in return_type that are updated here.
    N)Ú
state_varsr  r–  Ústate_types)r1  r�   r7  Znew_state_typesr�  r^   r^   rd   r0  B  s
    

r0  c                 C   s@   |d kri }|d kri }t | ƒ}t|||ƒ\}}t| ƒ ||fS rl   )rQ  r2   rT  )r   r  Úreverse_call_tablerk  r^   r^   rd   Úget_parfor_call_tableM  s    ÿr	  c                 C   s,   |d kri }t | ƒ}t ||¡}t| ƒ |S rl   )rQ  r   Úget_tuple_tablerT  )r   Útuple_tablerk  r^   r^   rd   Úget_parfor_tuple_table\  s    r  c                 C   s.   |d krt ƒ }t| ƒ}t ||¡}t| ƒ |S rl   )rN  rQ  r   Úget_array_accessesrT  )r   Úaccessesrk  r^   r^   rd   Úget_parfor_array_accessesh  s    r  c                 C   s6   t | ƒ}t||ƒ}|| |d< | |¡ t| |ƒ d S r˜   )rQ  r7   r)  rT  )r   rC  rk  r^   r^   rd   Úparfor_add_offset_to_labelsu  s    


r  c                 C   s   t | ƒ}t |¡}t| ƒ |S rl   )rQ  r   r  rT  )r   rk  Ú	max_labelr^   r^   rd   Úparfor_find_max_label�  s    
r  c                    sŽ   |j }t| ƒ}dd„ | jD ƒ}t| ¡ ƒ}|| j‰ ‡ fdd„|D ƒ}|| j}||| j || _||_ | ¡  ||_ ||| _t| ƒ d S )Nc                 S   s   g | ]
}|j ‘qS r^   )r  r×  r^   r^   rd   re   �  s     z$parfor_typeinfer.<locals>.<listcomp>c              	      s&   g | ]}t  t jd ˆ dd�|ˆ ¡‘qS )r|   F)r  Úuse_literal_type)r   r*  r1  rí  r—  r^   rd   re   “  s     )	rk  rQ  r   r‰   r~  r  r4  Zbuild_constraintrT  )r   ZtypeinfererZsave_blocksrk  ro  Úfirst_blockZindex_assignsZsave_first_block_bodyr^   r—  rd   Úparfor_typeinferŠ  s    


r  c                 C   s0   |dkrt tƒ}t| j|ƒ td| ji|ƒ |S )z)get variable definition table for parforsNr   )r   rZ  r?   r"  r!  )r   Údefinitionsr^   r^   rd   Úbuild_parfor_definitionsŸ  s
    r  c              	   c   sh   t |  ¡ ƒ}| | j}t |tdƒt dd¡¡}| | j t 	|t dd¡¡¡ dV  | | j 
¡  dS )zLadds dummy return to last block of parfor loop body for CFG computation
    rì  rÓ  r”  N)r–   r~  r,  r   r  r   rÖ  r4  r  rê  r)  )r"  rp  r,  rí  r^   r^   rd   r  ¬  s    

ÿr  c                   @   s   e Zd Zdd„ ZdS )ÚReduceInferc                 C   sF   |rt ‚t|ƒdkrt d¡‚t|d tjƒs2t ‚t|d jf|žŽ S )Nrã   zlen(args) != 3r|   )	r&  r�   r   ÚNumbaAssertionErrorr�   r
   r³   rP   r…   )r  rs   r·  r^   r^   rd   Úgeneric¼  s
    
zReduceInfer.genericN)ru   rv   rw   r  r^   r^   r^   rd   r  º  s   r  c                  C   s   t jrd} t | ¡‚dS )zKCheck if the platform supports parallel=True and raise if it does not.
    zDThe 'parallel' target is not currently supported on 32 bit hardware.N)r   Ú	IS_32BITSr   rI  )rJ  r^   r^   rd   Úensure_parallel_supportÄ  s    r  )F)NNNNN)NN)T)T)NNN)N)N)F)NN)N)N)N(  r  r
   Úpytypesr=  rÛ   rà  Útextwraprz  r´  rä  Ú	functoolsr   Úcollectionsr   r   r   Ú
contextlibr   rz  Údataclassesr   Úllvmliter   ÚlirÚnumba.core.imputilsr	   Únumba.core.irr}   r  r   r   r   r   r   r   r   r   r   r   r   Znumba.np.npdatetime_helpersr   r   Únumba.np.numpy_supportr   r   Únumba.core.typing.templatesr   r   Znumba.stencils.stencilparforr   Únumba.core.extendingr   r   Únumba.core.ir_utilsr   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   Únumba.core.analysisrJ   rK   rL   rM   Znumba.core.controlflowrN   Únumba.core.typingrO   rP   Znumba.core.types.functionsrQ   Znumba.parfors.array_analysisrR   rS   rT   rU   rV   rW   rX   r÷   r©   Únumba.parforsrY   Únumba.cpython.builtinsZnumba.stencilsrZ   r÷  ÚTextWrapperrg   rk   rø  rm   ro   r¦  rp   r’   r—   r¡   r£   r¨   r­   r°   rµ   r¼   rÀ   rÃ   rÉ   rÌ   rè   rð   r  r  r  r”   r€   r™   r¢   r	  r  r  ru  ÚStmtr  rU  Zarray_analysis_extensionsrV  r  r2  rD  rJ  r  r€  re  rd  r¡  rÀ  rÓ  rÈ  r  r  r(  rº  r»  r®  r<  r?  r>  r2  rW  rZ  r!  rg  rf  re  rr  rs  r"  rx  ry  rŠ  rw  r�  r”  r•  Úvisit_vars_extensionsr   Úir_extension_usedefsr¢  Úir_extension_use_allocar«  Úir_extension_insert_delsr#  r­  r³  r±  r´  rµ  r·  r%  rÁ  rÅ  r¿  r¾  rš  rå  rÔ  Úremove_dead_extensionsrÙ  rÕ  rë  Úalias_analysis_extensionsr  rQ  rT  rò  Úcopy_propagate_extensionsrø  Úapply_copy_propagate_extensionsr+  rÿ  r¯  r0  r	  Úcall_table_extensionsr  Útuple_table_extensionsr  Úarray_accesses_extensionsr  Úadd_offset_to_labels_extensionsr  Úfind_max_label_extensionsr  Ztypeinfer_extensionsr  Úbuild_defs_extensionsr  r  r  r^   r^   r^   rd   Ú<module>   s¸  	4´. 
" -ò ÿ



ú
 

     V  v B
 ^    R19iS(qMG#ý      þ
R5

4

.
ÿ

d+  ú
 kf!
*


8!
	


	




	