What is the default probability of [[likely]]
? Is it possible to change it?
Backgound: GCC has the following built-in functions:
long __builtin_expect(long exp, long c)
: the probability that a __builtin_expect expression is true is controlled by GCC'sbuiltin-expect-probability
parameter, which defaults to 90%.long __builtin_expect_with_probability(long exp, long c, double probability)
: the last argument, probability, is a floating-point value in the range 0.0 to 1.0, inclusive.
What is the C definition of the term "likely"? 51%? 90%? What does the term "arbitrarily (un)likely" mean?
CodePudding user response:
Nowadays, most architectures have pipelines. If the processor decodes a conditional jump (which if
is translated to) earlier than the condition is evaluated, it's permitted to continue evaluation speculatively (without actually committing the result). [[likely]]
and [[unlikely]]
simply directs the compiler to generate code choosing the path to take in these speculative cases. I'm not aware of any architecture that has probabilities involved here, it's definitely evaluated that way (if speculative evaluation is possible).
Also, sometimes you might use these against probabilities. Say you have a code optimized for a specific processor. You are aware that on the actual evaluation path you'll use each and every cache line in the CPU and you've identified which conditions might cause a cache line to be loaded. In this case, you'll likely want to put [[likely]]
on the path that doesn't load a new cache line, regardless of probabilities: causing speculative loading to load a new line (and therefore potentially drop a line you'd still use) likely costs more than simply planning for no new cache line loads. So it's really not about probabilities, but speculative path to be taken by CPU (until the condition is evaluated).
CodePudding user response:
There is no "probability" for these things. They tell the compiler to rearrange code and tests around branches to optimize for the case where one path is more often taken than another. But that's all.
These are not everyday tools you should be tossing into every loop and if
statement. These are micro-optimization tools that are best used when one has a clear performance target in mind and one sees that the compiler is generating sub-optimal machine code in a performance-critical section of code. Only then do you employ these tools. And even then, you need to check the generated code to see if they fixed the problem you're trying to solve.
These are compiler tweaks for cases where the compiler's usual methods of code generation around a branch does not produce optimal code. It's not about probability; it's about micro-optimization.
Here is a quote from the paper adding this feature to the standard:
Objection #1: Can this feature easily result in code pessimization?
Yes, as shown by the conditional move example misusing a branch hint can definitely result in worse code with a much longer run time. This feature is primarily meant to be used after a hotspot has been found in existing code. The proposed attributes are not meant to be added to code without measuring the impact to ensure they do not end up degrading performance.
Emphasis added. So please do not just throw these anywhere.