o
    8ήc:                     @   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   5/tmp/pip-target-vg8gfxp4/lib/python/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__%      
z_CacheListVars.__init__c                 C   s*   | j |}|d u r|  | j |< }|S r   )r   get	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rCt	
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defmapcfg_postr   r   r   r   /   s&   
r   c                 C   sx   t | }||d< ||d< tt |d< }||d< t|||d< t| |t|}| D ]\}	}
||	 }|
|j |_q+|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labelphilistcurblkr   r   r   r$   S   s   r$   c                    sp   dd |    D  d}|r6d}  D ]\}}ttj fdd|D t }||r3||O }d}q|s 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   )r=   v	domfrontsr   r   
<listcomp>p   s    z'_iterated_domfronts.<locals>.<listcomp>)dominance_frontierr4   r   operatoror_r;   
difference)r&   
keep_goingr>   r?   innerr   rB   r   r   e   s   
r   c                 C   s,   t  }| D ]\}}|r|| | O }q|S r   )r;   r4   )iterated_dfr+   r.   deflabeldefstmtsr   r   r   r1   w   s   r1   c                 C   s6   t | }||d< tt |d< }t| |t }||fS )z(Rewrite to put fresh variable names
    r*   r+   )r/   r   r0   r2   _FreshVarHandler)r   r*   r6   r+   r7   r   r   r   r#      s
   r#   c                 C   s   |   ^}}|jS r   )valuesscope)r   first_r   r   r   
