U
    hâËd»:  ã                   @   sH  d Z ddlZddlZddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZmZmZ dd	lmZ e e¡Zd
d„ ZG 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dd„ Zdd„ Z d d!„ Z!d"d#„ Z"G d$d%„ d%ƒZ#G d&d'„ d'e#ƒZ$G d(d)„ d)ƒZ%G d*d+„ d+e#ƒZ&G d,d-„ d-e#ƒZ'd.d/„ Z(dS )0a  
Implement Dominance-Fronter-based SSA by Choi et al described in Inria SSA book

References:

- Static Single Assignment Book by Inria
  http://ssabook.gforge.inria.fr/latest/book.pdf
- Choi et al. Incremental computation of static single assignment form.
é    N)Úreduce)Úcopy)Úpformat)Údefaultdict)Úconfig)ÚirÚir_utilsÚerrors)Úcompute_cfg_from_blocksc                 C   s   t | jƒ| _| S )znApply SSA reconstruction algorithm on the given IR.

    Produces minimal SSA using Choi et al algorithm.
    )Ú_run_ssaÚblocks)Zfunc_ir© r   úG/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/numba/core/ssa.pyÚreconstruct_ssa   s    r   c                   @   s   e Zd Zdd„ Zdd„ ZdS )Ú_CacheListVarsc                 C   s
   i | _ d S ©N)Ú_saved©Úselfr   r   r   Ú__init__%   s    z_CacheListVars.__init__c                 C   s*   | j  |¡}|d kr&| ¡  | j |< }|S r   )r   ÚgetZ	list_vars)r   ÚinstÚgotr   r   r   r   (   s    z_CacheListVars.getN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r   r   $   s   r   c                 C   sŠ   | si S t | ƒ}t|ƒ}t| ƒ}tƒ }|D ]@}t d|¡ t| |ƒ\} }t dt|ƒ¡ t| |||||ƒ} q*t | ƒ}||kr†t	 
d¡‚| S )z7Run SSA reconstruction on IR blocks of a function.
    zFix SSA violator on var %szReplaced assignments: %szCFG mutated in SSA pass)r
   Ú_iterated_domfrontsÚ_find_defs_violatorsr   Ú_loggerÚdebugÚ_fresh_varsr   Ú_fix_ssa_varsr	   ZCompilerError)r   ÚcfgÚdf_plusÚ	violatorsÚcache_list_varsÚvarnameÚdefmapZcfg_postr   r   r   r   /   s(     ÿÿ
r   c                 C   sx   t | ƒ}||d< ||d< ttƒ |d< }||d< t||ƒ|d< t| |t|ƒƒ}| ¡ D ]\}	}
||	 }|
|j |_qV|S )z=Rewrite all uses to ``varname`` given the definition map
    r&   r'   Úphimapr"   Úphi_locations)Ú_make_statesr   ÚlistÚ_compute_phi_locationsÚ_run_block_rewriteÚ_FixSSAVarsÚitemsÚbody)r   r&   r'   r"   r#   r%   Ústatesr(   Ú	newblocksÚlabelZphilistZcurblkr   r   r   r!   S   s    r!   c                    sn   dd„ |   ¡  ¡ D ƒ‰ d}|rjd}ˆ  ¡ D ]<\}}ttj‡ fdd„|D ƒtƒ ƒ}| |¡r*||O }d}q*qˆ S )z²Compute the iterated dominance frontiers (DF+ in literatures).

    Returns a dictionary which maps block label to the set of labels of its
    iterated dominance frontiers.
    c                 S   s   i | ]\}}|t |ƒ“qS r   )Úset©Ú.0ÚkÚvsr   r   r   Ú
<dictcomp>k   s      z'_iterated_domfronts.<locals>.<dictcomp>TFc                    s   g | ]}ˆ | ‘qS r   r   )r6   Úv©Z	domfrontsr   r   Ú
<listcomp>p   s     z'_iterated_domfronts.<locals>.<listcomp>)Zdominance_frontierr/   r   ÚoperatorÚor_r4   Ú
difference)r"   Z
keep_goingr7   r8   Úinnerr   r;   r   r   e   s    
r   c                 C   s,   t ƒ }| ¡ D ]\}}|r|| | O }q|S r   )r4   r/   )Ziterated_dfr'   r)   ZdeflabelZdefstmtsr   r   r   r,   w   s
    r,   c                 C   s6   t | ƒ}||d< ttƒ |d< }t| |tƒ ƒ}||fS )z(Rewrite to put fresh variable names
    r&   r'   )r*   r   r+   r-   Ú_FreshVarHandler)r   r&   r1   r'   r2   r   r   r   r    ‚   s
    r    c                 C   s   |   ¡ ^}}|jS r   )ÚvaluesÚscope)r   ÚfirstÚ_r   r   r   Ú
