Assembly Hall of Shame
🏛️ Assembly Hall of Shame
While most developers spend their time optimizing for speed racing to the top of performance benchmarks, the Assembly Hall of Shame pursues a different goal: finding the absolute floor of single-instruction execution time.
"Instruction latency analysis usually focuses on performance optimization—making code run as fast as possible. The Assembly Hall of Shame takes the opposite approach: searching for the absolute floor of single-instruction performance."
🏆 The Reigning Champion 🏆
The current record holder for the slowest x86 instruction is fxrstor64.
The Strategy: PCIe Fabric Starvation
The goal is to force the CPU to wait as long as possible. By using fxrstor64 to load a 512-byte state from a high-latency MMIO region within the PCIe fabric, the instruction is already slow. To make it worse, a "fleet" of other CPU cores is used to "hammer" a different high-latency MMIO register with tight 4-byte reads. This saturates the PCIe root complex and endpoint with non-posted transactions, forcing the original fxrstor64 load to queue behind a massive wall of contending traffic.
The Stats:
- Hardware: AMD Ryzen 7 5800H
- The "Slow" Instruction:
fxrstor64 %rsi - The "Hammer" Code:
; CPU 0 (The Victim) movl $0xfcc68830, %rsi fxrstor64 %rsi ; CPUs 1..N (The Hammers) movl 0xfcc68858, %eax - Score:
198,002,498,236cycles - Wall Time: seconds
🎖️ Honorable Mentions
A notable mention goes to a spec-violating unaligned ymm0 load. By forcing non-posted dword transactions from stalled GPU registers, this technique was used to undermine the design of System Management Mode (SMM) in the smiiiiiiiiiiiiiiii project:
vmovdqu 0xfcc003b1, %ymm0
📜 The Rules of Engagement
To keep the competition fair, the following constraints are applied:
- Single Instruction Scoring: Setup code is permitted, but only one specific instruction is timed.
- No Handler Timing: For instructions that are trapped, emulated, or virtualized, only the time to trigger the trap is measured (not the handler's execution).
- Stock Hardware: No physical modifications; all platforms must remain in factory configurations.
📉 The Leaderboard (Intel Core i7-8559U @ 2.7GHz)
The following table summarizes the "race to the bottom" on a standard Intel chip.
| Instruction | Cycles | Time (ns) | Strategy Summary |
|---|---|---|---|
nop | 1 | 0 | Baseline reference. |
nop16 | 20 | 7 | Making "nothing" take longer. |
rdtsc | 49 | 18 | Reference for timing. |
idiv | 77 | 28 | Maximize quotient via 128-bit dividend. |
enter | 112 | 41 | Max nesting depth (31) for display-walk. |
fldl | 133 | 49 | Trigger FP microcode assist via denormal. |
clflush | 165 | 60 | Flush dirty L3 cache line. |
fsin | 257 | 94 | Use exponent 0x7ff for special value processing. |
mfence | 326 | 120 | Saturate write-combining LFBs. |
mov cr3 | 352 | 110 | TLB invalidation (AMD Ryzen 7 5800H). |
fadd | 677 | 249 | Denormal source microcode assist. |
🔍 Deep Dive into Strategies
1. The Divider (idiv)
To maximize latency, the dividend is set to (using rdx:rax) with a small divisor (5). This pushes the quotient above the sign-extension ceiling, forcing the microcode to take the longest possible path.
2. The Stack Frame (enter)
By setting the nesting depth to the maximum of 31, the CPU is forced to perform 30 display-pointer loads and pushes.
enter $0, $31 ; 0 bytes allocated, depth 31
3. Floating Point Assists (fldl & fadd)
Using denormal (subnormal) numbers triggers a "microcode assist," which is significantly slower than the fast path.
fldl: Load a small denormal.fadd: Use a subnormal source operand (e.g., ).
4. Memory Fencing (mfence)
The strategy here is to saturate all write-combining line-fill buffers (LFBs) using movnti stores to 16 different cache lines. The mfence instruction cannot retire until the entire LFB write path is drained to the uncore.
5. The Split Lock
The goal is to align a lock-prefixed operand so that it straddles a cache-line boundary. This forces the processor to assert an external bus lock rather than using the internal cache-locking mechanism.
![]()