Looking at the actual code generated by GCC 14.2 (https://godbolt.org/z/8oTfPKE4q), I get the following diff from adding [[likely]]
:
0@@ -1,6 +1,13 @@
1 mov rax, rdi
2 shr rax, 33
3- je .L8
4+ jne .L2
5+ movsx rax, edx
6+ mov esi, esi
7+ xor edx, edx
8+ imul rax, rdi
9+ div rsi
10+ ret
11+.L2:
12 movsx r10, edx
13 sub rsp, 24
14 mov rax, r10
15@@ -24,10 +31,3 @@
16 adc rax, -1
17 add rsp, 24
18 ret
19-.L8:
20- movsx rax, edx
21- mov esi, esi
22- xor edx, edx
23- imul rax, rdi
24- div rsi
25- ret
which is exactly what I’d expect. The default branch prediction (before observations are available) is to assume that a conditional jump backwards will happen, while a conditional jump forward will not happen, so we want the likely branch to be emitted first; adding the [[likely]]
does indeed result in that.
It may be hard to observe this effect in a micro-benchmark as we expect that after a few iterations the CPU branch predictor will guess 100% correctly anyway.
I think that’s sufficient reason to keep the [[likely]]
here because (1) it is semantically correct (it is the only branch relevant in production code) (2) it documents this fact to human readers (3) it does not measurably worsen the code and (4) it appears to make at least some compilers produce marginally better code, but if people feel it should only be used when backed by observably better benchmarks, I’m okay with dropping it.