name: cheap-masm-equivalents
description: Use when writing or reviewing MASM hot paths — prefer the cheaper equivalent instruction: neq.0 over gt.0 for non-zero checks, cdrop over an if/else selecting between two values, dup.N over loc_load for a value still on the stack, eqw over element-wise word comparison, u32gt/u32lt over generic gt/lt on known-u32 operands.
Prefer Cheap MASM Equivalents
Rule
Several MASM idioms have a cheap and an expensive form. Use the cheap one when both produce the same result on the inputs the procedure can see:
- Non-zero check:
neq.0(3 cycles) overgt.0(16 cycles). - Selecting between two values on a flag:
cdropover anif.true ... else ... endbranch with the same effect. - Re-fetch a recently-pushed value:
dup.Noverloc_load.Nwhen the value is still on the stack. - Whole-word equality:
eqwover element-wise comparisons. - u32-known operands:
u32gt/u32ltover genericgt/lt.
Don't apply the cheap form when the operands violate its precondition (e.g. u32gt on a value that might exceed u32::MAX).
Why
MASM cycle costs are not uniform — gt.0 does signed-comparison work that neq.0 skips, so a hot path using the expensive form pays for it on every call. The swaps are semantically equivalent under their preconditions, so the saving is free.
Examples
# Good
push.0 neq # non-zero check, 3 cycles
# or simply
neq.0
# Bad
push.0 gt # same answer, 16 cycles
# Good: cdrop for ternary selection
# stack: [b, a, cond]
cdrop
# stack: [a if cond else b]
# Bad: branchy equivalent
if.true
drop # drop b, keep a
else
swap drop # drop a, keep b
end