4 ms·
If indeed if (array[i] < boundary) count++; is slower than count += (array[i] < boundary) ? 1 : 0; Any reason why compilers can't infer the latter?
by alain94040 12y ago
If indeed
if (array[i] < boundary) count++;
is slower than
count += (array[i] < boundary) ? 1 : 0;
Any reason why compilers can't infer the latter?
- zokier 12y agoNo particular reason. Clang generates identical code for both on my system (Arch Linux/x86_64). Compile flags: "-std=c11 -c -O3 -S -march=native -mtune=native", windows-specific stuff removed. GCC creates different code for the variations, but the generated code is too complex for me to say which one is faster. edit: with -Os GCC generates identical code too.
- whoopdedo 12y agoI've discovered the x86_64 opcode CMOVL -- a conditional move -- because of this. if (array[i] < boundary) count+=2; I had to work hard to make GCC not produce optimal code. Even this if (array[i] < boundary) return count+1; else return count; came out the same as all the others. Avoiding branch prediction is hardly news. Was the article's author even compiling with optimizations enabled?
- WWLink 12y agoIt does seem weird that the compiler didn't catch that one.
- mtdewcmu 12y ago>>Was the article's author even compiling with optimizations enabled? Quite possibly not. Which, I guess, is reasonable, since the point was really about cpu instructions and not C compilers. What comes out is more predictable with optimizations off. Note that the author mentions the optimizer in relation to the second version. I think it might be because that code generates a branch with optimizations off in Visual C++. gcc seems to treat ?: as inherently a cmov and VC++ seems to treat it no differently than an if.
- yongjik 12y agoLinus once wrote a nice (typically Linus) rant on why cmov is a terrible idea in most cases: http://yarchive.net/comp/linux/cmov.html http://yarchive.net/comp/linux/cmov.html > In contrast, if you use a predicated instruction, ALL of it is on the critical path. Calculating the conditional is on the critical path. Calculating the value that gets used is obviously ALSO on the critical path, but so is the calculation for the value that DOESN'T get used too. So the cmov - rather than speeding things up - actually slows things down, because it makes more code be dependent on each other.
- mtdewcmu 12y agoHuh. I guess the reason it works in the article is that the value is not calculated, it's just a constant.