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?

Reply via email to