
    sg                        d dl Z d dlZd dlZd dlmZmZmZmZmZm	Z	m
Z
 d dlZd dlmc mZ d dlmZ d dlmZ d dlmZmZmZmZ d dlmZmZ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
rd d
l(m)Z) g Z* ejV                  ddd       ejV                  ddd       ejV                  d       ejV                  d       ejV                  d       ejV                  d      fZ, ejV                  dddd       ejV                  dddd       ejV                  d       ejV                  d       ejV                  d       ejV                  d      fZ-de.de.de.de.dee/ef   f
dZ0dedefdZ1dedefdZ2dedefdZ3d Z4de.de.de.dede.defdZ5de.de.de.dede.defdZ6dddedede.fdZ7dddedede.fdZ8d ede.fd!Z9d ede.fd"Z:d#edee/e	eef   f   fd$Z;d%eeef   deeef   fd&Z<d'ed(efd)Z=d'ed*efd+Z>d,ed-eeef   fd.Z?d/edefd0Z@d/eded1e	ed2f   de.def
d3ZAd/efd4ZBd/efd5ZCd'ed*efd6ZDd/edefd7ZEd/eded1e	ed2f   de.def
d8ZFy)9    N)AnyCallableDictListOptionalTupleTYPE_CHECKING)quantized_decomposed_lib)_WrapperModule)DerivedQuantizationSpec
EdgeOrNodeQuantizationSpecBaseSharedQuantizationSpec)GraphGraphModuleNode)replace_pattern_with_filtersReplacedPatterns   )_conv1d_bn_example_inputs_conv2d_bn_example_inputs"_get_aten_graph_module_for_pattern_is_bn_node_is_conv_or_conv_transpose_node_is_conv_transpose_fnfold_bn_weights_into_conv_node)InternalMatch   is_per_channelhas_biasbias_is_quantizedis_cudareturnc                 "   i }| rt        j                  dgt         j                        |d<   t        j                  dgt         j                        |d<   |rT|rRt        j                  dgt         j                        |d<   t        j                  dgt         j                        |d<   |rt        j                  d      |d<   |rF|j                         D ]3  \  }}t        |t         j                        s!|j                         ||<   5 |S )	zu
    Optional example inputs for quantized and folded conv-bn patterns
    used in convert, expressed as kwargs.
    r   dtypeweight_scaler   weight_zero_point
bias_scalebias_zero_point	conv_bias)	torchtensorfloatintrandnitems
isinstanceTensorcuda)r   r    r!   r"   kwargskvs          W/var/www/html/venv/lib/python3.12/site-packages/torch/ao/quantization/pt2e/qat_utils.py,_get_quantized_conv_bn_example_inputs_kwargsr9   :   s     F !&qc!E~&+llA3eii&H"#)#(<<5;;#GF< (-aS		(JF$%#kk!n{LLN 	%DAq!U\\*FFHq		% M    conv_fnc                 &    dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  f fd	}t        |      S )
Nxconv_weightr+   	bn_weightbn_biasbn_running_meanbn_running_varr#   c                 R     | ||      } t        j                  | ||||d      } | S )NT)training)F
batch_norm)r=   r>   r+   r?   r@   rA   rB   r;   s          r8   _conv_bn_patternz._get_conv_bn_pattern.<locals>._conv_bn_patternW   s5     A{I.LL	7T
 r:   r,   r3   r   )r;   rG   s   ` r8   _get_conv_bn_patternrI   V   s    <<\\ << <<	
    
 *++r:   c                 &    dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  f fd	}t        |      S )
Nr=   r>   r+   r?   r@   rA   rB   r#   c           	         d}t        j                  ||z         }||z  }	dgt        |j                        z  }
t	              rdnd}d|
|<   dgt        |j                        z  }d|d<   ||	j                  |
      z  }t        j                  || j                        } | ||      } | |	j                  |      z  } | |j                  |      z   } t        j                  | ||||d|      } | S )z
        Approximated method to fuse conv and bn. It requires only one forward pass.
        conv_orig = conv / scale_factor where scale_factor = bn.weight / running_std.
        This is based on `nniqat.ConvBn2d._forward_approximate`.
        h㈵>r   r   r%   TrD   eps)
r,   sqrtlenshaper   reshape
zeros_liker&   rE   rF   )r=   r>   r+   r?   r@   rA   rB   bn_epsrunning_stdscale_factorweight_shapeweight_in_channel_axis
bias_shapescaled_weight	zero_biasr;   s                  r8   _qat_conv_bn_patternz6_get_qat_conv_bn_pattern.<locals>._qat_conv_bn_patternk   s    jj&!89 ;.sS!2!233&;G&D!/1+,S3{0011

1#l&:&:<&HH$$Yagg>	A}i0$$Z00	!!*--LL
 r:   rH   )r;   r]   s   ` r8   _get_qat_conv_bn_patternr^   j   s    %<<%\\% <<% <<	%
 % % % 
