Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are BOOST_LIKELY and __builtin_expect still relevant?

I understand what is explained here as well as these would include hints to CPU for static branch prediction.

I was wondering how relevant are these on Intel CPUs now that Intel CPUs have dropped support for static prediction hints as mentioned here. Also if I understand how it works now, the number of branch instructions in the path would be the only thing that the compiler can control and which branch path is predicted, fetched and decoded is decided at runtime.

Given this, are there any scenarios where branch hints in code are still useful for software targeting recent Intel processors, perhaps using conditional return or for avoiding the number of branch instructions in the critical path in case of nested if/else statements?

Also, if these are still relevant, any specifics on gcc and other popular compilers are appreciated.

P.S. I am not for premature optimization or for peppering the code with these macros, but I am interested in the topic as I am working with some time critical code and still like to reduce code clutter where possible.

Thanks

like image 756
Aelian Avatar asked May 15 '15 18:05

Aelian


People also ask

What is __ Builtin_expect?

You can use the __builtin_expect built-in function to indicate that an expression is likely to evaluate to a specified value. The compiler can use this knowledge to direct optimizations. This built-in function is portable with the GNU C/C++ __builtin_expect function.

What is the use of likely and unlikely macros in Linux kernel?

A look at the Linux kernel code will show many if conditions enclosed in likely and unlikely macros. These macros invoke compiler directives that give the compiler a hint on the code leg that should be optimized for performance.


1 Answers

As in the comments section for your question you correctly figure out that:

  1. There are no static branch prediction hints in opcode map anymore on Intel x86 CPUs;
  2. Dynamic branch prediction for "cold" conditional jumps tend to predict the fallthrough path;
  3. The compiler can use __builtin_expect to reorder what path of the if-then-else construct will be placed as a fallthrough case in generated assembly.

Now, consider a code base being compiled for multiple target architectures, not just Intel x86. A lot of them do have either static branch hints, dynamic branch predictors of different complexity, or both.

As an example, Intel Itanium architecture does offer an extensive system of prediction hints for all types of instructions: control flow, load/store etc. And Itanium was designed to have code being extensively optimized by a compiler with all these statically assigned instructions slots in a bundle and hints.

Therefore, __builtin_expect is still relevant for (rare) cases when 1) correct branch prediction information was too hard to deduce automatically by a compiler, and 2) the underlying hardware on at least one of target architectures was also known to be unable to reliably predict them dynamically. Given that certain low-power processors include primitive branch predictors that do not track branch history but always choose the fallthrough path, it starts to look beneficial. For modern Intel x86 hardware, not so much.

like image 97
Grigory Rechistov Avatar answered Sep 19 '22 12:09

Grigory Rechistov