PR rtl-optimization/18861
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Jan 2005 09:04:01 +0000 (09:04 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Jan 2005 09:04:01 +0000 (09:04 +0000)
* cfgbuild.c (BLOCK_USED_BY_TABLEJUMP): Define.
(FULL_STATE): Define.
(mark_tablejump_edge): New function.
(purge_dead_tablejump_edges): New function.
(find_bb_boundaries): Use it.

* gcc.dg/20050105-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@93041 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cfgbuild.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20050105-1.c [new file with mode: 0644]

index 47923a1..244d034 100644 (file)
@@ -1,5 +1,12 @@
 2005-01-07  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/18861
+       * cfgbuild.c (BLOCK_USED_BY_TABLEJUMP): Define.
+       (FULL_STATE): Define.
+       (mark_tablejump_edge): New function.
+       (purge_dead_tablejump_edges): New function.
+       (find_bb_boundaries): Use it.
+
        PR tree-optimization/18828
        * builtins.c (expand_builtin_next_arg): Remove argument and all
        the argument checking.
index 5761cd2..a21c726 100644 (file)
@@ -559,14 +559,73 @@ enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
 #define STATE(BB) (enum state) ((size_t) (BB)->aux)
 #define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
 
+/* Used internally by purge_dead_tablejump_edges, ORed into state.  */
+#define BLOCK_USED_BY_TABLEJUMP                32
+#define FULL_STATE(BB) ((size_t) (BB)->aux)
+
+static void
+mark_tablejump_edge (rtx label)
+{
+  basic_block bb;
+
+  gcc_assert (LABEL_P (label));
+  /* See comment in make_label_edge.  */
+  if (INSN_UID (label) == 0)
+    return;
+  bb = BLOCK_FOR_INSN (label);
+  SET_STATE (bb, FULL_STATE (bb) | BLOCK_USED_BY_TABLEJUMP);
+}
+
+static void
+purge_dead_tablejump_edges (basic_block bb, rtx table)
+{
+  rtx insn = BB_END (bb), tmp;
+  rtvec vec;
+  int j;
+  edge_iterator ei;
+  edge e;
+
+  if (GET_CODE (PATTERN (table)) == ADDR_VEC)
+    vec = XVEC (PATTERN (table), 0);
+  else
+    vec = XVEC (PATTERN (table), 1);
+
+  for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
+    mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
+
+  /* Some targets (eg, ARM) emit a conditional jump that also
+     contains the out-of-range target.  Scan for these and
+     add an edge if necessary.  */
+  if ((tmp = single_set (insn)) != NULL
+       && SET_DEST (tmp) == pc_rtx
+       && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
+       && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
+    mark_tablejump_edge (XEXP (XEXP (SET_SRC (tmp), 2), 0));
+
+  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+    {
+      if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
+        SET_STATE (e->dest, FULL_STATE (e->dest)
+                            & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
+      else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
+        {
+          remove_edge (e);
+          continue;
+        }
+      ei_next (&ei);
+    }
+}
+
 /* Scan basic block BB for possible BB boundaries inside the block
    and create new basic blocks in the progress.  */
 
 static void
 find_bb_boundaries (basic_block bb)
 {
+  basic_block orig_bb = bb;
   rtx insn = BB_HEAD (bb);
   rtx end = BB_END (bb);
+  rtx table;
   rtx flow_transfer_insn = NULL_RTX;
   edge fallthru = NULL;
 
@@ -623,6 +682,11 @@ find_bb_boundaries (basic_block bb)
      followed by cleanup at fallthru edge, so the outgoing edges may
      be dead.  */
   purge_dead_edges (bb);
+
+  /* purge_dead_edges doesn't handle tablejump's, but if we have split the
+     basic block, we might need to kill some edges.  */
+  if (bb != orig_bb && tablejump_p (BB_END (bb), NULL, &table))
+    purge_dead_tablejump_edges (bb, table);
 }
 
 /*  Assume that frequency of basic block B is known.  Compute frequencies
index e12f538..fdfd601 100644 (file)
@@ -1,5 +1,8 @@
 2005-01-07  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/18861
+       * gcc.dg/20050105-1.c: New test.
+
        PR tree-optimization/18828
        * gcc.dg/20050105-2.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/20050105-1.c b/gcc/testsuite/gcc.dg/20050105-1.c
new file mode 100644 (file)
index 0000000..46a742f
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR rtl-optimization/18861 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -floop-optimize2" } */
+
+extern void abort (void);
+
+int
+foo (int code)
+{
+  if (code >= 3)
+    switch (code)
+      {
+      case 3: return 4;
+      case 4: return 3;
+      case 5: return 6;
+      case 6: return 7;
+      case 7: return 8;
+      case 8: return 5;
+      default: abort ();
+      }
+  switch (code)
+    {
+    case 3: return 4;
+    case 4: return 3;
+    case 5: return 6;
+    case 6: return 7;
+    case 7: return 8;
+    case 8: return 5;
+    default: abort ();
+    }
+}