o
    Zh,q                     @   s>  d dl Z d dlZd dlZd dlZd dlmZmZmZ er'd dlZd dl	m
Z
 neZ
d dlZd dlm  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 d d	lmZ d d
lmZ dgZeeZ ej!"edZ#dej$dee% fddZ&dej$ded fddZ'edd	ddede
de%de(ddf
ddZ)dS )    N)AnyOptionalTYPE_CHECKING)ShapeEnv)fx)is_sparse_any)compatibility)lazy_format_graph_code)py_sym_types)SymNode)GraphModuleinsert_deferred_runtime_assertsZ
graph_codenodereturnc                 C   s,   d| j v r
| j d S d| j v r| j d S dS )zx
    Get the example value key for a node, since dynamo uses "example_value"
    while non-strict export uses "val.
    example_valuevalN)metar    r   M/var/www/auris/lib/python3.10/site-packages/torch/fx/passes/runtime_assert.py_get_example_value"   s
   



r   
sympy.Exprc                 C   s   t | }t|tr|jjS d S N)r   
isinstancer
   r   exprr   r   r   r   r   _get_sym_val/   s   
r   T)Zis_backward_compatibleFgm	shape_envnameexportc           #         s  ddl ddlm ddlmmmmmm	m
m} ddlm ddlm}m} ddlm} |j jtjtdtd	| d
d i t }d}	jD ]jdkrc}	 n| qXdtj dt!ffdd}
djD ]dj"v rd ndj"v r nq{		d9dt#jj dt$t% dt$t&t%t'f  ddffddt 
t |r|n|  	fdd	dddt!ffdd	
fdd}t(j}t)|dd D ]\*|vr|d   n|	 |v rft+ }durffd!d"}||fd#d$ t,| }t#j-rft)|. D ]\}||fd%d$ q-t/|sft)|0 D ]\}||fd&d$ qI||1 fd'd$ |	krs|2dg  j3t#j4t#j5j6j7j8fv rj9d d
kst:j9d  }v s|dur|rj9d }j; t,|tj r|j<sj;| n
| jdkrct: durcfd(d)}||j"=d*i dusJ fd+d,}v s|
rI| sI| sI|
r0t>j?j"=dj"=dd- 	< W d   n	1 s+w   Y   j@}A| j; tBd.| nvrct,jCjDjEjFfsctjGd/< j3t#j5j6jHj8t#j5j6jIj8fv ryj; g }||j"=d* }r|J D ]F\}}|K| fd0d1|vrЈ tjG|d/|< W d   n	1 sw   Y  tBd2||  q|D ]}2|g }|v rq||jLv r|rMt#j5j6jIj8| j@f nMt#jN| j@f |jO| }|jPr|jQtRjSd  kr||jT}|U V|sfd3d4}| j@j3krt>j?j"=dj"=dd-d ||jT }durw	||kj@}Mt#j5j6j7j8|d5||k d6| d7f 
||k ||jQ }dur	||kj@} Mt#j5j6j7j8| d5||k d6|  d7f 
||k W d   n	1 sw   Y  | || qW d   n	1 sw   Y  qJ D ]%\}!}"t,|!jWr|"j@jdkr|"j@j<stBd8|! j;|"j@ qdS ):a  
    During tracing, we may have discovered that some data-dependent values
    had runtime assert on them; e.g., torch.empty(x.item()) induces a runtime
    that x.item() >= 0.  This asserts can happen unpredictably during fake
    tensor propagation, so we cannot conveniently insert them into the FX graph
    when they occur.  Instead, we accumulate them in the ShapeEnv, and in this
    pass insert them into the graph as proper tests.

    This pass also deduplicates size-related computation, CSE-ing ops that produce
    symbolic values and/or are involved in runtime asserts. Additionally, shape calls
    (size/stride/storage_offset) are turned into compute on input sizes if possible,
    allowing intermediate tensors to be freed earlier. For example, here dynamo will
    DCE the cat and repeat calls:

        z = torch.cat([x, x], dim=0)  # 2*s0
        w = z.repeat(y.shape[0])  # 2*s0*s1
        _w = w.shape[0]
        # something with _w, but not w ...

        # turns into ->
        _w0 = 2 * s0
        _w = _w0 * s1

        # where s0, s1 are either SymInt graph inputs, or the result of added size calls

    Redundant torch._check or torch.ops.aten._assert_scalar.default calls that assert
    the same expression, and redundant constrain_range calls are also deduplicated.
    Additionally, because single-symbol bound checks (e.g. u0 >= 0, u0 <= 5) accumulate
    information in the ShapeEnv, the ShapeEnv contains min/max bounds for each symbol,
    and we delete all previous calls, adding bound checks at the end of this pass.
    r   N)_set_node_metadata_hook)#_has_uninterpretable_sympy_functionCallMethodKey cast_symbool_to_symint_guardlessConvertIntKeyDivideByKeyfree_symbolsInnerTensorKeyresolve_unbacked_bindingsint_oo) OptimizedPythonReferenceAnalysisPythonReferenceAnalysis)ValueRangesz%sz$pre insert_deferred_runtime_asserts T)Zcoloredplaceholderr   r   c                    s<   t |  }duot|j o | otdd | jD S )z
        If a size/stride/storage offset call on an intermediate tensor,
        we can try to compute the value from input shapes instead.
        Nc                 s   s<    | ]}t |tjot t|tjtjfo|jd kV  qdS )r/   N)r   r   Noder   torchTensorSizeop.0argr   r   r   	<genexpr>   s    