%N .//r:   c                 &    dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  f fd	}t        |      S )
Nr=   r>   r+   r?   r@   rA   rB   r#   c           	      x   d}t        j                  ||z         }||z  }	dgt        |j                        z  }
t	              rdnd}d|
|<   dgt        |j                        z  }d|d<   ||	j                  |
      z  } | |d      } | |	j                  |      z  } t        j                  | ||||d|      } | S )z]
        Same as `_get_qat_conv_bn_pattern`, but handles the case with no conv bias.
        rL   r   r   rM   NTrN   )r,   rP   rQ   rR   r   rS   rE   rF   )r=   r>   r+   r?   r@   rA   rB   rU   rV   rW   rX   rY   rZ   r[   r;   s                 r8   !_qat_conv_bn_pattern_no_conv_biaszP_get_qat_conv_bn_pattern_no_conv_bias.<locals>._qat_conv_bn_pattern_no_conv_bias   s     jj&!89 ;.sS!2!233&;G&D!/1+,S3{0011

1#l&:&:<&HHA}d+$$Z00LL
 r:   rH   )r;   ra   s   ` r8   %_get_qat_conv_bn_pattern_no_conv_biasrb      s    "<<"\\" <<	"
 <<" " " " 
"H ;<<r:   c           	      ^   d}|rdnd}|rdnd}|r||   nd}|r||   nd}d}	d}
t         j                  }t         j                  j                  }|r0|j	                  | ||||	|
|      } |j                  | ||||	|
|      } | S |j                  | |||	|
|      } |j                  | |||	|
|      } | S )	a  
    Helper function to append q-dq ops after `x`, using dummy values for the qparams
    and qmin/qmax. We use dummy values here because we match with `ignore_literals=True`
    and will manually replace these values after subgraph rewriting.

    Return the dq node.
    r   r)   r'   r*   r(   g      ?i   )r,   int8opsquantized_decomposedquantize_per_channeldequantize_per_channelquantize_per_tensordequantize_per_tensor)r=   r   is_biasr5   per_channel_axis	scale_keyzp_keyscalezpqminqmaxr&   qds                r8   _append_qdqru      s      '^I")/BF!/F9SE)qBDDJJE		'	'B##Aub2BD$PUV%%a4DdDRWX H ""1eRtUC$$Qr4uEHr:   bn_is_trainingc                     ddt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  f fd	}t        |      S )
a  
    Return the quantized version of QAT conv + BN pattern.
    This is based on `nniqat.ConvBn2d._forward_approximate`,
    used in QAT convert. We first match this pattern and replace
    it with the normal [conv - bn] pattern, then fold the BN
    weights into conv.
    rL   r=   r>   r?   r@   rA   rB   r#   c           	      *   t        j                  |z         }||z  }dgt        |j                        z  }	d|	d<   dgt        |j                        z  }
d|
d<   ||j	                  |	      z  }t        |d|      }r@t        j                  |d   | j                        }rt        |d|      } | ||      } n
 | |d       } | |j	                  |
      z  } r| |d   j	                  |
      z   } t        j                  | ||||	      } | S )
Nr   rM   r   Frl   r5   r+   r%   TrN   )
r,   rP   rQ   rR   rS   ru   rT   r&   rE   rF   )r=   r>   r?   r@   rA   rB   r5   rV   rW   rX   rZ   r[   r\   r!   rU   rv   r;   r    r   s                r8   _quantized_qat_conv_bn_patternzJ_get_quantized_qat_conv_bn_pattern.<locals>._quantized_qat_conv_bn_pattern   s@    jj&!89 ;.sS!2!233QS3{0011

1#l&:&:<&HH#	
 (()<AGGLI '" !		 =)4A=$/A$$Z00F;'//
;;ALL#
 r:   rH   )r   r    r!   r;   rv   rz   rU   s   ````` @r8   "_get_quantized_qat_conv_bn_patternr{      s     F.<<.\\. <<. 	.
 . . 
. .` 899r:   c                     ddt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  dt         j                  f fd	}t        |      S )
zQ
    Quantized QAT conv - bn pattern with bn weights being folded into conv.
    rL   r=   r>   r?   r@   rA   rB   r#   c           	          t        |d|      }r|d   }rt        |d|      }nd } | ||      } t        j                  | ||||
	      } | S )NFry   r+   TrN   )ru   rE   rF   )r=   r>   r?   r@   rA   rB   r5   biasr!   rU   rv   r;   r    r   s           r8   %_folded_quantized_qat_conv_bn_patternzX_get_folded_quantized_qat_conv_bn_pattern.<locals>._folded_quantized_qat_conv_bn_pattern*  s     "	
 +&D "" !	 DA{D)LL#
 r:   rH   )r   r    r!   r;   rv   r   rU   s   ````` @r8   )_get_folded_quantized_qat_conv_bn_patternr     s     F$<<$\\$ <<$ 	$
 $ $ 
