o
    پi$                     @   sv   d dl Z d dlZd dlmZ d dlmZmZ d dlZd dlm	Z	 d dl
mZ d dlmZ e eZG dd deZdS )	    N)Iterable)OptionalUnion)auto_functionalized)is_func)SGLangInductorPassc                   @   s  e Zd ZdZdejjfddZdeejj	e
ejj	 f fddZ	ddejjd	ejj	d
eeeejj	ef f deeeejj	ef df  fddZd	ejj	d
eeeejj	ef f fddZd	ejj	deeejj	f fddZ	ddejjd	ejj	deeeejj	ef df  fddZdS )FixFunctionalizationPassa"  
    This pass defunctionalizes certain nodes to avoid redundant tensor copies.
    After this pass, DCE (dead-code elimination) should never be run,
    as de-functionalized nodes may appear as dead code.

    To add new nodes to defunctionalize, add to the if-elif chain in __call__.
    graphc                 C   s   |    | |d g | _d}|jD ]}t|tsq|d7 }q| |d t| j}| jD ]}|| q-t	d|| | |d | 
  d S )Nbefore_fix_functionalizationr      $before_fix_functionalization_cleanupz,De-functionalized %s nodes, removed %s nodesafter_fix_functionalization)begin
dump_graphnodes_to_removenodesr   r   len
erase_nodeloggerdebugend_and_log)selfr	   countnodecount_removed r   `/home/ubuntu/.local/lib/python3.10/site-packages/sglang/srt/compilation/fix_functionalization.py__call__   s"   




z!FixFunctionalizationPass.__call__node_or_nodesc                 C   s.   t |tjjr| j| dS | j| dS )zM
        Stage a node (or nodes) for removal at the end of the pass.
        N)
isinstancetorchfxNoder   appendextend)r   r   r   r   r   _remove2   s   z FixFunctionalizationPass._removeNr   mutated_argsargs.c                 C   s*   |  || | j|||d | | dS )z
        De-functionalize a node by replacing it with a call to the original.
        It also replaces the getitem users with the mutated arguments.
        See replace_users_with_mutated_args and insert_defunctionalized.
        r'   N)replace_users_with_mutated_argsinsert_defunctionalizedr%   )r   r	   r   r&   r'   r   r   r   defunctionalize;   s   z(FixFunctionalizationPass.defunctionalizec                 C   sP   |  | D ]\}}|| }t|tr|j| n|}|| | | qdS )a7  
        Replace all getitem users of the auto-functionalized node with the
        mutated arguments.
        :param node: The auto-functionalized node
        :param mutated_args: The mutated arguments, indexed by getitem index.
        If the value of an arg is a string, `node.kwargs[arg]` is used.
        N)getitem_usersitemsr   strkwargsreplace_all_uses_withr%   )r   r   r&   idxuserargr   r   r   r)   K   s   

z8FixFunctionalizationPass.replace_users_with_mutated_argsreturnc                 C   s2   i }|j D ]}t|tjr|jd }|||< q|S )z
        Returns the operator.getitem users of the auto-functionalized node,
        indexed by the index they are getting.
        r   )usersr   operatorgetitemr'   )r   r   r5   r2   r1   r   r   r   r,   [   s   

z&FixFunctionalizationPass.getitem_usersc                    s   t  tsJ d  d| 5  jd }|du r%|j| jd nt fdd|D }|j||d W d   dS W d   dS 1 sJw   Y  dS )	a>  
        Insert a new defunctionalized node into the graph before node.
        If one of the kwargs is 'out', provide args directly,
        as node.kwargs cannot be used.
        See https://github.com/pytorch/pytorch/blob/a00faf440888ffb724bad413f329a49e2b6388e7/torch/_inductor/lowering.py#L351

        :param graph: Graph to insert the defunctionalized node into
        :param node: The auto-functionalized node to defunctionalize
        :param args: If we cannot use kwargs, specify args directly.
        If an arg is a string, `node.kwargs[arg]` is used.
        z%node must be auto-functionalized, is z insteadr   N)r/   c                 3   s(    | ]}t |tr j| n|V  qd S N)r   r.   r/   ).0r3   r   r   r   	<genexpr>   s    
zCFixFunctionalizationPass.insert_defunctionalized.<locals>.<genexpr>r(   )r   r   inserting_beforer'   call_functionr/   tuple)r   r	   r   r'   functionr   r:   r   r*   g   s    

"z0FixFunctionalizationPass.insert_defunctionalizedr8   )__name__
__module____qualname____doc__r    r!   Graphr   r   r"   r   r%   dictintr.   r   r>   r+   r)   r,   r*   r   r   r   r   r      s8    "

"r   )loggingr6   collections.abcr   typingr   r   r    *torch._higher_order_ops.auto_functionalizer   sglang.srt.compilation.fx_utilsr   $sglang.srt.compilation.inductor_passr   	getLoggerr@   r   r   r   r   r   r   <module>   s   
