U
    Jc[                  	   @   s  d dl Z d dlmZ d dlmZmZ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mZmZ d dlmZ eed	d
dZeedddZe
eeee
eedf eedf f dddZe
e
eedf eedf dddZe
edddZe
ee e
dddZdS )    N)SimpleQueue)ListDictTuple)GraphModule)Graph)Node)NodeListNodeSetlegalize_graph)lift_subgraph_as_module)nodesreturnc                 C   s   dd | D }t  }| D ]>}|jD ]}||kr"||  d7  < q"|| dkr|| qt }| s| }|| |jD ]2}||kr~||  d8  < || dkr~|| q~q^t| t|kst	d|S )Nc                 S   s   i | ]
}|d qS )r    ).0noder   r   E/tmp/pip-unpacked-wheel-gikjz4vx/torch/fx/passes/utils/fuser_utils.py
<dictcomp>   s      ztopo_sort.<locals>.<dictcomp>   r   z@topological sorted nodes doesn't have same length as input nodes)
r   Zall_input_nodesputlistemptygetappenduserslenAssertionError)r   Zindegree_map
candidatesr   nsorted_nodesr   r   r   	topo_sort   s&    


r    )	partitionr   c                    sh   t | t }D ]"}|jD ]}|kr|| qqt   fdd |D ]} |rP dS qPdS )Nc                    s<   | krdS  |  | jD ]}|kr |r dS qdS )NTF)addr   )r   	user_nodedfs_find_cycleZpartition_setvisitedr   r   r%   9   s    

z*validate_partition.<locals>.dfs_find_cycleFT)setr   r   r   )r!   outputsr   r#   Zoutput_noder   r$   r   validate_partition(   s    
r)   .)gmr   module_namer   c                    sB  D ]\}|j j| ks*t| d|   |jr>t| d|| j jkst| d|   qtsrtdt i i   fdd}D ]}||}| |< qi }D ]$}|j	D ]}|kr | ||< qqt
| }t|dkr|d n|   t| |d	}	t
 }
t
| }|	|
|fS )
a1  
    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

    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 cyclesc                    sR   | j dkr
| kr |  S | krJ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_inputsr   s    
z)fuse_as_graphmodule.<locals>.remap_inputsr   r   )
class_name)graphZowning_moduler   Z	_get_nameZ_erasedr   r)   r   Z	node_copyr   tuplevaluesoutputr   Zlintr   keys)r*   r   r+   r   r4   Znew_nodeZoutput_mappingr#   ZoutsZfused_gmZoriginal_inputsZoriginal_outputsr   r3   r   fuse_as_graphmoduleK   s0    "$

 r;   )r*   sub_gmorig_inputsorig_outputsc           	      C   st   |j j}| || | jj||d d}t|dkrB|d | n.t|D ]$\}}tj	
|| j}|| qJ| S )N)argskwargsr   r   )	__class____name__Zadd_submoduler6   Zcall_moduler   Zreplace_all_uses_with	enumeratetorchZfxZProxyr   )	r*   r<   r=   r>   submodule_nameZmodule_nodeiZorig_outputZ	proxy_outr   r   r   insert_subgm   s    rG   )r*   r   c                 C   s   t |D ]}| j| qd S )N)reversedr6   Z
erase_node)r*   r   r   r   r   r   erase_nodes   s    rI   )r*   
partitionsr   c           	      C   s\   t |D ]F\}}t|}dt| }t| ||\}}}t| ||| t| | qt|  | S )NZfused_)rC   r    strr;   rG   rI   r   )	r*   rJ   Zpartition_idr   r   rE   r<   r=   r>   r   r   r   fuse_by_partitions   s    rL   )r0   queuer   typingr   r   r   Ztorch.fxrD   Ztorch.fx.graph_moduler   Ztorch.fx.graphr   Ztorch.fx.noder   Ztorch.fx.passes.tools_commonr	   r
   r   Ztorch.fx.passes.utilsr   r    boolr)   rK   r;   rG   rI   rL   r   r   r   r   <module>   s$   # `$