o
    ߗi+                     @   sd  d dl Z 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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 )    N)	dataclass)AnyDictListMappingOptionalSetTupleUnion)compatibility)_get_qualified_name)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!   Z/home/ubuntu/transcripts/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   Q   s   r   c                   @   sx   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
deeef dee 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nodesr5   )selfr    r5   r!   r!   r"   __init__d   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_idxr9   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(   r9   ).0nr:   r!   r"   	<setcomp>   s
    z=FxNetAccFusionsFinder.FusionGroup.add_node.<locals>.<setcomp>)r9   r?   addr>   discardupdateall_input_nodes)r:   r$   r!   rB   r"   add_nodew   s   

z*FxNetAccFusionsFinder.FusionGroup.add_nodeN)r   r   __qualname__int__annotations__NodeSetrH   r!   r!   r!   r"   FusionGroupi   s   
 rM   Nfusion_groupr<   r>   visitedc                 C   sz   |D ]8}|dur||v rq| | |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.
        NTF)	rD   r'   r(   r9   indexr=   recursive_add_noderG   rH   )r:   rN   r>   rO   argr!   r!   r"   rQ      s    




z(FxNetAccFusionsFinder.recursive_add_noder%   c                 C   s  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||jt d d|jvrl|jD ]}|jtvrVqN||jv r\qN|| | j||jt d qN|j	D ].}|jtvrwqod|jv r}qo||jv rqo|| t|j| j||_| j||jt d qo|j
s7t|j| jks|  j|j8  _q	|jD ]}|j||< qq	|S )Ntensor_meta)r=   r9   r>   r?   )rO   )r7   r5   r'   r(   r/   rM   r9   rP   setrG   r?   poprQ   r>   usersrH   minr=   )r:   resultr5   r$   rN   userrR   rA   r!   r!   r"   __call__   sv   















*
zFxNetAccFusionsFinder.__call__r6   )r   r   rI   __doc__r2   fxGraphModulerL   r;   r   rM   r
   NodeListr   rQ   r   NoderZ   r!   r!   r!   r"   r   ]   s    #

&r   gmc                    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  < qIqDt }| jjD ]}| dkrj| | q]i  t!|dkr|" }|#| fdd |< |jD ]%}|  d8  < | dkr|j$dkr|j%|v r|&| q| | qt!|dksst!|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 r6   r!   )x)envr!   r"   <lambda>.  s    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>))operatorrD   mulsubfloordivtruedivmodleltgegteqner2   opsatensym_constrain_rangedefaultsym_constrain_range_for_size_assert_asyncmsgscalar_tensor_assert_scalardictfromkeysr8   r9   r\   GraphrV   collectionsdequeappendlenpopleft	node_copyr'   r*   
appendleftRuntimeError_codegen)r`   PRIORITIZED_OPS	new_graphr$   rY   queuecurr!   )rc   re   r"   r      s`   










r   )'r   rg   dataclassesr   typingr   r   r   r   r   r   r	   r
   r2   torch.fxtorch.fx._compatibilityr   torch.fx.noder   __all__r3   TensorsTensorOrTensorsr\   r_   r^   rL   r   Namesr(   r   nnModuler   boolr   r   r]   r   r!   r!   r!   r"   <module>   s@   (
&  