
    ɯwg/                       U d Z ddlmZ ddlmZmZ ddl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mZmZmZmZmZ er"ddlZdd	lmZ dd
lmZ ddlmZ ddlm Z  ddl!m"Z"  e       Z# ed      Z$ G d d      Z% G d dee$         Z& G d de%      Z' e&de      Z(de)d<    e&de%      Z*de)d<    e&de%      Z+de)d<    e&de%      Z,de)d <    e&d!e'      Z-d"e)d#<    e&d$e%      Z.d%e)d&<    e&d'e%      Z/d(e)d)<    e&d*e%      Z0d+e)d,<    e&d-e%      Z1d.e)d/<    e&d0e%      Z2d1e)d2<    G d3 d4      Z3 G d5 d6      Z4 e4       Z5 G d7 d8      Z6 e6       Z7y)9ak  
This file provides a number of "global" variables/handlers that are actually
thread local and dynamically scoped, with Inductor patching them to various
implementations depending on the situation.

These handlers are interacted with in a fairly stylized way.  Typically,
we will import V from this module::

    from .virtualized import V

Various handlers are accessible as attributes on this module; for example,
you might access ``V.graph.sizevars.size_hint`` to resolve a size hint associated with
a number.

There are a few distinct usage patterns for virtualized global variables:

1. Implicit argument passing.  Examples: ``V.current_node``, ``V.aot_compilation``.
   Use ``V.set_current_node`` to change what the current node is while we're
   executing some region of code, so code inside that region can query ``V.current_node``
   to find out what it is.  This is often more convenient than manually threading
   the current node as an argument through all call stacks.

2. Per-compilation global state.  Examples: ``V.fake_mode``, ``V.graph``.  For a
   given ``compile_fx`` invocation, these typically don't change, but they are
   associated with some internal state so they cannot just be global functions.
   We install these objects at the beginning of compilation and then you can
   conveniently access them without having to pass them around.

3. Alternate define-by-run interpretations.  Examples: ``V.ops``, ``V.kernel``.
   A commonly used IR in Inductor is define-by-run: instead of maintaining
   explicit syntax data structures, we instead represent loop bodies as
   callable functions, which internally invoke operations defined on
   ``V.ops``.  To perform semantic analysis, print or code generate these
   operations, we dynamically patch ``V.ops`` with an alternate handler with
   the intended semantics and then run the callable function.  For example, to
   extract out a traditional (FX) graph representation of the define-by-run
   IR, simply install a handler that records each ``ops`` call to a graph.

   TODO: Define a parent class / protocol that defines all of the operations
   V.ops is expected to support.

It is typically an error to access a virtualized global without having installed
an appropriate handler (you will get a NullHandler), although in some cases we
provide a default implementation.

One last thing: although most virtualized globals are accessed via ``V``, ``ops`` is
ubiquitous enough to have its own top level variable, so you will typically see
``ops.constant(...)`` rather than ``V.ops.constant(...)``.  In fact, these are not
equivalent; the former interface supports arithmetic overloads like ``x + y``
instead of forcing ``ops.add(x, y)``, so it should be preferred.

Some operators are seemingly unused, but they are implicitly used by ops_wrapper.
In particular, we typically have an operator for every basic pointwise PyTorch operation
supported.
    )annotations)AbstractContextManagercontextmanager)local)AnyCallableGenericListTypeTYPE_CHECKINGTypeVarUnion   )KernelFormatterHandlerMockHandler
OpsHandlerReductionType	StoreModeWrapperHandlerN)LocalBufferContext)DebugContext)GraphLowering)InterpreterShim)FakeTensorModeTc                      e Zd ZdZy)NullHandlerz
    Sentinel indicating that a global variable is unset ala None.  Typically,
    attempting to access the global variable before it's set is an error, but with
    NullHandler it won't fail until you try to access an attribute on it.
    N)__name__
