__builtin_expect hint ignored

For the code below generated assembly is the worst possible - test 1, else test 3, else test 2 with expected value of 2 last ... Whats going on?

long case_2();
long case_3();
long case_1();
long case_else();
long test(long a) {
    switch (__builtin_expect(a, 2)) {
        case 2: return case_2();
        case 3: return case_3();
        case 1: return case_1();
        case 0:
        case 4:
        case 5: return case_else();
        default: __builtin_unreachable();

On x86-64, clang-trunk at least checks for the expected case first:

  Compiler Explorer.

What changed? Well bisection results show that this was fixed by r300440:

  [llvm] [mirror/master] [BPI] Use metadata info before any other heuristics

But the gcc 7 snapshot produces a lookup table. That might be better. CC'ing Marcello and Hans to comment, since IIRC they have both worked on switch lowering.


GCC produces a jump table. Clang doesn't do that for switches with
fewer than 4 cases (the example code effectively has cases 1, 2, 3 and
the "else case"). I don't know if that cut-off is optimal, but it's
not entirely obvious that a jump table would be better in this case.

Yes, the switch lowering code doesn't handle when the fall-through is
the most likely case.