Suppose we have an SM80 core with an unsigned integer x in SASS register R0, and an unsigned integer modulus q in register R7. Now, to obtain x % q in R0, we run:
I2F.U32.RP R6, R7
IMAD.MOV R9, RZ, RZ, -R7
ISETP.NE.U32.AND P1, PT, R7, RZ, PT
MUFU.RCP R6, R6
IADD3 R4, R6, 0xffffffe, RZ
F2I.FTZ.U32.TRUNC.NTZ R5, R4
HFMA2.MMA R4, -RZ, RZ, 0, 0
IMAD R9, R9, R5, RZ
IMAD.HI.U32 R5, R5, R9, R4
IMAD.HI.U32 R5, R5, R0, RZ
IMAD.MOV R5, RZ, RZ, -R5
IMAD R0, R7, R5, R0
ISETP.GE.U32.AND P0, PT, R0, R7, PT
@P0 IADD3 R0, -R7, R0, RZ
ISETP.GE.U32.AND P0, PT, R0, R7, PT
@P0 IMAD.IADD R0, R0, 0x1, -R7
@!P1 LOP3.LUT R0, RZ, R7, RZ, 0x33, !PT
(I got this from compiling a modulo operation and assignment statement in GodBolt, see here).
I have a few questions about this code…
- What are the
@!Pnlines for n = 0, 1, 2 ? Are those predicated execution? Something else? - I don’t quite understand the use of the floating-point work we see here, followed be a conversion back to int: it seems to be taking 1.0f / q, and then turning off the least-significant-bit… huh? I kind of lost the logic there.