Ignored branch predictor hints


#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:

  mov eax, OFFSET FLAT:.LC0
  test edi, edi
  jne .L7

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


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

I did

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”;
if (e == 1)
return “1”;
else return “f”;


Thanks, interesting.

But a fix needs to be made since branch predictor hints are broken in a valid C++20 code:

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.


Yes, the compiler may ignore attributes in [[ ]] but I believe Clang/LLVM wants to support it.