OSDN Git Service

* gcc.dg/tree-ssa/ssa-dse-10.c: Clean up all dse dump files.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-threadupdate.c
index 6732f2e..d4d9ee5 100644 (file)
@@ -1,11 +1,11 @@
 /* Thread edges through blocks and update the control flow and SSA graphs.
-   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -223,15 +222,15 @@ create_block_for_threading (basic_block bb, struct redirection_data *rd)
 static hashval_t
 redirection_data_hash (const void *p)
 {
-  edge e = ((struct redirection_data *)p)->outgoing_edge;
+  edge e = ((const struct redirection_data *)p)->outgoing_edge;
   return e->dest->index;
 }
 
 static int
 redirection_data_eq (const void *p1, const void *p2)
 {
-  edge e1 = ((struct redirection_data *)p1)->outgoing_edge;
-  edge e2 = ((struct redirection_data *)p2)->outgoing_edge;
+  edge e1 = ((const struct redirection_data *)p1)->outgoing_edge;
+  edge e2 = ((const struct redirection_data *)p2)->outgoing_edge;
 
   return e1 == e2;
 }
@@ -313,6 +312,7 @@ create_edge_and_update_destination_phis (struct redirection_data *rd)
   edge e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
   tree phi;
 
+  rescan_loop_exit (e, true, false);
   e->probability = REG_BR_PROB_BASE;
   e->count = rd->dup_block->count;
   e->aux = rd->outgoing_edge->aux;
@@ -461,26 +461,26 @@ redirect_edges (void **slot, void *data)
    is one, this is equivalent to a "forwarder" block.  */
 
 static bool
-redirection_block_p (basic_block bb)
+redirection_block_p (const_basic_block bb)
 {
-  block_stmt_iterator bsi;
+  const_block_stmt_iterator bsi;
 
   /* Advance to the first executable statement.  */
-  bsi = bsi_start (bb);
-  while (!bsi_end_p (bsi)
-          && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
-              || IS_EMPTY_STMT (bsi_stmt (bsi))))
-    bsi_next (&bsi);
+  bsi = cbsi_start (bb);
+  while (!cbsi_end_p (bsi)
+          && (TREE_CODE (cbsi_stmt (bsi)) == LABEL_EXPR
+              || IS_EMPTY_STMT (cbsi_stmt (bsi))))
+    cbsi_next (&bsi);
 
   /* Check if this is an empty block.  */
-  if (bsi_end_p (bsi))
+  if (cbsi_end_p (bsi))
     return true;
 
   /* Test that we've reached the terminating control statement.  */
-  return bsi_stmt (bsi)
-        && (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
-            || TREE_CODE (bsi_stmt (bsi)) == GOTO_EXPR
-            || TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR);
+  return cbsi_stmt (bsi)
+        && (TREE_CODE (cbsi_stmt (bsi)) == COND_EXPR
+            || TREE_CODE (cbsi_stmt (bsi)) == GOTO_EXPR
+            || TREE_CODE (cbsi_stmt (bsi)) == SWITCH_EXPR);
 }
 
 /* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
@@ -530,10 +530,10 @@ thread_block (basic_block bb, bool noloop_only)
   /* If we thread the latch of the loop to its exit, the loop ceases to
      exist.  Make sure we do not restrict ourselves in order to preserve
      this loop.  */
