https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59521
--- Comment #9 from Martin Liška <marxin at gcc dot gnu.org> ---
(In reply to Yuri Gribov from comment #8)
> Created attachment 41737 [details]
> New draft patch
>
> How about this? I added edge attribute for builtin_expect and later used it
> in emit_case_decision_tree to emit expected comparison prior to decision
> tree for other case values.
>
> With this patch GCC optimizes original example. If it's not too ugly I'll do
> proper testing and send to gcc-patches.
The patch works for me for the described case, but does not for PGO, which
should do the same based on real numbers:
$ cat pr59521-profile.c
#include <stdio.h>
void
f(int ch) {
switch (ch) {
case 100: puts("100"); break;
case 10: puts("10"); break;
case 1: puts("1"); break;
}
}
int main()
{
for (int i = 0; i < 10000; i++)
{
int v;
if (i % 100 == 0)
v = 100;
else if(i % 10 == 0)
v = 10;
else
v = 1;
f(v);
}
}
$ gcc pr59521-profile.c -fprofile-generate && ./a.out && gcc pr59521-profile.c
-fprofile-use -S -fdump-tree-optimized=/dev/stdout
...
f (int ch)
{
<bb 2> [100.00%] [count: 10000]:
switch (ch_2(D)) <default: <L3> [0.00%] [count: 0], case 1: <L2> [90.00%]
[count: 9000], case 10: <L1> [9.00%] [count: 900], case 100: <L0> [1.00%]
[count: 100]>
...
But assembly looks as follows:
cmpl $10, %eax
je .L3
cmpl $100, %eax
je .L4
cmpl $1, %eax
je .L5
jmp .L6
Just a small note, Honza's planning to rewrite switch expansion to happen on
tree level. Maybe (hopefully) such transformations
will be easier on tree level?