OSDN Git Service

PR c/18946
[pf3gnuchains/gcc-fork.git] / gcc / profile.c
index 7b04bfd..318defd 100644 (file)
@@ -142,8 +142,9 @@ instrument_edges (struct edge_list *el)
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
+      edge_iterator ei;
 
-      for (e = bb->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, bb->succs)
        {
          struct edge_info *inf = EDGE_INFO (e);
 
@@ -239,7 +240,9 @@ get_exec_counts (void)
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
-      for (e = bb->succ; e; e = e->succ_next)
+      edge_iterator ei;
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
        if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
          num_edges++;
     }
@@ -295,11 +298,12 @@ compute_branch_probabilities (void)
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
+      edge_iterator ei;
 
-      for (e = bb->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, bb->succs)
        if (!EDGE_INFO (e)->ignore)
          BB_INFO (bb)->succ_count++;
-      for (e = bb->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, bb->preds)
        if (!EDGE_INFO (e)->ignore)
          BB_INFO (bb)->pred_count++;
     }
@@ -317,7 +321,9 @@ compute_branch_probabilities (void)
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
-      for (e = bb->succ; e; e = e->succ_next)
+      edge_iterator ei;
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
        if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
          {
            num_edges++;
@@ -380,9 +386,10 @@ compute_branch_probabilities (void)
              if (bi->succ_count == 0)
                {
                  edge e;
+                 edge_iterator ei;
                  gcov_type total = 0;
 
-                 for (e = bb->succ; e; e = e->succ_next)
+                 FOR_EACH_EDGE (e, ei, bb->succs)
                    total += e->count;
                  bb->count = total;
                  bi->count_valid = 1;
@@ -391,9 +398,10 @@ compute_branch_probabilities (void)
              else if (bi->pred_count == 0)
                {
                  edge e;
+                 edge_iterator ei;
                  gcov_type total = 0;
 
-                 for (e = bb->pred; e; e = e->pred_next)
+                 FOR_EACH_EDGE (e, ei, bb->preds)
                    total += e->count;
                  bb->count = total;
                  bi->count_valid = 1;
@@ -405,15 +413,16 @@ compute_branch_probabilities (void)
              if (bi->succ_count == 1)
                {
                  edge e;
+                 edge_iterator ei;
                  gcov_type total = 0;
 
                  /* One of the counts will be invalid, but it is zero,
                     so adding it in also doesn't hurt.  */
-                 for (e = bb->succ; e; e = e->succ_next)
+                 FOR_EACH_EDGE (e, ei, bb->succs)
                    total += e->count;
 
                  /* Seedgeh for the invalid edge, and set its count.  */
-                 for (e = bb->succ; e; e = e->succ_next)
+                 FOR_EACH_EDGE (e, ei, bb->succs)
                    if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
                      break;
 
@@ -432,15 +441,16 @@ compute_branch_probabilities (void)
              if (bi->pred_count == 1)
                {
                  edge e;
+                 edge_iterator ei;
                  gcov_type total = 0;
 
                  /* One of the counts will be invalid, but it is zero,
                     so adding it in also doesn't hurt.  */
-                 for (e = bb->pred; e; e = e->pred_next)
+                 FOR_EACH_EDGE (e, ei, bb->preds)
                    total += e->count;
 
                  /* Search for the invalid edge, and set its count.  */
-                 for (e = bb->pred; e; e = e->pred_next)
+                 FOR_EACH_EDGE (e, ei, bb->preds)
                    if (!EDGE_INFO (e)->count_valid && !EDGE_INFO (e)->ignore)
                      break;
 
@@ -485,6 +495,7 @@ compute_branch_probabilities (void)
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
+      edge_iterator ei;
       rtx note;
 
       if (bb->count < 0)
@@ -493,7 +504,7 @@ compute_branch_probabilities (void)
                 bb->index, (int)bb->count);
          bb->count = 0;
        }
-      for (e = bb->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, bb->succs)
        {
          /* Function may return twice in the cased the called function is
             setjmp or calls fork, but we can't represent this by extra
@@ -518,11 +529,11 @@ compute_branch_probabilities (void)
        }
       if (bb->count)
        {
-         for (e = bb->succ; e; e = e->succ_next)
+         FOR_EACH_EDGE (e, ei, bb->succs)
            e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count;
          if (bb->index >= 0
              && block_ends_with_condjump_p (bb)
-             && bb->succ->succ_next)
+             && EDGE_COUNT (bb->succs) >= 2)
            {
              int prob;
              edge e;
@@ -530,9 +541,9 @@ compute_branch_probabilities (void)
 
              /* Find the branch edge.  It is possible that we do have fake
                 edges here.  */
-             for (e = bb->succ; e->flags & (EDGE_FAKE | EDGE_FALLTHRU);
-                  e = e->succ_next)
-               continue; /* Loop body has been intentionally left blank.  */
+             FOR_EACH_EDGE (e, ei, bb->succs)
+               if (!(e->flags & (EDGE_FAKE | EDGE_FALLTHRU)))
+                 break;
 
              prob = e->probability;
              index = prob * 20 / REG_BR_PROB_BASE;
@@ -557,21 +568,36 @@ compute_branch_probabilities (void)
              num_branches++;
            }
        }
-      /* Otherwise distribute the probabilities evenly so we get sane
-        sum.  Use simple heuristics that if there are normal edges,
+      /* Otherwise try to preserve the existing REG_BR_PROB probabilities
+         tree based profile guessing put into code.  BB can be the
+        ENTRY_BLOCK, and it can have multiple (fake) successors in
+        EH cases, but it still has no code; don't crash in this case.  */
+      else if (profile_status == PROFILE_ABSENT
+              && !ir_type ()
+              && EDGE_COUNT (bb->succs) > 1
+              && BB_END (bb)
+              && (note = find_reg_note (BB_END (bb), REG_BR_PROB, 0)))
+       {
+         int prob = INTVAL (XEXP (note, 0));
+
+         BRANCH_EDGE (bb)->probability = prob;
+         FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
+       }
+      /* As a last resort, distribute the probabilities evenly.
+        Use simple heuristics that if there are normal edges,
         give all abnormals frequency of 0, otherwise distribute the
         frequency over abnormals (this is the case of noreturn
         calls).  */
-      else
+      else if (profile_status == PROFILE_ABSENT)
        {
          int total = 0;
 
-         for (e = bb->succ; e; e = e->succ_next)
+         FOR_EACH_EDGE (e, ei, bb->succs)
            if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
              total ++;
          if (total)
            {
-             for (e = bb->succ; e; e = e->succ_next)
+             FOR_EACH_EDGE (e, ei, bb->succs)
                if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
                  e->probability = REG_BR_PROB_BASE / total;
                else
@@ -579,17 +605,17 @@ compute_branch_probabilities (void)
            }
          else
            {
-             for (e = bb->succ; e; e = e->succ_next)
-               total ++;
-             for (e = bb->succ; e; e = e->succ_next)
+             total += EDGE_COUNT (bb->succs);
+             FOR_EACH_EDGE (e, ei, bb->succs)
                e->probability = REG_BR_PROB_BASE / total;
            }
          if (bb->index >= 0
              && block_ends_with_condjump_p (bb)
-             && bb->succ->succ_next)
+             && EDGE_COUNT (bb->succs) >= 2)
            num_branches++, num_never_executed;
        }
     }
