I understand the need for re-order buffer in speculative execution. However, given a sequence of non-speculative instructions without any branches, why is it that all these instructions still have to go through the ROB and then commit in order? Since there is no control hazard and assuming the presence of register renaming to avoid WAR and WAW hazards, is ROB a necessity in such a case?
One reason I could think of, is for handling imprecise exceptions. Is there any other reason?
In a real out-of-order machine there's no such thing as non-speculative instructions, everything has to go through the reordering buffer because you do not know, at the pipestage of allocation, what is going to be cleared and what gets committed, because any older branch may have not executed yet. At any moment such branch may be resolved as a mispredict, and flush all younger ROB entries.
I guess you could prevent control hazards by stalling allocation on each conditional branch, but that would have horrible performance and eliminate a lot of the benefits in out-of-order execution by turning each branch (whose average frequency is usually expected to be once every 5 instructions) into a serialization point and a stall.
Another "benefit" of having to go through the ROB is register renaming. Without an ordered index, you'll have trouble managing your physical registers to make any sense according to program order. Say you have 3 consecutive instructions as such:
Say
rbx
is ready late, when it's finally ready to execute theadd
, how would the out-of-order engine know which value ofrax
to take? you have by now the old value, the+1
and+2
and all of them are ready - an OOO machine should mark the source as the renamed version of rax at the moment the add entered the ROB. By the way, there are other ways to achieve that correctness but they're more complicated and still require ordering queues.