U
    dJ                     @   s   d dl Z d dlmZ d dlmZ d dlmZ d dlZd dlZd dl	m
Z
mZ e jee j ee j dddZdeeed
ddZee dddZe jjdddZdS )    N)Node)symbolic_trace)legalize_graph)DictList)resultinputsreturnc                 C   s8   t | tjjrdgt| }ndd |D }t| |S )a  
    A free function for use in the merge_matmul graph transformation below that
    splits the output from a merged matmul into the individual results for each
    input tensor.

    Arguments:
        result: The merged matmul result tensor.
        inputs: The list of inputs that were merged into one for the matmul.

    Returns:
        List of matmul results for each input tensor.
    r   c                 S   s   g | ]}|j d  qS r   )shape).0x r   F/tmp/pip-unpacked-wheel-ua33x9lu/torch/fx/experimental/merge_matmul.py
<listcomp>   s     z(split_result_tensors.<locals>.<listcomp>)
isinstancetorchZfxZProxylensplit)r   r   splitsr   r   r   split_result_tensors   s    r      )absearch_depthc                 C   sP   | |krdS t | jdkrdS |dkr*dS | jD ]}t|||d r0 dS q0dS )a^  
    Determine if one node depends on another in a torch.fx.Graph.

    Arguments:
        a: The node that may have a dependency on b.
        b: The node that a may have a dependency on.
        search_depth: In the case of an indirect dependency, this function
                        searches upto this many nodes away in search of a
                        data dependency. If none is found, the function
                        makes the conservative assumption that there is a
                        dependency.

    Returns:
        True if a may depend on b, False if it definitely does not.
    Tr   F   )r   Zall_input_nodesmay_depend_on)r   r   r   inpr   r   r   r   #   s    
r   )nodesc                 C   s4   t | dD ]"\}}t||s(t||r dS qdS )z
    Check if all of the given nodes are pairwise-data independent.

    Arguments:
        nodes: The nodes to check for data dependencies.

    Returns:
        True if any pair in nodes has a data dependency.
       FT)	itertoolscombinationsr   )r   ijr   r   r   are_nodes_independentH   s    r$   )in_modc                    s  t |  i }i } jjD ]r}|jdks|jtjk	r4q|j\}}|jdkrN|jn|}|jdkrb|jn|}||g 	| ||g 	| q|
 D ]\}}t|dk rqt|sqdd |D } fdd|D }t|tr j|n|} jtj|fi } jtj||fi }	 jt|	|fi  fddtt|D }
t||
D ] \}}||  j| qRt  q    j   S )a  
    A graph transformation that merges matrix multiplication operations that share the same right-hand
    side operand into one large matrix multiplication.
               ____      _________        _________
      ----    |    |    |         |     M|  A * C  |
    M| A  |  T| B  | * K|    C    | =    |---------|
      ---- ,  |    |    |         |     T|  B * C  |
       K       ----      ---------        ---------
                K            R                R
    call_functionget_attrr   c                 S   s   g | ]}|j d  qS r
   )args)r   mmr   r   r   r      s     z merge_matmul.<locals>.<listcomp>c                    s&   g | ]}t |tr j|n|qS r   )r   strgraphr'   )r   l)gmr   r   r      s     c                    s"   g | ]} j tj|fi qS r   )r+   r&   operatorgetitem)r   outr-   Zmerge_mm_splitr   r   r      s   )r   r+   r   optargetr   matmulr(   
setdefaultappenditemsr   r$   r   r*   r'   r&   catr   rangezipZreplace_all_uses_withZ
erase_noder   Z	recompileZlint)r%   Z	rhs_usersZ	lhs_usersnodelhsrhsmmsZlhs_valsZmerge_mm_catZmerge_mmZmerge_mm_resoldnewr   r1   r   merge_matmulZ   sH    
  



rA   )r   )r   Ztorch.fx.noder   Ztorch.fx._symbolic_tracer   Ztorch.fx.passes.tools_commonr   r    r.   typingr   r   ZTensorr   intr   r$   nnModulerA   r   r   r   r   <module>   s    %