Hi!

Cross-jumping at GIMPLE level gives up e.g. because there are any labels
at the beginning of the block (which is always the case for bbs referenced
from switches).  While labels for non-local goto as well as computed goto
are hard to handle, after all the edges are then EDGE_ABNORMAL that can't be
redirected anyway, other labels can be handled very easily.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

In the PR, beyond this I'm also talking about switchconv pass not being able
to know that some cases could be cross-jumped and thus use better conversion
sequences.  Wonder if we shouldn't schedule either a full, or a limited
version of tailmerging before switchconv, perhaps just use the
infrastructure from tree-ssa-tail-merge.c to handle the easiest cases
where the cross-jumping in the end would end up simplifying some of the
switches.  Thoughts on this?

2016-06-13  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/71520
        * tree-ssa-tail-merge.c (find_duplicate): Handle labels.
        (replace_block_by): Move user labels from bb1 to bb2.

        * gcc.dg/tree-ssa/pr71520.c: New test.

--- gcc/tree-ssa-tail-merge.c.jj        2016-06-10 20:23:55.196164390 +0200
+++ gcc/tree-ssa-tail-merge.c   2016-06-13 12:08:34.691985005 +0200
@@ -1265,6 +1265,10 @@ find_duplicate (same_succ *same_succ, ba
       gimple *stmt1 = gsi_stmt (gsi1);
       gimple *stmt2 = gsi_stmt (gsi2);
 
+      if (gimple_code (stmt1) == GIMPLE_LABEL
+         && gimple_code (stmt2) == GIMPLE_LABEL)
+       break;
+
       if (!gimple_equal_p (same_succ, stmt1, stmt2))
        return;
 
@@ -1277,6 +1281,20 @@ find_duplicate (same_succ *same_succ, ba
       gsi_advance_bw_nondebug_nonlocal (&gsi2, &vuse2, &vuse_escaped);
     }
 
+  while (!gsi_end_p (gsi1) && gimple_code (gsi_stmt (gsi1)) == GIMPLE_LABEL)
+    {
+      tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi1)));
+      if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
+       return;
+      gsi_prev (&gsi1);
+    }
+  while (!gsi_end_p (gsi2) && gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL)
+    {
+      tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)));
+      if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
+       return;
+      gsi_prev (&gsi2);
+    }
   if (!(gsi_end_p (gsi1) && gsi_end_p (gsi2)))
     return;
 
@@ -1555,6 +1573,23 @@ replace_block_by (basic_block bb1, basic
       e2->probability = GCOV_COMPUTE_SCALE (e2->count, out_sum);
     }
 
+  /* Move over any user labels from bb1 after the bb2 labels.  */
+  gimple_stmt_iterator gsi1 = gsi_start_bb (bb1);
+  if (!gsi_end_p (gsi1) && gimple_code (gsi_stmt (gsi1)) == GIMPLE_LABEL)
+    {
+      gimple_stmt_iterator gsi2 = gsi_after_labels (bb2);
+      while (!gsi_end_p (gsi1)
+            && gimple_code (gsi_stmt (gsi1)) == GIMPLE_LABEL)
+       {
+         tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi1)));
+         gcc_assert (!DECL_NONLOCAL (label) && !FORCED_LABEL (label));
+         if (DECL_ARTIFICIAL (label))
+           gsi_next (&gsi1);
+         else
+           gsi_move_before (&gsi1, &gsi2);
+       }
+    }
+
   /* Clear range info from all stmts in BB2 -- this transformation
      could make them out of date.  */
   reset_flow_sensitive_info_in_bb (bb2);
--- gcc/testsuite/gcc.dg/tree-ssa/pr71520.c.jj  2016-06-13 12:26:55.251630020 
+0200
+++ gcc/testsuite/gcc.dg/tree-ssa/pr71520.c     2016-06-13 12:26:31.000000000 
+0200
@@ -0,0 +1,90 @@
+/* PR tree-optimization/71520 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void bar (int);
+
+void
+foo (int x)
+{
+  switch (x)
+    {
+    case 1:
+    case 12:
+    case 28:
+    case 174:
+      bar (1);
+      bar (2);
+      break;
+    case 3:
+    case 7:
+    case 78:
+    case 96:
+    case 121:
+    default:
+      bar (3);
+      bar (4);
+      bar (5);
+      bar (6);
+      break;
+    case 8:
+    case 13:
+    case 27:
+    case 19:
+    case 118:
+      bar (3);
+      bar (4);
+      bar (5);
+      bar (6);
+      break;
+    case 4:
+      bar (7);
+      break;
+    }
+}
+
+void
+baz (int x)
+{
+  switch (x)
+    {
+    case 1:
+    case 12:
+    case 28:
+    case 174:
+      bar (8);
+      bar (9);
+      break;
+    case 3:
+    case 7:
+    case 78:
+    case 96:
+    case 121:
+    default:
+    lab1:
+    lab2:
+      bar (10);
+      bar (11);
+      bar (12);
+      bar (13);
+      break;
+    case 8:
+    case 13:
+    case 27:
+    case 19:
+    case 118:
+    lab3:
+    lab4:
+      bar (10);
+      bar (11);
+      bar (12);
+      bar (13);
+      break;
+    case 4:
+      bar (14);
+      break;
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "bar \\\(3\\\);" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bar \\\(10\\\);" 1 "optimized" } } */

        Jakub

Reply via email to