_get_scopeŒ   s    rF   c                 C   sL   t tƒ}t| |tƒ ƒ t dt|ƒ¡ dd„ | ¡ D ƒ}t dt|ƒ¡ |S )zm
    Returns
    -------
    res : Set[str]
        The SSA violators in a dictionary of variable names.
    zdefs %sc                 S   s    h | ]\}}t |ƒd kr|’qS )é   )Úlenr5   r   r   r   Ú	<setcomp>›   s      z'_find_defs_violators.<locals>.<setcomp>zSSA violators %s)r   r+   Ú_run_block_analysisÚ_GatherDefsHandlerr   r   r   r/   )r   Údefsr$   r   r   r   r   ‘   s    r   c                 C   s4   |   ¡ D ]&\}}t d|¡ t|||ƒD ]}q(qd S )Nz"==== SSA block analysis pass on %s)r/   r   r   Ú_run_ssa_block_pass)r   r1   Úhandlerr3   ÚblkrE   r   r   r   rJ       s    rJ   c           	      C   s‚   i }|   ¡ D ]p\}}t d|¡ tj|j|jd�}g }||d< ||d< t|||ƒD ]}|d k	sbt‚| 	|¡ qR||_
|||< q|S )Nz!==== SSA block rewrite pass on %s)rC   Úlocr3   Úblock)r/   r   r   r   ZBlockrC   rP   rM   ÚAssertionErrorÚappendr0   )	r   r1   rN   r2   r3   rO   ZnewblkZnewbodyÚstmtr   r   r   r-   §   s    
r-   c                 C   s   t t| ƒd�S )N)rC   )ÚdictrF   )r   r   r   r   r*   ¸   s    ÿr*   c                 c   sp   t  d|¡ |jD ]X}t  d|¡ t|tjƒr<| | |¡}n| | |¡}||k	rd|d k	rdt  d|¡ |V  qd S )Nz
Running %szon stmt: %szreplaced with: %s)r   r   r0   Ú
isinstancer   ÚAssignÚ	on_assignÚon_other)r1   rO   rN   rT   Úretr   r   r   rM   ¾   s    
rM   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )Ú_BaseHandlerzGA base handler for all the passes used here for the SSA algorithm.
    c                 C   s   dS )a’  
        Called when the pass sees an ``ir.Assign``.

        Subclasses should override this for custom behavior

        Parameters
        -----------
        states : dict
        assign : numba.ir.Assign

        Returns
        -------
        stmt : numba.ir.Assign or None
            For rewrite passes, the return value is used as the replacement
            for the given statement.
        Nr   ©r   r1   Úassignr   r   r   rX   Î   s    z_BaseHandler.on_assignc                 C   s   dS )a¥  
        Called when the pass sees an ``ir.Stmt`` that's not an assignment.

        Subclasses should override this for custom behavior

        Parameters
        -----------
        states : dict
        assign : numba.ir.Stmt

        Returns
        -------
        stmt : numba.ir.Stmt or None
            For rewrite passes, the return value is used as the replacement
            for the given statement.
        Nr   ©r   r1   rT   r   r   r   rY   à   s    z_BaseHandler.on_otherN©r   r   r   Ú__doc__rX   rY   r   r   r   r   r[   Ë   s   r[   c                   @   s   e Zd ZdZdd„ ZdS )rK   zEFind all defs

    ``states`` is a Mapping[str, List[ir.Assign]]
    c                 C   s   ||j j  |¡ d S r   )ÚtargetÚnamerS   r\   r   r   r   rX   ø   s    z_GatherDefsHandler.on_assignN)r   r   r   r`   rX   r   r   r   r   rK   ó   s   rK   c                   @   s   e Zd Zdd„ ZejZdS )ÚUndefinedVariablec                 C   s   t dƒ‚d S )NzNot intended for instantiation)ÚNotImplementedErrorr   r   r   r   r   ý   s    zUndefinedVariable.__init__N)r   r   r   r   r   Ú	UNDEFINEDra   r   r   r   r   rc   ü   s   rc   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )rA   z9Replaces assignment target with new fresh variables.
    c                 C   s®   |j j|d krª|d }|d }t|ƒdkrp|j }t d|¡ |j|jkr„d|j›d�}t tj	||j
d�¡ n|j|j j|j
d�}tj||j|j
d	�}||d
   |¡ |S )Nr&   rC   r'   r   zfirst assign: %sz	variable z is not in scope.©rP   ©ra   ÚvaluerP   r3   )ra   rb   rH   r   r   Z	localvarsÚwarningsÚwarnr	   ZNumbaIRAssumptionWarningrP   Úredefiner   rW   rh   rS   )r   r1   r]   rC   r'   Z	newtargetZwmsgr   r   r   rX     s&    
ÿ
ýz_FreshVarHandler.on_assignc                 C   s   |S r   r   r^   r   r   r   rY     s    z_FreshVarHandler.on_otherNr_   r   r   r   r   rA     s   rA   c                   @   sR   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d„ZdS )r.   aF  Replace variable uses in IR nodes to the correct reaching variable
    and introduce Phi nodes if necessary. This class contains the core of
    the SSA reconstruction algorithm.

    See Ch 5 of the Inria SSA book for reference. The method names used here
    are similar to the names used in the pseudocode in the book.
    c                 C   s
   || _ d S r   )Ú_cache_list_vars)r   r%   r   r   r   r   )  s    z_FixSSAVars.__init__c                 C   sà   |j }t|tjƒr†|  ||| j |j ¡¡}|d k	rÜ|jtjk	rÜ|d |jj	krÜ|d |ji}t
|ƒ}t ||¡ tj|j||jd�S nVt|tjƒrÜ|  |||g¡}|d k	rÜ|jtjk	rÜ|d |jj	krÜtj|j|j|jd�S |S )Nr&   rg   )rh   rV   r   ZInstÚ_fix_varrl   r   ra   re   rb   r   r   Zreplace_vars_innerrW   rP   ZVar)r   r1   r]   ÚrhsÚnewdefÚreplmapr   r   r   rX   ,  s6      ÿýýz_FixSSAVars.on_assignc                 C   s`   |   ||| j |¡¡}|d k	r\|jtjk	r\|d |jjkr\|d |ji}t|ƒ}t 	||¡ |S )Nr&   )
rm   rl   r   ra   r   re   rb   r   r   Zreplace_vars_stmt)r   r1   rT   ro   rp   r   r   r   rY   K  s      
ÿz_FixSSAVars.on_otherc                 C   s.   dd„ |D ƒ}|d }||kr*|   ||¡S dS )z0Fix all variable uses in ``used_vars``.
        c                 S   s   g | ]
}|j ‘qS r   )rb   )r6   r7   r   r   r   r<   Y  s     z(_FixSSAVars._fix_var.<locals>.<listcomp>r&   N)Ú	_find_def)r   r1   rT   Z	used_varsÚvarnamesZphivarr   r   r   rm   V  s    z_FixSSAVars._fix_varc                 C   s¬   t  d|d |¡ d}|d }|d | }|d | }|d }|  ||¡}t|ƒD ]:}	| j|	||d�}
|
|k rx|	} qŽqR|	|krR|d	 } qŽqR|dkr¨| j|||jd
�}|S )z?Find definition of ``stmt`` for the statement ``stmt``
        zfind_def var=%r stmt=%sr&   Nr3   r'   r(   rQ   )Ústopéÿÿÿÿrf   )r   r   Ú_stmt_indexÚreversedÚ_find_def_from_toprP   )r   r1   rT   Zselected_defr3   Z
