An in-order core issues strictly in program order. When the next instruction waits on an unready operand, every later instruction waits behind it, even independent ones.
This head-of-line blocking is simple to build and verify. Its cost is idle issue slots behind every exposed latency.
An out-of-order core issues any ready instruction from its window. Independent work flows past the stall, and true dependencies still wait for their operands.
Consider single-issue cores with ALU latency 1 and load latency 3, on this sequence: LD r1, then ADD r2 from r1, then independent ADD r3, then MUL r6 from r3.
in-order, single issue (result usable N cycles after issue; LD 3, ALU 1)
cycle 1: issue LD (r1 ready end of cycle 3)
cycle 2: stall (ADD r2 waits on r1)
cycle 3: stall (ADD r2 waits on r1)
cycle 4: issue ADD r2
cycle 5: issue ADD r3 (r3 ready end of cycle 5)
cycle 6: issue MUL r6
total 6 cycles for 4 instructions -> IPC = 4 / 6 = 0.67
out-of-order on the same sequence
cycle 1: issue LD (r1 ready end of cycle 3)
cycle 2: issue ADD r3 (independent; r3 ready end of cycle 2)
cycle 3: issue MUL r6 (r3 ready; ADD r2 still waits on r1)
cycle 4: issue ADD r2 (r1 ready)
total 4 cycles for 4 instructions -> IPC = 4 / 4 = 1.0In-order | Out-of-order | |
|---|---|---|
Issue rule | Program order only | Any ready instruction in the window |
Independent work behind a stall | Waits | Issues past the stall |
True dependency latency | Paid in full, plus blocking | Paid in full, without blocking others |
Hardware cost | Scoreboard or stall logic | Window, wakeup, select, reorder buffer |
Execution order is invisible to software. Both designs commit results in program order, so interrupts and exceptions stay precise.
The reorder buffer is the mechanism. A later lesson covers it in full.
ADD r2 on the LD through r1: the 3-cycle load latency is paid by both designs.
Nothing about its own dependency: its operand r3 was ready earlier, and out-of-order issue let it pass the stalled ADD r2.