This trace follows the actual state transitions behind the companion Branch Prediction and Exposing Parallel Work. It describes a common execution path; implementation details can vary, so keep the contract separate from the mechanism.
Step 1: Predict the branch direction
Branches make program control depend on data. A modern CPU predicts likely directions so it can keep fetching instructions before the condition is fully resolved. Correct predictions preserve pipeline flow; incorrect ones require discarding speculative work and refilling parts of the pipeline.
Step 2: Execute along the predicted path
A loop over sorted values may have a highly predictable branch, while a branch on randomized values may be difficult to predict. Some code can be expressed with conditional operations or grouped data to reduce unpredictable control flow, but those rewrites can increase instruction count or complicate correctness.
Step 3: Resolve the condition
The processor can begin work before a branch resolves; if the prediction is wrong, dependent speculative instructions are discarded and the correct path must refill the pipeline.
At this point, record the state that changed and check the invariant before advancing. If the operation repeats, make clear which values persist and which are recomputed.
Step 4: Keep or discard speculative work
Instruction-level parallelism is limited by dependencies, branches, and memory stalls. Removing a branch is not automatically faster; the new operations may cost more or prevent vectorization. Benchmark realistic input distributions and check that the compiler generated the intended code.
Step 5: Measure the actual workload
You have a filter with a branch that is true for almost every element. Explain why that may perform differently from a branch that is true half the time, and name one measurement you would collect.
The trace is complete when the result satisfies the stated contract. Compare this model with the concrete runtime or system you are studying before making a performance claim.