Parser utilities#
A few helpers act at parse time (when TVMScript is turned into TIRx), letting you inline Python-computed values, factor out reusable fragments, and bundle parser-side state.
T.meta_var — preserve Python metadata#
T.meta_var(x) returns x unchanged. It is useful for retaining a
parser-side handle or a tuple of Python metadata. It does not bypass the
ordinary assignment rules: scalar expressions assigned inside TVMScript create
native value bindings. Compute shape parameters, instruction widths, and TMA
box sizes in the Python factory before @T.function.
widths = T.meta_var((32, 64)) # the tuple remains Python metadata
for j in T.unroll(widths[0]):
acc[0] = acc[0] + A[tx, j]
A plain range(n) creates a serial TIRx loop; T.unroll(n) marks it for
unrolling during lowering. meta_var does not make a runtime value recompute
when its inputs change. For a persistent scheduler, compute tile coordinates
inside each task loop, after the current cursor is updated.
@T.inline — inline functions#
@T.inline defines a function whose body is inlined at each call site during
parsing — no call appears in the generated code. It follows Python’s lexical (LEGB)
scoping with late binding, so a parameter shadows an enclosing variable:
@T.inline
def add_into(acc, x):
acc[0] = acc[0] + x
add_into(acc, A[tx, j]) # inlined -> acc[0] = acc[0] + A[tx, j]
@T.meta_class — parser-side state objects#
@T.meta_class marks a plain Python class whose instances are parser meta
values: their fields can hold buffers and scalars, so you can bundle related
allocations and state into one object and use it in the kernel body.
Define State outside @T.function. Instantiate it and use its fields
inside the kernel, where smem has already been allocated.
@T.meta_class
class State:
def __init__(self, smem):
self.acc = T.bind_(T.alloc_local([1], "float32"))
self.buf = T.bind_(T.decl_tensor(smem, ty_args=[
T.Tensor((64,), "float16", scope="shared.dyn")]))
s = State(smem.ptr_to([0]))
s.acc[0] = T.float32(0.0) # use its fields like ordinary buffers
# ... s.buf[i] ...
This is handy for grouping a kernel’s pipeline state (barriers, accumulators, scratch views) instead of threading many separate locals through the body.
T.constexpr#
A parameter annotated with T.constexpr is fixed by @T.jit’s
.specialize(...). Inside a function body, if T.constexpr(condition)
selects a Python branch during parsing. Use it for known specialization flags,
such as is_causal in FA4. An ordinary if constructs IR control flow and
parses both branches.