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)?