fma#
T.cuda.tile.apply(T.ptx["fma.rn.f32"], dst, a, b, c) computes the
selected fused multiply-add for each repeat. a*b+c is one native FMA
atom, including its explicit rounding qualifier. It is not a request for
two independently rounded multiply/add instructions.
Scalar tensor operands have suffix (1,). Read-only scalar operands
broadcast over repeats. Packed f16x2/bf16x2 forms use uint32 carriers;
packed f32x2 uses uint64. A packed constant must encode both values.
The opcode and storage representation stay explicit even if a contiguous
layout would permit several other forms.
Example: four fused operations#
from tvm.script import tirx as T
@T.function
def affine_fma(A: T.Tensor((4, 1), "float32"), Out: T.Tensor((4, 1), "float32")):
T.device_entry(launch=T.cuda.LaunchConfig(grid=1, block=1))
r = T.alloc_local((4, 1), "float32", layout="default")
T.cuda.tile.apply(T.ptx["ld.global.f32"], r, A)
T.cuda.tile.apply(T.ptx["fma.rn.f32"], r, r, T.float32(2), T.float32(1))
T.cuda.tile.apply(T.ptx["st.global.f32"], Out, r)
The arithmetic expansion has four fma.rn.f32 calls. For small integer
inputs the reference is exactly 2*A+1. Tests intended to distinguish
rounding modes must instead use inputs whose exact product-plus-addend lies
between representable outputs; a rounded multiply followed by a rounded
add is not an adequate FMA reference.
Use .rm, .rp or .rz only when that form’s rounding is intended
and supported by the selected type. Predication and destination preservation
follow mov. Memory loads/stores and synchronization remain caller code.
Implementation: python/tvm/backend/cuda/tile/patterns/register.py.