jax-ml/jax · error · ValueError
MMA rhs swizzle must match lhs swizzle. {lhs_swizzle=} {rhs_
Error message
MMA rhs swizzle must match lhs swizzle. {lhs_swizzle=} {rhs_swizzle=} What it means
In the Mosaic GPU (Pallas) tcgen05 MMA lowering, the LHS and RHS operands of a Blackwell tcgen05 matrix-multiply must share the same swizzle pattern. If only one side specifies a swizzle it is inherited from the other, but if both are given and differ, the lowering refuses to continue because the Tensor Core memory layout would be inconsistent.
Source
Thrown at jax/_src/pallas/mosaic_gpu/primitives.py:2777
swizzle_elems = 8 * rhs_swizzle // dtypes.itemsize_bits(b_dtype)
if rhs_tiling != (8, swizzle_elems):
raise ValueError(
"MMA rhs tiling does not fit swizzle"
f" {rhs_tiling=} expected={(8, swizzle_elems)}"
)
if barrier_transforms_tree is not None and barrier_ref is not None:
barrier_transforms = barrier_transforms_tree.unflatten(
barrier_transforms_leaves
)
base_index = _get_barrier_base_index(barrier_ref_aval, barrier_transforms)
if base_index is not None:
barrier_ref = barrier_ref[base_index]
if lhs_swizzle is None:
lhs_swizzle = rhs_swizzle
elif rhs_swizzle != lhs_swizzle:
raise ValueError("MMA rhs swizzle must match lhs swizzle."
f" {lhs_swizzle=} {rhs_swizzle=}")
if lhs_transpose:
if isinstance(a_ref, tcgen05.TMEMRef):
raise ValueError("TMEM transpose not allowed.")
a_ref = mgpu.memref_transpose(a_ref, (1, 0, 3, 2))
if rhs_transpose:
b_ref = mgpu.memref_transpose(b_ref, (1, 0, 3, 2))
if isinstance(accumulate, bool):
accumulate = mgpu.c(accumulate, ir.IntegerType.get_signless(1))
elif isinstance(accumulate, mgpu.FragmentedArray):
accumulate = accumulate.registers.item()
assert isinstance(accumulate, ir.Value)
if a_scale_ref is not None and a_scale_transforms_tree is not None:
assert isinstance(a_scale_ref_aval, state.AbstractRef)
a_scale_transforms = a_scale_transforms_tree.unflatten(
a_scale_transforms_leaves
)View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Set both lhs_swizzle and rhs_swizzle to the same value (or leave one as None so it inherits the other)
- Build both operands from the same memref layout / copy pipeline so swizzles are derived identically
- Check the swizzle mode reported in the message and adjust your mgpu.memref with the matching swizzle attribute
Example fix
// before tcgen05_mma(lhs, rhs, acc, lhs_swizzle=SwizzleMode.W32, rhs_swizzle=SwizzleMode.W64) // after tcgen05_mma(lhs, rhs, acc, lhs_swizzle=SwizzleMode.W32, rhs_swizzle=SwizzleMode.W32)
Defensive patterns
Strategy: validation
Validate before calling
assert lhs_swizzle is None or rhs_swizzle is None or lhs_swizzle == rhs_swizzle, 'swizzle mismatch'
Prevention
- Derive both operand swizzles from the same memref layout helper
- Log swizzle modes of both operands before the MMA call
When it happens
Trigger: Calling tcgen05_mma (or the tcgen05 MMA Pallas primitive) where the lhs Swizzle (e.g. SwizzleMode.W32_ATTRIBUTE etc.) differs from the rhs Swizzle, e.g. lhs built with a 32B swizzle and rhs with 64B or no swizzle.
Common situations: Mixing SMEM layouts when one operand comes from TMEM/SMEM with one tiling and the other from an async copy with a different tiling; upgrading JAX versions where swizzle defaults changed; hand-writing a tiled GEMM kernel.
Related errors
- Swizzle {self.swizzle} is not supported. Only 32, 64 and 128
- Swizzle {self.swizzle} requires the trailing dimension to be
- Can't transpose the swizzled dimension.
- Reshape shape {shape} is not divisible by swizzle elements {
- Expected metadata dtype to be uint2, got: {meta.dtype}
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/581fb4256b151559.
Report an issue: GitHub.