o
    h`%                     @   sX  d dl 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mZ d dlmZ g d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h dZedd	d
d Zedd	deeejjf dejjdefddZedd	dejjde fddZ!edd	G dd dZ"edd	dejj#dejj#fddZ$dS )    )ListTupleUnionDictAnySetMappingN)	dataclass)_get_qualified_name)compatibility)get_acc_ops_nameget_node_targetis_node_output_tensorFxNetAccFusionsFinderlegalize_graph>   call_methodcall_modulecall_functionF)is_backward_compatiblec                 C   sP   t | tr| S | jrd| jv rd| j S | jdd}|r |nd d| j S )Nacc_opsacc_ops.z
torch._opsz	torch.ops .)
isinstancestr
__module____name__replace)kmodule r    R/var/www/html/ai/venv/lib/python3.10/site-packages/torch/fx/passes/tools_common.pyr      s   
r   
submodulesnodereturnc                 C   s   |j tv sJ ddt d|j   |j dkr2t|jts!J | |j }t|dt|}t|S |j dkrN|j}|j	durJd|j	v rJd	|j
 S t|S t|jtsVJ |j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   _base_class_originr   Nr   r   )opCALLABLE_NODE_OPSjoinr   targetr   getattrtyper   r   r   r
   )r"   r#   submodsubmod_typer)   r    r    r!   r      s"   



r   c                 C   s"   | j dd}|du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   C   s   r   c                   @   sl   e Zd ZdZdejjdefddZe	G dd dZ
dd	d
eeef fddZdeejjef f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nodesr4   )selfr   r4   r    r    r!   __init__U   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_idxr8   inputsnodes_need_processc                    sR   | j v 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v r| jvr|qS r    )r&   r'   r8   ).0nr9   r    r!   	<setcomp>s   s
    z=FxNetAccFusionsFinder.FusionGroup.add_node.<locals>.<setcomp>)r8   r>   addr=   discardupdateall_input_nodes)r9   r#   r    rA   r!   add_nodeh   s   

z*FxNetAccFusionsFinder.FusionGroup.add_nodeN)r   r   __qualname__int__annotations__NodeSetrG   r    r    r    r!   FusionGroupZ   s   
 rL   fusion_groupr;   r=   c                 C   s\   |D ])}|j tvr
q| j||jk rq||jv r 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.
        TF)r&   r'   r8   indexr<   recursive_add_noderF   rG   )r9   rM   r=   argr    r    r!   rO   z   s   	


z(FxNetAccFusionsFinder.recursive_add_noder$   c                 C   sn  i }t | j}|D ]}||v rq	|jtvrq	d|jv rq	|| jvr"q	| j| j||ht|j	|hd}|j
r|j
 }| ||j d|jvrf|jD ]}|jtvrSqK||jv rYqK|| | ||j qK|j	D ]+}|jtvrqqid|jv rwqi||jv r}qi|| t|j| j||_| ||j qi|j
s7t|j| jks|  j|j8  _q	|jD ]}|j||< qq	|S )Ntensor_meta)r<   r8   r=   r>   )r6   r4   r&   r'   r.   rL   r8   rN   setrF   r>   poprO   r=   usersrG   minr<   )r9   resultr4   r#   rM   userrP   r@   r    r    r!   __call__   s^   
















zFxNetAccFusionsFinder.__call__N)r   r   rH   __doc__r1   fxGraphModulerK   r:   r	   rL   r   NodeListrO   r   NoderX   r    r    r    r!   r   N   s    

r   gmc                    s&  dd | j jD tj }| j jD ]}|jD ]
}|  d7  < qqt }| j jD ]}| dkr8|| q+i  t	|dkrp|
 }|| fdd |< |jD ]}|  d8  < | dkri|| qTt	|dksAt	|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
    c                 S   s   i | ]}|d qS r   r    r?   r#   r    r    r!   
<dictcomp>   s    z"legalize_graph.<locals>.<dictcomp>   r   c                    s    |  S r5   r    )x)envr    r!   <lambda>   s    z legalize_graph.<locals>.<lambda>z&Input graph has cycles, unable to add c                    s   g | ]
} | d kr|qS r_   r    r`   )indegr    r!   
<listcomp>   s    z"legalize_graph.<locals>.<listcomp>)r7   r8   r1   rZ   GraphrT   collectionsdequeappendlenpopleft	node_copyRuntimeError_codegen)r^   	new_graphr#   rW   queuecurr    )rd   rf   r!   r      s4   




	
r   )%typingr   r   r   r   r   r   r   ri   dataclassesr	   r1   torch.fxtorch.fx.noder
   torch.fx._compatibilityr   __all__r2   TensorsTensorOrTensorsrZ   r]   r\   rK   r   Namesr'   r   nnModuler   boolr   r   r[   r   r    r    r    r!   <module>   s2   $ 

(#
  