local_defsZ
local_phisrQ   Zcur_posÚdefstmtZdef_posr   r   r   rq   ^  s,      ÿz_FixSSAVars._find_defc                 C   s:  t  d|¡ |d }|d }|d }|d }||krð|d }|d j}|j|d |d	�}	tj|	tjj|d	�|d
�}
t  d|
|¡ ||  d|
¡ ||  	|
¡ | 
|¡D ]B\}}| j|||d	�}t  d|¡ |
jj 	|j¡ |
jj 	|¡ q¨|
S | ¡ | }||k�rt|d |ƒ tS t  d||¡ | j|||d	�S dS )z—Find definition reaching block of ``label``.

        This method would look at all dominance frontiers.
        Insert phi node if necessary.
        zfind_def_from_top label %rr"   r'   r(   r)   rC   rQ   r&   rf   rg   zinsert phi node %s at %sr   zincoming_def %szidom %s from label %sN)r   r   rP   rk   r   rW   ÚExprÚphiÚinsertrS   ZpredecessorsÚ_find_def_from_bottomrh   Zincoming_valuesra   Zincoming_blocksZimmediate_dominatorsÚ"_warn_about_uninitialized_variablerc   )r   r1   r3   rP   r"   r'   r(   r)   rC   ZfreshvarZphinodeÚpredrE   Zincoming_defZidomr   r   r   rw   z  sB    
ý  ÿ
z_FixSSAVars._find_def_from_topc                 C   s@   t  d|¡ |d }|| }|r,|d }|S | j|||d�S dS )z<Find definition from within the block at ``label``.
        zfind_def_from_bottom label %rr'   rt   rf   N)r   r   rw   )r   r1   r3   rP   r'   rL   Zlastdefr   r   r   r|   ¨  s    z!_FixSSAVars._find_def_from_bottomrt   c                 C   s<   t t|jƒƒd|… D ]}|j| |kr|  S qt|jƒS )z‘Find the positional index of the statement at ``block``.

        Assumptions:
        - no two statements can point to the same object.
        N)ÚrangerH   r0   )r   rx   rQ   rs   Úir   r   r   ru   ´  s    	
z_FixSSAVars._stmt_indexN)rt   )r   r   r   r`   r   rX   rY   rm   rq   rw   r|   ru   r   r   r   r   r.      s   .r.   c                 C   s$   t jr t tjd| › �|d�¡ d S )Nz Detected uninitialized variable rf   )r   ZALWAYS_WARN_UNINIT_VARri   rj   r	   ZNumbaWarning)r&   rP   r   r   r   r}   Ã  s    þÿr}   ))r`   Úloggingr=   ri   Ú	functoolsr   r   Úpprintr   Úcollectionsr   Znumbar   Z
numba.corer   r   r	   Znumba.core.analysisr
   Ú	getLoggerr   r   r   r   r   r!   r   r,   r    rF   r   rJ   r-   r*   rM   r[   rK   rc   rA   r.   r}   r   r   r   r   Ú<module>   s>   	

$
(	 $