o
    Zh%                     @   s  d dl Z d dlmZ d dlmZ d dlZd dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZmZmZ d d	lmZ e	d
ddedefddZe	d
ddedefddZe	d
d	d'd
ddedededeeedf  dedeeeedf eedf f fddZe	d
ddededeedf deedf fddZe	d
ddedefd d!Ze	d
d	"	
d(ded#eeedf  d$ededef
d%d&Z dS ))    N)SimpleQueue)Optional)compatibility)Graph)GraphModule)Node)legalize_graphNodeListNodeSet)lift_subgraph_as_moduleF)Zis_backward_compatiblenodesreturnc                 C   s   t | d}t }| D ]}|jD ]}||v r||  d7  < q|| dkr*|| qg }| s[| }|| |jD ]}||v rV||  d8  < || dkrV|| q=| r1t	| t	|ksgJ d|S )Nr      z@topological sorted nodes doesn't have same length as input nodes)
dictfromkeysr   Zall_input_nodesputemptygetappenduserslen)r   Zindegree_map
candidatesnodensorted_nodes r   P/var/www/auris/lib/python3.10/site-packages/torch/fx/passes/utils/fuser_utils.py	topo_sort   s6   





r   	partitionc                    sZ   t |  g } D ]}|jD ]}| vr|| qqdtdtf fdd}||r+dS dS )N
root_nodesr   c                    sT   t  }| }|r(| }|| | v rdS |jD ]}||v r q|| q|sdS )NTF)setpopaddr   r   )r   visitedqueuecurrent	user_nodeZpartition_setr   r   bfs_find_cycle?   s   

z*validate_partition.<locals>.bfs_find_cycleFT)r    r   r   r	   bool)r   Zoutputsr   r&   r(   r   r'   r   validate_partition.   s   

r*   always_return_tuplegmmodule_namepartition_lookup_tabler,   .c                   sh  |D ].}|j j| u sJ | d|   |jrJ | d|| j jv s0J | d|   qt|s9J ddu rBt|t i i   fdd}|D ]}	||}| |< qTi }|D ]}|j
D ]}	|	vrv | ||< qjqet| }
|r|
 nt|
dkr|
d	 n|
   t| d
|d\}}t }t| }|||fS )a  
    Fuse nodes in graph_module into a GraphModule.

    Args:
        gm (GraphModule): target graph_module

        nodes (List[Node]): list of nodes in `gm` to fuse, where the node must be topologically sorted

        module_name: class name for the fused GraphModule

        partition_lookup_table (Optional[Dict[Node, None]]): optional dict of nodes to speed up lookup

        always_return_tuple (bool): whether to always return a tuple, even if there is only one output

    Returns:
        fused_gm (GraphModule): fused graph module, where its node is a copy of `nodes` in `gm`

        original_inputs (Tuple[Node, ...]): input nodes to `nodes` in original `gm`

        original_outputs (Tuple[Node, ...]): consumer nodes of `nodes` in original `gm`

    z* doesn't belong to passed in graph module z# has been removed from owning graphz is not found in graph module z*Invalid partition, found dependency cyclesNc                    sT   | j dkr	 | v r |  S | vr&j| j| jd}t| j|_|| < |  S )NZget_attr)Z	type_expr)opplaceholdernametypecopymeta)xZplaceholder_nodeZnode_mapZnode_to_placeholderr/   Zsubgraphr   r   remap_inputs   s   
z)fuse_as_graphmodule.<locals>.remap_inputsr   r    )Z	comp_name
class_name)graphZowning_moduleZ	_get_nameZ_erasedZ_find_nodes_lookup_tabler*   r   r   r   Z	node_copyr   tuplevaluesoutputr   Zlintr   keys)r-   r   r.   r/   r,   r   r8   new_nodeZoutput_mappingr&   ZoutsZfused_gm_Zoriginal_inputsZoriginal_outputsr   r7   r   fuse_as_graphmodule_   sJ   "




rB   sub_gmorig_inputsorig_outputsc           
      C   s   |j j}| || | jj||d d}|j }t|dkr1t|jd t	s1|d j
|dd | S t|D ]\}}tj|| j}	|j
|	dd q5t	dd |D |jd< | S )	N)argskwargsr   r   T)Zpropagate_metac                 s   s    | ]
}|j d dV  qdS )valN)r5   r   ).0orig_outputr   r   r   	<genexpr>   s    
zinsert_subgm.<locals>.<genexpr>rH   )	__class____name__Zadd_submoduler;   Zcall_moduleoutput_noder   
isinstancerF   r<   Zreplace_all_uses_with	enumeratetorchZfxZProxyr   r5   )
r-   rC   rD   rE   submodule_nameZmodule_noderN   irJ   Z	proxy_outr   r   r   insert_subgm   s   

rT   c                 C   s   t |D ]}| j| qd S N)reversedr;   Z
erase_node)r-   r   r   r   r   r   erase_nodes   s   rW   fused_
partitionsprefixc                 C   sf   t |D ](\}}tt|}|t| }t| ||||d\}}	}
t| ||	|
 t| | qt|  | S )Nr+   )rP   r   liststrrB   rT   rW   r   )r-   rY   rZ   r,   Zpartition_idr   r   rR   rC   rD   rE   r   r   r   fuse_by_partitions   s   r]   rU   )rX   F)!r4   r$   r   typingr   Z	_OptionalZtorch.fxrQ   Ztorch.fx._compatibilityr   Ztorch.fx.graphr   Ztorch.fx.graph_moduler   Ztorch.fx.noder   Ztorch.fx.passes.tools_commonr   r	   r
   Ztorch.fx.passes.utilsr   r   r)   r*   r\   r   r<   rB   rT   rW   r[   r]   r   r   r   r   <module>   sr   0u