z\insert_deferred_runtime_asserts.<locals>._is_intermediate_tensor_sym_call.<locals>.<genexpr>)r   r   Numberanyargsr   )r"   sympyr   r    _is_intermediate_tensor_sym_call   s   zIinsert_deferred_runtime_asserts.<locals>._is_intermediate_tensor_sym_callr   r   stack_tracenn_module_stackc                    s   t dd | j}z'| j}| jdkr(t| jtsJ t|d | j}|dd  }|| | j < W n	 t	y9   Y nw |d urC|| jd< |d urN|| jd< d S d S )Nc                 S   s   t | tjjrt| S | S r   )r   r1   r   r0   r   )r7   r   r   r   <lambda>   s   zNinsert_deferred_runtime_asserts.<locals>._node_metadata_hook.<locals>.<lambda>call_methodr      r>   r?   )
pytreeZtree_mapr;   targetr4   r   strgetattrr   NotImplementedError)r   r>   r?   Z	fake_argsrD   )val_keyr   r   _node_metadata_hook   s&   

z<insert_deferred_runtime_asserts.<locals>._node_metadata_hookc                    s   ddl m}m}m} ddlm} ddlm}m} | v r  | S t	|||||fr/| |S | fdd|j
D | |<  | S )Nr   )Integerr9   Symbol)BooleanAtom)_run_sympy_handlersympy_interpc                    s   g | ]} |qS r   r   r5   )_sympy_interpexpr_to_proxyr   r   
<listcomp>   s    zJinsert_deferred_runtime_asserts.<locals>._sympy_interp.<locals>.<listcomp>)r<   rJ   r9   rK   Zsympy.logic.boolalgrL   Ztorch.utils._sympy.interprM   rN   r   r;   )rP   r   rJ   r9   rK   rL   rM   rN   )AnalysisrO   )rP   r   rO      s   z6insert_deferred_runtime_asserts.<locals>._sympy_interpr   r   c                    s^   t | jdks| j j jfvrdS | j\}}t| jr#t| jp.t| jo.t| jS )N   F)lenr;   funcZLessThanZGreaterThanr   rK   r9   )r   lhsrhs)r<   r   r   _is_bound_expr_for_symbol   s    
zBinsert_deferred_runtime_asserts.<locals>._is_bound_expr_for_symbolc                    s  | D ]~}|j v s%t|j jdkr tt|j jv r |j s% |j r&qtd|j  |j }|  }|rJt|t	d}
|g | q	# |j j}
tjjjj|d|j  d| df W d    n1 suw   Y  |j  qd S )NrB   zinserting runtime assert %skey(Runtime assertion failed for expression 
 on node '')r   rT   r'   nextiterlogdebugkeysminrE   
setdefaultappendr   call_functionr1   opsaten_assert_scalardefaultadd)rasraZfvsmissingi1res)r"   rX   rI   r!   rO   added_assertsconstrained_unbacked_symbolsrP   r'   r   graphras_by_symbolr   r   add_runtime_asserts   s4   


