o
    h                     @   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def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   L/var/www/html/ai/venv/lib/python3.10/site-packages/torch/_inductor/bounds.py
<dictcomp>   s    z&BoundVars.__init__.<locals>.<dictcomp>c                 s   s0    | ]}|j d dtjfv sd|j v r|V  qdS )load	reductionmasked_subblockN)targetoperatorgetitemr   noder   r   r   	<genexpr>   s    
z%BoundVars.__init__.<locals>.<genexpr>)r   
var_rangesitemsreplacement_valsr   	get_nodesunbounded_vars_bounds)selfr   r   r   r   __init__   s   

zBoundVars.__init__c                 C   s   |  | jj}| jD ]}t|jtrd|jvr#d|jvr#t | j	|< q
t
t  t| jjj|}|jt
 | j	d W d    | j	S 1 sIw   Y  | j	S )Nr   set_indirectinitial_env)swap_submodulesr   
submodulesr$   
isinstancer   strr   unknownr%   r   set_ops_handlerr   r
   
root_blockgraphrunget_ops_handler)r&   r,   r   interpreterr   r   r   
get_bounds'   s   



zBoundVars.get_boundsc                    s   i  |  D ]A}|dkrj |< qd|v r'jj|  fdd |< qd|v s-J 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(   )	keysr7   r   	subblocksintlenindirect_varsr   r(   )r&   r,   keyidxvarindirectr   r;   r   r+   9   s   
zBoundVars.swap_submodulesc                 C   sN   t |j|}|jt |d dd |jjD }t|dks J |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
   r2   r3   r   r4   nodesrB   env)r&   r=   rK   r9   r:   r,   interprH   r   r   r   r   N   s
   zBoundVars.masked_subblockc                 C   s   t |tsJ || j|< |S r8   )r-   r   r"   )r&   oldnewr   r   r   r(   W   s   
zBoundVars.set_indirectc                 C   s:   | j j| }| j|}|d u rt|| j}|| j|< |S r8   )r   indexing_exprsr"   getr   )r&   nameexprboundr   r   r   r7   \   s   
zBoundVars.get_indexN)__name__
__module____qualname____doc__r   r'   r   r6   r+   r   r(   r7   r   r   r   r   r      s    	
	r   )r   	functoolsr   typingr   r   torch%torch.fx.experimental.symbolic_shapesr   torch.utils._sympy.value_rangesr   r   r   irr
   r   utilsr   r   virtualizedr   r   r   r   r   r   <module>   s    