_get_scope   s   rS   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 )   )lenr<   r   r   r   	<setcomp>   s     z'_find_defs_violators.<locals>.<setcomp>zSSA violators %s)r   r0   _run_block_analysis_GatherDefsHandlerr!   r"   r   r4   )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)r4   r!   r"   _run_ssa_block_pass)r   r6   handlerr8   blkrR   r   r   r   rW      s   rW   c           	      C   s   i }|   D ]8\}}td| tj|j|jd}g }||d< ||d< t|||D ]}|d us1J || q)||_	|||< q|S )Nz!==== SSA block rewrite pass on %s)rP   locr8   block)
r4   r!   r"   r   BlockrP   r]   rZ   appendr5   )	r   r6   r[   r7   r8   r\   newblknewbodystmtr   r   r   r2      s   
r2   c                 C   s   t t| dS )N)rP   )dictrS   )r   r   r   r   r/      s   r/   c                 c   sr    t d| |jD ],}t d| t|tjr|| |}n|| |}||ur3|d ur3t d| |V  q
d S )Nz
Running %szon stmt: %szreplaced with: %s)r!   r"   r5   
isinstancer   Assign	on_assignon_other)r6   r\   r[   rc   retr   r   r   rZ      s   
rZ   c                   @       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      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   r6   assignr   r   r   rg          z_BaseHandler.on_assignc                 C   rl   )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   r6   rc   r   r   r   rh      ro   z_BaseHandler.on_otherNr   r   r   __doc__rg   rh   r   r   r   r   rk      s    rk   c                   @   s   e Zd ZdZdd ZdS )rX   zEFind all defs

    ``states`` is a Mapping[str, List[ir.Assign]]
    c                 C   s   ||j j | d S r   )targetnamer`   rm   r   r   r   rg      s   z_GatherDefsHandler.on_assignN)r   r   r   rr   rg   r   r   r   r   rX      s    rX   c                   @   s   e Zd Zdd ZejZdS )UndefinedVariablec                 C   s   t d)NzNot intended for instantiation)NotImplementedErrorr   r   r   r   r      s   zUndefinedVariable.__init__N)r   r   r   r   r   	UNDEFINEDrs   r   r   r   r   ru      s    
ru   c                   @   rj   )rN   z9Replaces assignment target with new fresh variables.
    c                 C   s   |j j|d krU|d }|d }t|dkr8|j }td| |j|jvr7d|jd}ttj	||j
d n
|j|j j|j
d}tj||j|j
d	}||d
  | |S )Nr*   rP   r+   r   zfirst assign: %sz	variable z is not in scope.r]   rs   valuer]   r8   )rs   rt   rU   r!   r"   	localvarswarningswarnr	   NumbaIRAssumptionWarningr]   redefiner   rf   rz   r`   )r   r6   rn   rP   r+   	newtargetwmsgr   r   r   rg     s(   
z_FreshVarHandler.on_assignc                 C   s   |S r   r   rp   r   r   r   rh     s   z_FreshVarHandler.on_otherNrq   r   r   r   r   rN     s    rN   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 )r3   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   )  r   z_FixSSAVars.__init__c                 C   s   |j }t|tjrD| ||| j|j }|d urB|jtjurB|d |jj	krB|d |ji}t
|}t|| tj|j||jdS |S t|tjro| |||g}|d uro|jtjuro|d |jj	krotj|j|j|jdS |S )Nr*   ry   )rz   re   r   Inst_fix_varr   r   rs   rw   rt   r   r   replace_vars_innerrf   r]   Var)r   r6   rn   rhsnewdefreplmapr   r   r   rg   ,  s4   z_FixSSAVars.on_assignc                 C   s`   |  ||| j|}|d ur.|jtjur.|d |jjkr.|d |ji}t|}t	|| |S )Nr*   )
r   r   r   rs   r   rw   rt   r   r   replace_vars_stmt)r   r6   rc   r   r   r   r   r   rh   K  s   z_FixSSAVars.on_otherc                 C   s.   dd |D }|d }||v r|  ||S dS )z0Fix all variable uses in ``used_vars``.
        c                 S   s   g | ]}|j qS r   )rt   )r=   r>   r   r   r   rD   Y  s    z(_FixSSAVars._fix_var.<locals>.<listcomp>r*   N)	_find_def)r   r6   rc   	used_varsvarnamesphivarr   r   r   r   V  s
   z_FixSSAVars._fix_varc                 C   s   t d|d | d}|d }|d | }|d | }|d }| ||}t|D ]}	| j|	||d}
|
|k r;|	} n|	|v rE|d	 } nq)|du rS| j|||jd
}|S )z?Find definition of ``stmt`` for the statement ``stmt``
        zfind_def var=%r stmt=%sr*   Nr8   r+   r-   r^   )stoprx   )r!   r"   _stmt_indexreversed_find_def_from_topr]   )r   r6   rc   selected_defr8   
local_defs
local_phisr^   cur_posdefstmtdef_posr   r   r   r   ^  s*   z_FixSSAVars._find_defc                 C   s4  t d| |d }|d }|d }|d }||v rx|d }|d j}|j|d |d	}	tj|	tjj|d	|d
}
t d|
| || d|
 || 	|
 |
|D ]!\}}| j|||d	}t d| |
jj	|j |
jj	| qT|
S | | }||krt|d | tS t d|| | j|||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.   rP   r^   r*   rx   ry   zinsert phi node %s at %sr   zincoming_def %szidom %s from label %s)r!   r"   r]   r   r   rf   Exprphiinsertr`   predecessors_find_def_from_bottomrz   incoming_valuesrs   incoming_blocksimmediate_dominators"_warn_about_uninitialized_variableru   )r   r6   r8   r]   r&   r+   r-   r.   rP   freshvarphinodepredrR   incoming_defidomr   r   r   r   z  s>   
z_FixSSAVars._find_def_from_topc                 C   s<   t d| |d }|| }|r|d }|S | j|||dS )z<Find definition from within the block at ``label``.
        zfind_def_from_bottom label %rr+   r   rx   )r!   r"   r   )r   r6   r8   r]   r+   rY   lastdefr   r   r   r     s   z!_FixSSAVars._find_def_from_bottomr   c                 C   s<   t t|jd| D ]}|j| |u 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)rangerU   r5   )r   r   r^   r   ir   r   r   r     s
   	
z_FixSSAVars._stmt_indexN)r   )r   r   r   rr   r   rg   rh   r   r   r   r   r   r   r   r   r   r3      s    .r3   c                 C   s(   t jrttjd|  |d d S d S )Nz Detected uninitialized variable rx   )r   ALWAYS_WARN_UNINIT_VARr|   r}   r	   NumbaWarning)r*   r]   r   r   r   r     s   r   ))rr   loggingrF   r|   	functoolsr   r   pprintr   collectionsr   numbar   
numba.corer   r   r	   numba.core.analysisr
   	getLoggerr   r!   r   r   r   r$   r   r1   r#   rS   r    rW   r2   r/   rZ   rk   rX   ru   rN   r3   r   r   r   r   r   <module>   s@    	

$
(	 $