Patchwork PR53887

login
register
mail settings
Submitter Steven Bosscher
Date July 9, 2012, 10:57 a.m.
Message ID <CABu31nM+ugvubLHPzEpvXDvH-m7ZAK+Pyzns-mk7uqdYZ8k4YA@mail.gmail.com>
Download mbox | patch
Permalink /patch/169779/
State New
Headers show

Comments

Steven Bosscher - July 9, 2012, 10:57 a.m.
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?

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.
Richard Guenther - July 9, 2012, 12:05 p.m.
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:
> +        ;
> +    }
> +}
> +

Patch

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:
+        ;
+    }
+}
+