$ $L ?@@r:   matchr   original_graphpattern_graphc                     | j                   j                         D ]:  }t        |      st        |j                        dkD  xr |j                  d   duc S  t        d      )zw
    Match filter for the subgraph rewriter that returns True if the conv node in
    the original graph has bias.
       Nz5Could not find conv node in matched conv + bn pattern)	nodes_mapvaluesr   rQ   args
ValueError)r   r   r   ns       r8   _has_conv_bias_filterr   S  sZ     __##% =*1-qvv;?<qvvay'<<= L
MMr:   c                     t        | ||       S )z
    Match filter for the subgraph rewriter that returns True if the conv node in
    the original graph does NOT have bias.
    )r   )r   r   r   s      r8   _no_conv_bias_filterr   b  s     %UNMJJJr:   r   c                 ,   | j                   t        j                  j                  j                  j
                  t        j                  j                  j                  j                  t        j                  j                  j                  j
                  fv S N)targetr,   rf   rg   rj   defaultr-   rh   r   s    r8   _is_quantizer   n  sc    88		&&::BB		&&::AA		&&;;CC  r:   c                 ,   | j                   t        j                  j                  j                  j
                  t        j                  j                  j                  j                  t        j                  j                  j                  j
                  fv S r   )r   r,   rf   rg   rk   r   r-   ri   r   s    r8   _is_dequantizer   v  sc    88		&&<<DD		&&<<CC		&&==EE  r:   rc                    dt         t           dt        t        t        t        t           f   fd}dt        dt        t        t        t        f   fd}t	        t        | j                        j                               } ||      \  }}} || j                        \  }}}	||	J ||f||fd}
n|	J |J ||f||f||	fd}
 |t	        | j                  j                                     \  }}}|j                  ^}}}|j                  ^}}}t        |t              sJ t        |t              sJ t        |t              sJ t        |t              sJ | j                  |   }| j                  |   }t        |      rS ||      \  }}} ||      \  }}}| j                  |   }| j                  |   }| j                  |   }||f|
d<   ||f|
d	<   ||f|
d
<   ||f|
d<   t        |j                        dkD  rt        |j                        dkD  r|j                  d   }|j                  d   }t        |t              sJ t        |t              sJ | j                  |   }t        |      rS ||      \  }}} ||      \  }}}| j                  |   }| j                  |   } | j                  |   }!| |f|
d<   |!|f|
d<   ||f|
d<   |
S )a  
    Helper function to extract the nodes in the conv-bn fusion pattern after
    subgraph rewriting, in the form of a map:

        {name: (original_node, replacement_node)}

    The following names must exist in the map:

        "conv", "conv_weight", "conv_input", "bn", "getitem"

    The following names may exist in the map:

        "conv_weight_q", "conv_weight_dq", "conv_bias",
        "conv_bias_q", "conv_bias_dq"
    nodesr#   c                     d\  }}}| D ]X  }|j                   dk7  rt        |      r|J |}t        |      r|J |}|j                  t        j
                  k(  sS|J |}Z |J |J |||fS )z
        Return a 3-tuple of (conv_node, bn_node, getitem_node).
        This asserts that the match contains exactly one of each node.
        )NNNcall_function)opr   r   r   operatorgetitem)r   	conv_nodebn_nodegetitem_noder   s        r8   