+  counts_to_freqs ();
 
   if (dump_file)
     {
@@ -776,6 +802,7 @@ branch_prob (void)
       int need_exit_edge = 0, need_entry_edge = 0;
       int have_exit_edge = 0, have_entry_edge = 0;
       edge e;
+      edge_iterator ei;
 
       /* Functions returning multiple times are not handled by extra edges.
          Instead we simply allow negative counts on edges from exit to the
@@ -783,7 +810,7 @@ branch_prob (void)
          with the extra edges because that would result in flowgraph that
         needs to have fake edges outside the spanning tree.  */
 
-      for (e = bb->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, bb->succs)
        {
          if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
               && e->dest != EXIT_BLOCK_PTR)
@@ -791,7 +818,7 @@ branch_prob (void)
          if (e->dest == EXIT_BLOCK_PTR)
            have_exit_edge = 1;
        }
-      for (e = bb->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, bb->preds)
        {
          if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
               && e->src != ENTRY_BLOCK_PTR)
@@ -902,11 +929,12 @@ branch_prob (void)
       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
        {
          edge e;
+         edge_iterator ei;
 
          offset = gcov_write_tag (GCOV_TAG_ARCS);
          gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
 
-         for (e = bb->succ; e; e = e->succ_next)
+         FOR_EACH_EDGE (e, ei, bb->succs)
            {
              struct edge_info *i = EDGE_INFO (e);
              if (!i->ignore)
@@ -979,7 +1007,7 @@ branch_prob (void)
                        {
                          expanded_location s;
                          NOTE_EXPANDED_LOCATION (s, insn);
-                         output_location (s.file, NOTE_LINE_NUMBER (insn), &offset, bb);
+                         output_location (s.file, s.line, &offset, bb);
                        }
                    }
                  insn = NEXT_INSN (insn);
@@ -1024,10 +1052,10 @@ branch_prob (void)
 
              /* Notice GOTO expressions we eliminated while constructing the
                 CFG.  */
-             if (bb->succ && !bb->succ->succ_next && bb->succ->goto_locus)
+             if (EDGE_COUNT (bb->succs) == 1 && EDGE_SUCC (bb, 0)->goto_locus)
                {
                  /* ??? source_locus type is marked deprecated in input.h.  */
-                 source_locus curr_location = bb->succ->goto_locus;
+                 source_locus curr_location = EDGE_SUCC (bb, 0)->goto_locus;
                  /* ??? The FILE/LINE API is inconsistent for these cases.  */
 #ifdef USE_MAPPED_LOCATION 
                  output_location (LOCATION_FILE (curr_location),
@@ -1070,7 +1098,11 @@ branch_prob (void)
   if (profile_arc_flag
       && coverage_counter_alloc (GCOV_COUNTER_ARCS, num_instrumented))
     {
-      unsigned n_instrumented = instrument_edges (el);
+      unsigned n_instrumented;
+
+      profile_hooks->init_edge_profiler ();
+
+      n_instrumented = instrument_edges (el);
 
       if (n_instrumented != num_instrumented)
        abort ();
@@ -1080,7 +1112,7 @@ branch_prob (void)
 
       /* Commit changes done by instrumentation.  */
       if (ir_type ())
-       bsi_commit_edge_inserts ((int *)NULL);
+       bsi_commit_edge_inserts ();
       else
        {
           commit_edge_insertions_watch_calls ();