OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cfgloopanal.c
index 9b3ffa0..6c625d6 100644 (file)
@@ -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,16 +426,16 @@ 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
          count_in += e->count;
 
       if (count_in == 0)
-       return 0;
-
-      expected = (count_latch + count_in - 1) / count_in;
+        expected = count_latch * 2;
+      else
+        expected = (count_latch + count_in - 1) / count_in;
 
       /* Avoid overflows.  */
       return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected);
@@ -445,15 +447,121 @@ 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
          freq_in += EDGE_FREQUENCY (e);
 
       if (freq_in == 0)
-       return 0;
+       return freq_latch * 2;
 
       return (freq_latch + freq_in - 1) / freq_in;
     }
 }
+
+/* Returns the maximum level of nesting of subloops of LOOP.  */
+
+unsigned
+get_loop_level (const struct loop *loop)
+{
+  const struct loop *ploop;
+  unsigned mx = 0, l;
+
+  for (ploop = loop->inner; ploop; ploop = ploop->next)
+    {
+      l = get_loop_level (ploop);
+      if (l >= mx)
+       mx = l + 1;
+    }
+  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;
+}
+