_get_nodesz._get_conv_bn_pattern_nodes.<locals>._get_nodes  s    
 ,<(	7L 	!Att&.q1 (((	1~&xx8+++#+++ 	! $$$"""7L11r:   r   c                     t        |       sJ | j                  d   }t        |t              sJ t	        |      sJ |j                  d   }t        |t              sJ ||| fS )zC
        Return a 3-tuple of (orig_node, q_node, dq_node).
        r   )r   r   r2   r   r   )r   q_node	orig_nodes      r8   _get_q_dq_nodesz3_get_conv_bn_pattern_nodes.<locals>._get_q_dq_nodes  sg     a   &$'''F###KKN	)T***61%%r:   )convbn)r   r   r   conv_weight_qconv_weight_dq
conv_inputr>   r   conv_bias_qconv_bias_dqr+   )r   r   r   r   list_filter_nodes_mapr   r   replacementskeysr   r2   r   rQ   )"r   r   r   original_nodeso_convo_bn	o_getitemr_convr_bn	r_getitemmappingp_conv_p_conv_inputp_conv_weightr_conv_inputr_conv_weighto_conv_inputo_conv_weightp_conv_weight_qp_conv_weight_dqr_conv_weight_qr_conv_weight_dqo_conv_weight_qo_conv_weight_dqp_conv_biasr_conv_biaso_conv_biasp_conv_bias_qp_conv_bias_dqr_conv_bias_qr_conv_bias_dqo_conv_bias_qo_conv_bias_dqs"                                     r8   _get_conv_bn_pattern_nodesr   ~  s%   "2$t* 2tT8D>/I)J 2.
&4 
&E$d*:$; 
& +AKK8??ABN(8FD)(8FD)    V$,
 $$$$$$V$,!9-
  Q[[%5%5%7 89NVQ(.%\=1(.%\=1lD)))mT***lD)))mT***;;|,LKK.M m$;J<
8(8 <K<
8(8 M2++o6;;'78$3_#E %57G$H !)<8GL+];GM 6;;!FKK 01 4kk!nkk!n+t,,,+t,,,kk+. +&9H9U6K9H9U6K++k2KKK6M[[8N&3]%CGM"'5~&FGN# +[9Nr:   r   c                 j    i }| j                         D ]  \  }}|	|j                  dk(  r|||<    |S )z
    Return a filtered `nodes_map` returned from the subgraph rewriter.
    The filtered `nodes_map` will contain only nodes that are actually
    matched in the pattern, excluding None or placeholder nodes.
    placeholder)r1   r   )r   new_nodes_mappattern_node
graph_nodes       r8   r   r     sN     ')M$-OO$5 1 j??m+&0l#1 r:   original_nodenew_nodec                     t        |       sJ t        |      sJ t        |j                        }t        |      dk  r|j	                  d       t        |dd       | j                  dd z   |_        y)a=  
    Copy over literal args in conv, such as stride and padding, from the matched node
    in the original graph to its replacement in the new graph.

    This is needed due to the following limitation in the subgraph rewriter when used
    with dynamo export: literal (non-tensor) args are not supported in the match and
    replacement patterns. This is because dynamo export automatically inlines these
    literal args, making them dead placeholder nodes. In the future, we should check
    if dynamo export can optionally disable this inlining, or if subgraph rewriter
    can do the copying for us. See https://github.com/pytorch/pytorch/issues/100419.

    Note: Unlike other tensor args like conv weights and biases, literal args are
    preserved in the original nodes after replacement, so we can access them here.
    r   N)r   r   r   rQ   appendtuple)r   r   new_argss      r8   _copy_over_literal_conv_argsr     sj     +=999*8444HMM"H
8}q(2A,'-*<*<QR*@@HMr:   replacement_nodec                    t        |       sJ t        |      sJ d| j                  vry| j                  d   j                  }i }t        |j	                               }|d   d   ||j
                  d   <   |d   d   ||j
                  d   <   t        |j
                        dkD  r&t        |      dkD  r|d   d   ||j
                  d   <   ||j                  d   _        y)a  
    Update the `input_qspec_map` in the annotation after subgraph rewriting.

    The original annotation referred to the nodes in the original graph,
    so the keys in the `input_qspec_map` will need to be updated to reflect
    the corresponding nodes in the replacement graph.
    quantization_annotationNr   r   r   )r   metainput_qspec_mapr   r1   r   rQ   )r   r   original_input_qspec_mapr   all_configss        r8   ._update_conv_input_qspec_map_after_replacementr   (  s     +=999*+;<<< (:(::,11! o  O /5578K0;Aq0AO$))!,-0;Aq0AO$))!,-
  !A%#k*:Q*>4?N14E(--a01GV34Dr:   nodeoriginal_to_replacement_nodec                    dt         ffddt        ffd}d| j                  vry| j                  d   }|j                  j	                         D ]  \  }} ||      |j                  |<     ||j
                        |_        y)ai  
    Update the `SharedQuantizationSpec`s and `DerivedQuantizationSpec`s
    used in `node`'s quantization annotation after subgraph rewriting.

    The original annotation referred to the nodes in the original graph,
    so the nodes used in these special quantization specs will need to
    be updated to the corresponding nodes in the replacement graph.
    edge_or_nodec                 (   t        | t              r| }j                  ||      S t        | t              rIt	        |       dk(  r;t        d | D              r)| \  }}j                  ||      j                  ||      fS t        dt        |             )Nr   c              3   <   K   | ]  }t        |t                y wr   )r2   r   ).0r=   s     r8   	<genexpr>zZ_update_special_qspecs_after_replacement.<locals>._get_new_edge_or_node.<locals>.<genexpr>\  s     >AJq$'>s   z"unexpected type for edge_or_node: )r2   r   getr   rQ   allr   type)r   _nodesrcdestr   s       r8   _get_new_edge_or_nodezG_update_special_qspecs_after_replacement.<locals>._get_new_edge_or_nodeU  s    lD) E/33E5AA|U+L!Q&>>>$IC,00c:,00t< 
 A4CUVVr:   qspecc                     t        | t              r | j                        }t        |      S t        | t              r6| j                  D cg c]
  } |       }}t        j                  | |      S | S c c}w )N)derived_from)r2   r   r   r   r   dataclassesreplace)r   new_edge_or_noder=   new_derived_fromr   s       r8   _get_new_qspecz@_update_special_qspecs_after_replacement.<locals>._get_new_qspecf  su    e344U5G5GH)*:;;67BGBTBTUQ 5a 8UU&&u;KLLL  Vs   A7r   N)r   r   r   r   r1   output_qspec)r   r   r   
annotation
input_noder   r   s    `    @r8   (_update_special_qspecs_after_replacementr   H  s    WJ W"2  !		145J'77==? G
E1?1F
"":.G,Z-D-DEJr:   mc                    t        d | j                  j                  D              }|s| S t        j                  j                         rddgndg}|D ]  }t        | t        j                  t        |      } t        | t        j                  t        |      } t        | t        j                  t        |      } t        | t        j                  t        |      }  | S )Nc              3   2   K   | ]  }t        |        y wr   r   r   r   s     r8   r   z$_fuse_conv_bn_qat.<locals>.<genexpr>y       7AQ7   TFr"   )anygraphr   r,   r4   is_available_fuse_conv_bn_qat_helperrE   conv1dr   conv2dr   conv_transpose1dconv_transpose2d)r   has_bnis_cuda_optionsr"   s       r8   _fuse_conv_bn_qatr  x  s    777F',zz'>'>'@tUmugO" 
$qxx2G
 %qxx2G
 %q!!#<g
 %q!!#<g

 Hr:   example_inputs.c                    | j                   j                          | j                          t        |      }t	        |||      }t        |      }t	        |||      }t        | ||t        gd      }| j                          t        |      }	t	        |	||      }
t        | ||
t        gd      }| j                          i }||z   D ]\  }t        |      j                         D ]>  \  }}|j                  |_        t        |      rt        ||       t        ||       |||<   @ ^ | j                   j                   D ]  }t#        ||        | S )aU  
    Given a graph of decomposed aten ops, replace the (conv + bn) pattern with
    the fused QAT subgraph equivalent. The input graph should already be annotated.
    The annotations in the original nodes will be preserved in the corresponding
    nodes in the new subgraph.

    Note: This also handles the (conv + bn + relu) pattern.
    T)match_filtersignore_literals)r	  eliminate_dead_code	recompilerI   r   r^   r   r   rb   r   r   r   r   r   r   r   r   r   )r   r;   r  r"   conv_bn_patternmatch_patternqat_conv_bn_pattern"replacement_pattern_with_conv_biasreplacements_with_conv_bias qat_conv_bn_pattern_no_conv_bias replacement_pattern_no_conv_biasreplacements_no_conv_bias!all_original_to_replacement_nodesr   r   r   r   s                    r8   r  r    s    GG!KKM*73O6M 37;)K*&
 #?	*,-# KKM (MW'U$'I(($
 !=	(+,! KKM( )+%(+DD P/I!/L/S/S/U 
	P+M+$1$6$6!.}=,]<LM>!#3 @P-m<
	PP WW]] W04UVW Hr:   c           	      b   t         j                  j                  j                  }| j                  j
                  D ]  }|j                  dk7  s'|j                  |k7  st        |j                        dk(  r:t        |j                        D ]j  }| j                  j                  |      5  | j                  j                  d||j                  |j                        }ddd       |j                  |       l | j                  j!                  |        | j#                          y# 1 sw Y   KxY w)a{  
    Helper function to duplicate all dequantize nodes in the graph if the
    node has more than one user. For example:

    Before:
      quantize -> dequantize -> a
                          \--> b
                          \--> c

    After:
      quantize -> dequantize_1 -> a
            \--> dequantize_2 -> b
            \--> dequantize_3 -> c

    This is useful for subgraph rewriting. E.g. if we wish to match the
    pattern [dequantize - a] above, subgraph matching would fail because
    the dequantize node has users outside the matched portion of the graph.
    Instead, we match [dequantize_1 - a], which is safe.
    r   r   N)r,   rf   rg   rk   r	  r   r   r   rQ   usersr   inserting_beforecreate_noder   r5   replace_input_with
erase_noder  )r   dq_opr   userr   s        r8   _duplicate_dequantize_noder*    s    ( II**@@EWW]] 44?"ahh%&73qww<1;LM 	1D))!, Y77..qvvqxxXY##Ax0	1 	
1 KKM	Y Ys   (3D%%D.c                 Z   t         j                  j                  j                  }| j                  j
                  D ]  }|j                  D cg c]"  }|j                  dk(  r|j                  |k(  r|$ }}t        |      dkD  sI| j                  j                  |d         5  | j                  j                  d||d   j                  i       }ddd       |D ].  }|j                         | j                  j                  |       0  | j                          yc c}w # 1 sw Y   TxY w)a  
    Removes duplicate dequant nodes in the graph, for an operator that has
    multiple dequant nodes as a user, replace them with a single dequant node
    that can be shared across all the uses. This should be seen as the "reverse"
    of `_duplicate_dequantize_node`.
    r   r   r   N)r,   rf   rg   rk   r	  r   r#  r   r   rQ   inserting_afterr%  r   replace_all_uses_withr'  r  )r   r(  r   r)  dq_usersr   dq_users          r8   _remove_extra_dequantizer0    s    II**@@EWW]] , 
ww/)dkkU.B 
 

 x=1((!5 77..#UHQK,<,<b $ ,--h7""7+,, KKM
 s   'D",D!!D*	c                 `   | j                   |j                   k(  sJ | j                   t        j                  j                  j                  j
                  t        j                  j                  j                  j
                  fv rd}n| j                   t        j                  j                  j                  j
                  t        j                  j                  j                  j
                  fv rd}nt        d| j                    d      |j                  d| | j                  |d z   |_
        y)z
    Given a pair of quantize or dequantize nodes, copy over all literal args
    from the original node to the replacement node.
    r   r   z)Expected quantize/dequantize nodes, got ''N)r   r,   rf   rg   rj   r   rk   rh   ri   r   r   )r   r   start_copy_arg_indexs      r8   _copy_over_q_dq_argsr4  (  s    #3#:#::::		&&::BB		&&<<DD  
  !					&&;;CC		&&==EE" 

  !78L8L7MQO
 	
 	334


12
3	4 r:   c                    t        d | j                  j                  D              }|s| S t        j                  j                         rddgndg}|D ]  }t        | t        j                  t        |      } t        | t        j                  t        |      } t        | t        j                  t        |      } t        | t        j                  t        |      }  | j                  j                  D ]  }|j                  t        j                  j                   j"                  j$                  k(  s?|j&                  d   j(                  dk(  s\|j&                  d   dk(  sot        j*                  j,                  j.                  j0                  |j2                  d   D cg c]  }|d   	 c}v s| j                  j5                  |        | j                  j7                          | j9                          | S c c}w )	Nc              3   2   K   | ]  }t        |        y wr   r  r  s     r8   r   z$_fold_conv_bn_qat.<locals>.<genexpr>G  r  r  TFr  r   get_attrr   source_fn_stack)r  r	  r   r,   r4   r
  _fold_conv_bn_qat_helperrE   r  #_quantized_conv1d_bn_example_inputsr  #_quantized_conv2d_bn_example_inputsr  r  r   rf   atenadd_r3   r   r   nnmodules	batchnormBatchNorm2dr   r'  r  r  )r   r  r  r"   r   vals         r8   _fold_conv_bn_qatrC  F  s   777F',zz'>'>'@tUmugO" 
$qxx<g
 %qxx<g
 %q!!#FPW
 %q!!#FPW

  %KK599>>..555		!:-		!!  **66"&)),=">?3A?@ GGt$% GG!KKMH @s   G8c           	         | j                   j                          | j                          t        |        g }t	        j
                  ddgddgddgddg      }|D ]r  \  }}}}	|s|rt        ||||      }
t        |||||	      }t        |||fi |
}t        |||||	      }t        |||fi |
}|j                  t        | ||d             t | j                          t        |        |D ]  }t        |      }|j                         D ]  \  }}|j                  |_         t!        |d     t!        |d     d|v rd|v sJ t!        |d     t!        |d     d}|d	   \  }}|d
   \  }}|d   \  }}d|v r|d   \  }}t#        |||||        t%        |j&                        j                         D ]  }t)        |      st+        ||         | j                   j                          | j                          | S )zn
    Replace the quantized (conv + bn) pattern with conv with bn weights folded into the weights of conv.
    TF)r  r   r   r   r   Nr   r   r>   r+   )r	  r  r  r*  	itertoolsproductr9   r{   r   r   extendr   r0  r   r   r   r4  r   r   r   r   r   )r   r;   r  r"   r   replacement_optionsr   r    r!   rv   r5   r  replacement_patternr   node_mapr   r   r+   r   r   r   r>   s                         r8   r9  r9  j  s~    GG!KKMq! L#++	u	u	u	u	 
 
 	 -=H&7
 ;H&7.
 ;>7
6<
 HH&7.
 A
<B
 	(# $		
3 
B KKMQ G-a0 08/@ 	7+M+$1$6$6!	7 	h78h'789H$!X--- (="9: (>":; 	!&)I~G#M2K("%k2NQ	&y+y'STU /q{{;BBD 	GM.}=,]IF	G3G: GG!KKMHr:   )Gr   rE  r   typingr   r   r   r   r   r   r	   r,   torch.nn.functionalr>  
functionalrE   $torch.ao.quantization.fx._decomposedr
   'torch.ao.quantization.pt2e.export_utilsr   torch.ao.quantization.quantizerr   r   r   r   torch.fxr   r   r   torch.fx.subgraph_rewriterr   r   utilsr   r   r   r   r   r   r   6torch.fx.passes.utils.matcher_with_name_node_map_utilsr   __all__r0   r:  r;  boolstrr9   rI   r^   rb   ru   r{   r   r   r   r   r   r   r   r   r   r   r  r  r*  r0  r4  rC  r9   r:   r8   <module>rY     s      L L L    I B  . - U   T

 EKK1aEKK1aEKKNEKKNEKKNEKKN' # EKK1aEKK1aEKKNEKKNEKKNEKKN' #  	
 
#s(^8,( ,x ,((0h (08 (0V%=8 %= %=P8A:A:A: A: 	A:
 A: A:H3A3A3A 3A 	3A
 3A 3AlNNN N 
	N	K	K	K 	K 
		KD T d t {"2 {tCtTzAR<R7S {|dDj!1 d4:6F &A A A2WW+/W@-F
-F"&tTz"2-F`  *___ #s(O_ 	_
 _D+ @ 2  <! ! !HXXX #s(OX 	X
 Xr:   