llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.85k stars 11.02k forks source link

Lost branch predictor hints #36716

Open davidbolvansky opened 6 years ago

davidbolvansky commented 6 years ago
Bugzilla Link 37368
Version trunk
OS Linux
CC @hfinkel,@rotateright,@TNorthover

Extended Description

Hello,

When we have small "switch"-es with two or three cases, clang could generate a smarter code.

Example: char * a(int e) { switch (e) { case 0: return "0"; default: return "default"; } }

Clang's output: a: # @​a push rbp mov rbp, rsp mov dword ptr [rbp - 12], edi mov edi, dword ptr [rbp - 12] test edi, edi jne .LBB0_2 jmp .LBB0_1 .LBB0_1: movabs rax, offset .L.str mov qword ptr [rbp - 8], rax jmp .LBB0_3 .LBB0_2: movabs rax, offset .L.str.1 mov qword ptr [rbp - 8], rax .LBB0_3: mov rax, qword ptr [rbp - 8] pop rbp ret

Better code (GCC does it): a: test edi, edi mov edx, OFFSET FLAT:.LC1 mov eax, OFFSET FLAT:.LC0 cmovne rax, rdx ret

Also for this example: char * a(int e) { switch (e) { case 0: return "0"; case 1: return "1"; default: return "default"; } }

A better code can be generated like: a: mov eax, OFFSET FLAT:.LC1 test edi, edi je .L1 cmp edi, 1 mov eax, OFFSET FLAT:.LC2 mov edx, OFFSET FLAT:.LC0 cmovne rax, rdx .L1: ret

Thanks

davidbolvansky commented 6 years ago

[[likely]] in C++20 supports cases but Clang ignores it yet?

https://godbolt.org/g/dpSDqd

davidbolvansky commented 6 years ago

Clang ignores likely 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"; }

Clang: b: # @​b 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

GCC: b: mov eax, OFFSET FLAT:.LC0 test edi, edi jne .L7 ret .L7: cmp edi, 1 mov edx, OFFSET FLAT:.LC2 mov eax, OFFSET FLAT:.LC1 cmovne rax, rdx ret

davidbolvansky commented 6 years ago

Seems like GCC prefers first case, Clang prefers nothing.

Any annotation or attribute to mark the case as "hot/likely"?

davidbolvansky commented 6 years ago

Sorry, somehow I didnt applied Clang with O3, godbolt somehow removes it.

But even with it in case: char * a(int e) { switch (e) { case 0: return "0"; case 1: return "1"; default: return "default"; } }

Clang: a: # @​a 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

GCC: a: mov eax, OFFSET FLAT:.LC1 test edi, edi je .L1 cmp edi, 1 mov eax, OFFSET FLAT:.LC2 mov edx, OFFSET FLAT:.LC0 cmovne rax, rdx .L1: ret