U
    dL-                     @   s   d dl Z d dlmZmZmZmZmZ d dlZd dl	m
Z
 d dlmZ G dd dejjZejjeddd	Zejjeed
ddZdeejjejjf eeejjgef  edddZdS )    N)CallableDictSetOptionalUnion)map_arg)split_modulec                       sR   e Zd ZdZd
ejjejje	ejj e
d fddZ fddZdd	 Z  ZS )FoldedGraphModulea  
    FoldedGraphModule is a GraphModule which also contains another
    `const_subgraph_module` representing a subgraph which has all const attr
    inputs and which can be run once before running the main standard
    `graph`. The `const_output_names` are the ordered list names of attrs which
    represent what each respective output from the const_subgraph should be set
    on which attrs.
    N)rootgraphconst_subgraphfx_const_folded_attrs_namec                    s@   d|_ t || |d kr d ntj||| _d| _|| _d S )Nr   F)	Z_ownerssuper__init__torchfxGraphModuleconst_subgraph_modulehas_folding_been_runr   )selfr
   r   r   r   	__class__ D/tmp/pip-unpacked-wheel-ua33x9lu/torch/fx/experimental/const_fold.pyr      s    zFoldedGraphModule.__init__c                    s   | j s|   t j| S N)r   run_foldingr   __call__)r   argskwargsr   r   r   r   (   s    zFoldedGraphModule.__call__c                 C   s   | j d ks| jd krd S | jr"td| _|   }t|trPtjdd |D n$tj	t|t
sd|nt|g }t| | j| d S )NTc                 S   s2   g | ]*}t jt|ts|nt |g qS r   )r   nn	Parameter
isinstanceintTensorcuda).0ir   r   r   
<listcomp>>   s   z1FoldedGraphModule.run_folding.<locals>.<listcomp>)r   r   r   AssertionErrorr!   tupler   r   ParameterListr    r"   r#   r$   setattr)r   folded_attrsparamsr   r   r   r   -   s"    
zFoldedGraphModule.run_folding)NN)__name__
__module____qualname____doc__r   r   Moduler   ZGraphr   strr   r   r   __classcell__r   r   r   r   r	   	   s     
r	   )gminline_mod_namec              
      s
  t |  | }t|tjjs"td}| jjD ] }|j	dkr.|j
|kr.|} qPq.|dk	s\t|j}i  d} fdd}|jjD ]|}|j	dkr||  |< |d7 }q~|j	dkr|jd }	t|	|}
||
 q~| j| | j||}W 5 Q R X | |< q~| j  dS )	z
    Given `gm` and some graph module which is called with target name `inline_mod_name`,
    this helper will inline all of the nodes from that called graph module into `gm`.
    Ncall_moduler   c                    s    |  }| j  |_ |S r   )metacopy)nodenew_nodeZreplacement_mappingr   r   replacement_fn\   s    z&_inline_module.<locals>.replacement_fnplaceholder   output)dictZnamed_modulesr!   r   r   r   r(   r   nodesoptargetr   r   replace_all_uses_withinserting_beforeZ	node_copyeliminate_dead_code)r5   r6   Z
inline_modZcall_mod_node_to_replacer:   Zcall_mod_argsZph_countr=   Zinline_nodeoutputsZoutput_replacementsr;   r   r<   r   _inline_moduleG   s4    





rI   )
mod_tracednamereturnc                 C   sx   t dd|}|d  r$d| }t| |rtt d|}|dkrL|d }q$|dd\}}| dt|d  }q$|S )	zP
    Make sure the name is unique (in a module) and can represents an attr.
    z[^0-9a-zA-Z_]+_r   z(.*)_(\d+)$NZ_1r?      )resubisdigithasattrmatchgroupr"   )rJ   rK   rS   basenumr   r   r   get_unique_attr_name_in_modulet   s    


rW   )moduleskip_folding_node_fnrL   c              
      s  t | tjjstj| }n| }t  d}|jjD ]RjdkrBq2jdkr^tj	
 s^q2|rl|rlq2  jdkr2d}q2|st||jS tjjd fdd}t|| |}|j|j }}d\}}	|jjD ]$jd	krt|jt|j q|jjD ](jd	krt|jt|j qd
}
|jjD ]*jd	kr:j|kr:j}
 qfq:|
d
k	stttj||j}|jjD ]jdkrt jd t}qjdkrqtfdd|
D }|jdkst|j |j|j}W 5 Q R X j |_| |j qdt ksBtt|d}t|||rbtj ! ntj "  |jjD ]^jd	krvj|krvj j|}W 5 Q R X j |_|  q֐qv|j#  t$||	 t||j|j|S )aJ  
    Looks through `module` for any nodes that have all constant attribute inputs
    and separates them out into their own constant subgraph, and returns a
    FoldedGraphModule which runs that constant subgraph on the first run to set
    attributes on the module prior to running the non-constant portion of the
    graph.
    F>   r>   r@   get_attrTr:   c                    s   |  krdS dS )Nr   r?   r   r[   )const_nodesr   r   mod_partition   s    z,split_const_subgraphs.<locals>.mod_partition)submod_0submod_1r7   Nr@   r   r>   c                 3   s   | ]}|j  jkr|V  qd S r   )rK   rD   )r%   nr[   r   r   	<genexpr>   s      z(split_const_subgraphs.<locals>.<genexpr>multiple_outputsZ_FX_CONST_FOLDED_ATTRS)%r!   r   r   r   Zsymbolic_tracesetr   rB   rC   Zall_input_nodesissubsetaddr	   Noder   r^   r_   r+   rD   getattrr   r(   r)   nextrF   rZ   r8   r9   rE   Z
erase_nodelocalsrW   r   r*   r    rG   rI   )rX   rY   rJ   Zfound_const_foldingr]   splitZconst_gmZnon_const_gmZconst_mod_nameZnon_const_mod_nameZcall_const_gm_argsZroot_const_gmrb   Zin_noder;   r   r,   r   )r\   r:   r   split_const_subgraphs   s    





 



   rk   )N)rO   typingr   r   r   r   r   Ztorch.fxr   Ztorch.fx.noder   Ztorch.fx.passes.split_moduler   r   r   r	   r3   rI   rW   r   r2   rf   boolrk   r   r   r   r   <module>   s   >- 