
    iF                     F   S r SSKrSSKJr  SSKJrJrJrJrJ	r	  SSK
r
SSKJr  SSKJr  SSKJr  SSKJrJr  SS	KJr  SS
KJr  SSKJr  SSKJrJrJr  SSKJrJ r   SSK!J"r#  SSK$J%r%  SSK&J'r'  SSK(J)r)  SSK*J+r+J,r,  SSK-J.r.  \R^                  " \05      r1S\
Rd                  Rf                  Rh                  S\54S jr6S\
Rd                  Rh                  S\54S jr7S\
Rd                  Rh                  S\54S jr8S\
Rd                  Rf                  Rh                  S\54S jr9S\
Rd                  Rf                  Rh                  S\54S jr:S\
Rd                  Rf                  Rh                  S\54S jr;S\
Rd                  Rh                  S\<S\54S jr=S\<S\,S \ SS4S! jr> " S" S#\5      r?g)$a  Provide a partitioner for delegating subgraphs to the TOSA backend.

Implement logic to identify and tag regions of an ``ExportedProgram`` that can
be delegated to the TOSA backend. Use this module to:

- Partition graphs based on operator support and additional checks.
- Prune trivial no-op partitions that would lower to empty TOSA graphs.
- Tag constant data and report reasons for rejected nodes.

    N)count)CallableListOptionalSequenceTuple)get_first_fake_tensor)calculate_multiples)ensure_type)DQ_OPSQ_OPS)tosa_support_factory)TOSABackend)TosaCompileSpec)DelegationSpecPartitionerPartitionResult)tag_constant_dataWhyNoPartitionReporter)ops)get_cond_while_submodules)ExportedProgram)GraphModule)CapabilityBasedPartitioner	Partition)OperatorSupportBasenodereturnc                 x    U R                   [        R                  R                  R                  R
                  :H  $ N)targetexir_opsedgedim_order_ops_clone_dim_orderdefaultr   s    g/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/executorch/backends/arm/tosa/partitioner.py_is_noop_cloner)   1   s'    ;;(--55FFNNNN    c                 x    U R                   [        R                  R                  R                  R
                  :H  $ r    )r!   r"   r#   aten
