o
    Zhi(                     @   s"  d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ eeZeej g dZed	d
dedefddZdeeegef dee ddfddZdee dee dee fddZed	d
dededefddZed	d
G dd dZdS )    N)wraps)QueueCallable)compatibility)GraphModule)
PassResult)pass_result_wrapper this_before_that_pass_constraintPassManagerF)Zis_backward_compatiblefnreturnc                    s:    du rdS t   fdd}t st j|_|S )a+  
    Wrapper for passes which currently do not return a PassResult.
    This wrapper makes them return a PassResult containing the modified object
    and True for the "modified" flag.

    Args:
        fn (Callable[Module, Any])

    Returns:
        wrapped_fn (Callable[Module, PassResult])
    Nc                    sB    | }|d u rt | dS t|t r|S t|tjrt |dS d S )NT)r   
isinstancennModule)Zgmresr    Q/var/www/auris/lib/python3.10/site-packages/torch/fx/passes/infra/pass_manager.py
wrapped_fn$   s   


z'pass_result_wrapper.<locals>.wrapped_fn)r   inspect
isfunctiontype__name__)r   r   r   r   r   r	      s   
	r	   
constraintpassesc                 C   sl   t |D ]/\}}t ||d d  D ] \}}| ||rqtd| d| d| d| d| d| dqd S )	N   z,pass schedule constraint violated. Expected z before z but found z
 at index z and z	 at indexz in pass list.)	enumerateRuntimeError)r   r   iajbr   r   r   "_validate_pass_schedule_constraint4   s"   
r#   constraintsc                    sH  t |dkr| S dd | D }t| d t }| D ]0}| D ] }||kr%q|D ]}|||s=|| |  |  d7  < q'q | dkrJ|| qt| d}g }| s| }	||	 d||	< ||	 D ]}
||
 s |
  d8  <  |
 dkr||
 qh| rWtt	 fdd 
 }t |dkrd	| }t||S )
z
    Args
        passes: Passes that we are ordering
        constraints: Constraints applied on these passes

    Returns
        A sorted list of callables and a boolean of if a circular dependency
        existed
    r   c                 S   s   i | ]}|g qS r   r   .0pr   r   r   
<dictcomp>R   s    z,_topological_sort_passes.<locals>.<dictcomp>r   FTc                    s    |  dkS )Nr   r   )r'   Zindegree_mapr   r   <lambda>q   s    z*_topological_sort_passes.<locals>.<lambda>z:Circular dependency detected within the following passes: )lendictfromkeysr   appendputemptygetlistfilterkeysr   )r   r$   graph
candidatesr    r"   r   visitedZsorted_passesr'   nZcycle_passeserrorr   r)   r   _topological_sort_passesB   sJ   



r:   thisthatc                    s   dt dt f fdd}|S )a  
    Defines a partial order ('depends on' function) where `this` must occur
    before `that`.

    For example, the following pass list and constraint list would be invalid.
    ```
    passes = [pass_b, pass_a]

    constraints = [this_before_that_pass_constraint(pass_a, pass_b)]
    ```

    Args:
        this (Callable): pass which should occur first
        that (Callable): pass which should occur later

    Returns:
        depends_on (Callable[[Object, Object], bool]
    r    r"   c                    s   |  kp|kS Nr   )r    r"   r<   r;   r   r   
depends_on   s   z4this_before_that_pass_constraint.<locals>.depends_onr   )r;   r<   r?   r   r>   r   r
   {   s   r
   c                   @   s   e Zd ZU dZeeejgef  e	d< eeeege
f  e	d< dZe
e	d< dZee	d< 					d d	e
d
e
fddZdefddZdefddZdd Zdd ZdeddfddZdejddfddZdejdefddZdS )!r   ad  
    Construct a PassManager.

    Collects passes and constraints. This defines the pass schedule, manages
    pass constraints and pass execution.

    Args:
        passes (Optional[List[Callable]]): List of passes. A pass is a
            callable which modifies an object and returns a PassResult
        constraint (Optional[List[Callable]]): List of constraints. A
            constraint is a callable which takes two passes (A, B) and returns
            True if A depends on B and False otherwise. See implementation of
            `this_before_that_pass_constraint` for example.
        steps (int): Max number of times we run the passes (default = 1).
        run_checks_after_each_pass (bool): Whether to run checks and linting
            after each pass
        suppress_check_failures (bool): Whether to raise errors when running
            checks
    r   r$   F
