Core TVMScript#
TIRx kernels use tvm.script.tirx for the parser and core IR builders:
from tvm.script import tirx as Tx
Tx.alloc_tensor(...)
Tile primitives and backend-specific namespaces are documented separately in Tensor Instruction Authoring API, CUDA Authoring and Support APIs, and Direct PTX Instructions. For the relationship between these authoring layers and TIRx IR, see The Programming Model.
Parser entry points#
Public canonical TVMScript dialect namespace.
- tvm.script.tirx.function(function: LambdaType | None = None, **options: Any) Any
Parse a Python function into a function of the selected IR language variant.
- Parameters:
function (Callable, optional) – The function to be parsed. May be omitted to use the decorator with keyword options, such as
@T.function(private=True).private (bool, optional) – Whether the function should be treated as private. A private function has no global symbol attribute; a public function has a global symbol matching its name. Defaults to False.
check_well_formed (bool, optional) – Whether to check that the constructed function is well formed. Defaults to True.
persistent (bool, optional) – For
T.function, mark the resulting function as a persistent kernel. Defaults to False. Seetvm.tirx.script.ir_builder.function().pure (bool, optional) – For
R.function, declare whether the function is pure, meaning that it has no observable side effects. Defaults to True. Seetvm.relax.script.ir_builder.function_().**options – Keyword options are forwarded to the selected language variant’s
function_()hook, exceptcheck_well_formed, which controls parser validation. Options supported by only one language variant are not shared betweenT.functionandR.function.
- Returns:
result – The parsed function, or a decorator when
functionis omitted. Class members retain their Python functions until the enclosing module is constructed.- Return type:
Function or relax.Function or Callable
- tvm.script.tirx.inline(function: LambdaType | None = None, **options: Any) Callable[[...], Any]
Decorate a helper that constructs IR in its caller’s active frames.
- Parameters:
function (Callable, optional) – The helper function. May be omitted to supply keyword options.
hygienic (bool, optional) – Whether the helper resolves symbols in its definition environment instead of its calling environment. Defaults to True.
T.macroandR.macrocapture values at definition time;T.inlinerefreshes captured closure cells when called.**options – Keyword configuration for this helper decorator.
hygieniccontrols name lookup as described above; other options are accepted but are not consumed or forwarded to builder hooks.
- Returns:
result – The construction helper, or a decorator when
functionis omitted.- Return type:
Callable
Notes
T.inlinefollows Python lexical scoping with late binding of captured closure cells. Its return statements produce Python values, as do those ofR.macro.T.macroemits returns in the active primitive function.Examples
An inline helper can read values from its enclosing scope:
import tvm from tvm.script import tirx as T x_value = 128 @T.inline def capture(A, B): B[()] = A[x_value] # x_value resolved from enclosing scope @T.function def use(A: T.Tensor((1024,), "int32"), B: T.Tensor((), "int32")) -> None: capture(A, B) # Produces B[()] = A[128]
- tvm.script.tirx.jit(func: LambdaType | None = None, *, private: bool = False, check_well_formed: bool = True, persistent: bool = False) TIRJit | Callable[[LambdaType], TIRJit]
Decorator: capture the kernel and defer parsing until
.specialize().Use
@T.jit(instead of@T.function) when the kernel takes compile-time parameters annotated withT.constexpror runtime parameters that may be removed withT.Optional. The resulting object exposes.specialize(**const_args), which returns atvm.tirx.Function.- Parameters:
func (types.FunctionType or None, optional) – Function supplied by a definition-site
@T.jitapplication. None, the default, returns a decorator for@T.jit(**options).private (bool, optional) – Omit the function’s public global symbol when True. Default is False.
check_well_formed (bool, optional) – Validate each constructed specialization. Default is True; this option controls the parser separately from the function builder kwargs.
persistent (bool, optional) – Mark constructed specializations as persistent kernels. Default is False.
- Returns:
Deferred kernel, or its definition-site decorator when func is None.
- Return type:
TIRJit or Callable[[types.FunctionType], TIRJit]
- Raises:
TypeError – If the decorated value is not a Python function.
SyntaxError – If application occurs after definition or uses an unsupported bare or preconfigured callable alias instead of a qualified namespace decorator.
OSError – If the function’s source cannot be recovered.
Examples
Specialize compile-time dimensions before compiling the kernel:
from __future__ import annotations from tvm.script import tirx as T @T.jit def add( A: T.Tensor((N,), "float32"), B: T.Tensor((N,), "float32"), *, N: T.constexpr, ): for i in T.serial(N): B[i] = A[i] + 1.0 kernel = add.specialize(N=1024) # returns a Function @T.jit def guarded( optional: T.Optional(T.Tensor((1,), "int32")), output: T.Tensor((1,), "int32"), ): if T.constexpr(optional is not None): output[0] = optional[0] else: output[0] = 0 present = guarded.specialize() absent = guarded.specialize(optional=None)
- tvm.script.tirx.macro(function: LambdaType | None = None, **options: Any) Callable[[...], Any]
Decorate a helper that constructs IR in its caller’s active frames.
- Parameters:
function (Callable, optional) – The helper function. May be omitted to supply keyword options.
hygienic (bool, optional) – Whether the helper resolves symbols in its definition environment instead of its calling environment. Defaults to True.
T.macroandR.macrocapture values at definition time;T.inlinerefreshes captured closure cells when called.**options – Keyword configuration for this helper decorator.
hygieniccontrols name lookup as described above; other options are accepted but are not consumed or forwarded to builder hooks.
- Returns:
result – The construction helper, or a decorator when
functionis omitted.- Return type:
Callable
Notes
T.inlinefollows Python lexical scoping with late binding of captured closure cells. Its return statements produce Python values, as do those ofR.macro.T.macroemits returns in the active primitive function.Examples
An inline helper can read values from its enclosing scope:
import tvm from tvm.script import tirx as T x_value = 128 @T.inline def capture(A, B): B[()] = A[x_value] # x_value resolved from enclosing scope @T.function def use(A: T.Tensor((1024,), "int32"), B: T.Tensor((), "int32")) -> None: capture(A, B) # Produces B[()] = A[128]
Core IR builder#
Common statement frames and construction helpers live in
tvm.script.ir_builder.frame and tvm.script.ir_builder.stmt. The TIRx
namespace re-exports them alongside its function, tensor/layout, and execution
scope builders. Native shared statement builders live under
include/tvm/script/ir_builder and src/script/ir_builder; dialect-specific
thread-placement and tensor alias policies remain in the TIRx/S-TIR builders.
Concrete TIRx types, tensors, allocations and construction metadata.
- class tvm.tirx.script.ir_builder.ir.Axis(*args: Any, **kwargs: Any)
Layout axis wrapper.
- property name: str
Return the canonical axis name.
- classmethod get(name: str) Axis
Get or create the axis singleton named name.
Unknown names are registered without thread or memory attributes.
- is_thread() bool
Check if the axis is a thread axis.
- is_memory() bool
Check if the axis is a memory axis.
- get_scope() ExecScope | None
Get the scope of the axis.
- get_subscope() ExecScope | None
Get the subscope of the axis.
- class tvm.tirx.script.ir_builder.ir.ComposeLayout(per_element: int, swizzle_len: int, atom_len: int, tile_layout: TileLayout, swizzle_inner: bool = True)
A memory layout that swizzles a tile layout.
per_element/swizzle_len/atom_len/swizzle_innercarry the swizzle (formerly the standaloneSwizzleLayout);tile_layoutis the tiled memory map the swizzle is applied to. A bare swizzle is aComposeLayoutover a trivial identity tile.
- class tvm.tirx.script.ir_builder.ir.DtypeConstructor(ffi_name: str, dtype_str: str)
Callable + subscriptable dtype object.
Replaces the plain functions previously returned by
func_gen.T.float32()— same FFI call as before (returnstirx.Var).T.float32[N]— returnsLocalVectorAnnotation("float32", (N,)).T.float32[M, N]— returnsLocalVectorAnnotation("float32", (M, N)).x: T.float32— parser calls this object, gets atirx.Var.
- class tvm.tirx.script.ir_builder.ir.ExecScope(backend: str, name: str)
A node in one backend’s registered execution hierarchy.
- class tvm.tirx.script.ir_builder.ir.FloatImm(dtype: str | PrimType, value: float, loc: Location = UnknownLoc())
Float constant.
- class tvm.tirx.script.ir_builder.ir.IntImm(dtype: str | PrimType, value: int, loc: Location = UnknownLoc())
Int constant.
- class tvm.tirx.script.ir_builder.ir.Iter(extent: Expr, stride: Expr, axis: Axis | str)
A memory layout that tiles data across devices.
- tvm.tirx.script.ir_builder.ir.Lambda(parameter_types, function, *, ret_type=None)
Build a shared staging lambda from explicit types and a Python callable.
Scalar constructors such as
T.float32may be used as parameter types. An optional return annotation checks the body type without inserting casts.
- class tvm.tirx.script.ir_builder.ir.Layout
- verify_well_formed() bool
Verify if the layout is well-formed.
- Returns:
True if the layout is well-formed, False otherwise
- Return type:
- size(axis_name: str | None = None)
Get the size of the layout.
- Parameters:
axis_name (Optional[str]) – The name of the axis to get the size of. If not provided, the default input size will be returned.
- span(axis_name: str | None = None)
Get the span of the layout.
- Parameters:
axis_name (Optional[str]) – The name of the axis to get the span of. If not provided, the default span will be returned.
- apply(*coord: list[Expr], shape: list[Expr] | None = None) dict[str, Expr]
Apply the layout on the input coordinate and get the mapped output.
Input cases: - coord is a single element -> will be treated as a 1D coordinate - coord is a list of elements -> will be treated as a multi-dimensional coordinate - shape is provided -> turn the coord with shape into a 1D coordinate - shape is not provided -> use the default shape
- apply_to_shape(coord: list[Expr], input_shape: list[Expr]) list[Expr]
Compute the per-shard value that each shard would take if
coordwere interpreted againstinput_shape.Tries
self.group(input_shape)first. On success, each group owns exactly oneinput_shapeentry, socoord[d]can be split within that group’s shard extents (bounds stay local to one input dim — simpler analyzer simplification, no cross-dim complications).Falls back to
FlattenCoord(coord, input_shape)+SplitCoordonself’s raw shard shape when the group call fails (e.g. wheninput_shapedoes not align with the layout’s factor boundaries).Returns a list of length
len(self.shard); each entry is the value that shard would iterate.
- canonicalize() Layout
Canonicalize the layout by simplifying and fusing iterators where possible.
- Returns:
The canonicalized layout
- Return type:
Layout
- tile(outer: TileLayout, outer_shape: list[Expr], inner_shape: list[Expr]) TileLayout | ComposeLayout
Tile the current layout with an outer layout.
- direct_sum(left: TileLayout, left_shape: list[Expr], right_shape: list[Expr]) TileLayout | ComposeLayout
Direct-sum on the tiling domain (unscaled composition): A + B.
This layout is treated as the right addend B grouped by right_shape. The left layout is treated as A grouped by left_shape. The resulting layout is evaluated over the interleaved domain S_A ⊗ S_B, without span scaling (unlike tiling).
- is_tile_inner(tile_layout: TileLayout | ComposeLayout, tiled_shape: list[Expr], inner_shape: list[Expr]) TileLayout | None
Check if a layout is the inner layout of a tiled layout.
- Parameters:
- Returns:
The outer layout if it is the inner layout of the tiled layout, None otherwise
- Return type:
Optional[TileLayout]
- is_tile_outer(tile_layout: TileLayout | ComposeLayout, tiled_shape: list[Expr], outer_shape: list[Expr]) Layout | None
Check if a layout is the outer layout of a tiled layout.
- Parameters:
- Returns:
The inner layout if it is the outer layout of the tiled layout, None otherwise
- Return type:
Optional[Layout]
- is_direct_sum_right(sum_layout: TileLayout | ComposeLayout, interleaved_shape: list[Expr], right_shape: list[Expr]) TileLayout | None
Check if this layout is the right addend B in a direct-sum A + B.
Returns the left addend A if recognized, otherwise None.
- is_direct_sum_left(sum_layout: TileLayout | ComposeLayout, interleaved_shape: list[Expr], left_shape: list[Expr]) Layout | None
Check if this layout is the left addend A in a direct-sum A + B.
Returns the right addend B if recognized, otherwise None.
- slice(shape: list[Expr], region: list[tuple[Expr, Expr]]) Layout | None
Slice the layout with a given shape and region.
- Parameters:
shape (List[Expr]) – The shape of the layout
region (List[Tuple[Expr, Expr], tvm.ir.Range]) – The region to slice, each element is (begin, end)
- Returns:
The sliced layout, or None if slicing is not possible
- Return type:
Optional[Layout]
- tile_to(to_shape: list[Expr], current_shape: list[Expr]) Layout
Tile the current layout to the given shape.
- is_swizzle() bool
Check if the layout is a bare swizzle (ComposeLayout over a trivial tile).
- is_trivial() bool
Check if the layout is trivial.
- unpack(num: int) Layout
Unpack the layout, where a single element in the layout is unpacked into num contiguous elements.
- Parameters:
num (int) – The number of elements to unpack into
- Returns:
The unpacked layout
- Return type:
Layout
- broadcast(num: int, position: int = -1, axis: 'Axis' | str = 'm') Layout
Insert a stride-0 broadcast dim of extent
numatposition.positionfollows Python list-insert semantics (negative indices count from the end;-1appends after the last shard dim). The new dim has stride 0 — accessing along it doesn’t move the byte offset, so the same physical element is “seen”numtimes.Useful for layouts where a consumer reads the same SMEM datum multiple times (e.g.
sf_reuseover MMA-K steps).
- class tvm.tirx.script.ir_builder.ir.LocalVectorAnnotation(dtype: str, shape: tuple)
Marker for local vector/tensor allocation via type annotation subscript.
Created when a DtypeConstructor is subscripted, e.g.
T.float32[N]orT.float32[M, N]. The declaration protocol recognizes this annotation and allocates local storage withT.alloc_local(shape=..., dtype=...).
- tvm.tirx.script.ir_builder.ir.Ptr(element_type, storage_scope='global', *, loc: LocationEntry | Location = UnknownLoc())
Construct a pointer type from an element type or its annotation constructor.
For example,
Ptr(int32)andPtr(TensorMap)construct pointers in global scope;Ptr(int32, "shared")selects shared scope. UseI.Var(name, ty)to construct a variable of this type. String element dtypes remain accepted, as inPtr("float32", "shared").
- class tvm.tirx.script.ir_builder.ir.Range(begin: Expr, end: Expr | None = None, loc: Location = UnknownLoc())
Represent a range in TVM.
You do not need to create a Range explicitly. Python lists and tuples will be converted automatically to a Range in API functions.
- Parameters:
Note
The constructor creates the range [begin, end) if the end argument is not None. Otherwise, it creates [0, begin).
- tvm.tirx.script.ir_builder.ir.Tensor
alias of
_tensor_type
- tvm.tirx.script.ir_builder.ir.TensorLoad(tensor: Var, indices: list[Expr], loc: Location = UnknownLoc()) TensorLoad
Construct a validated tensor load.
- tvm.tirx.script.ir_builder.ir.TensorMap
alias of
TensorMapType
- class tvm.tirx.script.ir_builder.ir.TileLayout(spec: _LayoutSpec)
A memory layout that tiles data across devices.
- static from_iters(shard: Sequence[Iter] = (), replica: Sequence[Iter] = (), offset: dict[Axis | str, Expr] | None = None) TileLayout
Construct a TileLayout from pre-built Iter objects.
- is_trivial() bool
Check if the layout is trivial.
- group_many(shapes: Sequence[Sequence[Expr]]) tuple[TileLayout, list[list[int]]]
Group the layout by the minimal common refinement of several shapes.
Repeated cumulative product boundaries are retained, so an extent-one dimension in any input shape becomes a real unit iterator in the refined layout. This operation only splits existing shard iterators; it does not canonicalize or reorder the layout.
- tvm.tirx.script.ir_builder.ir.Tuple(*fields: Type) Type
Construct a tuple type for a TIRx function or binding annotation.
- class tvm.tirx.script.ir_builder.ir.Var(name: str | None = None, ty: Type | str | None = None, loc: Location = UnknownLoc(), *, name_hint: str | None = None)
A canonical local variable in the IR.
- tvm.tirx.script.ir_builder.ir.alloc_cast_frag(src, dtype)
Allocate a register frag holding
srcvalue-cast todtype.Inherits
src’s logical shape and its(lane, register)layout — only the element dtype changes — soTx.cast(dst, src)is a per-thread element-wise cast with no cross-lane movement..permute(...)the result to the axis order a downstream consumer (e.g.stmatrixviaTx.copy(dispatch="ldstmatrix")) expects.- Parameters:
src (tirx.Var) – Source register frag (e.g. from
alloc_tcgen05_ldst_frag).dtype (str) – Destination element dtype.
- Returns:
Fresh
localfrag,src.shapeshaped,src.layout, dtype-cast.- Return type:
tirx.Var
- tvm.tirx.script.ir_builder.ir.alloc_local(shape, dtype='float32', data=None, strides=None, elem_offset=None, byte_offset=None, *, scope='local', align=-1, offset_factor=0, layout=<MISSING>, allocated_addr=None, annotations=None)
Implement separately named allocation conveniences using the canonical Op.
- tvm.tirx.script.ir_builder.ir.alloc_scalar(dtype: str = 'float32', scope: str = 'global', *, annotations: dict[str, Any] | None = None) TensorLoad
Allocate a zero-dimensional tensor (scalar), with optional allocation annotations.
- tvm.tirx.script.ir_builder.ir.alloc_shared(shape, dtype='float32', data=None, strides=None, elem_offset=None, byte_offset=None, *, scope='shared', align=-1, offset_factor=0, layout=<MISSING>, allocated_addr=None, annotations=None)
Implement separately named allocation conveniences using the canonical Op.
- tvm.tirx.script.ir_builder.ir.alloc_tensor(placement=None, *, ty_args, attrs=None, annotations: dict[str, Any] | None = None, loc: Location = UnknownLoc(), ty=None) Call
Allocate the tensor described by one explicit
Tensortype argument.Optional placement is an ordinary tuple operand. Allocation annotations belong to
attrs;annotationsaccepts a Python dictionary whose scalar values are normalized to typed IR constants.
- tvm.tirx.script.ir_builder.ir.boolean(expr: Expr | None = None) Expr
Construct a new tirx.Var with type boolean or cast expression to type boolean.
- tvm.tirx.script.ir_builder.ir.decl_scalar(dtype, data, scope, elem_offset=None, byte_offset=None) TensorLoad
Declare a zero-dimensional tensor (scalar) from a pointer.
- tvm.tirx.script.ir_builder.ir.decl_tensor(data, *, ty_args, attrs=None, loc: Location = UnknownLoc(), ty=None) Call
Declare a pointer-backed tensor with one explicit
Tensortype argument.
- tvm.tirx.script.ir_builder.ir.handle(dtype: str | None = None, storage_scope: str = 'global') Var
Create a TIR var that represents a pointer.
- tvm.tirx.script.ir_builder.ir.index_map(mapping: Callable, *, inverse_index_map: Callable | None = None, index_dtype: str = 'int64') IndexMap
Create a TIR Index mapping
- tvm.tirx.script.ir_builder.ir.local_scalar(dtype: str = 'float32', *, annotations: dict[str, Any] | None = None) TensorLoad
Allocate a zero-dimensional tensor in local memory.
- tvm.tirx.script.ir_builder.ir.meta_class(cls)
Decorator for utility classes used inside @T.function.
Instances of decorated classes are treated as parser meta values.
- tvm.tirx.script.ir_builder.ir.meta_var(value: T) T
Return a Python metadata value without binding, naming or relocating it.
- Parameters:
value (T) – Any host or IR object, including an unpackable sequence.
- Returns:
T – The exact input object. No frame is required, no IR is emitted, and existing names and source locations are retained.
.. code:: python – # Source and generated Python (the value retains its identity) value = I.meta_var(existing_value) a, b = I.meta_var((left, right))
- tvm.tirx.script.ir_builder.ir.ptr(dtype: str, storage_scope: str = 'global') Var
The pointer declaration function.
- tvm.tirx.script.ir_builder.ir.shared_scalar(dtype: str = 'float32', *, annotations: dict[str, Any] | None = None) TensorLoad
Allocate a zero-dimensional tensor in shared memory.
- tvm.tirx.script.ir_builder.ir.smem(shape, dtype='float32', data=None, strides=None, elem_offset=None, byte_offset=None, *, scope='shared', align=-1, offset_factor=0, layout=<MISSING>, allocated_addr=None, annotations=None)
Implement separately named allocation conveniences using the canonical Op.
- tvm.tirx.script.ir_builder.ir.target(target_config: dict | str, host: dict | str | Target | None = None) Target
Create a target
- tvm.tirx.script.ir_builder.ir.tmem(shape, dtype='float32', data=None, strides=None, elem_offset=None, byte_offset=None, *, scope='tmem', align=-1, offset_factor=0, layout=<MISSING>, allocated_addr=None, annotations=None)
Implement separately named allocation conveniences using the canonical Op.
- tvm.tirx.script.ir_builder.ir.void(expr: Expr | None = None) Expr
Construct a new tirx.Var with type void or cast expression to type void.
- tvm.tirx.script.ir_builder.ir.wg_reg_tile(elem_per_thread: int, dtype: str = 'float32') Var
Warpgroup-wide
(128, elem_per_thread)register tile in local scope.Sugar for the recurring pattern:
T.alloc_tensor(ty_args=[T.Tensor( (128, elem_per_thread), dtype, layout=wg_local_layout(elem_per_thread), scope="local", )])
Used to stage a tcgen05 load: each of the 128 threads in a warpgroup owns one row of
elem_per_threadcontiguous elements.
- class tvm.tirx.script.ir_builder.ir.LetAnnotation(type_spec=None)#
Marker used by
Tx.letandTx.let[dtype]annotations to construct an explicitLetStmt.
- tvm.tirx.script.ir_builder.ir.alloc_tcgen05_ldst_frag(instr_shape, tensor_shape, dtype)#
Allocate a local register fragment whose layout matches a
tcgen05.{ld,st}atom.instr_shapeaccepts"32x32b","16x64b","16x128b", or"16x256b". For example, a two-CTA Layout-B accumulator and its readback fragment can be allocated as:C = tmem_pool.alloc_tcgen05_mma_D( (64, 128), "float32", M=128, cta_group=2) frag = Tx.alloc_tcgen05_ldst_frag("32x32b", (64, 128), "float32") Tx.cuda.tile.tcgen05.ld(frag[:, :], C[:, :], scope="warpgroup")