Message ID | CABu31nM+ugvubLHPzEpvXDvH-m7ZAK+Pyzns-mk7uqdYZ8k4YA@mail.gmail.com |
---|---|
State | New |
Headers | show |
On Mon, Jul 9, 2012 at 12:57 PM, Steven Bosscher <stevenb.gcc@gmail.com> wrote: > Hello, > > How annoying that it was decided at some point to not always group > switch case labels in tree-cfgcleanup! This PR53887 and PR53881 before > it are both cases where the switch lowering to bit tests ICEs because > the case labels haven't been grouped. For PR53887 there is a case > label that shares an edge with the default label, and for PR53881 > there were two cases going to the same basic block (i.e. same edge) > but with different CASE_LABELs. > > The most robust fix is to group the case labels before trying the > switch lowering. This also helps for switch conversion to a load from > a static initializer because before this patch the heuristics were > being fooled to perform unprofitable conversions. > > Bootstrapped on powerpc64-unknown-linux-gnu, testing in progress. OK > if it passes? Ok. Thanks, Richard. > Ciao! > Steven > > gcc/ > PR tree-optimization/53887 > * tree-cfg.c (group_case_labels_stmt): Make non-static. > * tree-flow.h (group_case_labels_stmt): Add prototype. > * tree-switch-conversion.c (process_switch): Use group_case_labels_stmt > to pre-process every switch. > > testsuite/ > PR tree-optimization/53887 > * gcc.dg/pr53887.c: New test. > > Index: tree-cfg.c > =================================================================== > --- tree-cfg.c (revision 189366) > +++ tree-cfg.c (working copy) > @@ -125,7 +125,6 @@ static edge find_taken_edge_computed_goto (basic_b > static edge find_taken_edge_cond_expr (basic_block, tree); > static edge find_taken_edge_switch_expr (basic_block, tree); > static tree find_case_label_for_value (gimple, tree); > -static void group_case_labels_stmt (gimple); > > void > init_empty_tree_cfg_for_function (struct function *fn) > @@ -1331,7 +1330,7 @@ cleanup_dead_labels (void) > the ones jumping to the same label. > Eg. three separate entries 1: 2: 3: become one entry 1..3: */ > > -static void > +void > group_case_labels_stmt (gimple stmt) > { > int old_size = gimple_switch_num_labels (stmt); > Index: tree-flow.h > =================================================================== > --- tree-flow.h (revision 189366) > +++ tree-flow.h (working copy) > @@ -428,6 +428,7 @@ extern void debug_loop_num (unsigned, int); > extern void print_loops (FILE *, int); > extern void print_loops_bb (FILE *, basic_block, int, int); > extern void cleanup_dead_labels (void); > +extern void group_case_labels_stmt (gimple); > extern void group_case_labels (void); > extern gimple first_stmt (basic_block); > extern gimple last_stmt (basic_block); > Index: tree-switch-conversion.c > =================================================================== > --- tree-switch-conversion.c (revision 189366) > +++ tree-switch-conversion.c (working copy) > @@ -1339,9 +1339,15 @@ process_switch (gimple swtch) > { > struct switch_conv_info info; > > - /* Degenerate case with only a default label should never happen. */ > - gcc_checking_assert (gimple_switch_num_labels (swtch) > 1); > + /* Group case labels so that we get the right results from the heuristics > + that decide on the code generation approach for this switch. */ > + group_case_labels_stmt (swtch); > > + /* If this switch is now a degenerate case with only a default label, > + there is nothing left for us to do. */ > + if (gimple_switch_num_labels (swtch) < 2) > + return "switch is a degenerate case"; > + > collect_switch_conv_info (swtch, &info); > > /* No error markers should reach here (they should be filtered out > Index: testsuite/gcc.dg/pr53887.c > =================================================================== > --- testsuite/gcc.dg/pr53887.c (revision 0) > +++ testsuite/gcc.dg/pr53887.c (revision 0) > @@ -0,0 +1,24 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2" } */ > + > +enum > +{ Failed, NoError, NoDiskette } > +a; > +int b, c; > +void > +fn1 () > +{ > + if (c) > + a << 1; > + switch (b) > + { > + default: > + a << 1; > + case 0: > + b = 0; > + case 1: > + case NoDiskette: > + ; > + } > +} > +
Index: tree-cfg.c =================================================================== --- tree-cfg.c (revision 189366) +++ tree-cfg.c (working copy) @@ -125,7 +125,6 @@ static edge find_taken_edge_computed_goto (basic_b static edge find_taken_edge_cond_expr (basic_block, tree); static edge find_taken_edge_switch_expr (basic_block, tree); static tree find_case_label_for_value (gimple, tree); -static void group_case_labels_stmt (gimple); void init_empty_tree_cfg_for_function (struct function *fn) @@ -1331,7 +1330,7 @@ cleanup_dead_labels (void) the ones jumping to the same label. Eg. three separate entries 1: 2: 3: become one entry 1..3: */ -static void +void group_case_labels_stmt (gimple stmt) { int old_size = gimple_switch_num_labels (stmt); Index: tree-flow.h =================================================================== --- tree-flow.h (revision 189366) +++ tree-flow.h (working copy) @@ -428,6 +428,7 @@ extern void debug_loop_num (unsigned, int); extern void print_loops (FILE *, int); extern void print_loops_bb (FILE *, basic_block, int, int); extern void cleanup_dead_labels (void); +extern void group_case_labels_stmt (gimple); extern void group_case_labels (void); extern gimple first_stmt (basic_block); extern gimple last_stmt (basic_block); Index: tree-switch-conversion.c =================================================================== --- tree-switch-conversion.c (revision 189366) +++ tree-switch-conversion.c (working copy) @@ -1339,9 +1339,15 @@ process_switch (gimple swtch) { struct switch_conv_info info; - /* Degenerate case with only a default label should never happen. */ - gcc_checking_assert (gimple_switch_num_labels (swtch) > 1); + /* Group case labels so that we get the right results from the heuristics + that decide on the code generation approach for this switch. */ + group_case_labels_stmt (swtch); + /* If this switch is now a degenerate case with only a default label, + there is nothing left for us to do. */ + if (gimple_switch_num_labels (swtch) < 2) + return "switch is a degenerate case"; + collect_switch_conv_info (swtch, &info); /* No error markers should reach here (they should be filtered out Index: testsuite/gcc.dg/pr53887.c =================================================================== --- testsuite/gcc.dg/pr53887.c (revision 0) +++ testsuite/gcc.dg/pr53887.c (revision 0) @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +enum +{ Failed, NoError, NoDiskette } +a; +int b, c; +void +fn1 () +{ + if (c) + a << 1; + switch (b) + { + default: + a << 1; + case 0: + b = 0; + case 1: + case NoDiskette: + ; + } +} +