__module____qualname____doc__     `/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/torch/_inductor/virtualized.pyr   r   W   s    r#   r   c                  0    e Zd ZdZddZddZd	dZd
dZy)Virtualizeda  
    Implements a global variable that redirects via thread local variable
    (NB: construct this class to create the global variable; this is not
    a singleton class!)

    This allows us to swap in different op implementations in codegen.

    NB: Despite the fact that we typically call these "handlers" (e.g., NullHandler is
    the default value of the variable), we sometimes use these variables to
    store other things, like booleans.
    c                &    d| | _         || _        y )N__torchinductor_)_key_default)selfvnamedefaults      r$   __init__zVirtualized.__init__l   s    +E73	r#   c                      j                         t        t         j                  |       t         fd       } |       S )Nc               3  f   K   	 d  j                          y # j                          w xY wwN)_set_handler)priorr+   s   r$   ctxz%Virtualized._set_handler.<locals>.ctxt   s+     )!!%(!!%(s   1 1.1)_get_handlersetattrthreadlocalr)   r   )r+   valuer4   r3   s   `  @r$   r2   zVirtualized._set_handlerp   s<    !!#TYY.		) 
	) ur#   c                v    	 t        t        | j                        S # t        $ r | j	                         cY S w xY wr1   )getattrr7   r)   AttributeErrorr*   r+   s    r$   r5   zVirtualized._get_handler}   s5    	#;		22 	# ==?"		#s    88c                6    t        | j                         |      S r1   )r:   r5   )r+   names     r$   __getattr__zVirtualized.__getattr__   s    t((*D11r#   N)r,   strr-   z)Union[Callable[[], T], Type[NullHandler]])r8   r   returnzAbstractContextManager[None])rA   r   )r>   r@   rA   r   )r   r   r    r!   r.   r2   r5   r?   r"   r#   r$   r&   r&   _   s    
 #2r#   r&   c                  "     e Zd ZdZ fdZ xZS )NullKernelHandleraO  
    We need access `V.kernel.removed_buffers` in DeferredLine class when there
    is no kernel in the context. This happens when codegening the wrapper.
    Initialize `removed_buffers` and `inplaced_to_remove` explicitly so we don't
    need call 'getattr' with default value which is error prone to typo in
    attribute name.
    c                l    t         |           t               | _        t               | _        d| _        y )Nztl.int64)superr.   setremoved_buffersinplaced_to_removeindex_dtype)r+   	__class__s    r$   r.   zNullKernelHandler.__init__   s*    "u"%%%r#   )r   r   r    r!   r.   __classcell__)rJ   s   @r$   rC   rC      s    & &r#   rC   opszVirtualized[OpsHandler[Any]]_opsgraphzVirtualized[GraphLowering]_graphreal_inputszVirtualized[List[torch.Tensor]]_real_inputs	fake_modezVirtualized[FakeTensorMode]
_fake_modekernelzVirtualized[NullKernelHandler]_kerneldebugzVirtualized[DebugContext]_debuginterpreterzVirtualized[InterpreterShim]_interpreteraot_compilationzVirtualized[bool]_aot_compilationcurrent_nodezVirtualized[torch.fx.Node]_current_nodelocal_buffer_contextzVirtualized[LocalBufferContext]_local_buffer_contextc                      e Zd ZU dZded<   d Zd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)OpsValuea,  The return type of most ops calls.

    This exists so we can overload magic methods, and write mathematical
    expressions much more fluently. So instead of

        ops.add(ops.mul(ops.mul(ops.sub(ops.mul(_Ap2, x), _Ap3), x), x), _1)

    we can write

        (_Ap2 * x - _Ap3) * x * x + _1

    r   r8   c                    || _         y r1   r8   )r+   r8   s     r$   r.   zOpsValue.__init__   s	    
