U
    ©Ê¹j`%  ã                   @   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 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ÚMappingN)Ú	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   ú[/var/www/html/bwave/python/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	r”d|j
kr”d	|j› �S t|ƒS t|jtƒs¬t‚|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   C   s    c                   @   sh   e Zd ZdZejjedœdd„Ze	G dd„ dƒƒZ
deeef 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Únodesr0   )Úselfr   r0   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_idxr4   Ú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$   r4   )Ú.0Ún©r5   r   r   Ú	<setcomp>s   s   
 
þz=FxNetAccFusionsFinder.FusionGroup.add_node.<locals>.<setcomp>)r4   r:   Úaddr9   ÚdiscardÚupdateÚall_input_nodes)r5   r!   r   r=   r   Úadd_nodeh   s    

þÿz*FxNetAccFusionsFinder.FusionGroup.add_nodeN)r   r   Ú__qualname__ÚintÚ__annotations__ÚNodeSetrC   r   r   r   r   ÚFusionGroupZ   s
   
rH   r7   )Úfusion_groupr9   c                 C   s\   |D ]R}|j tkrq| j |¡|jk r(q||jkr8 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$   r4   Úindexr8   Úrecursive_add_noderB   rC   )r5   rI   r9   Úargr   r   r   rK   z   s    	


z(FxNetAccFusionsFinder.recursive_add_node)r"   c                 C   sr  i }t | jƒ}|D �]X}||kr"q|jtkr.qd|jkr:q|| jkrFq| j| j |¡|ht|j	ƒ|hd�}|j
�r0|j
 ¡ }|  ||j¡ d|jkrÐ|jD ]4}|jtkrªqš||jkr¶qš| |¡ |  ||j¡ qš|j	D ]V}|jtkræqÖd|jkròqÖ||jkrþqÖ| |¡ t|j| j |¡ƒ|_|  ||j¡ qÖqjt|jƒ| jk�sT|  j|j8  _q|jD ]}|j||< �qZq|S )NZtensor_meta)r8   r4   r9   r:   )r2   r0   r#   r$   r*   rH   r4   rJ   ÚsetrB   r:   ÚpoprK   r9   ÚusersrC   Úminr8   )r5   Úresultr0   r!   rI   ÚuserrL   r<   r   r   r   Ú__call__™   s\    





ü










 
ÿ
zFxNetAccFusionsFinder.__call__N)r   r   rD   Ú__doc__r-   ÚfxÚGraphModulerG   r6   r	   rH   r   ÚNodeListrK   r   ÚNoderS   r   r   r   r   r   N   s   !
ý)Úgmr"   c                    s  dd„ | j jD ƒ‰tj ¡ }| j jD ] }|jD ]}ˆ|  d7  < q.q$t ¡ }| j jD ]}ˆ| dkrV| |¡ qVi ‰ t	|ƒdkrÖ| 
¡ }| |‡ fdd„¡ˆ |< |jD ]*}ˆ|  d8  < ˆ| dkr¨| |¡ q¨qvt	|jƒt	| j jƒk �r
t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 r1   r   )Úx)Úenvr   r   Ú<lambda>ó   ó    z legalize_graph.<locals>.<lambda>z&Input graph has cycles, unable to add c                    s   g | ]}ˆ | d kr|‘qS rZ   r   r[   )Úindegr   r   Ú
<listcomp>û   s      z"legalize_graph.<locals>.<listcomp>)r3   r4   r-   rU   ZGraphrO   ÚcollectionsÚdequeÚappendÚlenÚpopleftZ	node_copyÚRuntimeErrorZ_codegen)rY   Z	new_graphr!   rR   ÚqueueÚcurr   )r_   rb   r   r   Ô   s,    



)%Útypingr   r   r   r   r   r   r   rd   Údataclassesr	   r-   Ztorch.fxZtorch.fx.noder
   Ztorch.fx._compatibilityr   Ú__all__r.   ZTensorsZTensorOrTensorsrU   rX   rW   rG   r   ZNamesr$   r   ÚnnÚModuler   Úboolr   r   rV   r   r   r   r   r   Ú<module>   s0   $


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