-  if (current_loops && loop->header == bb)
+  if (loop->header == bb)
     {
       e = loop_latch_edge (loop);
-      e2 = e->aux;
+      e2 = (edge) e->aux;
 
       if (e2 && loop_exit_edge_p (loop, e2))
        {
@@ -546,13 +546,12 @@ thread_block (basic_block bb, bool noloop_only)
      efficient lookups.  */
   FOR_EACH_EDGE (e, ei, bb->preds)
     {
-      e2 = e->aux;
+      e2 = (edge) e->aux;
 
       if (!e2
          /* If NOLOOP_ONLY is true, we only allow threading through the
             header of a loop to exit edges.  */
          || (noloop_only
-             && current_loops
              && bb == bb->loop_father->header
              && !loop_exit_edge_p (bb->loop_father, e2)))
        {
@@ -561,7 +560,7 @@ thread_block (basic_block bb, bool noloop_only)
        }
 
       update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
-                                      e->count, e->aux);
+                                      e->count, (edge) e->aux);
 
       /* Insert the outgoing edge into the hash table if it is not
         already in the hash table.  */
@@ -574,10 +573,13 @@ thread_block (basic_block bb, bool noloop_only)
      DO_NOT_DUPLICATE attribute.  */
   if (all)
     {
-      edge e = EDGE_PRED (bb, 0)->aux;
+      edge e = (edge) EDGE_PRED (bb, 0)->aux;
       lookup_redirection_data (e, NULL, NO_INSERT)->do_not_duplicate = true;
     }
 
+  /* We do not update dominance info.  */
+  free_dominance_info (CDI_DOMINATORS);
+
   /* Now create duplicates of BB.
 
      Note that for a block with a high outgoing degree we can waste
@@ -621,7 +623,7 @@ static basic_block
 thread_single_edge (edge e)
 {
   basic_block bb = e->dest;
-  edge eto = e->aux;
+  edge eto = (edge) e->aux;
   struct redirection_data rd;
   struct local_info local_info;
 
@@ -634,6 +636,11 @@ thread_single_edge (edge e)
       /* If BB has just a single predecessor, we should only remove the
         control statements at its end, and successors except for ETO.  */
       remove_ctrl_stmt_and_useless_edges (bb, eto->dest);
+
+      /* And fixup the flags on the single remaining edge.  */
+      eto->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
+      eto->flags |= EDGE_FALLTHRU;
+
       return bb;
     }
 
@@ -664,9 +671,9 @@ thread_single_edge (edge e)
 
 static basic_block dbds_ce_stop;
 static bool
-dbds_continue_enumeration_p (basic_block bb, void *stop)
+dbds_continue_enumeration_p (const_basic_block bb, const void *stop)
 {
-  return (bb != (basic_block) stop
+  return (bb != (const_basic_block) stop
          && bb != dbds_ce_stop);
 }
 
@@ -820,7 +827,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
 
   if (latch->aux)
     {
-      tgt_edge = latch->aux;
+      tgt_edge = (edge) latch->aux;
       tgt_bb = tgt_edge->dest;
     }
   else if (!may_peel_loop_headers
@@ -843,7 +850,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
              goto fail;
            }
 
-         tgt_edge = e->aux;
+         tgt_edge = (edge) e->aux;
          atgt_bb = tgt_edge->dest;
          if (!tgt_bb)
            tgt_bb = atgt_bb;
@@ -1023,6 +1030,9 @@ thread_through_all_blocks (bool may_peel_loop_headers)
   struct loop *loop;
   loop_iterator li;
 
+  /* We must know about loops in order to preserve them.  */
+  gcc_assert (current_loops != NULL);
+
   if (threaded_edges == NULL)
     return false;
 
@@ -1046,21 +1056,15 @@ thread_through_all_blocks (bool may_peel_loop_headers)
   /* Then perform the threading through loop headers.  We start with the
      innermost loop, so that the changes in cfg we perform won't affect
      further threading.  */
-  if (current_loops)
+  FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
     {
-      FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
-       {
-         if (!loop->header
-             || !bitmap_bit_p (threaded_blocks, loop->header->index))
-           continue;
+      if (!loop->header
+         || !bitmap_bit_p (threaded_blocks, loop->header->index))
+       continue;
 
-         retval |= thread_through_loop_header (loop, may_peel_loop_headers);
-       }
+      retval |= thread_through_loop_header (loop, may_peel_loop_headers);
     }
 
-  if (retval)
-    free_dominance_info (CDI_DOMINATORS);
-
   if (dump_file && (dump_flags & TDF_STATS))
     fprintf (dump_file, "\nJumps threaded: %lu\n",
             thread_stats.num_threaded_edges);
@@ -1072,6 +1076,9 @@ thread_through_all_blocks (bool may_peel_loop_headers)
   VEC_free (edge, heap, threaded_edges);
   threaded_edges = NULL;
 
+  if (retval)
+    loops_state_set (LOOPS_NEED_FIXUP);
+
   return retval;
 }