2026-07-20
x86 CPUs decode multiple instructions per cycle, but the decoders are not identical. On Intel's classic 4-wide front-end (Skylake through Golden Cove's legacy path), you get one complex decoder and three simple decoders. This asymmetry shapes performance in ways that surprise almost everyone who doesn't stare at Agner Fog's tables for a living.
A simple decoder handles instructions that produce exactly one micro-op. Add, mov reg-to-reg, xor, cmp, jmp — the daily bread. Fast, cheap, replicated three or four times because the silicon cost is small.
A complex decoder handles instructions that produce 2–4 µops. Anything that touches memory in a non-trivial way, computes a segment override, or does two logical things at once. Only one exists per cycle because the logic for splitting an instruction into multiple µops needs a wider datapath, more control signals, and more buffering. Building four of these would blow the area and power budget for something you rarely need.
Instructions producing 5+ µops bypass the decoders entirely and go to the microcode sequencer (MSROM) — a slow, serialized path that stalls the front-end for many cycles. CPUID, RDTSC, string operations with prefixes, and gather/scatter often land here.
The alignment rule (4-1-1-1): The decoders are positioned in order. Slot 0 is complex; slots 1, 2, 3 are simple. If a 2-µop instruction appears in slot 1 (a simple slot), that slot rejects it, and the instruction has to wait until the next cycle where it can land in slot 0. You just lost decode bandwidth for this cycle.
Real-world example: A tight loop of add [rdi+rax*8], rcx (memory-destination add — 2 µops: load, add-store). Even though you can theoretically dispatch four per cycle, the decoders can only produce one per cycle because each needs the complex decoder. Your effective front-end throughput drops from 4 IPC to 1 IPC — a 4× regression that doesn't show up in any static instruction count. Rewriting as separate load + add + store (three 1-µop instructions) can double throughput because now three simple decoders fire in parallel.
Rule of thumb: If your hot loop's IPC is mysteriously stuck near 1.0 despite plenty of independent work, check IDQ.MITE_UOPS vs UOPS_ISSUED.ANY. If MITE (decoder path) is your bottleneck, you're probably starving the simple decoders by feeding them multi-µop instructions.
The µop cache (DSB) exists largely to hide this asymmetry — decoded µops replay from cache and skip the 4-1-1-1 constraint entirely.
