OSDN Git Service

PR tree-optimization/40550
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-ch.c
index c465e2e..9f1f4c3 100644 (file)
@@ -1,11 +1,11 @@
 /* Loop header copying on trees.
 /* Loop header copying on trees.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008 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
    
 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) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
    
 GCC is distributed in the hope that it will be useful, but WITHOUT
 later version.
    
 GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -14,9 +14,8 @@ 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
 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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -51,14 +50,21 @@ static bool
 should_duplicate_loop_header_p (basic_block header, struct loop *loop,
                                int *limit)
 {
 should_duplicate_loop_header_p (basic_block header, struct loop *loop,
                                int *limit)
 {
-  block_stmt_iterator bsi;
-  tree last;
+  gimple_stmt_iterator bsi;
+  gimple last;
 
   /* Do not copy one block more than once (we do not really want to do
      loop peeling here).  */
   if (header->aux)
     return false;
 
 
   /* Do not copy one block more than once (we do not really want to do
      loop peeling here).  */
   if (header->aux)
     return false;
 
+  /* Loop header copying usually increases size of the code.  This used not to
+     be true, since quite often it is possible to verify that the condition is
+     satisfied in the first iteration and therefore to eliminate it.  Jump
+     threading handles these cases now.  */
+  if (optimize_loop_for_size_p (loop))
+    return false;
+
   gcc_assert (EDGE_COUNT (header->succs) > 0);
   if (single_succ_p (header))
     return false;
   gcc_assert (EDGE_COUNT (header->succs) > 0);
   if (single_succ_p (header))
     return false;
@@ -72,22 +78,22 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
     return false;
 
   last = last_stmt (header);
     return false;
 
   last = last_stmt (header);
-  if (TREE_CODE (last) != COND_EXPR)
+  if (gimple_code (last) != GIMPLE_COND)
     return false;
 
   /* Approximately copy the conditions that used to be used in jump.c --
      at most 20 insns and no calls.  */
     return false;
 
   /* Approximately copy the conditions that used to be used in jump.c --
      at most 20 insns and no calls.  */
-  for (bsi = bsi_start (header); !bsi_end_p (bsi); bsi_next (&bsi))
+  for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi))
     {
     {
-      last = bsi_stmt (bsi);
+      last = gsi_stmt (bsi);
 
 
-      if (TREE_CODE (last) == LABEL_EXPR)
+      if (gimple_code (last) == GIMPLE_LABEL)
        continue;
 
        continue;
 
-      if (get_call_expr_in (last))
+      if (is_gimple_call (last))
        return false;
 
        return false;
 
-      *limit -= estimate_num_insns (last);
+      *limit -= estimate_num_insns (last, &eni_size_weights);
       if (*limit < 0)
        return false;
     }
       if (*limit < 0)
        return false;
     }
