U
    Jc2                     @   s  d dl mZmZmZ d dlZd dlmZmZ d dlm	Z	 d dl
mZmZ d dl
mZ ejjZeejejejejejejejejejejejejejejejgZ eej!ej"ej#ej$ej%ej&ej'ej(ej)g	Z*ej+j,j-ddd	d
 Z.ej+j,j-ddG dd deZ/dS )    )DictTupleAnyN)PassBase
PassResult)tree_flatten)GraphModuleGraph)NodeF)Zis_backward_compatiblec                   C   s
   t tS N)rand_opsunioninplace_ops r   r   K/tmp/pip-unpacked-wheel-gikjz4vx/torch/fx/passes/dialect/common/cse_pass.pyget_CSE_banned_ops   s    r   c                       s.   e Zd Zd fdd	ZeedddZ  ZS )CSEPassNc                    s"   |dkrt  }|| _t   dS )a  
        This version of CSE Pass aims to be dialect agnostic, and it's implemented purely based on the connectivity between fx.Node.

        For functional dialects, user would only need to specify the random ops in ban list.

        Warning: CSE Pass cannot be safely applied on a FX graph in non-functional dialects.
        If your dialect contains stateful operators, please customized the banned_ops.

        N)set
banned_opssuper__init__)selfr   	__class__r   r   r      s    
zCSEPass.__init__)graph_modulereturnc                    s4  dd }d}t  }i  i }i }|jjD ]}|jdksV|jdksV|jdksV||| jkrt|| fdd}| |< q& fd	d
}	|	|j\}
}|	|j\}}|j|
|||d}t	|
|f}|j|f}||k}|r|| |krd}||  |< q&|| fdd}| |< |s&|||< |||< q&t
||}t||S )a  
        Return a new copy of torch.fx.GraphModule with CSE applied to the input graph

        Example usage:

        from torch.fx.experimental.proxy_tensor import make_fx
        def f(a):
            b = a * a
            c = a * a
            return b+c

        p = CSEPass()
        traced_graph = make_fx(f)(torch.tensor(1))
        print(traced_graph)
        result = p(traced_graph)
        print(result.graph_module)
        c                 S   s   t | jdr| jjS | jS )Noverloadpacket)hasattrtargetr   )noder   r   r   get_aten_target<   s    z%CSEPass.call.<locals>.get_aten_targetFplaceholderoutputZget_attrc                    s    |  S r   r   xenvr   r   <lambda>J       zCSEPass.call.<locals>.<lambda>c                    sP   t | \} }tt| D ]*}| | }t|tr| kr | | |< qt| |fS r   )r   rangelen
isinstancer
   tuple)arg_listspecivr%   r   r   
substituteO   s    z CSEPass.call.<locals>.substitute)r   args	args_speckwargskwargs_specTc                    s    |  S r   r   r#   r%   r   r   r'   i   r(   )r	   graphZnodesopr   Z	node_copyr2   r4   r   hashr   r   )r   r   r    modifiedZ	new_graphZhash_envZ	token_mapnZnew_noder1   r2   r3   r4   r5   tokenZhash_argZhash_valZhash_val_in_hash_envZcsed_gmr   r%   r   call*   s>    ,
 


zCSEPass.call)N)__name__
__module____qualname__r   r   r   r<   __classcell__r   r   r   r   r      s   r   )0typingr   r   r   ZtorchZtorch.fx.passes.infra.pass_baser   r   Ztorch.utils._pytreer   Ztorch.fxr   r	   r
   opsZatenr   ZdropoutZ_fused_dropoutZ_standard_gammaZ	bernoulliZmultinomialZnative_dropoutnormalZpoissonZbinomialZrreluZ	rand_likeZrandrandintZrandnZrandpermr   Zadd_Zsub_Zmul_Zdiv_Zpow_Zlerp_Zrelu_Zsigmoid_Ztanh_r   ZfxZ_compatibilityZcompatibilityr   r   r   r   r   r   <module>   s   D,
