instruction waits to updated reg for comparison is a wrong description of control dependencies, no wonder
Conditional branch instructions themselves have a data dependency on their input register(s) before the branch condition can be checked.
Instructions after the branch have a control dependency on the branch. The front-end needs to know which instructions to fetch/decode, based on whether the branch was taken or not. (Or for indirect branches, what the target address was).
Branch prediction makes a guess that might later be discovered to be wrong. (When the branch instruction actually executes and checks the prediction).
In simple (scalar) in-order pipelines, there's no way for dependent instructions to reach the exec stage before the branch instruction does. Discovering and recovering from a branch mispredict just means re-steering the front-end to fetch from the correct address, discarding the instructions from the wrong path that had been fetched (and decoded).
But in out-of-order exec CPUs that can happen. Especially if the branch's inputs were part of a long dependency chain, but the instructions with a control dependency on it don't have data dependencies. (i.e. they're independent work that the out-of-order back-end can get started on speculatively.)
Branch prediction + speculative execution effectively hide control dependencies when the prediction is correct. That's why compilers will often transform if (a==0) return a;
into if (a==0) return 0;
and similar; if they're going to branch anyway (control dependency), break / avoid the data dependency for the code using the return value.
Related: