1
$\begingroup$

A common issue with CPU performance is that pipelining requires the knowledge of what will come next, and what comes next can only be known once a branch condition is evaluated, so that instructions in the branch can be preloaded.

As such, CPUs employ branch predictors to predict which branch will be taken so that the pipeline can be preloaded.

However, depending on the circumstance, if there is a lot of work to be done between the evaluation of the branch condition and the actual branch, the next instructions in the pipeline to be preloaded do not yet depend on the outcome of the branch. If the condition can be known before the first do_something() or do_something_else() instruction has to even be prefetched, then can the branch be 'predicted' with certainty (i.e., no chance of pipeline flush due to misprediction), because there are enough intermediate instructions that at the time the condition becomes known, none of the branch-dependent instructions need to have been loaded. For starters, does what I am saying make sense, and can CPUs work this way? Is my understanding correct?

const bool condition = some_condition();
do_work();
if (condition) {
    do_something();
} else {
    do_something_else();
}
$\endgroup$
0

2 Answers 2

2
$\begingroup$

The delay slot is one realisation of this idea. On many first-generation RISC CPUs (e.g. MIPS, PA-RISC, SPARC), the next instruction after a branch is always executed. Some special-purpose machines (e.g. DSP) have multiple delay slots. If no useful work can be done, the instructions following a branch can be filled with NOPs.

Compilers would often spend a lot of effort to try to fill that delay slot.

For a scalar in-order pipeline, this makes a certain amount of sense. But the modern CPU design trend is to much longer instruction windows, and much deeper branch prediction to go with it. The chance that there is a pipeline full of work to be done between the time that the branch is "resolved in software" and the time that the branch is taken/not taken is essentially zero.

$\endgroup$
0
$\begingroup$

Various PowerPCs had a count register that was part of the branch unit, with an instruction “decrement and branch if non-zero”. Setting the count register had significant latency, but the “decrement and branch if non-zero” was not predicted. The processor handled it like an unconditional branch. Or like a no-operation if the counter reached zero.

I wonder if that would be a win on a modern processor.

More to your question: Prefetching isn’t a problem. Those instructions will be put into some cache, so the work isn’t lost. And often the code is already cached. The real problem and gain is executing instructions when you don’t know (yet) that they should be executed. So you execute an instruction but mark it as “predicted”. Once the branch result is known, either the instructions are committed (changed from predicted to executed), or the results are thrown away.

So your question is: If there is a conditional branch, and the condition is already known, will any overhead for conditional execution be avoided? Answer: Processors will try to make the cost as little as possible, and try very hard to make the cost zero. So you might not be able to see or measure a difference.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.