Hello,
#define likely(x) __builtin_expect((x),1)
// switch like
char * b(int e) {
if (likely(e == 0))
return "0";
else if (e == 1)
return "1";
else return "f";
}
GCC correctly prefers the first case:
b(int):
mov eax, OFFSET FLAT:.LC0
test edi, edi
jne .L7
ret
But Clang seems to ignore _builtin_expect hints in this case.
b(int): # @b(int)
cmp edi, 1
mov eax, offset .L.str.1
mov ecx, offset .L.str.2
cmove rcx, rax
test edi, edi
mov eax, offset .L.str
cmovne rax, rcx
ret
[https://godbolt.org/g/tuAVT7](https://godbolt.org/g/tuAVT7)
davez
May 9, 2018, 6:29pm
2
I’d wager that the if-else chain is being converted to a "switch statement” during an optimization pass and the __builtin_expect() hint is lost. Can you file a bug? https://bugs.llvm.org
davez
May 9, 2018, 6:40pm
4
Hi Dávid,
Looks like you can defeat the switch conversion by adding a dummy asm(“”):
#define likely(x) __builtin_expect((x),1)
// switch like
char * b(int e) {
if (likely(e == 0))
return “0”;
asm(“”);
if (e == 1)
return “1”;
else return “f”;
}
Dave
Thanks, interesting.
But a fix needs to be made since branch predictor hints are broken in a valid C++20 code:
https://godbolt.org/g/dpSDqd
Dňa st 9. 5. 2018, 20:40 David Zarzycki <dave@znu.io > napísal(a):
They don't affect performance in the expected way, but they also don't
actually break code. I'm not saying it's not a bug, but it's certainly
not on the same level as a miscompilation.
Tim.
Yes, the compiler may ignore attributes in [ ] but I believe Clang/LLVM wants to support it.