<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hello,<div class=""><br class=""></div><div class="">Recently I have stumbled across an almost double performance decrease in one of my codebases when compiling with clang instead of gcc. I was testing with the currently latest 3.9.1 as well as 4.0.0 rc2 targeting x86-64 darwin with -Ofast, and after some investigation was able to narrow down the code to the following snippet:</div><div class=""><br class=""></div><div class=""><div class="">__attribute__ ((noinline)) bool calculate(double c) {</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>uint32_t b = 0;</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>uint32_t a = 0;</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>while (b < 0xFFFFFFFF) {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;"> </span>if ((uint64_t)(b / c) % 2 == 0)</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>a++;</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>b++;</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div class=""><span class="Apple-tab-span" style="white-space:pre"> </span>return a;</div><div class="">}</div></div><div class=""><br class=""></div><div class="">The culprit here is the division, which is not hoisted out of the loop and replaced with a multiplication by a reciprocal. From what I understand the current implementation of combineRepeatedFPDivisors responsible for floating point division conversion does that given that the following preconditions are met:</div><div class="">— unsafe math optimisations are enabled;</div><div class="">— the amount of the divisions by the same divisor in a single basic block is above the threshold (2 for x86-64).</div><div class=""><br class=""></div><div class="">According to the IR the divisions are in two separate blocks, and I guess that it must be the reason for the optimisation not taking place. This seems to be proven by using an even loop count like 0xFFFFFFF0 to avoid a middle check. In this case the optimisation works just fine. Here are the IR samples: <a href="https://ghostbin.com/paste/r4td2" class="">https://ghostbin.com/paste/r4td2</a>.</div><div class=""><br class=""></div><div class="">At this point the thoughts arising on my side are:</div><div class="">— Should this be considered a bug and reported to llvm-bugs or a desired behaviour?</div><div class="">— If this is considered a bug, how is one supposed to fix it? With the exact sample provided the compiler could generally predict the amount of iterations being over the threshold and optimise the output, however, the real world examples (including mine) will unlikely be that simple. Loop body would be much larger, the conditions would be more complicated, the divisions would likely occur in several different basic blocks for various reasons, and I think in general it is not possible to predict the iteration count.</div><div class=""><div class="">— From what I can tell at least current gcc (6.3.0) and icc (17.0.2) are capable of doing that, with both this snippet and even when the loop count depends on an another argument, which means they are not capable to determine whether there would only be 0 iterations or many more, however, the optimisation would still be applied (<a href="https://ghostbin.com/paste/ttnrz" class="">https://ghostbin.com/paste/ttnrz</a>). Perhaps llvm could also be more permissive when it sees a loop?</div></div><div class=""><br class=""></div><div class="">Best regards,</div><div class="">Vit</div><div class=""><br class=""></div></body></html>