This question is mostly a follow up after reading this article by Aater Suleman on improving branch prediction from the software side. The author provides a way to "unroll" conditional statements such to increase the probability of predicting a branch taken in the case of a 2-bit saturated counter scheme. Here's an exerpt:
Let me explain with an example. Lets suppose that X is random variable between 0 and 99. I want to run the following code:
if (X > 5 && X < 95) //branch is taken 90% of the time
do_something();However, if I write the code as:
if(X > 5) //branch is taken 95% of the time
if(X < 95) //branch is taken 95% of the time
do_something();The branch predictor has a better shot at predicting both these branches more accurately which may lead to better performance because the counters assigned to both these branches are more likely to stay saturated at taken (because two not-taken are less likely).
In general, any time you are ANDing/ORing conditions in an if-statement, you should think if the combination will be more biased or less biased and pick the version which is more biased.
My question is: do compilers follow this heuristic all of the time? Would a compiler even have the jurisdiction to do something like this since compilers exist in the scope of ISA's and architectures and branch prediction schemes exist in the scope of processors and more specific hardware implementations?
My intuition is that it would not hurt performance to expand control statements in such a way but at the same time I have not been able to find any evidence that compilers make such optimizations. If that is the case, why don't they? What am I missing in my reasoning and can someone please provide an example where such an optimization would be detrimental with respect to a certain architecture or prediction scheme?
Thanks.