When I look at the kernel, I always encounter the IF (likely ()) {} or if (unlikely ()) statement, which is understood at first, so I would like to introduce you.
Likely () and unlikely () are the two macros defined in the kernel (I see version 2.6.22.6, 2.6 should have). Located in/include/linux/compiler.h,
It is defined as follows:
#define LIKELY (x) __builtin_expect (!! (x), 1)
#define UNLIKELY (x) __builtin_expect (!! (x), 0)
__builtin_expect is a pre-processing command provided in GCC (version >=2.96, on-line, I haven't verified) (this noun is also written on the web, I want to call the function better), which facilitates code optimization. GCC (version 4.4.0) is specifically defined as follows:
Long __builtin_expect (long exp, long c) [built-in Function]
The annotations are:
__builtin_expect to provide the compiler with branch prediction information. In the general, you should prefer to use actual profiles feedback for this ('-fprofile-arcs '), as programmers is notoriously b Ad at predicting how their programs actually perform. However, there was applications in which the this data was hard to collect. The return value is the value of exp, which should are an integral expression. The semantics of the built-in is that it's expected that exp = = c.
It means: We can use this function to tell the Yi that some branches predict that "exp==c" is "likely to happen".
#define LIKELY (x) __builtin_expect (!! (x), 1) means that x==1 is "often occurring" or "likely to happen".
With likely, the likelihood of executing an if statement is greater, the compiler compiles the contents of if{} to the front, and with unlikely, it is more likely to execute else after the statement, and the compiler compiles the contents of the else{} to the front. This facilitates CPU prefetching and increases the accuracy of prefetch instructions, thus improving efficiency.
For example (kernel version 2.6.22.6): There is a paragraph in/KERNEL/SHED.C:
if (likely (!active_balance)) {
/* We were unbalanced, so reset the balancing interval */
Sd->balance_interval = sd->min_interval;
} else {
/*
* If we ' ve begun active balancing, start to back off. This
* Case is not being covered by the all_pinned logic if there
* is a 1 task on the busy Runqueue (because we don t call
* move_tasks).
*/
if (Sd->balance_interval max_interval)
Sd->balance_interval *= 2;
}
During compilation, the contents of {} After if are compiled to the front, and the contents of the {} after else are compiled to the back. The opposite is true if the likely is replaced with unlikely.
In short, likely and unlikely interchange or not will not affect the correctness of the program. However, the efficiency of the program may be affected.
if (likely (foo))//think Foo is usually 1
if (Unlikely (foo))//think Foo is usually 0
Thank you for visiting!
Do not know whether to write clearly, to correct!
Doubts:
Why likely or unlikely to be defined as __builtin_expect (!!) (x), 1), not directly with __builtin_expect (x, 1)? " !! (x) "and" X "What is the difference?
In addition, likely and unlikely in the kernel 2.6.31.5 also have a definition:
# ifndef likely
# define likely (x) (__builtin_constant_p (x)?!! (x): __branch_check__ (x, 1))
# endif
# ifndef unlikely
# define unlikely (x) (__builtin_constant_p (x)?!! (x): __branch_check__ (x, 0))
# endif
"Go" GCC compilation optimization---likely () and unlikely () functions