U
    Kc                      @   s4  d dl Z d dlmZ d dlm  mZ e jj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mZ d d	lmZmZmZmZmZmZmZ eeee f eeeef  d
ddZeeeeeef f Z eee e f ee e e e f f Z!eee!e"f  dddZ#ee!e
ee e$dddZ%dS )    N)GraphModule)Node)getattr_from_fqn   )NSNodeTargetType)get_native_quant_patterns)ObserverBaseFakeQuantizeBase)DictTupleSetCallableAnyUnionList) base_name_to_sets_of_related_opsreturnc                 C   sx   t  }|  D ]d\}}t|}tdt|D ]D}t|t|D ]0}||| || f ||| || f q>q,q|S )Nr   )setitemslistrangelenadd)r   Ztype_a_related_to_b	base_namesZs_listZidx_0Zidx_1 r   @/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/ns/fx/pattern_utils.pyget_type_a_related_to_b   s    r   )r   c            
   	   C   s  g } t  }d}| D ]\}}t|trpt|dkrpt|d trpt|d dkrp|d |d d |d d f}t|tr| ||f ttfD ]0}t|tr|f|}n||f}| ||f qqd}dtj	ft
jt
jdf|ftjtjf|ftjtjf|ftjtjf|ftjtjtjf|ftjtjtjf|ftjtjtjf|fg}|D ]H}	| |	 | tf|	d |	d f | tf|	d |	d f qH| S )a  
    Set of potential fusions, in reverse order.  The order is reversed
    to match how fusion patterns are defined in quantization code.

    Fusion format:
    ((fusion_op_0, fusion_op_1), base_op_idx)

    Where base_op_idx is the idx of the op we should use to match other related
    ops. Note: base_op_idx is specified in non-reverse order, i.e. a base_op_idx
    of 0 represents the first op in regular (non-reverse) order, 1 represents the
    second op, etc.
    r      r   toZ
dequantize)r   r   
isinstancetupler   appendr   r	   torchZfloat16FZreluZlinearnnZBatchNorm1dZConv1dZBatchNorm2dZConv2dZBatchNorm3dZConv3dZReLU)
resultsZall_quant_patternsZdefault_base_op_idxZquant_patternZ_quant_handlerclsZnew_patternZfp16_em_base_op_idxZpatterns_to_addpr   r   r   get_reversed_fusions1   s>    


 r)   )end_nodereversed_fusiongm
seen_nodesr   c                 C   s&  | }t t|D ]}||kr$ dS || }|jdkrt|t oLt|t }|r|j|krb dS t|jdkrt|jd tr|jd }q dS n dS q|jdkr2t|t}|r*t|jtst	t
||j}	t|ts dS t|	|s dS t|jdkr"t|jd tr"|jd }n dS n dS q|jdkrt|toTt|dk}
t|t}|sl|
r|r|j|kr dS nVt|tst	|j|d kr dS t|jdk r dS |jd |d kr dS t|jdkr
t|jd tr
|jd }n dS n dS q dS qdS )	zZ
    Returns true if a pattern ending with `end_node` matches
    the fusion pattern.
    Fcall_functionr   Zcall_moduleZcall_methodr   r   T)r   r   opr    strtypetargetargsr   AssertionErrorr   r!   )r*   r+   r,   r-   Zcur_nodeZ
fusion_idxZcur_fusion_elZfusion_el_is_funZfusion_el_is_modZ
target_modZ!fusion_el_is_meth_with_second_argZfusion_el_is_meth_without_argsr   r   r    end_node_matches_reversed_fusion~   sd    






"
"r5   )&r#   Ztorch.nnr%   Ztorch.nn.functionalZ
functionalr$   opsZ	quantizedZtoqZtorch.fxr   Ztorch.fx.graphr   Ztorch.ao.quantization.utilsr   Zns_typesr   Z-torch.ao.quantization.fx.backend_config_utilsr   Ztorch.ao.quantizationr   r	   typingr
   r   r   r   r   r   r   r0   r   ZNSFusionElTypeZNSFusionTypeintr)   boolr5   r   r   r   r   <module>   s>   $

N