r#   c                ,    t        | j                        S r1   )r@   r8   r<   s    r$   __str__zOpsValue.__str__   s    4::r#   c                "    d| j                   dS )Nz	OpsValue()rc   r<   s    r$   __repr__zOpsValue.__repr__   s    4::.**r#   c                .    t         j                  | |      S r1   )rL   addr+   others     r$   __add__zOpsValue.__add__       wwtU##r#   c                .    t         j                  | |      S r1   )rL   mulrk   s     r$   __mul__zOpsValue.__mul__   rn   r#   c                .    t         j                  | |      S r1   )rL   subrk   s     r$   __sub__zOpsValue.__sub__   rn   r#   c                ,    t         j                  |       S r1   )rL   negr<   s    r$   __neg__zOpsValue.__neg__   s    wwt}r#   c                .    t         j                  | |      S r1   )rL   truedivrk   s     r$   __truediv__zOpsValue.__truediv__   s    {{4''r#   c                .    t         j                  | |      S r1   )rL   floordivrk   s     r$   __floordiv__zOpsValue.__floordiv__   s    ||D%((r#   c                .    t         j                  | |      S r1   )rL   modrk   s     r$   __mod__zOpsValue.__mod__   rn   r#   c                .    t         j                  | |      S r1   )rL   powrk   s     r$   __pow__zOpsValue.__pow__   rn   r#   c                .    t         j                  | |      S r1   )rL   ltrk   s     r$   __lt__zOpsValue.__lt__       vvdE""r#   c                .    t         j                  | |      S r1   )rL   lerk   s     r$   __le__zOpsValue.__le__   r   r#   c                .    t         j                  | |      S r1   )rL   eqrk   s     r$   __eq__zOpsValue.__eq__   r   r#   c                .    t         j                  | |      S r1   )rL   nerk   s     r$   __ne__zOpsValue.__ne__   r   r#   c                .    t         j                  | |      S r1   )rL   gtrk   s     r$   __gt__zOpsValue.__gt__   r   r#   c                .    t         j                  | |      S r1   )rL   gerk   s     r$   __ge__zOpsValue.__ge__   r   r#   c                .    t         j                  | |      S r1   )rL   bitwise_andrk   s     r$   __and__zOpsValue.__and__       tU++r#   c                .    t         j                  | |      S r1   )rL   
bitwise_orrk   s     r$   __or__zOpsValue.__or__   s    ~~dE**r#   c                .    t         j                  | |      S r1   )rL   bitwise_xorrk   s     r$   __xor__zOpsValue.__xor__   r   r#   c                ,    t         j                  |       S r1   )rL   bitwise_notr<   s    r$   
__invert__zOpsValue.__invert__   s    t$$r#   c                .    t         j                  | |      S r1   )rL   bitwise_right_shiftr+   ns     r$   
__rshfit__zOpsValue.__rshfit__   s    &&tQ//r#   c                .    t         j                  | |      S r1   )rL   bitwise_left_shiftr   s     r$   
__lshift__zOpsValue.__lshift__   s    %%dA..r#   N)r   r   r    r!   __annotations__r.   re   rh   rm   rq   rt   rw   rz   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r"   r#   r$   ra   ra      s     J+$$$()$$######,+,%0/r#   ra   c                  H    e Zd ZdZd Zed        Zed        Zedd       Zy)
OpsWrapperzThis wraps any returned IR values into an `OpsValue` instance, so that we
    can overload the magic methods for writing mathematical expressions fluently.
    c                    fd}|S )Nc                    | D cg c]  }t         j                  |       }}|j                         D ci c]  \  }}|t         j                  |       }}}t         j                   t	        t
              |i |      S c c}w c c}}w r1   )r   _unwrapitems_wrapr:   rM   )argskwargsanew_argskv
new_kwargsr>   s          r$   innerz%OpsWrapper.__getattr__.<locals>.inner  s{    7;<!
**1-<H<?E||~Ntq!!Z//22NJN##$7GD$$7$PZ$PQQ =Ns
   B Br"   )r+   r>   r   s    ` r$   r?   zOpsWrapper.__getattr__  s    	R
 r#   c                    t        | t        t        f      rt        d | D              S t        | t              r| j                  S | S )Nc              3  F   K   | ]  }t         j                  |        y wr1   )r   r   .0r   s     r$   	<genexpr>z%OpsWrapper._unwrap.<locals>.<genexpr>  s     :1++A.:s   !)
isinstancelisttuplera   r8   xs    r$   r   zOpsWrapper._unwrap  s9    a$'::::a"77Nr#   c                h    t        | t        t        f      rt        d | D              S t        |       S )Nc              3  2   K   | ]  }t        |        y wr1   )ra   r   s     r$   r   z#OpsWrapper._wrap.<locals>.<genexpr>  s     0!0s   )r   r   r   ra   r   s    r$   r   zOpsWrapper._wrap  s+    a$'0a000{r#   c                \    t         j                  |       } t        j                  | |||      S r1   )r   r   rM   indirect_indexing)indexsizecheckwrap_negs       r$   r   zOpsWrapper.indirect_indexing  s+     ""5)%%eT5(CCr#   N)TT)	r   r   r    r!   r?   staticmethodr   r   r   r"   r#   r$   r   r      sJ        
 D Dr#   r   c                     e Zd ZU eZeZeZej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d	<   ej                  Zde	d
<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   ej                  Zde	d<   e j                  Z!de	d<   e j                  Z"de	d<   e#d d       Z$e#d!d       Z%e#d        Z&e#d        Z'e#d        Z(e#d        Z)e#d        Z*e#d        Z+e#d        Z,e#d        Z-y)"_VzCallable[[Any], Any]set_ops_handlerzCallable[[], Any]get_ops_handlerzCallable[[GraphLowering], Any]set_graph_handlerset_real_inputsget_real_inputsset_fake_modeget_fake_modeset_kernel_handlerset_debug_handlerset_interpreter_handlerzCallable[[bool], Any]set_aot_compilationget_aot_compilationset_current_nodeget_current_nodeset_local_buffer_contextget_local_buffer_contextc                *    t         j                         S )z9The operator handler specific to the current codegen task)rM   r5   r<   s    r$   rL   z_V.ops;  s       ""r#   c                *    t         j                         S z#The graph currently being generated)rO   r5   r<   s    r$   rN   z_V.graph@  s     ""$$r#   c                *    t         j                         S )znon-fake example inputs)rQ   r5   r<   s    r$   rP   z_V.real_inputsE  s     ((**r#   c                *    t         j                         S r   )rS   r5   r<   s    r$   rR   z_V.fake_modeJ  s     &&((r#   c                *    t         j                         S )z$The kernel currently being generated)rU   r5   r<   s    r$   rT   z	_V.kernelO  s     ##%%r#   c                *    t         j                         S r1   )rW   r5   r<   s    r$   rV   z_V.debugT  s    ""$$r#   c                *    t         j                         S r1   )rY   r5   r<   s    r$   rX   z_V.interpreterX  s    ((**r#   c                *    t         j                         S r1   )r[   r5   r<   s    r$   rZ   z_V.aot_compilation\  s    ,,..r#   c                *    t         j                         S r1   )r]   r5   r<   s    r$   r\   z_V.current_node`  s    ))++r#   c                *    t         j                         S r1   )r_   r5   r<   s    r$   r^   z_V.local_buffer_contextd  s    $1133r#   N)rA   zOpsHandler[Any])rA   r   ).r   r   r    r   r   r   rM   r2   r   r   r5   r   rO   r   rQ   r   r   rS   r   r   rU   r   rW   r   rY   r   r[   r   r   r]   r   r   r_   r   r   propertyrL   rN   rP   rR   rT   rV   rX   rZ   r\   r^   r"   r#   r$   r   r   %  s   K3#N,0,=,=O)=)-):):O&:8>8K8K5K,8,E,EO)E)5)B)BO&B*4*A*AM'A'1'>'>M$>/6/C/C,C.4.A.A+A4@4M4M1M1A1N1N.N-=-J-J*J-:-G-G*G*7*D*D'D5J5W5W2W2G2T2T/T# # % % + + ) ) & & % % + + / / , , 4 4r#   r   )8r!   
__future__r   
contextlibr   r   	threadingr   typingr   r   r	   r
   r   r   r   r   ops_handlerr   r   r   r   r   r   torch!torch._inductor.codegen.cpp_utilsr   torch._inductor.debugr   torch._inductor.graphr   torch._inductor.loop_bodyr   torch._subclassesr   r7   r   r   r&   rC   rM   r   rO   rQ   rS   rU   rW   rY   r[   r]   r_   ra   r   rL   r   Vr"   r#   r$   <module>r      sv  6p # =  T T T  D2390gCL (2'!* (2V& &  &1%D" D%0+%F" F0;M;0W- W*5k;*O
' O*5+	'  %0$E! E-8-T* T&12C[&Q # Q,7,T) T9DK: 6 
S/ S/lD DD lA4 A4H Dr#   