@@ -100,17 +106,17 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
 static bool
 do_while_loop_p (struct loop *loop)
 {
 static bool
 do_while_loop_p (struct loop *loop)
 {
-  tree stmt = last_stmt (loop->latch);
+  gimple stmt = last_stmt (loop->latch);
 
   /* If the latch of the loop is not empty, it is not a do-while loop.  */
   if (stmt
 
   /* If the latch of the loop is not empty, it is not a do-while loop.  */
   if (stmt
-      && TREE_CODE (stmt) != LABEL_EXPR)
+      && gimple_code (stmt) != GIMPLE_LABEL)
     return false;
 
   /* If the header contains just a condition, it is not a do-while loop.  */
   stmt = last_and_only_stmt (loop->header);
   if (stmt
     return false;
 
   /* If the header contains just a condition, it is not a do-while loop.  */
   stmt = last_and_only_stmt (loop->header);
   if (stmt
-      && TREE_CODE (stmt) == COND_EXPR)
+      && gimple_code (stmt) == GIMPLE_COND)
     return false;
 
   return true;
     return false;
 
   return true;
@@ -120,44 +126,38 @@ do_while_loop_p (struct loop *loop)
    of the loop.  This is beneficial since it increases efficiency of
    code motion optimizations.  It also saves one jump on entry to the loop.  */
 
    of the loop.  This is beneficial since it increases efficiency of
    code motion optimizations.  It also saves one jump on entry to the loop.  */
 
-static void
+static unsigned int
 copy_loop_headers (void)
 {
 copy_loop_headers (void)
 {
-  struct loops *loops;
-  unsigned i;
+  loop_iterator li;
   struct loop *loop;
   basic_block header;
   edge exit, entry;
   basic_block *bbs, *copied_bbs;
   unsigned n_bbs;
   unsigned bbs_size;
   struct loop *loop;
   basic_block header;
   edge exit, entry;
   basic_block *bbs, *copied_bbs;
   unsigned n_bbs;
   unsigned bbs_size;
-  gcov_type entry_count, body_count, total_count;
 
 
-  loops = loop_optimizer_init (dump_file);
-  if (!loops)
-    return;
-  rewrite_into_loop_closed_ssa (NULL);
-  
-  /* We do not try to keep the information about irreducible regions
-     up-to-date.  */
-  loops->state &= ~LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
+  loop_optimizer_init (LOOPS_HAVE_PREHEADERS
+                      | LOOPS_HAVE_SIMPLE_LATCHES);
+  if (number_of_loops () <= 1)
+    {
+      loop_optimizer_finalize ();
+      return 0;
+    }
 
 #ifdef ENABLE_CHECKING
 
 #ifdef ENABLE_CHECKING
-  verify_loop_structure (loops);
+  verify_loop_structure ();
 #endif
 
 #endif
 
-  bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
-  copied_bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
+  bbs = XNEWVEC (basic_block, n_basic_blocks);
+  copied_bbs = XNEWVEC (basic_block, n_basic_blocks);
   bbs_size = n_basic_blocks;
 
   bbs_size = n_basic_blocks;
 
-  for (i = 1; i < loops->num; i++)
+  FOR_EACH_LOOP (li, loop, 0)
     {
       /* Copy at most 20 insns.  */
       int limit = 20;
 
     {
       /* Copy at most 20 insns.  */
       int limit = 20;
 
-      loop = loops->parray[i];
-      if (!loop)
-       continue;
       header = loop->header;
 
       /* If the loop is already a do-while style one (either because it was
       header = loop->header;
 
       /* If the loop is already a do-while style one (either because it was
@@ -199,45 +199,59 @@ copy_loop_headers (void)
       /* Ensure that the header will have just the latch as a predecessor
         inside the loop.  */
       if (!single_pred_p (exit->dest))
       /* Ensure that the header will have just the latch as a predecessor
         inside the loop.  */
       if (!single_pred_p (exit->dest))
-       exit = single_succ_edge (loop_split_edge_with (exit, NULL));
+       exit = single_pred_edge (split_edge (exit));
 
       entry = loop_preheader_edge (loop);
 
       entry = loop_preheader_edge (loop);
-      entry_count = entry->src->count;
-      body_count = exit->dest->count;
 
 
-      if (!tree_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs))
+      if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs))
        {
          fprintf (dump_file, "Duplication failed.\n");
          continue;
        }
 
        {
          fprintf (dump_file, "Duplication failed.\n");
          continue;
        }
 
-      /* Fix profiling info.  Scaling is done in gcov_type arithmetic to
-        avoid losing information; this is slow, but is done at most
-        once per loop.  We special case 0 to avoid division by 0;
-         probably other special cases exist.  */
-      total_count = body_count + entry_count;
-      if (total_count == 0LL)
-       {
-         scale_bbs_frequencies_int (bbs, n_bbs, 0, 1);
-         scale_bbs_frequencies_int (copied_bbs, n_bbs, 0, 1);
-       }
-      else
+      /* If the loop has the form "for (i = j; i < j + 10; i++)" then
+        this copying can introduce a case where we rely on undefined
+        signed overflow to eliminate the preheader condition, because
+        we assume that "j < j + 10" is true.  We don't want to warn
+        about that case for -Wstrict-overflow, because in general we
+        don't warn about overflow involving loops.  Prevent the
+        warning by setting the no_warning flag in the condition.  */
+      if (warn_strict_overflow > 0)
        {
        {
-         scale_bbs_frequencies_gcov_type (bbs, n_bbs, body_count, total_count);
-         scale_bbs_frequencies_gcov_type (copied_bbs, n_bbs, entry_count, 
-                                          total_count);
+         unsigned int i;
+
+         for (i = 0; i < n_bbs; ++i)
+           {
+             gimple_stmt_iterator bsi;
+
+             for (bsi = gsi_start_bb (copied_bbs[i]);
+                  !gsi_end_p (bsi);
+                  gsi_next (&bsi))
+               {
+                 gimple stmt = gsi_stmt (bsi);
+                 if (gimple_code (stmt) == GIMPLE_COND)
+                   gimple_set_no_warning (stmt, true);
+                 else if (is_gimple_assign (stmt))
+                   {
+                     enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+                     if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
+                       gimple_set_no_warning (stmt, true);
+                   }
+               }
+           }
        }
 
       /* Ensure that the latch and the preheader is simple (we know that they
         are not now, since there was the loop exit condition.  */
        }
 
       /* Ensure that the latch and the preheader is simple (we know that they
         are not now, since there was the loop exit condition.  */
-      loop_split_edge_with (loop_preheader_edge (loop), NULL);
-      loop_split_edge_with (loop_latch_edge (loop), NULL);
+      split_edge (loop_preheader_edge (loop));
+      split_edge (loop_latch_edge (loop));
     }
 
   free (bbs);
   free (copied_bbs);
 
     }
 
   free (bbs);
   free (copied_bbs);
 
-  loop_optimizer_finalize (loops, NULL);
+  loop_optimizer_finalize ();
+  return 0;
 }
 
 static bool
 }
 
 static bool
@@ -246,8 +260,10 @@ gate_ch (void)
   return flag_tree_ch != 0;
 }
 
   return flag_tree_ch != 0;
 }
 
-struct tree_opt_pass pass_ch = 
+struct gimple_opt_pass pass_ch = 
 {
 {
+ {
+  GIMPLE_PASS,
   "ch",                                        /* name */
   gate_ch,                             /* gate */
   copy_loop_headers,                   /* execute */
   "ch",                                        /* name */
   gate_ch,                             /* gate */
   copy_loop_headers,                   /* execute */
@@ -260,6 +276,6 @@ struct tree_opt_pass pass_ch =
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_cleanup_cfg | TODO_dump_func 
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_cleanup_cfg | TODO_dump_func 
-  | TODO_verify_ssa,                   /* todo_flags_finish */
-  0                                    /* letter */
+  | TODO_verify_ssa                    /* todo_flags_finish */
+ }
 };
 };