#include <stdio.h>
#include <stdbool.h>
int Test0(int v, int v1, int v2, int v3)
{
return v == v1 || v == v2 || v == v3;
}
int Test1(int v, int v1, int v2, int v3)
{
int r = (int)((bool)(v^v1)) & (int)((bool)(v^v2)) & (int)((bool)(v^v3));
return !r;
}
int Test2(int v, int v1, int v2, int v3)
{
int r = !!(v^v1) & !!(v^v2) & !!(v^v3);
return !r;
}
int main(void)
{
printf("%d\n", Test0(5, 1, 2, 4));
printf("%d\n", Test0(5, 1, 2, 5));
printf("%d\n", Test1(5, 1, 2, 4));
printf("%d\n", Test1(5, 1, 2, 5));
printf("%d\n", Test2(5, 1, 2, 4));
printf("%d\n", Test2(5, 1, 2, 5));
return 0;
}
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Using gcc -s, I see that Test1 and Test2 do indeed compile without branches (using setne) whilst Test0 has branches. However with flag -O3, all three functions compile to identical highly-compact code without branches.
I think the moral is: don't waste your time trying to outsmart the compiler.
It's true that Go's compiler doesn't currently optimise this case, but new optimisations are being added over time.