o
    j9:j>                     @   s   d dl Z d dlmZ d dlZd dlmZ d dlmZ g dZ	G dd dej
jZ	dd	ej
jd
ededeej
jej
jf fddZdej
jdedefddZ		ddejjej
jB deej
jgef dB dedefddZdS )    N)Callable)map_arg)split_module)FoldedGraphModuleget_unique_attr_name_in_modulesplit_const_subgraphsc                       sf   e Zd ZdZ			ddejjdejjdejjdB de	dB de	f
 fd	d
Z
 fddZdd Z  ZS )r   a  
    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cudarootgraphconst_subgraphfx_const_folded_attrs_namedevice_for_folded_attrsc                    s@   t  || |d u rd ntj||| _d| _|| _|| _d S )NF)	super__init__torchfxGraphModuleconst_subgraph_modulehas_folding_been_runr   r   )selfr	   r
   r   r   r   	__class__ g/home/nk/hobo-godmode/plappi-mvp/.venv/lib/python3.10/site-packages/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                    s~   j d u s
jd u rd S jrtdd_  }fdd t|tr2tj fdd|D n |}t	j| d S )NzFolding has already been runTc                    sN   t jjt| ts|   n
t | gj j	dt| t jr#| j
dS ddS )N)deviceF)requires_grad)r   nn	Parameter
isinstanceintdetachcloneTensortor   r    )i)r   r   r   _create_paramD   s   z4FoldedGraphModule.run_folding.<locals>._create_paramc                    s   g | ]} |qS r   r   ).0r)   )r*   r   r   
<listcomp>M   s    z1FoldedGraphModule.run_folding.<locals>.<listcomp>)
r   r   r   AssertionErrorr#   tupler   r!   ParameterListsetattr)r   folded_attrsparamsr   )r*   r   r   r   2   s   


zFoldedGraphModule.run_folding)NNr   )__name__
__module____qualname____doc__r   r!   Moduler   Graphstrr   r   r   __classcell__r   r   r   r   r      s$    
r   Tgminline_mod_namerun_dcereturnc              	      s  t |  | }t|tjjstdt| d}| jj	D ]}|j
dkr.|j|kr.|} nq|du r:td| |j}|j}i d}fdd}	|jj	D ]}
|
j
dkrj|
j|v r_||
j n|| |
< |d	7 }qN|
j
d
kr|
jd }t||	}g }t|ttfrddl  fdd|jD }|| |D ](}|jd	 }t|tstdt| |||  | j| || |< qqN| j| | j|
|	}W d   n1 sw   Y  ||
< qN| j| |r| j  S )a  
    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`.

    Returns a mapping from subgraph nodes to the newly created/mapped nodes in gm.
    zExpected GraphModule, got Ncall_modulez$Could not find call_module node for r   c                    s    |  }| j  |_ |S r   )metacopy)nodenew_node)replacement_mappingr   r   replacement_fnq   s   z&_inline_module.<locals>.replacement_fnplaceholder   outputc                    s6   g | ]}|j d kr|j ju rt|jd tr|qS )call_functionrG   )optargetgetitemr#   r   r$   )r+   user)operatorr   r   r,      s    
z"_inline_module.<locals>.<listcomp>zExpected int index, got )dictnamed_modulesr#   r   r   r   r-   typer
   nodesrJ   rK   r   r   namer   listr.   rN   usersreplace_all_uses_withr$   
erase_nodeinserting_before	node_copyeliminate_dead_code)r;   r<   r=   
inline_modcall_mod_node_to_replacerB   call_mod_argscall_mod_kwargsph_countrE   inline_nodeoutputsoutput_replacementsgetitem_usersrM   idxrC   r   )rN   rD   r   _inline_moduleT   sd   












re   
mod_tracedrS   c                 C   s   t dd|}|d  rd| }t| |r>t d|}|du r&|d }n|dd\}}| dt|d  }t| |s|S )	zP
    Make sure the name is unique (in a module) and can represents an attr.
    z[^0-9a-zA-Z_]+_r   z(.*)_(\d+)$N_1rG      )resubisdigithasattrmatchgroupr$   )rf   rS   rn   basenumr   r   r   r      s   



r   cpumoduleskip_folding_node_fnr   c              	      s  ddl }t| tjjstj| }n| }dtjjdtf fdd t d}|jj	D ]S}|j
dv r2q*|j
d	kr@t|js@q*|rG||rGq*| rLq*t|jd
d|jrXq*|j
dkrq||j }rqt|tjjrq |rqq*| |j
d	kr}d}q*|st||jS dtjjffdd}t|| |}	d\}
}|	jt|	|d}}|r|jj	ng D ]}|j
dkrt|	|jt||j q|jj	D ]}|j
dkrt|	|jt||j qd}|	jj	D ]}|j
dkr|j|
kr|j} nq|du rtdtj|	|j}d}|jj	D ]t}|j
dkrt|jd t}q|j
dkrq|t|kr3td| dt| d|| }|d7 }|j
d	krItd|j
 |j| |j|j}W d   n	1 sbw   Y  |j ! |_ |"| |j#| qdt$ vrtdt%|d}t|	||rtj&' ntj&(  |	jj	D ]9}|j
dkr|j|
kr|j| |j|}W d   n	1 sw   Y  |j ! |_ |"|  nqt)|	|rt*|	| |	j+  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.
    r   Nrs   r>   c                    st   t | tjjstd| jjD ](}|jdkr| r dS |jdkr7| 	|j
 }r7t |tjjr7 |  S qdS )z`
        Return True if a GraphModule type subgraph contains any impure op, else False.
        zDcaller should only pass GraphModule to subgraph_has_impure_ops checkrI   Tr?   F)r#   r   r   r   r-   r
   rR   rJ   	is_impureget_submodulerK   )rs   rB   	submodule)_subgraph_has_impure_opsr   r   rx      s   
z7split_const_subgraphs.<locals>._subgraph_has_impure_opsF>   rH   rF   get_attr
fill_valuer?   TrB   c                    s   |  v rdS dS )Nr   rG   r   )rB   )const_nodesr   r   mod_partition  s   z,split_const_subgraphs.<locals>.mod_partition)submod_0submod_1z,Could not find call_module node for const_gmrH   rF   zPlaceholder index z out of range for args (len=)rG   zExpected get_attr, got multiple_outputsz multiple_outputs not set in loop_FX_CONST_FOLDED_ATTRS),sympyr#   r   r   r   symbolic_traceboolsetr
   rR   rJ   all_input_nodesissubsetru   r   getExprrv   rK   addr   Noder   r}   getattrr0   r   r-   r.   lenrX   ry   r@   rA   rV   rW   localsr   r!   r/   r"   rm   re   rZ   )rs   rt   r   r   rf   found_const_foldingrB   
target_modr|   splitconst_mod_namenon_const_mod_nameconst_gmnon_const_gmcall_const_gm_argsroot_const_gmph_idxr   in_noderC   r   r1   r   )rx   r{   r   r      s   











r   )T)Nrr   )rj   collections.abcr   torch.fxr   torch.fx.noder   torch.fx.passes.split_moduler   __all__r   r   r   r9   r   rO   r   re   r   r!   r7   r   r   r   r   r   <module>   s:   D
Z