U
    ªÊ¹j  ã                   @   sŠ   d dl Z d dlmZ d dlmZmZ d dlZd dlmZ d dl	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 G d
d„ dƒZdS )é    N)Úpartial)ÚDictÚOptional)Úfree_symbols)Úbound_sympyÚValueRangeAnalysisÚValueRangesé   )ÚInterpreterShimÚLoopBody)Úcache_on_selfÚdominated_nodes)ÚVc                   @   sJ   e Zd ZdZedœdd„Zedd„ ƒZdd„ Zd	d
„ Z	dd„ Z
dd„ ZdS )Ú	BoundVarsa¢  
    Performs Value Range Analysis on LoopBody's fx graph by calling BoundVars.run()
    It exposes the ranges of the nodes in the `bounds` variable

    Note. A current limitation of this analysis is that it just works on a per-loop basis.
    We should be able to propagate the bounds between across the whole graph. This may benefit
    the case a bounded variable is returned by a kernel and fed into another.
    )Ú	loop_bodyc                 C   s@   || _ dd„ |j ¡ D ƒ| _tdd„ | j  ¡ D ƒƒ| _i | _d S )Nc                 S   s0   i | ](\}}|t |ƒs$td |d ƒnt|ƒ“qS )r   r	   )r   r   r   )Ú.0ÚkÚv© r   úU/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/_inductor/bounds.pyÚ
<dictcomp>   s   ÿ z&BoundVars.__init__.<locals>.<dictcomp>c                 s   s.   | ]&}|j d dtjfks"d|j kr|V  qdS )ÚloadZ	reductionÚmasked_subblockN)ÚtargetÚoperatorÚgetitem©r   Únoder   r   r   Ú	<genexpr>   s   
ýz%BoundVars.__init__.<locals>.<genexpr>)r   Z
var_rangesÚitemsÚreplacement_valsr   Z	get_nodesÚunbounded_varsÚ_bounds)Úselfr   r   r   r   Ú__init__   s    þþ
zBoundVars.__init__c              	   C   sŠ   |   | jj¡}| jD ]2}t|jtƒr8d|jkrd|jkrt ¡ | j	|< qt
 tƒ ¡�* t| jjj|ƒ}|jt
 ¡ | j	d� W 5 Q R X | j	S )Nr   Úset_indirect©Zinitial_env)Úswap_submodulesr   Ú
submodulesr!   Ú
isinstancer   Ústrr   Úunknownr"   r   Zset_ops_handlerr   r
   Z
root_blockÚgraphÚrunÚget_ops_handler)r#   r(   r   Úinterpreterr   r   r   Ú
get_bounds'   s    
ÿþzBoundVars.get_boundsc                    s”   i ‰ |  ¡ D ]‚}|dkr$ˆjˆ |< qd|krNˆjj| ‰‡ ‡‡fdd„ˆ |< qd|ksZt‚t|tdƒd … ƒ}ˆjj| }tˆj	|ƒ}|ˆ |< qˆ S )NÚ	get_indexr   c                    s   ˆ  ˆˆj| |ˆ ¡S ©N)r   r"   )ÚmaskÚvalue©Úresultr#   Úsubblockr   r   Ú<lambda>B   s       ÿz+BoundVars.swap_submodules.<locals>.<lambda>r%   )
Úkeysr1   r   Z	subblocksÚAssertionErrorÚintÚlenZindirect_varsr   r%   )r#   r(   ÚkeyÚidxÚvarZindirectr   r5   r   r'   9   s    
zBoundVars.swap_submodulesc                 C   sN   t |j|ƒ}|jt ¡ |d� dd„ |jjD ƒ}t|ƒdks@t‚|j|d  S )Nr&   c                 S   s   g | ]}|j d kr|‘qS )Úoutput)r   r   r   r   r   Ú
<listcomp>Q   s     
 z-BoundVars.masked_subblock.<locals>.<listcomp>r	   r   )	r
   r,   r-   r   r.   Znodesr<   r:   Úenv)r#   r7   rB   r3   r4   r(   Úinterpr@   r   r   r   r   N   s
    zBoundVars.masked_subblockc                 C   s   t |tƒst‚|| j|< |S r2   )r)   r   r:   r    )r#   ÚoldÚnewr   r   r   r%   W   s    
zBoundVars.set_indirectc                 C   s:   | j j| }| j |¡}|d kr,t|| jƒ}|| j|< |S r2   )r   Zindexing_exprsr    Úgetr   )r#   ÚnameÚexprÚboundr   r   r   r1   \   s    
zBoundVars.get_indexN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r$   r   r0   r'   r   r%   r1   r   r   r   r   r      s   	
	r   )r   Ú	functoolsr   Útypingr   r   ZtorchZ%torch.fx.experimental.symbolic_shapesr   Ztorch.utils._sympy.value_rangesr   r   r   Zirr
   r   Úutilsr   r   Zvirtualizedr   r   r   r   r   r   Ú<module>   s   