U
    |e:                     @   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)func_ir r   K/var/www/website-v5/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   get	list_vars)r   instZ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rt	
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	   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 )zCompute 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   )r8   vZ	domfrontsr   r   
<listcomp>p   s     z'_iterated_domfronts.<locals>.<listcomp>)dominance_frontierr1   r   operatoror_r6   
difference)r$   Z
keep_goingr9   r:   innerr   r=   r   r   e   s    
r   c                 C   s,   t  }| D ]\}}|r|| | O }q|S r   )r6   r1   )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(   r3   r)   r4   r   r   r   r!      s
    r!   c                 C   s   |   ^}}|jS r   )valuesscope)r   first_r   r   r   
_get_scope   s    rI   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 )   )lenr7   r   r   r   	<setcomp>   s      z'_find_defs_violators.<locals>.<setcomp>zSSA violators %s)r   r-   _run_block_analysis_GatherDefsHandlerr   r    r   r1   )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)r1   r   r    _run_ssa_block_pass)r   r3   handlerr5   blkrH   r   r   r   rM      s    rM   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)rF   locr5   block)r1   r   r    r   BlockrF   rS   rP   AssertionErrorappendr2   )	r   r3   rQ   r4   r5   rR   newblkZnewbodystmtr   r   r   r/      s    
r/   c                 C   s   t t| dS )N)rF   )dictrI   )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    r2   
isinstancer   Assign	on_assignon_other)r3   rR   rQ   rY   retr   r   r   rP      s    
rP   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   r3   assignr   r   r   r]      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   r3   rY   r   r   r   r^      s    z_BaseHandler.on_otherNr   r   r   __doc__r]   r^   r   r   r   r   r`      s   r`   c                   @   s   e Zd ZdZdd ZdS )rN   zEFind all defs

    ``states`` is a Mapping[str, List[ir.Assign]]
    c                 C   s   ||j j | d S r   )targetnamerW   ra   r   r   r   r]      s    z_GatherDefsHandler.on_assignN)r   r   r   re   r]   r   r   r   r   rN      s   rN   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   	UNDEFINEDrf   r   r   r   r   rh      s   rh   c                   @   s    e Zd ZdZdd Zdd ZdS )rD   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rd|jd}ttj	||j
d n|j|j j|j
d}tj||j|j
d	}||d
  | |S )Nr(   rF   r)   r   zfirst assign: %sz	variable z is not in scope.rS   rf   valuerS   r5   )rf   rg   rK   r   r    	localvarswarningswarnr	   NumbaIRAssumptionWarningrS   redefiner   r\   rm   rW   )r   r3   rb   rF   r)   Z	newtargetZwmsgr   r   r   r]     s&    

z_FreshVarHandler.on_assignc                 C   s   |S r   r   rc   r   r   r   r^     s    z_FreshVarHandler.on_otherNrd   r   r   r   r   rD     s   rD   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 )r0   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rtj|j|j|jdS |S )Nr(   rl   )rm   r[   r   Inst_fix_varrs   r   rf   rj   rg   r   r   replace_vars_innerr\   rS   Var)r   r3   rb   rhsnewdefreplmapr   r   r   r]   ,  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(   )
ru   rs   r   rf   r   rj   rg   r   r   replace_vars_stmt)r   r3   rY   ry   rz   r   r   r   r^   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   )rg   )r8   r9   r   r   r   r>   Y  s     z(_FixSSAVars._fix_var.<locals>.<listcomp>r(   N)	_find_def)r   r3   rY   	used_varsvarnamesZphivarr   r   r   ru   V  s    z_FixSSAVars._fix_varc                 C   s   t d|d | d}|d }|d | }|d | }|d }| ||}t|D ]:}	| j|	||d}
|
|k rx|	} qqR|	|krR|d	 } qqR|dkr| j|||jd
}|S )z?Find definition of ``stmt`` for the statement ``stmt``
        zfind_def var=%r stmt=%sr(   Nr5   r)   r*   rT   )stoprk   )r   r    _stmt_indexreversed_find_def_from_toprS   )r   r3   rY   Zselected_defr5   Z
local_defsZ
local_phisrT   Zcur_posdefstmtZdef_posr   r   r   r|   ^  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 )zFind 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+   rF   rT   r(   rk   rl   zinsert phi node %s at %sr   zincoming_def %szidom %s from label %sN)r   r    rS   rr   r   r\   ExprphiinsertrW   predecessors_find_def_from_bottomrm   incoming_valuesrf   incoming_blocksimmediate_dominators"_warn_about_uninitialized_variablerh   )r   r3   r5   rS   r$   r)   r*   r+   rF   ZfreshvarZphinodepredrH   Zincoming_defidomr   r   r   r   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)   r   rk   N)r   r    r   )r   r3   r5   rS   r)   rO   Zlastdefr   r   r   r     s    z!_FixSSAVars._find_def_from_bottomr   c                 C   s<   t t|jd| D ]}|j| |kr|  S qt|jS )zFind the positional index of the statement at ``block``.

        Assumptions:
        - no two statements can point to the same object.
        N)rangerK   r2   )r   r   rT   r   ir   r   r   r     s    	
z_FixSSAVars._stmt_indexN)r   )r   r   r   re   r   r]   r^   ru   r|   r   r   r   r   r   r   r   r0      s   .r0   c                 C   s$   t jr ttjd|  |d d S )Nz Detected uninitialized variable rk   )r   ALWAYS_WARN_UNINIT_VARro   rp   r	   NumbaWarning)r(   rS   r   r   r   r     s    r   ))re   loggingr@   ro   	functoolsr   r   pprintr   collectionsr   numbar   
numba.corer   r   r	   numba.core.analysisr
   	getLoggerr   r   r   r   r   r"   r   r.   r!   rI   r   rM   r/   r,   rP   r`   rN   rh   rD   r0   r   r   r   r   r   <module>   s>   	

$
(	 $