U
    zh"                     @   sP  d dl Z d dlmZ d dlmZmZmZmZmZm	Z	m
Z
 d dlZd dlZd dlZd dlmZmZmZmZ d dlmZ d dlmZ ddlmZ e	e
ejjj ed	ef f ejjjee ejjjf e!d
ddZ"G dd dZ#ej$e%dddZ&ejjee% dddZ'dd Z(ejje	e!e	e ee ef f dddZ)ejje!dddZ*dS )    N)defaultdict)AnyCallableDefaultDictDictOptionalTupleType)compute_unbacked_bindingsrebind_unbackedstatically_known_truesym_eq)_pytree)tree_map   )V.)patternnodemodulesreturnc                 C   s   t |jdkrdS t|jd tjjr4t|tjjs8dS |jd jdkrLdS t|jd jtsbdS |jd j|krvdS t	||jd j | d k	rdS |jdkr|jdkrdS |j| d krdS t |jd j
dkrdS dS )Nr   FZcall_modulecall_functionZcall_methodr   T)lenargs
isinstancetorchfxNodeoptargetstrtypeusers)r   r   r    r"   J/var/www/html/venv/lib/python3.8/site-packages/torch/_inductor/fx_utils.pymatches_module_function_pattern   s,     r$   c                   @   s<   e Zd ZdZejjdddZejjdddZ	dd	 Z
d
S )FakeTensorUpdatera:  
    The main idea here is that it's difficult to maintain accurate fake
    tensors (our primary form of metadata) for each node in our graph as we
    transform it.

    The most reliable way to obtain this information is by rerunning
    faketensor propagation. However, in general, faketensor propagation is
    fairly expensive. So, instead we'd like to only rerun faketensor
    propagation on nodes that have changed.

    In order to detect which nodes have changed, we first hash its node,
    target, and argument lists (which are immutable in FX).

    Then, whenever we call incremental_update, we check which FX nodes have a
    new hash, and recompute the faketensor metadata for that node. Then, we
    continue to recursively compute the faketensors for all users until the
    fake tensors stop changing.
    )graphc                 C   s2   t  | _|| _| jjD ]}| j| | qd S N)setprocessed_hashesr&   nodesadd	hash_node)selfr&   r   r"   r"   r#   __init__J   s    zFakeTensorUpdater.__init__r   c                 C   s   ||j t|jt|jfS r'   )r   idr   kwargs)r-   r   r"   r"   r#   r,   Q   s    zFakeTensorUpdater.hash_nodec              
      s^  t  }tt jjD ]} t|  d7  < qdd  fdddd }t  }jjD ]}|jkrt||krq`||sq`t	|\}}}|sq`t
j |j||}W 5 Q R X d|jkrڈ||jd rq`tt
jj|| ||jd< t
jj }	rt|	| }
r|
|jd	<  t|  d7  < |d
d |jD  j| q`d S )Nr   c                 S   s   t t| |S r'   )r   r   newoldr"   r"   r#   is_intlist_same[   s    z=FakeTensorUpdater.incremental_update.<locals>.is_intlist_samec                    sl  t | t |krdS t| ttfrRt| t|kr6dS tfddt| |D S | d krb|d kS t| tjst| tj	tj
tjfstdt |  dj | jjt| jj|jjtjkS | j|jr| j|jkrdS | jtjkr|  | rt|  | ksdS | j|jkr.dS t| t|krDdS  t| dkrht|  krhdS dS )NFc                 3   s   | ]\}} ||V  qd S r'   r"   ).0Znew_iZold_i)is_fake_tensor_samer"   r#   	<genexpr>d   s    zTFakeTensorUpdater.incremental_update.<locals>.is_fake_tensor_same.<locals>.<genexpr>zUnknown type z in Tr   )r    r   listtupler   allzipr   TensorZSymIntZSymBoolZSymFloatAssertionErrorr&   r   	shape_envZ_maybe_evaluate_staticsympyEqexprtrueshapeZlayoutZstridedZstrider   Zstorage_offsetZdeviceget_storager2   Zexisting_storagesr7   r5   r-   r"   r#   r7   ^   sV     
zAFakeTensorUpdater.incremental_update.<locals>.is_fake_tensor_samec                 S   s&   | j dko$t| jtjjp$| jtjkS )Nr   )r   r   r   r   Z_opsZ
OpOverloadoperatorgetitemr/   r"   r"   r#   should_process_node   s    

zAFakeTensorUpdater.incremental_update.<locals>.should_process_nodevalZunbacked_bindingsc                 S   s   g | ]}t |qS r"   )r0   r6   userr"   r"   r#   
<listcomp>   s     z8FakeTensorUpdater.incremental_update.<locals>.<listcomp>)r(   r   intr&   r*   get_node_storager,   r)   r0   get_fake_args_kwargsr   Z	fake_moder   metar   r?   r
   updater!   r+   )r-   	processedr   rI   Z
to_processZis_validr   r1   Znew_fake_tensorr?   Zsymbol_to_pathr"   rF   r#   incremental_updateU   sF    -
 

z$FakeTensorUpdater.incremental_updateN)__name__
__module____qualname____doc__r   r   ZGraphr.   r   r,   rT   r"   r"   r"   r#   r%   6   s   r%   )tr   c                 C   s
   |   jS r'   )Zuntyped_storageZ_cdata)rY   r"   r"   r#   rE      s    rE   r   r   c                 C   sH   d| j krd S t| j d tjs$d S tj| j d s:d S t| j d S NrJ   )rQ   r   r   r=   Z_CZ_has_storagerE   r/   r"   r"   r#   rO      s    
rO   c                 C   s*   t | tjjr&d| jkr| S | jd S | S r[   )r   r   r   r   rQ   )xr"   r"   r#   get_fake   s
    

r]   )r\   r   c                 C   sD   t t| j| jf\}}tdd tj||D r:d||fS d||fS )zZ
    First value returns a boolean if any of the input nodes don't have a faketensor.
    c                 s   s   | ]}t |tjjV  qd S r'   )r   r   r   r   )r6   ar"   r"   r#   r8      s    z'get_fake_args_kwargs.<locals>.<genexpr>FT)r   r]   r   r1   anypytreeZarg_tree_leaves)r\   r   r1   r"   r"   r#   rP      s    

rP   c                    sn   ddl m m tjjtd fdd| r6dS tjjtdfddtfd	d
| jD rjdS dS )zReturns true if a node is always realized when lowered to inductor IR.

    NOTE: This may return some false negatives. e.g. it doesn't
    handle buffers realized heuristically during lowering, or
    buffers realized indirectly through view ops.
    r   )	fallbacksneeds_realized_inputsrZ   c                    s8   | j dkr$| jtjkr$| jd S | j dkp6| j kS )Nr   r   )placeholderoutput)r   r   rG   rH   r   r/   )ra   	is_bufferr"   r#   re      s    z#is_node_realized.<locals>.is_bufferTc                    s   | j dkp| j kS )Nrd   )r   r   r/   )rb   r"   r#   realizes_inputs   s    z)is_node_realized.<locals>.realizes_inputsc                 3   s   | ]} |V  qd S r'   r"   rK   )rf   r"   r#   r8      s     z#is_node_realized.<locals>.<genexpr>F)	Ztorch._inductor.loweringra   rb   r   r   r   boolr_   r!   r/   r"   )ra   re   rb   rf   r#   is_node_realized   s    
rh   )+rG   collectionsr   typingr   r   r   r   r   r   r	   r@   r   Ztorch.fxZ%torch.fx.experimental.symbolic_shapesr
   r   r   r   Ztorch.utilsr   r`   Ztorch.utils._pytreer   Zvirtualizedr   nnr   Moduler   r   r   r   rg   r$   r%   r=   rN   rE   rO   r]   rP   rh   r"   r"   r"   r#   <module>   s*   $ 
*