OSDN Git Service

* varasm.c (default_assemble_visibility): Remove extra ().
[pf3gnuchains/gcc-fork.git] / gcc / cfgloopanal.c
index 358bfa7..055375d 100644 (file)
@@ -1,5 +1,5 @@
 /* Natural loop analysis code for GNU compiler.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -24,6 +24,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
+#include "obstack.h"
 #include "basic-block.h"
 #include "cfgloop.h"
 #include "expr.h"
@@ -208,8 +209,7 @@ check_irred (struct graph *g, struct edge *e)
 
   /* All edges should lead from a component with higher number to the
      one with lower one.  */
-  if (g->vertices[e->src].component < g->vertices[e->dest].component)
-    abort ();
+  gcc_assert (g->vertices[e->src].component >= g->vertices[e->dest].component);
 
   if (g->vertices[e->src].component != g->vertices[e->dest].component)
     return;
@@ -268,6 +268,7 @@ mark_irreducible_loops (struct loops *loops)
 {
   basic_block act;
   edge e;
+  edge_iterator ei;
   int i, src, dest;
   struct graph *g;
   int *queue1 = xmalloc ((last_basic_block + loops->num) * sizeof (int));
@@ -279,7 +280,7 @@ mark_irreducible_loops (struct loops *loops)
   FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
     {
       act->flags &= ~BB_IRREDUCIBLE_LOOP;
-      for (e = act->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, act->succs)
        e->flags &= ~EDGE_IRREDUCIBLE_LOOP;
     }
 
@@ -287,7 +288,7 @@ mark_irreducible_loops (struct loops *loops)
   g = new_graph (last_basic_block + loops->num);
 
   FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
-    for (e = act->succ; e; e = e->succ_next)
+    FOR_EACH_EDGE (e, ei, act->succs)
       {
         /* Ignore edges to exit.  */
         if (e->dest == EXIT_BLOCK_PTR)
@@ -416,6 +417,7 @@ unsigned
 expected_loop_iterations (const struct loop *loop)
 {
   edge e;
+  edge_iterator ei;
 
   if (loop->header->count)
     {
@@ -424,7 +426,7 @@ expected_loop_iterations (const struct loop *loop)
       count_in = 0;
       count_latch = 0;
 
-      for (e = loop->header->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, loop->header->preds)
        if (e->src == loop->latch)
          count_latch = e->count;
        else
@@ -445,7 +447,7 @@ expected_loop_iterations (const struct loop *loop)
       freq_in = 0;
       freq_latch = 0;
 
-      for (e = loop->header->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, loop->header->preds)
        if (e->src == loop->latch)
          freq_latch = EDGE_FREQUENCY (e);
        else
@@ -474,3 +476,121 @@ get_loop_level (const struct loop *loop)
     }
   return mx;
 }
+
+/* Returns estimate on cost of computing SEQ.  */
+
+static unsigned
+seq_cost (rtx seq)
+{
+  unsigned cost = 0;
+  rtx set;
+
+  for (; seq; seq = NEXT_INSN (seq))
+    {
+      set = single_set (seq);
+      if (set)
+       cost += rtx_cost (set, SET);
+      else
+       cost++;
+    }
+
+  return cost;
+}
+
+/* The properties of the target.  */
+
+unsigned target_avail_regs;    /* Number of available registers.  */
+unsigned target_res_regs;      /* Number of reserved registers.  */
+unsigned target_small_cost;    /* The cost for register when there is a free one.  */
+unsigned target_pres_cost;     /* The cost for register when there are not too many
+                                  free ones.  */
+unsigned target_spill_cost;    /* The cost for register when we need to spill.  */
+
+/* Initialize the constants for computing set costs.  */
+
+void
+init_set_costs (void)
+{
+  rtx seq;
+  rtx reg1 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER);
+  rtx reg2 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER + 1);
+  rtx addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 2);
+  rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
+  unsigned i;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
+       && !fixed_regs[i])
+      target_avail_regs++;
+
+  target_res_regs = 3;
+
+  /* These are really just heuristic values.  */
+  
+  start_sequence ();
+  emit_move_insn (reg1, reg2);
+  seq = get_insns ();
+  end_sequence ();
+  target_small_cost = seq_cost (seq);
+  target_pres_cost = 2 * target_small_cost;
+
+  start_sequence ();
+  emit_move_insn (mem, reg1);
+  emit_move_insn (reg2, mem);
+  seq = get_insns ();
+  end_sequence ();
+  target_spill_cost = seq_cost (seq);
+}
+
+/* Calculates cost for having SIZE new loop global variables.  REGS_USED is the
+   number of global registers used in loop.  N_USES is the number of relevant
+   variable uses.  */
+
+unsigned
+global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses)
+{
+  unsigned regs_needed = regs_used + size;
+  unsigned cost = 0;
+
+  if (regs_needed + target_res_regs <= target_avail_regs)
+    cost += target_small_cost * size;
+  else if (regs_needed <= target_avail_regs)
+    cost += target_pres_cost * size;
+  else
+    {
+      cost += target_pres_cost * size;
+      cost += target_spill_cost * n_uses * (regs_needed - target_avail_regs) / regs_needed;
+    }
+
+  return cost;
+}
+
+/* Sets EDGE_LOOP_EXIT flag for all exits of LOOPS.  */
+
+void
+mark_loop_exit_edges (struct loops *loops)
+{
+  basic_block bb;
+  edge e;
+  if (loops->num <= 1)
+    return;
+
+  FOR_EACH_BB (bb)
+    {
+      edge_iterator ei;
+
+      /* Do not mark exits from the fake outermost loop.  */
+      if (!bb->loop_father->outer)
+       continue;
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       {
+         if (loop_exit_edge_p (bb->loop_father, e))
+           e->flags |= EDGE_LOOP_EXIT;
+         else
+           e->flags &= ~EDGE_LOOP_EXIT;
+       }
+    }
+}
+