OSDN Git Service

* gcc.dg/vect/costmodel/ppc/costmodel-vect-outer-fir.c: Add
[pf3gnuchains/gcc-fork.git] / gcc / tracer.c
index dd263c4..44a2e50 100644 (file)
@@ -1,12 +1,13 @@
 /* The tracer pass for the GNU compiler.
    Contributed by Jan Hubicka, SuSE Labs.
-   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 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, but WITHOUT
@@ -15,9 +16,8 @@
    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/>.  */
 
 /* This pass performs the tail duplication needed for superblock formation.
    For more information see:
 #include "timevar.h"
 #include "params.h"
 #include "coverage.h"
+#include "tree-pass.h"
 
-static int count_insns (basic_block);
-static bool ignore_bb_p (basic_block);
-static bool better_p (edge, edge);
+static int count_insns (const_basic_block);
+static bool ignore_bb_p (const_basic_block);
+static bool better_p (const_edge, const_edge);
 static edge find_best_successor (basic_block);
 static edge find_best_predecessor (basic_block);
 static int find_trace (basic_block, basic_block *);
@@ -65,13 +66,13 @@ static int branch_ratio_cutoff;
 /* Return true if BB has been seen - it is connected to some trace
    already.  */
 
-#define seen(bb) (bb->rbi->visited || bb->rbi->next)
+#define seen(bb) (bb->il.rtl->visited || bb->aux)
 
 /* Return true if we should ignore the basic block for purposes of tracing.  */
 static bool
