Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Registry-Only & Special-Op Lowering

Lowering observed by feeding PTX to ptxas v13.1 (CUDA 13.1.115) at the lowest -arch that accepts each form (sm_89 for the classic ops, sm_90a / sm_100 for the cluster ops) and disassembling with nvdisasm. Other versions will differ.

This page documents the SASS lowering of the PTX instructions that the MercConverter dispatch table routes to a handler but which are otherwise undocumented: the predicate/select ops, the FP class test, the bit-manipulation primitives, the address-space queries, the cache/scheduler hints, the stack/frame ops, and the cluster intrinsics. For each: the SASS op(s) emitted (or pseudo / no-op / barrier-only / driver-handled), a one-line semantics, and the SM floor.

Predicate, select, and class-test ops

PTXSASSSemanticsFloor
set.<cmp>.f32.ssingle native FSET.BF.<cmp> (float dest = 1.0f/0.0)compare a,b, write float result; .BF = boolean-float result modesm_50+
set.<cmp>.u32.sISETP.<cmp> + SEL Rd, RZ, 0xffffffff, !P (int dest = all-ones / 0)compare a,b, write integer mask resultsm_50+
set.<cmp>.<boolop>one fused ISETP.<cmp>.{AND,OR,XOR} (predicate q folds into the third predicate input) + SELcompare then combine with predicate qsm_50+
slct.d.s32ISETP.GE …, RZ + predicated SEL/loadd = (c ≥ 0) ? a : b (select on sign of c)sm_50+
slct.d.f32ISETP.GE …, RZ + SELsame, f32 selector compared ≥ 0sm_50+
selp.b32SEL Rd, Ra, Rb, Ppredicate-driven select (consumes an existing predicate)sm_50+
cnot.b32ISETP.EQ.U32 …, RZ + SEL + IMAD.MOV R, RZ, RZ, -RC-logical not: d = (a == 0) ? 1 : 0sm_50+
testp.<class>.f32LOP3.LUT …, 0x7fffffff (clear sign) + 1–3 ISETP against IEEE bit patterns + SEL/predicateFP class test {finite, infinite, number, notanumber, normal, subnormal} → predicatesm_50+

set is the data-register sibling of setp: it runs the same *SETP compare and then expands the predicate to a full-width data value with SEL. The boolean-secondary form (set.lt.and) does not emit a second op — the predicate operand folds into the ISETP's third predicate input (ISETP.LT.AND P, PT, a, b, q). testp is a small open-coded sequence (mask off the sign bit, then compare the magnitude against +INF / smallest-normal / zero), never a single op.

Example — cnot.b32:

ISETP.EQ.U32.AND P0, PT, Ra, RZ, PT     ; a == 0 ?
SEL  R0, RZ, 0xffffffff, !P0
IMAD.MOV R, RZ, RZ, -R0                  ; -> 0/1

Example — testp.finite.f32:

LOP3.LUT R, Ra, 0x7fffffff, RZ, 0xc0, !PT     ; |x| bits
ISETP.GE.U32.AND P0, PT, R, 0x7f800000, PT     ; |x| >= +INF ?
SEL R, RZ, 0x1, P0                              ; finite = NOT(>=INF)

Bit-manipulation primitives

PTXSASSSemanticsFloor
bmsk.{clamp,wrap}.b32BMSK Rd, Ra, Rbmask of b ones starting at bit asm_75+ (native; rejected below)
szext.{clamp,wrap}.s32SGXT Rd, Ra, Rbsign/zero-extend the low field of a from bit bsm_75+ (native; rejected below)
fns.b32multi-op: BREV + POPC/FLO + ISETP/SHF/PLOP3 searchfind the n-th set bit (from a base, with direction)sm_75+ accepts; open-coded

bmsk and szext are 1:1 native ops on every architecture ptxas still targets; there is no software fallback (the bare op is required). fns accepts but expands into a leading-one / population-count search sequence rather than a single op:

BREV  R4, Ra
... PLOP3 / ISETP base+direction handling ...
IADD3 R5, -R5, 0x1f, RZ        ; convert FLO index to bit position
SHF.L.U32 R7, 0x1, R5, RZ      ; produce the result mask/index

Address-space & type queries

PTXSASSSemanticsFloor
isspacep.{global,shared,local,const}QSPC.E.{G,…} P, RZ, [Ra] + UISETP/PLOP3/SEL window-range composetest whether a generic pointer is in a state space → predicatesm_75+ (native QSPC)
isspacep.shared::clusterQSPC.E.D P0, RZ, [Ra] + SELtest pointer is in the distributed (cluster) shared windowsm_90+
istypep.{texref,samplerref,surfref}LOP3.LUT …, <typemask> + ISETP.NE + SELtest an opaque handle's type → predicate (bit-test on the driver handle layout)sm_50+

