the load/store queue
Out-of-order cores happily reorder arithmetic, but memory is trickier: a load might read a location that an earlier, not-yet-finished store is about to write. Letting the load run early would read stale data and silently corrupt the program. Picture a delivery desk that must check, before handing a parcel to whoever asks, whether an earlier instruction was about to change that same parcel. The load/store queue (LSQ) is that desk: hardware that tracks all in-flight memory operations and enforces the correct ordering between loads and stores to the same address.
Concretely, every load and store is entered, in program order, into the LSQ (often a separate load queue and store queue). Store addresses and data are buffered there until the store commits — it is not written to memory or cache speculatively. When a load wants to execute, the hardware does memory disambiguation: it checks the store queue for any older store to the same address whose value has not yet reached memory. If it finds one with the data ready, it forwards that store's value straight to the load (store-to-load forwarding), skipping memory entirely. If an older store's address is still unknown, the load must either wait or speculate and be ready to re-execute if the guess proves wrong. Stores themselves drain to memory only at commit, in order.
The LSQ is what makes out-of-order execution safe for memory, not just registers, and store-to-load forwarding is a significant performance win for common producer-consumer patterns. The honest difficulty is that addresses are often computed late, so the machine must guess whether a load and an unknown-address store collide (memory dependence speculation) and recover when wrong — a subtle, bug-prone, and security-sensitive piece of the core. It is also exactly the kind of speculative memory machinery implicated in several microarchitectural attacks.
store [x1] = 5 (address x1 still unknown), then load x9 = [x2]. If x2 turns out to equal x1, the load must get 5 — the LSQ forwards the buffered store value; if it guessed they differed and executed early, it must re-execute.
Track in-flight memory ops; forward a pending store to a matching load, or re-execute if a guess was wrong.
Memory cannot be reordered as freely as registers because store/load addresses may alias and are often computed late. Disambiguation guesses and recovers; getting it wrong is both a correctness bug and, historically, a speculative side-channel surface.