On Fri, Jan 09, 2015 at 11:59:44AM +0100, Richard Biener wrote: > > If you want, I can try instead of disabling it for tablejumps > > just move the label. > > Yeah, I'd prefer that - it can't be too difficult, no?
So like this (tested just on the testcase, fully bootstrap/regtest will follow)? > > Still, I think we should be able to optimize it somewhere else too > > (we can remove the tablejumps not just if all jump_table_data entries > > point to next_bb, but even when they point to some completely different bb, > > as long as it is a single_succ_p). And ideally also optimize it at GIMPLE, > > but guess that is GCC 6 material. > > cfgcleanup material, similar for GIMPLE I guess. You mean that cfgcleanup changes are GCC 6 material too? 2015-01-09 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/64536 * cfgrtl.c (rtl_tidy_fallthru_edge): Handle removal of degenerate tablejumps. * gcc.dg/pr64536.c: New test. --- gcc/cfgrtl.c.jj 2015-01-08 18:10:23.616598916 +0100 +++ gcc/cfgrtl.c 2015-01-09 14:47:26.637855477 +0100 @@ -1791,6 +1791,24 @@ rtl_tidy_fallthru_edge (edge e) && (any_uncondjump_p (q) || single_succ_p (b))) { + rtx label; + rtx_jump_table_data *table; + + if (tablejump_p (q, &label, &table)) + { + /* The label is likely mentioned in some instruction before + the tablejump and might not be DCEd, so turn it into + a note instead and move before the tablejump that is going to + be deleted. */ + const char *name = LABEL_NAME (label); + PUT_CODE (label, NOTE); + NOTE_KIND (label) = NOTE_INSN_DELETED_LABEL; + NOTE_DELETED_LABEL_NAME (label) = name; + rtx_insn *lab = safe_as_a <rtx_insn *> (label); + reorder_insns (lab, lab, PREV_INSN (q)); + delete_insn (table); + } + #ifdef HAVE_cc0 /* If this was a conditional jump, we need to also delete the insn that set cc0. */ --- gcc/testsuite/gcc.dg/pr64536.c.jj 2015-01-09 13:55:53.035267213 +0100 +++ gcc/testsuite/gcc.dg/pr64536.c 2015-01-09 13:55:53.035267213 +0100 @@ -0,0 +1,67 @@ +/* PR rtl-optimization/64536 */ +/* { dg-do link } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-fPIC" { target fpic } } */ + +struct S { long q; } *h; +long a, b, g, j, k, *c, *d, *e, *f, *i; +long *baz (void) +{ + asm volatile ("" : : : "memory"); + return e; +} + +void +bar (int x) +{ + int y; + for (y = 0; y < x; y++) + { + switch (b) + { + case 0: + case 2: + a++; + break; + case 3: + a++; + break; + case 1: + a++; + } + if (d) + { + f = baz (); + g = k++; + if (&h->q) + { + j = *f; + h->q = *f; + } + else + i = (long *) (h->q = *f); + *c++ = (long) f; + e += 6; + } + else + { + f = baz (); + g = k++; + if (&h->q) + { + j = *f; + h->q = *f; + } + else + i = (long *) (h->q = *f); + *c++ = (long) f; + e += 6; + } + } +} + +int +main () +{ + return 0; +} Jakub