https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Looking at godbolt and LLVM release notes, this optimization appeared in LLVM 9
and looks to be a switch optimization:

LLVM can now sink similar instructions to a common successor block also when
the instructions have no uses, such as calls to void functions. This allows
code such as

void g(int);
enum e { A, B, C, D };
void f(e x, int y, int z) {
  switch(x) {
    case A: g(6); break;
    case B: g(3); break;
    case C: g(9); break;
    case D: g(2); break;
  }
}

to be optimized to a single call to g, with the argument loaded from a lookup
table.
I bet it is https://reviews.llvm.org/D59936

We don't optimize even:
void
foo (int *p, int x)
{
  switch (x)
    {
    case 7: *p = 14; break;
    case 8: *p = 15; break;
    case 9: *p = 16; break;
    case 10: *p = 17; break;
    case 11: *p = 18; break;
    case 12: *p = 19; break;
    default: return;
    }
}
but do optimize if one performs the switch parametrized tail merging manually:
void
bar (int *p, int x)
{
  int y;
  switch (x)
    {
    case 7: y = 14; break;
    case 8: y = 15; break;
    case 9: y = 16; break;
    case 10: y = 17; break;
    case 11: y = 18; break;
    case 12: y = 19; break;
    default: return;
    }
  *p = y;
}

So, do you prefer to do this in tree-ssa-tail-merge.c (for blocks starting with
switches) or in tree-switch-conversion.c, and should we handle both the case
where the constant(s) are linear vs. the switch expression, or also any other
(let the switchconv pass then create the arrays)?

Reply via email to