isspacep queries the hardware state-space window with QSPC (query-space) and then composes the window membership with uniform-predicate logic; istypep is a pure bit-test against the handle-descriptor type field — no query op.

Cache & scheduler hints

PTXSASSSemanticsFloor
prefetch.global.L2CCTL.E.PF2 [Ra]prefetch line into L2sm_50+
prefetch.global.L1CCTL.E.PF1 [Ra]prefetch line into L1sm_50+
prefetchu.L1CCTL.E.PF1 [Ra]prefetch into the uniform/constant pathsm_50+
applypriority.global.L2::evict_normalCCTL.E.DML2 [Ra]demote a cache line to a lower L2 prioritysm_80+
discard.global.L2CCTL.E.RML2 [Ra]remove (discard) a cache line from L2sm_80+
griddepcontrol.launch_dependentsno SASS emitted (pure scheduler hint, consumed by the launch path)release dependent grids earlysm_90+
griddepcontrol.waitACQBULKwait until prerequisite grids have signalledsm_90+

The prefetch / priority / discard family are all CCTL (cache-control) sub-modes selected by a suffix (PF1/PF2/DML2/RML2). griddepcontrol.launch_dependents is the notable no-op — it produces zero SASS instructions; it is a hint to the programmatic-dependent-launch machinery, not a datapath op.

Stack / frame ops

These manipulate the stack pointer R1 directly; there is no dedicated SASS opcode for any of them.

PTXSASSSemanticsFloor
stacksave.u32 dMOV Rd, R1read the current stack pointersm_50+
alloca.u32 ptr, size, alignIMAD.IADD R1, R1, 1, -Rsize + LOP3.LUT R1, R1, 0xfffffff0, RZ, 0xc0 (align-down) + MOV Rptr, R1grow the per-thread stack frame, return new pointersm_50+
stackrestore.u32 dMOV R1, Rdrestore the stack pointer to a saved valuesm_50+

alloca subtracts the (aligned) size from R1 and returns the new R1 as the frame pointer; the align immediate becomes the LOP3 mask (0xfffffff0 for 16-byte alignment). The returned pointer is a .local window offset.

Cluster intrinsics (sm_90+)

PTXSASSSemanticsFloor
mapa.shared::cluster.u64 d, a, rankUPRMT (insert target CTA-id into the address bits)map a shared address to peer CTA rank's windowsm_90+
getctarank.shared::cluster.u32 d, aSHF.L.U64.HI (extract the CTA-rank field of a cluster address)rank of the CTA owning a cluster shared addresssm_90+
clusterlaunchcontrol.try_cancel … [mbar], [out]ELECT + UGETNEXTWORKID.SELFCAST [out], [mbar] (warp-leader-gated)attempt to cancel/claim the next cluster work item, posting to an mbarriersm_100+
st.bulk.weak [addr], size, valUMEMSETS.64 [UR], URZ, UR<size/8>bulk-initialize a shared region to val (uniform memset)sm_100+

mapa rewrites the CTA-id portion of a distributed-shared address via a uniform byte-permute (UPRMT); getctarank reads that same field back out with a funnel shift. clusterlaunchcontrol.try_cancel elects a warp leader and runs the cluster work-distribution op UGETNEXTWORKID. st.bulk is the uniform shared memset (UMEMSETS), the same SASS family as MercConverter's MEMSET opcode.

Trap, breakpoint, sleep, perf-event

PTXSASSSemanticsFloor
trapBPT.TRAP 0x1abort the kernel / enter the trap handlersm_50+
brkptBPT.TRAP 0x1debugger breakpoint (suspend the warp)sm_50+
nanosleep.u32 tNANOSLEEP Rtsuspend the warp for ~t nanosecondssm_70+ (native; no pre-Volta path)
pmevent NPMTRIG 0x<1<<N>fire performance-monitor trigger N (index → one-hot mask)sm_50+
pmevent.mask MPMTRIG 0x<M>fire the set of triggers in mask Msm_50+

trap and brkpt lower to the same BPT.TRAP opcode (distinguished only by an internal mode subfield, not visible in the disassembly). pmevent converts its single index into a one-hot trigger mask (1 << N); pmevent.mask passes the mask through unchanged to PMTRIG.

Cross-References