Layout IR#
Layouts describe how logical tensor coordinates map to storage and execution axes. See Tensor Layout for the programming model and worked examples.
The primary classes are re-exported from tvm_tirx.tirx, but are defined in this
module:
- class tvm_tirx.tirx.layout.Layout(*args: Any, **kwargs: Any)
Base class for mappings from logical indices to named physical axes.
Concrete layouts describe memory offsets and thread ownership.
apply()returns coordinates keyed by axis name;size()describes the input size andspan()the covered output span.- check_well_formed() None
Check whether the layout is well formed.
- Raises:
ValueError, RuntimeError – If the layout is not well formed.
- 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
- 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.
- tile_to(to_shape: list[Expr], current_shape: list[Expr]) Layout
Tile the current layout to the given shape.
- is_trivial() bool
Check if the layout is trivial.
- unpack(num: int, axis: str = 'm') Layout
Unpack the layout, where a single element in the layout is unpacked into num contiguous elements.
- class tvm_tirx.tirx.layout.Axis(*args: Any, **kwargs: Any)
A named physical coordinate used by a layout.
Use
Axis.get(name)or a registered attribute such asAxis.m. Axis metadata identifies memory or thread coordinates and any owning backend;value @ axisattaches a stride or offset to that coordinate.Examples
from tvm_tirx.script import tirx as T memory = T.Axis.get("m") # Also available as T.Axis.m. layout = T.TileLayout(T.S[8 : 2 @ memory]) assert int(layout.apply(3)["m"]) == 6
- 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() ThreadScope | None
Get the scope of the axis.
- get_subscope() ThreadScope | None
Get the subscope of the axis.
- class tvm_tirx.tirx.layout.Iter(extent: Expr, stride: Expr, axis: Axis | str)
One extent-and-stride factor contributing to a layout axis.
- class tvm_tirx.tirx.layout.TileLayout(spec: _LayoutSpec)
Map logical indices to memory and ownership coordinates using strided factors.
shardholds the factors for distinct logical elements;replicaholds factors for copies of those elements.offsetgives an origin per axis. Usefrom_iters()to construct these fields directly.- Parameters:
spec (layout specification) – Compose
S[shape:stride]shard factors, optionalR[shape:stride]replica factors, and offsets with+. Integer strides use the memory axism;stride @ Axis.nameselects another axis. Omitted strides use contiguous row-major memory order.
Examples
from tvm_tirx.script import tirx as T layout = T.TileLayout(T.S[4, 8]) # Contiguous 4-by-8 tile. assert int(layout.apply(1, 2)["m"]) == 10
- 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_contiguous(analyzer=None) bool
Whether memory-only tile strides are contiguous, regardless of origin.
Replicas and non-memory axes are rejected. An optional analyzer supplies existing constraints; symbolic proof is otherwise initialized lazily.
- is_trivial() bool
Check if the layout is trivial.
- class tvm_tirx.tirx.layout.ComposeLayout(per_element: int, swizzle_len: int, atom_len: int, tile_layout: TileLayout, swizzle_inner: bool = True)
Apply an XOR swizzle to the memory coordinate of a tile layout.
All three bit counts must be nonnegative.
- Parameters:
per_element (int) – Number of low address bits left unchanged by the swizzle.
swizzle_len (int) – Number of bits in each XOR group; zero disables swizzling.
atom_len (int) – Separation between the bit groups; must be at least
swizzle_len.tile_layout (TileLayout) – The underlying mapping to memory coordinates.
swizzle_inner (bool, optional) – If true, XOR the higher group into the lower group; otherwise XOR the lower group into the higher group. Defaults to true.
Examples
from tvm_tirx.script import tirx as T tile = T.TileLayout(T.S[8, 8]) layout = T.ComposeLayout(0, 2, 3, tile) # Memory offset 10 becomes 10 ^ ((10 >> 3) & 3) = 11. assert int(layout.apply(1, 2)["m"]) == 11
S[...] and R[...] build shard and replica layout specifications,
respectively. Named axes such as laneid, warpid, tid_in_wg,
TLane, and TCol belong to CUDA. Use T.cuda.Axis.laneid or
import axes from tvm_tirx.backend.cuda.axis. Trainium’s P, F, and
Bank belong to T.trn.Axis. The generic memory axis remains T.Axis.m.
CUDA memory/instruction layout factories are defined in
tvm_tirx.backend.cuda.layout and exposed as T.cuda.layout. Trainium
layouts use explicit partition, free and bank axes. For example:
from tvm_tirx.backend.trn.axis import P, F, Bank
from tvm_tirx.tirx.layout import TileLayout, S
# A (128, 512) SBUF tile: partition p, free element f.
sbuf_layout = TileLayout(S[(128, 512) : (1 @ P, 1 @ F)])
# Two (128, 512) PSUM tiles, one per bank.
psum_layout = TileLayout(S[(2, 128, 512) : (1 @ Bank, 1 @ P, 1 @ F)])
Annotation strings are not accepted by generic tensor constructors.
Omitting layout or passing layout=None leaves every storage scope
without a layout. layout="default" explicitly requests a compact
TileLayout. Ordinary views preserve shape, strides and element offsets
without creating a layout. TensorType.effective_layout() returns an
explicit layout or infers a temporary compact layout for a global tensor.
Tile instructions query it through tensor.ty.effective_layout(), using
the full tensor shape before slicing an operand region. The query does not
change the tensor type or its layout=None field. Noncompact global tensors
and other storage scopes require an explicit layout when the instruction uses one.
Represent tensor layouts, iteration axes, and mappings between logical and physical storage.