U
    yhs+                     @   sd  d dl mZmZmZmZmZmZmZmZ d dl	Z	d dl
m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dd	d
gZeeej eej f Zeejef Zeejj Zeejj Zee ZdddhZedddd Zeddeeejj f ejjedddZ!eddejje"dddZ#eddG dd	 d	Z$eddejj%ejj%ddd
Z&dS )    )ListTupleUnionDictAnySetMappingOptionalN)	dataclass)_get_qualified_name)compatibilityget_acc_ops_nameget_node_targetis_node_output_tensorFxNetAccFusionsFinderlegalize_graphcall_modulecall_functionZcall_methodF)Zis_backward_compatiblec                 C   sT   t | tr| S | jr*d| jkr*d| j S | jdd}|r@|nd d| j S d S )Nacc_opsacc_ops.z
torch._opsz	torch.ops .)
isinstancestr
__module____name__replace)kmodule r   N/var/www/html/venv/lib/python3.8/site-packages/torch/fx/passes/tools_common.pyr      s    
)
submodulesnodereturnc                 C   s   |j tks(tddt d|j   |j dkrdt|jtsBt| |j }t|dt|}t	|S |j dkr|j}|j
dk	rd|j
krd	|j S t|S t|jtst|jS dS )
a,  
    Given a `node` returns its target typename.

    For "call_method" node, return node.target which is the name of that method being called.
    This could potential lead to conflict but should be okay because normally it's on a tensor.

    For "call_function" node, return typename of node.target.

    For "call_module" node, return typename of the module that node.target point to.

    If seeing "_VariableFunctionsClass" in the target name string, it will be replaced by
    "torch". e.g. _VariableFunctionsClass.relu would become torch.relu.
    zExpect op types of z, z, but found r   Z_base_class_originr   Nr   r   )opCALLABLE_NODE_OPSAssertionErrorjoinr   targetr   getattrtyper   r   r   r   )r!   r"   ZsubmodZsubmod_typer(   r   r   r    r   !   s$    


)r"   r#   c                 C   s"   | j dd}|dk	o t|tjS )a  Checks if the node output produces a Tensor or not.

    NOTE: This requires to run `ShapeProp` on the containing fx graph before
    calling this function. This is because it works by checking the `type`
    metadata on the node. This metadata is produced by the `ShapeProp`.
    r*   N)metaget
issubclasstorchTensor)r"   type_r   r   r    r   E   s    c                   @   sp   e Zd ZdZejjedddZe	G dd dZ
ddeeef ee d	d
dZeejjef dddZdS )r   z
    Finds groups of connected ACC nodes that pass non-tensor data between each other.
    Such groups are called fusion groups.
    )r   	acc_nodesc                 C   s   || _ t|jj| _|| _d S N)r   listgraphnodesr1   )selfr   r1   r   r   r    __init__W   s    zFxNetAccFusionsFinder.__init__c                   @   s6   e Zd ZU eed< eed< eed< eed< dd ZdS )!FxNetAccFusionsFinder.FusionGrouptop_node_idxr5   inputsnodes_need_processc                    sR   | j krdS  j|  j |  j|  j fdd|jD  dS )z5
            Add a node to fusion group.
            Nc                    s$   h | ]}|j tkr| jkr|qS r   )r$   r%   r5   ).0nr6   r   r    	<setcomp>u   s   
 
z=FxNetAccFusionsFinder.FusionGroup.add_node.<locals>.<setcomp>)r5   r;   addr:   discardupdateall_input_nodes)r6   r"   r   r>   r    add_nodej   s    

z*FxNetAccFusionsFinder.FusionGroup.add_nodeN)r   r   __qualname__int__annotations__NodeSetrD   r   r   r   r    FusionGroup\   s
   
rI   Nr8   )fusion_groupr:   visitedc                 C   sz   |D ]p}|dk	r$||krq| | |jtkr0q| j||jk rDq||jkrT dS | ||j|r||  dS qdS )z
        Start from inputs and going reverse topological order. If any upstream node
        is in the fusion group, add all the nodes in this path to fusion group.
        NTF)	r@   r$   r%   r5   indexr9   recursive_add_noderC   rD   )r6   rJ   r:   rK   argr   r   r    rM   |   s    




z(FxNetAccFusionsFinder.recursive_add_node)r#   c                 C   s  i }t | j}|D ]l}||kr"q|jtkr.qd|jkr:q|| jkrFq| j| j||ht|j	|hd}|j
rD|j
 }| j||jt d d|jkr|jD ]:}|jtkrq||jkrq|| | j||jt d q|j	D ]^}|jtkrqd|jkrq||jkrq|| t|j| j||_| j||jt d qqjt|j| jksh|  j|j8  _q|jD ]}|j||< qnq|S )NZtensor_meta)r9   r5   r:   r;   )rK   )r3   r1   r$   r%   r+   rI   r5   rL   setrC   r;   poprM   r:   usersrD   minr9   )r6   resultr1   r"   rJ   userrN   r=   r   r   r    __call__   st    















 


zFxNetAccFusionsFinder.__call__)N)r   r   rE   __doc__r.   fxGraphModulerH   r7   r
   rI   r   NodeListr	   rM   r   NoderU   r   r   r   r    r   P   s   # 
&)gmr#   c                    s  t jt jt jt jt jt jt jt jt j	t j
t jt jtjjjjtjjjjtjjjjtjjjjtjjjjg}t| jjdtj }| jjD ] }|jD ]}|  d7  < qqt }| jjD ]}| dkr| | qi  t!|dkrd|" }|#| fdd |< |jD ]R}|  d8  < | dkr|j$dkrT|j%|krT|&| n
| | qqt!|jt!| jjk rt'dfddD  | jj(|_(|| _| S )	a  
    Replace the graph of the given GraphModule with one that contains the same nodes as the
    original, but in topologically sorted order.

    This is used by the merge_matmul transformation below, which disturbs the topologically sorted
    order of its input GraphModule, so that this order is restored before further transformation.

    Arguments:
        gm: The graph module to topologically sort. It is modified in-place.

    Returns:
        The graph module in-place sorted
    r      c                    s    |  S r2   r   )x)envr   r    <lambda>!      z legalize_graph.<locals>.<lambda>r   z&Input graph has cycles, unable to add c                    s   g | ]} | d kr|qS )r   r   )r<   r"   )indegr   r    
<listcomp>,  s      z"legalize_graph.<locals>.<listcomp>))operatorr@   mulsubfloordivtruedivmodleltgegteqner.   ZopsZatenZsym_constrain_rangedefaultZsym_constrain_range_for_sizeZ_assert_asyncmsgZscalar_tensorZ_assert_scalardictfromkeysr4   r5   rW   ZGraphrQ   collectionsdequeappendlenpopleftZ	node_copyr$   r(   
appendleftRuntimeErrorZ_codegen)r[   ZPRIORITIZED_OPSZ	new_graphr"   rT   queuecurr   )r^   ra   r    r      sT    








)'typingr   r   r   r   r   r   r   r	   rs   dataclassesr
   rc   r.   Ztorch.fxZtorch.fx.noder   Ztorch.fx._compatibilityr   __all__r/   ZTensorsZTensorOrTensorsrW   rZ   rY   rH   r   ZNamesr%   r   nnModuler   boolr   r   rX   r   r   r   r   r    <module>   s2   (


$#
 