alias_copyr&   r'   s    r(   _is_noop_alias_copyr.   5   s'    ;;(--,,77????r*   c                 x    U R                   [        R                  R                  R                  R
                  :H  $ r    )r!   r"   r#   r,   detach_copyr&   r'   s    r(   _is_noop_detach_copyr1   9   s'    ;;(--,,88@@@@r*   c                 @   U R                   [        R                  R                  R                  R
                  :w  a  g[        [        R                  R                  U R                  S   5      nU R                  R                  S5      [        U5      R                  :H  $ )NFr   dtype)r!   r"   r#   r$   _to_dim_order_copyr&   r   torchfxNodeargsmetagetr	   r3   )r   
input_nodes     r(   _is_noop_to_dim_order_copyr<   =   sg    {{hmm11DDLLL 		!=
yy}}W%)>z)J)P)PPPr*   c                     U R                   [        R                  R                  R                  R
                  :w  a  g[        U R                  5      u  p[        S U 5       5      =(       a    U(       + $ )NFc              3   *   #    U  H	  oS :H  v   M     g7f)   N ).0ms     r(   	<genexpr>"_is_noop_expand.<locals>.<genexpr>J   s     )y!Avys   )	r!   r"   r#   r,   expand_copyr&   r
   r8   all)r   	multipleschanges_ranks      r(   _is_noop_expandrI   E   sQ    {{hmm((44<<<"5dii"@	)y))>,.>>r*   c                 x    U R                   [        R                  R                  R                  R
                  :H  $ r    )r!   r"   r#   r,   	view_copyr&   r'   s    r(   _is_view_copyrL   M   s'    ;;(--,,66>>>>r*   tagc                 R    SU R                   ;   =(       a    U R                   S   U:H  $ )zReturn True if the node currently belongs to the partition ``tag``.

Args:
    node (torch.fx.Node): FX node to check.
    tag (str): Delegation tag identifying the partition.

Returns:
    bool: True if the node carries the matching delegation tag.

delegation_tag)r9   )r   rM   s     r(   is_partitionedrP   Q   s'     tyy(OTYY7G-HC-OOr*   reason	partitionreporterc                     UR                    H4  nSUR                  ;   d  M  UR                  S	 UR                  UU 5        M6     g)a+  Remove a proposed partition and record the rejection reason.

Args:
    reason (str): Human-readable explanation for rejection.
    partition (object): Proposed partition object from the
        capability partitioner.
    reporter (WhyNoPartitionReporter): used to report why nodes were rejected.

rO   N)nodesr9   report_reject)rQ   rR   rS   r   s       r(   reject_partitionrW   b   s?     tyy(		*+""  r*   c                       \ rS rSrSr SS\S\\\      SS4S jjr	S\
S	\S
\SS4S jr SS\
S\S
\S\S-  S\\   4
S jjrS\S\4S jrS\S\\\R.                  R0                     \\\R4                  R6                  /\4      4   4S jrSrg)TOSAPartitionerw   a  Partition an exported program into TOSA-delegable subgraphs.

Construct this partitioner for compile specs targeting TOSA. The partition
algorithm uses capability checks and optional additional operator-support
rules to tag nodes with a delegation tag per subgraph.

Ncompile_specadditional_checksr   c                     [        [        R                  UR                  5       5      U l        UR
                  U l        X l        g)ax  Initialize the TOSAPartitioner.

Args:
    compile_spec (TosaCompileSpec): Parsed compile specifications for
        TOSA containing the TOSA spec and original list.
    additional_checks (Optional[Sequence[OperatorSupportBase]]): Extra
        operator-support checks to apply when partitioning.

Raises:
    RuntimeError: If the provided compile spec does not target TOSA.

N)r   r   __name__to_listdelegation_spec	tosa_specr\   )selfr[   r\   s      r(   __init__TOSAPartitioner.__init__   s:    "  .  ,"6"6"8 
 &//!2r*   modulerM   rS   c                   ^ UR                   R                   GH6  n[        UT5      (       d  M  UR                  [        ;   nUR                  [
        ;   nU=(       a    [        UR                  S   T5      (       + nU=(       a    [        U4S jUR                   5       5      nU(       d  U(       a  UR                  S	 M  U(       a  M  U(       a  M  UR                   Hk  n	[        U	T5      (       a  M  [        U	5      R                  R                  (       d  M<  UR                  USU	R                   S35        UR                  S	   GM4     GM9     g)a  De-tag nodes at the partition boundary.

Remove delegation tags from quantize nodes with inputs outside the
partition and from dequantize nodes with outputs outside the partition.

For non Q/DQ nodes, remove the tag from the first node in the partition
if any input has floating-point dtype.

Args:
    tag: The delegation tag assigned to the partition.
    reporter: A reporter to log rejected nodes.
    module: The GraphModule containing the partition.

r   c              3   F   >#    U  H  n[        UT5      (       + v   M     g 7fr    )rP   )rA   userrM   s     r(   rC   8TOSAPartitioner._detag_boundary_nodes.<locals>.<genexpr>   s!      5:D$N4---*s   !rO   z&Was first node in partition and input z had fp dtype.N)graphrU   rP   r!   r   r   all_input_nodesanyusersr9   r	   r3   is_floating_pointrV   name)
rb   re   rM   rS   r   	is_q_node
is_dq_nodeis_boundary_q_nodeis_boundary_dq_nodeinputs
     `       r(   _detag_boundary_nodes%TOSAPartitioner._detag_boundary_nodes   s   ( LL&&D!$,,u,I.J!* ">$$Q'4 0 #- # 5:>**5 2 "%8 II./Yzz!11E%eS11 ,U399KKK .. DUZZLP^_ !II&67 2' 'r*   containing_programtag_iteratorc                    [        5       nUc  [        S5      n[        U5       H8  u  pgnU R                  XrX45      n[	        XX-  5      S:w  a  [        S5      eXX-  nM:     [        U R                  X#U R                  5      n	[        UU	SS9n
U
R                  5       nU H  nS[        U5       3nUR                  U5        UR                   H  nXR                  S'   M     U R                  R                  5       (       a2  U R                  R!                  5       (       d  U R#                  UUU5        [%        S UR                   5       5      nU(       d  M  ['        SUU5        UR)                  U5        M     U$ )	aG  Tag nodes in a module or submodule from the containing program.

Args:
    module: A GraphModule from `containing_program` to tag nodes in.
    containing_program: The ExportedProgram that contains the module.
    reporter: A reporter to report why nodes were rejected.

Returns:
    A set of strings with the partition tags.

r   zEGot overlapping tags in two different modules, this shouldn't happen.T)allows_single_node_partitionrM   rO   c              3   0  #    U  H  n[        U5      =(       du    [        U5      =(       dc    [        U5      =(       dQ    [        U5      =(       d?    [	        U5      =(       d-    UR
                  [        ;   =(       d    UR
                  [        ;   v   M     g 7fr    )r)   r.   rI   r<   rL   r!   r   r   )rA   r   s     r(   rC   .TOSAPartitioner._tag_module.<locals>.<genexpr>  s      	) ,D t$ )&t,)"4() .d3) !&	)
 ;;%') ;;&() ,s   BBzcPartition contained only ops which are removed in the TOSA lowering, leading to an empty partition.)setr   r   _tag_modulelenRuntimeErrorr   ra   r\   r   propose_partitionsnextaddrU   r9   support_integersupport_floatru   rF   rW   remove)rb   re   rw   rS   rx   tags_	submodulesubmodule_tagsoperator_supportcapability_partitionerpartition_listrR   rM   r   is_nocompute_partitions                   r(   r~   TOSAPartitioner._tag_module   s   $  8L8@OA!!--xN 4()Q."[  (D  A 0NN.$:P:P
 "<)-"

 0BBD'I\*+,CHHSM!.1		*+ ( ~~--//8T8T8V8V** &) 	) &OO	) 	&" &% y
 C A (B r*   exported_programc                    [         R                  S5        [         R                  SU R                  R                   SU R                   35        [        5       nU R                  UR                  X5      nU Vs0 s H  oDU R                  _M     nn[        U5        [         R                  SU R                   S35        [         R                  SUR                  5       -   5        [         R                  S5        [        XS9$ s  snf )	a  Partition the program and tag TOSA-compatible subgraphs.

Run the FX capability-based partitioner to propose subgraphs, then
refine tags by removing boundary-only quantize/dequantize nodes and by
rejecting partitions that would lower to no-ops. Emit a detailed report
of rejected nodes and their reasons.

Args:
    exported_program (ExportedProgram): Program to analyze and
        partition.

Returns:
    PartitionResult: The input program with nodes tagged for delegation
    and a mapping of partition tags to delegation specs.

zTOSAPartitioner::partitionzPartitioning for z: z&The following nodes were rejected for :
z8(Placeholders and outputs are not included in this list))tagged_exported_programpartition_tags)loggerinfor`   
backend_idra   r   r~   graph_moduler   get_table_reportr   )rb   r   rS   r   rM   r   s         r(   rR   TOSAPartitioner.partition  s    " 	01 4 4 ? ?@4>>BRS	
 *+))+;
 @DDtt333tD*+<T^^<LANOD844667NO$4
 	
 Es   9Depc                 l  ^ ^^^^ [         R                  R                  R                  R                  [         R                  R                  R
                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  1m[         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  1m[         R                  R                  R                  R                  1m[         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  [         R                  R                  R                  R                  1mS[         R                  R                  S[        4UUUUU 4S jjn[        TT-  T-  T-  5      nT R                   R"                  (       dz  UR%                  [         R                  R                  R&                  R(                  5        UR%                  [         R                  R                  R*                  R(                  5        X24$ )aO  Return operators and a filter that should not be decomposed.

Provide a base set of ops to preserve as-is and a predicate that keeps
certain activations whole when surrounded by quantize/dequantize ops in
a quantized graph. This helps downstream TOSA lowering and delegation.

Args:
    ep (ExportedProgram): Program used to infer target-specific policy.

Returns:
    Tuple[List[torch._ops.OpOverload], Optional[Callable[[torch.fx.Node], bool]]]:
        A list of op overloads to keep intact, and an optional filter
        function that returns True when an op should not be decomposed.

r   r   c                 t  > TR                   R                  5       (       a  U R                  T;   a  g[        R                  R
                  R                  R                  [        R                  R
                  R                  R                  4n[        R                  R
                  R                  R                  [        R                  R
                  R                  R                  4nU R                  T;   Ga(  SnSnU R                  nU R                  nU H  nUR                  U;  d  M  SnM     U H  nUR                  U;  d  M  SnM     U R                  [        R                  R                  R                  R                  :X  a  [        U5      S:X  ax  [!        U5      S   R                  [        R                  R                  R"                  R                  [        R                  R                  R$                  R                  4;   a  SnU(       a  U(       a  gU R                  T;   a  ['        U 5      R(                  n	U	R*                  (       d  U	R,                  (       d  gU R                  nU Hz  n
U
R                  [        R                  R                  R.                  R(                  :w  a    g['        U
5      R(                  nUR,                  (       d  UR*                  (       d  Mz    g   gU R                  T;   a   TR                   R                  5       (       a  gU R                  T;   a  gg)aB  Filter function applied to ops in 'ops_to_not_decompose'. Returns
True if the op should not be decomposed. If this function returns
True, the partitioner *must* accept the node, or the lowering fails.

Args:
    node (torch.fx.Node): FX node to evaluate.

Returns:
    bool: True to keep the op intact; otherwise, False.

TFr?   r   )ra   r   r!   r5   r   quantized_decomposeddequantize_per_tensorr&   dequantize_per_channelquantize_per_tensorquantize_per_channelrk   rm   r,   linearr   listreluhardtanhr	   r3   rn   
is_complexto)r   dqqcorrect_output_quantcorrect_input_quantinput_nodesoutput_nodesinpoutr3   rh   
cast_dtypeops_to_not_decompose_alwaysops_to_not_decompose_if_fpops_to_not_decompose_if_integer ops_to_not_decompose_if_quant_oprb   s               r(   	filter_fn7TOSAPartitioner.ops_to_not_decompose.<locals>.filter_fnd  s[    ,,..KK#== 		..DDLL		..EEMMB
 		..BBJJ		..CCKKA
 {{>>'+$&*#"22#zz&Czz+.3+ ' (Czz*/4, (
 KK599>>#8#8#@#@@L)Q.\*1-44		++33UYY^^5L5L5T5TUV ,0(&+?{{== .d399..u7G7G#zz(D{{eiinn&7&7&=&==$%:4%@%F%F
%00J4P4P4P#( ) {{88>>//11{{99r*   )r5   r   r,   eyer&   hardsigmoid	hardswishr   linspacesilusilu_logitr6   r7   boolr   ra   is_U55_subsetappendupsample_nearest2dvecupsample_bilinear2d)rb   r   r   ops_to_not_decomposer   r   r   r   s   `   @@@@r(   r   $TOSAPartitioner.ops_to_not_decompose8  sH   ( IINN&&IINN&&..IINN$$,,IINN!!))IINN##++IINN''IINN  ((,
( IINN&&IINN  ((IINN!!))IINN##++	&
" IINN  (('
# IINN&&IINN##++IINN''IINN  ((	+
'P	EHHMM P	d P	 P	d  $'./() .. 
 ~~++ !''		(I(I(M(MN ''		(J(J(N(NO$00r*   )r\   r`   ra   r    )r^   
__module____qualname____firstlineno____doc__r   r   r   r   rc   r   strr   ru   r   r   r}   r~   r   rR   r   r   r5   _ops
OpOverloadr   r6   r7   r   r   __static_attributes__r@   r*   r(   rY   rY   w   s	    FJ3%3 $H-@$AB3 
	3.0!0(+07M0	0n &*II ,I )	I
 dlI 
SIV"
/ "
o "
HN1N1 
tEJJ))*HXuxx}}ot>S5T,UU	VN1r*   rY   )@r   logging	itertoolsr   typingr   r   r   r   r   r5   .executorch.backends.arm._passes.arm_pass_utilsr	   =executorch.backends.arm._passes.convert_expand_copy_to_repeatr
   #executorch.backends.arm.common.typer   !executorch.backends.arm.constantsr   r   Aexecutorch.backends.arm.operator_support.tosa_supported_operatorsr   $executorch.backends.arm.tosa.backendr   )executorch.backends.arm.tosa.compile_specr   #executorch.exir.backend.partitionerr   r   r   executorch.exir.backend.utilsr   r   executorch.exir.dialects._opsr   r"   executorch.exir.graph_moduler   torch.export.exported_programr   torch.fxr   !torch.fx.passes.infra.partitionerr   r    torch.fx.passes.operator_supportr   	getLoggerr^   r   r6   r   r7   r   r)   r.   r1   r<   rI   rL   r   rP   rW   rY   r@   r*   r(   <module>r      s  
	   < <  P < ; = E 
 T 9 B 9   S @			8	$O++ O O@ehhmm @ @Auxx}} A AQUXX]]%7%7 QD Q?%((--,, ? ??** ?t ?P
((--P	P 
P"%1G	*O1k O1r*   