a
    h+                     @   sT  d dl Z d dlZd dlmZ d dlmZ d dl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
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 )    N)Mapping)	dataclass)AnyOptionalUnion)compatibility)_get_qualified_name)get_acc_ops_nameget_node_targetis_node_output_tensorFxNetAccFusionsFinderlegalize_graph>   Zcall_methodcall_functioncall_moduleF)Zis_backward_compatiblec                 C   sT   t | tr| S | jr*d| jv 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   J/var/www/auris/lib/python3.9/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rdt|jtsBJ | |j }t|dt|}t|S |j dkr|j}|j	durd|j	v rd	|j
 S t|S t|jtsJ |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joinr   targetr   getattrtyper	   r   r   r   )r   r   ZsubmodZsubmod_typer#   r   r   r   r
   +   s$    


r
   )r   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   R   s    r   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nodesr,   )selfr   r,   r   r   r   __init__e   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_idxr0   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!   r0   ).0nr1   r   r   	<setcomp>   s   z=FxNetAccFusionsFinder.FusionGroup.add_node.<locals>.<setcomp>)r0   r6   addr5   discardupdateall_input_nodes)r1   r   r   r9   r   add_nodex   s    

z*FxNetAccFusionsFinder.FusionGroup.add_nodeN)r   r   __qualname__int__annotations__NodeSetr?   r   r   r   r   FusionGroupj   s
   
rD   Nr3   )fusion_groupr5   visitedc                 C   sz   |D ]p}|dur$||v rq| | |jtvr0q| j||jk rDq||jv 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!   r0   indexr4   recursive_add_noder>   r?   )r1   rE   r5   rF   argr   r   r   rH      s    




z(FxNetAccFusionsFinder.recursive_add_node)r   c                 C   s  i }t | j}|D ]l}||v r"q|jtvr.qd|jv r:q|| jvrFq| j| j||ht|j	|hd}|j
rD|j
 }| j||jt d d|jvr|jD ]:}|jtvrq||jv rq|| | j||jt d q|j	D ]^}|jtvrqd|jv rq||jv 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)r4   r0   r5   r6   )rF   )r.   r,   r    r!   r&   rD   r0   rG   setr>   r6   poprH   r5   usersr?   minr4   )r1   resultr,   r   rE   userrI   r8   r   r   r   __call__   sr    

















zFxNetAccFusionsFinder.__call__)N)r   r   r@   __doc__r)   fxGraphModulerC   r2   r   rD   r   NodeListr   rH   dictNoderP   r   r   r   r   r   ^   s   # 
&r   )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%|v 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 r-   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   )r7   r   )indegr   r   
<listcomp>;  r\   z"legalize_graph.<locals>.<listcomp>))operatorr;   mulsubfloordivtruedivmodleltgegteqner)   opsZatenZsym_constrain_rangedefaultZsym_constrain_range_for_sizeZ_assert_asyncmsgZscalar_tensorZ_assert_scalarrU   fromkeysr/   r0   rR   ZGraphrL   collectionsdequeappendlenpopleftZ	node_copyr    r#   
appendleftRuntimeErrorZ_codegen)rW   ZPRIORITIZED_OPSZ	new_graphr   rO   queuecurr   )rZ   r]   r   r      sX    








r   )'ro   r_   collections.abcr   Zdataclassesr   typingr   r   r   r)   Ztorch.fxZtorch.fx._compatibilityr   Ztorch.fx.noder   __all__tupler*   r.   ZTensorsZTensorOrTensorsrR   rV   rT   rJ   rC   r   ZNamesr!   r	   nnModuler
   boolr   r   rS   r   r   r   r   r   <module>   s8   
& 