-ignore_bb_p (basic_block bb)
+ignore_bb_p (const_basic_block bb)
 {
-  if (bb->index < 0)
+  if (bb->index < NUM_FIXED_BLOCKS)
     return true;
   if (!maybe_hot_bb_p (bb))
     return true;
@@ -81,9 +82,9 @@ ignore_bb_p (basic_block bb)
 /* Return number of instructions in the block.  */
 
 static int
-count_insns (basic_block bb)
+count_insns (const_basic_block bb)
 {
-  rtx insn;
+  const_rtx insn;
   int n = 0;
 
   for (insn = BB_HEAD (bb);
@@ -96,7 +97,7 @@ count_insns (basic_block bb)
 
 /* Return true if E1 is more frequent than E2.  */
 static bool
-better_p (edge e1, edge e2)
+better_p (const_edge e1, const_edge e2)
 {
   if (e1->count != e2->count)
     return e1->count > e2->count;
@@ -118,8 +119,9 @@ find_best_successor (basic_block bb)
 {
   edge e;
   edge best = NULL;
+  edge_iterator ei;
 
-  for (e = bb->succ; e; e = e->succ_next)
+  FOR_EACH_EDGE (e, ei, bb->succs)
     if (!best || better_p (e, best))
       best = e;
   if (!best || ignore_bb_p (best->dest))
@@ -136,8 +138,9 @@ find_best_predecessor (basic_block bb)
 {
   edge e;
   edge best = NULL;
+  edge_iterator ei;
 
-  for (e = bb->pred; e; e = e->pred_next)
+  FOR_EACH_EDGE (e, ei, bb->preds)
     if (!best || better_p (e, best))
       best = e;
   if (!best || ignore_bb_p (best->src))
@@ -196,9 +199,9 @@ find_trace (basic_block bb, basic_block *trace)
 static void
 tail_duplicate (void)
 {
-  fibnode_t *blocks = xcalloc (last_basic_block, sizeof (fibnode_t));
-  basic_block *trace = xmalloc (sizeof (basic_block) * n_basic_blocks);
-  int *counts = xmalloc (sizeof (int) * last_basic_block);
+  fibnode_t *blocks = XCNEWVEC (fibnode_t, last_basic_block);
+  basic_block *trace = XNEWVEC (basic_block, n_basic_blocks);
+  int *counts = XNEWVEC (int, last_basic_block);
   int ninsns = 0, nduplicated = 0;
   gcov_type weighted_insns = 0, traced_insns = 0;
   fibheap_t heap = fibheap_new ();
@@ -247,8 +250,7 @@ tail_duplicate (void)
 
       if (ignore_bb_p (bb))
        continue;
-      if (seen (bb))
-       abort ();
+      gcc_assert (!seen (bb));
 
       n = find_trace (bb, trace);
 
@@ -270,16 +272,16 @@ tail_duplicate (void)
              blocks[bb2->index] = NULL;
            }
          traced_insns += bb2->frequency * counts [bb2->index];
-         if (bb2->pred && bb2->pred->pred_next
+         if (EDGE_COUNT (bb2->preds) > 1
              && can_duplicate_block_p (bb2))
            {
-             edge e = bb2->pred;
+             edge e;
              basic_block old = bb2;
 
-             while (e->src != bb)
-               e = e->pred_next;
+             e = find_edge (bb, bb2);
+
              nduplicated += counts [bb2->index];
-             bb2 = duplicate_block (bb2, e);
+             bb2 = duplicate_block (bb2, e, bb);
 
              /* Reconsider the original copy of block we've duplicated.
                 Removing the most common predecessor may make it to be
@@ -291,8 +293,8 @@ tail_duplicate (void)
                fprintf (dump_file, "Duplicated %i as %i [%i]\n",
                         old->index, bb2->index, bb2->frequency);
            }
-         bb->rbi->next = bb2;
-         bb2->rbi->visited = 1;
+         bb->aux = bb2;
+         bb2->il.rtl->visited = 1;
          bb = bb2;
          /* In case the trace became infrequent, stop duplicating.  */
          if (ignore_bb_p (bb))
@@ -320,63 +322,95 @@ tail_duplicate (void)
 static void
 layout_superblocks (void)
 {
-  basic_block end = ENTRY_BLOCK_PTR->succ->dest;
-  basic_block bb = ENTRY_BLOCK_PTR->succ->dest->next_bb;
+  basic_block end = single_succ (ENTRY_BLOCK_PTR);
+  basic_block bb = end->next_bb;
 
   while (bb != EXIT_BLOCK_PTR)
     {
+      edge_iterator ei;
       edge e, best = NULL;
-      while (end->rbi->next)
-       end = end->rbi->next;
+      while (end->aux)
+       end = end->aux;
 
-      for (e = end->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, end->succs)
        if (e->dest != EXIT_BLOCK_PTR
-           && e->dest != ENTRY_BLOCK_PTR->succ->dest
-           && !e->dest->rbi->visited
+           && e->dest != single_succ (ENTRY_BLOCK_PTR)
+           && !e->dest->il.rtl->visited
            && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
          best = e;
 
       if (best)
        {
-         end->rbi->next = best->dest;
-         best->dest->rbi->visited = 1;
+         end->aux = best->dest;
+         best->dest->il.rtl->visited = 1;
        }
       else
        for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
          {
-           if (!bb->rbi->visited)
+           if (!bb->il.rtl->visited)
              {
-               end->rbi->next = bb;
-               bb->rbi->visited = 1;
+               end->aux = bb;
+               bb->il.rtl->visited = 1;
                break;
              }
          }
     }
 }
 
-/* Main entry point to this file.  FLAGS is the set of flags to pass
-   to cfg_layout_initialize().  */
+/* Main entry point to this file.  */
 
 void
-tracer (unsigned int flags)
+tracer (void)
 {
-  if (n_basic_blocks <= 1)
-    return;
+  gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT);
 
-  timevar_push (TV_TRACER);
+  if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
+    return;
 
-  cfg_layout_initialize (flags);
   mark_dfs_back_edges ();
   if (dump_file)
-    dump_flow_info (dump_file);
+    dump_flow_info (dump_file, dump_flags);
   tail_duplicate ();
   layout_superblocks ();
+  relink_block_chain (/*stay_in_cfglayout_mode=*/true);
+  
   if (dump_file)
-    dump_flow_info (dump_file);
-  cfg_layout_finalize ();
+    dump_flow_info (dump_file, dump_flags);
 
   /* Merge basic blocks in duplicated traces.  */
-  cleanup_cfg (CLEANUP_EXPENSIVE);
+  cleanup_cfg (0);
+}
+\f
+static bool
+gate_handle_tracer (void)
+{
+  return (optimize > 0 && flag_tracer);
+}
 
-  timevar_pop (TV_TRACER);
+/* Run tracer.  */
+static unsigned int
+rest_of_handle_tracer (void)
+{
+  if (dump_file)
+    dump_flow_info (dump_file, dump_flags);
+  tracer ();
+  return 0;
 }
+
+struct tree_opt_pass pass_tracer =
+{
+  "tracer",                             /* name */
+  gate_handle_tracer,                   /* gate */
+  rest_of_handle_tracer,                /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_TRACER,                            /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func | TODO_verify_rtl_sharing, /* todo_flags_finish */
+  'T'                                   /* letter */
+};
+