z<insert_deferred_runtime_asserts.<locals>.add_runtime_assertsrB   c                    s   t | tjrDt | jtrFt | jj }jrH|vrJ  tj| d|< W d    n1 s4w   Y  t	
d||  d S d S d S d S d S )Ntracerexpr_to_proxy[%s] = %s)r   r1   ZSymIntr   r   r   rK   r   Proxyr`   ra   )Zsymintcbs)rI   r!   rP   r   r<   rx   r   r   match_symbol!  s   

z5insert_deferred_runtime_asserts.<locals>.match_symbolc                      s    S r   r   r   r   r   r   r@   ,  s    z1insert_deferred_runtime_asserts.<locals>.<lambda>c                           tjjjjfS r   )rf   r1   rg   rh   sym_sizeintr   rs   ir   r   r   r@   1      c                      r~   r   )rf   r1   rg   rh   
sym_strider   r   r   r   r   r@   9  r   c                      s     tjjjjfS r   )rf   r1   rg   rh   Zsym_storage_offsetrj   r   )rs   r   r   r   r@   ?  s    c                     s   j D ]	} |  vr dS qdS NTF)r'   )symbol)rP   sym_exprr   r   has_new_untracked_symbolsf  s
   
zBinsert_deferred_runtime_asserts.<locals>.has_new_untracked_symbolsunbacked_bindingsc                     s      D ]	} |  vr dS qdS r   )rb   rY   )rP   resolved_unbacked_bindingsr   r   has_new_unbacked_bindingsu  s
   zBinsert_deferred_runtime_asserts.<locals>.has_new_unbacked_bindings)r>   r?   zCSE node %s -> %s for expr %srw   c                    s  |dkr| S t |dkrjt|d  rjt|d tjrj|d jdkr8tjjj	j
| |d jf|dd  S |d jdkrUtjjjj
| |d jf|dd  S |d j| |d jf|dd  S t|d  r|d j| f|dd  S t|d tjrtj| |d jf|dd  S t|d r| f|dd  S t|d r̈tj| |d jf|dd  S t|d rt| |d jf|dd  S td| )Nr   rS   r   rB   sizestridezunrecognized keypath )rT   r   rC   ZSequenceKeyr   rf   r1   rg   rh   r   r   idxr   rA   operatorgetitemfloordivZdivisorrF   Z
inner_nameAssertionError)r   keypath)r#   r%   r&   r(   r$   gors   r   r   r     s|   








z+insert_deferred_runtime_asserts.<locals>.gory   c                    s2   |    fv r	d S zt | W S  ty   Y d S w r   )r   	TypeError)r|   r*   r   r   convert?  s   
z0insert_deferred_runtime_asserts.<locals>.convertr[   r\   r]   z%deleting unused reified symbol for %s)NN)Xr<   Z(torch._export.passes._node_metadata_hookr!   %torch.fx.experimental.symbolic_shapesr"   r#   r$   r%   r&   r'   r(   r)   Ztorch.utils._sympy.numbersr+   Ztorch.utils._sympy.referencer,   r-   Ztorch.utils._sympy.value_rangesr.   Zdeferred_runtime_assertscopyrs   r   proxyZGraphAppendingTracergraph_code_logra   r	   setnodesr4   rk   r0   boolr   r1   r   rE   dictr   list	enumerateZinserting_beforer   r   r2   r   r   r   Zstorage_offsetpoprD   _checkrg   rh   ri   rj   r;   r   Z
erase_nodeZusersget	functoolspartialr   Zreplace_all_uses_withr`   r9   ZlogicZboolalgrL   rz   Zsym_constrain_rangeZsym_constrain_range_for_sizeitemsre   Z	size_likerf   Z_check_is_sizeZvar_to_rangeZis_intuppersysmaxsizelowerZ _default_unspecified_value_rangeissubsetrK   )#r   r   r   r    r)   r,   r-   r.   ZplaceholdersZfirst_non_placeholderr=   ru   r   r   r}   tr|   Zassert_exprr7   r   r   Z	hash_nodeZdefsr   r   Zi0rl   Zvrr   Zmin_valgeZmax_valler   r   r   )rR   r#   r%   r&   r(   r"   rX   rI   r!   rO   rq   r$   rr   rP   r'   r   r   rs   r   r+   r   rt   r   r   r<   rx   rH   r   r   6   s  ((






"
*






	










B

(



	




   \
)F)*r   loggingr   r   typingr   r   r   r<   r   r   r1   Ztorch.utils._pytreeutilsZ_pytreerC   r   Ztorch._subclasses.meta_utilsr   Ztorch.fx._compatibilityr   Ztorch.fx._utilsr	   Z"torch.fx.experimental.proxy_tensorr
   Ztorch.fx.experimental.sym_noder   Ztorch.fx.graph_moduler   __all__	getLogger__name__r`   Z_loggingZgetArtifactLoggerr   r0   rE   r   r   r   r   r   r   r   r   <module>   sH   
