Ë
    ÄÓ^jP ã                  ó¢	  — U d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl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mZ d dl m!Z! d dl"m#Z# dd	l$m%Z%m&Z& er"d d
l'm(Z(m)Z)m*Z* d dl+m,Z, d dl-m.Z. ddl/m0Z0 ddl1m2Z2 d dl3Z3d dl4Z4d dl5Z4d dl6m7c m8Z9 d dl:m;Z;m<Z< d dl=m>Z> d dl?m@Z@mAZA d dlBmCZC d dlDmEZEmFZF d dlGmHZH d dlImJZJ d dlKmLZL d dlMmNZNmOZOmPZP d dlQmRZR ddlSmTZTmUZUmVZVmWZWm$Z$mXZX ddlYmZZZ ddl[m\Z\m]Z]m^Z^ ddl_m`Z`maZa ddlWmbZbmcZcmdZdmeZe ddlfmgZgmhZh ddlimjZj dd l$mkZkmlZlmmZmmnZnmoZompZp dd!lqmrZr dd"lsmtZtmuZu dd#lvmwZwmxZx dd$lymzZzm{Z{m|Z| dd%l}m~Z~ dd&l7mZm€Z€m�Z�m‚Z‚mƒZƒm„Z„m…Z…m†Z†m‡Z‡mˆZˆm‰Z‰mŠZŠm‹Z‹mŒZŒm�Z�mŽZŽm�Z�m�Z�m‘Z‘ dd'l’m“Z“  e	�j(                  e•«      Z–e4�j.                  �j1                  e•d(«      Z™e4�j.                  �j1                  e•d)«      Zše4�j.                  �j1                  e•d*«      Z›e4�j.                  �j1                  e•d+«      Zœe�d,   Zžd-eŸd.<    ed/«      Z  e!d0«      Z¡e�jD                   G d1„ d2«      «       Z£e�jD                   G d3„ d4«      «       Z¤ G d5„ d6e«      Z¥ e�jD                  d7¬8«       G d9„ d:«      «       Z¦	 	 	 	 	 	 d}d;„Z§ G d<„ d=«      Z¨ G d>„ d?«      Z©e�jD                   G d@„ dA«      «       Zªe�jD                   G dB„ dCeª«      «       Z« G dD„ d,«      Z¬e�jZ                  d~dE„«       Z®ddF„Z¯	 	 	 	 d€dG„Z°d�dH„Z± e�jD                  d7¬8«       G dI„ dJ«      «       Z²d‚dK„Z³ G dL„ dM«      Z´	 	 	 	 	 	 	 	 dƒdN„Zµ G dO„ dPe¬«      Z¶ G dQ„ dRe¬«      Z· G dS„ dTe¬«      Z¸	 	 	 	 d„dU„Z¹	 	 	 	 	 	 	 	 d…dW„Zº G dX„ dYe¬«      Z» G dZ„ d[e»«      Z¼ G d\„ d]e»«      Z½ G d^„ d_e»«      Z¾ G d`„ dae»«      Z¿ G db„ dce¬«      ZÀ	 d†	 	 	 	 	 	 	 d‡dd„ZÁ	 	 	 	 	 	 dˆde„ZÂd‰df„ZÃ	 	 	 	 	 	 	 	 	 	 	 	 dŠdg„ZÄ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d‹dh„ZÅe�jD                   G di„ dj«      «       ZÆ e�jŽ                  «       ZÈdŒdk„ZÉ	 	 	 	 d�dl„ZÊdŽdm„ZËd7dnœ	 	 	 	 	 d�do„ZÌ	 	 	 	 	 	 d�dp„ZÍdŽdq„ZÎd‘dr„ZÏd‘ds„ZÐd‘dt„ZÑd‘du„ZÒe�jD                   G dv„ dw«      «       ZÓe�jD                   G dx„ dy«      «       ZÔ G dz„ dV«      ZÕ G d{„ d|«      ZÖy)’é    )ÚannotationsN)ÚCounterÚdefaultdict)Úas_completedÚFuture)ÚAnyÚGenericÚLiteralÚ
NamedTupleÚoverloadÚTYPE_CHECKINGÚ	TypeAliasÚTypeVar)Ú	ParamSpec©Ú
OrderedSeté   )ÚComputedBufferÚ	Pointwise)ÚCallableÚIteratorÚSequence)Ú
ModuleType)ÚEnterCudaStreamContextLine)ÚPythonWrapperCodegen)ÚCoalesceVarAnalysis)ÚcountersÚdynamo_timed)Úuse_pipelined_autotuning)ÚLambdaFutureÚPyCodeCache)ÚTritonTemplateCallerBase)Úget_metric_tableÚis_metric_table_enabled)Úget_stream_name)Úfree_symbols)ÚFloorDiv)Úfree_symbol_is_typeÚsymbol_is_typeÚSymT)Ú
has_triton)ÚcommsÚconfigÚconfig_commsÚdependenciesÚirÚmetrics)Úcan_codegen_without_upcasts)ÚBackendFeatureÚget_scheduling_for_deviceÚKernel)Ú estimate_nccl_collective_runtimeÚ/estimate_nccl_collective_runtime_nccl_estimator)ÚDepÚ	MemoryDepÚStarDepÚWeakDep)ÚGPUTooOldForTritonÚTritonMissing)Úcount_flops_fx)Úassign_origin_nodeÚget_device_typeÚGraphPartitionSignatureÚMultiOutputÚMultiOutputLayoutÚ
NoneLayout)ÚLoopBody)ÚMemoryPlanningInfoForBufferÚMemoryPlanningInfoForNode)ÚDevicePropertiesÚReductionHint)Ú
green_textÚis_power_of_2Úred_text)ÚSimplifyIndexing)Ú&_unstable_customized_partition_wrapperÚcache_on_selfÚcmpÚdevice_need_guardÚget_current_backendÚget_device_tflopsÚget_dtype_sizeÚget_gpu_dram_gbpsÚget_op_namesÚGraphPartitionMapÚIndentedBufferÚis_collectiveÚis_cudagraph_unsafe_opÚis_gpuÚis_multi_outputs_templateÚ#is_output_of_multi_outputs_templateÚis_waitÚsympy_productÚ
sympy_subs)ÚVÚfusionÚloop_orderingÚcompute_dependenciesÚ
cudagraphsÚBaseSchedulerNoder   ÚPartitionTypeÚ_TÚ_Pc                  ól   — e Zd ZU dZded<   dZded<   dZded<   d„ Zedd	„«       Z	e	 d	 	 	 dd
„«       Z
y)ÚFusionResultNzbool | NoneÚshould_fusezCallable[[], bool] | NoneÚcallable_fnúLambdaFuture | NoneÚfuturec                óL   — | j                   d u| j                  d uz  sJ d«       ‚y )NzLFusion result should contain either fusion decision or callable_fn, not both)rl   rm   ©Úselfs    úd/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/torch/_inductor/scheduler.pyÚ__post_init__zFusionResult.__post_init__‚   s0   € Ø× Ñ ¨Ð,°×1AÑ1AÈÐ1MÒNð 	
ØZó	
ÑNó    c                ó   — t        |¬«      S )N)rl   ©rk   )Úclsrl   s     rs   ÚfusezFusionResult.fuse‡   s   € ä¨Ô4Ð4ru   c                ó   — t        ||¬«      S )N©rm   ro   rw   )rx   rm   ro   s      rs   Úfrom_callablezFusionResult.from_callable‹   s   € ô ¨¸FÔCÐCru   )rl   Úbool©N)rm   úCallable[[], bool]ro   rn   )Ú__name__Ú
__module__Ú__qualname__rl   Ú__annotations__rm   ro   rt   Úclassmethodry   r|   © ru   rs   rk   rk   |   sf   … à#€K�Ó#Ø-1€KÐ*Ó1Ø"&€FÐÓ&ò
ð
 ò5ó ð5ð àLPðDØ,ðDØ6IòDó ñDru   rk   c                  óB   — e Zd ZU ded<   ded<   ded<   dZded<   d
d	„Zy)ÚPendingFusionr   rm   rf   Únode1Únode2Nrn   ro   c                ó2   — | j                   | j                  fS r~   ©rˆ   r‰   rq   s    rs   Úget_fusion_nodeszPendingFusion.get_fusion_nodes™   s   € Ø—
‘
˜DŸJ™JÐ'Ð'ru   )Úreturnú+tuple[BaseSchedulerNode, BaseSchedulerNode])r€   r�   r‚   rƒ   ro   rŒ   r…   ru   rs   r‡   r‡   ’   s$   … à#Ó#ØÓØÓØ"&€FÐÓ&ô(ru   r‡   c                  ó0   — e Zd ZU dZded<   ded<   ded<   y)Ú_LocalEntryzåOne row of the post-rewrite slice the gate builds.

    `cur` is the step the node currently wants to run at, `baseline`
    is its original index (used to break ties when sorting), and
    `node` is the slice member itself.
    ÚintÚcurÚbaselinerf   ÚnodeN)r€   r�   r‚   Ú__doc__rƒ   r…   ru   rs   r�   r�   �   s   … ñð 
ƒHØƒMØ
Ôru   r�   T)Úslotsc                  ór   — e Zd ZU dZded<   ded<   dZded<   dZded	<    ej                  e	¬
«      Z
ded<   y)ÚComboKernelMemoryContexta  Shared state used by the memory-aware combo gate.

    Candidate windows are evaluated independently against the original
    schedule. Earlier accepted combos only contribute through `running_peak`,
    which caps the cumulative peak drift from the original graph.
    úOrderedSet[str]Úgraph_outputsúdict[BaseSchedulerNode, int]Únode_to_idxr   r‘   Úbaseline_peakÚrunning_peak©Údefault_factoryú	list[int]Úbaseline_live_beforeN)r€   r�   r‚   r•   rƒ   r�   rž   ÚdataclassesÚfieldÚlistr¢   r…   ru   rs   r˜   r˜   ª   sE   … ñð #Ó"Ø-Ó-Ø€M�3Óð €L�#Óð '8 k×&7Ñ&7ÈÔ&MÐ˜)ÔMru   r˜   c                ó    — | j                  «       r|j                  «       sy| j                  «       j                  }|dv xr t        |«      dk(  S )NF)ÚcudaÚxpuÚtriton)r[   Ú
get_deviceÚtyperR   )rˆ   r‰   Údevice_types      rs   Ú_is_gpu_triton_backendr­   À   sI   € ð �<‰<Œ> §¡¤ØØ×"Ñ"Ó$×)Ñ)€Kà�Ð&ÒWÔ+>¸{Ó+KÈxÑ+Wðru   c                  ó$  — e Zd ZdZedd„«       Zedd„«       Ze	 	 	 	 	 	 dd„«       Zedd„«       Z	e	 	 	 	 	 	 dd„«       Z
e	 	 	 	 	 	 dd„«       Zedd„«       Ze	 	 	 	 	 	 dd	„«       Zedd
„«       Ze	 	 	 	 	 	 dd„«       Zedd„«       Zedd„«       Zy)ÚMixOrderReductionz™
    This class contains utility functions to decide if we should fuse reductions
    reducing across different dimensions of the same input tensor.
    c                óf   — | j                  «       xr  t        d„ | j                  «       D «       «      S )Nc              3  óÀ   K  — | ]V  }t        |t        «      rD|j                  «       r4t        |j                  t        «      r|j                  j
                  d u–— ŒX y ­wr~   )Ú
isinstanceÚSchedulerNodeÚis_reductionr”   r   Ú_split_size©Ú.0Úsubnodes     rs   ú	<genexpr>z7MixOrderReduction.is_split_reduction.<locals>.<genexpr>Ô   sK   è ø€ ò +
àÜ˜'¤=Ô1Ø×$Ñ$Ô&Ü˜7Ÿ<™<¬Ô8ð	 �L‰L×$Ñ$¨DÔ0ñ+
ùs   ‚AA)r´   ÚallÚ	get_nodes©r”   s    rs   Úis_split_reductionz$MixOrderReduction.is_split_reductionÒ   s3   € à× Ñ Ó"ò 
¤sñ +
àŸ>™>Ó+ô+
ó (
ð 	
ru   c                ó`  — | j                  |«      �rŽd }d }|j                  «       D �]n  }t        |t        «      r*|j	                  «       rt        |j
                  t        «      sŒ?|j
                  j                  €J ‚t        j                  j                  j                  t        |j
                  j                  «      «      }|j
                  j                  €J ‚t        j                  j                  j                  t        |j
                  j                  «      «      }|€|}|}�Œt        j                  j                  j                  ||«      sJ |› d|› �«       ‚t        j                  j                  j                  ||«      r�ŒeJ |› d|› �«       ‚ |€J ‚||fS |j                  d   S )Nú v.s. r   )r½   r»   r²   r³   r´   r”   r   Ú_original_rangesra   ÚgraphÚsizevarsÚsimplifyr_   Ú_original_reduction_rangesÚstatically_known_equalsÚgroup)rx   r”   ÚxnumelÚrnumelr¸   Ú	curxnumelÚ	currnumels          rs   Úget_numel_rnumelz"MixOrderReduction.get_numel_rnumelÜ   s‹  € à×!Ñ! $Õ'ØˆFØˆFØŸ>™>Ó+ó 4�ä˜w¬Ô6Ø×,Ñ,Ô.Ü" 7§<¡<´Ô@àà—|‘|×4Ñ4Ð@Ð@Ð@ÜŸG™G×,Ñ,×5Ñ5Ü! '§,¡,×"?Ñ"?Ó@ó�	ð —|‘|×>Ñ>ÐJÐJÐJÜŸG™G×,Ñ,×5Ñ5Ü! '§,¡,×"IÑ"IÓJó�	ð �>Ø&�FØ&’FäŸ7™7×+Ñ+×CÑCØ 	ôð 4à ˜ ¨	 {Ð3ó4ð ô Ÿ7™7×+Ñ+×CÑCØ 	öð 4à ˜ ¨	 {Ð3ó4ð ð14ð8 Ð%Ð%Ð%Ø˜FÐ#Ð#à—:‘:˜a‘=Ð ru   c                óÊ   — | j                  |«      }| j                  |«      }t        |«      dk7  st        |«      dk7  s||k(  ryt        |«      t        t        |«      «      k(  S )Né   F)rË   ÚlenÚtupleÚreversed)rx   rˆ   r‰   Úg1Úg2s        rs   Úhas_mix_reduction_ordersz*MixOrderReduction.has_mix_reduction_orders  sZ   € ð ×!Ñ! %Ó(ˆØ×!Ñ! %Ó(ˆäˆr‹7�aŠ<œ3˜r›7 aš<¨2°ª8Øä�R‹yœE¤(¨2£,Ó/Ñ/Ð/ru   c                óR  — d}|j                   j                  D ]&  }t        |t        «      sŒ|j                  |k(  sŒ$|} n |sy|j
                  }|j                   j                  }|sDt        |t        «      sJ t        |«      › «       ‚|j                  d   j                   j                  }|sJ ‚t        |«      t        |j                  «      z
  syt        j                  j                  j                  t!        |j"                  «      t!        |j%                  «       «      «      ryy)z@
        The access to 'buf' is not a broadcast access.
        NFr   T)Úread_writesÚreadsr²   r9   ÚnameÚindexÚ
var_rangesÚFusedSchedulerNoder«   Úsnodesr   r&   ra   rÁ   rÂ   rÅ   r_   ÚsizeÚvalues)rx   Úbufr”   Ú	found_depÚdeprØ   rÙ   s          rs   Ú_is_full_accessz!MixOrderReduction._is_full_access  sû   € ð
 ˆ	Ø×#Ñ#×)Ñ)ò 	ˆCÜ˜#œyÕ)¨c¯h©h¸#«oØ�	Ùð	ñ
 Øà—‘ˆØ×%Ñ%×0Ñ0ˆ
áÜ˜dÔ$6Ô7ÐH¼DÀ»J¸<ÓHÐ7ØŸ™ Q™×3Ñ3×>Ñ>ˆJáÐˆzÜ˜:Ó&¬°E×4FÑ4FÓ)GÒGØô
 �7‰7×Ñ×3Ñ3Ü˜)Ÿ.™.Ó)¬=¸×9JÑ9JÓ9LÓ+Mô
ð Øru   c                óÈ   — g }|j                  «       |j                  «       z  }|D ]9  }| j                  ||«      sŒ| j                  ||«      sŒ)|j                  |«       Œ; |S r~   )Úused_buffer_namesrá   Úappend)rx   rˆ   r‰   ÚoutÚcommon_readsrÞ   s         rs   Úget_common_readz!MixOrderReduction.get_common_read0  se   € ð ˆØ×.Ñ.Ó0°5×3JÑ3JÓ3LÑLˆØò 	 ˆCØ×"Ñ" 3¨Õ.°3×3FÑ3FÀsÈEÕ3RØ—
‘
˜3•ð	 ð ˆ
ru   c                ó>   — t        | j                  ||«      «      dkD  S ©Nr   )rÎ   rç   ©rx   rˆ   r‰   s      rs   Úhas_common_readz!MixOrderReduction.has_common_read<  s!   € ô �3×&Ñ& u¨eÓ4Ó5¸Ñ9Ð9ru   c                óŒ   — | j                  |«      }t        j                  j                  j	                  |d   |d   z  d¬«      S )Nr   r   ©Úfallback)rË   ra   rÁ   rÂ   Úoptimization_hint)rx   r”   rÑ   s      rs   Ú	get_numelzMixOrderReduction.get_numelB  s>   € à×!Ñ! $Ó'ˆÜ�w‰w×Ñ×1Ñ1°"°Q±%¸"¸Q¹%±-È!Ð1ÓLÐLru   c                ó$   — | j                  |«      S r~   )rð   rê   s      rs   Úget_fusion_scorez"MixOrderReduction.get_fusion_scoreG  s   € ð
 �}‰}˜UÓ#Ð#ru   c                ó  — t         j                  j                  syt        j                  j
                  ryt        ||«      sy|j                  «       r|j                  «       sy|j                  |j                  «       z  s|j                  |j                  «       z  ry| j                  ||«      syt        j                  ||«      }t        |«      dk(  ry| j                  |«      r||}}n| j                  |«      r||}}ny| j                  |«      }|\  }}t         j                  j                   sËd}	t        j                  j"                  j%                  t'        j(                  ||z  |	«      dd¬«      syt        j                  j"                  j%                  t'        j(                  ||dz  «      dd¬«      syt        j                  j"                  j%                  t'        j(                  |d«      dd¬«      syt+        d„ |j-                  «       D «       «      ryt        j                  j"                  j/                  |d	«      syt        j1                  |«      ryt3        d
„ |j-                  «       D «       «      }
|
S )zP
        Check whether we can fuse two reductions with mix loop orders.
        Fr   i  P T)Úsize_obliviousÚfallback_valuerÍ   i   c              3  ó¼   K  — | ]T  }|j                  «       rB|j                  j                  j                  t        j
                  t        j                  fv–— ŒV y ­wr~   )r´   r”   ÚdataÚreduction_hintrI   ÚINNERÚDEFAULTr¶   s     rs   r¹   z-MixOrderReduction.can_fuse.<locals>.<genexpr>Ÿ  sR   è ø€ ò 
ð Ø×#Ñ#Ô%ð �L‰L×Ñ×,Ñ,ä×#Ñ#Ü×%Ñ%ðôñ
ùs   ‚AAi @  c              3  ót   K  — | ]0  }|j                  «       r|j                  j                  «       d v –— Œ2 y­w)>   ÚsumÚprodN)r´   r”   Úget_reduction_typer¶   s     rs   r¹   z-MixOrderReduction.can_fuse.<locals>.<genexpr>µ  s=   è ø€ ò 
ð Ø×#Ñ#Ô%ð �L‰L×+Ñ+Ó-ðôñ
ùs   ‚68)r-   r©   Úmix_order_reductionra   rÁ   Úcpp_wrapperr­   r´   Ú	ancestorsÚget_operation_namesrÓ   r¯   rç   rÎ   Úis_contiguous_noderË   Ú#mix_order_reduction_non_strict_moderÂ   Úevaluate_exprÚsympyÚGeÚanyr»   Ústatically_known_leqr½   rº   )rx   rˆ   r‰   ræ   Úcontiguous_nodeÚ
other_noderÑ   ÚnrowÚncolÚ
size_thresrå   s              rs   Úcan_fusezMixOrderReduction.can_fuseO  sG  € ô
 �}‰}×0Ò0Øô �7‰7×ÒØä% e¨UÔ3ØØ×!Ñ!Ô#¨5×+=Ñ+=Ô+?Øà�O‰O˜e×7Ñ7Ó9Ò9Ø�O‰O˜e×7Ñ7Ó9Ò9ð ð ×+Ñ+¨E°5Ô9Øô )×8Ñ8¸ÀÓFˆÜˆ|Ó Ò!Øà×!Ñ! %Ô(Ø*/°˜Z‰OØ×#Ñ# EÔ*Ø*/°˜Z‰Oàà×!Ñ! /Ó2ˆØ‰
ˆˆdô �}‰}×@Ò@ð #ˆJô
 —7‘7×#Ñ#×1Ñ1Ü—‘˜ ™ jÓ1Ø#Ø$ð 2ô ð
 ô
 —7‘7×#Ñ#×1Ñ1Ü—‘˜˜t a™xÓ(Ø#Ø$ð 2ô ð
 ô
 —7‘7×#Ñ#×1Ñ1Ü—‘˜˜tÓ$Ø#Ø$ð 2ô ð
 ô ñ 
ð +×4Ñ4Ó6ô
ô 
ð ô
 �w‰w×Ñ×4Ñ4°T¸9ÔEØä×/Ñ/°Ô@Øô ñ 
ð &×/Ñ/Ó1ô
ó 
ˆð ˆ
ru   c                ó&   — | j                  ||«      S r~   )r  rê   s      rs   Úare_mix_order_reductionsz*MixOrderReduction.are_mix_order_reductionsÀ  s   € ð �|‰|˜E 5Ó)Ð)ru   c                ó\   ‡ ‡— t        ˆ ˆfd„‰j                  j                  D «       «      syy)Nc              3  óV   •K  — | ]   }‰j                  |j                  ‰«      –— Œ" y ­wr~   )Úis_contiguous_loadr×   )r·   rà   rx   r”   s     €€rs   r¹   z7MixOrderReduction.is_contiguous_node.<locals>.<genexpr>È  s'   øè ø€ ò 
Ø7:ˆC×"Ñ" 3§8¡8¨T×2ñ
ùó   ƒ&)FT)rº   rÕ   rÖ   )rx   r”   s   ``rs   r  z$MixOrderReduction.is_contiguous_nodeÆ  s,   ù€ äô 
Ø>B×>NÑ>N×>TÑ>Tô
ô 
ð Øru   c                ó  — ddl m} |j                  «       D ]ë  }t        |t        «      sJ ‚|j
                  }|j                  |j                     }|D �cg c]  }|j                  |k(  sŒ|j                  ‘Œ  }}t        |«      dk(  rŒr|D ]u  }	|j                  |	   }
|j                  }t        |j                  «       «      }t        j                   j"                  j%                  |
||«      }|d   dk(  rŒk|d   dk(  rŒt  y Œí yc c}w )Nr   ©ÚMemoryUsageTypeéÿÿÿÿr   FT)Útorch._inductor.loop_bodyr  r»   r²   r³   Ú_bodyÚmemory_usageÚLOADÚbuffer_nameÚ
index_namerÎ   Úindexing_exprsrÙ   r¥   Úkeysra   rÁ   rÂ   Ústride_vars)rx   rÞ   Úparent_noder  r”   Ú	loop_bodyÚentriesÚeÚindex_namesr  Ú
index_exprrÙ   Úvar_symbolsr"  s                 rs   r  z$MixOrderReduction.is_contiguous_loadÎ  s  € å=à×)Ñ)Ó+ò 	!ˆDÜ˜d¤MÔ2Ð2Ð2ØŸ
™
ˆIØ×,Ñ,¨_×-AÑ-AÑBˆGØ18ÖQ¨A¸A¿M¹MÈSÓ<P˜1Ÿ<›<ÐQˆKÐQä�;Ó 1Ò$Øð *ò !�
Ø&×5Ñ5°jÑA�
Ø&×1Ñ1�
ô # :§?¡?Ó#4Ó5�ÜŸg™g×.Ñ.×:Ñ:ØØØó�ð $ B™¨1Ó,°¸B±À1Ó0DÚ ñ!ð	!ð2 ùò+ Rs   ÁDÁ*DN©r”   rf   r�   r}   )r”   rf   r�   ztuple[sympy.Expr, sympy.Expr]©rˆ   rf   r‰   rf   r�   r}   )rÞ   Ústrr”   rf   r�   r}   )rˆ   rf   r‰   rf   r�   ú	list[str]©r”   rf   r�   r‘   ©rˆ   rf   r‰   rf   r�   r‘   )rÞ   r,  r#  rf   r�   r}   )r€   r�   r‚   r•   Ústaticmethodr½   r„   rË   rÓ   rá   rç   rë   rð   rò   r  r  r  r  r…   ru   rs   r¯   r¯   Ì   sv  „ ñð
 ò
ó ð
ð ò#!ó ð#!ðJ ð	0Ø%ð	0Ø.?ð	0à	ò	0ó ð	0ð òó ððB ð	Ø%ð	Ø.?ð	à	ò	ó ð	ð ð:Ø%ð:Ø.?ð:à	ò:ó ð:ð
 òMó ðMð ð$Ø%ð$Ø.?ð$à	ò$ó ð$ð ònó ðnð` ð*Ø%ð*Ø.?ð*à	ò*ó ð*ð
 òó ðð òó ñru   r¯   c                  ó`  — e Zd ZdZdZdZe	 	 	 	 	 	 dd„«       Ze	 	 	 	 	 	 dd„«       Ze	dd„«       Z
 G d„ dej                  «      Z G d	„ d
ej                  «      Z ej                   d¬«       G d„ d«      «       Ze		 	 	 	 	 	 dd„«       Ze		 	 	 	 	 	 	 	 dd„«       Ze		 	 	 	 	 	 	 	 d d„«       Ze		 	 	 	 	 	 d!d„«       Ze		 	 	 	 	 	 d"d„«       Ze		 	 	 	 	 	 	 	 d#d„«       Ze		 	 	 	 	 	 	 	 	 	 	 	 d$d„«       Ze		 	 	 	 	 	 d%d„«       Ze	dd„«       Ze	ddœ	 	 	 	 	 	 	 	 	 	 	 d&d„«       Ze		 	 	 	 	 	 d'd„«       Zy)(ÚNestedReductiona   
    Detects when an outer reduction and a dependent grouped reduction can be
    fused into one kernel. The outer reduction reduces over a large dimension
    (e.g. D) producing per-row statistics; the grouped reduction performs a
    small local reduction over the same logical elements. The grouped reduction
    may re-read the outer reduction's large input, consume its full-resolution
    output, or both.

    This is deliberately limited to same-total-numel pairs:
    both reductions must traverse the same number of logical elements.
    General output-size-reducing nested reductions, including split reductions,
    need different grid ownership and are rejected here.

    Example:
    - layernorm + block amax: amax over groups of G after layer_norm
    i   é€   c                ó–   — | j                  «       xr8 |j                  «       xr& t        | j                  «       |j                  z  «      S )zFCheck that the grouped reduction is a consumer of the outer reduction.)r´   r}   r  r  ©Ú
outer_nodeÚgrouped_nodes     rs   Ú_is_dependent_reduction_pairz,NestedReduction._is_dependent_reduction_pair  sI   € ð ×#Ñ#Ó%ò PØ×)Ñ)Ó+òPä�Z×3Ñ3Ó5¸×8NÑ8NÑNÓOð	
ru   c                óŒ   — t         j                  j                  xr) t        j                  j
                   xr t        | |«      S r~   )r-   r©   Únested_reductionra   rÁ   r   r­   r5  s     rs   Ú_is_enabled_forzNestedReduction._is_enabled_for  s<   € ô
 �M‰M×*Ñ*ò AÜ—G‘G×'Ñ'Ð'òAä& z°<Ó@ð	
ru   c                óê   — | j                  ||«      r| j                  ||«      sy|j                  \  }\  }}|j                  \  }\  }}t        j                  j
                  j                  ||«       S )zECheap filter for dependent reductions with different reduction sizes.F)r;  r8  rÆ   ra   rÁ   rÂ   rÅ   )rx   rˆ   r‰   Ú_Úrnumel1Úrnumel2s         rs   Úis_candidatezNestedReduction.is_candidate  sl   € ð ×"Ñ"Ø�5ô
à×1Ñ1°%¸Ô?ØØŸ+™+‰ˆ‰<ˆAˆwØŸ+™+‰ˆ‰<ˆAˆwÜ—7‘7×#Ñ#×;Ñ;¸GÀWÓMÐMÐMru   c                  óv   — e Zd ZdZ ej
                  «       Z ej
                  «       Z ej
                  «       Zy)úNestedReduction.PointwiseDomaina  
        Where a pointwise node runs in the nested pipeline.

        The local reduction stage has three meaningful domains: its reduced
        output, its input before reducing the local lane, and the outer
        reduction's parent tile after broadcast-back.
        N)	r€   r�   r‚   r•   ÚenumÚautoÚREDUCEDÚLOCAL_REDUCTION_INPUTÚPARENT_FULLr…   ru   rs   ÚPointwiseDomainrB  #  s1   „ ñ	ð �$—)‘)“+ˆà ) §	¡	£Ðà�d—i‘i“k‰ru   rH  c                  óP   — e Zd Z ej                  «       Z ej                  «       Zy)úNestedReduction.GroupedAxisN)r€   r�   r‚   rC  rD  ÚRÚXr…   ru   rs   ÚGroupedAxisrJ  3  s   „ ØˆD�I‰I‹KˆØˆD�I‰I‹K‰ru   rM  T)Úfrozenc                  ó@   — e Zd ZU ded<   ded<   ded<   ded<   ded<   y	)
ú&NestedReduction.PointwiseDomainContextr³   Úgrouped_reductionú
sympy.ExprÚgrouped_numelÚgrouped_rnumelztuple[sympy.Expr, ...]Úlocal_reduction_domainÚparent_full_domainN)r€   r�   r‚   rƒ   r…   ru   rs   ÚPointwiseDomainContextrP  7  s    … à(Ó(Ø!Ó!Ø"Ó"Ø 6Ó6Ø2Ô2ru   rW  c                ó~  — |j                  «       sy|j                  «       D �cg c]  }|j                  «       sŒ|‘Œ }}t        |«      dk7  ry|d   }t        |t        «      rt        |j
                  t        «      sy|j                  «       \  }}t        |«      dvst        |«      dk7  ry|j
                  j                  «       dvryt        j                  j                  j                  |«      }t        |t        t        j                  f«      rt        |«      dk  ry|t        j                  |«      fS c c}w )z<Validate the candidate as a single simple grouped reduction.Nr   r   )r   rÍ   >   r  ÚmaxÚminrü   rý   Úxor_sum)r´   r»   rÎ   r²   r³   r”   r   Ú
get_rangesrþ   ra   rÁ   rÂ   rÃ   r‘   r  ÚInteger)	rx   r7  rT  ÚsnÚ
reductionsÚ	reductionÚiter_rangesÚreduce_rangesÚ
group_sizes	            rs   Ú_get_grouped_reduction_and_sizez/NestedReduction._get_grouped_reduction_and_size?  s  € ð
 ×(Ñ(Ô*ØØ#/×#9Ñ#9Ó#;ÖQ˜R¸r¿¹Õ?P’bÐQˆ
ÐQÜˆz‹?˜aÒØØ˜q‘Mˆ	Ü˜)¤]Ô3¼:Ø�N‰NœNô<
ð Ø%.×%9Ñ%9Ó%;Ñ"ˆ�]ô ˆ{Ó 6Ñ)¬S°Ó-?À1Ò-DØð �>‰>×,Ñ,Ó.ð 7
ñ 
ð ä—W‘W×%Ñ%×.Ñ.¨~Ó>ˆ
Ü˜*¤s¬E¯M©MÐ&:Ô;¼sÀ:»ÐQRÒ?RØØœ%Ÿ-™-¨
Ó3Ð3Ð3ùòA Rs
   ¤D:ºD:c                óR   — | j                  |||«      }|€y| j                  ||«      S )a\  Classify pointwise nodes by nested stage and validate their ranges.

        Each pointwise node must run either on the grouped reduction output,
        on the grouped reduction's full local-group domain, or on the outer
        reduction's full parent domain, based on its producer/consumer
        relationship to the grouped reduction.
        F)Ú _classify_nested_pointwise_nodesÚ!_pointwise_domains_are_compatible)rx   r6  r7  Údomain_contextÚpointwise_domainss        rs   Ú%_pointwise_nodes_match_nested_domainsz5NestedReduction._pointwise_nodes_match_nested_domainsh  s=   € ð  ×@Ñ@ØØØó
Ðð
 Ð$Øà×4Ñ4°^ÐEVÓWÐWru   c                ó¼  — g }t        «       }|j                  «       D ]&  }|j                  «       sŒ||j                  «       z  }Œ( |j                  «       D ]\  }|j                  «       rŒ||j                  z  sŒ$t        |t        «      s y |j                  || j                  j                  f«       Œ^ | j                  ||j                  «       «      }|€y g |¢|¢S r~   )r   r»   r´   r  r  r²   r³   rä   rH  rF  Ú!_classify_grouped_pointwise_nodes)rx   r6  r7  rh  Úouter_pointwise_domainsÚouter_reduction_namesr^  Úgrouped_pointwise_domainss           rs   rf  z0NestedReduction._classify_nested_pointwise_nodes€  sï   € ð ð 	 ô
 2<³ÐØ×&Ñ&Ó(ò 	BˆBØ�‰Õ Ø%¨×)?Ñ)?Ó)AÑAÑ%ð	Bð ×&Ñ&Ó(ò 	ˆBØ�‰Ô ØØ$ r§|¡|Ó3Ü! "¤mÔ4ÙØ'×.Ñ.Ø˜×,Ñ,×BÑBÐCõð	ð %(×$IÑ$IØØ×"Ñ"Ó$ó%
Ð!ð %Ð,ØØEÐ(ÐEÐ+DÐEÐEru   c                óL  — |j                   }|j                  «       }t        j                  j                  j                  |j                  |j                  z  «      }g }|D �]?  }|j                  «       rŒt        |t        «      s y|j                  «       }t        ||j                  z  «      }	t        ||j                  z  «      }
|	r|
r y|	s|
s y|	r| j                  j                  n| j                  j                  }|j                   \  }\  }}t        j                  j                  j#                  ||j                  «      r| j                  j$                  }n/t        j                  j                  j#                  ||«      r|}n y|j'                  ||f«       �ŒB |S )aV  Classify pointwise nodes relative to the grouped reduction.

        A node must be on exactly one side of the grouped reduction: either a
        producer feeding its local-group body, or a consumer of its reduced
        output. Its numel then determines whether it runs at reduced,
        grouped-full, or parent-full resolution.
        N)rQ  r  ra   rÁ   rÂ   rÃ   rS  rT  r´   r²   r³   r}   r  rH  rF  rG  rÆ   rÅ   rE  rä   )rx   rh  ÚnodesrQ  Úreduction_namesÚ
full_numelri  r^  Úsn_namesÚis_producerÚis_consumerÚfull_domainr=  Úsn_numelÚdomains                  rs   rl  z1NestedReduction._classify_grouped_pointwise_nodes¥  s~  € ð +×<Ñ<ÐØ+×?Ñ?ÓAˆÜ—W‘W×%Ñ%×.Ñ.Ø×(Ñ(¨>×+HÑ+HÑHó
ˆ
ð
 ð 	ð ó  	3ˆBØ�‰Ô ØÜ˜b¤-Ô0Ùà×-Ñ-Ó/ˆHÜ˜xÐ*;×*EÑ*EÑEÓFˆKÜ˜°·±Ñ=Ó>ˆKÙ™{ñ Ù¡{ñ ñ ð ×#Ñ#×9Ò9à×(Ñ(×4Ñ4ð ð
  "Ÿx™xÑˆA‰}�˜!Ü�w‰w×Ñ×7Ñ7Ø˜.×6Ñ6ôð ×,Ñ,×4Ñ4‘Ü—‘×!Ñ!×9Ñ9¸(ÀJÔOØ$‘áØ×$Ñ$ b¨& \Ö2ðA 	3ðB !Ð ru   c                ó0   ‡ ‡— t        ˆ ˆfd„|D «       «      S )Nc              3  óJ   •K  — | ]  \  }}‰j                  ||‰«      –— Œ y ­wr~   )Ú_pointwise_domain_is_compatible)r·   r^  ry  rx   rh  s      €€rs   r¹   zDNestedReduction._pointwise_domains_are_compatible.<locals>.<genexpr>ã  s,   øè ø€ ò 
á��Fð ×/Ñ/°°F¸N×Kñ
ùó   ƒ #)rº   )rx   rh  ri  s   `` rs   rg  z1NestedReduction._pointwise_domains_are_compatibleÝ  s   ù€ ô ô 
à/ô
ó 
ð 	
ru   c                óú  — ddl m} |j                  j                  «       \  }}|j                  \  }\  }}|| j
                  j                  u r|j                  }t        |«      }	nË|| j
                  j                  u rMt        j                  j                  j                  |j                  |j                  z  «      }|j                  }	nf|| j
                  j                   u sJ ‚t        j                  j                  j                  |j                  |j                  z  «      }|j"                  }	t        j                  j                  j%                  ||«      xr  |j'                  |	|j                  «       «      S )Nr   ©Ú
SIMDKernel)Úcodegen.simdr€  rQ  r\  rÆ   rH  rE  rS  rÏ   rF  ra   rÁ   rÂ   rÃ   rT  rU  rG  rV  rÅ   Úis_compatible)
rx   r^  ry  rh  r€  ra  r=  rx  Úexpected_numelÚexpected_groupss
             rs   r|  z/NestedReduction._pointwise_domain_is_compatibleè  s=  € õ 	-à'×9Ñ9×DÑDÓF‰ˆ�QØŸ8™8Ñˆ‰=ˆH�aØ�S×(Ñ(×0Ñ0Ñ0Ø+×9Ñ9ˆNÜ49¸+Ó4F‰OØ�s×*Ñ*×@Ñ@Ñ@ÜŸW™W×-Ñ-×6Ñ6Ø×,Ñ,¨~×/LÑ/LÑLóˆNð -×CÑC‰Oà˜S×0Ñ0×<Ñ<Ñ<Ð<Ð<ÜŸW™W×-Ñ-×6Ñ6Ø×,Ñ,¨~×/LÑ/LÑLóˆNð -×?Ñ?ˆOÜ�w‰w×Ñ×7Ñ7Ø�nó
ò Ià×&Ñ& ¸¿¹»ÓHð	Iru   c               óþ  — ddl m} t        |t        t        f«      syt
        j                  j                  r|j                  «       nd }t        |j                  «       «      }|j                  ||||«      }	t        |	«      t        d«      k7  ryt        j                  j                  j!                  |	d   |«      r-t        j                  j                  j!                  |	d   |«      sy|| j#                  ||«      kD  S )Nr   ©ÚSIMDSchedulingT)ÚxÚr0_rˆ  r‰  )r�  r‡  r²   r³   rÚ   r-   r©   Úcoalesce_tiling_analysisÚget_coalesce_analysisr¥   r»   Úselect_tilingr   ra   rÁ   rÂ   rÅ   Ú_max_min_block_group_size)
rx   r6  Úouter_numelÚouter_rnumelÚgrouped_axisrc  r‡  Úcoalesce_analysisÚnode_scheduleÚtilings
             rs   Ú"_min_block_unprofitable_for_kernelz2NestedReduction._min_block_unprofitable_for_kernel  sÞ   € õ 	1ä˜*¤}Ô6HÐ&IÔJØô �}‰}×5Ò5ð ×,Ñ,Ô.àð 	ô
 ˜Z×1Ñ1Ó3Ó4ˆØ×-Ñ-ØØØØó	
ˆô �fÓ¤¨LÓ!9Ò9Øä�G‰G×Ñ×4Ñ4°V¸C±[À+ÔNÜ—‘× Ñ ×8Ñ8¸À¹ÈÔUàØ˜C×9Ñ9¸-ÈÓVÑVÐVru   c                óP  — ddl m} |D �cg c]M  }t        |t        «      r;|j	                  «       r+t        |j
                  t        «      r|j                  |«      ‘ŒO }}|| j                  j                  u r |rt        d„ |D «       «      r| j                  S | j                  S c c}w )Nr   ©ÚSIMDKernelFeaturesc              3  ó@   K  — | ]  }|t         j                  u –— Œ y ­wr~   )rI   rù   )r·   Úhints     rs   r¹   z<NestedReduction._max_min_block_group_size.<locals>.<genexpr>?  s   è ø€ ÒL°D�DœM×/Ñ/Ô/ÑLùó   ‚)Úcodegen.simd_kernel_featuresr—  r²   r³   r´   r”   r   rø   rM  rK  rº   ÚMAX_INNER_R_GROUP_SIZEÚMAX_NON_INNER_GROUP_SIZE)rx   r’  r�  r—  r^  Úreduction_hintss         rs   r�  z)NestedReduction._max_min_block_group_size-  s–   € õ 	Eð $ö
àÜ˜"œmÔ,Ø—‘Ô!Ü˜2Ÿ7™7¤NÔ3ð	 ×-Ñ-¨bÕ1ð
ˆð 
ð ˜CŸO™O×-Ñ-Ñ-ÙÜÑL¸OÔLÔLà×-Ñ-Ð-Ø×+Ñ+Ð+ùò
s   ‹AB#c                ó   — | j                  ||«      sy| j                  ||«      sJ ‚|}|}|j                  \  }}|j                  \  }}|\  }}	|\  }
}t        j                  j
                  j                  |	|«      ry| j                  ||«      }|€yt        j                  j
                  j                  ||	z  «      }t        j                  j
                  j                  |
|z  «      }t        j                  j
                  j                  ||«      sy|\  }}| j                  |||	||¬«      }|€y|| j                  j                  u r|	n|}|j                  «       \  }}t        |«      dk(  rW|| j                  j                  u r|d   n|d   }t        j                  j
                  j                  t        ||«      |«      s@yt        j                  j
                  j                  t        j                   ||«      d«      syt#        |«      }d|k  rt%        |«      sy| j'                  |||	||¬«      ry|j                  «       \  }}| j)                  ||
|g |¢|¢­||	f¬«      }| j+                  |||«      syy)	zACheck whether a dependent cross-axis reduction pair can be fused.F©r6  rÍ   r   r   )r�  rc  ©rQ  rS  rT  rU  rV  T)r;  r8  rÆ   ra   rÁ   rÂ   rÅ   rd  rÃ   Úget_grouped_axisrM  rK  r\  rÎ   r'   r  ÚModr‘   rK   r”  rW  rj  )rx   rˆ   r‰   r6  r7  r=  Úouter_groupÚgrouped_grouprŽ  r�  rS  rT  Úgrouped_reduction_infoÚouter_totalÚgrouped_totalrQ  rc  r�  Úparent_grouped_axisra  Úgrouped_axis_groupsÚgroup_size_intrb  rh  s                           rs   r  zNestedReduction.can_fuseD  s§  € ð
 ×"Ñ" 5¨%Ô0Øà×/Ñ/°°uÔ=Ð=Ð=àˆ
Øˆð $×)Ñ)‰ˆˆ;Ø'×-Ñ-Ñˆˆ=Ø$/Ñ!ˆ�\Ø(5Ñ%ˆ�~Ü�7‰7×Ñ×3Ñ3°LÀ.ÔQØð "%×!DÑ!DØ˜.ó"
Ðð "Ð)Øô —g‘g×&Ñ&×/Ñ/°¸lÑ0JÓKˆÜŸ™×(Ñ(×1Ñ1°-À.Ñ2PÓQˆÜ�w‰w×Ñ×7Ñ7¸À]ÔSØà(>Ñ%Ð˜:à×+Ñ+ØØØØØ!ð ,ó 
ˆð ÐØà(¨C¯O©O×,=Ñ,=Ñ=‰LÀ;ð 	ð +×5Ñ5Ó7‰ˆ�QÜˆ{Ó˜qÒ à".°#·/±/×2CÑ2CÑ"C�˜A’ÈÐUVÉð  ô —7‘7×#Ñ#×;Ñ;ÜÐ,¨jÓ9Ð;Nôð Ü—‘×!Ñ!×9Ñ9Ü�I‰IÐ)¨:Ó6¸ô
ð Ü˜Z›ˆØ�^Ò#¬°nÔ(EØØ×1Ñ1ØØØØ%Ø%ð 2ô 
ð Ø%6×%AÑ%AÓ%CÑ"ˆ�]Ø×3Ñ3Ø/Ø'Ø)Ø#A [Ð#A°=Ñ#AØ +¨\Ð:ð 4ó 
ˆð ×8Ñ8ØØØô
ð
 àru   Nr   c               ó”  — t         j                  j                  }|j                  «       \  }}t	        |«      dk7  st	        |«      dk7  rÁt	        |«      dk(  r²t	        |«      dk(  r¤|j                  |d   |«      sy|j                  t        ||«      |d   «      r(|j                  |d«      r| j                  j                  S |j                  t        ||«      d«      r+|j                  |d   |«      r| j                  j                  S y|j                  |d   |«      sy|j                  |d   |«      r5|j                  t        ||«      |d   «      r| j                  j                  S |j                  |d   |«      r5|j                  t        ||«      |d   «      r| j                  j                  S |�| j                  ||«      S y)zAReturn which parent axis is split by the grouped local reduction.rÍ   r   r   N)ra   rÁ   rÂ   r\  rÎ   rÅ   r'   rM  rK  rL  Ú _get_grouped_axis_from_loop_body)	rx   rQ  rŽ  r�  rc  r6  rÂ   ra  rb  s	            rs   r¢  z NestedReduction.get_grouped_axis¦  s¸  € ô —7‘7×#Ñ#ˆØ%6×%AÑ%AÓ%CÑ"ˆ�]Üˆ{Ó˜qÒ ¤C¨Ó$6¸!Ò$;Ü�;Ó 1Ò$¬¨]Ó);¸qÒ)@Ø×7Ñ7¸ÀaÑ8HÈ*ÔUØð ×3Ñ3Ü˜\¨:Ó6¸ÀA¹ôà×6Ñ6°{ÀAÔFØŸ?™?×,Ñ,Ð,ð ×3Ñ3Ü˜[¨*Ó5°qôà×6Ñ6°{À1±~À|ÔTØŸ?™?×,Ñ,Ð,ØØ×/Ñ/°¸aÑ0@À*ÔMØð ×+Ñ+Ø˜‰N˜Kô
à×.Ñ.Ü�\ :Ó.°¸A±ô
ð —?‘?×$Ñ$Ð$à×+Ñ+Ø˜‰N˜Lô
à×.Ñ.Ü�[ *Ó-¨{¸1©~ô
ð —?‘?×$Ñ$Ð$ØÐ!Ø×7Ñ7¸
ÐDUÓVÐVØru   c                óx  ‡‡‡— ddl mŠ |j                  «       D �cg c]  }|j                  «       sŒ|‘Œ }}t	        |«      dk7  ryt        j                  t        |d   «      }t        |dd«      }t        |dd«      }|�|€y|j                  «       \  }}	|j                  «       \  }
}t	        |	«      dk7  st	        |«      dk7  ryd	ˆfd„}t	        |j                  «      dk7  st	        |j                  «      dk7  ryt	        |j                  «      t	        |«      k7  s!t	        |j                  «      t	        |
«      k7  ry ||«      }d}|j                  d   } ||«      j                  «       D ]Ã  \  }}|j                  |«      }|sŒ|D ]¥  }|j                  |«      Š‰dk(  rŒ|D ]‡  Š|j                  d   }‰j                  |«      }‰|k(  }t        ˆˆfd„|j                  D «       «      }||k(  rŒM|r| j                   j"                  n| j                   j$                  }|�	||k7  r   y|}Œ‰ Œ§ ŒÅ |S c c}w )
z>Use LoopBody iter/reduce vars to disambiguate equal-size axes.r   r  r   Nr  c                ó   •— t        t        «      }| j                  j                  ‰j                  d«      D ]D  }|j
                  €Œ||j
                     j                  | j                  |j                     «       ŒF |S ©Nr…   )	r   r¥   r  Úgetr  r  rä   r   r  )ÚbodyÚresultÚentryr  s      €rs   Úload_exprs_by_namezLNestedReduction._get_grouped_axis_from_loop_body.<locals>.load_exprs_by_nameï  su   ø€ Ü2=¼dÓ2CˆFØ×*Ñ*×.Ñ.¨×/CÑ/CÀRÓHò �Ø×$Ñ$Ñ0Ø˜5×,Ñ,Ñ-×4Ñ4Ø×+Ñ+¨E×,<Ñ,<Ñ=õðð
 ˆMru   r  c              3  óF   •K  — | ]  }‰‰j                  |«      k(  –— Œ y ­wr~   )Úcoeff)r·   ÚvarÚgrouped_coeffÚouter_read_exprs     €€rs   r¹   zCNestedReduction._get_grouped_axis_from_loop_body.<locals>.<genexpr>  s)   øè ø€ ò 'àð &¨×)>Ñ)>¸sÓ)CÕCñ'ùs   ƒ!)r²  rE   r�   zdict[str, list[sympy.Expr]])r  r  r»   r´   rÎ   ÚtypingÚcastr³   Úgetattrr\  Úreduce_varsÚ	iter_varsÚitemsr±  r·  r  rM  rK  rL  )rx   r6  rQ  r^  Úouter_reductionsÚouter_reductionÚ
outer_bodyÚgrouped_bodyÚouter_iter_rangesÚouter_reduce_rangesÚgrouped_iter_rangesÚgrouped_reduce_rangesrµ  Úouter_reads_by_namer³  Úgrouped_reduce_varr×   Úgrouped_read_exprsÚouter_read_exprsÚgrouped_read_exprÚouter_reduce_varÚouter_reduce_coeffÚmatches_reductionÚmatches_iterÚ	candidater  r¹  rº  s                            @@@rs   r­  z0NestedReduction._get_grouped_axis_from_loop_bodyÚ  sj  ú€ õ
 	>à)3×)=Ñ)=Ó)?ÖU 2À2Ç?Á?ÕCTšBÐUÐÐUÜÐÓ  AÒ%ØÜ Ÿ+™+¤mÐ5EÀaÑ5HÓIˆÜ˜_¨g°tÓ<ˆ
ÜÐ0°'¸4Ó@ˆØÐ Ð!5Øà1@×1KÑ1KÓ1MÑ.ÐÐ.Ø5F×5QÑ5QÓ5SÑ2ÐÐ2ÜÐ"Ó# qÒ(¬CÐ0EÓ,FÈ!Ò,KØõ	ô ˆz×%Ñ%Ó&¨!Ò+¬s°<×3KÑ3KÓ/LÐPQÒ/QØÜˆz×#Ñ#Ó$¬Ð,=Ó(>Ò>Ä#Ø×"Ñ"óC
äÐ$Ó%òC&ð á0°Ó<ÐØ59ˆØ)×5Ñ5°bÑ9ÐÙ(:¸<Ó(H×(NÑ(NÓ(Pò 	'Ñ$ˆDÐ$Ø2×6Ñ6°tÓ<ÐÙ#ØØ%7ò 'Ð!Ø 1× 7Ñ 7Ð8JÓ K�Ø  AÒ%ØØ'7ò '�OØ'1×'=Ñ'=¸bÑ'AÐ$Ø)8×)>Ñ)>Ð?OÓ)PÐ&Ø(5Ð9KÑ(KÐ%Ü#&ô 'à#-×#7Ñ#7ô'ó $�Lð )¨LÒ8Ø á->˜Ÿ™×)Ò)ÀCÇOÁO×DUÑDUð ð Ð)¨f¸	Ò.AÛ#Ø&‘Fñ!'ñ	'ð		'ð2 ˆùòu Vs
   œH7²H7)r6  rf   r7  rf   r�   r}   r+  )r7  rf   rT  rR  r�   z*tuple[SchedulerNode, sympy.Integer] | None)r6  rf   r7  rf   rh  rW  r�   r}   )r6  rf   r7  rf   rh  rW  r�   ú2list[tuple[SchedulerNode, PointwiseDomain]] | None)rh  rW  rq  úSequence[BaseSchedulerNode]r�   rÓ  )rh  rW  ri  z/Sequence[tuple[SchedulerNode, PointwiseDomain]]r�   r}   )r^  r³   ry  rH  rh  rW  r�   r}   )r6  rf   rŽ  rR  r�  rR  r�  rM  rc  r‘   r�   r}   )r’  rÔ  r�  rM  r�   r‘   )rQ  r³   rŽ  rR  r�  rR  rc  rR  r6  úBaseSchedulerNode | Noner�   úGroupedAxis | None)r6  rf   rQ  r³   r�   rÖ  )r€   r�   r‚   r•   rœ  r�  r0  r8  r;  r„   r@  rC  ÚEnumrH  rM  r£   Ú	dataclassrW  rd  rj  rf  rl  rg  r|  r”  r�  r  r¢  r­  r…   ru   rs   r2  r2  î  s:  „ ñð" !ÐØ"Ðàð
Ø%ð
Ø5Fð
à	ò
ó ð
ð ð
Ø%ð
Ø5Fð
à	ò
ó ð
ð òNó ðNô"˜$Ÿ)™)ô "ô �d—i‘iô ð €[×Ñ $Ô'÷3ð 3ó (ð3ð ð&4Ø,ð&4Ø>Hð&4à	3ò&4ó ð&4ðP ðXà%ðXð (ðXð /ð	Xð
 
òXó ðXð. ð"Fà%ð"Fð (ð"Fð /ð	"Fð
 
<ò"Fó ð"FðH ð5!à.ð5!ð +ð5!ð 
<ò	5!ó ð5!ðn ð
à.ð
ð Kð
ð 
ò	
ó ð
ð ðIàðIð  ðIð /ð	Ið
 
òIó ðIð8 ð%Wà%ð%Wð  ð%Wð !ð	%Wð "ð%Wð ð%Wð 
ò%Wó ð%WðN ð,à2ð,ð "ð,ð 
ò	,ó ð,ð, ò_ó ð_ðB ð 04ñ1à(ð1ð  ð1ð !ð	1ð
 ð1ð -ð1ð 
ò1ó ð1ðf ð@Ø*ð@Ø?Lð@à	ò@ó ñ@ru   r2  c                  óÜ   — e Zd ZU ded<   ded<   ded<    ej
                  e¬«      Zded	<    ej
                  e¬«      Z	d
ed<   dd„Z
dd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zy)ÚSchedulerBufferÚ	SchedulerÚ	schedulerz	ir.Bufferr”   rÕ  Údefining_oprŸ   úlist[NodeUser]ÚusersrF   Ú
mpi_bufferc                óB   — | j                   }|€J ‚|j                  «       S r~   )rÝ  Úget_name)rr   Úops     rs   Údefining_op_namez SchedulerBuffer.defining_op_name(  s#   € Ø×ÑˆØˆ~Ðˆ~Ø�{‰{‹}Ðru   c                ó@   — t        | j                  j                  «      S r~   )Úhashr”   r×   rq   s    rs   Ú__hash__zSchedulerBuffer.__hash__-  s   € Ü�D—I‘I—N‘NÓ#Ð#ru   c                óv  — t        «       }| j                  «       }|j                  |› dt        | j                  «      j
                  › �«       |j                  |› d| j                  j                  › �«       | j                  «       r-|j                  |› dt        | j                  «       «      › �«       | j                  «       r-|j                  |› dt        | j                  «       «      › �«       t        | j                  «      dk  r0|j                  |› d| j                  › �«       |j                  «       S |j                  |› d�«       |j                  d«      5  | j                  D ]  }|j                  |› d�«       Œ 	 d d d «       |j                  d	«       |j                  «       S # 1 sw Y   Œ*xY w)
Nú: z
.layout = z.aliases = z.mutations = r   z	.users = z
.users = [ú,ú])rX   râ  Ú	writeliner«   r”   r€   ÚlayoutÚget_aliasesÚpformatÚget_mutationsrÎ   rß  ÚindentÚgetrawvalue)rr   r³  r×   Úusers       rs   Ú	debug_strzSchedulerBuffer.debug_str0  s…  € ÜÓ!ˆØ�}‰}‹ˆØ×Ñ˜D˜6 ¤D¨¯©£O×$<Ñ$<Ð#=Ð>Ô?Ø×Ñ˜D˜6 ¨D¯I©I×,<Ñ,<Ð+=Ð>Ô?Ø×ÑÔØ×Ñ ˜v [´¸×9IÑ9IÓ9KÓ1LÐ0MÐNÔOØ×ÑÔØ×Ñ ˜v ]´7¸4×;MÑ;MÓ;OÓ3PÐ2QÐRÔSäˆt�z‰z‹?˜aÒØ×Ñ ˜v Y¨t¯z©z¨lÐ;Ô<ð ×!Ñ!Ó#Ð#ð ×Ñ ˜v ZÐ0Ô1Ø—‘˜qÓ!ñ 1Ø ŸJ™Jò 1�DØ×$Ñ$¨ v¨Q ZÕ0ñ1÷1ð ×Ñ˜SÔ!Ø×!Ñ!Ó#Ð#÷	1ð 1ús   Å&F/Æ/F8c                ó6   — | j                   j                  «       S r~   ©r”   râ  rq   s    rs   râ  zSchedulerBuffer.get_nameD  ó   € Ø�y‰y×!Ñ!Ó#Ð#ru   c                óö  — | j                   €J ‚| j                   j                  «       sy | j                   j                  «       sL| j                   j                  «       s2t	        | j                   j                  «       t        j                  «      r4t        j                  j                  j                  | j                   «       y t        t        j                  d«      ré| j                  «       t        j                  j                  v r¿t        j                  j                  | j                  «          }|| j                   j"                  v r$| j                   j"                  |   j                   }n#| j                   j$                  |   j                   }t        j                  j                  j'                  || j                   «       y t        j                  j                  j                  | j                   «       y )NÚargs)r”   Úshould_allocateÚget_inputs_that_alias_outputÚget_mutation_namesr²   Úget_output_specr0   ÚCommBufferLayoutra   rÁ   Úwrapper_codeÚcodegen_allocationÚhasattrÚkernelrâ  Úinplace_update_buffersrÜ  Úname_to_donated_bufferÚname_to_bufÚcodegen_inplace_reuse)rr   Úinput_buffer_nameÚinput_buffers      rs   ÚallocatezSchedulerBuffer.allocateG  sV  € Ø�y‰yÐ$Ð$Ð$Ø�y‰y×(Ñ(Ô*Øð �I‰I×2Ñ2Ô4Ø�y‰y×+Ñ+Ô-Ü˜$Ÿ)™)×3Ñ3Ó5´r×7JÑ7JÔKä�G‰G× Ñ ×3Ñ3°D·I±IÔ>Øô ”A—H‘H˜fÔ%Ø—‘“¤1§8¡8×#BÑ#BÑBô !"§¡× ?Ñ ?ÀÇÁÃÑ PÐØ  D§N¡N×$IÑ$IÑIØ#Ÿ~™~×DÑDØ%ñ ç‘$ñ ð  $Ÿ~™~×9Ñ9Ð:KÑL×QÑQ�Ü�G‰G× Ñ ×6Ñ6ØØ—	‘	õô
 �G‰G× Ñ ×3Ñ3°D·I±IÕ>ru   c                ó  — | j                   €J ‚t        | j                   j                  t        j                  «      st        | j                   «      ry| j                  D ]  }t        |j                   t        «      sŒ y y©NFT)r”   r²   rí  r0   rD   r\   rß  Ú
OutputNode)rr   Úuses     rs   Úcan_freezSchedulerBuffer.can_freeh  sg   € à�y‰yÐ$Ð$Ð$Ü�d—i‘i×&Ñ&¬¯©Ô6Ô:SØ�I‰Iô;
ð Ø—:‘:ò 	ˆCÜ˜#Ÿ(™(¤JÕ/Ùð	ð ru   c                ó,  — i }|D ]o  }t        |j                  «      |v r>|j                  |t        |j                  «         «      |t        |j                  «      <   ŒX||t        |j                  «      <   Œq t        |j	                  «       «      | _        y r~   )Úidr”   Úmerger¥   rÝ   rß  )rr   rß  r³  r  s       rs   Ú	set_userszSchedulerBuffer.set_userst  st   € à&(ˆØò 	+ˆCÜ�#—(‘(‹|˜vÑ%Ø'*§y¡y°¼¸3¿8¹8»Ñ1EÓ'F�”r˜#Ÿ(™(“|Ò$à'*�”r˜#Ÿ(™(“|Ò$ð		+ô
 ˜&Ÿ-™-›/Ó*ˆ�
ru   c                óR   — | j                   €J ‚| j                   j                  «       S r~   )r”   rû  rq   s    rs   rî  zSchedulerBuffer.get_aliases~  s%   € Ø�y‰yÐ$Ð$Ð$Ø�y‰y×5Ñ5Ó7Ð7ru   c                óR   — | j                   €J ‚| j                   j                  «       S r~   )r”   rü  rq   s    rs   rð  zSchedulerBuffer.get_mutations‚  ó%   € Ø�y‰yÐ$Ð$Ð$Ø�y‰y×+Ñ+Ó-Ð-ru   c                óR   — | j                   j                  «       j                  «       S r~   )r”   rý  rª   rq   s    rs   rª   zSchedulerBuffer.get_device†  s   € Ø�y‰y×(Ñ(Ó*×5Ñ5Ó7Ð7ru   N©r�   r,  ©r�   r‘   ©r�   ÚNone©r�   r}   )rß  rÞ  r�   r  ©r�   zSequence[str]©r�   útorch.device | None)r€   r�   r‚   rƒ   r£   r¤   r¥   rß  rF   rà  rä  rç  rô  râ  r	  r  r  rî  rð  rª   r…   ru   rs   rÚ  rÚ    sz   … àÓØ
ƒOØ)Ó)Ø-˜K×-Ñ-¸dÔC€Eˆ>ÓCØ.?¨k×.?Ñ.?Ø3ô/€JÐ+ó óó
$ó$ó($ó?óB
ó+ó8ó.ô8ru   rÚ  c                  ó   — e Zd ZU dZded<   y)ÚSchedulerDonatedBufferNrÕ  rÝ  )r€   r�   r‚   rÝ  rƒ   r…   ru   rs   r   r   Š  s   … à,0€KÐ)Ô0ru   r   c                  ó.  — e Zd ZU ded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   ded<   dZded<   ded<   ded<   dZded<   ded<   ded<   dZded<   dVd„ZdWd „ZdXd!„Z	dXd"„Z
dXd#„ZdYd$„ZdXd%„ZdZd&„Z	 	 	 	 	 	 d[d'„Zd\d(„Zd]d)„Zd^d*„Zd_d+„ZdZd,„Zed`d-„«       Z	 	 	 	 	 	 dad.„ZdZd/„Zdbd0„Zdbd1„ZdZd2„ZdZd3„Z	 	 	 	 dcd4„ZdXd5„ZdXd6„Zedbd7„«       Z edbd8„«       Z!ed^d9„«       Z"ed^d:„«       Z#ddd;„Z$ded<„Z%dfd=„Z&dgd>„Z'd^d?„Z(d^d@„Z)d^dA„Z*d^dB„Z+d^dC„Z,d^dD„Z-d^dE„Z.d^dF„Z/dhdG„Z0d^dH„Z1dZdI„Z2	 di	 	 	 	 	 djdJ„Z3edkdK„«       Z4edkdL„«       Z5edkdM„«       Z6	 	 	 	 	 	 dldN„Z7	 	 	 	 	 	 dmdO„Z8edndP„«       Z9dodQ„Z:edodR„«       Z;dpdS„Z<dqdT„Z=e>	 	 	 	 drdU„«       Z?y)srf   r™   r  z7tuple[torch.device, tuple[tuple[sympy.Expr, ...], ...]]rÆ   Ú
last_usager‘   Úmin_input_distanceÚmax_input_distanceÚ	min_orderÚ	max_orderrG   Úmpi_nodeúdict[str, str]Úmutation_renamesNúir.Operation | Noner”   úlist[SchedulerBuffer]Úoutputsúdict[str, SchedulerBuffer]Úoutputs_by_nameúfloat | NoneÚoverride_estimated_runtimeúdependencies.ReadWritesrÕ   úOrderedSet[Dep]Úunmet_dependenciesFr}   Úwrittenc                ó"   — || _         d„ | _        y )Nc                 ó   — g S r~   r…   )rù  Úkwargss     rs   ú<lambda>z,BaseSchedulerNode.__init__.<locals>.<lambda>©  s   €  B€ ru   )rÜ  Údebug_device_str)rr   rÜ  s     rs   Ú__init__zBaseSchedulerNode.__init__¦  s   € Ø$-ˆŒá&ð 	Õru   c                óv  — || _         t        «       | _        d| _        d| _        t        t
           «       | _        d| _        |j                  «       D �cg c]  }t        | j                  || ¬«      ‘Œ c}| _        | j                  D �ci c]  }|j                  «       |“Œ c}| _        i | _        y c c}w c c}w )Nr   F)rÜ  r”   rÝ  )r”   r   r  r#  r$  r,  r"  r4  Úget_outputsrÚ  rÜ  r,  râ  r.  r)  )rr   r”   ÚoutputrÞ   s       rs   Ú_init_from_nodez!BaseSchedulerNode._init_from_node¬  s³   € ØˆŒ	Ü#›ˆŒØ"#ˆÔØ"#ˆÔÜ$Üñ
ó ˆŒð ˆŒð ×*Ñ*Ó,ö
ð ô ØŸ.™.ØØ öò
ˆŒð @D¿|¹|ÖL¸ §¡£°Ñ 3ÒLˆÔð !#ˆÕùò
ùò  Ms   ÁB1Â	B6c                óT   — t        | «      j                  › d| j                  «       ›d�S )Nz(name=ú)©r«   r€   râ  rq   s    rs   Ú__repr__zBaseSchedulerNode.__repr__Æ  s'   € Ü�t“*×%Ñ%Ð& f¨T¯]©]«_Ð,?¸qÐAÐAru   c                óˆ  — | j                  «       }t        «       }|j                  |› dt        | «      j                  › dt        t        | dd«      «      j                  › d|› dt        | j                  j                  «      › d|› dt        | j                  «      › d|› d	t        | j                  j                  | j                  z
  «      › d|› d
| j                  › d|› d| j                  › d|› d�«       |j                  «       5  | j                  «       D ]!  }|j                  |j                  «       «       Œ# 	 ddd«       |j!                  d«       	 |j                  | j#                  «       «       |j+                  «       j-                  «       S # 1 sw Y   ŒXxY w# t$        $ r t&        j)                  dd¬«       Y ŒLw xY w)ú#Longer form printout for trace logsré  ú(r”   Nú)
ú
.writes = ú
ú.unmet_dependencies = ú.met_dependencies = ú.min_input_distance = ú.max_input_distance = z.outputs = [
        rë  úIgnoring error in debug_str()T©Úexc_info)râ  rX   Úsplicer«   r€   r½  rï  rÕ   Úwritesr3  rÖ   r#  r$  rñ  r<  rô  rì  Údebug_str_extraÚ	ExceptionÚlogÚwarningrò  Úrstrip)rr   r×   rÞ   rå   s       rs   rô  zBaseSchedulerNode.debug_strÉ  s³  € à�}‰}‹ˆÜÓˆØ�
‰
à€€bŒˆd‹×	Ñ	Ð˜Qœt¤G¨D°&¸$Ó$?Ó@×IÑIÐJð KØ€€j”˜×)Ñ)×0Ñ0Ó1Ð2ð 3Ø€ÐœW T×%<Ñ%<Ó=Ð>ð ?Ø€Ðœ7 4×#3Ñ#3×#9Ñ#9¸D×<SÑ<SÑ#SÓTÐUð VØ€Ð˜T×4Ñ4Ð5ð 6Ø€Ð˜T×4Ñ4Ð5ð 6Ø€ð 	ðô
	
ð �Z‰Z‹\ñ 	,Ø×'Ñ'Ó)ò ,�Ø—
‘
˜3Ÿ=™=›?Õ+ñ,÷	,ð 	�‰�cÔð	HØ�J‰J�t×+Ñ+Ó-Ô.ð �‰Ó ×'Ñ'Ó)Ð)÷	,ð 	,ûô ò 	HÜ�K‰KÐ7À$ˆKÖGð	Hús   Ä5FÅF ÆFÆ GÇ Gc                 ó   — y)NÚ r…   rq   s    rs   rR  z!BaseSchedulerNode.debug_str_extraä  ó   € Øru   c                ó$   — | j                  | «      S r~   )r9  rq   s    rs   Ú_debug_str_for_devicez'BaseSchedulerNode._debug_str_for_deviceç  s   € Ø×$Ñ$ TÓ*Ð*ru   c                ó°  — t        | j                  dd «      }d}t        |t        j                  j
                  j                  «      r'd|j                  |j                  «       gdd¬«      z   }nct        |t        j                  j
                  j                  «      r5d|j                  |j                  «       |j                  «       gdd¬«      z   }| › |› �S )Nr÷   rX  ú, F)ÚshortenÚ	multiline)r½  r”   r²   ÚtorchÚ	_inductorr0   r   Ú
str_helperÚget_sizeÚ	ReductionÚget_reduction_sizerþ   )rr   Ú
maybe_dataÚdata_strs      rs   Údebug_str_shortz!BaseSchedulerNode.debug_str_shortê  sË   € Ü˜TŸY™Y¨°Ó5ˆ
ØˆÜ�j¤%§/¡/×"4Ñ"4×">Ñ">Ô?Ø˜j×3Ñ3Ø×$Ñ$Ó&Ð'°À%ð 4ó ñ ‰Hô ˜
¤E§O¡O×$6Ñ$6×$@Ñ$@ÔAØ˜j×3Ñ3Ø×.Ñ.Ó0°*×2OÑ2OÓ2QÐRØØð 4ó ñ ˆHð
 �˜�zÐ"Ð"ru   c                óp   — t         j                  d| | j                  | j                  j                  «       y )Nz(%s: unmet_dependencies = %s, writes = %s)rT  Úinfor3  rÕ   rQ  rq   s    rs   Úlog_detailszBaseSchedulerNode.log_detailsù  s,   € Ü�‰Ø6ØØ×#Ñ#Ø×Ñ×#Ñ#õ		
ru   c                 ó   — y©NFr…   )rr   Úself_depÚ	other_deps      rs   Úreorder_loops_by_dep_pairz+BaseSchedulerNode.reorder_loops_by_dep_pair  ó   € ð ru   c                óî   — d„ | j                   j                  «       D «       D �ci c]  }||v r|||   “Œ c}| _        | j                  | j                   j	                  | j                  «      «       y c c}w )Nc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   ©r×   ©r·   rà   s     rs   r¹   z9BaseSchedulerNode.update_mutated_names.<locals>.<genexpr>	  s   è ø€ ÒQ c˜Ÿ�ÑQùó   ‚)rÕ   Úreads_and_writesr)  Úset_read_writesÚrename)rr   Úrenamesr×   s      rs   Úupdate_mutated_namesz&BaseSchedulerNode.update_mutated_names  sp   € ñ R¨T×-=Ñ-=×-NÑ-NÓ-PÔQö!
àØ�w‰ð �'˜$‘-Ñò!
ˆÔð
 	×Ñ˜T×-Ñ-×4Ñ4°T×5JÑ5JÓKÕLùò!
s   ¤A2c                óX   — | j                  | j                  j                  |«      «       y r~   )rx  rÕ   Ú	with_read©rr   rà   s     rs   Úadd_fake_depzBaseSchedulerNode.add_fake_dep  s!   € Ø×Ñ˜T×-Ñ-×7Ñ7¸Ó<Õ=ru   c                óB   — t        d„ | j                  «       D «       «      S )Nc              3  ó`   K  — | ]&  }|j                  «       xs |j                  «       –— Œ( y ­wr~   )rî  rð  ©r·   rÞ   s     rs   r¹   z=BaseSchedulerNode.has_aliasing_or_mutation.<locals>.<genexpr>  s-   è ø€ ò 
Ø9<ˆC�O‰OÓÒ4 ×!2Ñ!2Ó!4Ó4ñ
ùs   ‚,.)r  r<  rq   s    rs   Úhas_aliasing_or_mutationz*BaseSchedulerNode.has_aliasing_or_mutation  s%   € Üñ 
Ø@D×@PÑ@PÓ@Rô
ó 
ð 	
ru   c                óˆ   — || _         | j                   j                  | _        | j                  «        | j	                  «        y r~   )rÕ   rÖ   r3  Ú"clear_read_writes_dependent_cachesÚ
prune_deps)rr   Úrws     rs   rx  z!BaseSchedulerNode.set_read_writes  s4   € ØˆÔØ"&×"2Ñ"2×"8Ñ"8ˆÔØ×/Ñ/Ô1Ø�‰Õru   c                ó:   — | j                   j                  | «       y r~   )r‹  Úclear_cacherq   s    rs   r…  z4BaseSchedulerNode.clear_read_writes_dependent_caches  s   € Ø×"Ñ"×.Ñ.¨tÕ4ru   c                óL   — ddl m} t        | t        t        f«      sy  || «      S )Nr   )Ú_analyze_memory_coalescing)Útiling_utilsr‹  r²   r³   rÚ   )rr   r‹  s     rs   r‹  z'BaseSchedulerNode.get_coalesce_analysis  s#   € å<ä˜$¤Ô0BÐ CÔDØÙ)¨$Ó/Ð/ru   c                ób   ‡— | j                  «       }t        ˆfd„|D «       «      }||z
  | _        y )Nc              3  óB   •K  — | ]  }‰j                  ||«      –— Œ y ­wr~   )r±  )r·   ÚkÚmutation_real_names     €rs   r¹   z3BaseSchedulerNode.set_last_usage.<locals>.<genexpr>+  s   øè ø€ Ò!UÀ1Ð"4×"8Ñ"8¸¸A×">Ñ!Uùó   ƒ)Úused_or_aliased_buffer_namesr   r"  )rr   Úfuture_used_buffersr�  Úused_bufferss     ` rs   Úset_last_usagez BaseSchedulerNode.set_last_usage'  s0   ø€ ð ×8Ñ8Ó:ˆÜ!Ó!UÈÔ!UÓUˆØ&Ð)<Ñ<ˆ�ru   c                óF   — | j                   D ]  }|j                  «        Œ y r~   )r,  r	  )rr   rÞ   s     rs   Úmark_runzBaseSchedulerNode.mark_run.  s   € Ø—<‘<ò 	ˆCØ�L‰L�Nñ	ru   c                óž   — t        d„ t        j                  | j                  j                  | j                  j
                  «      D «       «      S )Nc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   z6BaseSchedulerNode.used_buffer_names.<locals>.<genexpr>3  s   è ø€ ò 
àð �H�Hñ
ùrv  )r   Ú	itertoolsÚchainrÕ   rÖ   rQ  rq   s    rs   rã   z#BaseSchedulerNode.used_buffer_names2  s?   € Üñ 
ä —‘ t×'7Ñ'7×'=Ñ'=¸t×?OÑ?O×?VÑ?VÓWô
ó 
ð 	
ru   c                ó\  ‡— t        «       Št        j                  | j                  j                  | j                  j
                  «      D �cg c]*  }t        |t        «      r|j                  s|j                  ‘Œ, }}t        |«      dkD  rœ|j                  «       }‰j                  |«       t        j                  j                  j!                  |«      rC|j#                  ˆfd„t        j                  j                  |   j%                  «       D «       «       t        |«      dkD  rŒœ‰S c c}w )zË
        Returns buffer names used by this node, including aliases.

        Note: is_fake WeakDeps are excluded since they are purely for ordering
        and should not affect buffer lifetime.
        r   c              3  ó*   •K  — | ]
  }|‰vr|–— Œ y ­wr~   r…   )r·   ÚaliasÚ
used_namess     €rs   r¹   zABaseSchedulerNode.used_or_aliased_buffer_names.<locals>.<genexpr>J  s#   øè ø€ ò àð  JÑ.ô	 ñùs   ƒ)r   rš  r›  rÕ   rÖ   rQ  r²   r;   Úis_faker×   rÎ   ÚpopÚaddra   rÁ   Úname_to_bufferr±  Úextendrû  )rr   rà   ÚdepsrŸ  s      @rs   r’  z.BaseSchedulerNode.used_or_aliased_buffer_names8  sì   ø€ ô '1£lˆ
ô !—‘ t×'7Ñ'7×'=Ñ'=¸t×?OÑ?O×?VÑ?VÓWö
àÜ˜s¤GÔ,°·²ð �H‹Hð
ˆð 
ô
 �$‹i˜!ŠmØ—(‘(“*ˆCØ�N‰N˜3ÔÜ�w‰w×%Ñ%×)Ñ)¨#Ô.Ø—‘ó ä!"§¡×!7Ñ!7Øñ"ç2Ñ2Ó4ô	ô ô	 �$‹i˜!‹mð Ðùò!
s   Á/D)c                óL   ‡ — t        ˆ fd„‰ j                  D «       «      ‰ _        y )Nc              3  óf   •K  — | ](  }|j                   ‰j                  j                  vr|–— Œ* y ­wr~   )r×   rÜ  Úavailable_buffer_names©r·   rà   rr   s     €rs   r¹   z/BaseSchedulerNode.prune_deps.<locals>.<genexpr>T  s/   øè ø€ ò -
àØ�x‰x˜tŸ~™~×DÑDÑDô ñ-
ùs   ƒ.1©r   r3  rq   s   `rs   r†  zBaseSchedulerNode.prune_depsS  s#   ø€ Ü",ó -
à×.Ñ.ô-
ó #
ˆÕru   c                ó¸   ‡ ‡— dˆ fd„Št        ˆfd„‰ j                  j                  D «       «      }‰ j                  ‰ j                  j	                  |«      «       y )Nc                ó  •— t        | t        «      sy| j                  ‰j                  j                  vry‰j                  j                  | j                     j                  «       }|t        j                  j                  v S rm  )	r²   r;   r×   rÜ  r  rä  ra   rÁ   Úremoved_operations)rà   Úop_namerr   s     €rs   Úshould_prunez7BaseSchedulerNode.prune_weak_deps.<locals>.should_prune\  s_   ø€ Ü˜c¤7Ô+ØØ�x‰x˜tŸ~™~×9Ñ9Ñ9Øà—n‘n×0Ñ0°·±Ñ:×KÑKÓMˆGØœaŸg™g×8Ñ8Ð8Ð8ru   c              3  ó4   •K  — | ]  } ‰|«      sŒ|–— Œ y ­wr~   r…   ©r·   rà   r¯  s     €rs   r¹   z4BaseSchedulerNode.prune_weak_deps.<locals>.<genexpr>e  s   øè ø€ ò 
Ø±\À#Õ5FŒCñ
ùó   ƒ‘©rà   r8   r�   r}   )r   rÕ   rÖ   rx  Úremove_reads)rr   Ú	to_remover¯  s   ` @rs   Úprune_weak_depsz!BaseSchedulerNode.prune_weak_depsZ  sN   ù€ õ	9ô ó 
Ø×+Ñ+×1Ñ1ô
ó 
ˆ	ð 	×Ñ˜T×-Ñ-×:Ñ:¸9ÓEÕFru   c                óF   — t        | || j                  j                  «       y r~   )Ú_prune_redundant_depsrÜ  r  )rr   Úname_to_fused_nodes     rs   Úprune_redundant_depsz&BaseSchedulerNode.prune_redundant_depsj  s   € ô 	˜dÐ$6¸¿¹×8RÑ8RÕSru   c                óR   — | j                   €J ‚| j                   j                  «       S r~   )r”   Úget_operation_namerq   s    rs   râ  zBaseSchedulerNode.get_nameo  r  ru   c                ó"   — | j                  «       S r~   ©râ  rq   s    rs   Úget_first_namez BaseSchedulerNode.get_first_names  s   € Ø�}‰}‹Ðru   c                óB   — t        d„ | j                  «       D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   r¾  ©r·   r”   s     rs   r¹   z8BaseSchedulerNode.get_operation_names.<locals>.<genexpr>x  s   è ø€ ÒG¨d˜$Ÿ-™-Ÿ/ÑGùó   ‚)r   r»   rq   s    rs   r  z%BaseSchedulerNode.get_operation_namesv  s   € äÑG°d·n±nÓ6FÔGÓGÐGru   c                ó:   — t        d„ | j                  D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   r¾  ©r·   rå   s     rs   r¹   z5BaseSchedulerNode.get_buffer_names.<locals>.<genexpr>|  s   è ø€ ÒA¨S˜#Ÿ,™,Ÿ.ÑAùrÃ  )r   r,  rq   s    rs   Úget_buffer_namesz"BaseSchedulerNode.get_buffer_namesz  s   € äÑA°D·L±LÔAÓAÐAru   c                óB   — t        d„ | j                  «       D «       «      S )Nc              3  óZ   K  — | ]#  }t        |t        «      xr t        |d ¬«      –— Œ% y­w)T)Údisallow_fp32_opsN©r²   r³   r2   ©r·   Úns     rs   r¹   zABaseSchedulerNode.can_codegen_in_low_precision.<locals>.<genexpr>€  s7   è ø€ ò 
ð ô �qœ-Ó(ò GÜ+¨AÀÔFóGñ
ùó   ‚)+©rº   r»   rq   s    rs   Úcan_codegen_in_low_precisionz.BaseSchedulerNode.can_codegen_in_low_precision~  s%   € äñ 
ð —^‘^Ó%ô
ó 
ð 	
ru   c                óB   — t        d„ | j                  «       D «       «      S )Nc              3  óV   K  — | ]!  }t        |t        «      xr t        |«      –— Œ# y ­wr~   rË  rÌ  s     rs   r¹   z@BaseSchedulerNode.can_codegen_without_upcasts.<locals>.<genexpr>ˆ  s-   è ø€ ò 
àô �qœ-Ó(ÒKÔ-HÈÓ-KÓKñ
ùs   ‚')rÏ  rq   s    rs   r2   z-BaseSchedulerNode.can_codegen_without_upcasts†  s#   € äñ 
à—^‘^Ó%ô
ó 
ð 	
ru   c                ó   — | gS r~   r…   rq   s    rs   r»   zBaseSchedulerNode.get_nodes�  s	   € Øˆvˆru   c                ó   — | j                   S r~   )r,  rq   s    rs   r<  zBaseSchedulerNode.get_outputs�  s   € Ø�|‰|Ðru   c                ó    — | j                   |   S r~   )r.  )rr   Úbuf_names     rs   Ú
get_outputzBaseSchedulerNode.get_output“  s   € Ø×#Ñ# HÑ-Ð-ru   c                óR   — | j                   €J ‚| j                   j                  «       S r~   )r”   rª   rq   s    rs   rª   zBaseSchedulerNode.get_device–  s%   € Ø�y‰yÐ$Ð$Ð$Ø�y‰y×#Ñ#Ó%Ð%ru   c                óL   — | j                  «       }|d uxr |j                  dk(  S ©NÚcpu)rª   r«   ©rr   Údevices     rs   Úis_cpuzBaseSchedulerNode.is_cpuš  s'   € Ø—‘Ó"ˆØ˜TÐ!Ò: f§k¡k°UÑ&:Ð:ru   c                óX   — | j                  «       }|d uxr t        |j                  «      S r~   )rª   r[   r«   rÜ  s     rs   r[   zBaseSchedulerNode.is_gpuž  s'   € Ø—‘Ó"ˆØ˜TÐ!Ò9¤f¨V¯[©[Ó&9Ð9ru   c                 ó   — yrm  r…   rq   s    rs   r´   zBaseSchedulerNode.is_reduction¢  ó   € Øru   c                 ó   — yrm  r…   rq   s    rs   Úis_native_matmulz"BaseSchedulerNode.is_native_matmul¥  rá  ru   c                 ó   — yrm  r…   rq   s    rs   Úis_split_scanzBaseSchedulerNode.is_split_scan¨  rá  ru   c                 ó   — yrm  r…   rq   s    rs   Úis_templatezBaseSchedulerNode.is_template«  rá  ru   c                 ó   — yrm  r…   rq   s    rs   Ú	is_externzBaseSchedulerNode.is_extern®  rá  ru   c                 ó   — yrm  r…   rq   s    rs   Ú
is_foreachzBaseSchedulerNode.is_foreach±  rá  ru   c                 ó   — yrm  r…   ©rr   Úread_deps     rs   Úcan_inplacezBaseSchedulerNode.can_inplace´  rá  ru   c                 ó   — yrm  r…   rq   s    rs   Úhas_side_effectsz"BaseSchedulerNode.has_side_effects·  rá  ru   c           	     ó  ‡ — ddl m} t        ‰ t        «      rÇt        j
                  r·t        j                  j                  ‰ j                  «       t        j                  «      r{t        t        j                  t        j                  j                  j                   j"                  «      rt%        t        j                  dd«      �t'        t        j                  d«      sy‰ j(                  t        j                  j*                  z  ‰ j,                  j.                  z  }dˆ fd„}‰ j1                  «       D �]Q  }|j2                  }|€J ‚|j5                  «       rr|j7                  «       sb|j9                  «       sR|j;                  «       t        j                  j<                  v s(t        |j?                  «       t@        jB                  «      rŒ—‰ jD                  jF                  D �]¡  }|jH                  ‰ j,                  jJ                  v r$‰ j,                  jJ                  |jH                     }n/‰ j,                  jL                  jO                  |jH                  «      }|sŒ|t        j                  jP                  jS                  |‰ «      sŒ§t        |jT                  tV        «      rŒÂ|jX                  €J ‚|jX                  D �cg c]   }|j2                  j;                  «       |vr|‘Œ" }	}‰ j,                  j[                  |jH                  ‰ «      }
|
r�Œ/t]        |	«      dk(  s�Œ?|	d   j^                  s�ŒP|	d   j2                  ‰ u s�Œc|j2                  €�Œqt        |j2                  j?                  «       t@        j`                  t@        jb                  t@        jd                  t@        jB                  f«      r�ŒÓ|jT                  rft        |jT                  j2                  t@        jf                  t@        jh                  f«      r(t]        |j2                  j7                  «       «      dkD  r�ŒE ||j2                  |j2                  «      s�Œd ||«      s�Œnt        j                  jj                  jm                  |j;                  «       |j;                  «       «       t        t        j                  t        j                  j                  j                   j"                  «      rnt        j                  jn                  jq                  |j;                  «       «       t        j                  jn                  jq                  |j;                  «       «       |j;                  «       t        j                  jr                  |j;                  «       <    �ŒQ �ŒT yc c}w )	z~
        Decide if there should be inplace updates for the node
        and record the decision in the active kernel.
        r   )Úcan_match_buffer_sizeÚ	mutationsNrù  c                óÂ  •‡— | j                   j                  ‰«      }| j                  «       Št        «       }| j                  D ]™  }|j
                  }t        |t        «      sŒ |j                  «       | j                   j                  vs| j                   j                  |«      |urŒd|ˆfd„|j                  j                  «       D «       z  }t        |«      dkD  sŒ™ y y)Nc              3  ó@   •K  — | ]  }|j                   ‰k(  r|–— Œ y ­wr~   rt  )r·   ÚorÖ  s     €rs   r¹   z^BaseSchedulerNode.decide_inplace_update.<locals>.single_index_in_fused_node.<locals>.<genexpr>í  s%   øè ø€ ò àØ—v‘v Ò)ô ñùó   ƒr   FT)rÜ  Úget_fused_noderâ  r   rß  r”   r²   rf   r¿  r¹  rÕ   rw  rÎ   )Úbuf_to_be_inplacedÚ
fused_noder¥  ró  Ú	user_noderÖ  rr   s        @€rs   Úsingle_index_in_fused_nodezKBaseSchedulerNode.decide_inplace_update.<locals>.single_index_in_fused_nodeÕ  sÝ   ù€ ð
 ,×5Ñ5×DÑDÀTÓJˆJØ)×2Ñ2Ó4ˆHô %/£LˆDØ*×0Ñ0ò !�Ø ŸI™I�	Ü! )Ô->Ô?Øð ×,Ñ,Ó.Ø-×7Ñ7×JÑJñKà)×3Ñ3×BÑBÀ9ÓMØ%ñ&ð àó à&×2Ñ2×CÑCÓEôñ �ô
 �t“9˜q“=Ù ð'!ð* ru   r   )rú  rÚ  r�   r}   ):Úcodegen.wrapperró  r²   r³   r-   Úinplace_buffersra   rÁ   Úhas_featurerª   r3   ÚINPLACE_BUFFERSr  r`  ra  ÚcodegenÚsimdr€  r½  r  r  r­  rÜ  Úcompleted_operationsr<  r”   rú  rû  rü  râ  Úremoved_buffersrý  r0   rþ  rÕ   rÖ   r×   r  r  r±  rÿ  Ú	can_reuserÝ  ÚNopKernelSchedulerNoderß  Úhas_cross_stream_hazardrÎ   rï  rD   rC   ÚMutationLayoutSHOULDREMOVEÚFallbackKernelrB   rù  Úmake_inplacerô  r¢  r  )rr   ró  Úinconsequential_nodesrý  rÞ   Úbuf_nodeÚreadÚ	input_bufrˆ  Úremaining_usesr  s   `          rs   Údecide_inplace_updatez'BaseSchedulerNode.decide_inplace_updateº  sô  ø€ õ
 	;ô �tœ]Ô+Ü×&Ò&Ü—‘×#Ñ# D§O¡OÓ$5´~×7UÑ7UÔVäœqŸx™x¬¯©×)@Ñ)@×)EÑ)E×)PÑ)PÔQÜœ1Ÿ8™8 [°$Ó7ÐCô œŸ™ &Ô)àð �N‰NÜ�g‰g×(Ñ(ñ)à�n‰n×1Ñ1ñ2ð 	õ 	ðD ×#Ñ#Ó%ó L	ˆCØ—x‘xˆHØÐ'Ð'Ð'à×,Ñ,Ô.Ø×8Ñ8Ô:Ø×.Ñ.Ô0Ø—<‘<“>¤Q§W¡W×%<Ñ%<Ñ<ô ˜h×6Ñ6Ó8¼"×:MÑ:MÔNàà×(Ñ(×.Ñ.ó >�à—9‘9 §¡× EÑ EÑEØ $§¡× EÑ EÀdÇiÁiÑ P‘Ià $§¡× :Ñ :× >Ñ >¸t¿y¹yÓ I�Iò ÜŸ™×,Ñ,×6Ñ6°yÀ$ÕGÜ& y×'<Ñ'<Ô>TÕUà$Ÿ?™?Ð6Ð6Ð6ð "+§¡ö&àØŸ6™6Ÿ?™?Ó,Ð4IÑIò ð&�Nð &ð
 /3¯n©n×.TÑ.TØŸ	™	 4ó/Ð+ó
 4Ü Ó/°1Ô4Ø*¨1Ñ-×9Ô9Ø*¨1Ñ-×2Ñ2°dÓ:Ø%ŸN™NÒ6Ü *Ø%ŸN™N×:Ñ:Ó<ä "§¡Ü "× 4Ñ 4Ü "× =Ñ =Ü "× 3Ñ 3ð	ö!ð &×1Ò1Ü *Ø )× 5Ñ 5× :Ñ :Ü!#×!2Ñ!2´B·N±NÐ Cô!ô !$ I§N¡N×$OÑ$OÓ$QÓ RÐUVÔ Vá1°)·.±.À#Ç(Á(ÖKÙ6°yÖAô
 Ÿ™Ÿ™×2Ñ2°9×3EÑ3EÓ3GÈÏÉËÔXä%ÜŸH™H¤e§o¡o×&=Ñ&=×&BÑ&B×&MÑ&Môô ŸH™H×.Ñ.×2Ñ2°9×3EÑ3EÓ3GÔHÜŸH™H×.Ñ.×2Ñ2°3·<±<³>ÔBð &×.Ñ.Ó0ô Ÿ™×7Ñ7¸¿¹»ÑGò ò}>ñL	ùò6&s   Ê?%V
c                óR  — t         j                  sy |r| j                  ry | j                  €J ‚| j                  j	                  «       }g }|D �]0  }|j
                  dk(  rŒ|j                  d«       |j                  d«       d|j
                  › d|j                  › �}d|j                  v r|d|j                  d   › �z   }|j                  |«       d|j                  v sŒ•|j                  d   › }|j                  d	d
¬«      d   }|j                  d|j                  dd«      j                  dd«      j                  dd«      j                  dd«      z   «       |j                  d«       |j                  d«       �Œ3 t        |«      dk(  ry |j                  |«       d| _        y )Nr=  rX  z#pragma CMT ORIGIN:z#pragma CMT ú Úseq_nrz seq_nr:Ústack_traceú|r   )Úmaxsplitr  ú{z{{ú}z}}rH  ú\z\\z#pragma CMT END ORIGINr   T)r-   Úcomment_originr4  r”   Úget_originsrã  rä   ÚtargetÚmetaÚrsplitÚreplacerÎ   Ú
writelines)	rr   ÚbufferÚ	only_onceÚoriginsÚ	out_linesr÷  Úop_info_strr  Ústack_trace_last_lines	            rs   Úcodegen_originating_infoz*BaseSchedulerNode.codegen_originating_infoE  s™  € ô ×$Ò$Øá˜ŸšØØ�y‰yÐ$Ð$Ð$Ø—)‘)×'Ñ'Ó)ˆØˆ	àó 	%ˆAØ�t‰t�xÒàà×Ñ˜RÔ à×ÑÐ2Ô3Ø(¨¯©¨¨a°·±¨zÐ:ˆKØ˜1Ÿ6™6Ñ!Ø)¨h°q·v±v¸hÑ7GÐ6HÐ,IÑI�Ø×Ñ˜[Ô)Ø §¡Ò&Ø!"§¡¨Ñ!6Ð 7�Ø(3×(:Ñ(:¸3ÈÐ(:Ó(KÈBÑ(OÐ%Ø× Ñ Ø"Ø+×3Ñ3°C¸Ó>ß‘W˜S $Ó'ß‘W˜T 4Ó(ß‘WØ˜fóñ	ôð × Ñ Ð!9Ô:Ø× Ñ  Ö$ð3	%ô6 ˆy‹>˜QÒØð 	×Ñ˜)Ô$Øˆ�ru   c                ó(   — | j                  dd¬«      S )NT©Úinclude_readsÚinclude_writes©Ú!get_read_write_buffers_sizes_implrq   s    rs   Úget_read_write_buffers_sizesz.BaseSchedulerNode.get_read_write_buffers_sizest  s   € à×5Ñ5Ø¨tð 6ó 
ð 	
ru   c                ó(   — | j                  dd¬«      S )NTFr*  r-  rq   s    rs   Úget_read_buffer_sizesz'BaseSchedulerNode.get_read_buffer_sizesz  s   € à×5Ñ5Ø¨uð 6ó 
ð 	
ru   c                ó(   — | j                  dd¬«      S )NFTr*  r-  rq   s    rs   Úget_write_buffer_sizesz(BaseSchedulerNode.get_write_buffer_sizes€  s   € à×5Ñ5Ø°ð 6ó 
ð 	
ru   c                óZ   — t        | j                  ||¬«      j                  «       d¬«      S )Nr*  r   )Ústart)rü   Úget_read_write_buffer_accessesrÝ   )rr   r+  r,  s      rs   r.  z3BaseSchedulerNode.get_read_write_buffers_sizes_impl†  s3   € ô Ø×/Ñ/Ø+¸Nð 0ó ç‰f‹hØô	
ð 	
ru   c                ó  ‡ ‡‡‡‡‡— t        ‰ t        «      ri S t        ‰ t        «      rt        ‰ j                  t        «      ri S t        ‰ t        «      r`t        ‰ j                  t
        j                  «      r<‰ j                  j                  t        j                  j                  j                  u ri S dd„Št        ‰ t        «      r@ ‰t        ‰ j                  «       d   «      t        ‰ j                  «       d   «      z  «      Šnt        d«      Št!        j"                  t$        «      }|r9‰ j&                  j(                  D ]   }||j*                     j-                  |«       Œ" |r9‰ j&                  j.                  D ]   }||j*                     j-                  |«       Œ" |r&t1        d„ ‰ j&                  j(                  D «       «      n	t1        «       }|r&t1        d„ ‰ j&                  j.                  D «       «      n	t1        «       }dˆ fd„Št        ‰ t2        «      rt1        ˆˆ fd„|D «       «      }||z
  }||z
  }i }||z  D ]º  }	t5        ˆfd	„||	   D «       «      Š|	t6        j8                  j:                  v rt6        j8                  j:                  |	   }
n;|	t6        j8                  j<                  v rt6        j8                  j<                  |	   }
nŒ�	 	 	 	 dˆˆˆ ˆfd
„Š ‰|
«      }|	|vr|||	<   Œ®||	xx   |z  cc<   Œ¼ |S )az  
        Counting the number of bytes accessed for a kernel is
        surprisingly tricky. In particular, there is a differentiation
        between 'theoretical' memory accesses and practical memory
        accesses. For example, a layernorm kernel may actually access an
        input 3 times, but in theory, it only needs to access its input
        once (and may be optimized to do so through say, persistent
        reductions)

        Another example is that even though a buffer is passed in, we may
        not access the entire buffer. This may occur if we are accessing
        a slice of the buffer. Another tricky case is for indirect
        indexing, where the amount of bytes accessed depends on the
        values of the input.

        What this function aims to compute is the memory accesses for
        worst-case inputs, best-case optimization. What this means is
        that for each buffer we compute the amount of potential accesses in two ways and take the minimum.

        1. Numel in ranges multiplied by number of deps the buffer has
        2. The buffer size

        Returns memory accesses per buffer.
        c                óX   — t         j                  j                  j                  | d¬«      S )Nr   rí   )ra   rÁ   rÂ   rï   )Úss    rs   Útry_size_hintzGBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.try_size_hintº  s"   € Ü—7‘7×#Ñ#×5Ñ5°aÀ!Ð5ÓDÐDru   r   r   ç    eÍÍAc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zCBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.<genexpr>Ï  s   è ø€ ÒB C�s—x•xÑBùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zCBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.<genexpr>Ô  ó   è ø€ ÒC C�s—x•xÑCùrv  c                ó¢   •— ‰j                   j                  |    j                  }t        d„ |D «       «      }t	        |t        |«      z
  «      dkD  S )Nc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   r¼   )r·   ró  s     rs   r¹   z\BaseSchedulerNode.get_read_write_buffer_accesses.<locals>.is_materialized.<locals>.<genexpr>Û  s   è ø€ Ò!>° $§)¥)Ñ!>ùrv  r   )rÜ  r  rß  r   rÎ   )rÞ   rÛ   rß  Úbuf_usesrr   s       €rs   Úis_materializedzIBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.is_materializedÙ  sG   ø€ Ø—N‘N×.Ñ.¨sÑ3×9Ñ9ˆEÜ!Ñ!>¸Ô!>Ó>ˆHÜ�x¤*¨VÓ"4Ñ4Ó5¸Ñ9Ð9ru   c              3  óJ   •K  — | ]  } ‰|‰j                   «      rŒ|–— Œ y ­wr~   ©rÛ   )r·   rà   rB  rr   s     €€rs   r¹   zCBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.<genexpr>ß  s#   øè ø€ ò )Ø©_¸SÀ$Ç+Á+Õ-N”ñ)ùs   ƒ#œ#c              3  ó"   •K  — | ]  }‰–— Œ y ­wr~   r…   )r·   rà   Ú
node_numels     €rs   r¹   zCBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.<genexpr>è  s   øè ø€ Ò$R°C¤ZÑ$Rùs   ƒc                óB  •— | syt        | t        j                  «      r| j                  «       S t        | j                  t
        «      rÍ‰j                  j                  | j                  «          j                  }d}|D ]“  }t        |j                  t        «      rŒt        |j                  t        «      sJ ‚t        |j                  j                  t        «      r5|j                  j                  «       D ]  }| ‰|j                  «      z  }Œ Œ“ y |S t        | j                  t        j                  «      r"t!        ˆfd„| j#                  «       D «       «      S  ‰	t%        | j'                  «       «      «      }t)        | j+                  «       «      t-        ‰|«      z  S )Nr   c              3  óh   •K  — | ])  } ‰t         j                  j                  |«      «      –— Œ+ y ­wr~   )ra   rÁ   Ú
get_buffer)r·   Úmut_nameÚget_buf_bytess     €rs   r¹   zZBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.get_buf_bytes.<locals>.<genexpr>  s-   øè ø€ ò à$ñ &¤a§g¡g×&8Ñ&8¸Ó&B×Cñùs   ƒ/2)r²   r0   ÚTorchBindObjectrK  rí  rC   rÜ  r  râ  rß  r”   r  rf   rB   r<  rD   rü   rü  r_   rc  rT   Ú	get_dtyperZ  )
rÞ   rß  Útotró  Ú	sched_bufÚ	buf_elemsÚbuf_accessed_elemsrK  rr   r:  s
         €€€€rs   rK  zGBaseSchedulerNode.get_read_write_buffer_accesses.<locals>.get_buf_bytesñ  sT  ø€ ñ Øä˜c¤2×#5Ñ#5Ô6Ø×,Ñ,Ó.Ð.Ü §
¡
Ô,=Ô>ð !ŸN™N×6Ñ6°s·|±|³~ÑF×LÑL�EØ�CØ %ò %˜Ü% d§i¡i´Ô<Ø$Ü)¨$¯)©)Ô5FÔGÐGÐGÜ% d§i¡i§n¡n´kÔBØ-1¯Y©Y×-BÑ-BÓ-Dò E 	Ø #¡}°Y·^±^Ó'DÑ D¡ñEñ $%ð%ð �JÜ §
¡
¬B¯M©MÔ:Üó à(+×(>Ñ(>Ó(@ôó ð ñ
 !.¬m¸C¿L¹L»NÓ.KÓ L�IÜ)¨#¯-©-«/Ó:¼SØ*¨Ió>ñ ð ru   )r9  rR  r�   r‘   )rÞ   r,  rÛ   rÔ  r�   r}   )rÞ   z4ir.Buffer | ir.TensorBox | ir.TorchBindObject | Noner�   r‘   )r²   r  ÚExternKernelSchedulerNoder”   rB   r0   r
  Úop_overloadr`  Ú_primsÚ	rng_primsÚgraphsafe_run_with_rng_stater³   r_   r\  r‘   Úcollectionsr   r¥   rÕ   rÖ   r×   rä   rQ  r   rÚ   rü   ra   rÁ   r£  Úgraph_inputs)rr   r+  r,  Úbuf_accessesrà   rÖ   rQ  r  Úbuf_byte_accessesrÖ  rÞ   Ú	buf_bytesrQ  rK  rB  rF  r:  s   `           @@@@@rs   r6  z0BaseSchedulerNode.get_read_write_buffer_accesses�  s»  ý€ ô6 �dÔ2Ô3ØˆIÜ�dÔ5Ô6¼:Ø�I‰I”{ô<
ð ˆIä�tÔ6Ô7Ü˜4Ÿ9™9¤b×&7Ñ&7Ô8Ø—	‘	×%Ñ%Ü�|‰|×%Ñ%×BÑBñCð ˆIó	Eô �dœMÔ*Ù&Ü˜dŸo™oÓ/°Ñ2Ó3Ü §¡Ó 1°!Ñ 4Ó5ñ6ó‰Jô
 ˜S›ˆJÜ"×.Ñ.¬tÓ4ˆáØ×'Ñ'×-Ñ-ò 3�Ø˜SŸX™XÑ&×-Ñ-¨cÕ2ð3ñ Ø×'Ñ'×.Ñ.ò 3�Ø˜SŸX™XÑ&×-Ñ-¨cÕ2ð3ñ
 ô ÑB¨4×+;Ñ+;×+AÑ+AÔBÔBä“ð 	ñ ô ÑC¨4×+;Ñ+;×+BÑ+BÔCÔCä“ð 	õ	:ô
 �dÔ.Ô/Ü(ô )Ø%ô)ó ˆOð ˜oÑ-ˆFØ˜OÑ+ˆEà,.Ðà ™ò 3	9ˆHÜ!$Ó$R¸<ÈÑ;QÔ$RÓ!RÐàœ1Ÿ7™7×1Ñ1Ñ1Ü—g‘g×,Ñ,¨XÑ6‘ØœQŸW™W×1Ñ1Ñ1Ü—g‘g×*Ñ*¨8Ñ4‘àð#ØIð#à÷#ð #ñJ & cÓ*ˆIØÐ0Ñ0Ø.7Ð! (Ò+à! (Ó+¨yÑ8Ô+ðg3	9ðj !Ð ru   c                óT  — | j                   €y | j                   j                  «       }|€y t        |«      }|€y t        |t        j
                  «      r|j                   j                  }t        j                  j                  j                  |d¬«      }t        d   dxx   |z  cc<   |S )Nr   rí   ÚinductorÚ
flop_count)r”   Úget_origin_noder>   r²   r`  ÚSymIntÚexprra   rÁ   rÂ   rï   r   )rr   Úfx_nodeÚflopsÚresolved_flopss       rs   Úestimate_flopsz BaseSchedulerNode.estimate_flops  s�   € à�9‰9ÐØØ—)‘)×+Ñ+Ó-ˆØˆ?Øä˜wÓ'ˆØˆ=Øä�eœUŸ\™\Ô*Ø—J‘J—O‘OˆEäŸ™×)Ñ)×;Ñ;¸EÈAÐ;ÓNˆÜ�Ñ˜\Ó*¨nÑ<Ó*ØÐru   c                óR   — | j                   �| j                   S | j                  «       S r~   )r0  Ú_get_estimated_runtimerq   s    rs   Úget_estimated_runtimez'BaseSchedulerNode.get_estimated_runtime1  s)   € Ø×*Ñ*Ð6Ø×2Ñ2Ð2à×*Ñ*Ó,Ð,ru   c                óæ  — | j                  «       d   j                  «       d   }|j                  j                  «       }t	        t        |«      «      syt        | j                  «      r¿t        | j                  t        j                  «      sJ ‚	 t        j                  rst        | «      }t        «       }|j                  |«      }|�t        |t        «      sJ ‚|S t!        | «      }|€t#        | j                  «      }|j%                  ||¬«       |S t#        | j                  «      S t/        | j                  «      ryt1        | «      }|�|S |j                  j3                  «       }		 t5        «       }
t7        |	«      dz  }|
dk  rt9        d|
› �«      ‚|dk  rt9        d|› �«      ‚	 | j=                  «       }|dk(  s|€| j?                  «       |
z  }|dz  }|S d}| j?                  «       }|€dn|}||z  |z  d	z  }||
z  }tA        ||«      }|dz  }|S # t&        $ r}t(        j+                  |«       Y d}~yd}~wt,        $ r}t(        j+                  |«       Y d}~yd}~ww xY w# t:        $ r Y yw xY w)
zC
        Returns estimated op runtime in milliseconds (ms)
        r   N©Úvaluel    J)£z-gpu_memory_bandwidth cannot be <= 0, but got z"gpu_flops cannot be <= 0, but got g    €„.Ag      ð?r;  )!r»   r<  r”   rý  r[   r@   rY   r²   r0   ÚIRNoder.   Ú,runtime_estimations_use_nccl_lib_estimationsÚ)get_estimate_runtime_cache_key_from_snodeÚget_estimate_runtime_cacheÚlookupÚfloatr7   r6   Ú	set_valueÚ
ValueErrorrT  rj  Ú	TypeErrorr^   Ú maybe_estimate_runtime_benchmarkÚmaybe_get_dtyperU   rS   ÚAssertionErrorrS  re  r/  rY  )rr   rÞ   rí  Ú	cache_keyÚcacheÚ	cache_valÚmsr&  ÚretÚdtypeÚgpu_memory_bandwidthÚ	gpu_flopsÚ	flops_estÚnsÚfactorÚcounted_bytesÚcompute_timeÚtransfer_times                     rs   rg  z(BaseSchedulerNode._get_estimated_runtime7  sw  € ð
 �n‰nÓ˜qÑ!×-Ñ-Ó/°Ñ2ˆØ—‘×)Ñ)Ó+ˆÜ”o fÓ-Ô.àô ˜Ÿ™Ô#Ü˜dŸi™i¬¯©Ô3Ð3Ð3ðÜ×LÒLÜ IÈ$Ó O�IÜ6Ó8�EØ %§¡¨YÓ 7�IØ Ð,Ü)¨)´UÔ;Ð;Ð;Ø(Ð(äHÈÓN�BØ�zä=¸d¿i¹iÓH˜à—O‘O I°R�OÔ8Ø�IÜ7¸¿	¹	ÓBÐBô �T—Y‘YÔð
 ä.¨tÓ4ˆØˆ?ØˆJà—‘×(Ñ(Ó*ˆð	Ü#4Ó#6Ð Ü)¨%Ó0°6Ñ9ˆIð $ qÒ(Ü$ØCÐDXÐCYÐZóð ð ˜AŠ~Ü$Ð'IÈ)ÈÐ%UÓVÐVð ð
 ×'Ñ'Ó)ˆ	à˜Š>˜YÐ.à×2Ñ2Ó4Ð7KÑKˆBØ�c‘ˆBØˆIð ˆØ×9Ñ9Ó;ˆØ*Ð2™¸ˆØ Ñ*¨YÑ6¸#Ñ=ˆØ%Ð(<Ñ<ˆô �˜}Ó-ˆØ�#‰XˆØˆ	øôo ò ô —‘˜”ÜûÜò ä—‘˜”Üûðûô: ò 	Ùð	úsC   ÂAH Ã6H ÄH Å(>I$ È	I!ÈH6È6I!ÉIÉI!É$	I0É/I0c                 ó   — y r~   r…   rq   s    rs   Úget_template_nodez#BaseSchedulerNode.get_template_node�  ó   € Øru   c                ó.   — | j                  «       }|€J ‚|S r~   ©r‡  )rr   Útemplates     rs   Úget_template_node_or_throwz,BaseSchedulerNode.get_template_node_or_throw’  s!   € Ø×)Ñ)Ó+ˆØÐ#Ð#Ð#Øˆru   c                óf   — t        d„ t        | «      D «       «      }| d| }| |   }| |dz   d }|||fS )zQ
        For the list of nodes, get the prologue, template, and epilogue
        c              3  óH   K  — | ]  \  }}|j                  «       sŒ|–— Œ y ­wr~   ©rç  )r·   ÚirÍ  s      rs   r¹   zCBaseSchedulerNode.get_prologue_template_epilogue.<locals>.<genexpr>ž  s   è ø€ ÒP¡D A qÀÇÁÅœaÑPùs   ‚"›"Nr   )ÚnextÚ	enumerate)rq  Útemplate_indexÚprologueÚtemplate_nodeÚepilogues        rs   Úget_prologue_template_epiloguez0BaseSchedulerNode.get_prologue_template_epilogue—  sN   € ô ÑP¬I°eÓ,<ÔPÓPˆà˜˜.Ð)ˆØ˜nÑ-ˆØ˜¨!Ñ+Ð-Ð.ˆØ˜¨Ð0Ð0ru   )rÜ  rÛ  r�   r  )r”   úir.Operationr�   r  r  )r�   r-  r  ©rn  r9   ro  r9   r�   r}   ©rz  r(  r�   r  )rà   r8   r�   r  r  )r‡  r1  r�   r  )r�   zCoalesceVarAnalysis | None©r“  r™   r�  r(  r�   r  ©r�   r™   ©r¹  údict[str, BaseSchedulerNode]r�   r  ©r�   rÔ  )r�   zSequence[SchedulerBuffer])rÖ  r,  r�   rÚ  r  ©rî  zdependencies.Depr�   r}   ©T)r"  rX   r#  r}   r�   r  r  )r+  r}   r,  r}   r�   r‘   )r+  r}   r,  r}   r�   zdict[str, int]©r�   ú
int | None©r�   rq  ©r�   zir.TemplateBuffer | None)r�   zir.TemplateBuffer)rq  úlist[BaseSchedulerNode]r�   zJtuple[list[BaseSchedulerNode], BaseSchedulerNode, list[BaseSchedulerNode]])@r€   r�   r‚   rƒ   r”   r0  r4  r:  r>  rB  rô  rR  r[  rh  rk  rp  r{  r  rƒ  rx  r…  rO   r‹  r•  r—  rã   r’  r†  r¶  rº  râ  r¿  r  rÇ  rÐ  r2   r»   r<  r×  rª   rÞ  r[   r´   rã  rå  rç  ré  rë  rï  rñ  r  r(  r/  r1  r3  r.  r6  re  rh  rg  r‡  rŒ  r0  r—  r…   ru   rs   rf   rf   �  sÚ  … ØÓØBÓBØÓð ÓØÓØƒNØƒNØ'Ó'Ø$Ó$Ø $€DÐ
Ó$Ø"Ó"Ø/Ó/Ø/3Ð Ó3Ø(Ó(Ø'Ó'Ø€GˆTÓó
ó#ó4Bó*ó6ó+ó#ó
ðØ!ðØ.7ðà	óó
Mó>ó
ó
ó5ð ò0ó ð0ð=Ø#2ð=ØHVð=à	ó=óó
óó6
óGð TØ">ðTà	óTó
.óð òHó ðHð òBó ðBð ò
ó ð
ð ò
ó ð
óóó.ó&ó;ó:óóóóóóóóóIðX 9=ð-Ø$ð-Ø15ð-à	ó-ð^ ò
ó ð
ð
 ò
ó ð
ð
 ò
ó ð
ð

Ø!ð
Ø37ð
à	ó
ðL!Ø!ðL!Ø37ðL!à	óL!ð\ òó ðó$-ð òUó ðUónóð
 ð1Ø&ð1à	Sò1ó ñ1ru   c                 óR   — t         j                  j                  j                  «       S r~   )r`  ra  Ú	codecacheÚ
LocalCacher…   ru   rs   ro  ro  ¦  s   € ä�?‰?×$Ñ$×/Ñ/Ó1Ð1ru   c                óœ  ‡— t        | j                  dd«      }| j                  j                  }| j                  j                  g |¢| j                  j                  ¢| j                  j
                  «      }| j                  j
                  }t        j                  ||f«      \  }}dd„Št        |ft        ˆfd„|D «       «      z   «      }|S )NÚpython_kernel_namerX  c                ó�   — t        | t        j                  «      xr+ t        | t        j                  t        j                  f«       S r~   )r²   r0   rl  ÚGeneratorStateÚOpaqueObjectState©rˆ  s    rs   Ú_is_tensor_irz@get_estimate_runtime_cache_key_from_snode.<locals>._is_tensor_irµ  s<   € Ü˜!œRŸY™YÓ'ò 
´
Ø”×!Ñ!¤2×#7Ñ#7Ð8ó1
ð -
ð 	
ru   c              3  ód   •K  — | ]'  } ‰|«      rt        |j                  «       «      nd –— Œ) y ­wr~   )rÏ   rc  )r·   Úar°  s     €rs   r¹   z<get_estimate_runtime_cache_key_from_snode.<locals>.<genexpr>¼  s(   øè ø€ ÒUÀa¡}°QÔ'7”�a—j‘j“lÔ#¸TÓAÑUùs   ƒ-0r  )
r½  r”   ÚinputsÚfill_non_provided_argsÚconstant_argsr7  ÚpytreeÚtree_flattenr,  rÏ   )Úsnoder«  rù  r7  Ú	flat_argsÚflat_args_pytree_specrx  r°  s          @rs   rn  rn  «  s¼   ø€ Ü  §¡Ð-AÀ2ÓFÐØ�:‰:×Ñ€DØ�:‰:×,Ñ,Ø*ˆ$Ð*�—‘×)Ñ)Ð*Ø�
‰
×Ñó€Dð �Z‰Z×Ñ€FÜ'-×':Ñ':¸DÀ&¸>Ó'JÑ$€IÐ$ó
ô
 Ø	ÐÜ
ÓUÈ9ÔUÓ
Uñ	Vó€Ið Ðru   c                ó  — t        | t        «      sy t        | j                  t        j                  «      sy | j                  j
                  }t        |t        j                  j                  «      sy |j                  }ddl
m} ||vry |S )Nr   )Úflop_registry)r²   rR  r”   r0   ÚExternKernelrS  r`  Ú_opsÚ
OpOverloadÚoverloadpacketÚtorch.utils.flop_counterr¼  )r¸  rS  rã  r¼  s       rs   Ú_get_benchmarkable_extern_fnrÂ  Á  sk   € ô �eÔ6Ô7ØÜ�e—j‘j¤"§/¡/Ô2Øà—*‘*×(Ñ(€KÜ�k¤5§:¡:×#8Ñ#8Ô9Øà	×	#Ñ	#€Bå6à	�ÑØà€Iru   c                óZ  ‡ ‡— d }d }t         j                  rt        ‰ «      }|€y |}ˆ ˆfd„}ny t        ‰ «      }t	        «       }|j                  |«      }|�t        |t        «      sJ ‚|S ddlm	Š  |«       \  }}ddl
m}	 |	j                  |||ddd¬«      }
|j                  ||
¬	«       |
S )
Nc                 ó   •—  ‰‰ «      S r~   r…   )r¸  Úsnode_args_kwargss   €€rs   r8  z2maybe_estimate_runtime_benchmark.<locals>.<lambda>à  s   ø€ Ñ!2°5Ó!9€ ru   r   )rÅ  r   )Úbenchmarkeré   é
   )Úmemory_warmup_itersÚbenchmark_itersÚmax_benchmark_durationrj  )r-   Ú!runtime_estimations_mms_benchmarkrÂ  rn  ro  rp  r²   rq  ÚutilsrÅ  Ú$torch._inductor.runtime.benchmarkingrÆ  Ú	benchmarkrr  )r¸  Úbench_fnÚargs_kwargs_fnÚmm_fnrx  ry  rz  rù  r7  rÆ  r{  rÅ  s   `          @rs   ru  ru  ×  sÁ   ù€ Ø€HØ€NÜ×/Ò/Ü,¨UÓ3ˆØˆ=ØØˆä9‰àä9¸%Ó@€IÜ&Ó(€EØ—‘˜YÓ'€IØÐÜ˜)¤UÔ+Ð+Ð+ØÐå(á!Ó#�L€Dˆ&Ý@à	×	Ñ	ØØØØØØ!ð 
ó 
€Bð 
‡O�O�I R€OÔ(Ø€Iru   c                  óN   — e Zd ZU ded<   ded<   ded<   ded<   dd„Zdd„Zdd	„Zy
)Ú	WhyNoFuser,  Úname1Úname2Úreasonútuple[Any, ...]rù  c                óX   — |j                  «       | _        |j                  «       | _        y r~   )râ  rÕ  rÖ  ©rr   rˆ   r‰   s      rs   r:  zWhyNoFuse.__init__  s   € Ø—^‘^Ó%ˆŒ
Ø—^‘^Ó%ˆ�
ru   c                óJ   — || _         || _        t        j                  | «       y r~   )r×  rù  Ú
fusion_logÚdebug)rr   r×  rù  s      rs   Ú__call__zWhyNoFuse.__call__  s   € ØˆŒØˆŒ	Ü×Ñ˜Õru   c                óp   — d| j                   › d| j                  › d�| j                  | j                  z  z   S )Nzcannot fuse z with ré  )rÕ  rÖ  r×  rù  rq   s    rs   Ú__str__zWhyNoFuse.__str__  s6   € Ø˜dŸj™j˜\¨°·
±
¨|¸2Ð>Ø�K‰K˜$Ÿ)™)Ñ#ñ
ð 	
ru   N©rˆ   rf   r‰   rf   r�   r  )r×  r,  rù  r   r�   r  r  )r€   r�   r‚   rƒ   r:  rÞ  rà  r…   ru   rs   rÔ  rÔ  ý  s&   … àƒJØƒJØƒKØ
Óó&óô

ru   rÔ  c                ó¼   — t        | t        t        f«      rt        | t        ¬«      } t        j                  | d¬«      }d|v rdt        j                  |d«      › �S |S )N©Úkeyé   )rñ  rH  ú    )	r²   r   ÚsetÚsortedr,  Úpprintrï  Útextwraprñ  )Úobjr³  s     rs   rï  rï    sR   € Ü�#œ
¤CÐ(Ô)ä�SœcÔ"ˆÜ�^‰^˜C¨Ô*€FØˆv�~Ø”H—O‘O F¨GÓ4Ð5Ð6Ð6Ø€Mru   c                  ó0   — e Zd Zdd„Zdd„Zdd„Zd	d„ZeZy)
r  c                ó&   — t        |g«      | _        y r~   rª  r~  s     rs   r:  zOutputNode.__init__  s   € Ü",¨c¨UÓ"3ˆÕru   c                 ó   — yrm  r…   rq   s    rs   r´   zOutputNode.is_reduction!  rá  ru   c                 ó   — yr°  r…   rq   s    rs   rû  z'OutputNode.get_inputs_that_alias_output$  rY  ru   c                 ó   — y)NÚOUTPUTr…   rq   s    rs   râ  zOutputNode.get_name'  s   € Øru   N)rà   r:   r�   r  r  r  r  )r€   r�   r‚   r:  r´   rû  râ  rB  r…   ru   rs   r  r    s   „ ó4óóóð �Hru   r  c                óÀ  ‡ ‡‡‡‡— t        j                  «       Š‰ j                  D ]N  }t        |t        «      rŒ‰|j
                     j                  «       }‰‰|   j                  «       xx   dz  cc<   ŒP dˆˆˆˆ fd„Št        ˆfd„‰ j                  D «       «      }|r?‰ j                  |z
  ‰ _        ‰ j                  ‰ j                  j                  |«      «       yy)am  
    Prunes weakdeps intended for mutation ordering
    on an upstream fused node if after fusion there is another dependency
    on the fused upstream node, making the weakdep redundant

    In essence this enforces an ordering on fusions. As fusions occur, weakdeps will
    be incrementally removed, enabling other fusions, ensuring they are fused in order.
    r   c                óò   •— t        | t        «      rf‰| j                     j                  «       }‰‰|   j	                  «          dkD  xr  ‰j
                  j                  | ‰|   ‰«      }‰|   ‰k(  }|xs |S y)Nr   F)r²   r;   r×   rä  râ  rÜ  Úfusable_weak_dep)rà   r®  Úis_redundantÚis_self_depr  Úname_to_dep_countr¹  r”   s       €€€€rs   r¯  z+_prune_redundant_deps.<locals>.should_pruneA  s�   ø€ Ü�cœ7Ô#Ø! #§(¡(Ñ+×<Ñ<Ó>ˆGØ,Ø" 7Ñ+×4Ñ4Ó6ñàñò à—n‘n×5Ñ5ØÐ'¨Ñ0°$óð ð -¨WÑ5¸Ñ=ˆKØÒ. ;Ð.àru   c              3  ó4   •K  — | ]  } ‰|«      sŒ|–— Œ y ­wr~   r…   r±  s     €rs   r¹   z(_prune_redundant_deps.<locals>.<genexpr>Q  s   øè ø€ ò Ø±,¸sÕ2CŒñùr²  Nr³  )rW  r   r3  r²   r;   r×   rä  râ  r   rx  rÕ   r´  )r”   r¹  r  rà   r®  Údeps_to_pruner÷  r¯  s   ```   @@rs   r¸  r¸  -  sÐ   ü€ ô '2×&9Ñ&9Ó&;Ðà×&Ñ&ò KˆÜ˜#œwÕ'Ø! #§(¡(Ñ+×<Ñ<Ó>ˆGØÐ0°Ñ9×BÑBÓDÓEÈÑJÔEðK÷
ð ô  ó Ø×.Ñ.ôó €Mñ Ø"&×"9Ñ"9¸MÑ"IˆÔØ×Ñ˜T×-Ñ-×:Ñ:¸=ÓIÕJð ru   c                  óH   ‡ — e Zd Zdˆ fd„Zdd„Zd	d„Zd	d„Zd
d„Zdd„Zˆ xZ	S )rR  c                ón  •— t         ‰| �  |«       | j                  |«       | j                  |j	                  «       «       t        |t        j                  «      r[|j                  «       rJt        j                  |j                  d   j                  «      }d}|j                  «       }|||ff| _        y y y ©Nr   r   )Úsuperr:  r>  rx  Úget_read_writesr²   r0   ÚUserDefinedTritonKernelÚcan_fuse_epilogueÚmathrý   Úmutable_argsÚshapeÚget_device_or_errorrÆ   )rr   rÜ  r”   ÚnumelrÈ   rÝ  Ú	__class__s         €rs   r:  z"ExternKernelSchedulerNode.__init__[  s›   ø€ Ü‰Ñ˜Ô#Ø×Ñ˜TÔ"Ø×Ñ˜T×1Ñ1Ó3Ô4ä�dœB×6Ñ6Ô7¸D×<RÑ<RÔ<TÜ—I‘I˜d×/Ñ/°Ñ2×8Ñ8Ó9ˆEØˆFØ×-Ñ-Ó/ˆFà  5¨& /Ð2ˆD�Jð =UÐ7ru   c                óV   — | j                  «       › dt        | j                  dd «      › �S )Nz.node.kernel = r«  )râ  r½  r”   rq   s    rs   rR  z)ExternKernelSchedulerNode.debug_str_extrag  s*   € Ø—-‘-“/Ð" /´'¸$¿)¹)ÐEYÐ[_Ó2`Ð1aÐbÐbru   c                 ó   — y©NTr…   rq   s    rs   ré  z#ExternKernelSchedulerNode.is_externj  rˆ  ru   c                ó‚   — | j                   €J ‚t        | j                   d«      xr | j                   j                  «       S )Nrñ  )r”   r  rñ  rq   s    rs   rñ  z*ExternKernelSchedulerNode.has_side_effectsm  s6   € Ø�y‰yÐ$Ð$Ð$Ü�t—y‘yÐ"4Ó5ÒV¸$¿)¹)×:TÑ:TÓ:VÐVru   c                óü   — t        | j                  t        j                  «      rU| j                  j	                  «       r;t        j                  | j                  j                  d   j                  «      }|gg fS g g fS ré   )	r²   r”   r0   rÿ  r   r  rý   r  r  )rr   r  s     rs   r\  z$ExternKernelSchedulerNode.get_rangesq  s^   € ä�t—y‘y¤"×"<Ñ"<Ô=Ø—	‘	×+Ñ+Ô-ä—I‘I˜dŸi™i×4Ñ4°QÑ7×=Ñ=Ó>ˆEØ�G˜R�=Ð Ø�Bˆxˆru   c                ó„   — t        | j                  t        j                  «      sJ ‚| j                  j	                  |«      S r~   )r²   r”   r0   r½  r  )rr   Úwrappers     rs   r  z!ExternKernelSchedulerNode.codegenz  s/   € Ü˜$Ÿ)™)¤R§_¡_Ô5Ð5Ð5Ø�y‰y× Ñ  Ó)Ð)ru   ©rÜ  rÛ  r”   r˜  r�   r  r  r  ©r�   úSequence[Sequence[sympy.Expr]]©r  r   r�   r  )
r€   r�   r‚   r:  rR  ré  rñ  r\  r  Ú__classcell__©r  s   @rs   rR  rR  Z  s#   ø„ õ
3ócóóWó÷*ru   rR  c                  ó    ‡ — e Zd Zdˆ fd„Zˆ xZS )r  c                ó„   •— t         ‰| �  |«       | j                  |«       | j                  |j	                  «       «       y r~   )rý  r:  r>  rx  rþ  ©rr   rÜ  r”   r  s      €rs   r:  zNopKernelSchedulerNode.__init__€  s5   ø€ Ü‰Ñ˜Ô#Ø×Ñ˜TÔ"Ø×Ñ˜T×1Ñ1Ó3Õ4ru   r  )r€   r�   r‚   r:  r  r  s   @rs   r  r    s   ø„ ÷5ñ 5ru   r  c                  óÀ  ‡ — e Zd ZU dZded<   ded<   	 	 	 	 	 	 d&ˆ fd„Z	 	 d'	 	 	 	 	 d(d„Z	 	 d'	 	 	 	 	 d)d„Z	 	 	 	 	 	 d*d	„Zd+d
„Z	d,d„Z
d-d„Zd.d„Zd/d„Zd0d„Zd.d„Zd1d„Zd.d„Z	 	 	 	 	 	 d2d„Zd.d„Z	 	 	 	 	 	 d3d„Zd4d„Zd5d„Zd6d„Zd6d„Zd6d„Zd6d„Zd7d„Zd8d„Z	 	 	 	 d9d„Zd:d„Z	 d;	 	 	 d<d „Ze d=d!„«       Z!e d=d"„«       Z"d>d#„Z#e d?d$„«       Z$e d6ˆ fd%„«       Z%ˆ xZ&S )@r³   zu
    A SchedulerNode is a node for scheduling that encapsulates either
    a ComputedBuffer or a TemplateBuffer.
    z tuple[Sequence[sympy.Expr], ...]Ú_sizesrE   r  c                ót   •— t         ‰| �  |«       d | _        | j                  |«       | j	                  «        y r~   )rý  r:  Ú_loop_mutation_listenerr>  Ú_compute_attrsr  s      €rs   r:  zSchedulerNode.__init__�  s4   ø€ ô
 	‰Ñ˜Ô#ØOSˆÔ$Ø×Ñ˜TÔ"Ø×ÑÕru   c                óâ  — t        | j                  t        j                  t        j                  f«      sJ ‚| j                  j                  ||¬«      \  | _        }|| _        | j                  j                  «       }| j                  j                  |«      j                  }| || j                  «      f| _        t        j                   xs t        |j                   «       }t        | j                  t        j                  «      r,| j#                  | j                  j%                  |¬«      «       y | j#                  t'        j$                  | j                  g| j                  ¢­d|iŽ«       y )N©Úextra_indexing_constraintsÚrecompute_sizes_body_func)Ú	normalizer   )r²   r”   r0   r   ÚTemplateBufferÚsimplify_and_reorderr  r  r  rÜ  Úget_backendÚgroup_fnrÆ   r-   Úloop_ordering_after_fusionr[   r«   rx  Úextract_read_writesr/   )rr   r  r  r²  rÝ  r$  Úshould_normalizes          rs   r  zSchedulerNode._compute_attrs™  s7  € ô
 ˜$Ÿ)™)¤b×&7Ñ&7¼×9JÑ9JÐ%KÔLÐLÐLØ ŸI™I×:Ñ:Ø'AØ&?ð ;ó 
ÑˆŒ�Tð ˆŒ
à—‘×.Ñ.Ó0ˆØ—>‘>×-Ñ-¨fÓ5×>Ñ>ˆØ™h t§{¡{Ó3Ð4ˆŒ
ô  &×@Ñ@Ð@ò 
ÌØ�K‰KóI
ð E
Ðô �d—i‘i¤×!2Ñ!2Ô3Ø× Ñ Ø—	‘	×-Ñ-Ð8HÐ-ÓIõð × Ñ Ü×0Ñ0Ø—J‘JðØ!%§¡òØ8Hñõru   c                ó  — t        d„ | j                  j                  D «       «      }| j                  ||¬«       |rD| j	                  | j                  j                  |«      j                  | j                  «      «       y y )Nc              3  óN   K  — | ]  }t        |t        t        f«      sŒ|–— Œ y ­wr~   ©r²   r;   r:   ru  s     rs   r¹   z8SchedulerNode.recompute_size_and_body.<locals>.<genexpr>¿  ó#   è ø€ ò 0
Ø´ZÀÄgÌwÐEWÕ5XŒCñ0
ùó   ‚%ž%r  )r   rÕ   rÖ   r  rx  r}  ry  r)  )rr   r  r  Ú	fake_depss       rs   Úrecompute_size_and_bodyz%SchedulerNode.recompute_size_and_bodyº  s   € ô
 &0ñ 0
Ø×+Ñ+×1Ñ1ô0
ó &
ˆ	ð 	×ÑØ'AØ&?ð 	ô 	
ñ Ø× Ñ Ø× Ñ ×*Ñ*¨9Ó5×<Ñ<¸T×=RÑ=RÓSõð ru   c                ó:  — t        d„ | j                  j                  D «       «      }| j                  t	        j
                  | j                  g| j                  ¢­d|iŽj                  |«      j                  | j                  «      «       | j                  |«       y )Nc              3  óN   K  — | ]  }t        |t        t        f«      sŒ|–— Œ y ­wr~   r*  ru  s     rs   r¹   z5SchedulerNode.refresh_dependencies.<locals>.<genexpr>Ð  r+  r,  r   )r   rÕ   rÖ   rx  r/   r&  r  r  r}  ry  r)  Ú clear_loop_body_dependent_caches)rr   r   Úneed_clear_tiling_cacher-  s       rs   Úrefresh_dependenciesz"SchedulerNode.refresh_dependenciesË  s�   € ô
 &0ñ 0
Ø×+Ñ+×1Ñ1ô0
ó &
ˆ	ð 	×ÑÜ×,Ñ,Ø—
‘
ðØ!Ÿ[™[òØ4=ñ÷ ‰Y�yÓ!ß‰V�D×)Ñ)Ó*ô	
ð 	×-Ñ-Ð.EÕFru   c                ó    — | j                  «        | j                  j                  | «       |r!ddlm} |j
                  j                  «        y y )Nr   r†  )r…  Úpointwise_read_writesr‰  r�  r‡  Úcandidate_tilingsÚcache_clear)rr   r2  r‡  s      rs   r1  z.SchedulerNode.clear_loop_body_dependent_cachesà  sA   € Ø×/Ñ/Ô1Ø×"Ñ"×.Ñ.¨tÔ4á"Ý4ð ×,Ñ,×8Ñ8Õ:ð #ru   c                ót   — | j                   | j                  | j                  | j                  | j                  fS )z¶Snapshot mutable state modified by loop transformations
        (apply_new_loop_order, apply_loop_reindexing). Must be kept
        in sync with those methods and restore_loop_state.)r  r  rÆ   rÕ   r3  rq   s    rs   Úsnapshot_loop_statez!SchedulerNode.snapshot_loop_stateí  s5   € ð
 �J‰JØ�K‰KØ�J‰JØ×ÑØ×#Ñ#ð
ð 	
ru   c                ój   — |\  | _         | _        | _        | _        | _        | j                  d¬«       y)z'Restore state from snapshot_loop_state.T)r2  N)r  r  rÆ   rÕ   r3  r1  )rr   Ústates     rs   Úrestore_loop_statez SchedulerNode.restore_loop_stateù  s8   € ð ñ	
ØŒJØŒKØŒJØÔØÔ#à×-Ñ-ÀdÐ-ÕKru   c                ó@   — | j                   �| j                  | «       y y r~   )r  rq   s    rs   Ú_before_loop_state_mutationz)SchedulerNode._before_loop_state_mutation	  s!   € Ø×'Ñ'Ð3Ø×(Ñ(¨Õ.ð 4ru   c                óÀ   — | j                  «        | j                  j                  |«      | _        | j                  j                  | _        | j                  dd¬«       y ©NFT©r   r2  )r>  r  Úreorder_iter_loopsÚsizesr  r3  )rr   Ú	new_orders     rs   Úapply_new_loop_orderz"SchedulerNode.apply_new_loop_order	  sM   € Ø×(Ñ(Ô*Ø—Z‘Z×2Ñ2Øó
ˆŒ
ð —j‘j×&Ñ&ˆŒà×!Ñ!¨EÈ4Ð!ÕPru   c                óÜ  — t        | j                  t        j                  t        j                  f«      sJ ‚| j                  «        | j                  j                  |«      | _        | j                  j                  | _	        | j                  j                  «       }| j                  j                  |«      j                  }| || j                  «      f| _        | j                  dd¬«       y r@  )r²   r”   r0   r   r!  r>  r  Úreindex_iter_loopsrC  r  r  rÜ  r#  r$  rÆ   r3  )rr   Únew_iter_sizesrÝ  r$  s       rs   Úapply_loop_reindexingz#SchedulerNode.apply_loop_reindexing	  s®   € Ü˜$Ÿ)™)¤b×&7Ñ&7¼×9JÑ9JÐ%KÔLÐLÐLà×(Ñ(Ô*Ø—Z‘Z×2Ñ2°>ÓBˆŒ
Ø—j‘j×&Ñ&ˆŒà—‘×.Ñ.Ó0ˆØ—>‘>×-Ñ-¨fÓ5×>Ñ>ˆØ™h t§{¡{Ó3Ð4ˆŒ
à×!Ñ!¨EÈ4Ð!ÕPru   c                ó¦  — | j                   j                  «       }t        | j                   j                  «      |z
  }t	        t        |«      «      }t	        t        |||z   «      «      }| j                  ||z   «       t        | j                  d   «      dk(  sJ ‚| j                  d   | j                  d   d   | j                  d   d   ff| _        y )Nr   rÍ   r   )r  Úget_original_num_rdimsrÎ   r¿  rÏ   ÚrangerE  rÆ   )rr   Ú	num_rdimsÚ
num_pwdimsÚpwdimsÚrdimss        rs   Úswap_pw_red_dimensionz#SchedulerNode.swap_pw_red_dimension	  s²   € Ø—J‘J×5Ñ5Ó7ˆ	Ü˜Ÿ™×-Ñ-Ó.°Ñ:ˆ
Ü”u˜ZÓ(Ó)ˆÜ”e˜J¨
°YÑ(>Ó?Ó@ˆà×!Ñ! %¨&¡.Ô1Ü�4—:‘:˜a‘=Ó! QÒ&Ð&Ð&Ø—Z‘Z ‘] T§Z¡Z°¡]°1Ñ%5°t·z±zÀ!±}ÀQÑ7GÐ$HÐHˆ�
ru   c                óD   — | j                   j                  «       | _         | S r~   )r  Úextract_pw_from_reductionrq   s    rs   rS  z'SchedulerNode.extract_pw_from_reduction(	  s   € Ø—Z‘Z×9Ñ9Ó;ˆŒ
Øˆru   c                óú   — t         j                  | «      sy t        | j                  t        j
                  «      sJ ‚| j                  j                  «       5  | j                  «        d d d «       y # 1 sw Y   y xY wr~   )r¯   r½   r²   r”   r0   r   Úwith_original_inner_fnr  rq   s    rs   Úcancel_reduction_splitz$SchedulerNode.cancel_reduction_split,	  s^   € Ü ×3Ñ3°DÔ9ØÜ˜$Ÿ)™)¤R×%6Ñ%6Ô7Ð7Ð7Ø�Y‰Y×-Ñ-Ó/ñ 	"Ø×ÑÔ!÷	"÷ 	"ñ 	"ús   ÁA1Á1A:c                ó¾  — t        | j                  t        j                  t        j                  f«      sJ ‚| j
                  j                  ||«      | _        | j
                  j                  | _        | j                  j                  «       }| j                  j                  |«      j                  }| || j                  «      f| _        | j                  dd¬«       y )NTrA  )r²   r”   r0   r   r!  r  Ú#expand_dimension_for_pointwise_noderC  r  r  rÜ  r#  r$  rÆ   r3  )rr   Ú	dimensionÚ	new_rangerÝ  r$  s        rs   rX  z1SchedulerNode.expand_dimension_for_pointwise_node3	  s­   € ô ˜$Ÿ)™)¤b×&7Ñ&7¼×9JÑ9JÐ%KÔLÐLÐLà—Z‘Z×CÑCØ�yó
ˆŒ
ð —j‘j×&Ñ&ˆŒà—‘×.Ñ.Ó0ˆØ—>‘>×-Ñ-¨fÓ5×>Ñ>ˆØ™h t§{¡{Ó3Ð4ˆŒ
ð 	×!Ñ!¨DÈ$Ð!ÕOru   c                óž   — | j                   j                  «       | _         | j                   j                  | _        | j	                  dd¬«       y )NTFrA  )r  Úmerge_loopsrC  r  r3  rq   s    rs   r\  zSchedulerNode.merge_loopsD	  s<   € Ø—Z‘Z×+Ñ+Ó-ˆŒ
Ø—j‘j×&Ñ&ˆŒð 	×!Ñ!¨DÈ%Ð!ÕPru   c                óŠ  — d }| j                   d   }t        |«      |j                  cxk(  r|j                  k(  rn n|j                  |«      }|rPt        xj
                  dz  c_        t        j                  d| j                  «       |«       | j                  |«       yt        j                  d| j                  «       «       y)Nr   r   z"Reorder loops for %s with order %sTzEDon't reordering %s because we can not decide the suitable loop orderF)
r  rÎ   Únum_varsÚdecide_loop_order_to_matchr1   Únum_loop_reorderingÚloop_ordering_logrÝ  râ  rE  )rr   rn  ro  rD  Ú
self_sizess        rs   rp  z'SchedulerNode.reorder_loops_by_dep_pairP	  s¤   € ð ˆ	Ø—[‘[ ‘^ˆ
Üˆz‹?˜h×/Ñ/ÔE°9×3EÑ3EÕEØ ×;Ñ;¸IÓFˆIáä×'Ò'¨1Ñ,Õ'Ü×#Ñ#Ø4°d·m±m³oÀyôð ×%Ñ% iÔ0Øä×#Ñ#ØWØ—‘“ôð ru   c                ó$  — | j                  «       }|› d| j                  d   › �|› d| j                  d   › �|› d| j                  › �g}| j                  j	                  «       D ]‚  }t        |t        «      rŒ|j                  }t        j                  j                  |«      }t        |t        j                  «      rŒZ|j                  |› dt        |j                  «      › �«       Œ„ t        | j                   t"        «      rR|j                  d|› d�«       |j                  t%        j&                  | j                   j)                  «       d	«      «       | j*                  €J ‚|j-                  | j/                  «       «       d
j1                  |«      S )Nz.group.device = r   z.group.iteration = r   z	.sizes = z
_layout = zclass z_loop_body:ræ  rH  )râ  rÆ   r  rÕ   rw  r²   r;   r×   ra   rÁ   rI  r0   rL  rä   rï  rí  r  rE   rê  rñ  rô  r”   r¤  r[  Újoin)rr   r×   Úlinesrà   rÖ  rÞ   s         rs   rR  zSchedulerNode.debug_str_extrag	  sK  € Ø�}‰}‹ˆàˆfÐ$ T§Z¡Z°¡] OÐ4ØˆfÐ'¨¯
©
°1© Ð7Øˆf�I˜dŸk™k˜]Ð+ð
ˆð
 ×#Ñ#×4Ñ4Ó6ò 	OˆCÜ˜c¤7Õ+ØŸ8™8�Ü—g‘g×(Ñ(¨Ó2�Ü! #¤r×'9Ñ'9Õ:Ø—L‘L H :¨Z¼ÀÇ
Á
Ó8KÐ7LÐ!MÕNð	Oô �d—j‘j¤(Ô+Ø�L‰L˜6 $  {Ð3Ô4Ø�L‰LœŸ™¨¯©×)=Ñ)=Ó)?ÀÓHÔIà�y‰yÐ$Ð$Ð$Ø�‰�T×/Ñ/Ó1Ô2à�y‰y˜ÓÐru   c                ó   — | j                   S r~   )r  rq   s    rs   r\  zSchedulerNode.get_ranges}	  ó   € Ø�{‰{Ðru   c                ó<  — t        | j                  t        j                  t        j                  f«      sJ dt        | j                  «      ›�«       ‚t        | j                  j                  «       «      xr' | j                  d u xs | j                  j                   S ©Nútype(self.node)=)
r²   r”   r0   r   r!  r«   r}   rþ   r  Úhas_partial_accumulaterq   s    rs   r´   zSchedulerNode.is_reduction€	  s€   € Ü˜$Ÿ)™)¤b×&7Ñ&7¼×9JÑ9JÐ%KÔLð 	
ØŒt�D—I‘I‹Ð Ð!ó	
ÐLô �D—I‘I×0Ñ0Ó2Ó3ò 
Ø�J‰J˜$ÐÒG d§j¡j×&GÑ&GÐ"Gð	
ru   c                ó¾   — t        | j                  t        j                  «      sJ dt	        | j                  «      ›�«       ‚| j                  j                  «       dk(  S )Nrj  Údot)r²   r”   r0   r   r«   rþ   rq   s    rs   rã  zSchedulerNode.is_native_matmul�	  sJ   € Ü˜$Ÿ)™)¤R×%6Ñ%6Ô7ÐNÐ<L¼DÀÇÁ»OÐ;MÐ9NÓNÐ7Ø�y‰y×+Ñ+Ó-°Ñ6Ð6ru   c                óL  — t        | j                  t        j                  t        j                  f«      sJ dt        | j                  «      ›�«       ‚t        | j                  t        j                  «      xr. t        | j                  j                  t        j                  «      S ri  )r²   r”   r0   r   r!  r«   r÷   Ú	SplitScanrq   s    rs   rå  zSchedulerNode.is_split_scan‘	  sy   € Ü˜$Ÿ)™)¤b×&7Ñ&7¼×9JÑ9JÐ%KÔLð 	
ØŒt�D—I‘I‹Ð Ð!ó	
ÐLô ˜$Ÿ)™)¤R×%6Ñ%6Ó7ò 
¼JØ�I‰I�N‰NœBŸL™Ló=
ð 	
ru   c                óJ   — t        | j                  t        j                  «      S r~   ©r²   r”   r0   r!  rq   s    rs   rç  zSchedulerNode.is_template™	  s   € Ü˜$Ÿ)™)¤R×%6Ñ%6Ó7Ð7ru   c                óf   — t        | j                  t        j                  «      r| j                  S d S r~   rq  rq   s    rs   r‡  zSchedulerNode.get_template_nodeœ	  s$   € Ü& t§y¡y´"×2CÑ2CÔDˆt�y‰yÐNÈ$ÐNru   c                óf   — | j                  «        | j                  «        | j                  |«       y r~   )r  r—  r  )rr   Ú
index_varss     rs   ÚrunzSchedulerNode.runŸ	  s#   € Ø×"Ñ"Ô$Ø�‰ŒØ�‰�ZÕ ru   c                ó&  — | j                   }t        t        t        |«      «      t        t        t        |«      «      k(  sJ ‚t	        t        t        j                  j                  |«      t        j                  j                  |«      «      «      }|S r~   )	r  rü   ÚmaprÎ   ÚdictÚziprš  r›  Úfrom_iterable)rr   rt  rC  rÙ   s       rs   Úranges_from_index_varsz$SchedulerNode.ranges_from_index_vars¤	  sp   € ð —‘ˆÜ”3”s˜E“?Ó#¤s¬3¬s°JÓ+?Ó'@Ò@Ð@Ð@ÜÜÜ—‘×-Ñ-¨jÓ9Ü—‘×-Ñ-¨eÓ4óó
ˆ
ð Ðru   c                ó–  — | j                  |«      }	 t        j                  t        t        j                  «       |«      «      5  t        j
                  j                  | «      5   | j                  |Ž  ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w# t        $ r" t        j                  d| j                  «       ‚ w xY w)aê  
        Generate code for this node using the provided index variables.

        This method sets up the appropriate context for code generation, including
        simplifying indexing expressions based on the variable ranges, and then
        calls the node's body function with the index variables.

        Args:
            index_vars: A sequence of sequences of sympy expressions representing
                        the index variables for each dimension of the computation.
        NzError in codegen for %s)r{  ra   Úset_ops_handlerrM   Úget_ops_handlerr  Úset_current_noder  rS  rT  Úfatalr”   )rr   rt  rÙ   s      rs   r  zSchedulerNode.codegen±	  sª   € ð ×0Ñ0°Ó<ˆ
ð	ä×!Ñ!Ô"2´1×3DÑ3DÓ3FÈ
Ó"SÓTñ(ä—‘×)Ñ)¨$Ó/ñ(ð �—
‘
˜JÑ'÷	(÷ (÷ (ñ (ú÷ (ð (ûô
 ò 	Ü�I‰IÐ/°·±Ô;Øð	úsA   “1B Á BÁ$BÁ4BÁ<B ÂB	Â
BÂBÂB ÂB Â+Cc                óÞ   — |r| j                   nt        | j                   «      \  }}t        j                  | j                  |t
        j                  j                  gt        |«      z  g¬«      S )z\
        Get the memory dependencies in either the pointwise or the reduction axes.
        )Úhidden_args)	r  rÐ   r/   r&  r  r  ÚSÚZerorÎ   )rr   Ú	pointwiseÚ
keep_sizesÚignore_sizess       rs   Ú"pointwise_or_reduction_read_writesz0SchedulerNode.pointwise_or_reduction_read_writesÈ	  sT   € ñ 3< 4§;¢;ÄÈ$Ï+É+ÓAVÑ ˆ
�LÜ×/Ñ/Ø�J‰J˜
´%·'±'·,±,°Ä#ÀlÓBSÑ1SÐ0Tô
ð 	
ru   c                ó&   — | j                  d¬«      S )zH
        Get the memory dependencies in the non-reduction axes.
        T©r…  ©rˆ  rq   s    rs   r5  z#SchedulerNode.pointwise_read_writesÓ	  s   € ð
 ×6Ñ6ÀÐ6ÓFÐFru   c                ó&   — | j                  d¬«      S )zD
        Get the memory dependencies in the reduction axes.
        FrŠ  r‹  rq   s    rs   Úreduction_read_writesz#SchedulerNode.reduction_read_writesÚ	  s   € ð
 ×6Ñ6ÀÐ6ÓGÐGru   c                óò  — | j                  «       ryt        d„ | j                  «       D «       «      ryt        | j                  j
                  «      dk(  r£t        |t        j                  «      r‰t        t        | j                  j
                  «      «      }t        |t        j                  «      sJ dt        |«      ›�«       ‚|j                  |j                  k(  xr |j                  |j                  k(  S y)NFc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )rî  rÆ  s     rs   r¹   z,SchedulerNode.can_inplace.<locals>.<genexpr>ä	  s   è ø€ Ò? Sˆs�‰× Ñ?ùrÃ  r   ztype(write_dep)=)rç  r  r<  rÎ   rÕ   rQ  r²   r/   r9   r‘  Úiterr«   rØ   rÜ   )rr   rî  Ú	write_deps      rs   rï  zSchedulerNode.can_inplaceá	  sÃ   € Ø×ÑÔØÜÑ?¨D×,<Ñ,<Ó,>Ô?Ô?ØÜˆt×Ñ×&Ñ&Ó'¨1Ò,´Ø”l×,Ñ,ô2
ô œT $×"2Ñ"2×"9Ñ"9Ó:Ó;ˆIÜ˜i¬×)?Ñ)?Ô@ÐWÐEUÄTÈ)Ã_ÐDVÐBWÓWÐ@Ø—>‘> Y§_¡_Ñ4ÒX¸¿¹È)Ï.É.Ñ9XÐXØru   c                ó  — t        «       }t        | j                  t        «      rà| j                  j	                  «       D ]Ã  }|j
                  dk(  sŒ|j                  dk(  sŒ#d|j                  v r|j                  d   dk(  s,t        |j                  «      dk(  sŒ\|j                  d   dk(  sŒo|j                  d|j                  v r|j                  d   n(t        |j                  «      dk\  r|j                  d	   nd
«       ŒÅ |S )NÚcall_methodÚstoreÚmodeÚ
atomic_addrÇ  rå  r×   rÍ   r   rX  )r   r²   r  rE   r»   rã  r  r7  rÎ   rù  r¢  )rr   Úbuffers_store_as_atomic_addr”   s      rs   Ú_get_atomic_add_buffersz%SchedulerNode._get_atomic_add_buffersî	  sÕ   € ä7A³|Ð#Ü�d—j‘j¤(Ô+ØŸ
™
×,Ñ,Ó.ò �à—G‘G˜}Ó,ØŸ™ wÓ.à 4§;¡;Ñ.°4·;±;¸vÑ3FÈ,Ò3VÜ §	¡	›N¨aÓ/°D·I±I¸a±LÀLÓ4Pð 0×3Ñ3à! T§[¡[Ñ0ð Ÿ™ FÒ+ä.1°$·)±)«nÀÒ.A˜dŸi™i¨šlÀrõðð +Ð*ru   c                óp   •— | j                   �| j                   j                  d«      ryt        ‰| �  «       S )NÚdevice_assert_asyncT)r  Úhas_oprý  rñ  ©rr   r  s    €rs   rñ  zSchedulerNode.has_side_effects
  s2   ø€ ð �:‰:Ð! d§j¡j×&7Ñ&7Ð8MÔ&NØÜ‰wÑ'Ó)Ð)ru   )rÜ  rÛ  r”   z%ir.ComputedBuffer | ir.TemplateBufferr�   r  ©NN)r  ú'tuple[dict[Any, Any], list[Any]] | Noner  zCallable[_P, _T] | Noner�   r  )r  rž  r  zCallable[..., Any] | Noner�   r  )r   r}   r2  r}   r�   r  )r2  r}   r�   r  )r�   rØ  )r;  rØ  r�   r  r  )rD  úSequence[int]r�   r  )rH  úSequence[sympy.Expr]r�   r  ©r�   rf   )rY  r‘   rZ  r‘   r�   r  r™  r  r  r  r¥  )rt  r   r�   r  )rt  r  r�   zdict[sympy.Expr, sympy.Expr])rt  r  r�   r  r¡  )r…  r}   r�   r1  )r�   r1  r   rœ  )'r€   r�   r‚   r•   rƒ   r:  r  r.  r3  r1  r9  r<  r>  rE  rI  rQ  rS  rV  rX  r\  rp  rR  r\  r´   rã  rå  rç  r‡  ru  r{  r  rˆ  rO   r5  r�  rï  r˜  rñ  r  r  s   @rs   r³   r³   †  sÙ  ø… ñð
 -Ó,ØƒOðàðð 4ðð 
õ	ð OSØ=Aðà$Kðð $;ðð 
ó	ðF OSØ?Cðà$Kðð $=ðð 
ó	ð"GØðGØ8<ðGà	óGó*;ó

ó	Ló/óQóQóIóó"ðPØðPØ),ðPà	óPó"
QðØ!ðØ.7ðà	óó. ó,ó
ó7ó
ó8óOó!ð
Ø8ðà	%óóð0 !%ð	
Øð	
à	 ó	
ð òGó ðGð òHó ðHóð ò+ó ð+ð& ô*ó ô*ru   r³   c           	     ón  ‡ — ‰ j                   }‰ j                  t        j                  j	                  |D �cg c]  }|j
                  ‘Œ c}«      «       t        ˆ fd„t        j                  |D �cg c]  }|j                  ‘Œ c}Ž D «       «      ‰ j
                  j                  z
  ‰ _        y c c}w c c}w )Nc              3  óZ   •K  — | ]"  }|j                   ‰j                  «       vr|–— Œ$ y ­wr~   ©r×   rÇ  )r·   rà   Úgroup_snodes     €rs   r¹   z2refresh_group_node_dependencies.<locals>.<genexpr>
  s.   øè ø€ ò 
àØ�x‰x˜{×;Ñ;Ó=Ñ=ô ñ
ùó   ƒ(+)
rÛ   rx  r/   Ú
ReadWritesÚ
merge_listrÕ   r   Úunionr3  rQ  )r¥  rÛ   rˆ  s   `  rs   Úrefresh_group_node_dependenciesrª  

  sž   ø€ ð ×Ñ€FØ×ÑÜ×Ñ×*Ñ*À6Ö+J¸a¨A¯M«MÒ+JÓKôô
 	ó 
ä!×'Ñ'ÈÖ)OÀ1¨!×*>Ó*>Ò)OÐPô
ó 	
ð
 ×
!Ñ
!×
(Ñ
(ñ	)ð Õ"ùò ,Kùò *Ps   ¶B-Á0B2rÛ  c                ól  — t        | t        t        f«      sJ ‚|| _        || _        d | _        t        j                  |D �cg c]  }|j                  €Œ|j                  ‘Œ c}Ž | _        t        | «       t        d„ | j                  D «       «      | _        t        d„ | j                  D «       «      | _        t        d„ | j                  D «       «      | _        t        d„ | j                  D «       «      | _        | j!                  «       D �ci c]  }|j#                  «       |“Œ c}| _        y c c}w c c}w )Nc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   ©r%  ©r·   rˆ  s     rs   r¹   z"init_group_node.<locals>.<genexpr>+
  ó   è ø€ ÒH° §¥ÑHùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   )r&  r®  s     rs   r¹   z"init_group_node.<locals>.<genexpr>,
  r¯  rv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   )r#  r®  s     rs   r¹   z"init_group_node.<locals>.<genexpr>-
  ó   è ø€ ò )Ø!"ˆ×Õñ)ùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   )r$  r®  s     rs   r¹   z"init_group_node.<locals>.<genexpr>0
  r²  rv  )r²   rÚ   ÚGroupedSchedulerNoderÛ   rÜ  r”   r   r©  r  rª  rZ  r%  rY  r&  r#  r$  r<  râ  r.  )r¥  rÜ  rÛ   rˆ  rÞ   s        rs   Úinit_group_noderµ  
  s  € ô
 �kÔ$6Ô8LÐ#MÔNÐNÐNØ€KÔØ%€KÔØ€KÔÜ&×,Ñ,Ø%Ö	A˜!¨¯©Ñ)@ˆ!�+‹+Ò	Að€KÔô $ KÔ0äÑH°[×5GÑ5GÔHÓH€KÔÜÑH°[×5GÑ5GÔHÓH€KÔÜ%(ñ )Ø&1×&8Ñ&8ô)ó &€KÔ"ô &)ñ )Ø&1×&8Ñ&8ô)ó &€KÔ"ð (3×'>Ñ'>Ó'@ö#Ø #ˆ�‰‹˜Ñò#€KÕùò 
Bùò#s   ÁD,ÁD,ÄD1c                  ó¾  ‡ — e Zd ZU dZded<   e	 	 	 	 	 	 d!d„«       Zd"d„Zd#d„Ze	d$d„«       Z
	 	 	 	 	 	 d%d„Zd&ˆ fd	„Ze	d'd
„«       Zd'd„Ze	d(d„«       Zd)d„Zd'd„Zd'd„Z	 	 	 	 	 	 d*ˆ fd„Ze	d(d„«       Ze	d(d„«       Zd+d„Zd'd„Ze	d,d„«       Ze	d,d„«       Ze	d,d„«       Ze	d,d„«       Ze	d-d„«       Zd.d„Ze	d,d„«       Zd/d„Zd0d„Z d1d„Z!d'd„Z"e	d,ˆ fd „«       Z#ˆ xZ$S )2rÚ   zæ
    This is a "fake" scheduler node that represents a group of scheduler nodes
    that are meant to be fused together. The way it does this is by maintaining
    its unmet dependencies as the union of its constituent nodes.
    r¦  rÛ   c                ó¾  — |j                   |j                   u sJ ‚t        |t        t        f«      sJ ‚|j	                  «       r6t        |t
        «      r&t        |j                  t        j                  «      sJ ‚t        |t        t        f«      sJ ‚t        t        j                  |j                  «       |j                  «       «      «      } | |j                   |«      S r~   )rÜ  r²   r³   rÚ   rç  rR  r”   r0   rB   r¥   rš  r›  r»   )rx   rˆ   r‰   rq  s       rs   ry   zFusedSchedulerNode.fuseA
  s¨   € ð �‰ %§/¡/Ñ1Ð1Ð1Ü˜%¤-Ô1CÐ!DÔEÐEÐEØ×ÑÔ¤:¨eÔ5NÔ#OÜ˜eŸj™j¬"¯.©.Ô9Ð9Ð9ä˜e¤mÔ5GÐ%HÔIÐIÐIÜ”Y—_‘_ U§_¡_Ó%6¸¿¹Ó8IÓJÓKˆÙ�5—?‘? EÓ*Ð*ru   c                ó�   — | j                   D ]6  }t        |t        «      sJ ‚|j                  «       sJ ‚|j	                  «        Œ8 | S r~   )rÛ   r²   r³   r´   rS  ©rr   r¸   s     rs   rS  z,FusedSchedulerNode.extract_pw_from_reductionN
  sJ   € Ø—{‘{ò 	0ˆGÜ˜g¤}Ô5Ð5Ð5Ø×'Ñ'Ô)Ð)Ð)Ø×-Ñ-Õ/ð	0ð ˆru   c                ój   — | j                   D ]$  }t        |t        «      sJ ‚|j                  «        Œ& y r~   )rÛ   r²   r³   rQ  r¹  s     rs   rQ  z(FusedSchedulerNode.swap_pw_red_dimensionU
  s1   € Ø—{‘{ò 	,ˆGÜ˜g¤}Ô5Ð5Ð5Ø×)Ñ)Õ+ñ	,ru   c                óŽ   — t        t        d d„ | j                  «       D «       «      «      }t        |«      dk(  ry t	        |«      }|S )Nc              3  ó|   K  — | ]4  }|j                  «       s|j                  «       r|j                  «       –— Œ6 y ­wr~   ©rç  ré  re  rÂ  s     rs   r¹   z4FusedSchedulerNode.estimate_flops.<locals>.<genexpr>`
  ó6   è ø€ ò àØ×'Ñ'Ô)¨T¯^©^Ô-=ð ×'Ñ'×)ñùó   ‚:<r   ©r¥   Úfilterr»   rÎ   rü   ©rr   Úfpsr|  s      rs   re  z!FusedSchedulerNode.estimate_flopsZ
  óK   € ô ÜØñà $§¡Ó 0ôóó	
ˆô ˆs‹8�qŠ=ØÜ�#‹hˆØˆ
ru   c                óÔ  — | j                  «       ryd}| j                  D ]`  }t        |t        «      s y|�;t	        |«      t	        |j
                  d   «      k7  rt        j                  d«        y|j
                  d   }Œb d}|€J ‚t        |«      |j                  cxk(  r|j                  k(  rn n|j                  |«      }|s%t        j                  d| j                  «       «       yt        xj                  dz  c_        t        j                  d| j                  «       |«       | j                  D ]%  }t        |t        «      sJ ‚|j                  |«       Œ' t        | «       y)	z@
        Return true if a loop reordering is performed.
        FNr   z1Can not reorder fused node due to different sizeszODont reordering fused node %s because we can not decide the suitable loop orderr   z-Reorder loops for fused node %s with order %sT)rç  rÛ   r²   r³   rÏ   r  ra  rÝ  rÎ   r^  r_  râ  r1   r`  rE  rª  )rr   rn  ro  rb  r¸  rD  s         rs   rp  z,FusedSchedulerNode.reorder_loops_by_dep_pairl
  sI  € ð ×ÑÔàØˆ
Ø—[‘[ò 	)ˆEÜ˜e¤]Ô3ÙØÐ%¬%°
Ó*;¼uÀUÇ\Á\ÐRSÁ_Ó?UÒ*UÜ!×'Ñ'ØGôñ ØŸ™ a™‰Jð	)ð ˆ	àÐ%Ð%Ð%Üˆz‹?˜h×/Ñ/ÔE°9×3EÑ3EÕEØ ×;Ñ;¸IÓFˆIáÜ×#Ñ#ØaØ—‘“ôð ä×#Ò# qÑ(Õ#Ü×ÑØ;¸T¿]¹]»_Èiô	
ð —[‘[ò 	2ˆEÜ˜e¤]Ô3Ð3Ð3Ø×&Ñ& yÕ1ð	2ô 	(¨Ô-Øru   c                ó†   •— t         ‰| �  |«       t        | ||«       g | _        t	        |d„ ¬«      j
                  | _        y )Nc                ó4   — t        | j                  «       «      S r~   )r‘   r´   r¯  s    rs   r8  z-FusedSchedulerNode.__init__.<locals>.<lambda>›
  s   € ¬s°1·>±>Ó3CÓ/D€ ru   rã  )rý  r:  rµ  rß  rY  rÆ   )rr   rÜ  rÛ   r  s      €rs   r:  zFusedSchedulerNode.__init__—
  s8   ø€ Ü‰Ñ˜Ô#Ü˜˜i¨Ô0Ø%'ˆŒ
Ü˜Ñ%DÔE×KÑKˆ�
ru   c                óz   — dj                  | j                  D �cg c]  }|j                  «       ‘Œ c}«      S c c}w ©Nr=  ©rd  rÛ   râ  ©rr   rˆ  s     rs   râ  zFusedSchedulerNode.get_name�
  ó)   € à�x‰x¨t¯{©{Ö;¨!˜Ÿ™�Ò;Ó<Ð<ùÒ;ó   š8c                ó<   — | j                   d   j                  «       S ré   ©rÛ   râ  rq   s    rs   r¿  z!FusedSchedulerNode.get_first_name¡
  ó   € Ø�{‰{˜1‰~×&Ñ&Ó(Ð(ru   c                ó|   — t        j                  | j                  D �cg c]  }|j                  «       ‘Œ c}Ž S c c}w r~   ©r   r©  rÛ   rÇ  rË  s     rs   rÇ  z#FusedSchedulerNode.get_buffer_names¤
  ó.   € ä×ÑÀÇÁÖ!L¸1 !×"4Ñ"4Õ"6Ò!LÐMÐMùÒ!Ló   ž9c                ój   — g }| j                   D ]!  }|j                  |j                  «       «       Œ# |S r~   ©rÛ   r¤  r<  ©rr   r³  r”   s      rs   r<  zFusedSchedulerNode.get_outputs¨
  ó4   € Ø(*ˆØ—K‘Kò 	.ˆDØ�M‰M˜$×*Ñ*Ó,Õ-ð	.àˆru   c           
     ó~  — t        | j                  «      D ��cg c]+  \  }}| j                  «       › d|› d|j                  «       › �‘Œ- }}}| j                  d   j                  }|�|j                  | j                  «       «       t        j                  dj                  |«      j                  «       d«      S c c}}w )Nz.snodes[z] =
r   rH  ræ  )r’  rÛ   râ  rô  r”   r¤  r[  rê  rñ  rd  rV  )rr   r�  r”   re  s       rs   rR  z"FusedSchedulerNode.debug_str_extra®
  s¦   € ô % T§[¡[Ó1÷
á��4ð �}‰}‹Ð˜x¨ s¨%°·±Ó0@Ð/AÒBð
ˆñ 
ð �{‰{˜1‰~×"Ñ"ˆØÐØ�L‰L˜×3Ñ3Ó5Ô6ä�‰˜tŸy™y¨Ó/×6Ñ6Ó8¸&ÓAÐAùó
s   ™0B9c                óh   — | j                   D �cg c]  }|j                  «       ‘Œ }}| › d|› �S c c}w )Nz
, snodes: )rÛ   rh  )rr   r”   Ú
snodes_strs      rs   rh  z"FusedSchedulerNode.debug_str_short¹
  s9   € Ø9=¿¹ÖE°�d×*Ñ*Õ,ÐEˆ
ÐEØ��z * Ð.Ð.ùò Fs   �/c                óÈ   •— t         ‰| �  ||«       t        «       }t        | j                  «      D ]/  }|j                  ||«       |j                  |j                  «       Œ1 y r~   )rý  r•  r   rÐ   rÛ   Úupdater"  )rr   r“  r�  r”   r  s       €rs   r•  z!FusedSchedulerNode.set_last_usage½
  s\   ø€ ô
 	‰ÑÐ2Ð4FÔGô 0:«|ÐÜ˜TŸ[™[Ó)ò 	8ˆDØ×ÑÐ 3Ð5GÔHØ×&Ñ& t§¡Õ7ñ	8ru   c                ó|   — t        j                  | j                  D �cg c]  }|j                  «       ‘Œ c}Ž S c c}w r~   )r   r©  rÛ   rã   rË  s     rs   rã   z$FusedSchedulerNode.used_buffer_namesÊ
  s.   € ä×ÑÀÇÁÖ!M¸A !×"5Ñ"5Õ"7Ò!MÐNÐNùÒ!MrÔ  c                ó|   — t        j                  | j                  D �cg c]  }|j                  «       ‘Œ c}Ž S c c}w r~   )r   r©  rÛ   r’  rË  s     rs   r’  z/FusedSchedulerNode.used_or_aliased_buffer_namesÎ
  s3   € ä×ÑØ8<¿¹ÖD°1ˆa×,Ñ,Õ.ÒDð
ð 	
ùÚDrÔ  c                ó   — | j                   S r~   rD  rq   s    rs   r»   zFusedSchedulerNode.get_nodesÔ
  rg  ru   c                óT   — t        | «      j                  › d| j                  «       › d�S )Nz(nodes=r@  rA  rq   s    rs   rB  zFusedSchedulerNode.__repr__×
  s'   € Ü�t“*×%Ñ%Ð& g¨d¯m©m«oÐ->¸aÐ@Ð@ru   c                ó:   — t        d„ | j                  D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )r´   r®  s     rs   r¹   z2FusedSchedulerNode.is_reduction.<locals>.<genexpr>Ü
  s   è ø€ Ò9¨�1—>‘>×#Ñ9ùrÃ  ©r  rÛ   rq   s    rs   r´   zFusedSchedulerNode.is_reductionÚ
  s   € äÑ9¨T¯[©[Ô9Ó9Ð9ru   c                ó:   — t        d„ | j                  D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )rã  r®  s     rs   r¹   z6FusedSchedulerNode.is_native_matmul.<locals>.<genexpr>à
  s   è ø€ Ò=¨A�1×%Ñ%×'Ñ=ùrÃ  rä  rq   s    rs   rã  z#FusedSchedulerNode.is_native_matmulÞ
  s   € äÑ=°·±Ô=Ó=Ð=ru   c                ó:   — t        d„ | j                  D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )rå  r®  s     rs   r¹   z3FusedSchedulerNode.is_split_scan.<locals>.<genexpr>ä
  s   è ø€ Ò:¨�1—?‘?×$Ñ:ùrÃ  rä  rq   s    rs   rå  z FusedSchedulerNode.is_split_scanâ
  s   € äÑ:¨d¯k©kÔ:Ó:Ð:ru   c                ó:   — t        d„ | j                  D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   r�  r®  s     rs   r¹   z1FusedSchedulerNode.is_template.<locals>.<genexpr>è
  s   è ø€ Ò8 q�1—=‘=—?Ñ8ùrÃ  rä  rq   s    rs   rç  zFusedSchedulerNode.is_templateæ
  s   € äÑ8¨D¯K©KÔ8Ó8Ð8ru   c                ój   — | j                   D ]$  }|j                  «       sŒ|j                  «       c S  y r~   )rÛ   rç  r‡  ©rr   r”   s     rs   r‡  z$FusedSchedulerNode.get_template_nodeê
  s5   € à—K‘Kò 	0ˆDØ×ÑÕ!Ø×-Ñ-Ó/Ò/ð	0ð ru   c                ó    — | j                   d   S ré   )rÆ   rq   s    rs   rª   zFusedSchedulerNode.get_deviceñ
  s   € Ø�z‰z˜!‰}Ðru   c                ó:   — t        d„ | j                  D «       «      S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )rƒ  r®  s     rs   r¹   z>FusedSchedulerNode.has_aliasing_or_mutation.<locals>.<genexpr>ö
  s   è ø€ ÒE°A�1×-Ñ-×/ÑEùrÃ  rä  rq   s    rs   rƒ  z+FusedSchedulerNode.has_aliasing_or_mutationô
  s   € äÑE¸¿¹ÔEÓEÐEru   c                ó   — t         ‚r~   ©ÚNotImplementedError)rr   rz  s     rs   r{  z'FusedSchedulerNode.update_mutated_namesú
  ó   € Ü!Ð!ru   c                ó   — t         ‚r~   rñ  )rr   r×   s     rs   r  zFusedSchedulerNode.add_fake_depý
  ró  ru   c                ó   — t         ‚r~   rñ  rí  s     rs   rï  zFusedSchedulerNode.can_inplace   ró  ru   c                ó�  — | j                  «       }dj                  d„ | j                  D «       «      }t        «       }|j	                  |› dt        | «      j                  › d|› d|› dt        | j                  j                  «      › d|› dt        | j                  «      › d|› d	t        | j                  j                  | j                  z
  «      › d|› d
| j                  › d|› d| j                  › d|› d�«       |j                  «       5  | j                  «       D ]!  }|j	                  |j!                  «       «       Œ# 	 ddd«       |j#                  d«       	 |j	                  | j%                  «       «       |j-                  «       j/                  «       S # 1 sw Y   ŒXxY w# t&        $ r t(        j+                  dd¬«       Y ŒLw xY w)rD  rê  c              3  óF   K  — | ]  }t        |«      j                  –— Œ y ­wr~   )r«   r€   rÌ  s     rs   r¹   z/FusedSchedulerNode.debug_str.<locals>.<genexpr>  s   è ø€ ÒF°Q¤ Q£× 0Õ 0ÑFùs   ‚!ré  rE  rF  rG  rH  rI  rJ  rK  rL  z.outputs = [
            Nrë  rM  TrN  )râ  rd  rÛ   rX   rP  r«   r€   rï  rÕ   rQ  r3  rÖ   r#  r$  rñ  r<  rô  rì  rR  rS  rT  rU  rò  rV  )rr   r×   Únode_typestrrÞ   rå   s        rs   rô  zFusedSchedulerNode.debug_str  sµ  € à�}‰}‹ˆØ—x‘xÑF¸$¿+¹+ÔFÓFˆÜÓˆØ�
‰
à€€bŒˆd‹×	Ñ	Ð˜Q˜|˜nð -Ø€€j”˜×)Ñ)×0Ñ0Ó1Ð2ð 3Ø€ÐœW T×%<Ñ%<Ó=Ð>ð ?Ø€Ðœ7 4×#3Ñ#3×#9Ñ#9¸D×<SÑ<SÑ#SÓTÐUð VØ€Ð˜T×4Ñ4Ð5ð 6Ø€Ð˜T×4Ñ4Ð5ð 6Ø€ð ðô
	
ð �Z‰Z‹\ñ 	,Ø×'Ñ'Ó)ò ,�Ø—
‘
˜3Ÿ=™=›?Õ+ñ,÷	,ð 	�‰�cÔð	HØ�J‰J�t×+Ñ+Ó-Ô.ð �‰Ó ×'Ñ'Ó)Ð)÷	,ð 	,ûô ò 	HÜ�K‰KÐ7À$ˆKÖGð	Hús   Ä	5FÅF" ÆFÆ" GÇGc                óp   •— | j                   �t        d„ | j                   D «       «      S t        ‰| �  «       S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )rñ  rÂ  s     rs   r¹   z6FusedSchedulerNode.has_side_effects.<locals>.<genexpr>"  s   è ø€ ÒG°4�t×,Ñ,×.ÑGùrÃ  )rÛ   r  rý  rñ  rœ  s    €rs   rñ  z#FusedSchedulerNode.has_side_effects  s0   ø€ à�;‰;Ð"ÜÑG¸4¿;¹;ÔGÓGÐGÜ‰wÑ'Ó)Ð)ru   ©rˆ   rf   r‰   rf   r�   rÚ   r¡  r  r¢  r™  )rÜ  rÛ  rÛ   r¦  r�   r  r  rœ  ©r�   r+  r›  rŸ  r  r¥  )r�   útorch.devicerš  )r×   r8   r�   r  r   )%r€   r�   r‚   r•   rƒ   r„   ry   rS  rQ  rO   re  rp  r:  râ  r¿  rÇ  r<  rR  rh  r•  rã   r’  r»   rB  r´   rã  rå  rç  r‡  rª   rƒ  r{  r  rï  rô  rñ  r  r  s   @rs   rÚ   rÚ   8
  s´  ø… ñð $Ó#àð
+Ø%ð
+Ø.?ð
+à	ò
+ó ð
+óó,ð
 òó ðð")Ø!ð)Ø.7ð)à	ó)õVLð ò=ó ð=ó)ð òNó ðNóó	Bó/ð8Ø#2ð8ØHVð8à	õ8ð òOó ðOð ò
ó ð
ó
óAð ò:ó ð:ð ò>ó ð>ð ò;ó ð;ð ò9ó ð9ð òó ðóð òFó ðFó
"ó"ó"ó*ð8 ô*ó ô*ru   rÚ   c                  óH   ‡ — e Zd ZdZdˆ fd„Z	 	 	 	 	 	 dd„Zdd„Zdd„Zˆ xZS )	ÚFusedMixOrderReductionszNFused node for two reductions with different iteration orders (inner + outer).c                ó`  •— t         j                  |«      st         j                  |«      sJ ‚||}}|| _        || _        t        ‰| �  |j                  t        |j                  «       «      t        |j                  «       «      z   «       t         j                  | j                  «      | _
        y r~   )r¯   r  rˆ   r‰   rý  r:  rÜ  r¥   r»   rð   r  )rr   rˆ   r‰   r  s      €rs   r:  z FusedMixOrderReductions.__init__)  s‡   ø€ Ü ×3Ñ3°EÔ:Ü$×7Ñ7¸Ô>Ð>Ð>Ø  %�5ˆEàˆŒ
ØˆŒ
Ü‰ÑØ�O‰OœT %§/¡/Ó"3Ó4´t¸E¿O¹OÓ<MÓ7NÑNô	
ô '×0Ñ0°·±Ó<ˆ�
ru   c                óÄ  — t        |t        «      rJ ‚t        |t        «      rJ ‚| j                  j                  ||d¬«      syt        j                  |«      rt        j                  |«      sydd„}	 	 	 	 dd„}|r' |||f«       ||«      z  s ||«       |||f«      z  ry|j                  «        xs+ | j                  j                  ||d¬«      | j                  k\  S )a  
        node1 is from the current mix order reduction; node2 is another node we want to fuse in.

        other_nodes are passed in to check if fusion will introduce producer/consumer relationship
        between the inner and outer reduction. If yes, we don't fuse.
        F©Úallow_mix_order_reductionc                óB   — t        «       } |j                  d„ | D «       Ž S )Nc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   )r  rÌ  s     rs   r¹   zTFusedMixOrderReductions.sub_node_can_fuse.<locals>._get_ancestors.<locals>.<genexpr>S  s   è ø€ Ò:¨q˜qŸ{�{Ñ:ùrv  ©r   r©  ©rq  rå   s     rs   Ú_get_ancestorszAFusedMixOrderReductions.sub_node_can_fuse.<locals>._get_ancestorsQ  s    € Ü“,ˆCØ�3—9‘9Ñ:°EÔ:Ð;Ð;ru   c                óB   — t        «       } |j                  d„ | D «       Ž S )Nc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )r  rÌ  s     rs   r¹   zZFusedMixOrderReductions.sub_node_can_fuse.<locals>._get_operation_names.<locals>.<genexpr>Y  s   è ø€ ÒF¸1˜q×4Ñ4×6ÑFùrÃ  r  r  s     rs   Ú_get_operation_nameszGFusedMixOrderReductions.sub_node_can_fuse.<locals>._get_operation_namesU  s"   € ô “,ˆCØ�3—9‘9ÑFÀÔFÐGÐGru   )Úcount_bytes)rq  útuple[BaseSchedulerNode, ...]r�   r™   )	r²   rÿ  rÜ  r  r¯   r  r´   Úscore_fusion_memoryr  )rr   rˆ   r‰   Úother_nodesr  r  s         rs   Úsub_node_can_fusez)FusedMixOrderReductions.sub_node_can_fuse5  sû   € ô ˜eÔ%<Ô=Ð=Ð=Ü˜eÔ%<Ô=Ð=Ð=ð
 �~‰~×&Ñ& u¨eÈuÐ&ÔUØô ×/Ñ/Øô
ä#×6Ñ6°uÔ=Øó	<ð	HØ0ð	Hàó	Hñ Ù  u˜~Ó.Ñ1EÀkÓ1RÒRÙ˜{Ó+Ñ.BÀEÈ5À>Ó.RÒRàð ×"Ñ"Ó$Ð$ò Ø�~‰~×1Ñ1°%¸ÈEÐ1ÓRØ�z‰zñð	
ru   c                ó@  — t         j                  j                  }|dkD  r°t        «       }t	        j
                  | j                  «       |j                  «       «      D ]I  }|j                  j                  D ].  }t        |t        «      sŒ|j                  |j                  «       Œ0 ŒK t        |«      |kD  rt        xj                  dz  c_        yt        |t         «      sR| j#                  | j$                  || j&                  f«      xs( | j#                  | j&                  || j$                  f«      S | j#                  | j$                  |j$                  | j&                  |j&                  f«      xr/ | j#                  | j&                  |j&                  t)        «       «      S )Nr   r   F)r-   r©   Úmix_order_reduction_max_readsr   rš  r›  r»   rÕ   rÖ   r²   r9   r¢  r×   rÎ   r1   Ú#rejected_mix_order_reduction_fusionrÿ  r  rˆ   r‰   rÏ   )rr   ÚotherÚ	max_readsÚ	all_readsr^  rà   s         rs   Úcan_fuse_withz%FusedMixOrderReductions.can_fuse_withg  sD  € ô —M‘M×?Ñ?ˆ	Ø�qŠ=Ü)3«ˆIÜ—o‘o d§n¡nÓ&6¸¿¹Ó8IÓJò 0�ØŸ>™>×/Ñ/ò 0�CÜ! #¤yÕ1Ø!Ÿ™ c§h¡hÕ/ñ0ð0ô �9‹~ 	Ò)ä×;Ò;¸qÑ@Õ;ØÜ˜%Ô!8Ô9Ø×)Ñ)Ø—
‘
˜E D§J¡J =óò Jà×'Ñ'¨¯
©
°E¸D¿J¹J¸=ÓIðJð ×)Ñ)Ø—
‘
˜EŸK™K¨$¯*©*°e·k±kÐ)Bóò Kà×(Ñ(¨¯©°U·[±[Ä%Ã'ÓJðKru   c                óT  — | j                   j                  «       }| j                  j                  |«      }t	        |t
        «      rX|j                  | j                   |j                   «      }|j                  | j                  |j                  «      }t        ||«      S | j                  | j                   || j                  f«      r2|j                  | j                   |«      }t        || j                  «      S |j                  | j                  |«      }t        | j                   |«      S r~   )	rˆ   rª   rÜ  r#  r²   rÿ  ry   r‰   r  )rr   r  rÝ  ÚbackendÚfused_node1Úfused_node2rû  s          rs   Ú	fuse_withz!FusedMixOrderReductions.fuse_with€  sÖ   € Ø—‘×&Ñ&Ó(ˆØ—.‘.×,Ñ,¨VÓ4ˆä�eÔ4Ô5Ø!Ÿ,™, t§z¡z°5·;±;Ó?ˆKØ!Ÿ,™, t§z¡z°5·;±;Ó?ˆKÜ*¨;¸ÓDÐDà×%Ñ% d§j¡j°%¸$¿*¹*¸ÔGØ$Ÿ\™\¨$¯*©*°eÓ<�
Ü.¨z¸4¿:¹:ÓFÐFà$Ÿ\™\¨$¯*©*°eÓ<�
Ü.¨t¯z©z¸:ÓFÐFru   rá  )rˆ   rf   r‰   rf   r  r  )r  rf   )	r€   r�   r‚   r•   r:  r  r  r  r  r  s   @rs   rÿ  rÿ  &  s9   ø„ ÙXõ
=ð0
à ð0
ð !ð0
ð 3ó	0
ódK÷2Gru   rÿ  c                  ó4   ‡ — e Zd ZdZdˆ fd„Zdd„Zdd„Zˆ xZS )ÚFusedNestedReductionsz¶
    Fused node for two dependent reductions over the same logical elements.
    The outer reduction owns the codegen grid; the grouped reduction is staged
    inside that grid.
    c                ó¶  •— || _         || _        t        ‰| �  |j                  t        |j                  «       «      t        |j                  «       «      z   «       | xj                  | j                  «       z  c_        |}|j                  \  }\  }}t        j                  ||«      }|€J ‚|\  }}	|| _        |	| _        |j                  \  }\  }
}t        j                  ||
||	|¬«      }|€J ‚|| _        | j                  t        j                   j"                  u | _        |j'                  «       \  }}t        j)                  |||g |¢|¢­|
|f¬«      | _        y )Nr   r¡  )rˆ   r‰   rý  r:  rÜ  r¥   r»   r  r  rÆ   r2  rd  rQ  rc  r¢  r�  rM  rK  Úgroup_size_in_rr\  rW  rh  )rr   rˆ   r‰   r7  r=  rS  rT  r¦  rQ  Úexact_group_sizerŽ  r�  r�  ra  rb  r  s                  €rs   r:  zFusedNestedReductions.__init__˜  sn  ø€ ØˆŒ
ØˆŒ
Ü‰ÑØ�O‰OœT %§/¡/Ó"3Ó4´t¸E¿O¹OÓ<MÓ7NÑNô	
ð 	�Š˜$×2Ñ2Ó4Ñ4�ØˆØ-9×-?Ñ-?Ñ*ˆÑ*ˆM˜>Ü!0×!PÑ!PØ˜.ó"
Ðð &Ð1Ð1Ð1Ø.DÑ+ÐÐ+Ø0AˆÔØ)9ˆŒØ).¯©Ñ&ˆÑ&ˆK˜Ü&×7Ñ7ØØØØØð 8ó 
ˆð Ð'Ð'Ð'Ø9EˆÔØ%)×%6Ñ%6¼/×:UÑ:U×:WÑ:WÐ%WˆÔØ%6×%AÑ%AÓ%CÑ"ˆ�]ä×2Ñ2Ø"3Ø+Ø-Ø'E¨Ð'E°}Ñ'EØ$/°Ð#>ð 3ó ð 	Õru   c               ó�  — |j                  «       ry| j                  j                  «       |j                  z  syt        j                  | j                  |j                  «       «      }|€yt        j                  | j                  |«      syt        d„ |D «       «      ry| j                  j                  | j                  |||¬«      S )zÚAllow downstream pointwise of the grouped reduction to fuse in.

        Consumers fused directly into the grouped reduction must run at either
        reduced-output resolution or full parent-tile resolution.
        Fc              3  óZ   K  — | ]#  \  }}|t         j                  j                  u –— Œ% y ­wr~   )r2  rH  rF  )r·   r=  ry  s      rs   r¹   z6FusedNestedReductions.can_fuse_with.<locals>.<genexpr>Ý  s-   è ø€ ò 
á��6ð ”o×5Ñ5×KÑKÔKñ
ùrÎ  ©Úcan_reorder)r´   r‰   r  r  r2  rl  rh  r»   rg  r  rÜ  Ú!_can_fuse_nested_reduction_append)rr   r  r%  ri  s       rs   r  z#FusedNestedReductions.can_fuse_withÂ  sÌ   € ð ×ÑÔØð —
‘
×.Ñ.Ó0°5·?±?ÒBØô ×=Ñ=Ø×ÑØ�O‰OÓó
ð 	ð Ð$ØÜ×@Ñ@Ø×ÑÐ!2ô
ð ô ñ 
à.ô
ô 
ð Ø�~‰~×?Ñ?Ø�J‰JØØØ#ð	 @ó 
ð 	
ru   c                óÐ   — | j                   j                  «       }| j                  j                  |«      }|j	                  | j                   |«      }t        | j                  |«      S r~   )r‰   rª   rÜ  r#  ry   r  rˆ   )rr   r  rÝ  r  Ú	new_node2s        rs   r  zFusedNestedReductions.fuse_withé  sM   € Ø—‘×&Ñ&Ó(ˆØ—.‘.×,Ñ,¨VÓ4ˆØ—L‘L §¡¨UÓ3ˆ	Ü$ T§Z¡Z°Ó;Ð;ru   rá  )r  rf   r%  r}   r�   r}   )r  rf   r�   r  )r€   r�   r‚   r•   r:  r  r  r  r  s   @rs   r  r  ‘  s   ø„ ñõ(
óT%
÷N<ru   r  c                  óf   ‡ — e Zd Z	 	 	 	 	 	 	 	 dˆ fd„Ze	 	 	 	 	 	 dd„«       Zdd„Zd	d„Zd
d„Zˆ xZ	S )Ú$FusedExternTritonKernelSchedulerNodec                ó,  •— t        |j                  t        j                  «      sJ ‚t	        j
                  t        t           ||g«      }t        ‰| �%  ||«       || _
        || _        | j                  j                  | _        |j                  | _        y r~   )r²   r”   r0   rÿ  r»  r¼  r¥   rf   rý  r:  Úkernel_nodeÚfused_epiloguer%  r,  )rr   rÜ  r,  r-  rÛ   r  s        €rs   r:  z-FusedExternTritonKernelSchedulerNode.__init__ñ  s{   ø€ ô ˜+×*Ñ*¬B×,FÑ,FÔGÐGÐGÜ—‘œTÔ"3Ñ4°{ÀNÐ6SÓTˆÜ‰Ñ˜ FÔ+Ø&ˆÔØ,ˆÔØ×)Ñ)×3Ñ3ˆŒØ%×-Ñ-ˆ�ru   c                ó¢  — t        |j                  t        j                  «      sJ ‚|j                  }t        |j                  j                  «      dk(  sJ ‚|j                  j                  d   j                  }|j                  j                  ||«      }|j                  |   j                  j                  t        |«      «        | |||«      S )Nr   r   )r²   r”   r0   rÿ  rÜ  rÎ   Úmutation_outputsr×   r�  r±  r  rß  ÚremoveÚNodeUser)rx   rˆ   r‰   rÜ  Úmutated_nameÚ	real_names         rs   Úepilogue_fusez2FusedExternTritonKernelSchedulerNode.epilogue_fuseÿ  sª   € ô ˜%Ÿ*™*¤b×&@Ñ&@ÔAÐAÐAØ—O‘Oˆ	ä�5—:‘:×.Ñ.Ó/°1Ò4Ð4Ð4à!ŸJ™J×7Ñ7¸Ñ:×?Ñ?ˆð ×0Ñ0×4Ñ4°\À<ÓPˆ	Ø×Ñ˜iÑ(×.Ñ.×5Ñ5´h¸u³oÔFÙ�9˜e UÓ+Ð+ru   c                óÆ  — t        | j                  j                  t        j                  «      sJ ‚t        | j
                  j                  t        j                  «      sJ ‚| j
                  j                  j                  «       sJ ‚t        j                  | j
                  j                  j                  d   j                  «      }ddlm} |j                  | j                  g|«      \  }}ddlm}  || j                  g|«      }ddlm}  |||| «      }	|	j'                  «       }
| j
                  j                  j)                  || j                  j                  |
f«      S )Nr   r†  r–  )ÚFusedUserDefinedTritonKernel)r²   r-  r”   r0   r   r,  rÿ  r   r  rý   r  r  Útorch._inductor.codegen.simdr‡  Úget_tiling_and_scoresÚ,torch._inductor.codegen.simd_kernel_featuresr—  Útorch._inductor.codegen.tritonr6  r  Úcodegen_with_epilogue_fusion)rr   r  r  r‡  r“  r=  r—  Úkernel_featuresr6  Úfused_user_kernelÚnew_kernel_srcs              rs   r  z,FusedExternTritonKernelSchedulerNode.codegen  s   € Ü˜$×-Ñ-×2Ñ2´B×4EÑ4EÔFÐFÐFÜ˜$×*Ñ*×/Ñ/´×1KÑ1KÔLÐLÐLØ×Ñ×$Ñ$×6Ñ6Ô8Ð8Ð8Ü—	‘	˜$×*Ñ*×/Ñ/×<Ñ<¸QÑ?×EÑEÓFˆÝ?à"×8Ñ8¸$×:MÑ:MÐ9NÐPUÓV‰	ˆ�åSá,¨d×.AÑ.AÐ-BÀEÓJˆåOá8¸ÀÐRVÓWÐØ*×2Ñ2Ó4ˆà×Ñ×$Ñ$×AÑAØ�d×)Ñ)×.Ñ.°Ð?ó
ð 	
ru   c                 ó   — yr	  r…   rq   s    rs   ré  z.FusedExternTritonKernelSchedulerNode.is_extern(  rˆ  ru   c                ó6   — | j                   j                  «       S r~   )r,  r\  rq   s    rs   r\  z/FusedExternTritonKernelSchedulerNode.get_ranges+  s   € Ø×Ñ×*Ñ*Ó,Ð,ru   )rÜ  rÛ  r,  rR  r-  r³   r�   r  )rˆ   rR  r‰   r³   r�   rÚ   r  r  r  )
r€   r�   r‚   r:  r„   r4  r  ré  r\  r  r  s   @rs   r*  r*  ð  sm   ø„ ð.àð.ð /ð.ð &ð	.ð
 
õ.ð ð,à(ð,ð ð,ð 
ò	,ó ð,ó$
ó,÷-ru   r*  c                  óT  ‡ — e Zd ZU dZ	 	 	 	 dd„Z	 	 	 	 dd„Zedd„«       Ze	 	 	 	 	 	 dd„«       Z	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dˆ fd„Z	e	 	 	 	 dd„«       Z
e	 	 	 	 dd„«       ZeZd	ed
<   e	 	 	 	 dd„«       Ze	 	 	 	 dd„«       Zdd„Zdd„Zdd„Zdd„Zd d„Zd!d„Z	 	 	 	 d"d„Zˆ xZS )#ÚForeachKernelSchedulerNodezš
    This is a schedular node that consists of a set of scheduler nodes that
    has no data dependencies among them and can be executed in parallel.
    c                ó¤   — |j                  «       D ]=  }|j                  «       | j                  v sŒ | j                  |j                  «          c S  y r~   )r<  râ  Úread_to_node)rr   ÚproducerrÞ   s      rs   Úget_consumer_subnode_forz3ForeachKernelSchedulerNode.get_consumer_subnode_for5  sL   € ð ×'Ñ'Ó)ò 	9ˆCØ�|‰|‹~ ×!2Ñ!2Ò2Ø×(Ñ(¨¯©«Ñ8Ò8ð	9ð ru   c                ó¢  — t        t           «       }|j                  j                  D ]ƒ  }|j                  | j
                  j                  vrŒ&| j
                  j                  |j                     j                  «       }|| j                  v sŒf|j                  | j                  |   «       Œ… t        |«      dk(  rt        t        |«      «      S y ©Nr   )r   rf   rÕ   rÖ   r×   rÜ  r  rä  Úname_to_noder¢  rÎ   r‘  r�  )rr   ÚconsumerÚ	producersÚrdÚ	node_names        rs   Úget_producer_subnode_forz3ForeachKernelSchedulerNode.get_producer_subnode_for>  s¬   € ô Ô0Ñ1Ó3ˆ	Ø×&Ñ&×,Ñ,ò 	<ˆBØ�w‰w˜dŸn™n×8Ñ8Ñ8ØàŸ™×2Ñ2°2·7±7Ñ;×LÑLÓNˆIØ˜D×-Ñ-Ò-Ø—‘˜d×/Ñ/°	Ñ:Õ;ð	<ô ˆy‹>˜QÒÜœ˜Y›Ó(Ð(àru   c                óœ  ‡— t        ‰|«      }‰j                  «       r¯|j                  «       rŸt        j                  t        ‰«      Št        j                  t        |«      }t        ‰j                  «      t        |j                  «      k(  }|s |d«       |xr2 t        ˆfd„t        ‰j                  |j                  «      D «       «      S |j                  «       rk‰j                  «       r	 |d«       yt        j                  t        |«      }|j                  ‰«      }|�|j                  j                  ‰|«      S  |d«       y‰j                  «       rk|j                  «       r	 |d«       yt        j                  t        ‰«      Š‰j                  |«      }|�‰j                  j                  ||«      S  |d«       yt        d«      ‚)	Nzforeach do not have same lengthc              3  ó\   •K  — | ]#  \  }}‰j                   j                  ||«      –— Œ% y ­wr~   )rÜ  r  )r·   ÚlÚrrE  s      €rs   r¹   z6ForeachKernelSchedulerNode.can_fuse.<locals>.<genexpr>Z  s0   øè ø€ ò )á�A�qð ×"Ñ"×+Ñ+¨A¨q×1ñ)ùs   ƒ),zXcandidate producer is a reduction, foreach ops cannot be fused with reductions currentlyFz5candidate producer is not dep of any foreach consumerzXcandidate consumer is a reduction, foreach ops cannot be fused with reductions currentlyz5candidate consumer has no dep in any foreach producerzXAt least one node passed to ForeachKernelSchedulerNode.can_fuse should be a foreach node)rÔ  rë  r»  r¼  rB  rÎ   rÛ   rº   ry  r´   rF  rÜ  r  rN  rw  )rx   rE  rJ  ÚwhyÚforeach_matchÚconsumer_subnodeÚproducer_subnodes    `     rs   r  z#ForeachKernelSchedulerNode.can_fuseQ  sž  ø€ ä˜ (Ó+ˆØ×ÑÔ  X×%8Ñ%8Ô%:Ü—{‘{Ô#=¸xÓHˆHÜ—{‘{Ô#=¸xÓHˆHÜ §¡Ó0´C¸¿¹Ó4HÑHˆMÙ ÙÐ5Ô6Ø ò ¤Só )ä §¡°·±ÓAô)ó &ð ð × Ñ Ô"Ø×$Ñ$Ô&ÙØnôð ä—{‘{Ô#=¸xÓHˆHØ'×@Ñ@ÀÓJÐØÐ+Ø×)Ñ)×2Ñ2°8Ð=MÓNÐNáÐGÔHØà× Ñ Ô"Ø×$Ñ$Ô&ÙØnôð ä—{‘{Ô#=¸xÓHˆHØ'×@Ñ@ÀÓJÐØÐ+Ø×)Ñ)×2Ñ2Ð3CÀXÓNÐNáÐGÔHØäØfó
ð 	
ru   c                ó
  — |j                  «       s|j                  «       sJ ‚|j                  «       r3t        j                  t        |«      }|j                  }|j
                  }n2t        j                  t        |«      }|j                  }|j
                  }d }d }|j                  «       rŒ|j                  «       r|t        j                  t        |«      }t        j                  t        |«      }t        |j                  |j                  «      D ��cg c]  \  }}t        j                  ||«      ‘Œ }	}}�n/|j                  «       r‚t        j                  t        |«      }|j                  |«      }
g }	|}d }|j                  D ]A  }||
u r*t        j                  ||«      }|}|	j                  |«       Œ1|	j                  |«       ŒC n�|j                  «       r‚t        j                  t        |«      }|j                  |«      }g }	|}d }|j                  D ]A  }||u r*t        j                  ||«      }|}|	j                  |«       Œ1|	j                  |«       ŒC nt        d«      ‚ | |j                  |	||||¬«      S c c}}w )NzTAt least one node passed to ForeachKernelSchedulerNode.fuse should be a foreach node)Úuse_custom_partition_algoÚprev_node_1Úprev_node_2Úenable_autotune)rë  r»  r¼  rB  rX  r[  ry  rÛ   rÚ   ry   rN  rä   rF  rw  rÜ  )rx   rE  rJ  rX  r[  rY  rZ  rQ  rR  Úfused_nodesrV  r”   Únew_noderU  s                 rs   ry   zForeachKernelSchedulerNode.fuse€  sZ  € ð ×"Ñ"Ô$¨×(;Ñ(;Ô(=Ð=Ð=Ø×ÑÔ Ü—{‘{Ô#=¸xÓHˆHØ(0×(JÑ(JÐ%Ø&×6Ñ6‰Oä—{‘{Ô#=¸xÓHˆHØ(0×(JÑ(JÐ%Ø&×6Ñ6ˆOØˆØˆà×ÑÔ  X×%8Ñ%8Ô%:Ü—{‘{Ô#=¸xÓHˆHÜ—{‘{Ô#=¸xÓHˆHô   §¡°·±ÓA÷á�A�qô #×'Ñ'¨¨1Õ-ðˆKó ð × Ñ Ô"Ü—{‘{Ô#=¸xÓHˆHØ'×@Ñ@ÀÓJÐØˆKØ"ˆKØˆKØ Ÿ™ò -�ØÐ+Ñ+Ü1×6Ñ6°t¸XÓF�HØ"*�KØ×&Ñ& xÕ0à×&Ñ& tÕ,ñ-ð × Ñ Ô"Ü—{‘{Ô#=¸xÓHˆHØ'×@Ñ@ÀÓJÐØˆKØ"ˆKØˆKà Ÿ™ò -�ØÐ+Ñ+Ü1×6Ñ6°xÀÓF�HØ"*�KØ×&Ñ& xÕ0à×&Ñ& tÕ,ñ-ô !Øfóð ñ Ø×ÑØØ&?Ø#Ø#Ø+ô
ð 	
ùóKs   Ä I?c                ó|  •‡ — i ‰ _         i ‰ _        |�|€qt        ‰‰ �  ||«       |D ]Z  }|j                  j
                  D ]  }	|‰ j                   |	j                  <   Œ |j                  «       D ]  }
|‰ j                  |
<   Œ Œ\ �n<|‰ _        |‰ _	        d ‰ _
        g ‰ _        ‰ j                  t        j                  j                  |j                  |j                  g«      «       t!        ˆ fd„t!        j"                  |j$                  |j$                  «      D «       «      ‰ j                  j&                  z
  ‰ _        t)        |j*                  |j*                  g«      ‰ _        t-        |j.                  |j.                  g«      ‰ _        t)        |j0                  |j0                  «      ‰ _        t-        |j2                  |j2                  «      ‰ _        |j5                  «       rt7        |t8        «      sJ ‚||}}nt7        |t8        «      sJ ‚||}}|j:                  ‰ _        ‰ j:                  j=                  |j:                  «       |j                  ‰ _        |j                  «       D ]  }
|‰ j                  |
<   Œ ‰ j                  D ���ci c]'  }|j>                  jA                  «       D ]  \  }}||“Œ
 Œ) c}}}‰ _        |‰ _!        |d   jE                  «       }|sJ ‚|tG        jH                  d«      fff‰ _%        t!        tL        jN                  jP                     «       ‰ _)        |‰ _*        |‰ _+        y c c}}}w )Nc              3  óZ   •K  — | ]"  }|j                   ‰j                  «       vr|–— Œ$ y ­wr~   r¤  r©  s     €rs   r¹   z6ForeachKernelSchedulerNode.__init__.<locals>.<genexpr>ä  s0   øè ø€ ò àð —x‘x t×'<Ñ'<Ó'>Ñ>ô	 ñùr¦  r   Úcombo_kernel),rD  rI  rý  r:  rÕ   rÖ   r×   r  rÜ  rÛ   r”   rß  rx  r/   r§  r¨  r   r©  r3  rQ  rZ  r%  rY  r&  r#  r$  rë  r²   rB  r  rÝ  r.  rÀ  rX  rª   r  ÚExprrÆ   r`  ÚfxÚNoder$  r[  Úper_subkernel_blocks)rr   rÜ  rÛ   rX  rY  rZ  r[  rd  r”   r  r×   Úforeach_noder  r¸  r�  ÚvrÝ  r  s   `                €rs   r:  z#ForeachKernelSchedulerNode.__init__Á  s  ù€ ð ˆÔØˆÔàÐ +Ð"5Ü‰GÑ˜Y¨Ô/àò 3�Ø ×,Ñ,×2Ñ2ò 8�DØ37�D×%Ñ% d§i¡iÒ0ð8ð !×4Ñ4Ó6ò 3�DØ.2�D×%Ñ% dÒ+ñ3ò	3ð 'ˆDŒNØ ˆDŒKØˆDŒIØ)+ˆDŒJà× Ñ Ü×'Ñ'×2Ñ2Ø ×,Ñ,¨k×.EÑ.EÐFóôô ó ä)×/Ñ/Ø#×6Ñ6¸×8VÑ8Vó ôó ð ×"Ñ"×)Ñ)ñ*ð Ô#ô ! +×"7Ñ"7¸×9NÑ9NÐ!OÓPˆDŒNÜ  +×"7Ñ"7¸×9NÑ9NÐ!OÓPˆDŒNÜ&)Ø×.Ñ.°×0NÑ0Nó'ˆDÔ#ô '*Ø×.Ñ.°×0NÑ0Nó'ˆDÔ#ð ×%Ñ%Ô'Ü! +Ô/IÔJÐJÐJØ+6¸˜j‘ä! +Ô/IÔJÐJÐJØ+6¸˜j�à)×3Ñ3ˆDŒNØ�N‰N×!Ñ! *×"6Ñ"6Ô7à ,× 9Ñ 9ˆDÔØ"×6Ñ6Ó8ò 5�Ø*4�×!Ñ! $Ò'ð5ð #'§+¡+÷@ð @Ø¸%×:OÑ:O×:UÑ:UÓ:Wò@Ù26°!°Q��1‘ð@Øô@ˆDÔ ð *CˆÔ&Ø˜‘×%Ñ%Ó'ˆÙˆˆvØ¤§
¡
¨>Ó :Ð<Ð>Ð?ˆŒ
Ü!¤%§(¡(§-¡-Ñ0Ó2ˆŒØ.ˆÔØ$8ˆÕ!ùô@s   Ê,L7c                ó¦  — |D �cg c]  }t        |t        «      sŒ|‘Œ }}|rSt        j                  dt	        |«      |D �cg c])  }|j
                  €Œ|j
                  j                  «       ‘Œ+ c}«       |D �cg c]  }t        |t        «      sŒ|‘Œ }}|rt        j                  dt	        |«      «       |D �cg c]  }t        |t        «      sŒ|‘Œ }}|rt        j                  dt	        |«      «       |D �cg c]  }t        |t        «      sŒ|‘Œ }}|rt        j                  dt	        |«      «       |D �cg c])  }t        |t        t        t        t        t        f«      s|‘Œ+ }}|D �cg c]  }t        |t        «      sŒ|‘Œ }	}|	rt        j                  dt	        |	«      «       |D �cg c]  }t        |t        «      rŒ|‘Œ }}|D �cg c]  }|j                  «       sŒ|‘Œ }
}|
r t        j                  dt	        |
«      |
«       |D �cg c]	  }||
vsŒ|‘Œ }}t        j                  ra|D �cg c]  }|j                  «       sŒ|‘Œ }}|rt        j                  dt	        |«      «       |D �cg c]  }|j                  «       rŒ|‘Œ }}|S c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w )Nz/ComboKernels: %d external nodes are filtered %sz+ComboKernels: %d grouped nodes are filteredz;ComboKernels: %d FusedMixOrderReductions nodes are filteredz9ComboKernels: %d FusedNestedReductions nodes are filteredz+ComboKernels: %d foreach nodes are filteredz0ComboKernels: %d template nodes are filtered: %szCComboKernels: %d reduction nodes are filtered (pointwise_only mode))r²   rR  rT  rÝ  rÎ   r”   r  r´  rÿ  r  r  rB  rç  r-   Úcombo_kernels_pointwise_onlyr´   )rx   rq  rˆ  Úexternr”   ÚgroupedÚ	mix_orderÚnested_reductionsÚfiltered_nodesÚforeach_nodesÚtemplate_nodesÚreduction_nodess               rs   Úcombinable_nodesz+ForeachKernelSchedulerNode.combinable_nodes  s¨  € ð #ÖO˜¤j°Ô4MÕ&N’!ÐOˆÐOÙÜ�I‰IØAÜ�F“Ø5;ÖU¨T¸t¿y¹yÑ?T�—‘×&Ñ&Õ(ÒUôð
 $ÖK˜¤z°!Ô5IÕ'J’1ÐKˆÐKÙÜ�I‰IØ=Ü�G“ôð !&ÖP˜1¬°AÔ7NÕ)O’QÐPˆ	ÐPÙÜ�I‰IØMÜ�I“ôð ).ÖV 1´¸AÔ?TÕ1UšQÐVÐÐVÙÜ�I‰IØKÜÐ%Ó&ôð ö
àÜØä*Ü-Ü(Ü+Ü)ðô	ò ð
ˆð 
ð &ö
Ø¬°AÔ7QÕ)RŠAð
ˆð 
ñ Ü�I‰IÐCÄSÈÓEWÔXà%ö
Ø¬Z¸Ô;UÕ-VŠAð
ˆð 
ð &4ÖG °q·}±}µš!ÐGˆÐGÙÜ�I‰IØBÜ�NÓ#Øôð
 &4ÖO °qÀÒ7Nš!ÐOˆÐOô ×.Ò.Ø*8ÖM Q¸A¿N¹NÕ<LšqÐMˆOÐMÙÜ—	‘	ØYÜ˜Ó(ôð *8ÖP A¸q¿~¹~Õ?OšaÐPˆNÐPàÐùòG Pùò
 VùâKùò Qùò Wùò
ùò
ùò

ùò Hùò Pùò Nùò Qsˆ   …J›JÁJÁJÁ:J!ÂJ!Â;J&ÃJ&Ã<J+ÄJ+Ä=.J0Å1J5ÆJ5Æ2J:ÇJ:ÇJ?Ç(J?È	KÈKÈ8K	ÉK	É9KÊKc                ó2  — | j                  «       }g }t        j                  }t        |D ���cg c]0  }|D ])  }t	        |t
        «      r|j                  «       D ]  }|‘Œ Œ+ Œ2 c}}}«      }|D �]  }t        t        «      }	|D ][  }|j                  «       }
|
r|
j                  dk(  s|
j                  dk(  rŒ4|j                  «       |z  rŒH|	|
   j                  |«       Œ] |	j                  «       D ]”  }t        t        «      }|D ]0  }|| j                  j                  |d«         j                  |«       Œ2 |j                  «       D ];  }|j!                  t#        dt%        |«      |«      D �cg c]
  }||||z    ‘Œ c}«       Œ= Œ– �Œ |S c c}}}w c c}w )zS
        Returns a list of lists of nodes that are to be grouped together.
        ÚmpsrÛ  r   )Ú_topological_sort_nodesr-   Úcombo_kernel_max_num_nodesr   r²   rÿ  rÇ  r   r¥   rª   r«   rã   rä   rÝ   Únode_to_streamr±  r¤  rL  rÎ   )rÜ  Úsorted_nodesÚgrouped_nodesÚmax_num_nodesrÆ   r”   rÖ  Úexcluded_buffer_namesrq  Údevice_groupsrÝ  Údevice_nodesÚstream_groupsÚstream_nodesr�  s                  rs   Ú&_default_group_nodes_for_combo_kernelszAForeachKernelSchedulerNode._default_group_nodes_for_combo_kernelsZ  sÔ  € ð !×8Ñ8Ó:ˆØˆÜ×9Ñ9ˆä1;ð *÷ð àØ!òð Ü˜dÔ$;Ô<Ø $× 5Ñ 5Ó 7òð
 ò	 ðØðØôó2
Ðð "ó 	ˆEô œDÓ!ð ð ò 3�ØŸ™Ó*�Ù˜vŸ{™{¨eÒ3°v·{±{ÀeÒ7KØð ×)Ñ)Ó+Ð.CÒCØØ˜fÑ%×,Ñ,¨TÕ2ð3ð !.× 4Ñ 4Ó 6ò 
�ÜDOÔPTÓDU�Ø(ò V�DØ! )×":Ñ":×">Ñ">¸tÀQÓ"GÑH×OÑOÐPTÕUðVà$1×$8Ñ$8Ó$:ò �LØ!×(Ñ(ô &+¨1¬c°,Ó.?ÀÓ%Oöà !ð )¨¨Q°Ñ->Ò?òõñò	
ð%	ð: ÐùôKùò@s   ®5FÅ.Fú4Callable[[Scheduler], list[list[BaseSchedulerNode]]]Ú!group_algorithm_for_combo_kernelsc                ó   — | t         _        y r~   ©rB  r�  )Úcustom_group_algorithms    rs   Ú%set_group_algorithm_for_combo_kernelsz@ForeachKernelSchedulerNode.set_group_algorithm_for_combo_kernels‘  s   € ð
 #ô 	#ÕDru   c                ó,   — t         j                  | «      S r~   rƒ  ©rÜ  s    rs   Úgroup_nodes_for_combo_kernelsz8ForeachKernelSchedulerNode.group_nodes_for_combo_kernels™  s   € ô *×KÑKÈIÓVÐVru   c                ó   — t         ‚r~   rñ  rq   s    rs   r—  z#ForeachKernelSchedulerNode.mark_runŸ  ró  ru   c                ó   — t         ‚r~   rñ  rq   s    rs   r  z"ForeachKernelSchedulerNode.codegen¢  ró  ru   c                 ó   — yr	  r…   rq   s    rs   rë  z%ForeachKernelSchedulerNode.is_foreach¥  rˆ  ru   c                ó,   — t        | j                  «      S )zeReturns a list of nodes which comprise the combo kernel.
        These nodes may be vertically fused.)r¥   rÛ   rq   s    rs   Úget_subkernel_nodesz.ForeachKernelSchedulerNode.get_subkernel_nodes¨  s   € ô �D—K‘KÓ Ð ru   c                ót   — t        t        j                  j                  d„ | j                  D «       «      «      S )zqReturns all nodes contained in this kernel, unpacking fused nodes
        into their constituent scheduler nodes.c              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   )r»   r®  s     rs   r¹   z7ForeachKernelSchedulerNode.get_nodes.<locals>.<genexpr>°  s   è ø€ Ò1UÀA°!·+±+·-Ñ1UùrÃ  )r¥   rš  r›  rz  rÛ   rq   s    rs   r»   z$ForeachKernelSchedulerNode.get_nodes­  s(   € ô ”I—O‘O×1Ñ1Ñ1UÈÏÉÔ1UÓUÓVÐVru   c                ó<   — | j                   d   j                  «       S ré   )rÛ   r¿  rq   s    rs   r¿  z)ForeachKernelSchedulerNode.get_first_name²  s   € Ø�{‰{˜1‰~×,Ñ,Ó.Ð.ru   c                óŠ   — t        | || j                  j                  «       | j                  D ]  }|j	                  |«       Œ y r~   )r¸  rÜ  r  rÛ   rº  )rr   r¹  r”   s      rs   rº  z/ForeachKernelSchedulerNode.prune_redundant_depsµ  s=   € ô 	˜dÐ$6¸¿¹×8RÑ8RÔSà—K‘Kò 	:ˆDØ×%Ñ%Ð&8Õ9ñ	:ru   )rE  rf   r�   rÕ  )rJ  rf   r�   rÕ  ©rE  rf   rJ  rf   r�   r}   )rE  rf   rJ  rf   r�   rB  )NNFF)rÜ  rÛ  rÛ   r¦  rX  r}   rY  rÕ  rZ  rÕ  r[  r}   rd  r}   r�   r  ©rq  r¦  r�   r¦  )rÜ  rÛ  r�   úlist[list[BaseSchedulerNode]])r„  r€  r�   r  r  r  ©r�   r¦  rŸ  r  r�  )r€   r�   r‚   r•   rF  rN  r„   r  ry   r:  rq  r0  r  r�  rƒ   r…  rˆ  r—  r  rë  r�  r»   r¿  rº  r  r  s   @rs   rB  rB  /  sÁ  ø… ñð
Ø)ðà	!óðØ)ðà	!óð& ò,
ó ð,
ð\ ð>
Ø(ð>
Ø4Eð>
à	#ò>
ó ð>
ðJ 15Ø04Ø %Ø%*ðN9àðN9ð (ðN9ð $(ð	N9ð
 .ðN9ð .ðN9ð ðN9ð #ðN9ð 
õN9ð` ðFØ+ðFà	 òFó ðFðP ð0Øð0à	&ò0ó ð0ðh 	/ð &ð (ó /ð ð
Ø Tð
à	ò
ó ð
ð ðWØðWà	&òWó ðWó
"ó"óó!ó
Wó
/ð:Ø">ð:à	÷:ru   rB  c                  óÌ   ‡ — e Zd ZU dZded<   edd„«       Z	 d	 	 	 	 	 	 	 dˆ fd„Zdd„Zdd„Z	e
dd„«       Zdd	„Ze
dd
„«       Zdd„Ze
dd„«       Zdd„Zdd„Zedd„«       Zˆ xZS )r´  aC  
    This is a "fake" scheduler node that represents a group of scheduler nodes
    that are meant to be *grouped* together (it does not allow another node to be scheduled
    in between its constituent nodes, nor does it allow another node to fuse into any of its constituent nodes).
    The way it does this is by maintaining its unmet dependencies as the union of its constituent nodes.
    Fusion will still happen among the nodes within each GroupedSchedulerNode.
    At codegen time, this scheduler node will be unpacked and codegen is called on each constituent node.
    r¦  rÛ   c                óæ   ‡— |d   j                   Št        ˆfd„|D «       «      sJ ‚ | ‰|«      }|D ]  }|‰j                  |j                  «       <   Œ! |‰j                  |j                  «       <   |S )Nr   c              3  ó:   •K  — | ]  }|j                   ‰u –— Œ y ­wr~   r‡  )r·   r”   rÜ  s     €rs   r¹   z.GroupedSchedulerNode.create.<locals>.<genexpr>Í  s   øè ø€ ÒB°4�4—>‘> YÔ.ÑBùó   ƒ)rÜ  rº   r¹  râ  )rx   rÛ   Úgrouped_snoder¸  rÜ  s       @rs   ÚcreatezGroupedSchedulerNode.createÊ  sy   ø€ à˜1‘I×'Ñ'ˆ	ÜÓB¸6ÔBÔBÐBÐBÙ˜I vÓ.ˆØò 	KˆEØ=JˆI×(Ñ(¨¯©Ó)9Ò:ð	KàANˆ	×$Ñ$ ]×%;Ñ%;Ó%=Ñ>ØÐru   c                óL   •— t         ‰| �  |«       t        | ||«       || _        y r~   )rý  r:  rµ  Útemp_grouping)rr   rÜ  rÛ   r�  r  s       €rs   r:  zGroupedSchedulerNode.__init__Ô  s(   ø€ ô 	‰Ñ˜Ô#Ü˜˜i¨Ô0ð +ˆÕru   c                ó6  — | j                   r| j                  S | j                  D ])  }|| j                  j                  |j	                  «       <   Œ+ | j                  j                  | j	                  «       = | j                  j                  | j                  «      S )z�
        Do fusion among nodes within this GroupedSchedulerNode,
        and then unpack this GroupedSchedulerNode into regular nodes.
        )r�  rÛ   rÜ  r¹  râ  Ú
fuse_nodes)rr   r¸  s     rs   ÚunpackzGroupedSchedulerNode.unpackã  sx   € ð
 ×ÒØ—;‘;Ðà—[‘[ò 	HˆEØBGˆD�N‰N×-Ñ-¨e¯n©nÓ.>Ò?ð	Hà�N‰N×-Ñ-¨d¯m©m«oÐ>Ø�~‰~×(Ñ(¨¯©Ó5Ð5ru   c                óŽ   — | j                  | j                  j                  |«      «       | j                  j	                  |«       y r~   )rx  rÕ   r}  r3  r¢  )rr   Úfake_deps     rs   r  z!GroupedSchedulerNode.add_fake_depð  s5   € Ø×Ñ˜T×-Ñ-×7Ñ7¸ÓAÔBØ×Ñ×#Ñ# HÕ-ru   c                óz   — dj                  | j                  D �cg c]  }|j                  «       ‘Œ c}«      S c c}w rÉ  rÊ  rË  s     rs   râ  zGroupedSchedulerNode.get_nameô  rÌ  rÍ  c                ó<   — | j                   d   j                  «       S ré   rÏ  rq   s    rs   r¿  z#GroupedSchedulerNode.get_first_nameø  rÐ  ru   c                ó|   — t        j                  | j                  D �cg c]  }|j                  «       ‘Œ c}Ž S c c}w r~   rÒ  rË  s     rs   rÇ  z%GroupedSchedulerNode.get_buffer_namesû  rÓ  rÔ  c                ój   — g }| j                   D ]!  }|j                  |j                  «       «       Œ# |S r~   rÖ  r×  s      rs   r<  z GroupedSchedulerNode.get_outputsÿ  rØ  ru   c                óŽ   — t        t        d d„ | j                  «       D «       «      «      }t        |«      dk(  ry t	        |«      }|S )Nc              3  ó|   K  — | ]4  }|j                  «       s|j                  «       r|j                  «       –— Œ6 y ­wr~   r½  rÂ  s     rs   r¹   z6GroupedSchedulerNode.estimate_flops.<locals>.<genexpr>  r¾  r¿  r   rÀ  rÂ  s      rs   re  z#GroupedSchedulerNode.estimate_flops  rÄ  ru   c                ó   — | j                   S r~   rD  rq   s    rs   r»   zGroupedSchedulerNode.get_nodes  rg  ru   c                óX   — | j                   r| j                   d   j                  «       S d S ré   )rÛ   rª   rq   s    rs   rª   zGroupedSchedulerNode.get_device  s$   € Ø.2¯kªkˆt�{‰{˜1‰~×(Ñ(Ó*ÐC¸tÐCru   c                 ó   — yrm  r…   )rx   rE  rJ  s      rs   r  zGroupedSchedulerNode.can_fuse  rq  ru   )rÛ   r¦  r�   r´  )F)rÜ  rÛ  rÛ   r¦  r�  r}   r�   r  r•  )r¢  r8   r�   r  r  rœ  rü  r¢  rŸ  r  r’  )r€   r�   r‚   r•   rƒ   r„   r›  r:  r   r  rO   râ  r¿  rÇ  r<  re  r»   rª   r  r  r  s   @rs   r´  r´  ¾  sÃ   ø… ñð $Ó#àòó ðð $ð	+àð+ð (ð+ð ð	+ð
 
õ+ó6ó.ð ò=ó ð=ó)ð òNó ðNóð òó ðó"óDð òó ôru   r´  c           
     ó   ‡ ‡— t         j                  dˆˆ fd„«       }t        t        t	        t        ‰ d   «      «      «      «      }t        |«      dkD  r|D �cg c]  }‰ |   ‘Œ	 c}Š t        j                  r|j                  |¬«       |S c c}w )z�
    A heuristic to decide loop iteration orders.  This has not been well
    tuned and may be something we should autotune.
    c                ót  •— ‰|    dk(  s‰|   dk(  rt        ‰|    dk(  ‰|   dk(  «      S ‰D �cg c]  }t        ||    «      ‘Œ }}‰D �cg c]  }t        ||   «      ‘Œ }}t        d„ t        ||«      D «       «      }t        d„ t        ||«      D «       «      }||kD  ry||kD  ryt        || «      S c c}w c c}w )Nr   c              3  ó:   K  — | ]  \  }}|d k(  xs ||k  –— Œ y­w©r   Nr…   ©r·   Úsl_aÚsl_bs      rs   r¹   z5pick_loop_order.<locals>.index_cmp.<locals>.<genexpr>:  ó)   è ø€ ò 
Ù)3¨¨tˆD�A‰IÒ$˜ ™Ó$ñ
ùó   ‚c              3  ó:   K  — | ]  \  }}|d k(  xs ||k  –— Œ y­wr¯  r…   r°  s      rs   r¹   z5pick_loop_order.<locals>.index_cmp.<locals>.<genexpr>=  r³  r´  r  )rP   Úabsrü   ry  )	r²  ÚbÚslÚstride_len_aÚstride_len_bÚa_firstÚb_firstrC  Ústride_lengthss	          €€rs   Ú	index_cmpz"pick_loop_order.<locals>.index_cmp-  sÛ   ø€ à�‰8�qŠ=˜E !™H¨šMä�u˜Q‘x 1‘} e¨A¡h°!¡mÓ4Ð4ð .<Ö< rœ˜B˜q™E�
Ð<ˆÐ<Ø-;Ö< rœ˜B˜q™E�
Ð<ˆÐ<ô ñ 
Ü7:¸<ÈÓ7Vô
ó 
ˆô ñ 
Ü7:¸<ÈÓ7Vô
ó 
ˆð �WÒØØ�WÒØô �1�a‹yÐùò# =ùÚ<s   ®B0Á	B5r   rã  )r²  r‘   r·  r‘   r�   r‘   )	Ú	functoolsÚ
cmp_to_keyr¥   rÐ   rL  rÎ   r-   Úpick_loop_ordersÚsort)r½  rC  Úpriority_idxr¾  ÚorderÚpis   ``    rs   Úpick_loop_orderrÆ  #  s�   ù€ ô ×Ñõó ðô4 ”œ%¤ N°1Ñ$5Ó 6Ó7Ó8Ó9€EÜ
ˆ<Ó˜1Òà7CÖD°˜.¨Ó,ÒDˆÜ×ÒØ�
‰
�yˆ
Ô!Ø€Lùò Es   ÁBc                óÄ  — |j                  «       }| j                  «       }t        |t        «      rt        |t        «      sJ ‚|j                  «       }| j                  «       }t        |t        «      rt        |t        «      sJ ‚t        j
                  j                  |= ||_        t        j
                  j                  |= ||_	        t        j
                  j                  j                  | «      }t        j
                  j                  j                  |«       |t        j
                  j                  |<   |t        j
                  j                  |<   t        j
                  j                  j                  | «      }t        j
                  j                  j                  |«       |t        j
                  j                  |<   |t        j
                  j                  |<   y r~   )râ  r²   r,  r¼  ra   rÁ   r£  r×   Ú
name_to_opÚoperation_nameÚbuffersrØ   r0  Ú
operations)Ú	orig_noder]  Úreplaced_buf_nameÚorig_buf_nameÚreplaced_op_nameÚorig_op_nameÚorigs          rs   Ú_replace_operation_bufferrÒ  Q  sU  € ð !×)Ñ)Ó+ÐØ×&Ñ&Ó(€MÜ�m¤SÔ)¬jÐ9JÌCÔ.PÐPÐPà×2Ñ2Ó4ÐØ×/Ñ/Ó1€LÜ�l¤CÔ(¬ZÐ8HÌ#Ô-NÐNÐNä	�‰×ÑÐ0Ð1Ø!€H„Mä	�‰×ÑÐ+Ð,Ø*€HÔä�7‰7�?‰?× Ñ  Ó+€DÜ‡G�G‡O�O×Ñ˜8Ô$Ø$„A‡G�G‡O�O�DÑØ,4„A‡G�G×Ñ˜=Ñ)ä�7‰7×Ñ×#Ñ# IÓ.€DÜ‡G�G×Ñ×Ñ˜hÔ'Ø'„A‡G�G×Ñ�tÑØ'/„A‡G�G×Ñ�|Ò$ru   c                óp   — | j                  «       }|j                  «       }||z
  }||z  }|d|z   z  }||z  S rH  )r3  r1  )rˆ   r‰   Úepilogue_runtimeÚtemplate_write_bytesÚepilogue_read_bytesÚextra_bytesÚextra_bytes_ratioÚextra_memory_ratios           rs   Ú _estimate_fused_epilogue_runtimerÚ  m  sX   € Ø ×7Ñ7Ó9ÐØ×5Ñ5Ó7ÐØ%Ð(<Ñ<€Kð $Ð&:Ñ:Ðð +¨aÐ2CÑ.CÑDÐØÐ 0Ñ0Ð0ru   c                ó‚   — |dk\  ry|j                   }|€y|sJ ‚||j                  z  }| |z  }||z  }||z  }	||z  }
|	|
fS )Né   )r   r  )r   r   )Úregs_per_multiprocessorÚwarp_size_or_default)Úunfused_n_regsÚfused_n_regsÚfused_n_spillsÚ	num_warpsÚdevice_propsÚregs_per_smÚthreads_per_blockÚregs_per_block_unfusedÚregs_per_block_fusedÚblocks_unfusedÚblocks_fuseds              rs   Ú"_occupancy_before_and_after_fusionrê  z  sw   € ð ˜ÒØð ×6Ñ6€KØÐØáÐˆ9Ø! L×$EÑ$EÑEÐà+Ð.?Ñ?ÐØ'Ð*;Ñ;Ðà Ð$:Ñ:€NØÐ"6Ñ6€Là˜<Ð'Ð'ru   c                ó€   — d}d}t        |||||«      \  }	}
|d| z  kD  xr |
dkD  }|
dk7  xr |
|k\  xs |
|	z  |kD  xs |S )zE
    Determine whether to fuse an epilogue into a GEMM template.
    rå  g      à?rÍ   r   r  )rê  )Úms1Úms2rß  rà  rá  râ  rã  ÚMIN_ACCEPTED_OCCUPANCYÚREGRESSED_OCCUPANCY_RATIOrè  ré  Ú,epilogue_dominated_with_sufficient_occupancys               rs   Ú_fuse_epiloguerñ  •  s€   € ð ÐØ #Ðô $FØ˜ n°iÀó$Ñ €N�Lð 47¸¸S¹±=Ò3UÀ\ÐTUÑEUÐ0ð
 ˜2Ñò ØÐ.Ñ.ò 	8Ø˜.Ñ(Ð+DÑDò	8à7ðru   c                  óT   — e Zd ZU ded<   dZded<   dZded<   dd„Zdd„Zdd	„Zdd
„Z	y)r1  úBaseSchedulerNode | OutputNoder”   Fr}   rï  Úis_weakc                óv   — t        | j                  j                  «       | j                  | j                  f«      S r~   )ræ  r”   râ  rï  rô  rq   s    rs   rç  zNodeUser.__hash__¾  s+   € Ü�T—Y‘Y×'Ñ'Ó)¨4×+;Ñ+;¸T¿\¹\ÐJÓKÐKru   c                óÔ   — t        |t        «      xrW | j                  «       |j                  «       k(  xr4 | j                  |j                  k(  xr | j                  |j                  k(  S r~   )r²   r1  râ  rï  rô  ©rr   r  s     rs   Ú__eq__zNodeUser.__eq__Á  s[   € ä�uœhÓ'ò .Ø—‘“ 5§>¡>Ó#3Ñ3ò.à× Ñ  E×$5Ñ$5Ñ5ò.ð —‘ §¡Ñ-ð		
ru   c                ó6   — | j                   j                  «       S r~   rö  rq   s    rs   râ  zNodeUser.get_nameÉ  r÷  ru   c                óÄ   — | j                   |j                   u sJ ‚t        | j                   | j                  xr |j                  | j                  xr |j                  «      S r~   )r”   r1  rï  rô  r÷  s     rs   r  zNodeUser.mergeÌ  sP   € Ø�y‰y˜EŸJ™JÑ&Ð&Ð&ÜØ�I‰IØ×ÑÒ2 ×!2Ñ!2Ø�L‰LÒ*˜UŸ]™]ó
ð 	
ru   Nr  )r  Úobjectr�   r}   r  )r  r1  r�   r1  )
r€   r�   r‚   rƒ   rï  rô  rç  rø  râ  r  r…   ru   rs   r1  r1  µ  s3   … à
(Ó(Ø€K�Óð €GˆTÓóLó
ó$ô
ru   r1  c                ó¦  — t        «       }| j                  «       }t        |t        j                  «      r�|j                  t        |j                  «      t        |j                  «      z  t        |j                  «      z  «       t        |t        j                  «      r$|j                  t        |j                  «      «       |S |�
J d|› �«       ‚|S )z=Get free symbols from a node's layout (size, stride, offset).z*Expect layout to be None but found layout=)r   Úmaybe_get_layoutr²   r0   ÚLayoutrÝ  r&   rÜ   ÚstrideÚoffsetr	  Úget_layout_symintsr  )r”   Úfree_symbol_usesrí  s      rs   r  r  Ø  s³   € ä1;³ÐØ×"Ñ"Ó$€FÜ�&œ"Ÿ)™)Ô$Ø×ÑÜ˜Ÿ™Ó%Ü˜6Ÿ=™=Ó)ñ*ä˜6Ÿ=™=Ó)ñ*ô	
ô
 �fœb×;Ñ;Ô<à×#Ñ#Ô$6°v·}±}Ó$EÔFð Ðð ˆ~ÐTÐ!KÈFÈ8ÐTÓTˆ~ØÐru   c                ó"  — t        | t        «      r( t        «       j                  d„ | j                  D «       Ž S | j
                  €J ‚| j
                  j                  «       } |j                  d„ | j
                  j                  «       D «       Ž  |S )z‡
    Gets symbols used in a scheduler node, including free symbols from
    the node's operations and layout symints from outputs.
    c              3  ó2   K  — | ]  }t        |«      –— Œ y ­wr~   ©Úget_scheduler_node_symbol_uses)r·   r¸  s     rs   r¹   z1get_scheduler_node_symbol_uses.<locals>.<genexpr>ó  s   è ø€ ÒM¸Ô,¨U×3ÑMùó   ‚c              3  ó2   K  — | ]  }t        |«      –— Œ y ­wr~   )r  )r·   Úir_nodes     rs   r¹   z1get_scheduler_node_symbol_uses.<locals>.<genexpr>ø  s   è ø€ Ò	M¨'Ô
˜W×
%Ñ	Mùr  )	r²   rÚ   r   r©  rÛ   r”   Úget_free_symbol_usesrÝ  r<  )r”   r  s     rs   r  r  ê  s…   € ô �$Ô*Ô+Ø!Œz‹|×!Ñ!ÙMÀÇÁÔMð
ð 	
ð �9‰9Ð Ð Ð Ø—y‘y×5Ñ5Ó7ÐØÐ×ÑÙ	M°T·Y±Y×5JÑ5JÓ5LÔ	Mñð Ðru   c                óv   — | j                  «       }|�|j                  �|j                  S t        j                  S ©z4Check per-template flag, fall back to global config.)r‡  Úallow_epilogue_fusionr-   Úepilogue_fusion©r•  Útbs     rs   Ú_is_epilogue_fusion_enabledr  ý  ó8   € à	×	(Ñ	(Ó	*€BØ	€~˜"×2Ñ2Ð>Ø×'Ñ'Ð'Ü×!Ñ!Ð!ru   ©Úcheck_configc               óH  — |rt         j                  syt        | t        «      syt        | j                  t
        j                  «      syt        | j                  j                  t
        j                  «      sy| j                  j                  j                  dk7  ry| j                  «       }t        |«      dk7  ry|d   j                  «       st        |d   j                  «       «      dk7  ry| j                  j                  }t!        |«      xr t#        d„ |D «       «      S )NFr–  r   r   c              3  ó^   K  — | ]%  }t        |t        «      xr |j                  d k(  –— Œ' y­w)r–  N)r²   r9   r•  )r·   Úwrites     rs   r¹   z3_is_atomic_add_mutation_epilogue.<locals>.<genexpr>  s-   è ø€ ò  ØHMŒ
�5œ)Ó$ÒC¨¯©°|Ñ)CÓCñ ùs   ‚+-)r-   Úepilogue_fusion_with_atomic_addr²   r³   r”   r0   r   r÷   ÚScatterÚscatter_moder<  rÎ   rî  rð  rÕ   rQ  r}   rº   )r”   r  r,  rQ  s       rs   Ú _is_atomic_add_mutation_epiloguer    sç   € ñ œF×BÒBØÜ�dœMÔ*ØÜ�d—i‘i¤×!2Ñ!2Ô3ØÜ�d—i‘i—n‘n¤b§j¡jÔ1ØØ‡y�y‡~�~×"Ñ" lÒ2Øà×ÑÓ €GÜ
ˆ7ƒ|�qÒØØˆq�z×ÑÔ¤3 w¨q¡z×'?Ñ'?Ó'AÓ#BÀaÒ#GØà×Ñ×$Ñ$€FÜ�‹<ò œCñ  ØQWô ó ð ru   c                óp   — | j                  «       }t        |t        j                  «      xr t	        |«      S r~   )r‡  r²   r0   ÚTritonTemplateBufferr  )r•  Úepilogue_nodeÚtemplate_bufs      rs   Ú&_can_fuse_atomic_add_template_epiloguer     s7   € ð !×2Ñ2Ó4€LÜØ”b×-Ñ-óò :ä
*¨=Ó
9ð:ru   c                óv   — | j                  «       }|�|j                  �|j                  S t        j                  S r  )r‡  Úallow_prologue_fusionr-   Úprologue_fusionr  s     rs   Ú_is_prologue_fusion_enabledr$  (  r  ru   c                ób   — | j                  «       xr |j                  «        xr t        | «      S r~   )rç  r  r‹   s     rs   Úis_epilogue_fusionr&  0  ó4   € à×ÑÓò 	/Ø×!Ñ!Ó#Ð#ò	/ä'¨Ó.ðru   c                ób   — |j                  «       xr | j                  «        xr t        |«      S r~   )rç  r$  r‹   s     rs   Úis_prologue_fusionr)  8  r'  ru   c                ó6   — t        | |«      xs t        | |«      S r~   )r&  r)  r‹   s     rs   Úis_template_fusionr+  @  s   € Ü˜e UÓ+ÒOÔ/AÀ%ÈÓ/OÐOru   c                ó"   — t        | |«      r|S | S r~   )r&  r‹   s     rs   Útemplate_fusion_pw_noder-  D  s   € Ü& u¨eÔ4ˆ5Ð?¸%Ð?ru   c                  ó¤   — e Zd ZU dZ ej
                  e¬«      Zded<    ej
                  e¬«      Z	ded<   e
dd„«       Zdd„Zdd	„Zdd
„Zdd„Zy)Ú_LoopStateSnapshota  Captured loop state for a set of scheduler nodes, restorable on rollback.

    Stores both SchedulerNode loop state (body, sizes, deps) and
    FusedSchedulerNode group assignments, since the latter is reassigned
    directly after child reindexing and has no mutation listener.
    rŸ   z$dict[SchedulerNode, tuple[Any, ...]]Úscheduler_node_stateszdict[FusedSchedulerNode, Any]Úfused_node_groupsc                óD   —  | «       }|D ]  }|j                  |«       Œ |S )zDCapture scheduler-node boundaries and their mutable leaf loop state.)Úsnapshot_node)rx   rq  Úsnapshotr”   s       rs   r›  z_LoopStateSnapshot.createX  s-   € ñ “5ˆØò 	)ˆDØ×"Ñ" 4Õ(ð	)àˆru   c                ó^   — || j                   vsJ ‚|j                  «       | j                   |<   y)z?Capture one leaf scheduler node before its first loop mutation.N)r0  r9  ©rr   r^  s     rs   Ú_snapshot_scheduler_nodez+_LoopStateSnapshot._snapshot_scheduler_node`  s/   € à˜×3Ñ3Ñ3Ð3Ð3Ø)+×)?Ñ)?Ó)Aˆ×"Ñ" 2Ò&ru   c                óV   — || j                   vsJ ‚|j                  | j                   |<   y)zACapture fused-node group metadata changed outside leaf listeners.N)r1  rÆ   rì  s     rs   Ú_snapshot_fused_nodez'_LoopStateSnapshot._snapshot_fused_nodee  s*   € à˜4×1Ñ1Ñ1Ð1Ð1Ø'+§z¡zˆ×Ñ˜tÒ$ru   c                ó´   — t        |t        «      r| j                  |«       |j                  «       D ]$  }t        |t        «      sŒ| j                  |«       Œ& y)zBCapture a scheduler node boundary and all mutable leaf loop state.N)r²   rÚ   r9  r»   r³   r7  )rr   r”   r^  s      rs   r3  z _LoopStateSnapshot.snapshot_nodej  sI   € ä�dÔ.Ô/Ø×%Ñ% dÔ+Ø—.‘.Ó"ò 	2ˆBÜ˜"œmÕ,Ø×-Ñ-¨bÕ1ñ	2ru   c                óÒ   — | j                   j                  «       D ]  \  }}|j                  |«       Œ | j                  j                  «       D ]  \  }}||_        t        |«       Œ y)z>Restore all captured loop state and fused-node group metadata.N)r0  rÀ  r<  r1  rÆ   rª  )rr   r^  r;  r”   rÆ   s        rs   Úrestorez_LoopStateSnapshot.restorer  sc   € à×3Ñ3×9Ñ9Ó;ò 	)‰IˆB�Ø×!Ñ! %Õ(ð	)à×1Ñ1×7Ñ7Ó9ò 	2‰KˆD�%ØˆDŒJÜ+¨DÕ1ñ	2ru   N)rq  r  r�   r/  ©r^  r³   r�   r  )r”   rÚ   r�   r  ©r”   rf   r�   r  r  )r€   r�   r‚   r•   r£   r¤   rx  r0  rƒ   r1  r„   r›  r7  r9  r3  r<  r…   ru   rs   r/  r/  H  st   … ñð CTÀ+×BSÑBSØôCÐÐ?ó ð 8I°{×7HÑ7HØô8ÐÐ4ó ð òó ðóBó
2ó
2ô2ru   r/  c                  ó„   — e Zd ZU dZded<    ej                  e¬«      Zded<   dZ	ded	<   e
dd
„«       Zdd„Zdd„Zdd„Zy)Ú_LoopMutationTrackera+  Rollback scope for speculative loop mutations during can_fuse().

    can_fuse() may speculatively reorder or reindex loops while evaluating
    whether a fusion is legal. If the final decision rejects the fusion,
    this tracker restores the original loop structure so later fusion
    candidates do not inherit a speculative layout chosen for a fusion
    that did not happen.

    The first active tracker for a SchedulerNode leaf owns that leaf's
    listener. Recursive can_fuse() calls reuse the outer listener instead of
    installing nested listeners, so the captured state is the original state at
    the outermost decision boundary.

    Usage: call finish(commit=True) to keep mutations, or finish(commit=False)
    to restore the original state. If no mutation occurred, finish() is a no-op.
    r  rq  rŸ   zOrderedSet[SchedulerNode]Úwatched_nodesNz_LoopStateSnapshot | Noner;  c                ó¼   — t        |«      } | t        |«      ¬«      }|D ]9  }|j                  «       D ]$  }t        |t        «      sŒ|j                  |«       Œ& Œ; |S )z?Create a rollback scope and watch mutable leaf scheduler nodes.)rq  )r   rÏ   r»   r²   r³   Úwatch)rx   rq  ÚseenÚtrackerr”   r^  s         rs   r›  z_LoopMutationTracker.create”  s^   € ô ˜%Ó ˆÙœE $›KÔ(ˆØò 	&ˆDØ—n‘nÓ&ò &�Ü˜b¤-Õ0Ø—M‘M "Õ%ñ&ð	&ð ˆru   c                óv   — |j                   �y| j                  j                  |«       | j                  |_         y)z<Install this scope as the mutation listener for a leaf node.N)r  rA  r¢  Útrackr6  s     rs   rC  z_LoopMutationTracker.watchŸ  s1   € à×%Ñ%Ð1àØ×Ñ×Ñ˜rÔ"Ø%)§Z¡ZˆÕ"ru   c                ó†   — || j                   v sJ ‚| j                  �yt        j                  | j                  «      | _        y)z?Lazily snapshot candidate roots when the first mutation occurs.N)rA  r;  r/  r›  rq  r6  s     rs   rG  z_LoopMutationTracker.track§  s;   € à�T×'Ñ'Ñ'Ð'Ð'Ø�:‰:Ð!àô
 (×.Ñ.¨t¯z©zÓ:ˆ�
ru   c               ó†   — | j                   D ]	  }d|_        Œ |r| j                  €y| j                  j                  «        y)z<Detach listeners and restore captured state if rolling back.N)rA  r  r;  r<  )rr   Úrollbackr^  s      rs   Úfinishz_LoopMutationTracker.finish³  s>   € à×$Ñ$ò 	.ˆBØ)-ˆBÕ&ð	.á˜4Ÿ:™:Ð-ØØ�
‰
×ÑÕru   )rq  r  r�   r@  r=  )rJ  r}   r�   r  )r€   r�   r‚   r•   rƒ   r£   r¤   r   rA  r;  r„   r›  rC  rG  rK  r…   ru   rs   r@  r@  {  sZ   … ñð" )Ó(Ø/@¨{×/@Ñ/@Ø"ô0€MÐ,ó ð (,€EÐ$Ó+àòó ðó0ó
;ôru   r@  c                  ó.  ‡ — e Zd ZdZd�d„Zd�ˆ fd„Zd‚d„Zdƒd„Zd„d„Zd…d„Z	d†d„Z
ed‡d	„«       Zej                  dˆd
„«       Zdƒd„Zd‰d„ZdŠd„Zdƒd„Zdƒd„Zdƒd„Zdƒd„Zd‹d„Z	 	 	 	 dŒd„Zdƒd„Zd�d„ZdŽd„Zdƒd„Zdƒd„Zdƒd„ZdŒd„Zdƒd„Z	 	 	 	 d�d„Z	 d�	 	 	 	 	 	 	 d‘d„Z 	 	 	 	 	 	 d’d„Z!	 	 	 	 d“d „Z"dƒd!„Z#	 	 	 	 	 	 	 	 	 	 d”d"„Z$d•d#„Z%	 d�	 	 	 	 	 d–d$„Z&	 	 	 	 	 	 d—d%„Z'd˜d&„Z(	 	 	 	 	 	 	 	 d™d'„Z)	 	 	 	 	 	 	 	 dšd(„Z*	 	 	 	 	 	 d›d)„Z+	 	 	 	 	 	 	 	 	 	 dœd*„Z,	 	 	 	 d�d+„Z-	 	 	 	 džd,„Z.	 	 	 	 	 	 dŸd-„Z/e0	 	 	 	 	 	 	 	 d d.„«       Z1d�d¡d/„Z2d¢d0„Z3	 	 	 	 	 	 	 	 d£d1„Z4	 	 	 	 	 	 	 	 	 	 	 	 d¤d2„Z5d¥d3„Z6	 	 	 	 	 	 d¦d4„Z7	 	 	 	 	 	 d§d5„Z8	 	 	 	 	 	 d§d6„Z9	 	 	 	 	 	 	 	 d¨d7„Z:	 	 	 	 	 	 d§d8„Z;	 	 	 	 	 	 	 	 d©d9„Z<	 	 	 	 	 	 dªd:„Z=	 	 	 	 	 	 dªd;„Z>	 	 	 	 	 	 dªd<„Z?	 	 	 	 	 	 d§d=„Z@d«d>„ZA	 	 	 	 	 	 	 	 d¬d?„ZB	 	 	 	 	 	 d­d@„ZC	 	 	 	 	 	 d®dA„ZD	 	 	 	 	 	 d¯dB„ZE	 	 	 	 	 	 	 	 	 	 d°dC„ZF	 	 d±	 	 	 	 	 	 	 	 	 d²dE„ZG	 	 d±	 	 	 	 	 	 	 	 	 d²dF„ZH	 	 	 d³	 	 	 	 	 	 	 	 	 	 	 d´dG„ZIddHœ	 	 	 	 	 	 	 dµdI„ZJ	 	 	 	 	 	 	 	 d¶dJ„ZKe0d·dK„«       ZLdDdLœ	 	 	 	 	 	 	 d¸dM„ZM	 	 	 	 	 	 d·dN„ZNe0d·dO„«       ZO	 	 	 	 	 	 	 	 d¹dP„ZPe0dºdQ„«       ZQd»d¼dR„ZR	 	 d½	 	 	 	 	 	 	 	 	 d¾dS„ZS	 	 d½	 	 	 	 	 	 	 	 	 d¿dT„ZTeU	 	 	 dÀ	 	 	 	 	 	 	 	 	 	 	 dÁdU„«       ZVeU	 	 	 dÀ	 	 	 	 	 	 	 	 	 	 	 dÂdV„«       ZV	 	 	 dÃ	 	 	 	 	 	 	 	 	 	 	 dÄdW„ZV	 	 	 	 	 	 d§dX„ZW	 	 	 	 	 	 dªdY„ZX	 	 	 	 dÅdZ„ZY	 	 	 	 dÆd[„ZZdƒd\„Z[dƒd]„Z\dƒd^„Z]	 	 	 	 dÇd_„Z^dÈd`„Z_dÉda„Z`dÊdb„Za	 	 	 	 	 	 dËdc„ZbdÌdd„ZceddÍde„«       Ze	 	 	 	 dÌdf„Zf	 	 dÎdg„Zg	 	 	 	 dÏdh„Zh	 	 	 	 	 	 dÐdi„Zi	 	 	 	 	 	 dÑdj„Zj	 	 	 	 	 	 dÒdk„Zk	 	 	 	 dŒdl„Zl	 	 	 	 dŒdm„Zm	 	 	 	 dŒdn„Zn	 	 dÓdo„Zo	 	 	 	 	 	 dÔdp„ZpdÊdq„Zqdƒdr„Zr	 	 	 	 	 	 dÕds„Zs	 	 	 	 	 	 dÖdt„Zt	 	 	 	 	 	 dÔdu„Zudƒdv„Zvd¥dw„Zw	 	 	 	 d×dx„ZxdØdy„ZydÙdz„Zzdƒd{„Z{edÚd|„«       Z|edÛd}„«       Z}dÊd~„Z~dƒd„ZdÊd€„Z€ˆ xZ�S )ÜrÛ  z�
    A Scheduler is a graph of BaseSchedulerNodes. It is responsible for
    optimizations such as fusion, reorder, and graph partition.
    c                óf   — t        d«      5  | j                  |«       d d d «       y # 1 sw Y   y xY w)NzScheduler.__init__)r   Ú_init©rr   rq  s     rs   r:  zScheduler.__init__Â  s,   € ÜÐ.Ó/ñ 	Ø�J‰J�uÔ÷	÷ 	ñ 	ús   Œ'§0c           
     ó¶  •‡ — t         ‰‰ �  «        ‰ t        j                  _        i ‰ _        t        t        «      ‰ _        t        j                  «       ‰ _        t        «       ‰ _        t        g t        j                  j                  j                  «       ¢t        j                  j                   j                  «       ¢t        j                  j"                  j                  «       ¢«      ‰ _        |D �cg c]  }‰ j'                  |«      ‘Œ c}‰ _        d ‰ _        d ‰ _        ‰ j/                  «        ‰ j$                  j1                  t        j                  j                   j                  «       «       ‰ j(                  D ]  }|j3                  «        Œ d ‰ _        ‰ j7                  «       ‰ _        ‰ j(                  D �ci c]  }|j;                  «       |“Œ c}‰ _        ‰ j(                  D ��ci c](  }|j?                  «       D ]  }|j;                  «       |“Œ Œ* c}}‰ _         ‰ j<                  jC                  «       ‰ _"        i ‰ _#        i ‰ _$        t        «       ‰ _%        tM        jN                  ‰ j(                  ‰ j@                  ‰ jD                  «      ‰ _        ‰ jQ                  «        ‰ jS                  ‰ j(                  «      ‰ _        ‰ jU                  «        ‰ j(                  D �ci c]  }|j;                  «       |“Œ c}‰ _"        ‰ jW                  «        ‰ jY                  «        tZ        xj\                  t_        ‰ j(                  «      z  c_.        ddl0m1}m2}  |‰ j(                  «       t_        ‰ j(                  «      ‰ _3        ‰ ji                  «        ‰ jS                  ‰ j(                  «      ‰ _        t        tj        tl        tl        f      «       ‰ _7        tp        jr                  �$tq        jr                  ‰ j(                  «      ‰ _        tp        jt                  r'ddl;m<} |j{                  ‰ «       ‰ jW                  «        i ‰ _>        i ‰ _?        d‰ _@        i ‰ _A        ‰ j…                  «        ‰ j‡                  ‰ j(                  «      ‰ _        tp        jˆ                  �$tq        jˆ                  ‰ j(                  «      ‰ _        t‹        d„ ‰ j(                  D «       «      r‰ jU                  «        ‰ j�                  «        ‰ j�                  «        tp        j�                  stp        j’                  r<t•        «       r2t–        j˜                  jš                  jœ                  jŸ                  «        tp        j                   r)t£        ddd¬	«      5  ‰ j¥                  d ¬
«       d d d «       ‰ j§                  «        tp        j¨                  r‰ddlUmT}  |‰ j(                  ‰ j@                  ‰ jD                  t        t        j                  j                  j                  «       «      t        t        j                  j­                  «       «      «      ‰ _        tp        j®                  sâtp        j°                  rÒtp        j¨                  s#ddlUmY}	  |	‰ j(                  ‰ j@                  «       t´        j¶                  rFd}
‰ j(                  D ]  }t¹        |jº                  «      sŒd}
 n |
rddl&m^}  |‰ j(                  «       t´        j¾                  rddl`ma}  |dd„ ˆ fd„¬«       tM        jÄ                  ‰ j(                  «      ‰ _        ‰ jÇ                  «        tp        jÈ                  rttp        jÊ                  jÌ                  rZtp        jÊ                  jÎ                  r@‰ jÑ                  ‰ j(                  «      ‰ _        ‰ jÓ                  ‰ j(                  «      ‰ _        ‰ jÕ                  «        t–        j˜                  jp                  jÖ                  jØ                  r‰ jÛ                  «         |‰ j(                  «       t        jÜ                  jß                  ‰ j(                  «       ‰ já                  «        t        «       ‰ _q        i ‰ _r        d ‰ _s        té        d«      jë                  ˆ fd„«       t        «       ‰ _v        y c c}w c c}w c c}}w c c}w # 1 sw Y   �Œ1xY w)Nr   )Úlog_ir_post_fusionÚlog_ir_pre_fusionr   )Údistributed_autotuneFc              3  ó<   K  — | ]  }t        |t        «      –— Œ y ­wr~   )r²   r*  rÂ  s     rs   r¹   z"Scheduler._init.<locals>.<genexpr>/  s    è ø€ ò 
àô �tÔA×Bñ
ùrÃ  z#Scheduler.create_combo_kernel_nodesT©Úlog_pt2_compile_eventÚlog_waitcounter)Únum_ck_nodes)Úreorder_for_peak_memory)Ú1assign_memory_planning_info_for_scheduler_buffers)Ú6align_runtime_estimations_across_all_distributed_ranks)Útrace_structuredÚartifactc                 ó   — dddœS )NÚ#scheduler_nodes_before_comm_overlapÚstring)r×   Úencodingr…   r…   ru   rs   r8  z!Scheduler._init.<locals>.<lambda>u  s   € Ø EØ$,ñ)€ ru   c            
     óÐ   •— dj                  t        ‰j                  «      D � �cg c]0  \  } }d| › d�|j                  «       z   d|j	                  «       › �z   ‘Œ2 c}} «      S c c}} w )Nz

zsnode[rë  z buffer_names:)rd  r’  rq  rô  rÇ  )r�  rÍ  rr   s     €rs   r8  z!Scheduler._init.<locals>.<lambda>y  sl   ø€  v§{¡{ô
 )2°$·*±*Ó(=÷	ñ !%  1ð % Q C q˜MØŸk™k›mñ,à .¨q×/AÑ/AÓ/CÐ.DÐEóFóó(€ ùós   ¥5A"
)Úmetadata_fnÚ
payload_fnÚgraph_statsc                 ó^   •— ‰ j                   ‰ j                  t        ‰ j                  «      dœS )N)Úgraph_idÚnum_nodes_before_fusionÚnum_nodes_after_fusion)Úpost_grad_graph_idÚnum_orig_nodesrÎ   rq  rq   s   €rs   r8  z!Scheduler._init.<locals>.<lambda>¥  s'   ø€ Ø ×3Ñ3Ø+/×+>Ñ+>Ü*-¨d¯j©j«/ñ€ ru   )wrý  r:  ra   rÁ   rÜ  Úbackendsr‘  Ú_post_grad_graph_counterrj  rš  ÚcountÚ_graph_partition_counterr   r  rX  r!  Ú	constantsÚtorchbind_constantsr¨  Úcreate_scheduler_noderq  Úprevious_nodeÚcurrent_nodeÚupdate_zero_dim_cpu_tensorrÝ  r†  Údefault_device_contextÚget_donated_buffersr  râ  rI  r<  r  Úcopyr¹  r�  r)  Úseen_template_fusionsr,   Údecide_global_ordering_of_commsrd   Útopological_sort_scheduleÚdead_node_eliminationÚcompute_ancestorsÚcompute_input_distancesr1   Úir_nodes_pre_fusionrÎ   Útorch._inductor.debugrQ  rR  rk  Úcreate_foreach_nodesrÏ   r,  Úlogged_slow_fusionr-   Ú_pre_fusion_custom_passÚdistributed_max_autotune_gemmrX  rS  Úschedulerv  Úbuff_to_streamÚ_multi_stream_nodesÚstream_idx_to_user_obj_idxÚ_populate_stream_assignmentsrŸ  Ú_post_fusion_custom_passr  r\  Úfinalize_multi_template_buffersÚmax_autotune_gemmÚmax_autotuner   r`  ra  Úselect_algorithmÚPrecompileThreadPoolÚshutdown_instanceÚcombo_kernelsr   Úcreate_combo_kernel_nodesÚ_enforce_conditional_orderingrY  ÚmemoryÚget_output_namesÚdeterministicÚ reorder_for_compute_comm_overlaprZ  r.   Ú6runtime_estimations_align_across_all_distributed_ranksrY   r”   r[  Úreorder_sink_verbose_loggingÚtorch._loggingr\  Ú$reorder_compute_and_comm_for_overlapÚprocess_grouped_nodesÚgraph_partitionr©   re   Ú%reorder_for_reducing_graph_partitionsÚ&maybe_reorder_for_minimizing_partitionÚ,reorder_for_partition_with_simple_dependencyÚcompute_last_usageÚtest_configsÚtrack_memory_lifecycleÚinsert_memory_check_nodesrÝ  Úgraph_diagramÚdebug_draw_graphÚbuffer_names_to_freeÚorigin_to_indexÚ_current_stream_ctxr#   Úadd_rowÚremoved_ops)rr   rq  rÍ  r”   rÞ   rQ  rR  rS  rY  rZ  Úhas_collectivesr[  r\  r  s   `            €rs   rN  zScheduler._initÆ  s´  ù€ Ü‰ÑÔØ Œ�‰ÔØ<>ˆŒÜ"&Ô'?Ó"@ˆÔÜ(1¯©Ó(9ˆÔ%ä5?³\ˆÔ!Ü&0ðÜ—‘×%Ñ%×*Ñ*Ó,ðä—‘×"Ñ"×'Ñ'Ó)ðô —‘×,Ñ,×1Ñ1Ó3ðó'
ˆÔ#ð >CÖC¸�d×0Ñ0°Õ3ÒCˆŒ
Ø7;ˆÔØ6:ˆÔØ×'Ñ'Ô)à×#Ñ#×*Ñ*¬1¯7©7×+<Ñ+<×+AÑ+AÓ+CÔDØ—J‘Jò 	ˆDØ�O‰OÕð	ð <@ˆÔ#ð ×$Ñ$Ó&ð 	Ô#ð &*§Z¡Zö;
Ø !ˆA�J‰J‹L˜!‰Oò;
ˆÔð
 -1¯J©J÷8
Ø$(À$×BRÑBRÓBTò8
Ø;>ˆC�L‰L‹N˜CÑð8
Øó8
ˆÔð AE×@QÑ@Q×@VÑ@VÓ@XˆÔð 35ˆÔð 13ˆÔô ‹Lð 	Ô"ô
 ×:Ñ:Ø�J‰JØ×ÑØ×#Ñ#ó
ˆŒ
ð 	×!Ñ!Ô#Ø×3Ñ3°D·J±JÓ?ˆŒ
Ø×"Ñ"Ô$Ø<@¿J¹JÖ"G°q 1§:¡:£<°¡?Ò"GˆÔØ×ÑÔ Ø×$Ñ$Ô&ô 	×#Ò#¤s¨4¯:©:£Ñ6Õ#ßOá˜$Ÿ*™*Ô%Ü! $§*¡*›oˆÔØ×!Ñ!Ô#Ø×3Ñ3°D·J±JÓ?ˆŒ
Ü",¬U´3¼°8©_Ñ"=Ó"?ˆÔÜ×)Ñ)Ð5Ü×7Ñ7¸¿
¹
ÓCˆDŒJä×/Ò/Ý.à ×)Ñ)¨$Ô/Ø×"Ñ"Ô$ð =?ˆÔØ.0ˆÔØ).ˆÔ à:<ˆÔ'Ø×)Ñ)Ô+à—_‘_ T§Z¡ZÓ0ˆŒ
Ü×*Ñ*Ð6Ü×8Ñ8¸¿¹ÓDˆDŒJäñ 
àŸ
™
ô
ô 
ð ×&Ñ&Ô(à×ÑÔØ×,Ñ,Ô.ä×$Ò$¬×(;Ò(;Ü&Ô(Ü�O‰O×,Ñ,×AÑA×SÑSÔUä×ÒÜØ5Ø&*Ø $ôñ Bð
 ×.Ñ.¸DÐ.ÔA÷Bð 	×*Ñ*Ô,ô ×)Ò)Ý7á0Ø—
‘
Ø× Ñ Ø×'Ñ'Üœ1Ÿ7™7×/Ñ/×4Ñ4Ó6Ó7Üœ1Ÿ7™7×3Ñ3Ó5Ó6óˆDŒJô ×#Ò#¬×(OÒ(OÜ×1Ò1ÝUáAØ—J‘J × 0Ñ 0ôô ×RÒRØ"'�Ø ŸJ™Jò �DÜ$ T§Y¡YÕ/Ø*.˜Ùðñ #õñ KÈ4Ï:É:ÔVô ×8Ò8Ý;á Øñ!ó õô ×CÑCÀDÇJÁJÓOˆDŒJØ×"Ñ"Ô$ô ×"Ò"ä—‘×(Ò(ä—‘×CÒCà×DÑDÀTÇZÁZÓPˆDŒJØ×JÑJÈ4Ï:É:ÓVˆDŒJà×ÑÔ!ä�?‰?×!Ñ!×.Ñ.×EÒEØ×*Ñ*Ô,á˜4Ÿ:™:Ô&ä	�‰×Ñ˜dŸj™jÔ)Ø×ÑÔô 6@³\ˆÔ!ð :<ˆÔð GKˆÔ ä˜Ó'×/Ñ/óô	
ô -7«LˆÕùòs Dùò;
ùó8
ùòH #H÷hBñ Bús$   Ã5b9Æ?b>Ç.-cË(c	Öcãcc                ó  — i }t         j                  j                  D ]d  }t        t         j                  j                  |   t        j
                  «      sŒ9t        | t         j                  j                  |   d ¬«      ||<   Œf |S )N)rÝ  )ra   rÁ   Úgraph_inputs_originalr²   r0   ÚDonatedBufferr   )rr   Úname_to_donated_bufr×   s      rs   rw  zScheduler.get_donated_buffers°  sp   € Ø ÐÜ—G‘G×1Ñ1ò 	ˆDÜœ!Ÿ'™'×7Ñ7¸Ñ=¼r×?OÑ?OÕPÜ,BØÜ—G‘G×1Ñ1°$Ñ7Ø $ô-Ð# DÒ)ð	ð #Ð"ru   c                óv  ‡
— ddl mŠ
 i }t        j                  d«      }| j                  D ]‡  }‰
}|j
                  �D|j
                  j                  «       }|�(||vrt        |«      }|||<   || j                  |<   ||   }|| j                  |<   |j                  «       D ]  }|| j                  |<   Œ Œ‰ t        ˆ
fd„| j                  j                  «       D «       «      r¨t        d„ | j                  D «       d«      }|�‰| j                  D ]z  }|j
                  }	|j                  «       �Œ t        |	t         j"                  «      sŒ;t        |	j$                  t         j&                  «      sŒ`t!        j&                  |¬«      |	_        Œ| t        ˆ
fd„| j                  j                  «       D «       «      | _        y)a=  Populate node_to_stream and buff_to_stream from IR node stream_idx.

        Reads the stream_idx field set on IR nodes during lowering to determine
        which stream each scheduler node should run on. This field is propagated
        from 'custom.stream' FX node metadata via IRNode.current_stream_idx().
        r   )ÚDEFAULT_STREAM_IDXNc              3  ó(   •K  — | ]	  }|‰k7  –— Œ y ­wr~   r…   )r·   r9  r²  s     €rs   r¹   z9Scheduler._populate_stream_assignments.<locals>.<genexpr>Þ  s   øè ø€ ÒM¨1ˆqÐ&Õ&ÑMùó   ƒc              3  ó^   K  — | ]%  }|j                  «       €Œ|j                  «       –— Œ' y ­wr~   ©rª   rÌ  s     rs   r¹   z9Scheduler._populate_stream_assignments.<locals>.<genexpr>à  s!   è ø€ ÒR A°q·|±|³~Ñ7Q�—‘—ÑRùs   ‚-˜-©rÝ  c              3  ó(   •K  — | ]	  }|‰k7  –— Œ y ­wr~   r…   )r·   Ú
stream_idxr²  s     €rs   r¹   z9Scheduler._populate_stream_assignments.<locals>.<genexpr>î  s   øè ø€ ò '
àð Ð,Õ,ñ'
ùr´  )Ústream_constantsr²  rš  rn  rq  r”   Úget_stream_idxr‘  rˆ  rv  rÇ  r†  r  rÝ   rª   r²   r0   ÚBufferrí  rD   r‡  )rr   Úuser_obj_to_stream_idxÚstream_idx_counterr”   r¹  Úuser_obj_idxÚnew_stream_idxrÞ   rÝ  r	  r²  s             @rs   r‰  z&Scheduler._populate_stream_assignments»  s”  ø€ õ 	9ð 24ÐÜ&Ÿ_™_¨QÓ/Ðà—J‘Jò 	6ˆDØ+ˆJà�y‰yÐ$Ø#Ÿy™y×7Ñ7Ó9�ØÐ+Ø#Ð+AÑAÜ)-Ð.@Ó)A˜Ø?MÐ.¨|Ñ<ØJV˜×7Ñ7¸ÑGØ!7¸Ñ!E�Jà(2ˆD×Ñ Ñ%ð ×,Ñ,Ó.ò 6�Ø+5�×#Ñ# CÒ(ñ6ð!	6ô, ÓM°×0CÑ0C×0JÑ0JÓ0LÔMÔMÜÙR¨¯©ÔRÐTXóˆFð Ð!Ø ŸJ™Jò F�DØ"Ÿi™i�GàŸ™Ó)Ñ1Ü& w´·	±	Õ:Ü& w§~¡~´r·}±}ÕEô *,¯©¸fÔ)E˜�ðFô $'ó '
à"×1Ñ1×8Ñ8Ó:ô'
ó $
ˆÕ ru   c                ó   — | j                   S )z7Check if any nodes are assigned to non-default streams.)r‡  rq   s    rs   Ú_has_multi_stream_nodesz!Scheduler._has_multi_stream_nodesó  s   € à×'Ñ'Ð'ru   c                ó¦   — | j                   j                  ||«      }| j                  j                  || j                  j                  |d«      «      S )zAReturn the stream index for a buffer, resolving mutation renames.r   )r)  r±  r†  )rr   rÖ  Úreals      rs   Úget_buf_streamzScheduler.get_buf_stream÷  sF   € à×$Ñ$×(Ñ(¨°8Ó<ˆØ×"Ñ"×&Ñ& t¨T×-@Ñ-@×-DÑ-DÀXÈqÓ-QÓRÐRru   c                ó€   — | j                  «       sy| j                  |«      | j                  j                  |d«      k7  S )z»True if buf_name was produced on a different stream than node.

        Resolves mutation renames so that mutated buffers inherit the
        stream of their original definition.
        Fr   )rÂ  rÅ  rv  r±  )rr   rÖ  r”   s      rs   r  z!Scheduler.has_cross_stream_hazardü  s<   € ð ×+Ñ+Ô-ØØ×"Ñ" 8Ó,°×0CÑ0C×0GÑ0GÈÈaÓ0PÑPÐPru   c                ó6   — t         j                  j                  S r~   ©ra   rÁ   Úcurrent_devicerq   s    rs   rÉ  zScheduler.current_device  s   € ä�w‰w×%Ñ%Ð%ru   c                ó.   — |t         j                  _        y r~   rÈ  rÜ  s     rs   rÉ  zScheduler.current_device
  s   € à!'Œ�‰Õru   c                ó€   — t         j                  j                  dd«      dk(  rddlm}  || j
                  d¬«       yy)z,Generate an image of the graph for debuggingÚINDUCTOR_WRITE_SCHEDULER_GRAPHNÚ1r   )Údraw_buffersT)Úprint_graph)ÚosÚenvironr±  rÝ  rÎ  rq  )rr   rÎ  s     rs   r¦  zScheduler.debug_draw_graph  s1   € ä�:‰:�>‰>Ð:¸DÓAÀSÒHÝ+á˜Ÿ™°Ö6ð Iru   c                óº   — t         j                  t        j                  «      r8t         j	                  d|«       | j
                  D ]  }|j                  «        Œ y y )Nz%s:)rT  ÚisEnabledForÚloggingÚINFOrj  rq  rk  )rr   Úlabelr”   s      rs   Údebug_print_nodeszScheduler.debug_print_nodes  sF   € Ü×ÑœGŸL™LÔ)Ü�H‰H�U˜EÔ"ØŸ
™
ò #�Ø× Ñ Õ"ñ#ð *ru   c                ó6  — |j                  «       €J d«       ‚|j                  «       rt        | |«      S t        |t        j
                  t        j                  f«      rt        | |«      S t        |t        j                  «      rt        | |«      S t        |«      ‚)Nz2All nodes passed to scheduling must have an origin)r  Úis_no_opr  r²   r0   r   r!  r³   r½  rR  rò  rì  s     rs   rr  zScheduler.create_scheduler_node  s‡   € Ø×ÑÓ!Ð-ð 	
Ø@ó	
Ð-ð �=‰=Œ?Ü)¨$°Ó5Ð5Ü˜œr×0Ñ0´"×2CÑ2CÐDÔEÜ   tÓ,Ð,Ü˜œbŸo™oÔ.Ü,¨T°4Ó8Ð8ä% dÓ+Ð+ru   c                ó–  — t        «       }g }| j                  j                  «       }t        j                  j
                  j                  «       D ]«  }|D �cg c]%  }||v rt        | j                  |   t        «      s|‘Œ' }}|sŒ6|j                  |«       |D �cg c]  }| j                  |   ‘Œ }}t        j                  dkD  }t        | |d|¬«      }|j                  |«       |D ]  }|| j                  |<   Œ Œ­ | j                  D �	cg c]  }	|	j!                  «       |vsŒ|	‘Œ c}	t#        |«      z   | _        y c c}w c c}w c c}	w )Nr   F)rX  r[  )r   r¹  r!  ra   rÁ   ÚlistsrÝ   r²   rI  r  rÝ  r-   Úcombo_kernels_autotunerB  rä   rq  râ  r¥   )
rr   Úremoved_node_namesÚfe_nodesÚkept_node_namesÚnamesr×   rÛ   r[  Úfe_noder”   s
             rs   r�  zScheduler.create_foreach_nodes(  sN  € Ü.8«lÐØˆØ×1Ñ1×6Ñ6Ó8ˆä—W‘W—]‘]×)Ñ)Ó+ò 	8ˆEð "öàØ˜?Ñ*Ü" 4×#4Ñ#4°TÑ#:Ô<RÔSò ðˆEð ñ àà×%Ñ% eÔ,Ø:?Ö@°$�d×'Ñ'¨Ó-Ð@ˆFÐ@ä$×;Ñ;¸aÑ?ˆOÜ0ØØØ*/Ø /ô	ˆGð �O‰O˜GÔ$àò 8�Ø07�×'Ñ'¨Ò-ñ8ð1	8ð8 "ŸZ™Zö
Ø¨4¯=©=«?ÐBTÒ+TŠDò
ä�‹Nñˆ�
ùò5ùò Aùò
s   Á*D<ÂEÄEÄ#Ec                ó*  ‡ ‡'‡(‡)—  G ˆ'fd„dt         t           «      Š't        j                  ‰'«      Š(‰ j                  D ]Ï  }|j                  «       D ]º  }|j                  «       }t        |j                  j                  t        j                  «      rt        |j                  «       «      dkD  rŒ^|j                  «       D ]J  }|‰(v r/|‰(v r+‰(|   }‰(|   }||z   }‰(D ]  }‰(|   |u s‰(|   |u sŒ|‰(|<   Œ Œ6|‰(v r	‰(|   ‰(|<   ŒC‰(|   ‰(|<   ŒL Œ¼ ŒÑ dˆ)ˆ fd„Š)	 	 d	 	 	 	 	 	 	 	 	 dˆ(ˆ)fd„}	i }
t        j                  j                   j#                  «       D ]£  }t        |t$        j&                  «      r|j(                  D ]  }d|
|<   Œ	 Œ4t        |t        j*                  «      sŒO|j-                  «       D �cg c]  }t        |t$        j&                  «      sŒ|‘Œ! }}|D ]  }|j(                  D ]  }d|
|<   Œ	 Œ Œ¥ d}‰ j                  D ]s  }|j                  €J ‚t/        |j                  j1                  «       d„ ¬	«      }|D ]8  }t        |t$        j2                  «      sJ ‚d
}||
vsŒ&|j                  «       |
|<   Œ: Œu ‰ j                  D �]@  }t4        j7                  d|j                  «       |rŸ|j                  €J ‚t/        |j                  j9                  d
¬«      d„ ¬	«      }|D ]d  }||
v sJ |› d|
› �«       ‚|
|   x}€Œ‰ j:                  |   j                  «       D ]*  }|j=                  t?        |j                  «       «      «       Œ, Œf t        |j@                  jB                  «      dk(  rGtE        tG        |j@                  jB                  «      «      x}rt        |tH        «      r|jJ                  }nd}|j                  «       D �]7  }t        |jM                  «       «      dk  sJ ‚|jM                  «       D �]  } ‰)|«      } |	||«       |j=                  t?        ||¬«      «       ‰(|   jN                  D ]À  }|j                  «       |j                  «       k(  rŒ%t        |j                  tP        «      sJ ‚|j                  j                  «       D ]c  }|j                  «       } ‰)|«      }||j                  «       v }|j=                  tS        ||j                  «       | ¬«      «        |	||d
¬«       Œe ŒÂ �Œ �Œ: t        j                  jT                  |j                  «          D ]8  } |	||d
¬«       |j=                  tS        ||j                  «       d
¬«      «       Œ: t        j                  jV                  |j                  «          D ]'  } |	||d¬«       |j=                  t?        |«      «       Œ) |j@                  jX                  D ]6  }t        |tR        «      rŒ |	|jZ                  ||j]                  |«      «       Œ8 |j_                  ‰ j`                  «       |j                  «       D ]Ž  }|jM                  «       D ]y  }|j                  «       ‰ j`                   ‰)|«      <   |j                  «       ‰ j`                  |<   ‰ jb                  je                  ||«      ‰ jb                  |j                  «       <   Œ{ Œ� �ŒC t        j                  jg                  «       D ]3  }t4        j7                  d|«        |	|ti        t?        |«      «      «       Œ5 |r°t        j                  jj                  D ]“  }|j9                  d
¬«      D ]|  }||
v sJ |› d|
jm                  «       › �«       ‚|
|   x}sŒ)‰ j:                  |   jo                  «       D ]4  }t4        j7                  d||«        |	|ti        t?        |«      «      «       Œ6 Œ~ Œ• ‰ j`                  D ]›  }|t        j                  j                   v rE |	|ti        t?        |«      «      «       t        j                  jp                  js                  |«       Œd|t        j                  jt                  v sŒ� |	|ti        t?        |«      «      «       Œ� tw        t        j                  j                   jm                  «       «      D � �ci c]  \  } }|| “Œ
 }!} }t        j                  jp                  D �cg c]  }|!|   ‘Œ	 c}t        j                  _<        ‰ j                  D ]C  }|j                  «       D ].  }|j{                  ‰(|j                  «          jN                  «       Œ0 ŒE ‰ j|                  D ]-  }‰ j|                  |   j{                  ‰(|   jN                  «       Œ/ t        «       }"|"j�                  d«       ‰(jO                  «       D ]]  \  }}#|"jƒ                  «       5  |#jN                  D �$cg c]  }$|$j                  «       ‘Œ }%}$|"j�                  d|› d|%› d�«       ddd«       Œ_ |"j�                  d«       |"j…                  «       j‡                  «       }&tˆ        j7                  d«       tˆ        j7                  d|&«       yc c}w c c}} w c c}w c c}$w # 1 sw Y   ŒÙxY w)zi
        Create dependency edges between nodes, handling aliasing and
        mutation properly.
        c                  ó>   •— e Zd ZdZ	 	 d	 	 	 	 	 dd„Zdd„Zd	ˆ fd„Zy)
ú1Scheduler.compute_dependencies.<locals>.DedupListan  
            This data structure behaves like a list except it makes sure the
            elements remain unique.
            Normally one could use a OrderedSet/dict for this purpose however
            the list in question gets elements appended as it is being
            iterated over which means that we need to keep the list
            semantics.
            Nc                ó@   — |xs g | _         |xs
 t        «       | _        y r~   )rÀ  r   Ú
membership)rr   rÀ  ræ  s      rs   r:  z:Scheduler.compute_dependencies.<locals>.DedupList.__init__\  s   € ð
 #š[ b�”
Ø",Ò"<´
³�•ru   c                óŽ   — || j                   v ry | j                  j                  |«       | j                   j                  |«       y r~   )ræ  rÀ  rä   r¢  )rr   Ú	node_users     rs   rä   z8Scheduler.compute_dependencies.<locals>.DedupList.appendd  s5   € Ø §¡Ñ/ØØ—
‘
×!Ñ! )Ô,Ø—‘×#Ñ# IÕ.ru   c                óà   •— t        j                  | j                  |j                  «      }| j                  |j                  D �cg c]  }|| j                  vsŒ|‘Œ c}z   } ‰||«      S c c}w r~   )r   r©  ræ  rÀ  )rr   r  Únew_membershiprˆ  Ú	new_itemsÚ	DedupLists        €rs   Ú__add__z9Scheduler.compute_dependencies.<locals>.DedupList.__add__j  sc   ø€ Ü!+×!1Ñ!1°$·/±/À5×CSÑCSÓ!T�Ø ŸJ™JØ$Ÿ{™{ö*Ø¨a°t·±Ò.F’Aò*ñ �	ñ ! ¨NÓ;Ð;ùò*s   ÁA+ÁA+r�  )rÀ  zlist[_T] | Noneræ  zOrderedSet[_T] | Noner�   r  )rè  rh   r�   r  )r  úDedupList[_T]r�   rî  )r€   r�   r‚   r•   r:  rä   rí  )rì  s   €rs   rì  rä  R  s;   ø„ ñð *.Ø48ð=à&ð=ð 2ð=ð ó	=ó/ö<ru   rì  r   c                óN   •— | ‰j                   v r ‰‰j                   |    «      S | S r~   )r)  )rÍ  ry  rr   s    €€rs   ry  z.Scheduler.compute_dependencies.<locals>.rename—  s,   ø€ Ø�D×)Ñ)Ñ)Ù˜d×3Ñ3°AÑ6Ó7Ð7ØˆHru   Fc                óP   •— ‰ ‰| «         j                  t        |||«      «       y r~   )rä   r1  )Úused_by_namerü  rï  rô  Úname_to_usersry  s       €€rs   Úadd_userz0Scheduler.compute_dependencies.<locals>.add_userœ  s)   ø€ ð ™& Ó.Ñ/×6Ñ6Ü˜ K°Ó9õru   Nc                ó   — | j                   S r~   rt  r¯  s    rs   r8  z0Scheduler.compute_dependencies.<locals>.<lambda>¿  s
   € ÀAÇFÁF€ ru   rã  Tzscheduling %s)Úunbacked_onlyc                ó   — | j                   S r~   rt  r¯  s    rs   r8  z0Scheduler.compute_dependencies.<locals>.<lambda>Ò  s
   €  !§&¡&€ ru   z not in )r•  ©Úmutating_bufr   )rô  )r   zscheduling output %sz+scheduling output %s for unbacked symint %sr  ú'z': rê  r  zBUFFER USER LIST
z===== AFTER SCHEDULING =====
%s)rÍ  r,  r�   r,  )FF)
rñ  r,  rü  ró  rï  r}   rô  r}   r�   r  )Er	   rh   rW  r   rq  r<  râ  r²   r”   rí  r0   rD   rÎ   rî  ra   rÁ   rX  rÝ   r  ra  r&   Ú	TensorBoxrc  rè  Úget_unbacked_symbol_defsÚSymbolrT  rÝ  r
  rI  r  r:   rÕ   rQ  r‘  r�  r9   r•  rð  rÀ  rf   r;   Úadditional_buffer_depsÚadditional_star_depsrÖ   r×   rï  r{  r)  r�  r±  r•  r  rš   r!  rÇ  Úmutated_inputsr¢  rp  r’  Úmutated_input_idxsr  r  rX   rP  rñ  rò  rV  Úcompute_dependencies_log)*rr   r”   Úbuf1Ú	buf1_nameÚ	buf2_nameÚlist1Úlist2Úcombinedrä  ró  Úunbacked_symbol_to_origin_nodeÚvalÚfsr9  Úsym_sizeÚhas_non_input_unbacked_defsÚunbacked_symbol_defsÚunbacked_symbol_usesrR  rÞ   rà   Ú	node_modeÚalt_nameró  Úout_bufÚ
other_nameÚis_aliasÚadd_depr  rÖ  rå   r×   rØ   Ú	inp_namesÚlogbufrk  rf  rß  r,  rì  rò  ry  s*   `                                      @@@rs   rd   zScheduler.compute_dependenciesL  sB
  û€ ö	<œ¤™ô 	<ô@ @K×?VÑ?VØó@
ˆð —J‘Jò 	LˆDØ×(Ñ(Ó*ò L�Ø ŸM™M›O�	ô ˜tŸy™y×/Ñ/´·±Ô?Ü˜D×,Ñ,Ó.Ó/°!Ò3àØ!%×!1Ñ!1Ó!3ò L�IØ  MÑ1°iÀ=Ñ6Pà -¨iÑ 8˜Ø -¨iÑ 8˜Ø#(¨5¡=˜Ø#0ò >˜Cà -¨cÑ 2°eÑ ;Ø#0°Ñ#5¸Ò#>à5= ¨cÒ 2ñ>ð # mÑ3Ø3@ÀÑ3K˜ iÒ0à3@ÀÑ3K˜ iÒ0ñLñLð	Lö<	ð !&Ø!ð		àð		ð 6ð		ð ð			ð
 ð		ð ö		ð JLÐ&ô
 —7‘7×'Ñ'×.Ñ.Ó0ò 
	BˆCÜ˜#œuŸz™zÔ*Ø×*Ñ*ò >�BØ9=Ð2°2Ò6ñ>ä˜C¤§¡Õ.ð (+§|¡|£~ÖS !¼ÀAÄuÇzÁzÕ9RšAÐS�ÐSØ!ò B�AØŸn™nò B˜Ø=AÐ6°rÒ:ñBñBð
	Bð ',Ð#Ø—J‘Jò 	HˆDØ—9‘9Ð(Ð(Ð(ô $*Ø—	‘	×2Ñ2Ó4Ñ:Jô$Ð ð *ò H�Ü! !¤U§\¡\Ô2Ð2Ð2ð /3Ð+ØÐ:Ò:Ø8<¿¹»Ð2°1Ò5ñHð	Hð  —J‘Jó V	ˆDÜ�I‰I�o t§y¡yÔ1á*Ø—y‘yÐ,Ð,Ð,ä'-Ø—I‘I×2Ñ2ÀÐ2ÓFÙ(ô(Ð$ð
 .ò G�AØÐ >Ñ>ð Ø˜#˜XÐ&DÐ%EÐFóÐ>ð <¸AÑ>Ð>˜ÑKØ#'×#4Ñ#4°QÑ#7×#CÑ#CÓ#Eò G˜CØ ×-Ñ-¬g°c·l±l³nÓ.EÕFñGðGô �D×$Ñ$×+Ñ+Ó,°Ò1Ü ¤ d×&6Ñ&6×&=Ñ&=Ó!>Ó?Ð?�SÐ?Ü˜s¤IÔ.àŸH™H‘	à �	ð ×'Ñ'Ó)ó E�ä˜3×,Ñ,Ó.Ó/°1Ò4Ð4Ð4Ø #× 1Ñ 1Ó 3ó E�HÙ% hÓ/�Há˜X tÔ,Ø×%Ñ%¤g¨h¸YÔ&GÔHØ -¨hÑ 7× =Ñ =ò E˜ØŸ=™=›?¨d¯m©m«oÒ=Ø$ä)¨$¯)©)Ô5FÔGÐGÐGØ'+§y¡y×'<Ñ'<Ó'>ò E˜GØ)0×)9Ñ)9Ó);˜Já)/°
Ó);˜Jð (0°7×3FÑ3FÓ3HÐ'H˜HØ ×-Ñ-Ü 'Ø$.Ø14·±³Ø08¨Lô!"ôñ % Z°¸tÖDñ%EòEòEðEôB Ÿ7™7×9Ñ9¸$¿-¹-»/ÑJò S�Ù˜ $°Õ5ð ×!Ñ!¤'¨'°4·=±=³?ÈDÔ"QÕRð	Sô Ÿ7™7×7Ñ7¸¿¹»ÑHò 4�Ù˜ $°Õ6Ø×!Ñ!¤'¨'Ó"2Õ3ð4ð
 ×(Ñ(×.Ñ.ò F�Ü! $¬Õ0Ù˜TŸY™Y¨¨d×.>Ñ.>¸tÓ.DÕEðFð ×%Ñ% d×&;Ñ&;Ô<ð ×'Ñ'Ó)ò �Ø #× 1Ñ 1Ó 3ò �HØ>A¿l¹l»n�D×)Ñ)©&°Ó*:Ñ;Ø69·l±l³n�D×)Ñ)¨(Ñ3à×/Ñ/×3Ñ3°H¸hÓGð ×+Ñ+¨C¯L©L«NÒ;ñòðaV	ôr Ÿ™×0Ñ0Ó2ò 	>ˆHÜ�I‰IÐ,¨hÔ7Ù�Xœz¬'°(Ó*;Ó<Õ=ð	>ñ
 'Ü—w‘w×,Ñ,ò N�Ø×1Ñ1ÀÐ1ÓEò N�AØÐ >Ñ>ð Ø˜#˜XÐ&D×&IÑ&IÓ&KÐ%LÐMóÐ>ð ;¸1Ñ=Ð=�qÑ=Ø(,×(9Ñ(9¸!Ñ(<×(MÑ(MÓ(Oò N˜HÜŸI™IØ MØ (Ø !ôñ
 % X¬z¼'À(Ó:KÓ/LÕMñNñNðNð ×)Ñ)ò 	:ˆDØ”q—w‘w×+Ñ+Ñ+Ù˜œz¬'°$«-Ó8Ô9Ü—‘×&Ñ&×*Ñ*¨4Õ0ØœŸ™×*Ñ*Ò*á˜œz¬'°$«-Ó8Õ9ð	:ô ,5´Q·W±W×5IÑ5I×5NÑ5NÓ5PÓ+Q÷
Ù'˜E 4ˆD�%‰Kð
ˆ	ñ 
ô )*¯©×(>Ñ(>ö&
Ø $ˆI�d‹Oò&
Œ�‰Ô"ð
 —J‘Jò 	CˆDØ×'Ñ'Ó)ò C�Ø—‘˜m¨C¯L©L«NÑ;×AÑAÕBñCð	Cð ×/Ñ/ò 	SˆDØ×'Ñ'¨Ñ-×7Ñ7¸ÀdÑ8K×8QÑ8QÕRð	Sô  Ó!ˆØ�‰�cÔØ'×-Ñ-Ó/ò 	4‰JˆC�Ø—‘“ñ 4Ø/4¯{©{Ö;¨!˜Ÿ™�Ð;�Ð;Ø—‘  #  c¨%¨°Ð2Ô3÷4ð 4ð	4ð 	�‰�cÔØ× Ñ Ó"×)Ñ)Ó+ˆÜ ×&Ñ&Ð';Ô<Ü ×&Ñ&Ð'IÈ3ÕOùòK TùóX
ùò&
ùò" <÷4ð 4ús6   Æ5i4Çi4â2i9ãi?çj	çjç5j	êj	ê	j	c           
     ó  ‡ ‡— ddl m}m}m}m} t        t        j                  j                  j                  «       «      } |‰ j                  |«      }t        j                  j                  j                  s |‰ j                  ‰ j                  «       t        t        j                  j!                  «       «      } |‰ j                  ||«      \  }}	}	t#        t%        ‰ j                  «      «      D �	cg c]  }	g g f‘Œ c}	Š|D ]}  }
|
j&                  dk(  r|
j(                  dk(  rŒ"|
j*                  j-                  «       }‰|
j.                     d   j1                  |«       ‰|
j2                     d   j1                  |«       Œ ddlm}  |«        	 	 	 	 	 	 dˆ ˆfd„}g }t9        ‰ j                  «      D ]H  \  }}|j1                  |«       |j1                   |||t%        ‰ j                  «      dz
  k(  ¬«      «       ŒJ |‰ _
        y c c}	w )Nr   )rZ  Úcompute_memory_timelineÚFreeableInputBufferÚget_freeable_input_bufr   )Úregister_check_mem_opc                óX  •— ‰|    d   }‰|    d   }|||g}t        j                  t        t        j                  d«      ¬«      t        j
                  j                  j                  j                  g |d„ ¬«      }d‰j                  |    j                  «       › �|_        t        ‰|«      S )Nr   r   rÛ  r·  c                ó$   — | |d   |d   |d   dœfS )Nr   r   rÍ   )ÚaliveÚdeadÚis_final_stepr…   )Útensor_argsrµ  s     rs   r8  zWScheduler.insert_memory_check_nodes.<locals>.construct_mem_check_node.<locals>.<lambda>’  s*   € Øà!.¨qÑ!1Ø -¨aÑ 0Ø)6°qÑ)9ñðC€ ru   )rí  r  r!  Únontensor_argsÚunflatten_argsÚ
mem_check_)r0   ÚMemoryCheckKernelrD   r`  rÝ  ÚopsÚ_inductor_debugÚcheck_memory_stepÚdefaultrq  râ  rÉ  rR  )Ústep_idxr   Úexpected_newly_aliveÚexpected_newly_deadr"  r”   rr   Ústep_allocs_deallocss         €€rs   Úconstruct_mem_check_nodezEScheduler.insert_memory_check_nodes.<locals>.construct_mem_check_node…  s¨   ø€ ð $8¸Ñ#AÀ!Ñ#DÐ Ø"6°xÑ"@ÀÑ"CÐà2Ð4GÈÐWˆNä×'Ñ'Ü!¬¯©°eÓ)<Ô=Ü—y‘y×0Ñ0×BÑB×JÑJØØ-ñ ôˆDð %/¨t¯z©z¸(Ñ/C×/LÑ/LÓ/NÐ.OÐ"PˆDÔÜ,¨T°4Ó8Ð8ru   )r   )r*  r‘   r   r}   r�   rR  )r”  rZ  r  r  r  r   ra   rÁ   rX  r!  rq  r`  ra  r-   rY  r  r•  rL  rÎ   Ú
size_allocÚ	size_freer"  râ  Ú
start_steprä   Úend_stepÚ#torch._inductor.runtime.debug_utilsr  r’  )rr   rZ  r  r  r  rX  Úname_to_freeable_input_bufrš   Úbuf_info_listr=  Úbuf_inforÖ  r  r.  Ú	new_nodesr�  r”   r-  s   `                @rs   r¤  z#Scheduler.insert_memory_check_nodes[  sá  ù€ ÷	
ó 	
ô )3´1·7±7×3GÑ3G×3LÑ3LÓ3NÓ(Oˆá" 4§:¡:¨|Ó<ð 	#ô �‰×%Ñ%×=Ò=Ù=Ø—
‘
˜D×,Ñ,ôô *4´A·G±G×4LÑ4LÓ4NÓ)OˆÙ5Ø�J‰JØ&Øó
Ñˆ�q˜!ô $¤C¨¯
©
£OÓ4öC
ØˆR�ŠHòC
Ðð &ò 	HˆHà×"Ñ" aÒ'¨H×,>Ñ,>À!Ò,CØà—‘×/Ñ/Ó1ˆHà  ×!4Ñ!4Ñ5°aÑ8×?Ñ?ÀÔIØ  ×!2Ñ!2Ñ3°AÑ6×=Ñ=¸hÕGð	Hõ 	NáÔð	9Øð	9Ø*.ð	9à&ö	9ð2 ˆ	ä  §¡Ó,ò 	‰GˆAˆtØ×Ñ˜TÔ"Ø×ÑÙ(¨¸1ÄÀDÇJÁJÃÐRSÑ@SÑ;SÔUõð	ð ˆ�
ùòeC
s   Ã3Hc                ó|  ‡	— t         j                  syg }t        | j                  «      D �]Ð  }dd„Š	d}|j	                  «       D ]€  }t        ˆ	fd„|j                  D «       «      }|r\t        j                  d|j                  «       «       t        j                  j                  j                  |j                  «       «       Œd}Œ‚ |j                  «        xr | }|s|j                  |«       ŒÇt        j                  d|j                  «       «       t        j                  j                   j                  |j                  «       «       |j"                  j$                  D ]–  }|j&                  | j(                  v sŒ| j(                  |j&                     j                  }|D �cg c]0  }|j*                  j                  «       |j                  «       k7  sŒ/|‘Œ2 c}| j(                  |j&                     _        Œ˜ �ŒÓ t-        t        |«      «      | _        | j                  D ]  }|j/                  «        Œ yc c}w )	z0
        Remove any nodes without users
        Nc                ór   — | j                   xs* | j                  «       t        j                  j                  v S r~   )rô  râ  ra   rÁ   r­  )ró  s    rs   Úcan_eliminate_userz;Scheduler.dead_node_elimination.<locals>.can_eliminate_userµ  s&   € Ø—|‘|ÒT t§}¡}£¼!¿'¹'×:TÑ:TÐ'TÐTru   Fc              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   )r·   Úur:  s     €rs   r¹   z2Scheduler.dead_node_elimination.<locals>.<genexpr>º  s   øè ø€ Ò#M¸aÑ$6°q×$9Ñ#Mùó   ƒzremoved dead buffer: %sTzremoved dead operation: %s)ró  r1  r�   r}   )r-   Úuse_dcerÐ   rq  r<  rº   rß  rT  rÝ  râ  ra   rÁ   r  r¢  rñ  rä   r­  rÕ   rÖ   r×   r  r”   r¥   r¶  )
rr   Úupdated_nodesr”   Úactive_buffersrÞ   Úcan_eliminater  rß  r<  r:  s
            @rs   r|  zScheduler.dead_node_elimination¨  sÂ  ø€ ô �~Š~Øð
 ˆÜ˜TŸZ™ZÓ(ó 	ˆDóUð #ˆNØ×'Ñ'Ó)ò *�Ü #Ó#MÀ3Ç9Á9Ô#MÓ M�Ù Ü—I‘IÐ7¸¿¹»ÔHÜ—G‘G×+Ñ+×/Ñ/°·±³Õ?à%)‘Nð*ð !%× 5Ñ 5Ó 7Ð7ÒNÀÐ<NˆMá Ø×$Ñ$ TÕ*ô —	‘	Ð6¸¿¹»ÔHÜ—‘×*Ñ*×.Ñ.¨t¯}©}«Ô?Ø ×,Ñ,×2Ñ2ò �DØ—y‘y D×$4Ñ$4Ò4Ø $× 0Ñ 0°·±Ñ ;× AÑ A˜à',ö=Ø"#°·±·±Ó0AÀTÇ]Á]Ã_Ó0TšAò=˜×(Ñ(¨¯©Ñ3Õ9òð-	ô8 œ( =Ó1Ó2ˆŒ
ð —J‘Jò 	#ˆDØ× Ñ Õ"ñ	#ùò=s   Æ%0H9ÇH9c                ó
   — |duS )z:Check if store mode requires cross-thread synchronization.Nr…   )rr   r•  s     rs   Úmode_requires_synchronizationz'Scheduler.mode_requires_synchronizationÕ  s   € à˜4ÐÐru   c                óº   ‡‡‡‡— t        t           «       Št        «       Šg Šdˆˆˆˆfd„Š|D ]  }|j                  «       D ]  }|‰|<   Œ	 Œ |D ]
  } ‰|«       Œ ‰S )z?
        Ensure nodes is in topologically sorted order
        c                óÖ   •— | ‰vrd‰j                  | «       t        | j                  d„ ¬«      D ]&  }|j                  ‰vrŒ ‰‰|j                     «       Œ( ‰j	                  | «       y y )Nc                ó   — | j                   S r~   rt  )Úds    rs   r8  zDScheduler.topological_sort_schedule.<locals>.visit.<locals>.<lambda>æ  s
   € ÀaÇfÁf€ ru   rã  )r¢  rè  r3  r×   rä   )rÍ  rà   rI  r³  rD  Úvisits     €€€€rs   rH  z2Scheduler.topological_sort_schedule.<locals>.visitã  se   ø€ Ø˜‰}Ø—‘˜”Ü! !×"6Ñ"6Ñ<LÔMò 2�Cà—x‘x |Ñ3Ø Ù˜, s§x¡xÑ0Õ1ð	2ð
 —‘˜aÕ ð ru   )rÍ  rf   r�   r  )r   rf   rx  rÇ  )rr   rq  r”   r×   rI  r³  rD  rH  s       @@@@rs   r{  z#Scheduler.topological_sort_scheduleÙ  sy   û€ ô Ô+Ñ,Ó.ˆÜ59³VˆØ*,ˆ÷	!ð 	!ð ò 	*ˆDØ×-Ñ-Ó/ò *�Ø%)�˜TÒ"ñ*ð	*ð ò 	ˆDÙ�$�Kð	àˆru   c                ó˜  — | j                   D �cg c])  }t        |j                  t        j                  «      sŒ(|‘Œ+ }}t        dt        |«      «      D ]o  }t        t        ||   j                  «       «      «      }t        t        ||dz
     j                  «       «      «      }||   j                  t        ||d¬«      «       Œq y c c}w )Nr   Tr÷  )rq  r²   r”   r0   ÚConditionalrL  rÎ   r‘  r�  rÇ  r  r;   )rr   rÍ  Úconditional_nodesr�  rø  Úprev_bufs         rs   r“  z'Scheduler._enforce_conditional_orderingô  s´   € à—z‘zö
Ø¤Z°·±¼¿¹Õ%GŠAð
Ðð 
ô �qœ#Ð/Ó0Ó1ò 	ˆAÜ¤Ð%6°qÑ%9×%JÑ%JÓ%LÓ MÓNˆLÜœDÐ!2°1°q±5Ñ!9×!JÑ!JÓ!LÓMÓNˆHØ˜aÑ ×-Ñ-Ü˜¨|ÀTÔJõñ	ùò
s
   �)C¹Cc                ó<  ‡ — t        «       }t        |t        t        t        t
        t        f«      r-|j                  D ]  }|j                  |j                  «       Œ nt        dt        |«      › d�«      ‚ˆ fd„|D «       }t        t        ˆ fd„|D «       «      «      S )Nz+get_unmet_dep_nodes is not implemented for ú.c              3  óX   •K  — | ]!  }‰j                   |   j                  «       –— Œ# y ­wr~   )r  rä  r©  s     €rs   r¹   z1Scheduler._get_unmet_dep_nodes.<locals>.<genexpr>  s%   øè ø€ ÒXÀc˜×)Ñ)¨#Ñ.×?Ñ?×AÑXùs   ƒ'*c              3  ó<   •K  — | ]  }‰j                   |   –— Œ y ­wr~   ©r¹  )r·   rÍ  rr   s     €rs   r¹   z1Scheduler._get_unmet_dep_nodes.<locals>.<genexpr>  s   øè ø€ ÒQ¸a˜t×6Ñ6°qÕ9ÑQùó   ƒ)r   r²   r³   rR  r  rÚ   r´  r3  r¢  r×   ÚRuntimeErrorr«   r¥   )rr   r¸  Ú
unmet_depsrà   Úunmet_dep_opss   `    rs   Ú_get_unmet_dep_nodeszScheduler._get_unmet_dep_nodesÿ  s’   ø€ Ü&0£lˆ
ÜØäÜ)Ü&Ü"Ü$ðô	
ð ×/Ñ/ò )�Ø—‘˜sŸx™xÕ(ñ)ô Ø=¼dÀ5»k¸]È!ÐLóð ó YÈZÔXˆÜ”JÓQÀ=ÔQÓQÓRÐRru   c                óz  — g }t         j                  | j                  d«      }i }| j                  D ]P  }| j                  |«      }t	        |«      ||<   |D ]*  }|j                  |g «      }|j                  |«       |||<   Œ, ŒR |j                  «       D ��	cg c]  \  }}	|	dk(  sŒ|‘Œ }
}}	|
rx|j                  |
«       |
D ]7  }|j                  |g «      D ]  }||xx   dz  cc<   Œ |j                  |«       Œ9 |j                  «       D ��	cg c]  \  }}	|	dk(  sŒ|‘Œ }
}}	|
rŒx|rJ d«       ‚|S c c}	}w c c}	}w )zU
        Sort nodes by their topological order, return a list of node lists.
        r   r   zTopological sort failed!)	rx  Úfromkeysrq  rV  rÎ   r±  rä   rÀ  r¡  )rr   rÄ  rq  Úchildrenr”   r¥  rà   ÚcrÍ  rf  Úzero_deg_nodesró  s               rs   rt  z!Scheduler._topological_sort_nodes  sF  € ð ˆÜ—‘˜dŸj™j¨!Ó,ˆØ#%ˆØ—J‘Jò 	"ˆDØ×,Ñ,¨TÓ2ˆDÜ˜d›)ˆE�$‰KØò "�Ø—L‘L  bÓ)�Ø—‘˜”Ø !�˜’ñ"ð	"ð ).¯©«×@¡  1¸¸a»š!Ð@ˆÑ@ÙØ�L‰L˜Ô(Ø#ò �Ø$ŸL™L¨¨BÓ/ò %�DØ˜$“K 1Ñ$”Kð%à—	‘	˜!•ðð -2¯K©K«M×D¡D A q¸QÀ!»VšaÐDˆNÑDò ñ Ð4Ð4Ó4ˆyØˆùó Aùó Es   ÂD1Â%D1ÄD7ÄD7c                ój  — i }| j                   D ]w  }t        «       }|j                  D ]B  }| j                  |j                     j                  «       }|j                  |«       |||   z  }ŒD |||j                  «       <   ||_        Œy t        | j                   «      D ]  \  }}||_
        ||_        Œ y)z.
        Populate each node.ancestors
        N)rq  r   r3  r  r×   rä  r¢  râ  r  r’  r%  r&  )rr   Úname_to_ancestorsr”   r  rà   Údep_node_namerÄ  s          rs   r}  zScheduler.compute_ancestors.  s¸   € ð
 9;ÐØ—J‘Jò 	'ˆDÜ)3«ˆIØ×.Ñ.ò >�Ø $× 0Ñ 0°·±Ñ :× KÑ KÓ M�Ø—‘˜mÔ,ØÐ.¨}Ñ=Ñ=‘	ð>ð 2;Ð˜dŸm™m›oÑ.Ø&ˆD�Nð	'ô % T§Z¡ZÓ0ò 	#‰KˆE�4Ø"ˆDŒNØ"ˆD�Nñ	#ru   c                ó  — i }i }| j                   D ]å  }|j                  sd}d}nž|j                  D �cg c]/  }|| j                  |j                     j	                  «          dz   ‘Œ1 }}|j                  D �cg c]/  }|| j                  |j                     j	                  «          dz   ‘Œ1 }}t        |«      }t        |«      }|||j                  «       <   |||j                  «       <   ||_        ||_	        Œç yc c}w c c}w )zí
        Populate each node's min/max_input_distance with the depth from graph
        inputs, measured as dependency hops before fusion. Nodes whose
        dependencies are all satisfied by graph inputs/constants have depth 0.
        r   r   N)
rq  r3  r  r×   rä  rZ  rY  râ  r#  r$  )	rr   Úname_to_min_distanceÚname_to_max_distancer”   Úmin_distÚmax_distrà   Údep_min_distsÚdep_max_distss	            rs   r~  z!Scheduler.compute_input_distancesA  s   € ð 02ÐØ/1ÐØ—J‘Jò 	/ˆDØ×*Ò*Ø�Ø‘ð
  $×6Ñ6ö!ð ð )¨×)9Ñ)9¸#¿(¹(Ñ)C×)TÑ)TÓ)VÑWØóð!�ð !ð  $×6Ñ6ö!ð ð )¨×)9Ñ)9¸#¿(¹(Ñ)C×)TÑ)TÓ)VÑWØóð!�ð !ô
 ˜}Ó-�Ü˜}Ó-�Ø4<Ð  §¡£Ñ1Ø4<Ð  §¡£Ñ1Ø&.ˆDÔ#Ø&.ˆDÕ#ñ)	/ùò
!ùò
!s   ³4C:Á74C?c                óH  — t         j                  sy | j                  D ]‚  }t        |t        t
        f«      r#|j                  «       st         j                  dk7  rŒ=|j                  «       D ]3  }t        |t        «      r|j                  «       rŒ$|j                  «        Œ5 Œ„ y )NÚhalide)r-   r%  rq  r²   r³   rÚ   r[   Úcpu_backendr»   rç  r\  )rr   r”   r¸  s      rs   r\  zScheduler.merge_loops_  s†   € Ü×0Ò0Øà—J‘Jò 	$ˆDô ˜d¤]Ô4FÐ$GÔHØ—K‘K”M¤f×&8Ñ&8¸HÒ&DàØŸ™Ó)ò $�ä! %¬Ô7¸5×;LÑ;LÔ;NØà×!Ñ!Õ#ñ$ñ	$ru   c                óÚ  — t        ddd¬«      5  t        d«      D ]…  }t        |«      }t        j	                  d|dz   |«       | j                  |d¬«      }t        |«      }t        j	                  d	|dz   ||«       ||k(  s|dk(  sŒlt        j	                  d
|dz   «        n t        j                  st        j                  r| j                  |d¬«      }|cddd«       S # 1 sw Y   yxY w)zB
        Combine eligible nodes into FusedSchedulerNodes.
        zScheduler.fused_nodesTrU  rÈ  z/===== attempting fusion (%d/10): %d nodes =====r   F)Úis_reorder_roundz=completed fusion round (%d/10): fused %d nodes into %d nodes
z+===== fusion complete (%d iterations) =====N)	r   rL  rÎ   rÜ  rÝ  Úfuse_nodes_oncer-   r%  Úloop_index_inversion_in_fusion)rr   rq  r�  Úold_lenÚnew_lens        rs   rŸ  zScheduler.fuse_nodesz  sø   € ô Ø#¸4ÐQUô
ñ 	ô ˜2“Yò �Ü˜e›*�Ü× Ñ ØEØ˜‘EØôð
 ×,Ñ,¨UÀUÐ,ÓK�Ü˜e›*�Ü× Ñ ØTØ˜‘EØØô	ð ˜gÒ%¨°A«Ü×$Ñ$ØEÀqÈ1Áuôñ ð'ô, ×1Ò1Ü×8Ò8à×,Ñ,¨UÀTÐ,ÓJ�Ø÷;	÷ 	ò 	ús   �A7C!ÂAC!Ã!C*c                óœ   — g }| j                   D ]4  }|j                  t        |t        «      r|j	                  «       n|g«       Œ6 || _         y)zA
        Unpack GroupedSchedulerNode into regular nodes.
        N)rq  r¤  r²   r´  r   )rr   r7  r”   s      rs   rœ  zScheduler.process_grouped_nodes�  sJ   € ð .0ˆ	Ø—J‘Jò 	ˆDØ×ÑÜ!+¨DÔ2FÔ!G�—‘”ÈdÈVõð	ð ˆ�
ru   c                óâ   — t        |«      dkD  sJ ‚|d   j                  «       }|| _        | j                  |«      }t	        ddd¬«      5  |j                  |«      cddd«       S # 1 sw Y   yxY w)úƒ
        Benchmark fused list of nodes and return the execution time
        in milliseconds on randomly generated inputs.
        r   Úbenchmark_fused_nodesTÚcompile_time_autotune_time_us)rV  Údynamo_compile_column_usN)rÎ   rª   rÉ  r#  r   rr  )rr   rq  rÝ  r  s       rs   rr  zScheduler.benchmark_fused_nodes¨  st   € ô �5‹z˜AŠ~Ðˆ~Ø�q‘×$Ñ$Ó&ˆØ$ˆÔØ×"Ñ" 6Ó*ˆÜØ#Ø"&Ø%Dô
ñ 	8ð
 ×0Ñ0°Ó7÷	8÷ 	8ò 	8ús   Á
A%Á%A.Nc                óâ   — t        |«      dkD  sJ ‚|d   j                  «       }|| _        | j                  |«      }t	        d«      5  |j                  |||¬«      cddd«       S # 1 sw Y   yxY w)úD
        Generate a kernel given a list of pre-fused nodes.
        r   Úgenerate_kernel_code_from_nodes©Úhint_overrideN)rÎ   rª   rÉ  r#  r   rw  )rr   rq  Úbenchmark_kernelry  rÝ  r  s         rs   rw  z)Scheduler.generate_kernel_code_from_nodesº  sw   € ô �5‹z˜AŠ~Ðˆ~Ø�q‘×$Ñ$Ó&ˆØ$ˆÔØ×"Ñ" 6Ó*ˆÜÐ;Ó<ñ 	Ø×:Ñ:ØÐ'°}ð ;ó ÷	÷ 	ò 	ús   ÁA%Á%A.c                ó–   — || _         | j                  |«      }t        d«      5  |j                  |«      cddd«       S # 1 sw Y   yxY w)ú�
        Benchmark a compiled module and return the execution time
        in milliseconds on randomly generated inputs.
        Úbenchmark_codegened_moduleN)rÉ  r#  r   r}  )rr   ÚmodulerÝ  r  s       rs   r}  z$Scheduler.benchmark_codegened_moduleÌ  sH   € ð %ˆÔØ×"Ñ" 6Ó*ˆÜÐ6Ó7ñ 	>Ø×5Ñ5°fÓ=÷	>÷ 	>ò 	>ús	   ¤?¿Ac                ó  — t         j                  j                  }|syt        j	                  d||«       |j
                  D ]È  }|j                  «       }t        j                  j                  j                  |«      sŒ=|j                  }||   }t        |t        j                  «      r'|j                  |j                   «       |j                  }t        |t        j"                  «      sŒª||k7  sŒ°t        j%                  d|||«        y y)z 
        Check if selecting a Triton template would cause layout conflicts.
        Returns True if there's a conflict and we should fall back to ATen.
        FzNode %s has constraints %szOLayout conflict detected for %s: template expects %s but layout is frozen to %sT)ra   rÁ   Úbuffer_layout_constraintsrT  rÝ  r³  râ  r`  ra  rŽ  Úshould_use_layout_constraintsrí  r²   r0   ÚFlexibleLayoutÚ freeze_layout_with_exact_stridesrÿ  ÚFixedLayoutrU  )rr   Ú
multi_nodeÚconstraintsÚinpÚinp_namerí  Úexpected_layouts          rs   Ú!_has_layout_conflict_for_templatez+Scheduler._has_layout_conflict_for_templateØ  sá   € ô —g‘g×7Ñ7ˆÙØä�	‰	Ð.°
¸KÔHØ×$Ñ$ò 	ˆCà—|‘|“~ˆHä—?‘?×3Ñ3×QÑQÐRUÔVØð —Z‘ZˆFØ)¨(Ñ3ˆOÜ˜&¤"×"3Ñ"3Ô4ð ×4Ñ4°_×5KÑ5KÔLàŸ™�ä˜&¤"§.¡.Õ1°oÈÓ6Oä—‘ØeØØ#Øô	ñ ð3	ð6 ru   c           
     ó&  ‡— t        | j                  «      D �]à  \  }}t        |t        «      sŒt        |j                  t
        j                  «      sŒ=|j                  }t        j                  j                  s%| j                  |«      s|j                  «       \  }}n„|j                  D �cg c]2  }t        |t        j                  j                  j                   «      r|‘Œ4 }}|sJ d«       ‚t#        |«      dkD  r!|j%                  «       Št'        |ˆfd„¬«      }n|d   }t        |t        j                  j
                  j(                  «      rÎt        j*                  r¡i }||d<   t        j*                  D ]k  }	|j%                  |	¬«      Š‰j-                  «       D �
�ci c]  \  }
}t        |
t(        «      r|
|“Œ }}
}t'        |j-                  «       d„ ¬«      d   }|||	<   Œm |j                  j/                  |«       n|j                  j1                  |«       �Œt
        j2                  j5                  |j6                  «      5  |j9                  «       }ddd«       j:                  }t        |t
        j<                  «      sJ ‚|j:                  }t        |t
        j>                  «      sJ ‚|j@                  rtC        ||j@                  «       |jD                  |_"        | jG                  ||||«       �Œã yc c}w c c}}
w # 1 sw Y   Œ¯xY w)	a€  
        Finalize a backing choice for MultiTemplateBuffers which did not already have a
        choice finalized through fusion. In the case of an extern choice, this will result
        in replacing the SchedulerNode.

        If a MultiTemplateBuffer did not have any fusion opportunities, finalizing a choice
        will force completion of compilation and benchmarking.
        z&No extern kernel detected for fallbackr   c                ó   •— ‰|    S r~   r…   )rZ  Útimingss    €rs   r8  z;Scheduler.finalize_multi_template_buffers.<locals>.<lambda>"  s   ø€ ÈWÐUVÉZ€ ru   rã  r   Nrx  c                ó   — | d   S rH  r…   r¯  s    rs   r8  z;Scheduler.finalize_multi_template_buffers.<locals>.<lambda>7  s   € ÈqÐQRÉt€ ru   )$r’  rq  r²   r³   r”   r0   ÚMultiTemplateBufferr-   r¢  Ú%force_extern_kernel_in_multi_templaterŠ  Úget_min_choiceÚchoicesr`  ra  rŽ  ÚExternKernelCallerrÎ   Úchoice_timingsrZ  r"   Úmulti_kernel_hintsrÀ  Úfinalize_as_triton_callersÚfinalize_as_triton_callerrl  Úcurrent_originsr$  Úoutput_noder÷   Ú
StorageBoxÚOperationBufferÚorigin_noder?   rí  Ú_replace_node)rr   r�  r”   r…  Úmin_node_unfusedr=  rZ  Úextern_choicesÚcallersr™  r�  rf  Útriton_timingsÚchoiceÚout_tensorboxÚout_storageÚ
out_bufferr�  s                    @rs   r‹  z)Scheduler.finalize_multi_template_buffers  s¶  ø€ ô ! §¡Ó,ó ?	D‰GˆAˆtÜ˜$¤Õ.´:Ø—	‘	œ2×1Ñ1õ4ð "ŸY™Y�
ä×+Ñ+×QÒQØ ×BÑBÀ:ÔNð +5×*CÑ*CÓ*EÑ'Ð$¡að ",×!3Ñ!3ö&àÜ%ØÜ!ŸO™O×<Ñ<×OÑOôò ð&�Nð &ñ *ÐSÐ+SÓS˜>Ü˜>Ó*¨QÒ.Ø",×";Ñ";Ó"=˜Ü+.¨~ÓCWÔ+XÑ(à+9¸!Ñ+<Ð(äØ$Ü—O‘O×&Ñ&×?Ñ?ôô
 ×0Ò0ØNP˜Ø(8˜ ™ô %+×$=Ñ$=ò 3˜DØ&0×&?Ñ&?ÈdÐ&?Ó&S˜Gð -4¯M©M«O÷.á$( A qÜ#-¨aÔ1IÔ#Jð !" 1¡ð.˜Nñ .ô
 &)¨×)=Ñ)=Ó)?Á^Ô%TÐUVÑ%W˜FØ,2˜G DšMð3ð Ÿ	™	×<Ñ<¸WÕEàŸ	™	×;Ñ;Ð<LÔMÙä—Y‘Y×.Ñ.¨z×/AÑ/AÓBñ CØ$4×$@Ñ$@Ó$B�M÷Cà+×0Ñ0�Ü! +¬r¯}©}Ô=Ð=Ð=Ø(×-Ñ-�
Ü! *¬b×.@Ñ.@ÔAÐAÐAà×)Ò)Ü& }°j×6LÑ6LÔMà$.×$5Ñ$5�
Ô!Ø×"Ñ" :¨z¸1¸dÖCñ?	Dùò&ùó6.÷Cð Cús   Â-7K<Æ L
ÉLÌL	c                óŒ  ‡— t        ||«       | j                  |«      }|| j                  |<   || j                  |j	                  «       <   || j
                  |j	                  «       <   i Št        j                  |j                  j                  |j                  «      D ]:  }| j                  j                  |j                  d «      x}sŒ,|j                  ‰|<   Œ< dˆfd„} ||j                  «      |_
         ||j                  j                  «      |j                  _	        t        |j                  «       |j                  «       «      D ]3  \  }	}
|	| j                   |
j	                  «       <   |
j"                  |	_        Œ5 |j$                  |_        |j&                  |_        |j(                  |_        |j*                  |_        y )Nc                ó,   •— t        ˆfd„| D «       «      S )Nc              3  ó@   •K  — | ]  }|j                  ‰«      –— Œ y ­wr~   )ry  )r·   rà   r)  s     €rs   r¹   z?Scheduler._replace_node.<locals>.rename_deps.<locals>.<genexpr>a  s   øè ø€ ÒK¸s˜cŸj™jÐ)9×:ÑKùrø  r   )r¥  r)  s    €rs   Úrename_depsz,Scheduler._replace_node.<locals>.rename_deps`  s   ø€ ÜÓKÀdÔKÓKÐKru   )r¥  r2  r�   r2  )rÒ  rr  rq  rI  râ  r¹  rš  r›  rÕ   rÖ   r3  r�  r±  r×   ry  r<  r  rß  r%  r&  r  r"  )rr   r¥  r…  r�  r”   Únew_scheduler_noderà   r3  r©  Únew_outÚold_outr)  s              @rs   r�  zScheduler._replace_nodeL  s�  ø€ ô 	" *¨jÔ9Ø!×7Ñ7¸
ÓCÐà*ˆ�
‰
�1‰Ø-?ˆ×Ñ˜$Ÿ-™-›/Ñ*Ø3Eˆ×Ñ §¡£Ñ0ð ÐÜ—?‘? 4×#3Ñ#3×#9Ñ#9¸4×;RÑ;RÓSò 	7ˆCØ ×3Ñ3×7Ñ7¸¿¹À$ÓGÐGˆyÑGØ.1¯h©hÐ  Ò+ð	7õ	Lñ 1<Ø×1Ñ1ó1
ÐÔ-ñ 0;Ø×*Ñ*×0Ñ0ó0
Ð×&Ñ&Ô,ô !$Ø×*Ñ*Ó,¨d×.>Ñ.>Ó.@ó!
ò 	*ÑˆG�Wð 4;ˆD×Ñ˜W×-Ñ-Ó/Ñ0Ø#ŸM™MˆG�Mð		*ð (,§~¡~ÐÔ$Ø'+§~¡~ÐÔ$Ø'+§~¡~ÐÔ$Ø(,¯©ÐÕ%ru   c                ó&   — t        d„ |D «       «      S )Nc              3  óö   K  — | ]q  }t        |j                  d «      xrU |j                  duxrE t        |j                  j                  d«      xr# |j                  j                  j                  dk(  –— Œs y­w)r÷   Nr  r–  )r  r”   r÷   r  rÌ  s     rs   r¹   z,Scheduler._any_atomic_add.<locals>.<genexpr>v  so   è ø€ ò 
ð
 ô	 �A—F‘F˜FÓ#ò 9Ø—‘˜dÐ"ò9ä˜Ÿ™Ÿ™ ^Ó4ò9ð —‘—‘×(Ñ(¨LÑ8ó9ñ
ùs   ‚A7A9©r  )rr   Ú	node_lists     rs   Ú_any_atomic_addzScheduler._any_atomic_addu  s   € Üñ 
ð
 ô
ó 
ð 	
ru   c                ó"  — | j                  |d|¬«      }t        j                  |«      }t        j                  j
                  j                  «       }|j                  «       sd }||fS |j                  d|¬«      }t        |t        «      sJ ‚||fS )NT)rz  ry  Útriton_)Úkernel_nameÚsource_code)rw  r!   Úloadr`  ra  Úasync_compileÚAsyncCompileÚuse_process_poolr©   r²   r    )rr   rq  ry  Úsrc_codeÚmodr·  Úfuts          rs   Úcompile_kernelzScheduler.compile_kernel~  s˜   € ð ×7Ñ7Ø D¸ð 8ó 
ˆô ×Ñ˜xÓ(ˆÜŸ™×5Ñ5×BÑBÓDˆØ×-Ñ-Ô/ØˆCð
 �SˆzÐð  ×&Ñ&°9È(Ð&ÓSˆCÜ˜c¤<Ô0Ð0Ð0à�SˆzÐru   c                ó”  ‡ ‡‡‡‡‡‡ ‡!‡"‡#‡$‡%‡&‡'‡(‡)‡*‡+‡,‡-‡.‡/‡0— t        d„ ‰‰fD «       «      }t        ‰j                  «       t        j                  «      xr t        ‰d¬«      }|r%t        j                  st        j                  d«      S t        j                  s|st        j                  d«      S ‰j                  «       r(t        ‰j                  «       t        j                  «      r ‰j                  «       s‰j                  «       rt        j                  d«      S ‰j                  «       }|d   j                  «       Š!‰!sJ ‚‰!j                  dk(  r(t        j                   dk7  rt        j                  d«      S ‰j                  «       }t#        t%        j&                  ||«      «      Š/‰ j)                  ‰/«      }|r|st        j                  d«      S ddlmŠ t/        ‰‰«      Š0‰/d   j                  «       Š!‰!€J ‚dˆˆfd
„Š)|�rSt        d„ ‰‰fD «       «      �r>‰j                  «       d	uŠ"‰"r‰j                  «       n‰j                  «       Š.t        ‰.t        j0                  «      sJ ‚‰ j3                  ‰.«      rt        j                  d«      S i Š(|�sWg Š&t        j4                  D �]A  }‰.j7                  |«      Š t9        ‰ j;                  «       d„ ¬«      D ]~  \  }	}
t        |	t<        j>                  j@                  jB                  «      sŒ5‰.jE                  |	«      5  ‰&jG                  |	g‰ jI                  ‰/|	jJ                  ¬«      ¢­«       d	d	d	«       Œ€ tM        d«      }d	}i }‰&D ]V  \  }	}}	 |�|jO                  «        ‰.jE                  |	«      5  ‰ j]                  |‰!«      \  }}|||	<   ||k  r|}|	}d	d	d	«       ŒX |‰.j^                  |<   t        |t`        «      sJ ‚|‰(|<   �ŒD t        jb                  Šte        d„ ‰.jf                  D «       «      }ti        «       xr ‰ xr |t        jj                  k  Š'tM        d«      tM        d«      cŠ+Š,d	Š*‰'sR‰.j7                  «       Š ‰.jm                  «       \  Š*Š+t9        ‰ j;                  «       to        jp                  d«      ¬«      }n‰.jf                  D �cg c]  }|df‘Œ }}ddl9m:Š dˆ"ˆ.fd„}	 	 	 	 dˆˆ"ˆ.ˆ/ˆ fd„}|�r/‰"st        j                  d«      S g t        j4                  ¢d	‘D ]¶  }‰.j7                  |«      Š d	}t9        ‰ j;                  «       to        jp                  d«      ¬«      D ]R  \  }	}
 ||	«      sŒtw        jx                  t<        j>                  j@                  jB                  |	«      } ||«      sŒP|} n |€t        j                  d«      c S |‰(|<   Œ¸ t        j4                  r‰.j{                  ‰(«       n‰.j}                  ‰(d	   «       t        j                  d«      S ‰r(‰"r‰ j                  |«      n‰ j                  |«      \  Š,}n4‰"st        j                  d«      S ‰j�                  «       Š,tƒ        ‰‰‰,«      Š-g Š&d}|D ]Ž  \  }	} ||	«      sŒtw        jx                  t`        |	«      }	‰r
|‰+‰,z   k\  r n\|dz  }|t        jj                  kD  r nB‰.jE                  |	«      5  	 ‰&jG                  |	g‰ jI                  ‰/«      ¢­«       	 d	d	d	«       Œ� t…        ‰&«      dk(  rt        j                  d«      S dˆˆ ˆ!ˆ"ˆ&ˆ'ˆ(ˆ)ˆ*ˆ+ˆ,ˆ-ˆ.ˆ fd„}t        j‡                  |‰&d   d   «      S ‰ jI                  |«      Š#‰ jI                  |«      Š%‰ jI                  ‰/«      Š$dˆˆ!ˆ#ˆ$ˆ%ˆ)ˆ ˆ0fd„}t        j‡                  |‰$d   ¬«      S # 1 sw Y   �ŒäxY w# tP        $ rI}tR        jU                  tV        jX                  «      rtR        j[                  d‰"sdnd|«       Y d	}~�Œ¢d	}~ww xY w# 1 sw Y   �Œ´xY wc c}w # ‰$ r Y d	d	d	«       �ŒÁw xY w# 1 sw Y   �ŒÏxY w)ú‡
        If config.benchmark_fusion is False, always return True.
        Otherwise, return True if fusion can brings speedup.
        c              3  ó�   K  — | ]>  }|j                  «       xr( t        |j                  «       t        j                  «      –— Œ@ y ­wr~   )rç  r²   r‡  r0   r�  rÌ  s     rs   r¹   z.Scheduler.speedup_by_fusion.<locals>.<genexpr>–  sE   è ø€ ò  
ð ð �M‰M‹Oò JÜ˜1×.Ñ.Ó0´"×2HÑ2HÓIóJñ 
ùs   ‚AAFr  Tr   rÛ  r©   ©ÚCompilationErrorNc           
     ót  •— t         j                  t        j                  «      r”| ||z   k  rFt         j	                  d‰j                  «       ‰j                  «       t        ||z   | z  d›«      «       y t         j	                  d‰j                  «       ‰j                  «       t        | ||z   z  d›«      «       y y )Nz9can fuse (benchmark): fusing %s with %s cause %sx speedupú.3fz=cannot fuse (benchmark): fusing %s with %s cause %sx slowdown)rÜ  rÓ  rÔ  ÚDEBUGrÝ  rÇ  rJ   rL   )Úms_fusedrì  rí  rˆ   r‰   s      €€rs   Ú
log_fusionz/Scheduler.speedup_by_fusion.<locals>.log_fusionÈ  s¦   ø€ Ü×&Ñ&¤w§}¡}Ô5Ø˜c C™iÒ'Ü×$Ñ$ØSØ×.Ñ.Ó0Ø×.Ñ.Ó0Ü" s¨S¡y°HÑ&<¸SÐ%AÓCõ	ô ×$Ñ$ØWØ×.Ñ.Ó0Ø×.Ñ.Ó0Ü  H°°c±	Ñ$:¸3Ð#?ÓAõ	ð 6ru   c              3  ó@   K  — | ]  }|j                  «       d u–— Œ y ­wr~   rŠ  rÌ  s     rs   r¹   z.Scheduler.speedup_by_fusion.<locals>.<genexpr>Ù  s#   è ø€ ò %
Ø23ˆA×ÑÓ!¨Ô-ñ%
ùrš  c                ó   — | d   S rH  r…   r¯  s    rs   r8  z-Scheduler.speedup_by_fusion.<locals>.<lambda>î  s   € ÐRSÐTUÑRV€ ru   rã  rx  ÚinfúException in compiling %s: %sr”  r–  c              3  ó<   K  — | ]  }t        |t        «      –— Œ y ­wr~   )r²   r"   )r·   rZ  s     rs   r¹   z.Scheduler.speedup_by_fusion.<locals>.<genexpr>  s   è ø€ ò %Ø<=”
˜1Ô6×7ñ%ùrÃ  r   )Ú	CantSplitc                ó¼   •— t        | t        j                  j                  j                  «      sy‰ xr' t        | d«      xr | j                  ‰j                  k7   S )NFÚallowed_prologue_inps)r²   r`  ra  rŽ  ÚTritonTemplateCallerr  rÏ  )r¢  r  r…  s    €€rs   Úchoice_supports_fusionz;Scheduler.speedup_by_fusion.<locals>.choice_supports_fusion5  sb   ø€ Ü!ØœEŸO™O×<Ñ<×QÑQôð !ð (Ð'ò YÜ Ð(?Ó@òYà×4Ñ4¸
×8XÑ8XÑXðð ru   c                óÂ  •— ‰j                  | «      5  	 ‰j                  ‰| j                  ¬«      \  }}|�|j                  «        n|j                  j                  «        d d d «       y# ‰$ r Y d d d «       yt        $ rP}t        j                  t        j                  «      rt        j                  d‰sdnd|«       Y d }~d d d «       yd }~ww xY w# 1 sw Y   yxY w)Nrx  FrË  r”  r–  T)Úswap_as_triton_callerr½  ry  r³  r³  Ú
precompilerS  rÜ  rÓ  rÔ  rÅ  rÝ  )	r¢  ro   Ú	mod_fusedr&  rÍ  r  r…  Únode_list_fusedrr   s	       €€€€€rs   Úcompile_without_benchmarkingzAScheduler.speedup_by_fusion.<locals>.compile_without_benchmarkingE  sà   ø€ ð  ×5Ñ5°fÓ=ñ %ð%Ø,0×,?Ñ,?Ø+¸6×;OÑ;Oð -@ó -Ñ)˜ 	ð "Ð-Ø"ŸM™M�Oà%×-Ñ-×8Ñ8Ô:÷%ð& øð %ò %Ø$÷%ð %ô %ò %Ü%×2Ñ2´7·=±=ÔAÜ&×,Ñ,Ø ?Ù2A¡
ÀzØ !ôó
  %÷%%ð %ûð%ú÷%ð& ús;   “C•AA+Á+CÁ0CÁ:CÂ>CÃ CÃCÃCÃCc                 óö  •— t        d«      } d }i }‰rh‰rt        ‰t        j                  «      sJ ‚‰j	                  «       Š‰j                  «       \  ŠŠ‰D �cg c]  }|d   ‰v r|‘Œ c}Št        ‰ˆfd„¬«      Š‰D �]0  \  }}}	 |�|j                  «       }n!‰s|j                  }|j                  «        nd }‰r>‰j!                  |«      5  ‰j#                  |‰«      \  }	}
|	||<   |	| k  r|	} |}d d d «       Œ}‰|k(  xs ‰‰z   ‰|   ‰z   kD  }|sŒ•|sŒ˜|j                  «        |j$                  r|j&                  sJ ‚|j$                  d   }|j&                  }|j(                  }t+        ‰‰|j&                  |||j,                  j.                  t1        j2                  ‰«      «      }|s�Œ/|} n ‰r
 ‰| ‰‰«       ‰r| ‰‰z   k  rL|�Jt4        j6                  r|‰d <   ‰j9                  ‰«       n‰j;                  |«       ‰r|‰j<                  d <   yy	c c}w # t        $ rI}t        j                  t        j                  «      rt        j                  d‰sdnd|«       Y d }~�Œéd }~ww xY w# 1 sw Y   �ŒûxY w)
NrÊ  r   c                ó   •— ‰| d      S ré   r…   )rˆ  r”  s    €rs   r8  zKScheduler.speedup_by_fusion.<locals>.benchmark_when_ready.<locals>.<lambda>¼  s   ø€  n°Q°q±TÑ&:€ ru   rã  rË  r”  r–  TF)rq  r²   r0   r�  r”  r‘  rè  r³  r³  rÔ  rS  rÜ  rÓ  rÔ  rÅ  rÝ  rÓ  r}  Ú	launchersÚn_regsÚn_spillsrñ  Úbmreqrâ  rH   r›  r-   r•  r–  r—  Ú_choice_timings)Úmin_ms_fusedÚms_fused_choiceÚnew_timingsÚ
fut_choicer¢  ro   rÕ  Úresr&  rÆ  ÚpathÚfusible_choiceÚcompiled_kernelrà  rá  Úshould_fuse_epilogueÚbench_epiloguer”  rÝ  r  Úfuture_choicesÚget_choice_timings_asyncÚ hint_override_best_fusion_choicerÇ  Ú
min_choicerì  rí  Ú	ms2_fusedr…  rr   s                   €€€€€€€€€€€€€€rs   Úbenchmark_when_readyz9Scheduler.speedup_by_fusion.<locals>.benchmark_when_ready¨  s¶  ø€ ä$ U›|�Ø"&�Ø �á+Ù%¬*°ZÄ×AWÑAWÔ*XÐXÐXØ%/×%>Ñ%>Ó%@�NØ&0×&?Ñ&?Ó&A‘O�J ð
 +9ö&à&Ø% a™=¨NÑ:ò #ò&�Nô &,Ø&Û:ô&�Nð
 2@ó <&Ñ-�F˜F Ið!Ø!Ð-Ø"(§-¡-£/™CÙ!/Ø"+×"3Ñ"3˜CØŸN™NÕ,à"&˜Cñ &à'×=Ñ=¸fÓEñ 	9Ø-1×-LÑ-LØ )à &ó.™N˜H dð
 3;˜K¨Ñ/Ø'¨,Ò6Ø/7 Ø28 ÷	9ð 	9ð '¨&Ñ0ò NØ" S™y¨>¸&Ñ+AÀIÑ+MÑMð 'ò
 ¢>Ø"×-Ñ-Ô/à#&§=¢=°V·]²]ÐBÐ#Bà.1¯m©m¸AÑ.>˜Oà+:×+AÑ+A˜Là-<×-EÑ-E˜NÜ3AØ #Ø #Ø &§¡Ø ,Ø .Ø &§¡× 6Ñ 6Ü 0× 7Ñ 7¸Ó ?ó4Ð0ó  4Ø28 Ù %ðy<&ñ| "Ù˜|¨S°#Ô6ñ '¨,¸#À¹)Ò*DØ%Ð1Ü×0Ò0ØAPÐ8¸Ñ>à"×=Ñ=Ø<õð
 #×<Ñ<¸_ÔMá%à;F˜
×2Ñ2°4Ñ8Øà ùò}&øô. %ò !Ü%×2Ñ2´7·=±=ÔAÜ&×,Ñ,Ø ?Ù2A¡
ÀzØ !ôõ
 !ûð!ú÷	9ñ 	9ús*   ÁHÂ4HÃ$I.È	I+È">I&É&I+É.I8	c                 óâ  •‡‡‡‡‡‡— ddl m}  	 ‰d   ‰d   ‰d   fD ]  }|€Œ|j                  «        Œ ‰j                  ‰d   ‰
«      \  ŠŠt	        j
                  ‰«      r	 ‰d«       y‰j                  ‰d   ‰
«      \  ŠŠt	        j
                  ‰«      r	 ‰d«       y‰j                  ‰d   ‰
«      \  ŠŠt	        j
                  ‰«      r	 ‰d«       y ‰‰‰‰«       t        d«      rW‰‰‰z   k\  rO‰‰f‰j                  vr?‰j                  j                  ‰‰f«       t        d«      j                  ˆˆˆˆˆˆfd	„«       ‰‰‰z   k  S # | $ r Y y‰	$ r}d
t        |«      v rY d }~y‚ d }~ww xY w)Nr   )ÚNoTritonConfigsErrorr   z%register spilling of the first kernelFz&register spilling of the second kernelz%register spilling of the fused kernelÚslow_fusionc            	     ó$   •— ‰‰ ‰‰‰‰‰‰ ‰z   z  dœS )N)Úkernel1_pathÚkernel1_latencyÚkernel2_pathÚkernel2_latencyÚfused_kernel_pathÚfused_kernel_latencyÚslow_down_ratior…   )rì  rí  rÆ  Úpath1Úpath2Ú
path_fuseds   €€€€€€rs   r8  zKScheduler.speedup_by_fusion.<locals>.benchmark_when_ready.<locals>.<lambda>Q  s(   ø€ Ø05Ø36Ø05Ø36Ø5?Ø8@Ø3;¸sÀS¹yÑ3Iñ%€ ru   úLoop-carried variableT)Ú)torch._inductor.runtime.triton_heuristicsrð  r³  r}  r  Úisinfr$   r‚  r¢  r#   rª  r,  )rð  r¼  r&  rì  rí  rÆ  rú  rû  rü  rÂ  rÝ  Úfuture_and_mod_l1Úfuture_and_mod_l1_fusedÚfuture_and_mod_l2rÇ  rr   rS  s      @@@@@@€€€€€€€€rs   rî  z9Scheduler.speedup_by_fusion.<locals>.benchmark_when_ready  sœ  þ€ õðAð *¨!Ñ,Ø)¨!Ñ,Ø/°Ñ2ð ò )˜ð
 ™?ØŸJ™J�Lð)ð "&×!@Ñ!@Ø)¨!Ñ,àó"‘J�C˜ô
 —z‘z #”ÙÐCÔDØ$à!%×!@Ñ!@Ø)¨!Ñ,àó"‘J�C˜ô
 —z‘z #”ÙÐDÔEØ$à+/×+JÑ+JØ/°Ñ2àó,Ñ(�H˜jô
 —z‘z (Ô+ÙÐCÔDØ$á˜x¨¨cÔ2ô 0°Ô>Ø$¨¨c©	Ò1Ø" E˜N°$×2IÑ2IÑIà×/Ñ/×3Ñ3°U¸E°NÔCÜ(¨Ó7×?Ñ?÷ð ô
ð $ c¨C¡iÑ/Ð/øà+ò !Ù à'ò Ø.´#°a³&Ñ8Ü#Øûðús<   �E £AE Á+5E Â!5E ÃA3E ÅE.ÅE.ÅE)Å(E)Å)E.r{   )rÆ  rq  rì  rq  rí  rq  r�   r  )r¢  zir.ChoiceCallerr�   r}   )r¢  z5torch._inductor.select_algorithm.TritonTemplateCallerr�   r}   r  )Dr  r²   r‡  r0   r  r  r-   r  rk   ry   Úbenchmark_fusionrç  rë  r»   rª   r«   rh  r¥   rš  r›  r±  Útriton.compiler.errorsrÂ  rÔ  r�  rŠ  r•  r”  rè  rÀ  r`  ra  rŽ  rÐ  rÓ  rä   r½  ry  rq  r³  rS  rÜ  rÓ  rÔ  rÅ  rÝ  r}  rÞ  r"   Úbenchmark_epilogue_fusionrü   r’  r   Ú max_epilogue_benchmarked_choicesr‘  ÚoperatorÚ
itemgetterr7  rÍ  r»  r¼  r–  r—  rr  rg  rÚ  rÎ   r|   )1rr   rˆ   r‰   Úis_multi_templateÚatomic_add_template_epilogueÚnode_list_1Únode_list_2Úhas_atomic_addry  r¢  r=  rß  rà  rá  ro   rÕ  r&  rÆ  rä  Únum_triton_callersÚchoice_timings_iterrZ  rÑ  r×  Útriton_choicerû  Útriton_choicesÚunfused_timerî  rÍ  rÂ  rè  r”  rÝ  r  r   r  r  ré  rê  rë  rÇ  rì  rì  rí  rí  r…  rÖ  rS  s1   ```                          @@@@@@@@@@@@@@@@@@@@rs   Úspeedup_by_fusionzScheduler.speedup_by_fusionŽ  se  ÿÿþ€ ô  ñ  
ð ˜U�^ô 
ó 
Ðô
 (2Ø×#Ñ#Ó%¤r×'>Ñ'>ó(
ò (Jä.¨uÀ5ÔIð 	%ñ (´×0VÒ0VÜ×$Ñ$ UÓ+Ð+ä×&Ò&Ñ/@Ü×$Ñ$ TÓ*Ð*ð ×ÑÔÜ˜u×6Ñ6Ó8¼"×:QÑ:QÔRØ×ÑÔ!Ø×ÑÔ!ô  ×$Ñ$ TÓ*Ð*à—o‘oÓ'ˆØ˜Q‘×*Ñ*Ó,ˆÙˆˆvð �;‰;˜%Ò¤F×$6Ñ$6¸(Ò$BÜ×$Ñ$ TÓ*Ð*à—o‘oÓ'ˆÜœyŸ™¨{¸KÓHÓIˆØ×-Ñ-¨oÓ>ˆñ Ñ"3Ü×$Ñ$ TÓ*Ð*å;ä˜˜uÓ%ˆà  Ñ#×.Ñ.Ó0ˆØÐ!Ð!Ð!ö	ò" ¤ñ %
Ø8=¸u°~ô%
õ "
ð $×5Ñ5Ó7¸tÐCˆOñ #ð ×'Ñ'Ô)à×,Ñ,Ó.ð ô
 ˜j¬"×*@Ñ*@ÔAÐAÐAà×5Ñ5°jÔAÜ#×(Ñ(¨Ó/Ð/ð ð -ò "ØTV�Ü%+×%>Ñ%>ó ,V�MØ%/×%>Ñ%>¸}Ó%M�NÜ%+¨N×,@Ñ,@Ó,BÉÔ%Wò ™	˜ Ü)Ø"Ü!ŸO™O×<Ñ<×QÑQô ð %Ø'×=Ñ=¸fÓEñ 	Ø*×1Ñ1à$*ð!"à%)×%8Ñ%8Ø(7Ø6<×6JÑ6Jð &9ó &&ñ!"ô÷	ð 	ðô" $)¨£<�LØGK�OØ"$�KØ5Cò 9Ñ1˜ ¨	ð
%Ø%Ð1Ø &§¡¤ð (×=Ñ=¸fÓEñ 9Ø-1×-LÑ-LØ )¨6ó.™N˜H dð 3;˜K¨Ñ/Ø'¨,Ò6Ø/7 Ø28 ÷9ð 9ð9ð( AL�J×.Ñ.¨}Ñ=Ü% oÔ7OÔPÐPÐPØFUÐ4°]ÓCðY,Vô\ $×=Ñ=ˆNÜ!$ñ %ØAK×ASÑASô%ó "Ðô
 )Ó*ò RØ&Ð&òRà&¬&×*QÑ*QÑQð %ô ˜U“|¤U¨5£\ˆHˆC�Ø15ˆJÙ+à!+×!:Ñ!:Ó!<�Ø",×";Ñ";Ó"=‘�
˜CÜ&,Ø"×(Ñ(Ó*´×0CÑ0CÀAÓ0Fô'Ñ#ð 8B×7IÑ7IÖ&J°!¨¨1¢vÐ&JÐ#Ð&Jå>öð ØMðà÷ñ ò0 Ù&Ü'×,Ñ,¨UÓ3Ð3à%G¤v×'@Ñ'@Ð%GÀ$Ð%Gò V�MØ%/×%>Ñ%>¸}Ó%M�NØGK�OÜ%+Ø&×,Ñ,Ó.´H×4GÑ4GÈÓ4Jô&ò "™	˜ ñ  6°fÔ=Ø$Ü(.¯©Ü!ŸO™O×<Ñ<×QÑQØ"ó)˜ñ 8¸ÕFØ.;˜OÙ!ð"ð 'Ð.Ü+×0Ñ0°Ó7Ò7ØFUÐ4°]ÒCð#Vô& ×,Ò,Ø×9Ñ9Ø8õð ×8Ñ8Ø8¸Ñ>ôô $×(Ñ(¨Ó.Ð.áñ 'ð ×.Ñ.¨{Ô;à×3Ñ3°KÓ@ñ �‘Uñ 'Ü'×,Ñ,¨UÓ3Ð3à×2Ñ2Ó4�Ü<¸UÀEÈ3ÓO�	ð QSˆNØˆNØ(;ò !Ñ$�˜Ù-¨fÔ5ØÜŸ™Ô%=¸vÓF�á! l°c¸C±iÒ&?Ùà !Ñ#�Ø!¤F×$KÑ$KÒKÙà×5Ñ5°fÓ=ñ !ð!Ø&×-Ñ-Ø#ÐK d×&9Ñ&9¸/Ó&JÑKõ÷!ð !ð!ô, �>Ó" aÒ'Ü#×(Ñ(¨Ó/Ð/÷j!÷ j!ò j!ôX  ×-Ñ-Ø$ n°QÑ&7¸Ñ&:óð ð !%× 3Ñ 3°KÓ @ÐØ $× 3Ñ 3°KÓ @ÐØ&*×&9Ñ&9¸/Ó&JÐ#÷Fô FôP  ×-Ñ-Ø0Ð9PÐQRÑ9Sð .ó ð ÷e	ñ 	ûô$  )ò %Ü)×6Ñ6´w·}±}ÔEÜ *× 0Ñ 0Ø$CÙ6E¡JÈ:Ø$%ô!"õ
 %ûð%ú÷9ñ 9üòF 'Køð^ %ò !ð !÷!ñ !ð
!ú÷!ñ !ús`   Ì!1^5Í5_Î$`Ò:`$Û`=Û$`)Þ5^?ß	`ß>`à`à`!à)`:à.`=à9`:à:`=à=a	c                ó<   — | j                   |j                  «          S )z0Look up the node in Scheduler name_to_fused_node)r¹  r¿  rì  s     rs   rù  zScheduler.get_fused_nodej  s   € à×&Ñ& t×':Ñ':Ó'<Ñ=Ð=ru   c                óL  — t         j                  d|j                  «       |j                  «       «       |j                  «       }|j                  «       |k(  sJ ‚| j	                  |«      j                  ||«      }|j                  |«       |j                  |«       |j                  |«       | j                  j                  |j                  «       D �ci c]  }|j                  «       |“Œ c}«       | j                  j                  |«      }|�|| j                  |<   |S c c}w )Nzfusing %s with %s)rÜ  rÝ  râ  rª   r#  ry   r0  r¢  r¹  rÝ  r»   rv  r±  )rr   rˆ   r‰   r\  rÝ  Únode3rÍ  Ústream1s           rs   Úfuse_two_nodeszScheduler.fuse_two_nodesn  sù   € ô 	×ÑÐ,¨e¯n©nÓ.>ÀÇÁÓ@PÔQà×!Ñ!Ó#ˆØ×ÑÓ! VÒ+Ð+Ð+Ø× Ñ  Ó(×-Ñ-¨e°UÓ;ˆØ×Ñ˜5Ô!Ø×Ñ˜5Ô!Ø�‰˜ÔØ×Ñ×&Ñ&ÀUÇ_Á_ÓEVÖ'WÀ¨¯
©
«°eÑ(;Ò'WÔXð ×%Ñ%×)Ñ)¨%Ó0ˆØÐØ)0ˆD×Ñ Ñ&àˆùò (Xs   ÃD!c                ó‚   — | j                  ||«      r-| j                  ||«      s |«       r| j                  |||«       yy©NTF)r  Úwill_fusion_create_cycler  )rr   rˆ   r‰   Ú
speedup_fnr\  s        rs   Úfuse_if_speedupzScheduler.fuse_if_speedup†  s?   € ð �M‰M˜% Ô'Ø×1Ñ1°%¸Ô?Ù”à×Ñ  u¨kÔ:Øàru   c                óˆ  — |�r¿g }i }t        «       }|D �]  }||v rt        ||   «      dk\  sJ ‚||   j                  d«      }t        ||   «      dk(  r|j                  |«       |j	                  «       \  }}	|	|k(  rt        ||	«      sJ ‚|}
n||k(  sJ ‚t        ||	«      sJ ‚|	}
| j                  |
«      |
urŒ¥|j                  r3|j                  j                  }|€J ‚|j                  |«       ||f||<   Œä| j                  ||	|j                  |«      s�Œ|j                  |«       �Œ t        |«      D ]l  }||   \  }}| j                  | j                  |j                  «      | j                  |j                  «      |j                  |«      sŒ\|j                  |«       Œn |D ]  }|j                  |«       Œ |r�Œ¾yy)zÁ
        Evaluate pending template fusions for a set of fusion candidate nodes.
        The fusion candidate nodes are pointwise nodes as potential epilogue
        or prologue fusions
        r   r   N)r   rÎ   r¡  r¢  rŒ   r&  r)  rù  ro   rä   r  rm   r   rˆ   r‰   )rr   Útemplate_fusion_candidatesr\  Útemplate_futuresÚfuture_to_pending_fusionÚfusions_to_removerÒ  Úpending_fusionrˆ   r‰   r•  ÚfÚcands                rs   Ú"_evaluate_pending_template_fusionsz,Scheduler._evaluate_pending_template_fusions—  s  € ò )Ø-/Ðð ð %ô @J»|ÐØ7ó %9�	àÐ!;Ñ;ÜÐ6°yÑAÓBÀaÒGððHð "<¸IÑ!F×!JÑ!JÈ1Ó!M�äÐ1°)Ñ<Ó=ÀÒBØ%×)Ñ)¨)Ô4à-×>Ñ>Ó@‘��uà˜IÒ%Ü-¨e°UÔ;Ð;Ð;Ø$)‘Mà  IÒ-Ð-Ð-Ü-¨e°UÔ;Ð;Ð;Ø$)�Mð ×&Ñ& }Ó5¸]ÑJØà!×(Ò(Ø&×-Ñ-×4Ñ4�AØ˜=Ð(˜=Ø$×+Ñ+¨AÔ.Ø3AÀ9Ð2MÐ,¨QÒ/ð ×+Ñ+Ø˜u n×&@Ñ&@À+öð *×-Ñ-¨iÖ8ðK%9ôP "Ð"2Ó3ò 0�Ø'?ÀÑ'BÑ$� Ø×'Ñ'Ø×'Ñ'¨×(<Ñ(<Ó=Ø×'Ñ'¨×(<Ñ(<Ó=Ø"×.Ñ.Øõ	ð &×)Ñ)¨$Õ/ð0ð 'ò 2�Ø*×.Ñ.¨qÕ1ð2õq )ru   c                óÂ  ‡ ‡‡— 	 	 	 	 	 	 dˆˆˆ fd„}|D �]H  \  }} |||«       ‰ j                  |«      }‰ j                  |«      }t        ||«      r||f‰ j                  v rŒO‰ j                  |||«      sŒc‰ j	                  ||«      rŒv‰ j                  ||«      }	|	j                  �”t        |	j                  |||	j                  ¬«      }
t        ||«      rY||f‰ j                  vsJ ‚‰ j                  j                  ||f«       t        ||«      }||vrg ||<   ||   j                  |
«       n
|
‰|<   |
‰|<   �Œ(|	j                  s�Œ6‰ j                  ||‰«       �ŒK y )Nc                ób  •— ‰j                  | «      ‰v s‰j                  |«      ‰v �r‰j                  ‰j                  | «      ‰j                  ‰j                  |«      «      «      }|€J ‚|j                  «       \  }}|j                  }‰j	                  |d «       ‰j	                  |d «       ‰j                  |«      |u sJ ‚‰j                  |«      |u sJ ‚ |«       r‰j                  | |«      rŒñ‰j                  ||‰«       ‰j                  | «      ‰v rŒñ‰j                  |«      ‰v r�Œy y r~   )rù  r±  rŒ   rm   r¡  r  r  )	rˆ   r‰   r#  Ú	node_key1Ú	node_key2Ú
is_speedupr\  Úpending_fusionsrr   s	         €€€rs   Úresolve_pending_fusionsz<Scheduler._try_fusion_pairs.<locals>.resolve_pending_fusionså  s1  ø€ ð
 ×#Ñ# EÓ*¨oÑ=Ø×&Ñ& uÓ-°Ò@à!0×!4Ñ!4Ø×'Ñ'¨Ó.Ø#×'Ñ'¨×(;Ñ(;¸EÓ(BÓCó"�ð &Ð1Ð1Ð1à'5×'FÑ'FÓ'HÑ$�	˜9Ø+×7Ñ7�
à×#Ñ# I¨tÔ4Ø×#Ñ# I¨tÔ4à×*Ñ*¨9Ó5¸ÑBÐBÐBØ×*Ñ*¨9Ó5¸ÑBÐBÐBá!”| t×'DÑ'DÀUÈEÔ'RØà×#Ñ# I¨y¸+ÔFð+ ×#Ñ# EÓ*¨oÒ=Ø×&Ñ& uÓ-°Õ@ru   )rm   rˆ   r‰   ro   rá  )rù  r+  ry  r  r  r  rm   r‡   ro   r¢  r-  rä   rl   r  )rr   Úpossible_fusion_pairsr,  Útemplate_fusion_nodesr\  rj  r-  rˆ   r‰   Ú
fusion_resr#  Útemplate_pw_nodes   ` ` `       rs   Ú_try_fusion_pairszScheduler._try_fusion_pairsÝ  s”  ú€ ð	GØ$ð	Gà$ð	Gð ÷	Gð8 2ó +	?‰LˆE�5ñ $ E¨5Ô1Ø×'Ñ'¨Ó.ˆEØ×'Ñ'¨Ó.ˆEô # 5¨%Ô0Ø˜E�N d×&@Ñ&@Ñ@àà�}‰}Ø�uÐ.õà×3Ñ3°E¸5ÕAØ!×3Ñ3°E¸5ÓA�
Ø×)Ñ)Ð5Ü%2Ø$.×$:Ñ$:Ø#Ø#Ø)×0Ñ0ô	&�Nô *¨%°Ô7Ø % u˜~°T×5OÑ5OÑOÐOÐOØ×2Ñ2×6Ñ6¸¸u°~ÔFä+BÀ5È%Ó+PÐ(Ø+Ð3HÑHØFHÐ1Ð2BÑCØ-Ð.>Ñ?×FÑFÀ~ÕVà1?˜¨Ñ.Ø1?˜¨Ñ.áà!×-Ò-Ùà×#Ñ# E¨5°+Ö>ñW+	?ru   c                ó@  — t        «       }|j                  «       D ]�  }|j                  «       \  }}|j                  }||v st	        ||«      rŒ3|j                  |«       | j                  |«      |u sJ ‚| j                  |«      |u sJ ‚| j                  ||||«       Œƒ y r~   )r   rÝ   rŒ   rm   r+  r¢  rù  r  )rr   r\  r,  Úseen_pair_speedup_fnr#  r)  r*  Úis_speedup_fns           rs   Ú_finish_pending_fusionsz!Scheduler._finish_pending_fusions.  s·   € ô
 @J»|Ðð .×4Ñ4Ó6ò 	SˆNØ#1×#BÑ#BÓ#DÑ ˆI�yØ*×6Ñ6ˆMàÐ 4Ñ4Ô8JØ˜9ô9ð à ×$Ñ$ ]Ô3à×&Ñ& yÓ1°YÑ>Ð>Ð>Ø×&Ñ& yÓ1°YÑ>Ð>Ð>à× Ñ  ¨I°}ÀkÕRñ	Sru   c           
     óî   — t        |D ��cg c]  \  }}t        ||«      sŒ|‘Œ c}}«      }g }|D ]<  \  }}t        ||«      r||v r|j                  ||f«       Œ*|j                  ||f«       Œ> |S c c}}w r~   )r   r&  r)  rä   )rr   Úpossible_fusionsÚdeferred_prologue_fusionsÚn1Ún2Úepilogue_template_nodesÚnew_possible_fusionss          rs   Ú_handle_template_overlapz"Scheduler._handle_template_overlapF  sŠ   € ô #-Ø.×M‘F�B˜Ô2DÀRÈÕ2LŠRÓMó#
Ðð  "ÐØ&ò 	6‰FˆB�Ü! " bÔ)¨bÐ4KÑ.KØ)×0Ñ0°"°b°Õ:à$×+Ñ+¨R°¨HÕ5ð		6ð $Ð#ùó Ns
   ‹A1
 A1
c                óº  — | j                  |«       t        |«      }t        j                  t        j
                  «      r@t        j                  d«       |D ]&  }t        j                  d|j                  «       «       Œ( i }i }g }| j                  ||«      }t        j                  st        j                  r| j                  ||«      }| j                  |||||«       | j                  ||«       | j                  ||«       |j!                  «        |r'| j                  |||||«       | j                  ||«       t#        |d„ ¬«      }| j%                  |«      }|S )a  
        Combine eligible nodes into FusedSchedulerNodes.

        This relies on two key functions to control the logic:
            - self.can_fuse(): checks if a fusion is legal
            - self.score_fusion(): assigns priority to a given fusion
        zfuse_nodes_once, candidates:z  %sc                ó   — | j                   S r~   r­  r¯  s    rs   r8  z+Scheduler.fuse_nodes_once.<locals>.<lambda>›  s
   € °!·+±+€ ru   rã  )rº  r   rÜ  rÓ  rÔ  rÅ  rÝ  rh  Úget_possible_fusionsr-   rŒ  r�  r>  r2  r6  r&  Úclearrè  r{  )	rr   rq  rj  r\  r”   r,  r/  r9  r8  s	            rs   rk  zScheduler.fuse_nodes_onceZ  sk  € ð 	×!Ñ! %Ô(Ü  Ó'ˆÜ×"Ñ"¤7§=¡=Ô1Ü×ÑÐ;Ô<Ø#ò A�Ü× Ñ  ¨×)=Ñ)=Ó)?Õ@ðAð ð 	ð
 OQÐð ð 	"ð  ×4Ñ4ØØó
Ðô
 ×#Ò#¤v×':Ò':Ø#×<Ñ<Ø Ð";ó Ðð 	×ÑØØØ!ØØô	
ð 	×$Ñ$ [°/ÔBà×/Ñ/Ð0EÀ{ÔSØ×#Ñ#Ô%á$Ø×"Ñ"Ø)ØØ%ØØ ôð ×3Ñ3Ð4IÈ;ÔWä�{Ñ(=Ô>ˆØ×.Ñ.¨uÓ5ˆØˆru   c              #  ó¾   ‡K  — t        | ˆfd„¬«      }|dk  r|r|–— yg }d}|D ],  }‰|   }|r||z
  |kD  r|–— g }|s|}|j                  |«       Œ. |r|–— yy­w)u  Sort `nodes` by baseline index, then yield groups whose span
        is at most `max_distance`. Start a new window whenever the next
        node would push the span past the limit. Negative `max_distance`
        means "no limit" â€” yield everything as one window.
        c                ó   •— ‰|    S r~   r…   )rÍ  rœ   s    €rs   r8  z-Scheduler._distance_windows.<locals>.<lambda>ª  s   ø€ ¨k¸!©n€ ru   rã  r   Nr  )rè  rä   )rq  rœ   Úmax_distanceÚorderedÚwindowÚ
window_minrÍ  Úidxs    `      rs   Ú_distance_windowszScheduler._distance_windowsŸ  s‡   øè ø€ ô ˜Ó$<Ô=ˆØ˜!ÒÙØ’ØØ*,ˆØˆ
Øò 	ˆAØ˜a‘.ˆCÙ˜# 
Ñ*¨\Ò9Ø’Ø�ÙØ �
Ø�M‰M˜!Õð	ñ Ø‹Lð ùs   ƒAAc           	     ó<  ‡ ‡‡— t        ‰ j                  «      ŠdŠt        ‰ j                  «      }t        j	                  d|«       t
        j                  dkD  }t
        j                  }t
        j                  }|duxs |du}t
        j                  }d}d}	|r‰ j                  «       }	|	j                  }
n(t        ‰ j                  «      D ��ci c]  \  }}||“Œ
 }
}}	 	 	 	 	 	 	 	 dˆˆˆ fd„}t        t        j                  ‰ «      «      D ]÷  \  }}|�‰|kD  r nët        j                  |«      }t        |«      dk  rŒ3t         j#                  ||
|«      D ]«  }|�‰|kD  r ŒVt        |«      dk  s‰ j%                  |«      sŒ,|rI|	€J ‚t'        j(                  «       }‰ j+                  |||	||¬«       |t'        j(                  «       |z
  z  }Œwt        |d   j,                  |d|t
        j.                  ¬	«      } ||||«       Œ­ Œù t1        ‰d
„ ¬«      ‰ _        ‰ j3                  ‰ j                  «      ‰ _        t        j5                  d‰|t        ‰ j                  «      «       |rt        j5                  d|«       ‰ j7                  ‰ j                  «       yc c}}w )a"  Group parallel nodes into combo kernels.

        Each parallel group is split into windows whose baseline-index
        span is at most `combo_kernel_max_distance` (set the config to a
        negative value to disable splitting). If a peak-memory threshold is set,
        each window goes through the gate, which simulates the
        post-fusion peak and accepts the combo only if the peak stays
        under the threshold; rejected windows are halved and retried.
        Without a threshold, every window becomes a combo directly.
        r   z2ComboKernels: Generating with num_ck_nodes = %s...Nç        c                ó˜  •— ‰dz  Št         j                  dt        |«      |«       |D ]  }‰j                  |«       Œ ‰j	                  | «       ‰j
                  j                  | j                  «       D �ci c]  }|j                  «       | “Œ c}«       ‰j                  j                  |d   «      }|�|‰j                  | <   y y c c}w )Nr   z0ComboKernels: Combining %d nodes for %d-th groupr   )rT  rj  rÎ   r0  r¢  r¹  rÝ  r»   râ  rv  r±  )	Ú
combo_nodeÚacceptedÚnumr”   rÍ  Ústreamrn  r\  rr   s	         €€€rs   Ú_register_acceptz=Scheduler.create_combo_kernel_nodes.<locals>._register_acceptÙ  sÅ   ø€ ð �Q‰JˆEÜ�H‰HØBÜ�H“Øôð
 !ò )�Ø×"Ñ" 4Õ(ð)à�O‰O˜JÔ'Ø×#Ñ#×*Ñ*Ø3=×3GÑ3GÓ3IÖJ¨a�—‘“˜zÑ)ÒJôð ×(Ñ(×,Ñ,¨X°a©[Ó9ˆFØÐ!Ø28�×#Ñ# JÒ/ð "ùò Ks   Á7CrÍ   )r[  Ú	on_acceptT©rX  r[  rd  c                ó   — | j                   S r~   r­  r¯  s    rs   r8  z5Scheduler.create_combo_kernel_nodes.<locals>.<lambda>  s
   € °q·{±{€ ru   rã  zDGenerated ComboKernel nodes: %d ComboKernels, totally %d -> %d nodesz9ComboKernels memory-aware: %.3fs spent in peak simulation)rN  rB  rO  r¦  rP  r‘   r�   r  )r   rq  rÎ   rT  rÝ  r-   rÜ  Ú$combo_kernel_peak_memory_increase_gbÚ&combo_kernel_peak_memory_pct_thresholdÚcombo_kernel_max_distanceÚ_init_peak_memory_contextrœ   r’  rB  rˆ  rq  rÛ  rJ  Úspeedup_by_combo_kernelÚtimeÚperf_counterÚ_try_combo_with_halvingrÜ  Ú!combo_kernel_per_subkernel_blocksrè  r{  rj  rº  )rr   rX  Únum_nodes_origr[  Ú
abs_thr_gbÚpct_thrÚmemory_checkrE  Úmemory_sim_timeÚmem_ctxrœ   r�  rÍ  rR  rP  r°  ÚmembersrG  Ú	sim_startrN  rn  r\  s   `                   @@rs   r’  z#Scheduler.create_combo_kernel_nodes¼  s�  ú€ ô ! §¡Ó,ˆØˆÜ˜TŸZ™Z›ˆÜ�	‰	ÐFÈÔUÜ ×7Ñ7¸!Ñ;ˆä×@Ñ@ˆ
Ü×?Ñ?ˆØ!¨Ð-ÒD°ÀÐ1DˆÜ×7Ñ7ˆØˆØ37ˆÙØ×4Ñ4Ó6ˆGØ!×-Ñ-‰Kä,5°d·j±jÓ,A×B¡D A q˜1˜a™4ÐBˆKÑBð	9Ø2ð	9à-ð	9ð ð	9ð ÷		9ô, (Ü&×DÑDÀTÓJó
ò #	>‰NˆC�ð Ð'¨E°LÒ,@ÙÜ0×AÑAÀ)ÓLˆGÜ�7‹|˜aÒØä#×5Ñ5Ø˜ lóò >�ð  Ð+°¸Ò0DÙÜ�v“; ’?¨$×*FÑ*FÀvÔ*NØÙØ"Ð.Ð.Ð.Ü $× 1Ñ 1Ó 3�IØ×0Ñ0ØØØØ(7Ø"2ð 1ô ð $¤t×'8Ñ'8Ó':¸YÑ'FÑF‘Oä!;Ø˜q™	×+Ñ+ØØ26Ø(7Ü-3×-UÑ-Uô"�Jñ % Z°¸Õ=ñ5>ð#	>ôJ ˜KÑ-BÔCˆŒ
Ø×3Ñ3°D·J±JÓ?ˆŒ
Ü�‰ØRØØÜ�—
‘
‹Oô		
ñ Ü�H‰HØKØôð 	×!Ñ! $§*¡*Õ-ùóU Cs   ÃJc           	     ó¤  — ddl m}m}m}m}m}m} t        t        j                  j                  j                  «       «      }t        t        j                  j                  «       «      } || j                  |«      }	 || j                  | j                  «        || j                  | j                  | j                  |	«        || j                  |	|«      \  }
}} ||
t!        | j                  «      «      \  }} ||
t!        | j                  «      «      }t#        |t%        | j                  «      D ��ci c]  \  }}||“Œ
 c}}|||¬«      S c c}}w )zŠBuild the immutable baseline state the gate compares against:
        original buffer lifetimes, original peak, and step indices.
        r   )rZ  Ú/assign_memory_planning_info_for_scheduler_nodesr  r  Ú+live_memory_before_steps_from_buf_info_listÚpeak_memory_from_buf_info_list)rš   rœ   r�   rž   r¢   )r”  rZ  rh  r  r  ri  rj  r   ra   rÁ   rX  r!  r•  rq  r  r¹  rÎ   r˜   r’  )rr   rZ  rh  r  r  ri  rj  rX  rš   Úname_to_freeabler5  r=  r�   r¢   rI  r”   s                   rs   rY  z#Scheduler._init_peak_memory_context#  s   € ÷	
÷ 	
ô "¤!§'¡'×"6Ñ"6×";Ñ";Ó"=Ó>ˆÜ"¤1§7¡7×#;Ñ#;Ó#=Ó>ˆá1°$·*±*¸lÓKÐÙ9¸$¿*¹*Àd×FVÑFVÔWÙ7Ø�J‰JØ×#Ñ#Ø×ÑØô		
ñ 6Ø�J‰JÐ(¨-ó
Ñˆ�q˜!ñ :Øœ3˜tŸz™z›?ó
Ñˆ�qñ  KØœ3˜tŸz™z›?ó 
Ðô (Ø'Ü4=¸d¿j¹jÓ4I×J¡y s¨D˜˜s™ÓJØ'Ø&Ø!5ô
ð 	
ùãJs   Ä3Ec                ó:  ‡‡‡ — ddl m} t        |d   j                  |d|t        j
                  ¬«      }t        «       }|D ]'  }|j                  |j                  j                  «       Œ) t        |¬«      |_        |j                  Š t        «       }t        j                  }	d}
|D ]'  }|j                  |«       ‰ |   }||	k  r|}	||
kD  sŒ&|}
Œ) g Šd}dˆfd	„}t        |	|
dz   «      D ].  }| j                   |   }||v r|s |||	|«       d}Œ% ||||«       Œ0 t#        ‰d
„ ¬«      D �cg c]  }|j$                  ‘Œ }}| j'                  |«      }t)        |«      D ��ci c]  \  }}||	|z   “Œ c}}Š‰|   }|D ]  }|‰|<   Œ	 dˆˆ fd„}|j*                  |	   } |||	|
||j,                  |¬«      }|j.                  }t1        |j2                  |«      }||z
  }t        j4                  }t        j6                  }|�t9        |«      dz  gng }|�|j;                  ||z  «       |sJ ‚|t=        |«      k  }|dkD  rd|z  |z  nd}|s"t>        jA                  dtC        |«      ||«       yt>        jE                  dtC        |«      ||«       ||_        ||fS c c}w c c}}w )a4  The gate: does fusing `group_nodes` into one combo keep peak
        memory under the threshold?

        Returns `(combo_node, combo_step)` if accepted, or `(None, 0)`
        if rejected. The running peak lives on `mem_ctx.running_peak`.

        The pretend rewrite only changes node order inside the window
        `[region_start, region_end]` (the smallest range containing all
        members). Inside that window:
          - the members collapse into one combo node, all at `combo_step`,
          - everything else is evaluated from the original schedule.
        Outside the window, nothing moves. Earlier accepts are accounted
        for only by `mem_ctx.running_peak`. The threshold is checked
        against `mem_ctx.baseline_peak` (the original graph peak) so total
        peak drift is capped.
        r   )Úestimate_region_peak_memoryr   TrT  )Úpred_buffersr  Fc                ó>   •— ‰j                  t        ||| «      «       y r~   )rä   r�   )r”   r’   r“   Úlocal_entriess      €rs   Ú	add_localz9Scheduler._try_combo_with_memory_check.<locals>.add_localˆ  s   ø€ Ø× Ñ ¤¨S°(¸DÓ!AÕBru   c                ó2   — | j                   | j                  fS r~   )r’   r“   )r&  s    rs   r8  z8Scheduler._try_combo_with_memory_check.<locals>.<lambda>•  s   € ÀÇÁÈÏ
É
Ð@S€ ru   rã  c                ó    •— | ‰v r‰|    S ‰|    S r~   r…   )r”   Únew_steprœ   s    €€rs   Ústep_ofz7Scheduler._try_combo_with_memory_check.<locals>.step_ofž  s    ø€ Ø�xÑØ ‘~Ð%Ø˜tÑ$Ð$ru   )Úregion_startÚ
region_endru  rš   Ú
cur_memoryi   @g      Y@rL  zLComboKernels memory-aware: rejected %d nodes (peak delta %+d bytes = %.3f%%)ré   zLComboKernels memory-aware: accepted %d nodes (peak delta %+d bytes = %.3f%%))r”   rf   r’   r‘   r“   r‘   r�   r  r.  )#r”  rm  rB  rÜ  r-   r^  r   rÝ  r'  rn  rG   rœ   ÚsysÚmaxsizer¢  rL  rq  rè  r”   r{  r’  r¢   rš   r�   rY  rž   rV  rW  rq  rä   rZ  rT  rÝ  rÎ   rj  )!rr   Úgroup_nodesrd  r[  rm  rN  Úcombo_pred_buffersÚmÚ	group_setrv  rw  rÍ  rI  Úinserted_comborq  r�  r&  Úlocal_nodesÚ
combo_stepru  rx  Úregion_peakÚoriginal_peakÚnew_peakÚdeltar`  ra  ÚlimitsÚacceptÚpctrp  rt  rœ   s!                                 @@@rs   Ú_try_combo_with_memory_checkz&Scheduler._try_combo_with_memory_checkM  sô  ú€ õ, 	8ä/Ø˜‰N×$Ñ$ØØ&*Ø+Ü!'×!IÑ!Iô
ˆ
ô (›\ÐØò 	?ˆAØ×%Ñ% a§j¡j×&=Ñ&=Õ>ð	?ä7Ø+ô
ˆ
Ôð ×)Ñ)ˆô 4>³<ˆ	Ü—{‘{ˆØˆ
Øò 	!ˆAØ�M‰M˜!ÔØ˜a‘.ˆCØ�\Ò!Ø"�Ø�ZÓØ ‘
ð	!ð ,.ˆØˆõ	Cô �| Z°!¡^Ó4ò 	ˆAØ—
‘
˜1‘ˆAØ�I‰~Ù%Ù˜j¨,¸Ô:Ø%)�NØÙ�a˜˜AÕð	ô # =Ñ6SÔTö
ØˆA�F‹Fð
ˆð 
ð ×4Ñ4°[ÓAˆä4=¸kÓ4J×K©D¨A¨q�A�| aÑ'Ñ'ÓKˆØ˜jÑ)ˆ
Øò 	%ˆAØ$ˆH�QŠKð	%ö	%ð ×1Ñ1°,Ñ?ˆ
á1ØØ%Ø!ØØ!×/Ñ/Ø!ô
ˆð  ×-Ñ-ˆÜ�w×+Ñ+¨[Ó9ˆØ˜=Ñ(ˆÜ×@Ñ@ˆ
Ü×?Ñ?ˆØ4>Ð4J”%˜
Ó# wÑ/Ñ0ÐPRˆØÐØ�M‰M˜' MÑ1Ô2ÙˆˆvØœ#˜f›+Ñ%ˆà1>ÀÒ1Bˆu�u‰}˜}Ò,ÈˆÙÜ�I‰Ið2ä�KÓ ØØôð ä�‰ð.ä�ÓØØô	
ð  (ˆÔØ˜:Ð%Ð%ùòy
ùó
 Ls   Ä*JÅJc               ó�  — |j                   }|g}|�r%|j                  «       }t        |«      dk  s| j                  |«      sŒ3t        j                  | |||«      \  }	}
|	� ||	||«       Œ[|D �cg c]  }||   ‘Œ	 }}t        |«      t        |«      }}||k(  rŒ‰||z   dz  }|D �cg c]  }||   |k  sŒ|‘Œ }}|D �cg c]  }||   |kD  sŒ|‘Œ }}dt        |«      cxk  rt        |«      k  rn n|j                  |«       dt        |«      cxk  rt        |«      k  rn n|j                  |«       |r�Œ$yyc c}w c c}w c c}w )zkTry the full candidate; on reject, halve at the
        baseline-index midpoint and try each half.
        rÍ   N)	rœ   r¡  rÎ   rZ  rÛ  r‰  rZ  rY  rä   )rr   rÒ  rP  rd  r[  rS  Ún2iÚstackÚsubsetrN  r�  rÍ  ÚidxsÚloÚhiÚmidÚearlyÚlates                     rs   r]  z!Scheduler._try_combo_with_halvingÒ  sA  € ð ×!Ñ!ˆà09¨{ˆÚØ—Y‘Y“[ˆFÜ�6‹{˜QŠ d×&BÑ&BÀ6Ô&JØä%.×%KÑ%KØ�f˜g ó&Ñ"ˆJ˜
ð Ð%Ù˜* f¨cÔ2Øà$*Ö+˜q�C˜“FÐ+ˆDÐ+Ü˜“Y¤ D£	�ˆBØ�RŠxØØ˜‘7˜q‘.ˆCØ &Ö8˜1¨#¨a©&°C«-’QÐ8ˆEÐ8Ø%Ö6˜!¨¨Q©°#«’AÐ6ˆDÐ6Ø”C˜“IÔ+¤ F£Õ+Ø—‘˜TÔ"Ø”C˜“JÔ,¤ V£Õ,Ø—‘˜UÔ#õ- ùò ,ùò
 9ùÚ6s   Á/D9Â%D>Â3D>Â=EÃEc                óH   — |D ]  }|j                  | j                  «       Œ y r~   )rº  r¹  )rr   rq  r”   s      rs   rº  zScheduler.prune_redundant_depsû  s%   € Øò 	?ˆDØ×%Ñ% d×&=Ñ&=Õ>ñ	?ru   c                óÌ  ‡ ‡‡
‡— g Š
t        t        t        t        f      «       Šdˆˆ
ˆˆ fd„}t        j                  t
        «      }|D ]=  }‰ j                  |«      rŒ|j                  «       D ]  }||   j                  |«       Œ Œ? |j                  «       D ]
  } ||«       Œ t        j                  rat        j                  t
        «      }|D ]&  }t        |dd«      }	|	sŒ||	   j                  |«       Œ( |j                  «       D ]
  } ||«       Œ ‰ j                  ‰
«      Š
‰
j                  ‰ j                  d¬«       t         j#                  dt%        ‰
«      «       ‰
S )z^
        Helper to find all legal fusion opportunities, sorted by self.score_fusion()
        c                ó|  •— t        | «      D ]­  \  }}| |dz   |dz   t        j                  z    D ]‰  }||f}|‰v rŒ‰j                  |«       ‰j	                  ||‰«      r‰j                  |«       ŒB|j                  «       s|j                  «       sŒc‰j	                  ||‰«      sŒw‰j                  ||f«       Œ‹ Œ¯ y rH  )r’  r-   Ú)max_fusion_buffer_group_pairwise_attemptsr¢  r  rä   rç  rë  )	rq  Únode1_indexrˆ   r‰   rä  rj  r8  rD  rr   s	        €€€€rs   Úcheck_all_pairsz7Scheduler.get_possible_fusions.<locals>.check_all_pairs
  sÒ   ø€ Ü&/°Ó&6ò @Ñ"�˜UØ"Ø !‘O kØñ'ä×FÑFñ'Gðò @�Eð
 ! %˜.�CØ˜d‘{Ø Ø—H‘H˜S”Mà—}‘} U¨EÐ3CÔDØ(×/Ñ/°Õ4Ø×+Ñ+Ô-°×1AÑ1AÕ1CÈÏÉØ˜uÐ&6õJð )×/Ñ/°¸°Õ?ñ!@ñ@ru   rÆ   NT)rä  Úreversezfound %d possible fusions©rq  r¦  r�   r  )r   rÏ   rf   rW  r   r¥   Úunfusable_noderã   rä   rÝ   r-   Úaggressive_fusionr½  Ú*get_possible_fusions_with_highest_priorityrÂ  Úscore_fusion_keyrÜ  rÝ  rÎ   )rr   rq  rj  r™  Úbuffer_names_groupingr”   rÞ   Únode_groupingÚgroup_groupingrÆ   r8  rD  s   ` `       @@rs   rA  zScheduler.get_possible_fusionsÿ  sn  û€ ð ÐÜœ%Ô 1Ô3DÐ DÑEÑFÓHˆ÷	@ð 	@ô( !,× 7Ñ 7¼Ó =ÐØò 	8ˆDØ×"Ñ" 4Ô(ØØ×-Ñ-Ó/ò 8�Ø% cÑ*×1Ñ1°$Õ7ñ8ð	8ð
 3×9Ñ9Ó;ò 	+ˆMÙ˜MÕ*ð	+ô ×#Ò#Ü(×4Ñ4´TÓ:ˆNØò 7�Ü  g¨tÓ4�ÚØ" 5Ñ)×0Ñ0°Õ6ð7ð "0×!6Ñ!6Ó!8ò /�Ù Õ.ð/ð  ×JÑJØó
Ðð 	×Ñ $×"7Ñ"7ÀÐÔFÜ×ÑÐ4´cÐ:JÓ6KÔLØÐru   c                óÒ  ‡ ‡‡‡‡— t        t           «       Šdˆˆˆˆ ˆfd„Š|j                  «       j                  j	                  «       |j                  «       j                  j	                  «       z  Š|j
                  j                  j	                  «       |j
                  j                  j	                  «       z  ‰z
  Št        ˆˆ fd„‰D «       «      }|r t        ||«      d«       |S )z~
        Finds whether there's a path from node1 to node2 (or vice-versa)
        caused indirectly by other fusions.
        c                ó  •— t        | t        «      rq| ‰vrm‰j                  | «       | j                  «       j	                  ‰«      ryt        ‰| j                  z  «      xs" t        ˆˆfd„| j                  ‰z
  D «       «      S y)NFc              3  óH   •K  — | ]  } ‰‰j                   |   «      –— Œ y ­wr~   rQ  ©r·   rÍ  Ú
found_pathrr   s     €€rs   r¹   zIScheduler.will_fusion_create_cycle.<locals>.found_path.<locals>.<genexpr>R  s+   øè ø€ ò Hàñ # 4×#:Ñ#:¸1Ñ#=×>ñHùó   ƒ")r²   rÚ   r¢  r  Úissubsetr}   r  r  )r”   Úcombined_ancestorsÚcombined_namesr§  rr   Úvisiteds    €€€€€rs   r§  z6Scheduler.will_fusion_create_cycle.<locals>.found_pathA  s�   ø€ ä˜$Ô 2Ô3¸ÀGÑ8KØ—‘˜DÔ!Ø×+Ñ+Ó-×6Ñ6Ð7IÔJð !ô   °·±Ñ ?Ó@ò ÄCô Hà!%§¡Ð2DÑ!DôHó Eð ð ru   c              3  óH   •K  — | ]  } ‰‰j                   |   «      –— Œ y ­wr~   rQ  r¦  s     €€rs   r¹   z5Scheduler.will_fusion_create_cycle.<locals>.<genexpr>`  s!   øè ø€ ÒW¸q‘J˜t×6Ñ6°qÑ9×:ÑWùr¨  zwill create cycler*  )r   rÚ   r  Ú_dictr!  r  r  rÔ  )rr   rˆ   r‰   Úcyclerª  r«  r§  r¬  s   `   @@@@rs   r  z"Scheduler.will_fusion_create_cycle7  sÇ   ü€ ô Ô/Ñ0Ó2ˆ÷	ñ 	ð2 ×%Ñ%Ó'×-Ñ-×2Ñ2Ó4Ø×'Ñ'Ó)×/Ñ/×4Ñ4Ó6ñ7ð 	ð
 �O‰O×!Ñ!×&Ñ&Ó(¨5¯?©?×+@Ñ+@×+EÑ+EÓ+GÑGØñÐô ÔWÐDVÔWÓWˆÙØ#ŒI�e˜UÓ#Ð$7Ô8Øˆru   c                ó�  ‡ ‡— ddl mŠ 	 	 	 	 dˆ fd„} ||«      } ||«      }t        ˆfd„|D «       «      }t        ˆfd„|D «       «      }|j                  |«      }d}	|D ]  }
	 |	t	        |
d   «      z  }	Œ ‰ j                  ||«      }t        j                  j                  j                  |	d	|z  «      ry
y# t
        $ r Y  yw xY w)aó  
        Return true if fusing the two nodes can potentially increasing peak memory.

        The implementation is more like a heuristic since we don't really know if we are at peak
        or not when trying to fuse these two nodes. The order of nodes may change later which makes the
        peak memory estimation hard.

        Here is how we decide the LOWER BOUND of extra memory allocation if we fuse these 2 nodes:
        1. find all buffers read by each node with a single user. These buffers are supposed to
           be reused if we don't fuses these 2 nodes
        2. find the intersection of these buffers for the two node and sum the total buffer size.
           If we don't fuse these two nodes, we can at lease avoid this much memory allocation.
           Note that the extra memory allocation is not necessarily causing peak memory increase.
           This is just a heuristic.

        We return true only if the saving for fusion can not trade off the extra memory allocation.
        r   )Úbuffer_reuse_keyc                ó0  •— g }| j                   j                  D ]y  }‰j                  j                  |j                  «      }|sŒ+t        |j                  «      dk(  sŒD|j                  j                  «       sŒ_|j                  |j                  «       Œ{ |S rH  )
rÕ   rÖ   r  r±  r×   rÎ   rß  r”   Úhas_tensor_outputrä   )r”   r=  rL  rÞ   rr   s       €rs   Ú_find_single_user_inputszKScheduler.can_fusion_increase_peak_memory.<locals>._find_single_user_inputs|  sw   ø€ ð ˆFØ×&Ñ&×,Ñ,ò ,�Ø×&Ñ&×*Ñ*¨2¯7©7Ó3�Úœ3˜sŸy™y›>¨QÓ.°3·8±8×3MÑ3MÕ3OØ—M‘M #§(¡(Õ+ð,ð ˆMru   c              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   ©r·   rÞ   r±  s     €rs   r¹   z<Scheduler.can_fusion_increase_peak_memory.<locals>.<genexpr>Š  ó   øè ø€ Ò#S¸cÑ$4°S×$9Ñ#Sùr=  c              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   r¶  s     €rs   r¹   z<Scheduler.can_fusion_increase_peak_memory.<locals>.<genexpr>‹  r·  r=  r   rÍ   Fé    T)r”   rf   r�   zlist[ir.Buffer])rþ  r±  r   Úintersectionr‘   rs  r  ra   rÁ   rÂ   Ústatically_known_gt)rr   rˆ   r‰   r´  Úlhs_dep_nodesÚrhs_dep_nodesÚlhs_reuse_keysÚrhs_reuse_keysÚcommon_reuse_keysÚmemory_overheadrä  Ú	bw_savingr±  s   `           @rs   Úcan_fusion_increase_peak_memoryz)Scheduler.can_fusion_increase_peak_memorye  sÝ   ù€ õ* 	6ð	Ø#ð	àõ	ñ 1°Ó7ˆÙ0°Ó7ˆä#Ó#SÀ]Ô#SÓSˆÜ#Ó#SÀ]Ô#SÓSˆà*×7Ñ7¸ÓGÐàˆØ$ò 	ˆCðØ¤3 s¨1¡v£;Ñ.‘ð	ð ×,Ñ,¨U°EÓ:ˆ	ô �7‰7×Ñ×/Ñ/°ÀÀiÁÔPØØøô ò âðús   Á$B8Â8	CÃCc                ó¤  — t        |j                  «       D �cg c]  }|j                  «       ‘Œ c}|j                  «       D �cg c]  }|j                  «       ‘Œ c}z   «      }t        d„ |j                  j                  D «       «      }t        d„ |j                  j
                  D «       «      }||z  }t        «       }	|j                  j                  D ]:  }
| j                  |
j                  |«      sŒ |	j                  |
j                  «       Œ< t        d„ |j                  j
                  D «       «      t        d„ |j                  j
                  D «       «      z  }t        d„ |j                  j                  D «       «      t        d„ |j                  j                  D «       «      z  }||z
  }||	z
  }||z  }t        |«      |kD  S c c}w c c}w )Nc              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zEScheduler.fusion_prevent_too_many_reads_and_writes.<locals>.<genexpr>¬  s   è ø€ Ò&T°C s§x¥xÑ&Tùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zEScheduler.fusion_prevent_too_many_reads_and_writes.<locals>.<genexpr>­  ó   è ø€ Ò%R°3 c§h¥hÑ%Rùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zEScheduler.fusion_prevent_too_many_reads_and_writes.<locals>.<genexpr>º  s   è ø€ ò $
ØˆC�H�Hñ$
ùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zEScheduler.fusion_prevent_too_many_reads_and_writes.<locals>.<genexpr>¼  r>  rv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zEScheduler.fusion_prevent_too_many_reads_and_writes.<locals>.<genexpr>¿  s   è ø€ ò %
ØˆC�H�Hñ%
ùrv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zEScheduler.fusion_prevent_too_many_reads_and_writes.<locals>.<genexpr>Á  s   è ø€ ÒD C�s—x•xÑDùrv  )
r   r»   râ  rÕ   rQ  rÖ   Ú$can_buffer_be_removed_through_fusionr×   r¢  rÎ   )rr   rˆ   r‰   Ú	thresholdr”   Úfused_node_namesÚnode1_write_namesÚnode2_read_namesÚreads_removed_through_fusionÚwrites_removed_through_fusionr‘  Úall_read_namesÚall_write_namesÚunique_readsÚunique_writesÚunique_io_bufferss                   rs   Ú(fusion_prevent_too_many_reads_and_writesz2Scheduler.fusion_prevent_too_many_reads_and_writesž  s±  € ô &Ø).¯©Ó):Ö; ˆT�]‰]�_Ò;Ø+0¯?©?Ó+<Ö= 4ˆt�}‰}�Ò=ñ>ó
Ðô 'Ñ&T¸5×;LÑ;L×;SÑ;SÔ&TÓTÐÜ%Ñ%R¸%×:KÑ:K×:QÑ:QÔ%RÓRÐØ'7Ð:KÑ'KÐ$ô :D»Ð%Ø×*Ñ*×1Ñ1ò 	BˆIØ×8Ñ8Ø—‘Ð 0õð .×1Ñ1°)·.±.ÕAð		Bô $ñ $
Ø %× 1Ñ 1× 7Ñ 7ô$
ó 
äÑC¨5×+<Ñ+<×+BÑ+BÔCÓCñDˆô
 %ñ %
Ø %× 1Ñ 1× 8Ñ 8ô%
ó 
äÑD¨5×+<Ñ+<×+CÑ+CÔDÓDñEˆð
 &Ð(DÑDˆð (Ð*GÑGˆð )¨=Ñ8ÐäÐ$Ó%¨	Ñ1Ð1ùòM <ùÚ=s   ˜GÁG
c                ó¤   — t        t        |j                  |j                  z
  «      t        |j                  |j                  z
  «      «      }|dkD  S )aA  
        This function prevents fusion for nodes that can increase memory
        footprint. This problem is more common in horizontal fusion, where nodes
        that are far apart in the original order get fused, lengthening the live
        intervals of tensors. This is very evident in models with activation
        checkpointing, where the recomputed nodes from different checkpointed
        regions get fused and significantly increase the memory footprint.

        The current attempt is a quick, possibly hacky, heuristic to prevent the
        fusion of nodes that are far away in the original order.

        A better but difficult to implement heuristic would be to use live
        intervals of the buffers, find region of peak pressure in the original
        program and prevent fusion that crosses that peak region. We might need
        special care or good approximation in this implementation, as fusion of
        node changes live intervals, and re-computing live intervals and peak
        memory after each fusion can introduce large compilation overhead.
        é@   )rY  r¶  r%  r&  )rr   rˆ   r‰   Úproximity_scores       rs   Úare_long_distant_nodesz Scheduler.are_long_distant_nodesÎ  sE   € ô* Ü�—‘ %§/¡/Ñ1Ó2Ü�—‘ %§/¡/Ñ1Ó2ó
ˆð  Ñ#Ð#ru   c                óþ  — i }|j                   j                  «       D �ci c]  }|j                  |“Œ }}|j                   j                  «       D �ci c]  }|j                  |“Œ }}|D �]}  }t        j                  j                  |«      }	||   }
||   }t        |
t        «      rt        |t        «      sdt        |
«      › dt        |«      › �||<   Œk|
j                  «       |j                  «       k7  r(d|
j                  «       › d|j                  «       › �||<   Œ´t        |
j                  «      t        |j                  «      k7  rd||<   Œå|
j                  «       }|j                  «       }||k7  rd|› d|› �||<   �Œ|
j                  «       |j                  «       k(  rd|
› d|› �||<   �ŒEd}t        |	t        j                  «      sd|	j                   › �}d	|
› d|› d
|› �||<   �Œ€ t#        |«      S c c}w c c}w )z}
        Try to decide reasons why fusion fail due to no shared memory even though
        there are common buffers.
        znot MemoryDep: r¿   zdifferent numel: Ú	broadcastzdifferent offset: zMismatch loop orders: rX  zLayout: zUnknown reason: z. )rÕ   rw  r×   ra   rÁ   rI  r²   r9   r«   rð   r_   rÜ   Ú
get_offsetÚnormalize_with_stride_orderr0   rL  rí  r,  )rr   rˆ   r‰   Úcommon_buf_namesÚreasonsrà   Únode1_name2depÚnode2_name2deprÖ  rÞ   Úlhs_depÚrhs_depÚlhs_offÚrhs_offÚ
layout_strs                  rs   Údecide_fusion_fail_reasonz#Scheduler.decide_fusion_fail_reasoné  s  € ð ˆØ38×3DÑ3D×3UÑ3UÓ3WÖX¨C˜#Ÿ(™( C™-ÐXˆÐXØ38×3DÑ3D×3UÑ3UÓ3WÖX¨C˜#Ÿ(™( C™-ÐXˆÐXà(ó ,	ˆHÜ—'‘'×$Ñ$ XÓ.ˆCØ$ XÑ.ˆGØ$ XÑ.ˆGä˜g¤yÔ1¼ÀGÌYÔ9Wà%¤d¨7£m _°F¼4À»=¸/ÐJð ˜Ñ!ð à× Ñ Ó" g×&7Ñ&7Ó&9Ò9à'¨×(9Ñ(9Ó(;Ð'<¸FÀ7×CTÑCTÓCVÐBWÐXð ˜Ñ!ð ô ˜WŸ\™\Ó*¬m¸G¿L¹LÓ.IÒIØ$/�˜Ñ!Øà×(Ñ(Ó*ˆGØ×(Ñ(Ó*ˆGØ˜'Ò!ð '9¸¸	ÀÈÀyÐ$Q�˜Ñ!Ùð ×3Ñ3Ó5Ø×6Ñ6Ó8ò9ð '=¸W¸IÀVÈGÈ9Ð$U�˜Ñ!Ùð ˆJÜ˜c¤2×#5Ñ#5Ô6Ø'¨¯
©
 |Ð4�
à" 7 )¨6°'°¸"¸Z¸LÐIð �HÓðU,	ô\ �7‹|Ðùòc YùÚXs   ŸG5ÁG:c                ó´  — t         j                  syt        d„ ||fD «       «      ry|j                  j	                  «       }|j                  j	                  «       }||z  }|syt        d„ |j                  D «       «      }||z
  ryt        |«      dkD  ryt        |j                  j                  «      dkD  s"t        |j                  j                  «      dkD  ryt        t        |j                  j                  «      «      }t        t        |j                  j                  «      «      }t        |t        «      rt        |t        «      sy|j                  j                  D �	ci c]  }	|	j                  |	“Œ }
}	|j                  |
vry|
|j                     }t        |t        «      sy|j                  «       }|j                   |j                   k7  r|j"                  |j"                  k7  ry|j"                  |j"                  k7  st        |j$                  «      dk7  ryt        |j&                  j(                  «      dk7  ry|j&                  j*                  ryd|j&                  j(                  v rd|j&                  j(                  v sJ ‚t        d„ |j&                  j-                  «       D «       «      }t        |«      dk7  ryt        t        |«      «      }||j&                  j(                  d   k(  rd}d}n"||j&                  j(                  d   k(  sJ ‚d}d}d	d
lm} |j&                  j2                  d	   }t        |«      dk7  ryg }t4        j6                  j9                  |«      D ]:  }|j;                  t<        j>                  j@                  jC                  |«      «       Œ< tE        |«      } |||d	   «      }|€y|j&                  j(                  |   |j&                  j(                  |<   ||j&                  j(                  |<   |jG                  dd«       | jI                  ||«      }t        |tJ        «      sJ ‚tL        jO                  d|«       |S c c}	w )aW  
        Attempts to enable fusion between two nodes by inverting indexing patterns.

        This optimization targets cases where node1 has a contiguous write and
        node2 has a contiguous write but discontiguous read. By inverting the
        indexing in node2's read and write operations, we can make them compatible
        with node1 for potential fusion.

        Args:
            node1: First scheduler node (source)
            node2: Second scheduler node (target for inversion)

        Returns:
            int: Fusion score if successful, 0 if optimization not applicable
        r  c              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   ©rÞ  rÌ  s     rs   r¹   zAScheduler.shared_data_after_inverting_indexing.<locals>.<genexpr>=  ó   è ø€ Ò2˜aˆq�x‰x�zÑ2ùrÃ  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zAScheduler.shared_data_after_inverting_indexing.<locals>.<genexpr>I  s   è ø€ ò .
ØˆC�H�Hñ.
ùrv  r   rÍ   Úindex0Úindex1c              3  ó    K  — | ]  }|–— Œ y ­wr~   r…   )r·   ra  s     rs   r¹   zAScheduler.shared_data_after_inverting_indexing.<locals>.<genexpr>„  s   è ø€ Ò%T¨t¤dÑ%Tùs   ‚r   )Úgenerate_inverse_formulaTFz!Shared memory after inversion: %d)(r-   rl  r  rÕ   Úbuffer_namesr   r3  rÎ   rÖ   rQ  r‘  r�  r²   r9   r×   r   rØ   rÜ   Ú	var_namesr  r   Ú	subblocksÚget_read_exprsÚ$torch._inductor.invert_expr_analysisró  Úvarsr  ÚAddÚ	make_argsrä   ra   rÁ   rÂ   Úcombine_modular_indexing_pairsrü   r3  r  r‘   rÜ  rj  )rr   rˆ   r‰   Únode1_buffer_namesÚnode2_buffer_namesÚcommon_buffer_namesÚnode2_unmet_dependenciesÚ
node2_readÚnode2_writerà   Únode1_writesÚnode1_writeÚnode2_read_exprsÚ	read_exprÚread_expr_indexÚwrite_expr_indexró  rt  Úsimplified_termsÚtermÚsimplified_read_exprÚinverse_formulaÚscores                          rs   Ú$shared_data_after_inverting_indexingz.Scheduler.shared_data_after_inverting_indexing'  só  € ô& ×4Ò4ØäÑ2 E¨5 >Ô2Ô2Øð #×.Ñ.×;Ñ;Ó=ÐØ"×.Ñ.×;Ñ;Ó=ÐØ0Ð3EÑEÐá"Øô $.ñ .
Ø %× 8Ñ 8ô.
ó $
Ð ð $Ð&8Ò8ØäÐ'Ó(¨1Ò,Øô ˆu× Ñ ×&Ñ&Ó'¨!Ò+¬s°5×3DÑ3D×3KÑ3KÓ/LÈqÒ/PØäœ$˜u×0Ñ0×6Ñ6Ó7Ó8ˆ
Üœ4 × 1Ñ 1× 8Ñ 8Ó9Ó:ˆä˜*¤iÔ0¼
Øœô9
ð à16×1BÑ1B×1IÑ1IÖJ¨#˜Ÿ™ #™ÐJˆÐJØ�?‰? ,Ñ.Øà" :§?¡?Ñ3ˆä˜+¤yÔ1Øð "×+Ñ+Ó-ˆð ×Ñ ×!2Ñ!2Ò2Ø× Ñ  K×$4Ñ$4Ò4àà�?‰?˜k×.Ñ.Ò.´#°j×6JÑ6JÓ2KÈqÒ2PØô ˆu�{‰{×)Ñ)Ó*¨aÒ/Øð �;‰;× Ò Øð ˜Ÿ™×2Ñ2Ñ2Ø˜EŸK™K×6Ñ6Ñ6ð	
ð7ô
 &Ñ%T°u·{±{×7QÑ7QÓ7SÔ%TÓTÐÜÐÓ  AÒ%ØäœÐ.Ó/Ó0ˆ	ð ˜Ÿ™×2Ñ2°8Ñ<Ò<Ø&ˆOØ'Ñà §¡× :Ñ :¸8Ñ DÒDÐDÐDØ&ˆOØ'ÐåQà—[‘[×%Ñ% aÑ(ˆ
Üˆz‹?˜aÒØàÐÜ—I‘I×'Ñ'¨	Ó2ò 	ˆDØ×#Ñ#Ü—‘× Ñ ×?Ñ?ÀÓEõð	ô  #Ð#3Ó4Ðá2Ð3GÈÐTUÉÓWˆð Ð"Øð
 7<·k±k×6PÑ6PØñ7
ˆ�‰×"Ñ" ?Ñ3ð 8Gˆ�‰×"Ñ"Ð#3Ñ4ð 	×"Ñ" 4¨Ô/Ø×(Ñ(¨°Ó6ˆÜ˜%¤Ô%Ð%Ð%ä�‰Ð;¸UÔCØˆùòm Ks   Å"Qc                óì  — t        d„ ||fD «       «      ry|j                  «       s|j                  «       ry|j                  j                  «       |j                  j                  «       z  }|syt        j
                  r| j                  ||«      }|dk\  r|S t        j                  r| j                  ||«      syt        j
                  r| j                  ||«      }|dk\  r|S | j                  ||«      S )a«  
        Right now just greedily reorder the loop of node1 to be compatible with node2,
        but ideally we should have some heuristics to reorder the loop for node2
        to be compatible with node1 if that's more efficient.

        Return the amount of shared data re-computed in this method.
        If no such recomputation happens, return -1 (not return 0 since 0 is a valid
        amount of shared data).

        c              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   rí  rÌ  s     rs   r¹   z>Scheduler.shared_data_after_reordering_loop.<locals>.<genexpr>Æ  rî  rÃ  r  r   )
r  rç  rÕ   rô  r-   r%  Ú!_try_reorder_loops_for_candidatesÚloop_reindexing_after_fusionÚ$_try_reindex_pointwise_for_reductionr  )rr   rˆ   r‰   rÿ  r	  s        rs   Ú!shared_data_after_reordering_loopz+Scheduler.shared_data_after_reordering_loop¶  sé   € ô  Ñ2 E¨5 >Ô2Ô2Øð
 ×ÑÔ %×"3Ñ"3Ô"5Øð ×Ñ×*Ñ*Ó,¨u×/@Ñ/@×/MÑ/MÓ/OÑOð 	ñ #Øä×,Ò,Ø×:Ñ:¸5À%ÓHˆEØ˜ŠzØ�ô ×3Ò3Ø×<Ñ<¸UÀEÔJàä×,Ò,Ø×:Ñ:¸5À%ÓHˆEØ˜ŠzØ�à×'Ñ'¨¨uÓ5Ð5ru   c                ó”  ‡‡— |j                   j                  «       |j                   j                  «       z  }|j                   j                  D �ci c]  }|j                  |“Œ }}|j                   j                  D �ci c]  }|j                  |“Œ }}|j                   j                  D �ci c]  }|j                  |“Œ }}|j                   j                  D �ci c]  }|j                  |“Œ }}g }	|D �]‹  }
|j                  |
«      xs ||
   }|j                  |
«      xs ||
   }|
|v xr |
|v xs
 |
|v xr |
|v }|j                  «       |j                  «       k(  rM|	j                  |t        j                  j                  j                  |j                  «       d¬«      ||f«       Œ¸|sŒ»|j                  |
«      xs |j                  |
«      }|j                  |
«      xs |j                  |
«      }t        |t        «      s�Œt        |t        «      s�Œ't        j                  j                  Š|j                  «       j                   }|j                  «       j                   Št#        ˆˆfd„|D «       «      r�ŒŒ y t%        |	«      dk(  ryt'        |	t)        j*                  dd«      ¬«      \  }}}}t        |t        «      rt        |t        «      sy|j,                  |j,                  k7  r3|j                  «       |j                  «       k(  r| j/                  |«      S yd}|j1                  «       s|j3                  ||«      }nV|j1                  «       s|j3                  ||«      }n3t4        j7                  d|j9                  «       |j9                  «       «       |r| j;                  ||«      S dS c c}w c c}w c c}w c c}w )	z–
        Find common buffers with matching normalized stride order but different
        loop orders, and try to reorder loops to align them.
        r   rí   c              3  óJ   •‡K  — | ]  Št        ˆˆfd „‰D «       «      –— Œ y­w)c              3  óB   •K  — | ]  }‰j                  ‰|«      –— Œ y ­wr~   )rÅ   )r·   ÚrsÚsvÚwss     €€rs   r¹   zHScheduler._try_reorder_loops_for_candidates.<locals>.<genexpr>.<genexpr>%  s   øè ø€ ÒQÀ2˜B×6Ñ6°r¸2×>ÑQùr‘  Nr¯  )r·   r	  Úr_sizesr	  s    @€€rs   r¹   z>Scheduler._try_reorder_loops_for_candidates.<locals>.<genexpr>$  s$   ùè ø€ ò àô ÔQÈÔQ×Qñùs   „#r  r   rã  Fz?Don't reorder loops since both nodes are reductions: %s v.s. %s)rÕ   rô  rÖ   r×   rQ  r±  rà  rä   ra   rÁ   rÂ   rï   rð   r²   r9   r   rÜ   rº   rÎ   rY  r  r  r^  Údep_size_hintr´   rp  ra  rÝ  râ  r  )rr   rˆ   r‰   rÿ  rà   Únode1_readsr	  Únode2_readsÚnode2_writesÚ
candidatesr  rå  ræ  Úis_write_readÚwrR  Úw_sizesÚ_is_wrÚ_numelÚ	reorderedr	  r	  s                       @@rs   r	  z+Scheduler._try_reorder_loops_for_candidatesï  s{  ù€ ð ×Ñ×*Ñ*Ó,¨u×/@Ñ/@×/MÑ/MÓ/OÑOð 	ð 16×0AÑ0A×0GÑ0GÖH¨�s—x‘x ‘}ÐHˆÐHØ16×1BÑ1B×1IÑ1IÖJ¨#˜Ÿ™ #™ÐJˆÐJØ05×0AÑ0A×0GÑ0GÖH¨�s—x‘x ‘}ÐHˆÐHØ16×1BÑ1B×1IÑ1IÖJ¨#˜Ÿ™ #™ÐJˆÐJàˆ
Ø.ó '	"ˆKØ"×&Ñ& {Ó3ÒO°{À;Ñ7OˆGØ"×&Ñ& {Ó3ÒO°{À;Ñ7OˆGð ˜|Ð+ÒJ°¸{Ð0JòNà Ð-ÒL°+ÀÐ2Lð ð
 ×3Ñ3Ó5Ø×6Ñ6Ó8ò9ð ×!Ñ!à%ÜŸ™×(Ñ(×:Ñ:Ø#×-Ñ-Ó/¸!ð ;ó ð  Øðõ	ò ð !×$Ñ$ [Ó1ÒR°\×5EÑ5EÀkÓ5R�Ø—O‘O KÓ0ÒP°K·O±OÀKÓ4P�Ü˜a¤Ö+´
¸1¼iÖ0HÜŸ™×)Ñ)�BØŸk™k›m×0Ñ0�GØŸk™k›m×0Ñ0�GÜô à")ôö ñ  "ðO'	"ôR ˆz‹?˜aÒØô ,/ØœH×/Ñ/°°1Ó5ô,
Ñ(ˆ�˜ ô ˜'¤9Ô-´ZÀÌÔ5SØà×Ñ˜w×/Ñ/Ò/ð
 × Ñ Ó" g×&7Ñ&7Ó&9Ò9Ø×)Ñ)¨'Ó2Ð2Øàˆ	à×!Ñ!Ô#Ø×7Ñ7¸ÀÓI‰IØ×#Ñ#Ô%Ø×7Ñ7¸ÀÓI‰Iä×#Ñ#ØQØ—‘Ó Ø—‘Ó ôñ :Cˆt×'Ñ'¨¨uÓ5ÐJÈÐJùòc IùÚJùÚHùÚJs   ÁN6Á>N;Â,O ÃOc                óÊ  ‡ ‡‡‡‡‡‡‡— ddl mŠ |j                  «       s|j                  «       ry|j                  «       r|j                  «       s||}}n&|j                  «       r|j                  «       s||}}ny|j                  \  }}t        j                  t        j                  |d   «      Št        j                  t        j                  |d   «      Š‰‰z  Št        d„ |j                  «       D «       «      syt        j                  t        t           |j                  «       «      }t        ˆfd„|D «       «      syt        ˆˆˆfd„|D «       «      sy‰‰fŠt        ˆfd„|D «       «      ryt        j                  |f«      }|D ]  }	|	j                  ‰‰g«       Œ t!        |t"        «      r|d   j                  |_        t%        |«       |j&                  j)                  «       |j&                  j)                  «       z  }
|j&                  j+                  «       D �ci c]  }|j,                  |“Œ c}Š|j&                  j+                  «       D �ci c]  }|j,                  |“Œ c}Št/        ˆˆˆ fd	„|
D «       «      }|s|j1                  «        yt2        j4                  s5|D ]  }	|	j7                  d
d¬«       Œ t!        |t"        «      rt%        |«       y
c c}w c c}w )zÿ
        Reindex a pointwise's iteration loops to match a reduction's
        groups. After reindexing, the shared reads have identical index
        expressions, enabling the codegen to CSE loads.

        Returns True if reindexing was applied.
        r   r  Fr   c              3  ó<   K  — | ]  }t        |t        «      –— Œ y ­wr~   ©r²   r³   )r·   r^  s     rs   r¹   zAScheduler._try_reindex_pointwise_for_reduction.<locals>.<genexpr>m  s   è ø€ ÒO°R”:˜b¤-×0ÑOùrÃ  c              3  óž   •K  — | ]D  }t         j                  j                  j                  t	        |j
                  d    «      ‰«      –— ŒF y­wr¯  )ra   rÁ   rÂ   rÅ   r_   r  )r·   r^  Útarget_numels     €rs   r¹   zAScheduler._try_reindex_pointwise_for_reduction.<locals>.<genexpr>s  sB   øè ø€ ò 
ð ô �G‰G×Ñ×4Ñ4Ü˜bŸi™i¨™lÓ+¨\÷ñ
ùs   ƒA
Ac              3  ób   •K  — | ]&  }‰j                  ‰‰f|j                  «       «      –— Œ( y ­wr~   )r‚  r\  )r·   r^  r€  Ú	red_numelÚ
red_rnumels     €€€rs   r¹   zAScheduler._try_reindex_pointwise_for_reduction.<locals>.<genexpr>{  s1   øè ø€ ò 
àð ×$Ñ$ i°Ð%<¸b¿m¹m»o×Nñ
ùs   ƒ,/c              3  óT   •K  — | ]  }t        |j                  d    «      ‰k(  –— Œ! y­wr¯  )rÏ   r  )r·   r^  Útarget_iter_sizess     €rs   r¹   zAScheduler._try_reindex_pointwise_for_reduction.<locals>.<genexpr>ƒ  s$   øè ø€ ÒI¸BŒu�R—Y‘Y˜q‘\Ó"Ð&7Õ7ÑIùs   ƒ%(c              3  óN   •K  — | ]  }‰j                  ‰|   ‰|   «      –— Œ y ­wr~   )Údeps_match_normalized)r·   r×   Ún1_depsÚn2_depsrr   s     €€€rs   r¹   zAScheduler._try_reindex_pointwise_for_reduction.<locals>.<genexpr>™  s.   øè ø€ ò 
àð ×&Ñ& w¨t¡}°g¸d±m×Dñ
ùs   ƒ"%TrA  )r�  r€  rÞ  r´   rÆ   r»  r¼  r  ra  rº   r»   r¥   r³   r/  r›  rI  r²   rÚ   rª  rÕ   rô  rw  r×   r  r<  r-   r%  r3  )rr   rˆ   r‰   Úreduction_nodeÚpw_noder=  ÚgroupsrÛ   Úrollback_snapshotr^  Úcommon_namesrà   Úhas_benefitr€  r3	  r4	  r-	  r.	  r0	  r+	  s   `            @@@@@@@rs   r	  z.Scheduler._try_reindex_pointwise_for_reductionN  sŠ  ÿ€ õ 	-ð �<‰<Œ>˜UŸ\™\œ^Øà×ÑÔ¨×(:Ñ(:Ô(<Ø&+¨U˜G‰NØ×ÑÔ!¨%×*<Ñ*<Ô*>Ø&+¨U˜G‰Nàà"×(Ñ(‰	ˆˆ6Ü—K‘K¤§
¡
¨F°1©IÓ6ˆ	Ü—[‘[¤§¡¨V°A©YÓ7ˆ
Ø  :Ñ-ˆäÑO¸7×;LÑ;LÓ;NÔOÔOØÜ—‘œT¤-Ñ0°'×2CÑ2CÓ2EÓFˆô ó 
ð ô	
ô 
ð äõ 
àô
ô 
ð ð '¨
Ð3ÐÜÓIÀ&ÔIÔIØô /×5Ñ5°w°jÓAÐàò 	>ˆBØ×$Ñ$ i°Ð%<Õ=ð	>ô �gÔ1Ô2Ø" 1™IŸO™OˆGŒMÜ+¨GÔ4ð ×Ñ×*Ñ*Ó,¨u×/@Ñ/@×/MÑ/MÓ/OÑOð 	ð -2×,=Ñ,=×,NÑ,NÓ,PÖQ S�3—8‘8˜S‘=ÒQˆØ,1×,=Ñ,=×,NÑ,NÓ,PÖQ S�3—8‘8˜S‘=ÒQˆÜõ 
à$ô
ó 
ˆñ Ø×%Ñ%Ô'Øô ×0Ò0Øò W�Ø×'Ñ'°$ÐPUÐ'ÕVðWä˜'Ô#5Ô6Ü/°Ô8àùò+ RùÚQs   È"KÉK c                óf  — t        |t        «      r)|j                  «        xr t        |j                  «       S t        |t
        «      rht        |j                  t        j                  «      r|j                  j                  «        S |j                  «        xr t        |j                  «       S y)z>
        Is this node unfusable under any conditions.
        F)	r²   r  rç  r]   r”   rR  r0   rÿ  r   rì  s     rs   rœ  zScheduler.unfusable_node®  s¥   € ô �dÔ2Ô3Ø×'Ñ'Ó)Ð)ò Ô2UØ—	‘	ó3ð /ð ô �dÔ5Ô6Ü˜$Ÿ)™)¤R×%?Ñ%?Ô@ØŸ9™9×6Ñ6Ó8Ð8Ð8Ø×'Ñ'Ó)Ð)ò Ô2UØ—	‘	ó3ð /ð ð ru   c                ó  — |j                  «       t        j                  j                  k  ry|j	                  «       }|j                  «       }d}|||z  kD  r	 |d«       yt        d„ |j                  «       D «       «      }|t        j                  j                  j                  j                  fk(  r	 |d«       yd	d„}|j                  «       }	|	j                  «       s+ ||	j                  «      r|j!                  «       s	 |d«       yy)
zT
        Heuristics to avoid benchmarking predictably slow prologue fusions
        Tgš™™™™™ñ?z@prologue fusion will not increase amount of bytes read in kernelFc              3  ó¨   K  — | ]J  }|j                   �<|j                   j                  «       D ]  }|j                  dk(  r|j                  –— Œ! ŒL y ­w)NÚcall_function)r”   r  rã  r  )r·   rÍ  r&  s      rs   r¹   zEScheduler.check_prologue_fusion_heuristics_fusable.<locals>.<genexpr>Þ  sT   è ø€ ò 
àØ�v‰vÐ!Ø—V‘V×'Ñ'Ó)ò	
ð Ø�t‰t�Ò&ð	 �H�Hð
Øñ
ùs   ‚AAz\prologue fusion will not increase attempt to fuse in padding bc it increases unaligned readsc                ó<   — | j                   dk  xr | j                  S )NrÍ   )ÚitemsizeÚis_floating_point)r}  s    rs   Úlow_prec_fpzGScheduler.check_prologue_fusion_heuristics_fusable.<locals>.low_prec_fpë  s   € Ø—>‘> QÑ&ÒB¨5×+BÑ+BÐBru   zVprologue fusion that must be upcast to fp32 not profitable for low precision templates)r}  ztorch.dtyper�   r}   )r  ra   rÁ   Úinvoke_quant_opsr1  r3  rÏ   r»   r`  r&  ÚatenÚconstant_pad_ndr)  rŒ  r\   r}  rÐ  )
rr   Úprologue_noder•  rS  Ú
read_bytesÚwrite_bytesÚBYTES_THRESHOLD_MULTIPLIERr$  rB	  r  s
             rs   Ú(check_prologue_fusion_heuristics_fusablez2Scheduler.check_prologue_fusion_heuristics_fusable¾  s  € ð ×,Ñ,Ó.´!·'±'×2JÑ2JÒJØà"×8Ñ8Ó:ˆ
Ø#×:Ñ:Ó<ˆð &)Ð"Ø˜Ð'AÑAÒBÙÐRÔSØô ñ 
à"×,Ñ,Ó.ô
ó 
ˆð ”u—y‘y—~‘~×5Ñ5×=Ñ=Ð?Ò?ÙØnôð ó	Cð %×?Ñ?ÓAˆà×6Ñ6Ô8Ù˜L×.Ñ.Ô/Ø!×>Ñ>Ô@áØhôð àru   c                ó<  ‡ — t        |t        «      rt        |t        «      syt        |j                  t        j                  «      r$t        |j                  t        j                  «      sy|j                  «       s|j                  «       ryt        j                  dk(  ry|j                  |j                  }}|\  }}|\  }}|j                  «       s,|j                  «       s||k7  st        |«      t        |«      k7  ryt        |j                  j                  «      dkD  s"t        |j                  j                  «      dkD  ry‰ j                  t        t        |j                  j                  «      «      «      }	‰ j                  t        t        |j                  j                  «      «      «      }
t!        |	|
«      t        j"                  kD  rydˆ fd„} ||«      s ||«      ryg }t%        t'        ||«      «      D ]  \  }\  }}||k7  sŒ|j)                  |«       Œ! t        |«      dk7  ry|d   }||   ||   }}t*        j,                  j.                  j1                  ||«      r|||fS t*        j,                  j.                  j1                  ||«      r|||fS y)ao  
        Fusing two small pointwise nodes significantly reduces kernel overhead
        and launch overhead. However, slightly different sizes would prevent fusion.
        Here, we decide if expanding sizes of one node is profitible by allowing
        fusion, and returns the dimension to expand, node with smaller sizes,
        and new size after expand.
        Nrg  r   c                ó~  •— | j                   j                  D ]£  }|j                  ‰j                  v r‰j                  |j                     }n%‰j                  j                  |j                  «      }|sŒ]t        j                  j                  j                  || «      sŒˆt        |j                  t        «      rŒ£ y yr  )rÕ   rÖ   r×   r  r  r±  ra   rÁ   rÿ  r  r²   rÝ  r  )r”   r  r  rr   s      €rs   Úhas_reusable_bufferzIScheduler.get_expand_dim_for_pointwise_nodes.<locals>.has_reusable_buffer5  s–   ø€ Ø×(Ñ(×.Ñ.ò  �à—9‘9 × ;Ñ ;Ñ;Ø $× ;Ñ ;¸D¿I¹IÑ F‘Ià $× 0Ñ 0× 4Ñ 4°T·Y±YÓ ?�Iò ÜŸ™×,Ñ,×6Ñ6°yÀ$ÕGÜ& y×'<Ñ'<Ô>TÕUáð ð ru   r   r*  )r²   r³   r”   r0   r   rƒ  r-   rh  r  r´   rÎ   rÕ   rQ  r	  r‘  r�  rY  Úsmall_memory_access_thresholdr’  ry  rä   ra   rÁ   rÂ   Ústatically_known_lt)rr   rˆ   r‰   Ún1_sizesÚn2_sizesÚn1_iter_sizesÚn1_reduce_sizesÚn2_iter_sizesÚn2_reduce_sizesÚnode1_write_memoryÚnode2_write_memoryrM	  Úmismatch_dimensionsrI  Ún1_sizeÚn2_sizeÚmismatch_dimÚmismatch_size1Úmismatch_size2s   `                  rs   Ú"get_expand_dim_for_pointwise_nodesz,Scheduler.get_expand_dim_for_pointwise_nodesû  s]  ø€ ô ˜%¤Ô/´zÀ%ÌÔ7WØô �u—z‘z¤2×#4Ñ#4Ô5Ü˜5Ÿ:™:¤r×'8Ñ'8Ô9àð ×)Ñ)Ô+¨u×/MÑ/MÔ/OØô ×Ñ Ò)Øð #Ÿ\™\¨5¯<©<�(ˆØ)1Ñ&ˆ�Ø)1Ñ&ˆ�à×ÑÔ Ø×!Ñ!Ô#Ø /Ò1Ü�=Ó!¤S¨Ó%7Ò7àô ˆu× Ñ ×'Ñ'Ó(¨1Ò,´°E×4EÑ4E×4LÑ4LÓ0MÐPQÒ0QØð "×/Ñ/´´T¸%×:KÑ:K×:RÑ:RÓ5SÓ0TÓUÐØ!×/Ñ/´´T¸%×:KÑ:K×:RÑ:RÓ5SÓ0TÓUÐäÐ"Ð$6Ó7Ü×2Ñ2ò3ð õ	ñ  ˜uÔ%Ñ)<¸UÔ)CØð !ÐÜ'0´°]ÀMÓ1RÓ'Sò 	0Ñ#ˆCÑ#�'˜7Ø˜'Ó!Ø#×*Ñ*¨3Õ/ð	0ô Ð"Ó# qÒ(Øà*¨1Ñ-ˆà˜,Ñ'Ø˜,Ñ'ð 'ˆô �7‰7×Ñ×/Ñ/°ÀÔOØ ¨Ð6Ð6Ü�W‰W×Ñ×1Ñ1°.À.ÔQØ ¨Ð6Ð6àru   c                ó    ‡ ‡‡— t        ˆ fd„|j                  «       D «       «      Št        ˆˆˆ fd„|j                  j                  D «       «      S )Nc              3  óV   •K  — | ]   }‰j                   j                  ||«      –— Œ" y ­wr~   ©r)  r±  ©r·   r×   rr   s     €rs   r¹   zDScheduler._producer_output_names_read_by_consumer.<locals>.<genexpr>`  s,   øè ø€ ò (
àð ×!Ñ!×%Ñ% d¨D×1ñ(
ùr  c              3  óŠ   •K  — | ]:  }‰j                   j                  |j                  |j                  «      xŠ‰v r‰–— Œ< y ­wr~   ©r)  r±  r×   )r·   rà   r×   Úproducer_buf_namesrr   s     €€€rs   r¹   zDScheduler._producer_output_names_read_by_consumer.<locals>.<genexpr>d  sD   øè ø€ ò 
àØ×-Ñ-×1Ñ1°#·(±(¸C¿H¹HÓEÐE�Ø!ñ"ô ñ
ùs   ƒA A)r   rÇ  rÕ   rÖ   )rr   rE  rJ  r×   re	  s   `  @@rs   Ú'_producer_output_names_read_by_consumerz1Scheduler._producer_output_names_read_by_consumer]  sN   ú€ ô (ó (
à ×1Ñ1Ó3ô(
ó 
Ðô õ 
à×+Ñ+×1Ñ1ô
ó 
ð 	
ru   c                ó‚   — t         j                  ||«      sy t         j                  ||«      sy | j                  ||«      S r~   )r2  r@  r  rf	  rÚ  s      rs   Ú"_nested_index_equivalent_dep_namesz,Scheduler._nested_index_equivalent_dep_namesk  s?   € ô
 ×+Ñ+¨E°5Ô9Øô ×'Ñ'¨¨uÔ5ØØ×;Ñ;¸EÀ5ÓIÐIru   c               óH  ‡ ‡	— t        «       }t        ˆ fd„|j                  «       D «       «      Š	|D ][  \  }}|t        j                  j                  urŒ#ˆ fd„|j
                  j                  D «       }|j                  ˆ	fd„|D «       «       Œ] ‰ j                  ||||¬«      S )Nc              3  óV   •K  — | ]   }‰j                   j                  ||«      –— Œ" y ­wr~   ra	  rb	  s     €rs   r¹   z>Scheduler._can_fuse_nested_reduction_append.<locals>.<genexpr>‡  s,   øè ø€ ò '
àð ×!Ñ!×%Ñ% d¨D×1ñ'
ùr  c              3  ó~   •K  — | ]4  }‰j                   j                  |j                  |j                  «      –— Œ6 y ­wr~   rd	  r©  s     €rs   r¹   z>Scheduler._can_fuse_nested_reduction_append.<locals>.<genexpr>Ž  s4   øè ø€ ò àð ×%Ñ%×)Ñ)¨#¯(©(°C·H±H×=ñùs   ƒ:=c              3  ó,   •K  — | ]  }|‰v sŒ|–— Œ y ­wr~   r…   )r·   Údep_nameÚgrouped_buf_namess     €rs   r¹   z>Scheduler._can_fuse_nested_reduction_append.<locals>.<genexpr>’  s   øè ø€ ò .Ø%°(Ð>OÒ2O”ñ.ùs   ƒ	�)r%  Úindex_equivalent_dep_names)	r   rÇ  r2  rH  rG  rÕ   rÖ   rÝ  Ú	_can_fuse)
rr   r7  r  ri  r%  ro	  r^  ry  rÖ   rn	  s
   `        @rs   r&  z+Scheduler._can_fuse_nested_reduction_append|  sµ   ù€ ô 7A³lÐ"Ü&ó '
à$×5Ñ5Ó7ô'
ó 
Ðð ,ò 		‰JˆB�Øœ_×<Ñ<×HÑHÑHØóàŸ>™>×/Ñ/ôˆEð '×-Ñ-ó .Ø).ô.õ ð		ð �~‰~ØØØ#Ø'Að	 ó 
ð 	
ru   Fc                ó„   — t         j                  ||f«      }| j                  ||||¬«      }|j                  | ¬«       |S )zÛDetermine if node1 and node2 can be combined into a single fused node.

        Speculative loop mutations (reordering, reindexing) are automatically
        rolled back if the fusion decision ultimately fails.
        ©r%  r  )rJ  )r@  r›  Ú_can_fuse_implrK  )rr   rˆ   r‰   r%  r  rE  r  s          rs   r  zScheduler.can_fuseŸ  sP   € ô '×-Ñ-¨u°e¨nÓ=ˆØ×&Ñ&ØØØ#Ø&?ð	 'ó 
ˆð 	�‰ H ˆÔ-Øˆru   c                ó,   — | j                  ||||¬«      S )zj
        Determine if it is possible to combine node1 and node2 into a
        single fused node.
        rr	  )rp	  )rr   rˆ   r‰   r%  r  s        rs   rs	  zScheduler._can_fuse_implµ  s&   € ð �~‰~ØØØ#Ø&?ð	 ó 
ð 	
ru   c                ó  ‡ ‡‡‡!‡"‡#— ‰‰u ry|�t        ˆ fd„|D «       «      }‰ j                  «       r@‰ j                  j                  ‰«      }‰ j                  j                  ‰«      }|�|�||k7  ryt	        ‰t
        «      r‰j                  ‰|¬«      S t	        ‰t
        «      ryt	        ‰t        «      r‰j                  ‰«      S t	        ‰t        «      ryt        ‰‰«      }‰j                  «       r0‰ j                  ‰j                  «       «      j                  ‰‰«      ryt	        ‰t        «      st	        ‰t        «      r	 |d«       yt	        ‰t        «      r‰j                  «       s	 |d«       yt	        ‰t        «      �r¥t	        ‰j                   t"        j$                  «      s	 |d«       y‰j                   j'                  «       s	 |d«       yt	        ‰t(        «      s	 |d	«       yt	        ‰j                   t*        «      s	 |d
«       yt	        ‰j                   j,                  t.        «      s	 |d«       yt1        ‰j                   j2                  «      dk(  sJ ‚‰j                   j2                  d   j4                  Š#t7        ˆ#fd„‰j8                  j:                  D «       «      r	 |d«       y‰j                   j,                  j=                  «       }	|	D ];  }
‰j                   j,                  j?                  |
«      }t7        d„ |D «       «      sŒ; y t1        ‰j                   j@                  «      dk(  sJ ‚‰j                   j@                  d   jB                  }‰j                   jB                  }t	        |t"        jD                  «      rt	        |t"        jD                  «      sJ ‚|jF                  |jF                  k7  s2|jH                  |jH                  k7  s|jJ                  |jJ                  k7  r	 |d«       y	 	 d'ˆˆˆ#fd„Š!t7        ˆ!fd„‰ jL                  D «       «      ryt	        ‰t        t        f«      r‰j                  «       s	 |d«       y‰jO                  «       ‰jP                  z  r	 |d«       y‰j                  «       �rtS        ‰«      s	 |d«       y‰jU                  «       s‰j                  «       r	 |d«       y‰jW                  «       }|jY                  «       }|s	 |d«       yt        d„ |jZ                  D «       «      |z
  }‰j]                  «       |z  r	 |d«       y‰j_                  «       s|ja                  ‰«      r	 |d«       y‰jc                  «       Š"‰"d d D ]B  }|je                  «       }|D ]+  }tg        ˆ"fd„|jh                  D «       «      rŒ" |d«         y ŒD t	        ‰tj        «      s‰gn*‰jl                  D �cg c]  }|j                  «       sŒ|‘Œ c}}t1        |«      dk(  sJ ‚|d   }t1        ‰"d   jn                  «      dk(  rSt1        ‰"d   jn                  d   jh                  «      dk(  r+‰"d   jn                  d   jh                  d   j                   |u s	 |d«       y‰ jq                  ‰‰|«      sy‰j                  «       r“ts        ‰‰«      }‰j_                  «       r|r‰jU                  «       stu        ‰«      s	 |d «       y‰jw                  «       }|€J ‚|jy                  «       r-t	        ‰j                   t"        j*                  «      s	 |d!«       y‰j]                  «       tz        j|                  j~                  z  s+‰j]                  «       tz        j|                  j~                  z  r	 |d"«       y‰j                  «       }‰j                  «       }||k7  r |d#||«       y~|€‰ j�                  ‰‰«      }‰ jƒ                  ‰‰||¬$«      }|rL|t„        j†                  k  r9t„        jˆ                  st„        jŠ                  r‰ j�                  ‰‰«      }|dk\  r|}t„        jŽ                  r@‰ j‘                  ‰‰«      x}r,|\  }}} |j“                  || «       ‰ jƒ                  ‰‰|¬%«      }t„        j”                  r,|t„        j†                  k  r‰ j—                  ‰‰«      }|dk\  r|}t˜        j›                  tœ        jž                  «      r4t˜        j¡                  d&‰j£                  «       ‰j£                  «       |«       tz        j¤                  j§                  ‰ ‰‰|«      sy‰jO                  «       ‰jP                  z  rÖ‰ j©                  ‰‰|¬%«      rDtz        j¤                  j©                  ‰ ‰‰|«      r"‰ j                  |«      j©                  ‰‰«      ryt„        jŠ                  rm‰ j«                  ‰‰«      r[‰ j©                  ‰‰|¬%«      xrE tz        j¤                  j©                  ‰ ‰‰|«      xr! ‰ j                  |«      j©                  ‰‰«      S ytz        j¤                  j­                  ‰ ‰‰|«      xr! ‰ j                  |«      j­                  ‰‰«      S c c}w )(NFc              3  óV   •K  — | ]   }‰j                   j                  ||«      –— Œ" y ­wr~   ra	  rb	  s     €rs   r¹   z&Scheduler._can_fuse.<locals>.<genexpr>Ò  s,   øè ø€ ò 4àð ×%Ñ%×)Ñ)¨$°×5ñ4ùr  r$  Tz/grouped node must not be fused with other nodesznode1 is nopz'node1 is extern but not a triton kernelz5node1's triton kernel doesn't support epilogue fusionz.node1 is extern but node2 is not SchedulerNodez3node1 is extern but node2.node is not SchedulerNodez4node1 is extern but node2.node.data is not Pointwiser   r   c              3  ó<   •K  — | ]  }|j                   ‰k7  –— Œ y ­wr~   rt  )r·   rà   Úwritten_buffer_names     €rs   r¹   z&Scheduler._can_fuse.<locals>.<genexpr>  s   øè ø€ ÒV°s�3—8‘8Ð2Õ2ÑVùrR  z9epilogue reads from buffers other than the mutated outputc              3  ó&   K  — | ]	  }|d k7  –— Œ y­w)r¶  Nr…   )r·   Úusages     rs   r¹   z&Scheduler._can_fuse.<locals>.<genexpr>  s   è ø€ Ò;¨5�u •Ñ;ùs   ‚z*node1 and node2 uses different buf layoutsc                ó@   •— | ‰uxr | ‰uxr ‰| j                  «       v S r~   )rã   )r  rˆ   r‰   rx	  s    €€€rs   Ú._is_other_node_that_references_mutation_bufferzKScheduler._can_fuse.<locals>._is_other_node_that_references_mutation_buffer-  s7   ø€ ð   uÐ,ò NØ#¨5Ð0òNà+¨z×/KÑ/KÓ/MÐMðru   c              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   )r·   r”   r|	  s     €rs   r¹   z&Scheduler._can_fuse.<locals>.<genexpr>6  s   øè ø€ ò àñ ?¸t×Dñùr=  znode2 is extern or nopznode1 must go before node2zprologue fusion turned offz2prologue fusion only supported for pointwise nodesz'template has no allowed prologue inputsc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   r¾  )r·   r‡  s     rs   r¹   z&Scheduler._can_fuse.<locals>.<genexpr>W  s   è ø€ ÒE¨c˜3Ÿ<™<Ÿ>ÑEùrÃ  z;prologue fusion not implemented for kernel for these inputsz:template prologue can only fuse functional pointwise nodesr  c              3  ó:   •K  — | ]  }|j                   ‰v –— Œ y ­wr~   r¼   )r·   ró  Úprologue_nodess     €rs   r¹   z&Scheduler._can_fuse.<locals>.<genexpr>i  s   øè ø€ ÒQ¸t˜tŸy™y¨NÔ:ÑQùr™  z7template prologue can only fuse nodes with a single usezEtemplate prologue can only fuse nodes with a single use into templateztemplate epilogue not satisfiedz6multi-output template epilogue requires ComputedBufferz#fusion for buffer explicit disabledzdevice mismatch (%s vs %s))r  ro	  ©ro	  z%s and %s has %s shared data)r  rf   )Wr   rÂ  rv  r±  r²   r  r  rÿ  rÔ  rç  r#  rª   Úcan_fuse_multi_outputs_templater´  r  rR  r”   r0   rÿ  r   r³   r   r÷   r   rÎ   r/  r×   r  rÕ   rÖ   Úinner_fn_free_symbolsÚcollect_inner_fn_symbol_usager  rí  rþ  rÜ   rÿ  rÝ  rq  r  r  r$  r´   rŒ  Úget_allowed_prologue_inpsr³  rÇ  rƒ  Ú,has_aliasing_or_mutation_for_prologue_fusionr»   r<  rº   rß  rÚ   rÛ   r,  rJ	  r   r  r‡  r\   ra   rÁ   Úno_fuse_buffer_namesrh	  Ú!_score_fusion_memory_for_can_fuser-   Úscore_fusion_memory_thresholdr%  r	  r	  Ú$expand_dimension_for_pointwise_nodesr^	  rX  rl  r	  ra  rÓ  rÔ  rÅ  rÝ  râ  r’  r  Úcan_fuse_verticalr	  Úcan_fuse_horizontal)$rr   rˆ   r‰   r%  r  ro	  r  Ústream2rS  Únode2_inner_fn_free_symbolsÚsymbolÚusagesÚlayout1Úlayout2r‹  rÏ  Úunsupported_prologue_argsr”   Ú	node_outsrå   rÍ  Útemplate_snodesÚtemplate_snodeÚatomic_add_mutation_epiloguer  rÝ  Údevice2Úshared_data_scoreÚnew_shared_data_scoreÚexpand_analysisÚ
expand_dimÚsmaller_nodeÚexpand_sizer|	  r€	  rx	  s$   ```                              @@@rs   rp	  zScheduler._can_fuseÇ  sª	  ý€ ð �E‰>ØØ%Ð1Ü)3ó 4à6ô4ó *Ð&ð ×'Ñ'Ô)Ø×)Ñ)×-Ñ-¨eÓ4ˆGØ×)Ñ)×-Ñ-¨eÓ4ˆGØÐ" wÐ':¸wÈ'Ò?QØä�eÔ2Ô3Ø×&Ñ& u¸+Ð&ÓFÐFÜ�eÔ2Ô3Øä�eÔ4Ô5Ø×&Ñ& uÓ-Ð-Ü�eÔ4Ô5ð ä˜˜uÓ%ˆà×ÑÔ 4×#3Ñ#3Ø×ÑÓó$
ç
)Ñ
)¨%°Ó
7ð$8ð ä�eÔ1Ô2´jØÔ'ô7
ñ ÐAÔBØÜ�eÔ3Ô4¸U×=NÑ=NÔ=PÙ�ÔØä�eÔ6Õ7Ü˜eŸj™j¬"×*DÑ*DÔEÙÐ=Ô>Øà—:‘:×/Ñ/Ô1ÙÐKÔLØä˜e¤]Ô3ÙÐDÔEØÜ˜eŸj™j¬.Ô9ÙÐIÔJØÜ˜eŸj™jŸo™o¬yÔ9ÙÐJÔKØä�u—z‘z×2Ñ2Ó3°qÒ8Ð8Ð8Ø"'§*¡*×"=Ñ"=¸aÑ"@×"EÑ"EÐô ÓV¸e×>OÑ>O×>UÑ>UÔVÔVÙÐOÔPØð +0¯*©*¯/©/×*OÑ*OÓ*QÐ'Ø5ò !�ØŸ™Ÿ™×FÑFÀvÓN�ÜÑ;°FÔ;Õ;Ù ð!ô �u—z‘z×.Ñ.Ó/°1Ò4Ð4Ð4ð —j‘j×-Ñ-¨aÑ0×7Ñ7ˆGØ—j‘j×'Ñ'ˆGÜ˜g¤r§y¡yÔ1´jÀÌ"Ï)É)Ô6TÐTÐTà—‘ §¡Ò,Ø—>‘> W§^¡^Ò3Ø—>‘> W§^¡^Ò3áÐ@ÔAØðØ-÷ô ó à ŸJ™Jôô ð ô �uÔ8Ô:PÐQÔRØ×%Ñ%Ô'áÐ(Ô)Øà×$Ñ$Ó&¨¯©Ò8ÙÐ,Ô-Øà×ÑÕÜ.¨uÔ5ÙÐ0Ô1Øà×!Ñ!Ô# u×'8Ñ'8Ô':ÙÐHÔIØà×7Ñ7Ó9ˆHØ$,×$FÑ$FÓ$HÐ!Ù(ÙÐ=Ô>Øô ÑE°X·_±_ÔEÓEØ'ñ(ð &ð
 ×%Ñ%Ó'Ð*CÒCÙÐQÔRØà×-Ñ-Ô/Ø×EÑEÀeÔLáÐPÔQØà"Ÿ_™_Ó.ˆNØ& s¨Ð+ò %�Ø ×,Ñ,Ó.�	Ø$ò %�CÜÓQÀsÇyÁyÔQÕQÙÐUÔVÚ$ñ%ð%ô " %Ô);Ô<ð ‘à!&§¡ÖA˜A°·±µ’aÒAð ô
 �Ó'¨1Ò,Ð,Ð,Ø,¨QÑ/ˆNô �N 2Ñ&×.Ñ.Ó/°1Ò4Ü˜ rÑ*×2Ñ2°1Ñ5×;Ñ;Ó<ÀÒAØ" 2Ñ&×.Ñ.¨qÑ1×7Ñ7¸Ñ:×?Ñ?À>ÑQáØ[ôð à×@Ñ@ÀÈÈsÔSØà×ÑÔÜ+QØ�uó,Ð(ð ×/Ñ/Ô1Ñ:VØ×%Ñ%Ô'Ü2°5Ô9áÐ5Ô6ØØ ×2Ñ2Ó4ˆLØÐ+Ð+Ð+Ø×5Ñ5Ô7Ä
Ø—
‘
œB×-Ñ-ôAñ ÐLÔMØà×"Ñ"Ó$¤q§w¡w×'CÑ'CÒCØ×"Ñ"Ó$¤q§w¡w×'CÑ'CÒCáÐ5Ô6ØØ×!Ñ!Ó#ˆØ×"Ñ"Ó$ˆØ�WÒÙÐ,¨f°gÔ>ØØà%Ð-Ø)-×)PÑ)PØ�uó*Ð&ð !×BÑBØØØ&?Ø'Að	 Có 
Ðñ Ø!¤F×$HÑ$HÒHä×1Ò1´V×5XÒ5Xð %)×$JÑ$JÈ5ÐRWÓ$XÐ!Ø$¨Ò)Ø$9Ð!ä×6Ò6Ø#×FÑFÀuÈeÓTÐTˆOÐTà6EÑ3ˆZ˜ {Ø×<Ñ<¸ZÈÔUØ $× FÑ FØØØ+Eð !Gó !Ðô ×1Ò1Ø!¤F×$HÑ$HÒHà$(×$MÑ$MØ�uó%Ð!ð %¨Ò)Ø$9Ð!ä×)Ñ)¬'¯-©-Ô8Ü×#Ñ#Ø.Ø—‘Ó Ø—‘Ó Ø!ô	ô �y‰y×!Ñ! $¨¨uÐ6GÔHØà×$Ñ$Ó&¨¯©Ò8ð ×&Ñ&ØØØ/Ið 'ô ô
 —I‘I×/Ñ/°°e¸UÐDUÔVØ×$Ñ$ VÓ,×>Ñ>¸uÀeÔLàô ×3Ò3Ø×=Ñ=¸eÀUÔKð ×*Ñ*ØØØ3Mð +ó ò Qô
 Ÿ	™	×3Ñ3Ø˜e UÐ,=óòQð ×(Ñ(¨Ó0×BÑBÀ5È%ÓPð
ð ä—9‘9×0Ñ0Ø�e˜UÐ$5óò Mà×"Ñ" 6Ó*×>Ñ>¸uÀeÓLðMùòU Bs   ×i?×0i?r�	  c               óÖ  — |j                  «       }t        ||«      }t        t        «      }|j                  D ]j  }| j
                  j                  |j                  |j                  «      }t        |t        «      r| j                  |||«      rŒW||   j                  |«       Œl |j                  j                  D �]  }	t        |	t        «      st        |	t        «      sŒ%| j
                  j                  |	j                  |	j                  «      }
|j                  |
«      }|sŒi|D ]™  }t        |	t        «      rG| j!                  |j#                  | j
                  «      |	|duxr |
|v ¬«      r|j%                  |«       ŒZt        |	t        «      sŒk| j'                  ||	|j(                  «      sŒ‰|j%                  |«       Œ› �Œ	 t+        d„ t,        j.                  j1                  |j3                  «       «      D «       «      }||z  r	 |d«       y|j5                  «       }|D ]E  }| j6                  |   j9                  «       }|| j:                  |   j<                  z  sŒ= |d«        y y)aÔ  
        Check if it is legal to fuse a consumer (node2) into a producer (node1).

        We can fuse them if all the reads of node2 either match
        corresponding writes in node1, or are written by nodes that can
        be scheduled before the fusion of node1 and node2.

        ``index_equivalent_dep_names`` relaxes write/read matching only for
        named producer outputs; the remaining intermediate-dependency checks
        still run normally.
        N©Úallow_index_equivalencec              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   z.Scheduler.can_fuse_vertical.<locals>.<genexpr>1  s   è ø€ ò $
àð �H�Hñ$
ùrv  zmemory deps did not matchFz(intermediate nodes between node1 & node2T)rÇ  rÔ  r   r¥   r3  r)  r±  r×   r²   r;   rô  rä   rÕ   rQ  r9   r:   Úfusable_read_and_writery  r0  Ú.fusable_stardep_write_and_read_on_empty_tensorr”   r   rš  r›  rz  rÝ   r  r  rä  r¹  r  )rr   rˆ   r‰   ro	  Únode1_buf_namesrS  Úremaining_deps_by_namerà   r×   ÚcdÚ
write_nameÚ	remainingrL  Úremaining_depsÚnode1_op_namesr®  s                   rs   r‹	  zScheduler.can_fuse_verticalþ  s:  € ð$  ×0Ñ0Ó2ˆÜ˜˜uÓ%ˆÜ7BÄ4Ó7HÐà×+Ñ+ò 	5ˆCØ×(Ñ(×,Ñ,¨S¯X©X°s·x±xÓ@ˆDÜ˜#œwÔ'¨D×,AÑ,AÀ#ÀuÈeÔ,TØØ" 4Ñ(×/Ñ/°Õ4ð		5ð ×#Ñ#×*Ñ*ó 	-ˆBÜ˜b¤)Ô,´ZÀÄGÔ5LØØ×.Ñ.×2Ñ2°2·7±7¸B¿G¹GÓDˆJØ.×2Ñ2°:Ó>ˆIÚØ#ò -�BÜ! "¤iÔ0°T×5PÑ5PØŸ	™	 $×"7Ñ"7Ó8Øà6¸dÐBò IØ *Ð.HÐ Hð 6Qô 6ð "×(Ñ(¨Õ,Ü# B¬Õ0Ø×KÑKØ  E§J¡Jõð "×(Ñ(¨Õ,ò-ð	-ô. $ñ $
ä —‘×4Ñ4Ð5K×5RÑ5RÓ5TÓUô$
ó 
ˆð
 ˜OÒ+ñ
 Ð+Ô,Øà×2Ñ2Ó4ˆØ"ò 	ˆDØ×&Ñ& tÑ,×=Ñ=Ó?ˆGØ × 7Ñ 7¸Ñ @× JÑ JÓJÙÐ>Ô?Ùð		ð ru   c                ó  ‡— |j                   |j                  «       vry|j                  j                  D �cg c]  }|j                   |j                  k(  r|‘Œ }}t        |«      dk7  ry|d   Št        ‰t        «      ryt        ‰t        «      sJ ‚t        ‰j                  t        j                  «      ryt        ‰j                  «      ‰j                  j                  k  sy| j                   |j                     }|g}t        |t"        «      r|j$                  }d}|D ]R  }	|	j                  j&                  D �
cg c]  }
|
j                   |k(  r|
‘Œ }}
|sŒ8|dz  }t)        ˆfd„|D «       «      rŒR y |dk  S c c}w c c}
w )NFr   r   c              3  óø   •K  — | ]q  }t        |t        «      xr[ t        |j                  t        j
                  «       xr4 |j                  ‰j                  k(  xr |j                  ‰j                  k(  –— Œs y ­wr~   )r²   r9   r(   rØ   r*   ÚTMPrÜ   )r·   r  r  s     €rs   r¹   z-Scheduler.fusable_weak_dep.<locals>.<genexpr>r  sm   øè ø€ ò ð
 ô	 ˜4¤Ó+ò ,Ü+¨D¯J©J¼¿¹ÓAÐAò,à—J‘J %§+¡+Ñ-ò,ð —I‘I §¡Ñ+ó,ñùs   ƒA7A:)r×   rÇ  rÕ   rQ  rø  rÎ   r²   r:   r9   r(   rØ   r*   r®	  r   rõ  r&   r�  rB  rÛ   rÖ   rº   )rr   Úweak_deprˆ   r‰   r  Úmutating_writesr3  Úrelevant_reading_nodesÚnum_concurrent_readsÚreading_noder  Úrelevant_readss       `       rs   rô  zScheduler.fusable_weak_depG  sŽ  ø€ ð �=‰= × 6Ñ 6Ó 8Ñ8Øð ×*Ñ*×1Ñ1ö
àØ�z‰z˜X×2Ñ2Ò2ò ð
ˆð 
ô
 ˆÓ 1Ò$ØØ Ñ"ˆÜ�eœWÔ%ØÜ˜%¤Ô+Ð+Ð+ä˜uŸ{™{¬D¯H©HÔ5Øô
 ˜%Ÿ/™/Ó*¨e¯k©k×.FÑ.FÒFØà×+Ñ+¨H×,AÑ,AÑBˆ	Ø"' ÐÜ�eÔ7Ô8Ø%*§\¡\Ð"Ø ÐØ2ò 	ˆLð )×4Ñ4×:Ñ:öàØ—9‘9 	Ò)ò ðˆNð ñ
 "ØØ  AÑ%Ð Üó ð
 +ôõ ñ ð!	ð" $ qÑ(Ð(ùòW
ùò6s   ·"E:Ä;E?c                óð   — | j                   |j                   k(  xr\ t        | j                  «      t        |j                  «      k\  xr/ | j                  d t        |j                  «       |j                  k(  S r~   )rØ   rÎ   rÜ   )r  r  s     rs   Ú_same_index_with_prefix_sizez&Scheduler._same_index_with_prefix_size|  s[   € ð �J‰J˜%Ÿ+™+Ñ%ò ;Ü�D—I‘I“¤# e§j¡j£/Ñ1ò;à—	‘	Ð+œC §
¡
›OÐ,°·
±
Ñ:ð	
ru   r 	  c               óÐ  — t        |t        «      �r|j                  |j                  k7  sHt        |j                  t
        j                  «      s$t        |j                  t
        j                  «      ry|}|}| j                  |j                  «      ry| j                  ||«      ryt        j                  r9|j                  |j                  k7  r |j                  «       }|j                  «       }| j                  ||«      ry|sy| j                  ||«      S t        |t        «      r?|j                  |j                  k(  r&|j                  �|j                  |j                  k(  ryy)aÐ  Return whether a producer write can satisfy a consumer read.

        The default path accepts exact matches, plus the existing
        loop-ordering-normalized exact match when that config is enabled.
        ``allow_index_equivalence`` only runs after those checks fail. It keeps
        the producer write dense and injective, then accepts conservative
        consumer-side equivalent reads such as broadcasts or normalized
        loop-order changes.
        FT)r²   r9   r×   r(   rØ   r*   r®	  rC  r•  r¶	  r-   r%  r^  r   Ú%_fusable_read_after_index_equivalencer:   )rr   r  r  r¡	  Úoriginal_readÚoriginal_writes         rs   r£	  z Scheduler.fusable_read_and_write…  s  € ô �dœIÕ&à—	‘	˜UŸZ™ZÒ'Ü& t§z¡z´4·8±8Ô<Ü& u§{¡{´D·H±HÔ=àà ˆMØ"ˆNð ×1Ñ1°.×2EÑ2EÔFØð ×0Ñ0°ÀÔOØä×0Ò0°T·]±]ÀeÇnÁnÒ5Tð —~‘~Ó'�ØŸ™Ó)�ð
 ×0Ñ0°°uÔ=Øá*Øà×=Ñ=Ø˜~óð ô ˜œgÔ&à—	‘	˜UŸZ™ZÒ'Ø—J‘JÐ*Ø—I‘I §¡Ò+àØru   c                ó"  — t        |j                  «      |j                  j                  k  sy|j	                  «       j                  «       s|j                  «       j                  «       sy| j                  ||«      xs | j                  ||«      S rm  )	r   rõ  rØ   r&   r   Úis_contiguousrà  r2	  Ú_fusable_read_after_broadcast)rr   r  r  s      rs   r¸	  z/Scheduler._fusable_read_after_index_equivalenceÄ  s|   € ô ˜%Ÿ/™/Ó*¨e¯k©k×.FÑ.FÒFØð
 �O‰OÓ×+Ñ+Ô-Ø×0Ñ0Ó2×@Ñ@ÔBàà×)Ñ)Ø�%ó
ò =à×/Ñ/°°eÓ<ð	=ru   c           
     ó  ‡ — t        ˆ fd„‰ j                  D «       «      }t        |«      ‰ j                  k7  rŒ|D �ci c]  }|‰ j                  |   “Œ }}t        ‰ j                  ‰ j                  t        |«      t        |j                  «       «      ‰ j                  «      Š ‰ j                  «       |j                  «       k(  ry‰ j                  |j                  k7  ryt        j                  j                  }t        d„ t        ‰ j                  «      D «       «      }i }i }t        ‰ j                  ‰ j                   ||j                   «      D ]ª  \  }	}
}}|j#                  |
|«      r|||	<   Œ |j#                  t%        j&                  |
|«      d«      s y|j)                  t+        |
|«      «      }|j-                  |d«      s yt%        j.                  dt        |«      › �dd¬«      }||z  |z   ||	<   |||<   Œ¬ |sy|j1                  t3        ‰ j                  |«      i t5        t        ||j                   «      «      ¥|¥«      }t3        |j                  t5        t        |j                  |«      «      «      }|j#                  ||«      S c c}w )	aQ  Match conservative broadcasted read forms.

        This handles two nested-reduction dependency shapes:

        - Pure broadcast dims absent from the read index:

              read:  d1, {d0: 1024, d1: 16}
              write: d0, {d0: 16}

        - Same-rank expanded dims used through a quotient:

              read:  32*d0 + FloorDiv(d1, 128), {d0: 128, d1: 4096}
              write: 32*d0 + d1,                {d0: 128, d1: 32}

        Producer-side broadcast and non-dense writes are rejected before this
        helper, so these cases only relax consumer-side broadcasts.
        c              3  óT   •K  — | ]  }|‰j                   j                  v sŒ|–— Œ! y ­wr~   )rØ   r&   )r·   r¸  r  s     €rs   r¹   z:Scheduler._fusable_read_after_broadcast.<locals>.<genexpr>î  s'   øè ø€ ò 
Ø¨S°D·J±J×4KÑ4KÒ-KŒCñ
ùs   ƒ(¡(TFc              3  óR   K  — | ]  }t        j                  d |› �dd¬«      –— Œ! y­w)Ú_fusable_broadcast_T©ÚintegerÚnonnegativeN)r  rü  )r·   r�  s     rs   r¹   z:Scheduler._fusable_read_after_broadcast.<locals>.<genexpr>  s0   è ø€ ò 
àô �L‰LÐ.¨q¨cÐ2¸DÈd×SÐSñ
ùs   ‚%'r   r   Ú_fusable_broadcast_tail_rÂ	  )rÏ   rõ  rÎ   r^  Úrangesr9   r×   rØ   rÝ   r•  r   ra   rÁ   rÂ   rL  ry  rÜ   rÅ   r  r£  rÃ   r'   r»  rü  Úsimplify_with_rangesr`   rx  )r  r  Ú	read_varsr¸  Úread_rangesrÂ   Ú
write_varsÚreplacementsÚtail_rangesÚread_varÚ	read_sizeÚ	write_varÚ
write_sizer‚  Útail_varÚ
read_indexÚwrite_indexs   `                rs   r½	  z'Scheduler._fusable_read_after_broadcastÙ  sW  ø€ ô* ó 
ØŸ>™>ô
ó 
ˆ	ô ˆy‹>˜TŸ]™]Ò*Ø<EÖF°S˜3 §¡¨CÑ 0Ñ0ÐFˆKÐFÜØ—	‘	Ø—
‘
Ü�kÓ"Ü�k×(Ñ(Ó*Ó+Ø—	‘	óˆDð �~‰~Ó 5§?¡?Ó#4Ò4Øà�=‰=˜EŸN™NÒ*Øô
 —7‘7×#Ñ#ˆÜñ 
ä˜4Ÿ=™=Ó)ô
ó 
ˆ
ð 68ˆØ68ˆÜ:=Ø�N‰N˜DŸI™I z°5·:±:ó;
ò 	+Ñ6ˆH�i ¨Jð ×/Ñ/°	¸:ÔFØ)2�˜XÑ&Øà×3Ñ3Ü—	‘	˜) ZÓ0°!ôñ Ø×&Ñ&¤x°	¸:Ó'FÓGˆFØ×/Ñ/°¸Ô:Ùä—|‘|Ø*¬3¨{Ó+;Ð*<Ð=ØØ ôˆHð
 &/°Ñ%7¸(Ñ%BˆL˜Ñ"Ø$*ˆK˜Ò!ð+	+ñ. Øà×2Ñ2Ü�t—z‘z <Ó0Ø@Œt”C˜
 E§J¡JÓ/Ó0Ð@°KÐ@ó
ˆ
ô ! §¡¬d´3°u·±È
Ó3SÓ.TÓUˆØ×/Ñ/°
¸KÓHÐHùòo Gs   ¼J	c                óH  — t        |t        j                  «      sy|j                  «       sy| j                  j                  |j                  |j                  «      }| j                  j                  |j                  |j                  «      }t        |t        «      r||k(  ryyr  )r²   r0   rÿ  r   r)  r±  r×   r:   )rr   r  r  Úwriting_nodeÚ	read_namer¨	  s         rs   r¤	  z8Scheduler.fusable_stardep_write_and_read_on_empty_tensor.  s}   € ô ˜,¬×(BÑ(BÔCØØ×-Ñ-Ô/ØØ×)Ñ)×-Ñ-¨d¯i©i¸¿¹ÓCˆ	Ø×*Ñ*×.Ñ.¨u¯z©z¸5¿:¹:ÓFˆ
Ü�eœWÔ%¨)°zÒ*AØØru   c                ó  — t        | t        «      rt        |t        «      sy| |k(  ry| j                  |j                  k(  r!| j                  «       |j                  «       k(  S | j	                  «       |j	                  «       k(  S )a  Check if two deps refer to the same access pattern after normalization.

        Handles the case where FusedSchedulerNodes have more loop vars
        than a single SchedulerNode (e.g., 3 vars vs 2) by falling back
        to normalize() which merges loops before comparing.
        FT)r²   r9   r^  rà  r   ©Údep1Údep2s     rs   r2	  zScheduler.deps_match_normalized;  sn   € ô ˜$¤	Ô*´*¸TÄ9Ô2MØØ�4Š<ØØ�=‰=˜DŸM™MÒ)à×0Ñ0Ó2°d×6VÑ6VÓ6XÑXðð �~‰~Ó 4§>¡>Ó#3Ñ3Ð3ru   c                óB   — t         j                  j                  ||«      S r~   )ra   rÁ   Úget_dep_size_hint)rr   rà   r  s      rs   r	  zScheduler.dep_size_hintM  s   € Ü�w‰w×(Ñ(¨¨kÓ:Ð:ru   c           
     ón  — |j                  «       |j                  z  syt        |j                  j                  «      }t        «       }d}|j                  j                  D ]Ò  }t        |t        «      sŒ| j                  j                  |j                  |j                  «      }	t        |«      D ]�  \  }
}|
|v rŒ| j                  |j                  | j                  «      ||duxr |	|v ¬«      sŒA|j                  |
«       |t!        | j#                  ||«      | j#                  ||«      «      z  } ŒÒ ŒÔ |S )a0  Score vertical producer-output deps missed by exact dep scoring.

        Exact scoring is set-intersection based, but vertical legality can also
        accept normalized equivalent read/write deps. Give those pairs a memory
        score so heuristics do not discard them before legality runs.
        r   Nr 	  )r  r  r¥   rÕ   rÖ   r   rQ  r²   r9   r)  r±  r×   r’  r£	  ry  r¢  rY  r	  )rr   rE  rJ  r  ro	  rÖ   Úmatched_readsr	  r  r¨	  r�  r  s               rs   Ú*_score_fusion_memory_by_fusable_read_writez4Scheduler._score_fusion_memory_by_fusable_read_writeP  s7  € ð ×,Ñ,Ó.°×1CÑ1CÒCØä�X×)Ñ)×/Ñ/Ó0ˆÜ)3«ˆØˆØ×)Ñ)×0Ñ0ò 	ˆEÜ˜e¤YÔ/ØØ×.Ñ.×2Ñ2°5·:±:¸u¿z¹zÓJˆJÜ$ UÓ+ò ‘��4Ø˜Ñ%ØØ×.Ñ.Ø—K‘K × 5Ñ 5Ó6Øà2¸$Ð>ò EØ&Ð*DÐDð /õ ð "×%Ñ% aÔ(ØœSØ×*Ñ*¨4°Ó=Ø×*Ñ*¨5°+Ó>óñ �Eñ ñ!ð		ð* ˆru   c                óˆ   — | j                  |||¬«      }t        |t        «      sJ ‚|dk(  r|r| j                  |||¬«      }|S )Nr  r   r�	  )r  r²   r‘   rß	  )rr   rˆ   r‰   r  ro	  r	  s         rs   rˆ	  z+Scheduler._score_fusion_memory_for_can_fusez  sd   € ð ×(Ñ(ØØØ&?ð )ó 
ˆô
 ˜%¤Ô%Ð%Ð%Ø�AŠ:Ñ4Ø×CÑCØØØ+Eð Dó ˆEð
 ˆru   c                 ó   — y r~   r…   ©rr   rˆ   r‰   r  Úreturn_is_mix_order_reductionr  s         rs   r  zScheduler.score_fusion_memory�  s   € ð ru   c                 ó   — y r~   r…   râ	  s         rs   r  zScheduler.score_fusion_memory™  s   € ð !$ru   c           	     ód  ‡ ‡‡— ˆfd„}|r6t         j                  ||«      r t         j                  ||«      } ||dd«      S t        |j                  t
        j                  «      r|j                  j                  «       s |j                  «       s|j                  «       r¯|j                  j                  |j                  j                  z  }|j                  j                  |j                  j                  z  }	dd„}
d}|D ]@  }|	D ]9  } |
||«      sŒ|t        ‰ j                  |«      ‰ j                  |«      «      z  }Œ; ŒB  ||dd«      S |j                  j                  |j                  j                  z  }|j                  j                  |j                  j                  z  }	t        |«      t        |	«      kD  r|	|}	}|D �cg c]	  }||	v sŒ|‘Œ }}t        ˆˆ fd„|D «       «      }|r
 ||dd«      S d}|dk(  r$‰ j!                  ||«      r‰ j#                  ||«      } |||d«      S c c}w )a2  
        The first term in our fusion score that estimates number of saved
        memory operations.

        This function scores fusion candidates based on shared memory access patterns.
        Higher scores indicate better fusion candidates.

        Scoring strategy:
        1. If nodes share exact memory deps (same buffer + same indexing), return
           the sum of shared dep sizes (original behavior).
        2. If no dependency score remains, check for same-buffer reads with
           different indexing (e.g., split operations reading different slices).
           - Give bonus if nodes read from exactly the same set of buffers
           - Score based on overlap ratio: common_buffer_size / total_read_size
           - High overlap (>50%) suggests good cache locality benefit from fusion
        c                ó   •— ‰r| ||fS | |z   S r~   r…   )r	  Úbuffer_overlap_scoreÚis_mix_order_reductionrã	  s      €rs   Ú_construct_return_valuez>Scheduler.score_fusion_memory.<locals>._construct_return_value¼  s#   ø€ ñ -ØÐ3Ð5KÐLÐLØÐ/Ñ/Ð/ru   r   Tc                óš   — | |k(  ryt        | t        t        f«      r/t        |t        t        f«      r| j                  |j                  k(  S yr  )r²   r:   r9   r×   rØ	  s     rs   Ú_matchz-Scheduler.score_fusion_memory.<locals>._matchÜ  sD   € Ø˜4’<ØÜ˜d¤W¬iÐ$8Ô9¼jØœ7¤IÐ.ô?ð  Ÿ9™9¨¯	©	Ñ1Ð1Øru   Fc              3  óB   •K  — | ]  }‰j                  |‰«      –— Œ y ­wr~   ©r	  )r·   rà   r  rr   s     €€rs   r¹   z0Scheduler.score_fusion_memory.<locals>.<genexpr>õ  s   øè ø€ ÒW¸S�D×&Ñ& s¨K×8ÑWùr‘  )rÙ	  r8   rÚ	  r8   )r¯   r  rò   r²   r”   r0   rÿ  r   rç  rÕ   rÖ   rQ  rY  r	  rÎ   rü   Ú_can_use_buffer_overlap_scoringÚ&_score_fusion_memory_by_buffer_overlap)rr   rˆ   r‰   r  rã	  r  ré	  r	  Ú
node1_depsÚ
node2_depsrë	  Ú	node1_depÚ	node2_deprà   Úcommon_memory_depsrç	  s   `  ``           rs   r  zScheduler.score_fusion_memory£  s  ú€ ô2	0ñ %Ô):×)CÑ)CÀEÈ5Ô)Qô
 &×6Ñ6°u¸eÓDˆEÙ*¨5°!°TÓ:Ð:ô ˜5Ÿ:™:¤r×'AÑ'AÔBØ—J‘J×0Ñ0Ô2à× Ñ Ô"Ø× Ñ Ô"à×*Ñ*×0Ñ0°5×3DÑ3D×3KÑ3KÑKˆJØ×*Ñ*×0Ñ0°5×3DÑ3D×3KÑ3KÑKˆJóð ˆEØ'ò �	Ø!+ò �IÙ˜i¨Õ3Ø¤Ø ×.Ñ.¨yÓ9¸4×;MÑ;MÈiÓ;Xó"ñ ™ñðñ +¨5°!°UÓ;Ð;à×&Ñ&×,Ñ,¨u×/@Ñ/@×/GÑ/GÑGˆ
Ø×&Ñ&×,Ñ,¨u×/@Ñ/@×/GÑ/GÑGˆ
Üˆz‹?œS ›_Ò,Ø%/°˜
ˆJà-7ÖM c¸3À*Ò;LšcÐMÐÐMÜÔWÐDVÔWÓWˆÙÙ*¨5°!°UÓ;Ð;ð  !ÐØ�AŠ:˜$×>Ñ>¸uÀeÔLØ#'×#NÑ#NØ�uó$Ð ñ ' uÐ.BÀEÓJÐJùò Ns   Ç	H-ÇH-c                ót  — |j                  «       s|j                  «       ry|j                  «       s|j                  «       ryt        j                  st        j                  �rU|j                  «       }|j                  «       }|r|syt        d„ |D «       «      }t        d„ |D «       «      }t        «       }|D ]â  }|j                  D ]Ñ  }	t        |	j                  t        «      sŒ|	j                  j                  «       sŒ9t        |	j                  «      sŒO|	j                  j                  «       }
|
�Lt        |
t        j                  «      r2|
j                  «       }||z  sŒ›|j!                  |	j                  «       Œ·|j!                  |	j                  «       ŒÓ Œä |r®|D ]©  }|j                  D ]˜  }	t        |	j                  t        «      sŒ|	j                  j                  «       sŒ9|	j                  |v sŒH|	j                  j                  «       }
|
�3t        |
t        j                  «      r|
j                  «       }||z  sŒ”  y  y Œ« ||fD ]d  }|j"                  j$                  D ]I  }| j&                  j)                  |j*                  «      }|€Œ+|j                  «       sŒ<t-        |«      sŒH  y Œf y)a@  
        Check if buffer overlap scoring should be used for this node pair.

        Buffer overlap scoring handles split/cat patterns where nodes read from
        the same buffer at different indices. We skip it when:
        - Either node is a reduction (different memory access patterns)
        - Either node is a template
        - Both nodes are prologue/epilogue candidates for the same template,
          because horizontal fusion would prevent them from being absorbed
          into the template kernel. For example, in:
            q = a[:64, :]; k = a[64:, :]
            return mm(q + 2, k - 2)
          "q + 2" and "k - 2" both read from `a` and would get a high overlap
          score, but fusing them horizontally prevents prologue fusion into mm
          (resulting in 2 kernels instead of 1).

        We allow buffer overlap scoring when:
        - The node outputs are not actually in the template's allowed_prologue_inps,
          meaning they can't be prologue-fused anyway, so horizontal fusion doesn't
          prevent any optimization opportunity.
        FTc              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   r¾  r‚  s     rs   r¹   z<Scheduler._can_use_buffer_overlap_scoring.<locals>.<genexpr>*   ó   è ø€ Ò+T¸s¨C¯L©L¯NÑ+TùrÃ  c              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr~   r¾  r‚  s     rs   r¹   z<Scheduler._can_use_buffer_overlap_scoring.<locals>.<genexpr>+   r÷	  rÃ  )r´   rç  r-   r�  rŒ  r<  r   rß  r²   r”   rf   r$  r‡  r0   r  r…	  r¢  rÕ   rÖ   r¹  r±  r×   r  )rr   rˆ   r‰   Únode1_outputsÚnode2_outputsÚnode1_output_namesÚnode2_output_namesÚ&node1_prologue_eligible_template_usersrÞ   ró  r•  Úallowed_inpsr”   rà   rE  s                  rs   rî	  z)Scheduler._can_use_buffer_overlap_scoring   sf  € ð4 ×ÑÔ 5×#5Ñ#5Ô#7ØØ×ÑÔ %×"3Ñ"3Ô"5Øä×Ò¤&×":Ó":Ø!×-Ñ-Ó/ˆMØ!×-Ñ-Ó/ˆMñ !©Øä!+Ñ+TÀmÔ+TÓ!TÐÜ!+Ñ+TÀmÔ+TÓ!TÐô
 “ð 3ð %ò R�ØŸI™Iò R�Dä" 4§9¡9Ô.?Õ@Ø ŸI™I×1Ñ1Õ3Ü7¸¿	¹	ÕBð
 )-¯	©	×(CÑ(CÓ(E˜Ø(Ð4¼Ø)¬2×+BÑ+Bô:ð ,9×+RÑ+RÓ+T˜LØ1°LÓ@Ø F× JÑ JÈ4Ï9É9Õ Uð C×FÑFÀtÇyÁyÕQñ%RðRñ. 6Ø(ò -�CØ #§	¡	ò -˜ä& t§y¡yÔ2CÕDØ $§	¡	× 5Ñ 5Õ 7Ø $§	¡	Ð-SÒ Sð -1¯I©I×,GÑ,GÓ,I˜MØ,Ð8¼ZØ -¬r×/FÑ/Fô>ð 0=×/VÑ/VÓ/X Ø#5¸Ó#DÚ+0ò (-ñ!-ð-ð&  ˜ò %�Ø×+Ñ+×1Ñ1ò %�CØ#×6Ñ6×:Ñ:¸3¿8¹8ÓD�Hà Ñ,Ø$×0Ñ0Õ2Ü7¸ÕAâ$ñ%ð%ð ru   c                ó|  ‡ ‡‡‡— dŠd
ˆˆ fd„Št        d„ |j                  j                  D «       «      }t        d„ |j                  j                  D «       «      }||z  Š‰syt        ˆfd„|j                  j                  D «       «      }t        ˆfd„|j                  j                  D «       «      }t	        ||«      }|dk(  ryt        ˆˆfd„|j                  j                  D «       «      }t        ˆˆfd	„|j                  j                  D «       «      }	t	        ||	«      }
|
|z  }|t
        j                  k\  r|
S dS )a8  
        Score fusion based on buffer name overlap when exact dep matching fails.

        This handles the split/cat fusion case where nodes read from the same buffer
        but at different indices (e.g., different slices from a split operation).

        Scoring logic:
        - If nodes read from exactly the same buffers: high bonus (encourages fusion)
        - For common buffers: score based on overlap ratio
          - overlap_ratio = common_buffer_size /
            max(node1_total_reads, node2_total_reads)
          - If overlap_ratio > threshold (e.g., 0.5): give proportional score
          - If overlap_ratio < threshold: minimal/no score (not worth fusing)

        Note on dynamic shapes:
        - When deps have unbacked symbols (dynamic shapes), dep_size_hint returns 0
        - In this case, we use count * 10 as a proxy for size
        - This ensures fusion still works for models with dynamic batch sizes

        Note on multiple deps from same buffer:
        - A node may have multiple MemoryDep entries for the same buffer name
          (e.g., 4 split reads from arg0_1 at different indices)
        - We sum ALL dep sizes for each buffer, not just take max
        - This ensures overlap ratio is calculated correctly when nodes read
          multiple slices from the same underlying buffer
        rÈ  c                ó8   •— ‰j                  | «      }|dkD  r|S ‰S ré   rí	  )rà   rÜ   ÚFALLBACK_DEP_SIZErr   s     €€rs   Úget_dep_sizezFScheduler._score_fusion_memory_by_buffer_overlap.<locals>.get_dep_size‰   s%   ø€ Ø×%Ñ% cÓ*ˆDØ !š8�4Ð:Ð):Ð:ru   c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zCScheduler._score_fusion_memory_by_buffer_overlap.<locals>.<genexpr>�   rÇ  rv  c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   zCScheduler._score_fusion_memory_by_buffer_overlap.<locals>.<genexpr>Ž   rÇ  rv  r   c              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   ©r·   rà   r
  s     €rs   r¹   zCScheduler._score_fusion_memory_by_buffer_overlap.<locals>.<genexpr>—   ó   øè ø€ ò $
Ø"%‰L˜×ñ$
ùr=  c              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   r
  s     €rs   r¹   zCScheduler._score_fusion_memory_by_buffer_overlap.<locals>.<genexpr>š   r
  r=  c              3  óJ   •K  — | ]  }|j                   ‰v r
 ‰|«      –— Œ y ­wr~   rt  ©r·   rà   r9	  r
  s     €€rs   r¹   zCScheduler._score_fusion_memory_by_buffer_overlap.<locals>.<genexpr>¥   ó*   øè ø€ ò %
àØ�x‰x˜<Ñ'ñ ˜×ñ%
ùr}  c              3  óJ   •K  — | ]  }|j                   ‰v r
 ‰|«      –— Œ y ­wr~   rt  r

  s     €€rs   r¹   zCScheduler._score_fusion_memory_by_buffer_overlap.<locals>.<genexpr>ª   r
  r}  )rà   r8   r�   r‘   )r   rÕ   rÖ   rü   rY  r-   Úmin_overlap_ratio)rr   rˆ   r‰   Únode1_read_namesrÐ  Únode1_total_read_sizeÚnode2_total_read_sizeÚmax_total_read_sizeÚnode1_common_read_sizeÚnode2_common_read_sizeÚcommon_read_buffer_sizeÚoverlap_ratior
  r9	  r
  s   `           @@@rs   rï	  z0Scheduler._score_fusion_memory_by_buffer_overlapi   sQ  û€ ð< Ðö	;ô &Ñ%R¸%×:KÑ:K×:QÑ:QÔ%RÓRÐÜ%Ñ%R¸%×:KÑ:K×:QÑ:QÔ%RÓRÐð (Ð*:Ñ:ˆáØô !$ó $
Ø).×):Ñ):×)@Ñ)@ô$
ó !
Ðô !$ó $
Ø).×):Ñ):×)@Ñ)@ô$
ó !
Ðô "Ð"7Ð9NÓOÐØ !Ò#Øô
 "%ô %
à×(Ñ(×.Ñ.ô%
ó "
Ðô
 "%ô %
à×(Ñ(×.Ñ.ô%
ó "
Ðô #&Ð&<Ð>TÓ"UÐð 0Ð2EÑEˆð
 (5¼×8PÑ8PÒ'PÐ#ð	
ØVWð	
ru   c                óÀ  — t        |«      dk(  r|S i }|D ]…  \  }}|j                  «       |j                  «       k(  sJ ‚|j                  «       }t        | j                  |«      j	                  ||«      «      }||vr	||fg||<   Œp||   j                  ||f«       Œ‡ t        |j                  «       t        j                  d«      ¬«      d   }t        |«      dkD  sJ ‚|S )Nr   rã  r   )
rÎ   rª   r‘   r#  Úget_fusion_pair_priorityrä   rZ  rÀ  r  r  )rr   r8  Ú"possible_fusions_group_by_priorityrˆ   r‰   rÝ  Úfusion_pair_priorityÚ&possible_fusions_with_highest_prioritys           rs   rž  z4Scheduler.get_possible_fusions_with_highest_priority½   s  € ô
 ÐÓ  AÒ%Ø#Ð#ð ð 	+ð -ò 	‰LˆE�5Ø×#Ñ#Ó%¨×)9Ñ)9Ó);Ò;Ð;Ð;Ø×%Ñ%Ó'ˆFÜ#&Ø× Ñ  Ó(×AÑAÀ%ÈÓOó$Ð ð $Ð+MÑMà˜E�NðLÐ2Ð3GÒHð 3Ð3GÑH×OÑOØ˜E�Nõð	ô 25Ø.×4Ñ4Ó6¼H×<OÑ<OÐPQÓ<Rô2
à
ñ2Ð.ô Ð9Ó:¸QÒ>Ð>Ð>Ø5Ð5ru   c                óB   — t        j                  j                  | g|¢­Ž S )z-
        Shim for list.sort(key=...)
        )ra   r’  Úscore_fusionrO  s     rs   rŸ  zScheduler.score_fusion_keyÝ   s   € ô �y‰y×%Ñ% dÐ3¨UÒ3Ð3ru   c                óô   — t        t        j                  j                  «       «      }t	        | j
                  «      D ]9  }|j                  || j                  «       |j                  |j                  «       Œ; y)zg
        Populate node.last_usage recursively (also for the nodes within a FusedSchedulerNode)
        N)
r   ra   rÁ   r•  rÐ   rq  r•  r�  rÝ  r"  )rr   r“  r”   s      rs   r¡  zScheduler.compute_last_usageå   s]   € ô
 )¬¯©×)AÑ)AÓ)CÓDÐä˜TŸZ™ZÓ(ò 	8ˆDØ×ÑÐ 3°T×5LÑ5LÔMØ×&Ñ& t§¡Õ7ñ	8ru   c                óÞ  — t        | j                  t        j                  j                  z
  t        j                  j
                  j                  z
  «      D �]z  }|| j                  v rT| j                  |   }|j                  «       sŒ2t        j                  j
                  j                  |j                  «       Œf|t        j                  j                  v sŒƒt        j                  j                  |   }t        |t        j                  «      r*t        j                  j
                  j                  |«       Œät        |t        j                  t        j                   f«      r�Œ|j"                  }t        |t        j$                  «      r|j'                  «       sJ ‚t        j                  j
                  j                  |j"                  «       �Œ} | j                  j)                  «        y)z*Free any buffers that are no longer neededN)rè  r§  ra   rÁ   r  rÿ  Úfreedr  r  Úcodegen_freer”   rX  r²   r0   rL  r­  r®  r÷   rš  Úis_input_bufferrB  )rr   r×   rÞ   r‡  Ústorages        rs   Úfree_bufferszScheduler.free_buffersð   sV  € äØ×%Ñ%Ü�g‰g×%Ñ%ñ&ä�g‰g×"Ñ"×(Ñ(ñ)ó
ó 	DˆDð
 �t×'Ñ'Ñ'Ø×&Ñ& tÑ,�Ø—<‘<•>Ü—G‘G×(Ñ(×5Ñ5°c·h±hÕ?ØœŸ™×-Ñ-Ò-Ü—g‘g×*Ñ*¨4Ñ0�Ü˜c¤2×#5Ñ#5Ô6Ü—G‘G×(Ñ(×5Ñ5°cÕ:Ü ¤b×&7Ñ&7¼×9MÑ9MÐ%NÔOÙà!Ÿh™h�Gä" 7¬B¯M©MÔ:¸w×?VÑ?VÔ?XðØXä—G‘G×(Ñ(×5Ñ5°g·l±lÖCð)	Dð, 	×!Ñ!×'Ñ'Õ)ru   c                ó‚   — | j                   j                  «       D ]  }|j                  «        Œ | j                  «        y r~   )rl  rÝ   Úflushr#
  )rr   r  s     rs   r%
  zScheduler.flush
!  s3   € Ø—}‘}×+Ñ+Ó-ò 	ˆGØ�M‰M�Oð	à×ÑÕru   c                óv  — t        |t        t        f«      sJ ‚t        d   dxx   dz  cc<   t	        j
                  t        d¬«      «      5  |j                  «        |j                  «        d d d «       |j                  t        j                  j                  «       | j                  «        y # 1 sw Y   ŒCxY w)Nr]  Úextern_callsr   F)Úincrease_kernel_count)r²   rR  r*  r   ra   Úset_kernel_handlerr5   r  r—  r  rÁ   rÿ  r#
  )rr   Úscheduler_nodes     rs   Úcodegen_extern_callzScheduler.codegen_extern_call!  sŸ   € ô ØÜ&Ô(LÐMô
ð 	
ð 
ô 	�Ñ˜^Ó,°Ñ1Ó,Ü×!Ñ!¤&¸uÔ"EÓFñ 	&Ø×0Ñ0Ô2Ø×#Ñ#Ô%÷	&ð 	×ÑœqŸw™w×3Ñ3Ô4Ø×ÑÕ÷		&ð 	&ús   Á!B/Â/B8c                óP  — t        |j                  «      r|j                  €
J |› d�«       ‚t        j                  j                  |«       t        |j                  «      }|€t        d|j                  › �«      ‚t        «       sœ|j                  dk(  rLt        j                  j                  |«      x}j                  dk  rt        |t        j                  «       «      ‚t        |j                  «      r,|j                  dk(  st!        t        j                  «       «      ‚ || «      S )Nz( should have been normalized in loweringzUnsupported device type: r§   é   rs  )r[   r«   rØ   ra   rÁ   Úadd_device_infor4   rS  r+   r`  r§   Úget_device_propertiesÚmajorr<   ÚinspectÚcurrentframer=   )rr   rÝ  Údevice_schedulingrã  s       rs   Úcreate_backendzScheduler.create_backend"!  sï   € Ü˜&Ÿ+™+Ô&¨&¯,©,Ð*Bð 	
ØˆhÐ>Ð?ó	
ÐBô 	
�‰×Ñ Ô'ä5°f·k±kÓBÐØÐ$ÜÐ!:¸6¿;¹;¸-ÐHÓIÐIäŒ|à—‘˜vÒ%Ü%*§Z¡Z×%EÑ%EÀfÓ%MÐM�\×TÑTÐWXÒXä(¨´w×7KÑ7KÓ7MÓNÐNÜ˜Ÿ™Ô$¨V¯[©[¸EÒ-AÜ#¤G×$8Ñ$8Ó$:Ó;Ð;á  Ó&Ð&ru   c                ó€   — |€J ‚|| j                   vr| j                  |«      | j                   |<   | j                   |   S r~   )rl  r4
  rÜ  s     rs   r#  zScheduler.get_backend7!  sB   € ØÐ!Ð!Ð!Ø˜Ÿ™Ñ&Ø$(×$7Ñ$7¸Ó$?ˆD�M‰M˜&Ñ!Ø�}‰}˜VÑ$Ð$ru   c                ó”  ‡ — dˆ fd„}|j                  «       D ��ci c]8  }|j                  �*|j                  j                  «       D ]  } ||«      |fd “Œ Œ: }}}t        |j	                  «       «      }|rMt        |t        j                  d«      ¬«      \  }}t        j                  j                  j                  |«       y y c c}}w )Nc                óâ   •— | ‰j                   vrL‰j                   j                  t        | j                  j                  «      D �� ci c]  \  }} | |“Œ
 c} }«       ‰j                       S c c} }w r~   )r¨  rÝ  r’  rÁ   rq  )rÍ  r�  rr   s     €rs   Ú	get_orderz*Scheduler.enter_context.<locals>.get_order>!  s\   ø€ Ø˜×,Ñ,Ñ,Ø×$Ñ$×+Ñ+¼iÈÏÉÏÉÓ>V×,W±d°a¸¨Q°©TÓ,WÔXØ×'Ñ'¨Ñ*Ð*ùó -Xs   ÁA+
r   rã  )rÍ  ztorch.fx.Noder�   r‘   )r»   r”   r  r¥   r!  rY  r  r  ra   rÁ   rÿ  Úenter_context)rr   r”   r8
  rÍ  r&  r$  r=  Úlasts   `       rs   r9
  zScheduler.enter_context=!  sº   ø€ õ	+ð —^‘^Ó%÷
àØ�v‰vÐ!Ø—V‘V×'Ñ'Ó)ò	
ð ñ �q‹\˜1Ð˜tÑ#ð
Øð
ˆñ 
ô �w—|‘|“~Ó&ˆÙÜ˜'¤x×':Ñ':¸1Ó'=Ô>‰GˆAˆtÜ�G‰G× Ñ ×.Ñ.¨tÕ4ð ùó
s   ›=Cc                ó¾   ‡— 	 | j                   |   j                  }t        ˆfd„|D «       «      xr || j                  vxr || j
                  vS # t        $ r Y yw xY w)NFc              3  ó^   •K  — | ]$  }|j                   xs |j                  «       ‰v –— Œ& y ­wr~   )rô  râ  )r·   ró  rÎ  s     €rs   r¹   zAScheduler.can_buffer_be_removed_through_fusion.<locals>.<genexpr>W!  s)   øè ø€ ÒVÈ�—‘ÒC §¡£Ð3CÐ CÓCÑVùs   ƒ*-)r  rß  ÚKeyErrorrº   r)  r�  )rr   r×   rÎ  rß  s     ` rs   rÌ  z.Scheduler.can_buffer_be_removed_through_fusionO!  sn   ø€ ð	Ø×$Ñ$ TÑ*×0Ñ0ˆEô ÓVÐPUÔVÓVò 4Ø˜D×1Ñ1Ð1ò4à˜D×3Ñ3Ð3ð	
øô ò 	Ùð	ús   ƒA Á	AÁAc                ó  — |j                   }t        |t        j                  j                  j
                  «      rk|j                  x}r]t        |«      \  }}|t        j                  v s|t        j                  v r+t        |t        j                  j                  «      sJ ‚d|› �S t        j                  j                  j                  j                  st        j                  €yt        |t         «      r)|j"                  D ]  }| j%                  |«      }|sŒ|c S  y|j                   €J ‚|j'                  «       s|j)                  «       › d�S t        |j                   t        j*                  «      ryt        |j                   t        j,                  «      ryt/        |j                   dd«      ryt1        |j                   «      ry	| j3                  |«      x}r|S t        j                  j4                  rt7        |«      ry
y)zŠ
        Return the reason why we should partition the inductor graph on this node,
        or None if the node is cudagraphable.
        zcustom partition op: Nz6partition includes all ops when cudagraphs is disabledz opszDeviceCopy opszConditional opsÚunbacked_bindingszunbacked binding opszCUDAGraph-unsafe custom opszdynamic shape ops)r”   r²   r`  ra  r0   r
  rS  rV   r-   Úcustom_should_partition_opsr¾  r¿  r©   re   rN   r  rÚ   rÛ   Úshould_partitionr[   rª   Ú
DeviceCopyrJ  r½  rZ   Ú&_uses_cudagraph_unsafe_unbacked_symintÚcudagraph_skip_dynamic_graphsr  )rr   r”   r	  rã  Úop_overload_packet_nameÚop_overload_namer¸  r×  s           rs   rA
  zScheduler.should_partition\!  s¦  € ð —)‘)ˆÜ�gœuŸ™×1Ñ1×@Ñ@ÔAØ×%Ñ%Ð%ˆBÐ%ä8DÀRÓ8HÑ5Ð#Ð%5à'¬6×+MÑ+MÑMØ#¤v×'IÑ'IÑIä! "¤e§j¡j×&;Ñ&;Ô<Ð<Ð<Ø.Ð/?Ð.@ÐAÐAô —‘×&Ñ&×-Ñ-×8Ò8Ü6×>Ñ>ÐFàKä�dÔ.Ô/ØŸ™ò "�Ø×.Ñ.¨uÓ5�ÚØ!’Mð"ð à�y‰yÐ$Ð$Ð$à�{‰{Œ}Ø—o‘oÓ'Ð(¨Ð-Ð-ä�d—i‘i¤§¡Ô/Ø#ä�d—i‘i¤§¡Ô0Ø$ä�4—9‘9Ð1°4Ô8Ø)ä! $§)¡)Ô,Ø0à×@Ñ@ÀÓFÐFˆ6ÐFØˆMô �=‰=×6Ò6Ü-¨dÔ3Ø*àru   c                óT  — t        «       }t        j                  s|S | j                  D ]ü  }|j                  }|€Œt        |t        j                  j                  j                  «      sŒA|j                  }|€ŒPt        |«      \  }}|t        j                  vr|t        j                  vrŒƒ|j                  «       D ]g  }t        j                  j                  j!                  |«      }t#        |t$        j&                  t$        j(                  f«      sŒW|j+                  |«       Œi Œþ |S )zc
        Collect output unbacked symints from ops in config.cudagraph_unsafe_unbacked_ops.
        )r   r-   Úcudagraph_unsafe_unbacked_opsrq  r”   r²   r`  ra  r0   r
  rS  rV   rû  ra   rÁ   rÂ   rÃ   r)   r*   ÚUNBACKED_INTÚUNBACKED_FLOATr¢  )rr   Úunsafe_symintsr”   r	  rã  rE
  rF
  Úsyms           rs   Ú&_get_cudagraph_unsafe_unbacked_symintsz0Scheduler._get_cudagraph_unsafe_unbacked_symints›!  s  € ô
 4>³<ˆä×3Ò3Ø!Ð!à—J‘Jò 	,ˆDØ—i‘iˆGØˆØä˜g¤u§¡×'9Ñ'9×'HÑ'HÔIØà×$Ñ$ˆBØˆzØä8DÀRÓ8HÑ5Ð#Ð%5à'¬v×/SÑ/SÑSØ$¬F×,PÑ,PÑPàà×7Ñ7Ó9ò ,�Ü—g‘g×&Ñ&×/Ñ/°Ó4�Ü! #¬×(9Ñ(9¼4×;NÑ;NÐ'OÕPØ"×&Ñ& sÕ+ñ,ð'	,ð0 Ðru   c                óÜ   — | j                  «       }|sy t        |«      }|D ]I  }t        j                  j                  j                  |«      }|j                  D ]  }||v sŒd|› �c c S  ŒK y )Nz'uses cudagraph-unsafe unbacked symint: )rM
  r  ra   rÁ   rÂ   rÃ   r&   )rr   r”   rK
  Únode_symbolsrL
  Úsimplified_symÚfree_syms          rs   rC
  z0Scheduler._uses_cudagraph_unsafe_unbacked_symint¿!  s~   € ð ×DÑDÓFˆÙØä5°dÓ;ˆàò 	PˆCÜŸW™W×-Ñ-×6Ñ6°sÓ;ˆNØ*×7Ñ7ò P�Ø˜~Ò-ØDÀXÀJÐOÔOñPð	Pð ru   c                óà   — i }|j                  t        j                  j                  «       | j                  D ]3  }|j
                  j                  «       D ]  \  }}|j                  ||<   Œ Œ5 |S )z~
        Return a mapping from name strings to the corresponding graph inputs or
        base scheduler node outputs.
        )rÝ  ra   rÁ   rX  rq  r.  rÀ  r”   )rr   rI  r”   r×   Úscheduler_buffers        rs   Úget_name_to_nodeszScheduler.get_name_to_nodesÐ!  sr   € ð PRˆØ×ÑœAŸG™G×0Ñ0Ô1à—J‘Jò 	;ˆDØ*.×*>Ñ*>×*DÑ*DÓ*Fò ;Ñ&�Ð&Ø%5×%:Ñ%:�˜TÒ"ñ;ð	;ð Ðru   c           	     óÌ  — t        t        j                  j                  «      D ��ci c]  \  }}||“Œ
 }}}t        t        j                  j	                  «       «      D ��ci c]  \  }}||“Œ
 }}}g t        j                  _        t        |«      D ]Å  \  }}|j                  rŒg }|j                  D ]"  }|j                  |j                  |«      «       Œ$ g }	|j                  D ]0  }
|	j                  |j                  |
j                  «       «      «       Œ2 t        j                  j
                  j                  t        |||	|j                  «      «       ŒÇ yc c}}w c c}}w )z‚
        computes a mapping from partition input/output indices to graph input/output
        indices for each partition.
        N)r’  ra   rÁ   rX  r•  Úpartition_mapsÚskip_cudagraphÚinput_nodesrä   r±  Úoutput_nodesrâ  rW   Úconstant_names)rr   Ú
signaturesrI  r×   Úname_to_graph_input_indexÚname_to_graph_output_indexÚpartition_idÚ	signatureÚinput_mappingÚoutput_mappingr”   s              rs   Úcompute_graph_partition_mapsz&Scheduler.compute_graph_partition_mapsà!  sT  € ô (1´·±×1EÑ1EÓ'F÷%
Ù#˜#˜tˆD�#‰Ið%
Ð!ñ %
ô (1´·±×1IÑ1IÓ1KÓ'L÷&
Ù#˜#˜tˆD�#‰Ið&
Ð"ñ &
ð "$Œ�‰ÔÜ'0°Ó'<ò 	Ñ#ˆL˜)Ø×'Ò'ð
 àˆMØ!×-Ñ-ò J�Ø×$Ñ$Ð%>×%BÑ%BÀ4Ó%HÕIðJð  ˆNØ!×.Ñ.ò W�Ø×%Ñ%Ð&@×&DÑ&DÀTÇ]Á]Ã_Ó&UÕVðWô �G‰G×"Ñ"×)Ñ)Ü!Ø Ø!Ø"Ø×,Ñ,ó	õñ!	ùó%
ùó&
s   §EÁ!E c                ó¸  ‡— 	 	 	 	 dd„Š	 	 	 	 dd„} t        «       j                  d„ |D «       Ž } |j                  ˆfd„|j                  «       D «       Ž   ||«      }t        «       }|D ]F  }t        j
                  j                  j                  |«      }|j                  |j                  «       ŒH t        t        |t        j                  d«      ¬«      «      S )	ai  
        Returns all symbol inputs which are required to be in scope to successfully
        perform codegen for this graph partition, including:
        - free symbols used in partition nodes
        - free symbols in partition input/node shapes, strides, and offsets. This is needed
          for recording cudagraphs for tensors with dynamic shapes.
        c                óÂ   — t        | t        j                  «      r
t        «       S t        | t        j                  «      rt        | «      S t        dt        | «      › �«      ‚)zW
            Gets symbols used in input node shapes, strides, and offsets.
            zUnsupported input node type: )r²   r0   rL  r   rl  r  rò  r«   r¼   s    rs   Úget_input_node_symbolszKScheduler.get_graph_partition_symbol_inputs.<locals>.get_input_node_symbols"  sN   € ô ˜$¤× 2Ñ 2Ô3ä!“|Ð#Ü˜D¤"§)¡)Ô,Ü)¨$Ó/Ð/ô *Ð,IÌ$ÈtË*ÈÐ*VÓWÐWru   c                ó&   — t        d„ | D «       «      S )zÌ
            Filters a set of symbols that are required for codegen. Skip symbols
            that are always internal to kernels, such as SymT.TMP, SymT.INDEX,
            and SymT.R0_INDEX.
            c              3  ó°   K  — | ]N  }t        |t        j                  t        j                  t        j                  t        j
                  f«      r|–— ŒP y ­wr~   )r)   r*   ÚSIZEÚFLOATrI
  rJ
  ©r·   r9  s     rs   r¹   zVScheduler.get_graph_partition_symbol_inputs.<locals>.filter_symbols.<locals>.<genexpr>."  sH   è ø€ ò àÜ!ØäŸ	™	ÜŸ
™
Ü×)Ñ)Ü×+Ñ+ð	ôô ñùs   ‚AAr   )Úsymbolss    rs   Úfilter_symbolszCScheduler.get_graph_partition_symbol_inputs.<locals>.filter_symbols&"  s   € ô ñ à ôó ð ru   c              3  ó2   K  — | ]  }t        |«      –— Œ y ­wr~   r  rÂ  s     rs   r¹   z>Scheduler.get_graph_partition_symbol_inputs.<locals>.<genexpr>="  s   è ø€ ÒI°tÔ,¨T×2ÑIùr  c              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­wr~   r…   )r·   r”   re
  s     €rs   r¹   z>Scheduler.get_graph_partition_symbol_inputs.<locals>.<genexpr>@"  s   øè ø€ ÒL¨tÑ$ T×*ÑLùr=  r×   rã  )r”   z+ir.IRNode | sympy.Expr | ir.TorchBindObjectr�   úOrderedSet[sympy.Symbol])rk
  ro
  r�   ro
  )r   r©  rÝ  rÝ   ra   rÁ   rÂ   rÃ   r&   rè  r  Ú
attrgetter)	rr   Ú	partitionrX
  rl
  Úcandidate_symbolsrã  r9  Úsymplified_sre
  s	           @rs   Ú!get_graph_partition_symbol_inputsz+Scheduler.get_graph_partition_symbol_inputs	"  sã   ø€ ð	XØ=ð	Xà%ó	Xð 	Ø-ð	à%ó	ð, 7I´j³l×6HÑ6HÙI¸yÔIð7
Ðð 	!Ð× Ñ ÛL°{×7IÑ7IÓ7KÔLñ	
ñ +Ð+<Ó=Ðä(2«ˆØ"ò 	2ˆAÜŸ7™7×+Ñ+×4Ñ4°QÓ7ˆLà�J‰J�|×0Ñ0Õ1ð	2ô
 œ& ¬(×*=Ñ*=¸fÓ*EÔFÓGÐGru   c           
     óŽ  ‡ ‡— g }t        t        j                  j                  «       «      }‰ j	                  «       }dˆˆ fd„Št        t        |«      t        |«      «      D �]2  \  }}t        «       }|D ]+  }	|j                  |	j                  j                  «       «       Œ- |j                  |«      }
t        j                  j                  |D �	cg c]  }	|	j                  ‘Œ c}	«      }t        |j                  |j                   z  D �cg c]  }t#        |t$        «      s|j&                  ‘Œ  c}«      |z
  }t        ˆ fd„|D «       «      }t        «       }|D ]  }	|j                  |	j(                  «       Œ ||z
  D �cg c]  }||v r|‘Œ
 }}|j                  |«       |D �ci c]  }||v r|||   “Œ }}|D �ci c]  }||v r|||v “Œ }}|D �cg c]  }||v r||vr|‘Œ }}|
j                  |«       t        ˆ fd„|
D «       «      }
|
D �cg c]  } ‰|«      s||   ‘Œ }}|D �cg c]!  }|t        j                  j*                  v sŒ |‘Œ# }}‰ j-                  ||«      }t/        ||||||«      }|j1                  |«       |j3                  ||
z
  «      }�Œ5 |ddd…   S c c}	w c c}w c c}w c c}w c c}w c c}w c c}w c c}w )z¡
        Gets signature for each graph partition, including input nodes, output nodes, and
        whether deallocating an input within graph partition.
        c                óÚ   •— ‰j                   j                  | d«      }|€yt        |j                  j                  t
        «      r'‰j                  j                  | d«      x}r ‰|«      S yy)zì
            Checks if buf_name resolves to a NoneLayout buffer (following mutation_real_name).
            Buffers with NoneLayout are not allocated so graph partition should not
            take them as inputs or outputs.
            NFT)r  r±  r²   r”   rí  rD   r�  )rÖ  rÞ   r3  Úis_unallocated_bufferrr   s      €€rs   rw
  zFScheduler.get_graph_partition_signature.<locals>.is_unallocated_bufferY"  sh   ø€ ð ×"Ñ"×&Ñ& x°Ó6ˆCàˆ{Øä˜#Ÿ(™(Ÿ/™/¬:Ô6ð !%× 7Ñ 7× ;Ñ ;¸HÀdÓ KÐK�9ÐKÙ0°Ó;Ð;ààru   c              3  óV   •K  — | ]   }‰j                   j                  ||«      –— Œ" y ­wr~   ©r�  r±  rb	  s     €rs   r¹   z:Scheduler.get_graph_partition_signature.<locals>.<genexpr>Œ"  ó,   øè ø€ ò /àð ×'Ñ'×+Ñ+¨D°$×7ñ/ùr  c              3  óV   •K  — | ]   }‰j                   j                  ||«      –— Œ" y ­wr~   ry
  rb	  s     €rs   r¹   z:Scheduler.get_graph_partition_signature.<locals>.<genexpr>¶"  rz
  r  Nr  )rÖ  r,  r�   r}   )r   ra   rÁ   r•  rT
  ry  rÐ   rÝ  r.  r!  rº  r/   r§  r¨  rÕ   rÖ   rQ  r²   r;   r×   r"  rp  rt
  rA   rä   r©  )rr   Ú
partitionsÚskip_cudagraphsr[
  Úunmet_output_namesrI  rq
  rW
  Úoutput_namesr”   Úreturned_output_namesrÕ   rˆ  Úpartition_input_namesr§  r×   Úextra_input_namesrX
  Úinput_deallocationÚextra_output_namesrY
  rZ
  Úsymbol_inputsÚpartition_signaturerw
  s   `                       @rs   Úget_graph_partition_signaturez'Scheduler.get_graph_partition_signatureM"  s^  ù€ ð ˆ
ä'¬¯©×(@Ñ(@Ó(BÓCÐØ×-Ñ-Ó/ˆö	ô, *-Ü�ZÓ ¤(¨?Ó";ó*
ó g	Ñ%ˆI�~ô -7«LˆLà!ò A�Ø×#Ñ# D×$8Ñ$8×$=Ñ$=Ó$?Õ@ðAð %1×$=Ñ$=Ð>PÓ$QÐ!ô '×1Ñ1×<Ñ<Ø.7Ö8 d�×!Ó!Ò8óˆKô ð "-×!2Ñ!2°[×5GÑ5GÑ!GöàÜ)¨!¬WÔ5ð Ÿ›òóð ñð "ô %/ó /à1ô/ó %Ð!ô
 5?³LÐ Ø!ò =�Ø$×+Ñ+¨D¯O©OÕ<ð=ð 2°LÑ@ö!àØ˜<Ñ'ò ð!Ðð !ð
 "×(Ñ(Ð):Ô;ð 2öàØ˜<Ñ'ð �l 4Ñ(Ñ(ðˆKð ð 2ö"àØ˜<Ñ'ð �dÐ2Ð2Ñ2ð"Ðð "ð 2ö"àØ˜<Ñ'¨DÐ8LÑ,Lò ð"Ðð "ð "×(Ñ(Ð);Ô<ä$.ó /à1ô/ó %Ð!ð 2öàÙ,¨TÔ2ð ˜TÓ"ðˆLð ð "7öØ¸$Ä!Ç'Á'×BSÑBSÒ:S’ðˆNð ð !×BÑBØ˜;óˆMô #:ØØØØ"ØØó#Ðð ×ÑÐ1Ô2à!6×!<Ñ!<Ø"Ð%:Ñ:ó"ÒðKg	ðR ™$˜B˜$ÑÐùòy 9ùòùò*!ùòùò
"ùò"ùòùòs6   ÃJ
Ä
#J$
Å>J)Æ"J.Æ9J3ÇJ8ÈJ=È%!KÉKc                óÌ  — |j                   j                  «       D ��ci c]  \  }}||vr||“Œ }}}|j                  j                  «       D ��ci c]  \  }}||vr||“Œ }}}|j                  D �cg c]  }|j	                  «       |vr|‘Œ }	}|j
                  D �cg c]	  }||vsŒ|‘Œ }
}t        |j                  ||	||j                  |
«      S c c}}w c c}}w c c}w c c}w )z™
        Updates the partition signature by removing buffers specified in
        removed_buffers. See [Note: Removed Graph Partition Arguments]
        )	rX
  rÀ  rƒ
  rY
  Úmaybe_get_namerZ
  rA   r…
  rW
  )rr   r_
  r  r×   r"  rX
  r	  rƒ
  r”   rY
  rZ
  s              rs   Ú.clean_removed_buffer_from_partition_signaturesz8Scheduler.clean_removed_buffer_from_partition_signaturesÚ"  s  € ð !*× 5Ñ 5× ;Ñ ;Ó =÷
á��fØ˜?Ñ*ð �&‰Lð
ˆñ 
ð '×9Ñ9×?Ñ?ÓA÷
á��cØ˜?Ñ*ð �#‰Ið
Ðñ 
ð "×.Ñ.ö
àØ×"Ñ"Ó$¨OÑ;ò ð
ˆð 
ð '×5Ñ5ö
Ø¸À_Ò9TŠDð
ˆð 
ô 'Ø×#Ñ#ØØØØ×$Ñ$Øó
ð 	
ùó%
ùó

ùò

ùò

s   žCÁCÁ1CÂ	C!Â&C!c                óp  ‡ ‡‡	‡
‡‡‡— ddl Š	t        «       Šg Šg Št        |«      D ��ci c]  \  }}||“Œ
 c}}Šdˆˆ	ˆˆˆ fd„Š
dˆ
ˆfd„}|D ]5  }t        |j                  j
                  «      ‰|<   ‰|   dk(  sŒ. ‰
|«       Œ7 g }d}|t        |«      k  r�‰s‰r}‰r0‰	j                  ‰«      \  }}|j                  |«        ||«       ‰rŒ0‰r0‰	j                  ‰«      \  }}|j                  |«        ||«       ‰rŒ0|dz  }|t        |«      k  r‰rŒz‰rŒ}|t        |«      kD  rt        d«      ‚|S c c}}w )aœ  
        Reorder nodes to minimize the number of partitions via a bfs
        topological sort. This is the optimal reordering such that the
        number of partitions cannot be reduced further. This may be
        sub-optimal for other metrics such as peak memory. This does not
        change relative orders of two cudagraphable nodes, nor the
        relative order of two non_cudagraphable nodes.
        r   Nc                ó€   •— ‰|    | f}‰j                  | «      r‰j                  ‰|«       y ‰j                  ‰|«       y r~   )rA
  Úheappush)r”   Únode_with_indexÚcudagraphable_nodesÚheapqÚnode_to_indexÚnon_cudagraphable_nodesrr   s     €€€€€rs   Úinsert_pending_nodeszHScheduler.reorder_for_minimizing_partition.<locals>.insert_pending_nodes#  s>   ø€ Ø,¨TÑ2°DÐ9ˆOØ×$Ñ$ TÔ*Ø—‘Ð6¸ÕHà—‘Ð2°OÕDru   c                óŒ   •— | j                   j                  D ]*  }‰|   dkD  sJ ‚‰|xx   dz  cc<   ‰|   dk(  sŒ# ‰|«       Œ, y rü  )r'  Ú
succ_nodes)r”   Ú	succ_noder“
  Únode_to_indegrees     €€rs   Úupdate_indegreezCScheduler.reorder_for_minimizing_partition.<locals>.update_indegree#  sT   ø€ Ø!Ÿ]™]×5Ñ5ò 4�	Ø'¨	Ñ2°QÒ6Ð6Ð6Ø  Ó+¨qÑ0Ó+Ø# IÑ.°!Ó3Ù(¨Õ3ñ	4ru   r   z’
                Failed to schedule, while loop ran too long when
                reordering for minimizing the num of partitions
                r>  )	r�
  rx  r’  rÎ   r'  Ú
pred_nodesÚheappoprä   rS  )rr   rq  rI  r”   r˜
  r…  Ú	num_itersr=  r�
  r�
  r“
  r—
  r‘
  r’
  s   `       @@@@@@rs   Ú reorder_for_minimizing_partitionz*Scheduler.reorder_for_minimizing_partitionþ"  sU  þ€ ó 	ä9=»ÐØCEÐØGIÐÜ4=¸eÓ4D×E¡y s¨D˜˜s™ÓEˆ÷	Eñ 	Eö	4ð ò 	+ˆDÜ%(¨¯©×)AÑ)AÓ%BÐ˜TÑ"Ø Ñ%¨Ó*Ù$ TÕ*ð	+ð
 -/ˆØˆ	Øœ#˜e›*Ò$Ù#Ñ':á)ØŸ-™-Ð(?Ó@‘��4Ø—‘ Ô%Ù Ô%ò *ñ
 &ØŸ-™-Ð(;Ó<‘��4Ø—‘ Ô%Ù Ô%ò &ð
 ˜‰NˆIð œ#˜e›*Ò$Ú#Ò':ð ”s˜5“zÒ!Üðóð ð ˆùó] Fs   ¨D2c           	     óˆ  — ddl m}m} t        t        j
                  j                  «       «      } ||| j                  | j                  t        t        j
                  j                  j                  «       «      |«      \  }}| j                  |«      } ||||«      \  }}	||t        j                  j                  z  k  r|S |S )zx
        Reorder nodes to minimize the number of partitions if this only slightly
        increase peak memory.
        r   )Úestimate_peak_memoryÚprepare_planning_info)r”  rž
  rŸ
  r   ra   rÁ   r•  r  r¹  rX  r!  rœ
  r-   r©   Ú!cudagraph_partition_memory_budget)
rr   rq  rž
  rŸ
  rš   Údefault_peak_memoryr4  Úreordered_nodesÚreorder_peak_memoryr=  s
             rs   rŸ  z0Scheduler.maybe_reorder_for_minimizing_partition?#  s·   € ÷ 	Hä"¤1§7¡7×#;Ñ#;Ó#=Ó>ˆá:OØØ×ÑØ×#Ñ#Ü”q—w‘w×+Ñ+×0Ñ0Ó2Ó3Øó;
Ñ7ÐÐ7ð ×?Ñ?ÀÓFˆÙ!5ØÐ7¸ó"
ÑÐ˜Qð
  Ø!¤F§M¡M×$SÑ$SÑSòTð #Ð"àˆru   c                ó  — g }g }g }dd„}|D ]n  }| j                  |«      du}|r*t        |j                  «      dk(  r|j                  |«       ŒB|r ||«      r|j                  |«       Œ^|j                  |«       Œp ||z   |z   S )a  
        Reorder a node if it should be partitioned and has simple dependency:
        1. move a partitioned node to the front if it has no dependency
        2. move a partitioned node to the back if it is only used by OutputNode
        3. otherwise do not reorder
        c                óŠ   — | j                  «       D ]0  }|j                  D ]  }t        |j                  t        «      rŒ  y Œ2 yr  )r<  rß  r²   r”   r  )r”   rÞ   r  s      rs   Úonly_output_userzPScheduler.reorder_for_partition_with_simple_dependency.<locals>.only_output_usern#  sC   € Ø×'Ñ'Ó)ò %�ØŸ9™9ò %�CÜ% c§h¡h´
Õ;Ú$ñ%ð%ð ru   Nr   r*  )rA
  rÎ   r3  rä   )rr   rq  ÚfrontÚmiddleÚbackr¦
  r”   rA
  s           rs   r   z6Scheduler.reorder_for_partition_with_simple_dependency`#  s”   € ð *,ˆØ*,ˆØ(*ˆó	ð ò 	$ˆDØ#×4Ñ4°TÓ:À$ÐFÐÙ¤C¨×(?Ñ(?Ó$@ÀAÒ$EØ—‘˜TÕ"Ù!Ñ&6°tÔ&<Ø—‘˜DÕ!à—‘˜dÕ#ð	$ð �v‰~ Ñ$Ð$ru   c                ó€  — g }d}g }g }| j                   D ]S  }| j                  |«      du}|r)||k7  r$|j                  |«       |j                  |«       g }|}|j                  |«       ŒU |r"|j                  |«       |j                  |«       t        j                  j
                  }|dkD  rXt        t        ||«      «      D ]@  \  }\  }	}
|
rŒt        d„ |	D «       «      }||k  sŒ$d||<   t        j                  d|||«       ŒB | j                  ||¬«      }| j                  |«       | j                  ||«       ||fS )z’
        Given a list of BaseSchedulerNodes, split into a list of
        graph partitions and compute partition input/output signatures.
        TNr   c              3  ó@   K  — | ]  }t        |t        «      sd –— Œ y­w©r   N)r²   r  rÌ  s     rs   r¹   z,Scheduler.graph_partition.<locals>.<genexpr> #  s#   è ø€ ò 'àÜ)¨!Ô-CÔDô ñ'ùrš  zFPartition %d has %d kernels, below minimum size %d, skipping cudagraph)r|
  r}
  )rq  rA
  rä   r-   r©   Úcudagraph_min_partition_sizer’  ry  rü   Úcudagraphs_logrÝ  r‡
  rb
  Ú_log_graph_partitions)rr   r|
  rW
  Úcur_partitionr}
  r”   Únode_should_partitionÚmin_sizer�  rq
  ÚskipÚkernel_countr[
  s                rs   r�  zScheduler.graph_partition€#  sm  € ð +-ˆ
ØˆØ')ˆØˆØ—J‘Jò 	'ˆDØ$(×$9Ñ$9¸$Ó$?ÀtÐ$KÐ!Ù Ð3HÒ!HØ×!Ñ! -Ô0Ø×&Ñ& ~Ô6Ø "�à2ˆNØ× Ñ  Õ&ð	'ñ Ø×Ñ˜mÔ,Ø×"Ñ" >Ô2ô —=‘=×=Ñ=ˆØ�aŠ<Ü(1´#°jÀ/Ó2RÓ(Sò Ñ$�Ñ$�I˜tÚä#&ñ 'à!*ô'ó $�Lð
 $ hÓ.Ø-1˜¨Ñ*Ü&×,Ñ,ØdØØ(Ø$õ	ðð" ×7Ñ7Ø!°?ð 8ó 
ˆ
ð 	×)Ñ)¨*Ô5à×"Ñ" :¨zÔ:à˜:Ð%Ð%ru   c                ó`  — t         j                  t        j                  «      sy t	        d„ t
        j                  j                  D «       «      }|sy t        d„ |D «       «      }t        |«      |z
  }t         j                  dt        |«      ||«       t        t        ||«      «      D ]„  \  }\  }}t         j                  d|t        |«      |j                  rdndt        |j                  «      t        |j                  «      «       |j                  sŒm|D ]  }	| j!                  |	«       Œ Œ† y )Nc              3  ó2   K  — | ]  }t        |«      –— Œ y ­wr~   )r[   )r·   rÝ  s     rs   r¹   z2Scheduler._log_graph_partitions.<locals>.<genexpr>Á#  s   è ø€ ÒO°œV FŸ^ÑOùr  c              3  ó:   K  — | ]  }|j                   rŒd –— Œ y­wr¬
  )rW
  rj
  s     rs   r¹   z2Scheduler._log_graph_partitions.<locals>.<genexpr>Å#  s   è ø€ Ò!P¨¸q×?OÓ?O¤!Ñ!Pùs   ‚”zCCreated %d graph partitions: %d cudagraphable, %d non-cudagraphablez3  Partition %d: %d nodes, %s, inputs=%d, outputs=%dznon-cudagraphableÚcudagraphable)r®
  rÓ  rÔ  rÅ  r  ra   rÁ   Údevice_typesrü   rÎ   rÝ  r’  ry  rW
  rX
  rY
  Ú_log_non_cudagraphable_node)
rr   r|
  r[
  Úhas_gpu_deviceÚcudagraphable_countÚnon_cudagraphable_countr�  rq
  r_
  r”   s
             rs   r¯
  zScheduler._log_graph_partitions·#  s  € ô
 ×*Ñ*¬7¯=©=Ô9Øô ÑO¼!¿'¹'×:NÑ:NÔOÓOˆÙØä!Ñ!P¨ZÔ!PÓPÐÜ"% j£/Ð4GÑ"GÐÜ×ÑØQÜ�
‹OØØ#ô		
ô *3´3°zÀ:Ó3NÓ)Oò 	;Ñ%ˆAÑ%�	˜9Ü× Ñ ØEØÜ�I“Ø'0×'?Ò'?Ñ#À_Ü�I×)Ñ)Ó*Ü�I×*Ñ*Ó+ôð ×'Ó'à%ò ;�DØ×4Ñ4°TÕ:ñ;ñ	;ru   c                ó¢  — | j                  |«      }|sy|j                  «       }|j                  �|j                  j                  «       nd}d|› �g}t	        |j                  «      j
                  }|j                  d|› �«       |�F|j                  › ddj                  d„ |j                  D «       «      › d�}|j                  d|› �«       t        j                  d	|dj                  |«      «       |�Z|j                  j                  d
d«      }|r;|j                  «       j                  d«      D ]  }	t        j                  d|	«       Œ yyy)z)Log details for a non-cudagraphable node.Nzreason=zir=rE  r]  c              3  ó2   K  — | ]  }t        |«      –— Œ y ­wr~   )r,  )r·   r²  s     rs   r¹   z8Scheduler._log_non_cudagraphable_node.<locals>.<genexpr>ç#  s   è ø€ Ò2P¸a´3°q·6Ñ2Pùr  r@  zfx=z
    %s: %sr  rH  z         %s)rA
  râ  r”   r_  r«   r€   rä   r  rd  rù  r®
  rÝ  r  r±  ÚstripÚsplit)
rr   r”   r×  rM  rb  ÚpartsÚir_typeÚfx_strr  Úlines
             rs   rº
  z%Scheduler._log_non_cudagraphable_nodeÛ#  s1  € à×&Ñ& tÓ,ˆÙØà—M‘M“Oˆ	Ø15·±Ð1F�$—)‘)×+Ñ+Ô-ÈDˆØ˜6˜(Ð#Ð$ˆÜ�t—y‘y“/×*Ñ*ˆØ�‰�s˜7˜)�_Ô%ØÐØŸ™Ð' q¨¯©Ñ2PÀ7Ç<Á<Ô2PÓ)PÐ(QÐQRÐSˆFØ�L‰L˜3˜v˜h˜Ô(ä×Ñ˜\¨9°d·i±iÀÓ6FÔGð ÐØ!Ÿ,™,×*Ñ*¨=¸$Ó?ˆKÙØ'×-Ñ-Ó/×5Ñ5°dÓ;ò >�DÜ"×(Ñ(¨¸Õ=ñ>ð ð ru   c                óä   — t        d«      5  t        j                  j                  j                  r| j                  «       n| j                  | j                  «      	 cd d d «       S # 1 sw Y   y xY w)NzScheduler.codegen)r   r`  ra  r-   r�  Ú_codegen_partitionsÚ_codegenrq  rq   s    rs   r  zScheduler.codegenó#  sX   € ÜÐ-Ó.ñ 	ô —?‘?×)Ñ)×9Ò9ð ×(Ñ(Ô*à—]‘] 4§:¡:Ó.ð÷	÷ 	ò 	ús   ŒAA&Á&A/c                óê  — ddl m} t        j                  j                  }t        | j                  «      }t        j                  j                  «       5  t        j                  j                  dd|› �||¬«       t        j                  j                  j                  «       }| j                  |«       t        t        j                  j                  |«      sJ ‚t        j                  j                  |z
  }| j                  ||«      }|t        j                  j                  _        t        j                  j                  j                  «        t        j                  j                   }t        j                  j                  j#                  t        j                  j$                  «      \  }	}
ddd«       t        j                  j                  j'                  	«       t        j                  j                  j)                  ||«       t        j                  j                  j*                  j-                  |j.                  D �cg c]  }|j1                  «       ‘Œ c}«       y# 1 sw Y   Œ·xY wc c}w )z,Codegen a partition given its inputs/outputsr   )ÚSubgraphPythonWrapperCodegenTÚ
partition_)Úis_subgraphÚsubgraph_nameÚparent_wrapper_codeÚpartition_signaturesN)rþ  rÊ
  ra   rÁ   rÿ  r‘  ro  Úset_current_wrapper_codeÚinit_wrapper_coder  rx  rÈ
  r²   rŠ
  rÏ
  Úwrite_prefixr×   ÚgenerateÚis_inferenceÚdefine_subgraph_launcher_fnÚcodegen_partition_callÚ	allocatedrÝ  rY
  râ  )rr   rq
  r_
  rÊ
  rÎ
  Úgraph_partition_idÚremoved_buffers_before_codegenÚremoved_buffers_during_codegenÚ
graph_nameÚpartition_coder=  r”   s               rs   Ú_codegen_partition_wrapperz$Scheduler._codegen_partition_wrapperû#  sÊ  € õ 	BäŸg™g×2Ñ2ÐÜ! $×"?Ñ"?Ó@Ðä�W‰W×-Ñ-Ó/ñ 	TÜ�G‰G×%Ñ%Ø Ø *Ð+=Ð*>Ð?Ø$7Ø%.ð	 &ô ô ./¯W©W×-DÑ-D×-IÑ-IÓ-KÐ*Ø�M‰M˜)Ô$ô œaŸg™g×2Ñ2Ð4PÔQÐQÐQä—‘×'Ñ'Ð*HÑHð +ð ×KÑKØÐ9óˆIð 9BŒA�G‰G× Ñ Ô5Ü�G‰G× Ñ ×-Ñ-Ô/äŸ™Ÿ™ˆJÜ !§¡× 4Ñ 4× =Ñ =¼a¿g¹g×>RÑ>RÓ SÑˆN˜A÷?	TôB 	
�‰×Ñ×8Ñ8¸À^ÔTä	�‰×Ñ×3Ñ3Ð4FÈ	ÔRÜ	�‰×Ñ×&Ñ&×-Ñ-Ø)2×)?Ñ)?Ö@ ˆT�]‰]�_Ò@õ	
÷I	Tð 	TüòJ As   ÁEI$ÉI0É$I-c                óL   ‡ ‡‡— t         j                  dˆˆ ˆfd„«       } |«       S )Nc               3  ó¸  •K  — ‰j                  ‰ ‰«       ‰j                  ryt        ‰j                  j                  «      rZ‰j                  j                  €J d«       ‚t
        j                  j                  j                  ‰j                  j                  «       	 d –— ‰j                  rGt        ‰j                  j                  «      r(t
        j                  j                  j                  «        d ‰_        y # ‰j                  rGt        ‰j                  j                  «      r(t
        j                  j                  j                  «        d ‰_        w xY w­w)Núdevice should have an index)
Ú%update_graph_partition_default_devicerv  rQ   r«   rØ   ra   rÁ   rÿ  Úcodegen_device_guard_enterÚcodegen_device_guard_exit)r|
  rr   r[
  s   €€€rs   Úctxz1Scheduler.use_default_device_context.<locals>.ctx1$  s  øè ø€ à×6Ñ6°zÀ:ÔNØ×*Ò*Ô/@Ø×+Ñ+×0Ñ0ô0ð ×2Ñ2×8Ñ8ÐDð Ø1óÐDô —‘×$Ñ$×?Ñ?Ø×/Ñ/×5Ñ5ôð3Ûà×.Ò.Ô3DØ×/Ñ/×4Ñ4ô4ô —G‘G×(Ñ(×BÑBÔDØ.2�Õ+øð	 ×.Ò.Ô3DØ×/Ñ/×4Ñ4ô4ô —G‘G×(Ñ(×BÑBÔDØ.2�Õ+üs    ƒBEÂC; Â AEÃ;AEÅE)r�   zIterator[None])Ú
contextlibÚcontextmanager)rr   r|
  r[
  rä
  s   ``` rs   Úuse_default_device_contextz$Scheduler.use_default_device_context.$  s&   ú€ ô 
×	"Ñ	"ö	3ó 
#ð	3ñ* ‹uˆru   c                ó   — t        |«      dk(  r|d   j                  sy dd„}	 	 	 	 	 	 dd„}d }t        ||«      D ]  \  }}|j                  rŒ ||«      } n |€y t        ||«      D ]  \  }}|j                  sŒ |||«      rŒ y  || _        y )Nr   r   c                ó4   — | d   j                  «       }|€J ‚|S ré   r¶  )rq
  Úpartition_devices     rs   Úget_cudagraph_partition_devicezWScheduler.update_graph_partition_default_device.<locals>.get_cudagraph_partition_deviceX$  s'   € Ø(¨™|×6Ñ6Ó8ÐØ#Ð/Ð/Ð/Ø#Ð#ru   c                ó@   — | D ]  }|j                  «       }||k7  sŒ y yr  r¶  )rq
  Útarget_devicer”   rÝ  s       rs   Úall_on_target_devicezMScheduler.update_graph_partition_default_device.<locals>.all_on_target_device]$  s/   € ð "ò !�ØŸ™Ó*�Ø˜]Ó*Ù ð!ð ru   )rq
  rg   r�   rý  )rq
  rg   rí
  rý  r�   r}   )rÎ   rW
  ry  rv  )rr   r|
  r[
  rë
  rî
  Úcudagraph_partition_devicerq
  r_
  s           rs   rá
  z/Scheduler.update_graph_partition_default_deviceI$  sÊ   € ô ˆz‹?˜aÒ¨
°1©×(DÒ(Dð ó	$ð
	Ø$ð	Ø5Að	àó	ð &*Ð"Ü$'¨
°JÓ$?ò 	Ñ ˆI�yØ×+Ó+Ù-KÈIÓ-VÐ*Ùð	ð &Ð-Øä$'¨
°JÓ$?ò 	Ñ ˆI�yØ×'Ó'Ñ0DØÐ5õ1ñ ð		ð 'AˆÕ#ru   c                ó  — | j                  «       \  }}t        |«      dkD  rt        d   dxx   t        |«      z  cc<   | j                  ||«      5  t	        ||«      D ]V  \  }}t        |«      dk\  sJ dt        |«      › �«       ‚|j
                  r| j                  |«       ŒE| j                  ||«       ŒX 	 ddd«       t        | j                  «      }t        j                  j                  j                  |«       |dkD  rqt        j                  j                  €J ‚|t        t        j                  j                  «      k(  s.J d|› dt        t        j                  j                  «      › �«       ‚yy# 1 sw Y   Œ¾xY w)	zÊ
        Split nodes into partitions and codegen each partition into separate functions.
        This allows further applying different optimizations (e.g., cudagraph) to
        each function.
        r   r]  Úcudagraph_partitionsz5Each partition must have at least one node but found Nr   zExpect z partition maps but got )r�  rÎ   r   rç
  ry  rW
  rÈ
  rÝ
  r‘  ro  ra   rÁ   rÿ  Úset_all_partition_namesrV
  )rr   r|
  r[
  rq
  r_
  Únum_partitionss         rs   rÇ
  zScheduler._codegen_partitionsx$  sh  € ð "&×!5Ñ!5Ó!7Ñˆ
�Jäˆz‹?˜QÒÜ�ZÑ Ð!7Ó8¼CÀ
»OÑKÓ8à×,Ñ,¨Z¸ÓDñ 		JÜ(+¨J¸
Ó(Cò JÑ$�	˜9Ü˜9“~¨Ò*ð ØKÌCÐPYËNÐK[Ð\óÐ*ð ×+Ò+Ø—M‘M )Õ,à×3Ñ3°I¸yÕIñJ÷		Jô ˜d×;Ñ;Ó<ˆÜ	�‰×Ñ×4Ñ4°^ÔDð ˜AÒÜ—7‘7×)Ñ)Ð5Ð5Ð5Ø!¤S¬¯©×)?Ñ)?Ó%@Ò@ð Ø˜.Ð)Ð)AÄ#ÄaÇgÁg×F\ÑF\ÓB]ÐA^Ð_óÑ@ð ÷		Jð 		Jús   ÁA&E5Å5E>c                óÐ  — t         j                  r¿dd l}t        j                  «       }t        «       }t        |«      D ]�  }|j                  dk(  r/|j                  |j                  j                  j                  k(  r nQ|j                  |j                  f}||vs"J d|j                  › d|j                  › d�«       ‚|j                  |«       Œ‘ | j                  | _        | j                   �J ‚| j                  rBt         j"                  j$                  r(t&        j(                  j*                  j-                  «        t&        j(                  j*                  j/                  «        |D �]Ã  }t0        j3                  t4        j6                  «      r4	 t0        j9                  d|j;                  «       |j=                  «       «       | jA                  |«       t         jB                  rDt&        j(                  j*                  jE                  d„ |jF                  jH                  D «       «       |jK                  «       x}�rs|| j                  k7  s |jM                  «       s|jO                  «       r| jQ                  «        || j                  k7  �r$| j                  rctS        | j                  jT                  «      rD| jV                  �| jY                  «        t&        j(                  j*                  j[                  «        || _        tS        |jT                  «      r™|j\                  €J d	«       ‚d
}	| j_                  «       r5t        | j`                  jc                  «       «      }
|
rte        |
«      d
z   nd
}	t&        j(                  j*                  jg                  |j\                  |	| jh                  «       | j_                  «       r| j                  �| jk                  |«       t&        j(                  j*                  jm                  d„ |jF                  jH                  D «       «       || _7        | jp                  js                  |jt                  «       |jO                  «       rP|jw                  ty        |j{                  «       «      «      \  }}}| j}                  |«      j                  |||«       �nf|jM                  «       r| j�                  |«       �nC|jƒ                  «       rxt…        j†                  tˆ        |«      }| j}                  |«      }d
dlEmF} d
dlGmH} d
dlImJ} t—        ||||f«      r|}nt™        dtU        | «      ›�«      ‚|j›                  |«       n»t—        |tœ        «      r!| j}                  |«      jŸ                  |«       nŠt—        |t         «      r!| j}                  |«      j£                  |«       nYt—        |t¤        t¦        f«      r!| j}                  |«      j©                  |«       n"t—        |tª        «      sJ ‚|j­                  «        t         j"                  j®                  r| j}                  |«      j±                  «        | j²                  js                  |jµ                  «       «       | j¶                  js                  |j¹                  «       «       t—        |tª        «      sP|jK                  «       }|�>|jT                  dk7  r/| j}                  |«      j»                  «       r| jQ                  «        t½        d„ |j{                  «       D «       «      r	|| _        �Œ½d | _        �ŒÆ | j                  | j                  k7  rU| j                  €J ‚tS        | j                  jT                  «      r(t&        j(                  j*                  j[                  «        d | _        | jQ                  «        y # t>        $ r( t0        j9                  d|j;                  «       «       Y �Œ"w xY w)Nr   Ú_compile_innerzDuplicate stack frame ú:zs; did you add a decorator to one of the functions in this stack trace?  If so, try using a context manager instead.z5Generating code for node %s with estimated runtime %fz6Generating code for node %s with estimated runtime 0.0c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   z%Scheduler._codegen.<locals>.<genexpr>Ê$  s   è ø€ ò DØ!$�C—H•HñDùrv  rà
  r   c              3  ó4   K  — | ]  }|j                   –— Œ y ­wr~   rt  ru  s     rs   r¹   z%Scheduler._codegen.<locals>.<genexpr>û$  s   è ø€ ò CØ �—•ñCùrv  )ÚCUDACombinedSchedulingr†  )ÚXPUCombinedSchedulingztype(self)=r  c              3  ó<   K  — | ]  }t        |t        «      –— Œ y ­wr~   r)	  rÌ  s     rs   r¹   z%Scheduler._codegen.<locals>.<genexpr>:%  s   è ø€ ÒJ°A”:˜a¤×/ÑJùrÃ  )_r-   Ú"check_stack_no_cycles_TESTING_ONLYÚtorch._dynamo.convert_frameÚ	tracebackÚextract_stackr   rÐ   r×   ÚfilenameÚ_dynamoÚconvert_frameÚ__file__Úlinenor¢  rv  rÉ  rs  r©   Úautotune_at_compile_timera   rÁ   rÿ  Úwrite_get_raw_stream_headerÚregister_alignment_check_inputsrT  rÓ  rÔ  rÅ  rÝ  râ  rh  rS  r9
  Úsize_assertsÚcodegen_deferred_input_assertsrÕ   rÖ   rª   ré  rç  r%
  rQ   r«   Úcurrent_stream_idxÚgenerate_stream_ctx_exitrã
  rØ   rÂ  rv  rÝ   rY  râ
  rˆ  Úgenerate_stream_ctx_switchingÚ!codegen_deferred_alignment_copiesrt  r§  rÝ  r"  r—  r¥   r»   r#  Úcodegen_templater+
  rë  r»  r¼  rB  Ú codegen.cuda_combined_schedulingrù
  r�  r‡  Ú#codegen.xpu.xpu_combined_schedulingrú
  r²   rw  Úcodegen_combo_kernelr  Úcodegen_nested_reductionrÿ  Úcodegen_mix_order_reductionrÚ   r³   Úcodegen_noder  r—  Údebug_sync_kernelÚcodegen_syncr¨  rÇ  r  r  Úready_to_flushrº   )rr   rq  r`  rŒ  rD  Úframerä  r”   rÝ  Únum_streamsÚunique_streamsr”  r•  r–  Úbackend_rù
  r‡  rú
  r  s                      rs   rÈ
  zScheduler._codegen˜$  s>  € Ü×4Ò4Û.ä×+Ñ+Ó-ˆEÜ7A³|ˆDÜ! %›ò �ð —J‘JÐ"2Ò2ØŸ™¨%¯-©-×*EÑ*E×*NÑ*NÒNáØ—~‘~ u§|¡|Ð4�Ø $‘ð Ø,¨U¯^©^Ð,<¸A¸e¿l¹l¸^ð LJð Jó�ð
 —‘˜•ðð #×9Ñ9ˆÔØ×!Ñ!Ð)Ð)Ð)ð ×&Ò&¬6¯=©=×+QÒ+QÜ�G‰G× Ñ ×<Ñ<Ô>ô 	
�‰×Ñ×<Ñ<Ô>àó E	*ˆDÜ×Ñ¤§¡Ô.ð
Ü—I‘IØOØŸ™›Ø×2Ñ2Ó4ôð ×Ñ˜tÔ$ô ×"Ò"Ü—‘×$Ñ$×CÑCñ DØ(,×(8Ñ(8×(>Ñ(>ôDô ð Ÿ™Ó*Ð*ˆvÑ*à˜d×1Ñ1Ò1Ø—~‘~Ô'Ø×'Ñ'Ô)à—J‘J”LØ˜T×0Ñ0Ó0Ø×*Ò*Ô/@Ø×+Ñ+×0Ñ0ô0ð  ×2Ñ2Ð>Ø ×9Ñ9Ô;ÜŸ™×,Ñ,×FÑFÔHØ*0�DÔ'Ü(¨¯©Ô5Ø%Ÿ|™|Ð7ÐVÐ9VÓVÐ7à&'˜Ø×7Ñ7Ô9ä-7¸×8KÑ8K×8RÑ8RÓ8TÓ-U˜Ná;I¤ NÓ 3°aÒ 7Èqð (ô Ÿ™×,Ñ,×GÑGØ"ŸL™LØ'Ø ×;Ñ;ôð ×+Ñ+Ô-°$×2EÑ2EÐ2QØ×2Ñ2°4Ô8ô �G‰G× Ñ ×BÑBñ CØ$(×$4Ñ$4×$:Ñ$:ôCô ð !%ˆDÔØ×%Ñ%×,Ñ,¨T¯_©_Ô=à×ÑÔ!Ø48×4WÑ4WÜ˜Ÿ™Ó)Ó*ó5Ñ1�˜-¨ð × Ñ  Ó(×9Ñ9Ø! 8¨Xöð —‘Ô!Ø×(Ñ(¨Ö.Ø—‘Ô"Ü—{‘{Ô#=¸tÓD�à×+Ñ+¨FÓ3�ÝTÝ8ÝVäØØ#Ð%;Ð=RÐSôð '‘Gä(¨K¬D°«J¨=Ð)9Ó:Ð:Ø×,Ñ,¨TÕ2Ü˜DÔ"7Ô8à× Ñ  Ó(×AÑAÀ$ÕGÜ˜DÔ"9Ô:à× Ñ  Ó(×DÑDÀTÕJÜ˜DÔ#5´}Ð"EÔFà× Ñ  Ó(×5Ñ5°dÕ;ä! $Ô(>Ô?Ð?Ð?Ø—‘”ô �}‰}×.Ò.à× Ñ  Ó(×5Ñ5Ô7à×'Ñ'×.Ñ.¨t×/DÑ/DÓ/FÔGØ×%Ñ%×,Ñ,¨T×-EÑ-EÓ-GÔHä˜dÔ$:Ô;ØŸ™Ó*�àÐ&ØŸ™ vÒ-Ø×(Ñ(¨Ó0×?Ñ?ÔAà—J‘J”LäÑJ¸¿¹Ó9IÔJÔJØ%)�Ö"à%)�Ö"ðKE	*ðN ×Ñ $×"=Ñ"=Ò=ð ×&Ñ&Ð2Ð2Ð2Ü  ×!4Ñ!4×!9Ñ!9Ô:ô —‘×$Ñ$×>Ñ>Ô@à!ˆÔØ�
‰
�øôU !ò Ü—I‘IØPØŸ™›÷ðús   Æ3^4Þ4-_%ß$_%c                ó®   — |d   j                  «       }| t        j                  _        || _        |€J ‚| j                  |«      }|j                  ||«      S )rq  r   )rª   ra   rÁ   rÜ  rÉ  r#  Úbenchmark_combo_kernel)rr   r°  Únode_benchmark_resultsrÝ  r  s        rs   r  z Scheduler.benchmark_combo_kernelL%  sZ   € ð ˜1‘×(Ñ(Ó*ˆØ Œ�‰ÔØ$ˆÔØÐ!Ð!Ð!Ø×"Ñ" 6Ó*ˆØ×-Ñ-¨iÐ9OÓPÐPru   c                ó  ‡— |}|d   j                  «       Št        ˆfd„|D «       «      sJ d«       ‚t        j                  syddlm} dg }}i }t        |«      D ]›  \  }}|j                  «       }	| j                  |	«      rt        j                  d«       	 | j                  |	«      \  }
}|
|f||<   t        j                  |
«      rt        j                  d|«        y		 ||
z  }|j                  |«       Œ� 	 | j                  ||«      \  }}}||z
  dk  xs |dk  }t        j!                  t"        j$                  «      rP||kD  s|r%t        j                  dt'        ||z  d›«      «       n$t        j                  dt)        ||z  d›«      «       ||z
  |k  xs |S # |$ r.}d
t        |«      v rt        j                  d«       Y d}~ y‚ d}~ww xY w# |$ r-}d
t        |«      v rt        j                  d«       Y d}~y‚ d}~ww xY w)r¿  r   c              3  óD   •K  — | ]  }|j                  «       ‰k(  –— Œ y ­wr~   r¶  )r·   r”   rÝ  s     €rs   r¹   z4Scheduler.speedup_by_combo_kernel.<locals>.<genexpr>c%  s   øè ø€ ÒK°4�4—?‘?Ó$¨Õ.ÑKùs   ƒ z<All nodes in a combo kernel group must be on the same deviceTrÁ  rL  z<ComboKernel: benchmarking may not accurate due to atomic_addz;ComboKernel benchmark: register spilling of %d-th subkernelFrý  zCComboKernel benchmark: return True because of loop-carried variableNg333333Ó?z/can fuse (benchmark): fusing causes %sx speeduprÄ  z3cannot fuse (benchmark): fusing causes %sx slowdown)rª   rº   r-   r  r  rÂ  r’  r»   r±  rÜ  rÝ  rr  r  rÿ  r,  rä   rÓ  rÔ  rÅ  rJ   rL   )rr   rq  Úsubkernel_nodesrÂ  rì  Ú
path1_listr  r�  r¸  r°  r{  rä  r&  rí  Ú	ms2_cloneÚ_path2_listÚsmall_kernelrÝ  s                    @rs   rZ  z!Scheduler.speedup_by_combo_kernelZ%  s(  ø€ ð  ˆØ  Ñ#×.Ñ.Ó0ˆäÓK¸?ÔKÔKð 	
ØJó	
ÐKô ×,Ò,Øå;à˜rˆZˆØ!#ÐÜ! /Ó2ò 	$‰HˆAˆuØŸ™Ó)ˆIð ×#Ñ# IÔ.Ü× Ñ ØRôðØ×5Ñ5°iÓ@‘��DØ13°T°
Ð& uÑ-Ü—:‘:˜b”>Ü×$Ñ$ØUØôñ !ð "ð �2‰IˆCØ×Ñ˜dÕ#ð9	$ð<	Ø*.×*EÑ*EØÐ!7ó+Ñ'ˆC�˜Kð ˜Y‘¨Ñ,Ò9°°c±	ˆÜ×"Ñ"¤7§=¡=Ô1Ø�SŠy™LÜ× Ñ ØEÜ #¨¡)¨C Ó2õô
 × Ñ ØIÜ  c¡	¨#˜Ó0ôð
 �Y‰ Ñ$Ò4¨Ð4øðQ $ò à*¬c°!«fÑ4Ü×$Ñ$Ø]ôõ  àûðûð   ò 	à&¬#¨a«&Ñ0Ü× Ñ ØYôô àûð	ús=   ÂAFÃ9G ÆGÆ""GÇ
GÇGÇHÇ"H Ç?H È Hc                óp   — | j                   |   }|j                  €J ‚|j                  j                  «       S r~   )r  r”   Ú
get_layout)rr   rÖ  rÞ   s      rs   Úget_buffer_layoutzScheduler.get_buffer_layoutª%  s5   € Ø×Ñ˜xÑ(ˆØ�x‰xÐ#Ð#Ð#Ø�x‰x×"Ñ"Ó$Ð$ru   c                óØ  — | j                   D ]Û  }|j                  «       sŒ|j                  j                  D ]¯  }t        j
                  j                  j                  |j                  «      }|sŒ9t        |«      dk(  sŒHt        |j                  t        t        f«      rŒi|j                  «       g k(  sŒ}t        j
                  j                  j!                  |j                  «       Œ± ŒÝ y rÚ  )rq  r[   rÕ   rÖ   ra   rÁ   r£  r±  r×   r@   r²   rí  rD   rC   rc  Úzero_dim_cpu_tensor_listr¢  )rr   r”   r  r"  s       rs   ru  z$Scheduler.update_zero_dim_cpu_tensor¯%  s¯   € Ø—J‘Jò 	HˆDØ�{‰{�}Ø ×,Ñ,×2Ñ2ò 
H�DÜŸW™W×3Ñ3×7Ñ7¸¿	¹	ÓB�FâÜ+¨FÓ3°uÓ<Ü *Ø"ŸM™M¬JÔ8IÐ+Jõ!ð #ŸO™OÓ-°Ó3äŸ™×8Ñ8×<Ñ<¸T¿Y¹YÕGñ
Hñ	Hru   c                óH   — | j                   �| j                   j                  S y)z:CUDA Stream index that current scheduler node assigned to.N)r©  r¹  rq   s    rs   r
  zScheduler.current_stream_idx¾%  s%   € ð ×#Ñ#Ð/Ø×+Ñ+×6Ñ6Ð6àru   c                ó6   — | j                   x}�t        |«      S y)z9CUDA Stream name that current scheduler node assigned to.N)r
  r%   )rr   r¹  s     rs   Úcurrent_stream_namezScheduler.current_stream_nameÆ%  s#   € ð ×1Ñ1Ð1ˆJÐ>Ü" :Ó.Ð.àru   c                ó¤   — t        |t        «      rJ ‚| j                  |   }t        j                  j
                  j                  |¬«      | _        y)z6Code-gen to enter the Stream context assigned to node.)r¹  N)r²   r  rv  ra   rÁ   rÿ  Úcodegen_cuda_stream_enterr©  )rr   r”   Únode_streams      rs   Úgenerate_stream_ctx_enterz#Scheduler.generate_stream_ctx_enterÎ%  sI   € ä˜dÔ$:Ô;Ð;Ð;Ø×)Ñ)¨$Ñ/ˆÜ#$§7¡7×#7Ñ#7×#QÑ#QØ"ð $Ró $
ˆÕ ru   c                ó~   — | j                   €J ‚t        j                  j                  j	                  «        d| _         y)z1Code-gen to exit from the current Stream context.N)r©  ra   rÁ   rÿ  Úcodegen_cuda_stream_exitrq   s    rs   r  z"Scheduler.generate_stream_ctx_exitÖ%  s2   € à×'Ñ'Ð3Ð3Ð3Ü	�‰×Ñ×5Ñ5Ô7Ø#'ˆÕ ru   c                ó&  — || j                   v sJ ‚t        |t        «      rdn| j                   |   }| j                  |k(  ry| j                  �|€y| j                  €|�| j	                  |«       y| j                  «        | j	                  |«       y)am  Generate stream entering and exiting to properly run node in a multi-stream scenario.

        Stream context switching is only generated if ``node``'s assigned stream is different from
        the previous node's stream. NopKernelSchedulerNodes have stream=None and inherit the
        enclosing stream context (or do nothing if no context is active yet).
        N)rv  r²   r  r
  r1  r  )rr   r”   rQ  s      rs   r  z'Scheduler.generate_stream_ctx_switchingÜ%  s¢   € ð �t×*Ñ*Ñ*Ð*Ð*ô ˜$Ô 6Ô7ñ à×$Ñ$ TÑ*ð 	ð
 ×"Ñ" fÒ,ð Ø×$Ñ$Ð0°V°^ð Ø×$Ñ$Ð,°Ð1Cà×*Ñ*¨4Õ0ð ×)Ñ)Ô+Ø×*Ñ*¨4Õ0ru   )rq  zlist[ir.Operation]r�   r  )r�   z!dict[str, SchedulerDonatedBuffer]r  r  )rÖ  r,  r�   r‘   )rÖ  r,  r”   rf   r�   r}   r  )rÝ  r  r�   r  )rÖ  r,  r�   r  )r”   r˜  r�   rf   )r•  ú
str | Noner�   r}   r“  )r¸  rf   r�   r¦  )r�   r”  ©rq  rÔ  r�   útuple[float, str]r~   ©rq  rÔ  rz  r}   ry  r£  r�   r,  )r~  r   rÝ  rý  r�   r7  )r…  úir.MultiTemplateBufferr�   r}   )
r¥  úir.OperationBufferr…  r9  r�  r‘   r”   r³   r�   r  )r°  rÔ  r�   r}   )rq  rÔ  ry  r£  r�   z&tuple[LambdaFuture | None, ModuleType])rˆ   rf   r‰   rf   r�   rk   )r”   rf   r�   rf   )rˆ   rf   r‰   rf   r\  úOrderedSet[BaseSchedulerNode]r�   rf   )rˆ   rf   r‰   rf   r  r   r\  r;  )r  ú,dict[BaseSchedulerNode, list[PendingFusion]]r\  r;  r�   r  )
r.  ú1list[tuple[BaseSchedulerNode, BaseSchedulerNode]]r,  ú&dict[BaseSchedulerNode, PendingFusion]r/  r<  r\  r;  rj  r}   )r\  r;  r,  r>  )r8  r=  r9  r=  )rq  r¦  rj  r}   r�   r¦  )rq  r¦  rœ   r›   rE  r‘   r�   z!Iterator[list[BaseSchedulerNode]])rX  r£  r�   r  )r�   r˜   )r{  r¦  rd  r˜   r[  r}   r�   z-tuple[ForeachKernelSchedulerNode | None, int])rÒ  r¦  rP  r‘   rd  r˜   r[  r}   rS  zJCallable[[ForeachKernelSchedulerNode, list[BaseSchedulerNode], int], None]r�   r  r›  )rq  r¦  rj  r}   r�   r=  r+  )rˆ   rf   r‰   rf   rÍ  r‘   r�   r}   )rˆ   rf   r‰   rf   rá  z!tuple[str, ...] | OrderedSet[str]r�   r,  r/  r*  )rF	  rf   r•  rf   rS  rÔ  r�   r}   )rˆ   rf   r‰   rf   r�   z,tuple[int, SchedulerNode, sympy.Expr] | None)rE  rf   rJ  rf   r�   r™   )rˆ   rf   r‰   rf   r�   úOrderedSet[str] | None)
r7  rf   r  rf   ri  zCSequence[tuple[BaseSchedulerNode, NestedReduction.PointwiseDomain]]r%  r}   r�   r}   )FT)
rˆ   rf   r‰   rf   r%  r}   r  r}   r�   r}   )FTN)rˆ   rf   r‰   rf   r%  r}   r  r}   ro	  r?  r�   r}   )rˆ   rf   r‰   rf   ro	  r?  r�   r}   )r¯	  r;   rˆ   rf   r‰   rf   r�   r}   )r  r9   r  r9   r�   r}   )r  r8   r  r9   r¡	  r}   r�   r}   )r  r8   r  r:   rÕ	  r*  r�   r}   )rÙ	  r8   rÚ	  r8   r�   r}   r¡  )rà   r8   r  r}   r�   r‘   )TN)
rE  rf   rJ  rf   r  r}   ro	  r?  r�   r‘   )
rˆ   rf   r‰   rf   r  r}   ro	  r?  r�   r‘   )...)rˆ   rf   r‰   rf   r  r}   rã	  zLiteral[False]r  r}   r�   r‘   )rˆ   rf   r‰   rf   r  r}   rã	  zLiteral[True]r  r}   r�   ztuple[int, int, bool])TFT)rˆ   rf   r‰   rf   r  r}   rã	  r}   r  r}   r�   zint | tuple[int, int, bool])r8  r=  r�   r=  )rq  rŽ   r�   r   )r*
  rf   r�   r  )rÝ  rý  r�   ÚBaseScheduling)rÝ  r  r�   r@  r>  )r×   r,  rÎ  r™   r�   r}   )r”   rf   r�   r5  )r�   ro
  )r�   ú6dict[str, ir.IRNode | ir.TorchBindObject | sympy.Expr])r[
  úlist[GraphPartitionSignature]r�   r  )rq
  rg   rX
  rA  r�   ro
  )r|
  úlist[PartitionType]r}
  z
list[bool]r�   rB  )r_
  rA   r  r™   r�   rA   )r�   z9tuple[list[PartitionType], list[GraphPartitionSignature]])r|
  rC  r[
  rB  r�   r  )rq
  rg   r_
  rA   r�   r  )r|
  rC  r[
  rB  r�   z'contextlib.AbstractContextManager[None]©r°  rÔ  r�   z%tuple[float, float, list[str | None]])rq  r¦  r�   r}   )rÖ  r,  r�   z	ir.Layoutr¢  )r�   r5  )‚r€   r�   r‚   r•   r:  rN  rw  r‰  rÂ  rÅ  r  ÚpropertyrÉ  Úsetterr¦  r×  rr  r�  rd   r¤  r|  rC  r{  r“  rV  rt  r}  r~  r\  rŸ  rœ  rr  rw  r}  rŠ  r‹  r�  r±  r½  r  rù  r  r  r&  r2  r6  r>  rk  r0  rJ  r’  rY  r‰  r]  rº  rA  r  rÃ  rØ  rÜ  rê  r	  r	  r	  r	  rœ  rJ	  r^	  rf	  rh	  r&  r  rs	  rp	  r‹	  rô  r¶	  r£	  r¸	  r½	  r¤	  r2	  r	  rß	  rˆ	  r   r  rî	  rï	  rž  rŸ  r¡  r#
  r%
  r+
  r4
  r#  r9
  rÌ  rA
  rO   rM
  rC
  rT
  rb
  rt
  r‡
  rŠ
  rœ
  rŸ  r   r�  r¯
  rº
  r  rÝ
  rç
  rá
  rÇ
  rÈ
  r  rZ  r(  ru  r
  r-  r1  r  r  r  r  s   @rs   rÛ  rÛ  ¼  s  ø„ ñó
õh9óT	#ó6
óp(óSó
Qð ò&ó ð&ð ×Ñò(ó ð(ó7ó#ó,ó"óHMPó^KóZ+#óZ ðØ,ðà	 óó6	óSó*ó4#ó&/ó<$ó6!óF	ð8Ø0ð8à	ó8ð, %)ð	à*ðð ðð "ð	ð
 
óð$
>Ø ð
>Ø*6ð
>à	ó
>ð'Ø0ð'à	ó'óRIDðV'8à&ð'8ð +ð'8ð ð	'8ð
 ð'8ð 
ó'8óR
ð OSðØ0ðØAKðà	/óð ZØ&ðZØ/@ðZà	óZóx>ðà ðð !ðð 3ð	ð
 
óð0à ðð !ðð 'ð	ð
 3óð"D2à$PðD2ð 3ðD2ð 
ó	D2ðLO?àPðO?ð @ðO?ð  Lð	O?ð
 3ðO?ð óO?ðbSà2ðSð @óSð0$àKð$ð $Uó$ð(Cà&ðCð ðCð 
!ó	CðJ ðØ&ðà1ðð ðð 
+ò	ó ðô8e.óN(
ðTC&à,ðC&ð *ðC&ð ð	C&ð
 
7óC&ðJ'$à*ð'$ð ð'$ð *ð	'$ð ð'$ð
ð'$ð 
ó'$óR?ð6 à&ð6 ð ð6 ð 
;ó	6 ðp,Ø&ð,Ø/@ð,à	ó,ð\7Ø&ð7Ø/@ð7à	ó7ðr.2Ø&ð.2Ø/@ð.2ØMPð.2à	ó.2ð`$Ø&ð$Ø/@ð$à	ó$ð6<à ð<ð !ð<ð <ð	<ð
 
ó<ð|MØ&ðMØ/@ðMà	óMð^76Ø&ð76Ø/@ð76à	ó76ðr]Kà ð]Kð !ð]Kð 
ó	]Kð~^à ð^ð !ð^ð 
ó	^ó@ð ;à(ð;ð )ð;ð ð	;ð
 
ó;ðz`Ø&ð`Ø/@ð`à	5ó`ðD
Ø)ð
Ø5Fð
à	ó
ðJà ðJð !ðJð 
 ó	Jð"!
à'ð!
ð !ð!
ð
ð	!
ð ð!
ð 
ó!
ðN "Ø*.ðà ðð !ðð ð	ð
 $(ðð 
óð4 "Ø*.ð
à ð
ð !ð
ð ð	
ð
 $(ð
ð 
ó
ð, "Ø*.Ø=AðuMà ðuMð !ðuMð ð	uMð
 $(ðuMð %;ðuMð 
óuMðx	 >BñGà ðGð !ðGð
 %;ðGð 
óGðR3)Øð3)Ø(9ð3)ØBSð3)à	ó3)ðj ò
ó ð
ð OTñ=Øð=Ø )ð=ØGKð=à	ó=ð~=Øð=Ø&/ð=à	ó=ð* òOIó ðOIðhØðØ 'ðØ7Jðà	óð ò4ó ð4ô";ð !Ø=Að(à#ð(ð $ð(ð ð	(ð
 %;ð(ð 
ó(ð\ +/Ø=Aðà ðð !ðð $(ð	ð
 %;ðð 
óð* ð
  Ø8;Ø*-ðà ðð !ðð ð	ð
 (6ðð $(ðð 
òó ðð ð
  Ø7:Ø*-ð$à ð$ð !ð$ð ð	$ð
 (5ð$ð $(ð$ð 
ò$ó ð$ð !Ø.3Ø*.ð^Kà ð^Kð !ð^Kð ð	^Kð
 (,ð^Kð $(ð^Kð 
%ó^Kð@dà ðdð !ðdð 
ó	dðLR
Ø&ðR
Ø/@ðR
à	óR
ðh6Ø Qð6à	:ó6ð@4Ø@ð4à	ó4ó	8ó*ó4ð
à)ðð 
óó&'ó*%ó5ð$
Øð
Ø+:ð
à	ó
ó=ð~ ò!ó ð!ðFØ%ðà	óð"à	?óð 'à1ð'ð 
ó'ðRBHà ðBHð LðBHð 
"ó	BHðHK Ø-ðK Ø@JðK à	&óK ðZ"
à*ð"
ð )ð"
ð 
!ó	"
ðH?à&ð?ð 
!ó?ðBà&ðð 
!óðB%Ø,ð%à	 ó%ð@5&à	Bó5&ðn";à'ð";ð 2ð";ð 
ó	";óH>ó0ð1
à ð1
ð +ð1
ð 
ó	1
ðfØ-ðØ;Xðà	0óð6-AØ-ð-AØ;Xð-Aà	ó-Aó^ó@rðhQØ4ðQà	.óQóN5ó`%ó
Hð òó ðð òó ðó
ó(÷1ru   c                  óD  ‡ — e Zd Zdˆ fd„Zdd„Zdd„Z	 	 	 	 	 	 dd„Z	 	 	 	 	 	 dd„Z	 	 	 	 	 	 dd„Z	 	 	 	 	 	 dd„Z		 	 	 	 dd„Z
	 	 	 	 	 	 	 	 dd	„Z	 d	 	 	 	 	 	 	 dd
„Zdd„Zd d„Zd!d„Zdd„Zd"d„Zdd„Z	 	 	 	 d#d„Zd$d„Z	 	 	 	 	 	 d%d„Z	 	 	 	 d&d„Z	 d	 	 	 	 	 d'd„Zˆ xZS )(r@  c                ó0   •— t         ‰| �  «        || _        y r~   )rý  r:  rÜ  )rr   rÜ  r  s     €rs   r:  zBaseScheduling.__init__û%  s   ø€ Ü‰ÑÔØ"ˆ�ru   c                óR   — | j                   r| j                   j                  «        y y r~   )rÜ  r#
  rq   s    rs   Úfree_buffers_in_schedulerz(BaseScheduling.free_buffers_in_schedulerÿ%  s   € Ø�>Š>Ø�N‰N×'Ñ'Õ)ð ru   c                ó   — t        «       S )z0Return a set of .codegen.common.BackendFeature()r   rÜ  s     rs   Úget_backend_featuresz#BaseScheduling.get_backend_features&  s
   € ä‹|Ðru   c                ó   — t         ‚)zO
        Check whether node1 and node2 can be vertically fused or not.
        rñ  rÚ  s      rs   r‹	  z BaseScheduling.can_fuse_vertical&  ó
   € ô "Ð!ru   c                ó   — t         ‚)zQ
        Check whether node1 and node2 can be horizontally fused or not.
        rñ  rÚ  s      rs   rŒ	  z"BaseScheduling.can_fuse_horizontal&  rN  ru   c                óâ  — |j                  «       }t        |t        j                  «      sy|j	                  «       syt        |j
                  t        j                  «      r�t        |j
                  j                  «      dk(  xrk t        |j
                  j                  d   t        j                  «      xr8 |j
                  j                  d   j                  «       |j                  «       k(  S y)av  
        A Multi-Output Template (referenced in #144012) is a template node
        with MultiOutputLayout, and its output buffers are instances of MultiOutput.
        In this context, we verify whether node1 represents the Multi-Output Template
        and node2 corresponds to one of its outputs. If so, we further check if
        backend supports this fusion.

        Fr   r   )r‡  r²   r0   r!  r\   r”   rB   rÎ   r³  rl  râ  )rr   rˆ   r‰   r  s       rs   r‚	  z.BaseScheduling.can_fuse_multi_outputs_template&  s¹   € ð ×.Ñ.Ó0ˆÜ˜,¬×(9Ñ(9Ô:ØØ×5Ñ5Ô7Øä�e—j‘j¤"§.¡.Ô1ä�E—J‘J×%Ñ%Ó&¨!Ñ+ò OÜ˜uŸz™z×0Ñ0°Ñ3´R·Y±YÓ?òOà—J‘J×%Ñ% aÑ(×1Ñ1Ó3°|×7LÑ7LÓ7NÑNðð ru   c                óŠ  — |j                  «       s|j                  «       rt        j                  ||«      S t        j	                  ||«      r"t        j                  ||«      rt        ||«      S t        j                  ||«      rt        ||«      S t        |t        «      r|j                  |«      S t        |t        «      r|j                  |«      S t        |t        «      rLt        |t        «      r<t        |j                  t        j                   «      sJ ‚t"        j%                  ||«      S t&        j                  ||«      S )z 
        Fuse two nodes
        )rë  rB  ry   r2  r8  r  r  r¯   r  rÿ  r²   r  rR  r³   r”   r0   rÿ  r*  r4  rÚ   rÚ  s      rs   ry   zBaseScheduling.fuse1&  s  € ð ×ÑÔ ×!1Ñ!1Ô!3Ü-×2Ñ2°5¸%Ó@Ð@Ü×9Ñ9Ø�5ô
ä×&Ñ& u¨eÔ4Ü(¨°Ó6Ð6Ü×7Ñ7¸¸uÔEÜ*¨5°%Ó8Ð8Ü˜Ô4Ô5Ø—?‘? 5Ó)Ð)Ü˜Ô6Ô7Ø—?‘? 5Ó)Ð)Ü˜Ô8Ô9¼jØ”=ô?
ô ˜eŸj™j¬"×*DÑ*DÔEÐEÐEÜ7×EÑEÀeÈUÓSÐSä%×*Ñ*¨5°%Ó8Ð8ru   c                ó   — t         ‚)z[
        Process the iteration sizes in case a transformation needs to be applied.
        rñ  )rr   rC  s     rs   r$  zBaseScheduling.group_fnK&  rN  ru   c                ó   — t         ‚)zã
        Given a template node, generate a kernel.

        This function is only available for triton now. If the third-party backend behaves as a sub-class
        of TritonScheduling, it can override it or reuse it.
        rñ  )rr   r•  Úepilogue_nodesr€	  s       rs   r  zBaseScheduling.codegen_templateS&  s
   € ô "Ð!ru   c                ó   — t         ‚©rv  rñ  )rr   rq  rz  ry  s       rs   rw  z.BaseScheduling.generate_kernel_code_from_nodesa&  s
   € ô "Ð!ru   c                ó   — t         ‚rV  rñ  rì  s     rs   r  zBaseScheduling.codegen_nodel&  ó
   € ô "Ð!ru   c                ó   — t         ‚r~   rñ  rì  s     rs   r  z*BaseScheduling.codegen_mix_order_reductionr&  ró  ru   c                ó   — t         ‚r~   rñ  rì  s     rs   r  z'BaseScheduling.codegen_nested_reductionu&  ró  ru   c                ó   — t         ‚)zt
        Generate synchronization code for the kernel. This method depends on the hardware characteristics.
        rñ  rq   s    rs   r  zBaseScheduling.codegen_syncx&  rX  ru   c                 ó   — y)z•
        Check whether the backend is requesting the scheduler to flush the generated kernel.
        If not supported, please return False.
        Fr…   rq   s    rs   r  zBaseScheduling.ready_to_flush~&  s   € ð
 ru   c                ó   — t         ‚)z]
        Flush the generated kernel and python wrapper code to the source code file.
        rñ  rq   s    rs   r%
  zBaseScheduling.flush…&  rX  ru   c                ó   — t         ‚)rq  rñ  rO  s     rs   rr  z$BaseScheduling.benchmark_fused_nodes‹&  ó
   € ô "Ð!ru   c                ó   — t         ‚)r|  rñ  )rr   r~  s     rs   r}  z)BaseScheduling.benchmark_codegened_module”&  s
   € ô
 "Ð!ru   c                 ó   — y)zŒ
        Return an unsigned integer which represents the priority of this fusion pair.
        The smaller is with higher priority.
        r   r…   rÚ  s      rs   r
  z'BaseScheduling.get_fusion_pair_priority›&  s   € ð ru   c                ó   — t         ‚)z¡
        Benchmark the list of nodes to combine and return the execution time
        and memory copy time in milliseconds on randomly generated inputs.
        rñ  )rr   r°  r  s      rs   r  z%BaseScheduling.benchmark_combo_kernel¤&  r_  ru   c                ó|   — |r:ddl m}  |||«      }t        j                  j                  j                  ||«       y y )Nr   )Ú'set_kernel_post_grad_provenance_tracing)r€  rd  ra   rÁ   rÿ  Úwrite_provenance_debug_handle)rr   r’  r´  rd  Údebug_handles        rs   Úcodegen_commentzBaseScheduling.codegen_comment­&  s>   € ñ
 ÝUáBØØóˆLô �G‰G× Ñ ×>Ñ>Ø˜\õð ru   )rÜ  zScheduler | Noner  )rÝ  rý  r�   zOrderedSet[BackendFeature]r+  rû  )rC  r  r�   z"tuple[tuple[sympy.Expr, ...], ...])r•  rf   rT  rÔ  r€	  rÔ  r�   r5  r~   r8  )r”   z"FusedSchedulerNode | SchedulerNoder�   r  )r”   rÿ  r�   r  )r”   r  r�   r  r  r6  )r~  r   r�   r7  r/  rD  )r’  rÔ  r´  r5  r�   r  )r€   r�   r‚   r:  rJ  rL  r‹	  rŒ	  r‚	  ry   r$  r  rw  r  r  r  r  r  r%
  rr  r}  r
  r  rg  r  r  s   @rs   r@  r@  ú%  s†  ø„ õ#ó*óð"Ø&ð"Ø/@ð"à	ó"ð"Ø&ð"Ø/@ð"à	ó"ðØ&ðØ/@ðà	óð49Ø&ð9Ø/@ð9à	ó9ð4"Ø3ð"à	+ó"ð"à(ð"ð 4ð"ð 4ð	"ð
 
ó"ð$ %)ð		"à*ð	"ð ð	"ð "ð		"ð
 
ó	"ó"ó"ó"ó"óó"ð"Ø0ð"à	ó"ó"ðØ&ðØ/@ðà	óð"Ø4ð"à	.ó"ð #'ðà2ðð  ðð 
÷	ru   r@  r+  )r�   z$torch._inductor.codecache.LocalCache)r¸  rf   r�   r,  )r¸  rf   r�   zCallable[[Any], Any] | None)r¸  rf   r�   r/  )rë  r   r�   r,  )r”   rf   r¹  rž  r  r-  r�   r  )r¥  ú)FusedSchedulerNode | GroupedSchedulerNoder�   r  )r¥  rh  rÜ  rÛ  rÛ   r¦  r�   r  )r…   )r½  zlist[list[int]]rC  r   rÃ  rŸ  r�   r¡   )rÌ  r9  r]  r:  r�   r  r¤  )rß  r‘   rà  r‘   rá  r‘   râ  r‘   rã  rH   r�   ztuple[int, int])rì  rq  rí  rq  rß  r‘   rà  r‘   rá  r‘   râ  r‘   rã  rH   r�   r}   )r”   z	ir.IRNoder�   ro
  )r”   rf   r�   ro
  )r•  rf   r�   r}   )r”   rf   r  r}   r�   r}   )r•  rf   r  rf   r�   r}   )rˆ   rf   r‰   rf   )×Ú
__future__r   rW  rå
  r£   rC  r¿  r1
  rš  rÔ  r  r  rÐ  ré  ry  rê  r[  rþ
  r»  r   r   Úconcurrent.futuresr   r   r   r	   r
   r   r   r   r   r   Útyping_extensionsr   Útorch.utils._ordered_setr   r0   r   r   Úcollections.abcr   r   r   Útypesr   Útorch._inductor.codegen.wrapperr   rþ  r   rŒ  r   r  r`  Útorch._inductor.async_compileÚtorch.utils._pytreerÍ  Ú_pytreer¶  Útorch._dynamo.utilsr   r   Ú torch._inductor.autotune_processr   Útorch._inductor.codecacher    r!   Útorch._inductor.irr"   Útorch._inductor.metricsr#   r$   Útorch._inductor.stream_utilsr%   Ú%torch.fx.experimental.symbolic_shapesr&   Útorch.utils._sympy.functionsr'   Útorch.utils._sympy.symbolr(   r)   r*   Útorch.utils._tritonr+   rX  r,   r-   r.   r/   r1   Úanalyze_preserves_zero_maskr2   Úcodegen.commonr3   r4   r5   Úcomm_analysisr6   r7   r8   r9   r:   r;   Úexcr<   r=   Úfx_utilsr>   r?   r@   rA   rB   rC   rD   r$  rE   r”  rF   rG   Úruntime.hintsrH   rI   Úruntime.runtime_utilsrJ   rK   rL   rÂ   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   Úvirtualizedra   Ú	getLoggerr€   rT  Ú_loggingÚgetArtifactLoggerrÜ  ra  r  r®
  r¥   rg   rƒ   rh   ri   rØ  rk   r‡   r�   r˜   r­   r¯   r2  rÚ  r   rf   ry  ro  rn  rÂ  ru  rÔ  rï  r  r¸  rR  r  r³   rª  rµ  rÚ   rÿ  r  r*  rB  r´  rÆ  rÒ  rÚ  rê  rñ  r1  rn  rm  r  r  r  r  r   r$  r&  r)  r+  r-  r/  r@  rÛ  r@  r…   ru   rs   ú<module>rˆ     så  ðÞ "ã Û Û Û Û Û Û Û Û Û Û 	Û Û 
Û Û Û Û ß ,ß 3÷	÷ 	ó 	õ (å /ç )ñ ß<Ñ<Ý åJå5Ý1ã ã Û $ß $Ð $ß 6Ý Eß ?Ý 7ß MÝ 8Ý >Ý 1ß OÑ OÝ *ç D× DÝ Dß MÑ M÷÷ ;Ó :ß 2Ý $÷÷ õ  ß Jß :ß FÑ FÝ &÷÷ ÷ ÷ ÷ ñ õ* ð €g×Ò˜Ó!€Ø�^Š^×-Ò-¨h¸ÓA€
Ø—N’N×4Ò4°X¸ÓOÐ Ø Ÿ>š>×;Ò;ØÐ$óÐ ð —’×1Ò1°(¸LÓI€àÐ 3Ñ4€ˆyÓ 4ÙˆTƒ]€Ùˆtƒ_€ð ×Ò÷Dð Dó ðDð* ×Ò÷(ð (ó ð(ô
�*ô 
ð €×Ò˜TÔ"÷Nð Nó #ðNð*	Øð	àð	ð 
ó	÷_ñ _÷D	mñ mð` ×Ò÷h8ð h8ó ðh8ðV ×Òô1˜_ó 1ó ð1÷T1ñ T1ðn ‡‚ò2ó ð2óð,Øðà óó,#ðL €×Ò˜TÔ"÷
ð 
ó #ð
ó*÷ñ ð *KØ
ð*Kà4ð*Kð ,ð*Kð 
ó	*KôZ"*Ð 1ô "*ôJ5Ð.ô 5ôA*Ð%ô A*ðHØ:ðà	óð$Ø:ðàðð $ðð 
ó	ô8k*Ð*ô k*ô\hGÐ0ô hGôV\<Ð.ô \<ô~<-Ð+=ô <-ô~L:Ð!3ô L:ô^bÐ,ô bðP #%ð+Ø#ð+àð+ð  ð+ð ó	+ð\0Ø%ð0Ø1Cð0à	ó0ó8
1ð(Øð(àð(ð ð(ð ð	(ð
 #ð(ð ó(ð6Ø	ðà	ðð ðð ð	ð
 ðð ðð #ðð 
óð@ ×Ò÷
ð 
ó ð
ð> +˜9Ÿ?š?Ó,Ð óð$Ø
ðàóó&"ð 6:ñØ
ðØ.2ðà	óð4:Ø$ð:Ø5Fð:à	ó:ó"óóóPó@ð ×Ò÷/2ð /2ó ð/2ðd ×Ò÷=ð =ó ð=÷@{X1ñ {X1÷|qAò Aru   