_validatedr   stepsNrun_checks_after_each_passsuppress_check_failuresc                 C   s.   |pg | _ |pg | _|r|| _|| _|| _d S r=   )r   r$   rA   rB   rC   )selfr   r$   rA   rB   rC   r   r   r   __init__   s   


zPassManager.__init___passc                 C      | j | d| _dS )z>
        Adds a pass into the current list of passes.
        FN)r   r.   r@   )rD   rF   r   r   r   add_pass      
zPassManager.add_passr   c                 C   rG   )zI
        Adds a constraint into the current list of constraints.
        FN)r$   r.   r@   rD   r   r   r   r   add_constraint   rI   zPassManager.add_constraintc                 C   s,   | j rdS | jD ]}t|| j qd| _ dS )z
        Validates that current pass schedule defined by `self.passes` is valid
        according to all constraints in `self.constraints`
        NT)r@   r$   r#   r   rJ   r   r   r   validate_constraints   s
   

z PassManager.validate_constraintsc                 C   s   t | j| j| _d| _dS )ab  
        Finds a valid traversal order based on the given constraints and orders
        the passes based on this order.

        If a circular dependency exists between the constraints and steps = 1,
        then we will raise an error because if steps != 1 this means that we
        will re-run the passes, allowing for circular dependencies.
        TN)r:   r   r$   r@   )rD   r   r   r   solve_constraints   s   	
zPassManager.solve_constraintscheckr   c                 C   s8   t |}tt|j dkrtdt| d| dS )z
        Adds a function which takes runs various checks on a given graph module.
        This function is run before and after each pass if the
        `run_checks_after_each_pass` flag is enabled.
        r   zEPassManager check function should only take in one variable, a modulerN   N)r   	signaturer+   r2   
parametersvalues	TypeErrorsetattr)rD   rN   sigr   r   r   
add_checks   s   
zPassManager.add_checksmodulec                 C   s   d S r=   r   )rD   rV   r   r   r   rN      s   zPassManager.checkc                 C   sD  | j s|   | | d}t| jD ]}d}t| jD ]w\}}t|r(|j	nt
|j	}td| z;||}t|tsLt|dsLtd| dd |j}|pS|j}t|tretd||j |  | jrm| | W q ty }	 zdd	 | jd
| D }
d| d|
 }t||	d
}	~	ww |p|}|s nqt||S )a}  
        Runs a list of passes in the order based on `self.passes` on the given
        graph module. Each time a pass is run, checks and linting will be run on
        the graph module if `run_checks_after_each_pass` is set.

        If the module is a graph module, we will run the list of passes until
        the graph stops changing, or until `steps` number of times.
        FzRunning pass '%s'graph_modulezThe result of the pass z should be type PassResult.z)Please wrap it with pass_result_wrapper()zGraph after pass '%s': %sc                 S   s&   g | ]}t |r|jnt|jqS r   )r   r   r   r   r%   r   r   r   
<listcomp>)  s    z(PassManager.__call__.<locals>.<listcomp>Nz$An error occurred when running the 'z#' pass after the following passes: )r@   rM   rN   rangerA   r   r   r   r   r   r   loggerdebugr   r   hasattrrR   rW   modifiedr   r5   Z	recompilerB   	Exception)rD   rV   Zoverall_modified_r]   r   r   fn_namer   eZprev_pass_namesmsgr   r   r   __call__   sP   






	
zPassManager.__call__)NNNFF)r   
__module____qualname____doc__r2   r   r   r   r   __annotations__boolr@   rA   intrE   rH   rK   rL   rM   rU   rN   rc   r   r   r   r   r      s.   
 
r   )r   logging	functoolsr   queuer   typingr   Ztorch.nnr   Ztorch.fx._compatibilityr   Ztorch.fx.graph_moduler   Ztorch.fx.passes.infra.pass_baser   	getLoggerr   rZ   setLevelWARNING__all__r	   rh   r2   r#   r:   r
   r   r   r   r   r   <module>   s@   


9