OSDN Git Service

PR tree-optimization/38074
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 6 Dec 2008 08:34:20 +0000 (08:34 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 6 Dec 2008 08:34:20 +0000 (08:34 +0000)
* cgraphbuild.c (compute_call_stmt_bb_frequency): Fix handling of 0
entry frequency.
* predict.c (combine_predictions_for_bb): Ignore predictor predicting
in both dirrection for first match heuristics.
(tree_bb_level_predictions): Disable noreturn heuristic when there
is no returning path.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142517 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraphbuild.c
gcc/predict.c

index cf34965..248ba67 100644 (file)
@@ -1,3 +1,14 @@
+2008-12-06  Jan Hubicka  <jh@suse.cz>
+           Jakub Jelinek <jakub@redhat.com>
+
+       PR tree-optimization/38074
+       * cgraphbuild.c (compute_call_stmt_bb_frequency): Fix handling of 0
+       entry frequency.
+       * predict.c (combine_predictions_for_bb): Ignore predictor predicting
+       in both dirrection for first match heuristics.
+       (tree_bb_level_predictions): Disable noreturn heuristic when there
+       is no returning path.
+
 2008-12-05  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        PR rtl-optimization/38272
index 958fed7..75db875 100644 (file)
@@ -109,13 +109,12 @@ int
 compute_call_stmt_bb_frequency (basic_block bb)
 {
   int entry_freq = ENTRY_BLOCK_PTR->frequency;
-  int freq;
+  int freq = bb->frequency;
 
   if (!entry_freq)
-    entry_freq = 1;
+    entry_freq = 1, freq++;
 
-  freq = (!bb->frequency && !entry_freq ? CGRAPH_FREQ_BASE
-             : bb->frequency * CGRAPH_FREQ_BASE / entry_freq);
+  freq = freq * CGRAPH_FREQ_BASE / entry_freq;
   if (freq > CGRAPH_FREQ_MAX)
     freq = CGRAPH_FREQ_MAX;
 
index c6e933f..73dbcbd 100644 (file)
@@ -820,8 +820,33 @@ combine_predictions_for_bb (basic_block bb)
            probability = REG_BR_PROB_BASE - probability;
 
          found = true;
+         /* First match heuristics would be widly confused if we predicted
+            both directions.  */
          if (best_predictor > predictor)
-           best_probability = probability, best_predictor = predictor;
+           {
+              struct edge_prediction *pred2;
+             int prob = probability;
+
+              for (pred2 = (struct edge_prediction *) *preds; pred2; pred2 = pred2->ep_next)
+              if (pred2 != pred && pred2->ep_predictor == pred->ep_predictor)
+                {
+                  int probability2 = pred->ep_probability;
+
+                  if (pred2->ep_edge != first)
+                    probability2 = REG_BR_PROB_BASE - probability2;
+
+                  if ((probability < REG_BR_PROB_BASE / 2) != 
+                      (probability2 < REG_BR_PROB_BASE / 2))
+                    break;
+
+                  /* If the same predictor later gave better result, go for it! */
+                  if ((probability >= REG_BR_PROB_BASE / 2 && (probability2 > probability))
+                      || (probability <= REG_BR_PROB_BASE / 2 && (probability2 < probability)))
+                    prob = probability2;
+                }
+             if (!pred2)
+               best_probability = prob, best_predictor = predictor;
+           }
 
          d = (combined_probability * probability
               + (REG_BR_PROB_BASE - combined_probability)
@@ -1521,6 +1546,16 @@ static void
 tree_bb_level_predictions (void)
 {
   basic_block bb;
+  bool has_return_edges = false;
+  edge e;
+  edge_iterator ei;
+
+  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+    if (!(e->flags & (EDGE_ABNORMAL | EDGE_FAKE | EDGE_EH)))
+      {
+        has_return_edges = true;
+       break;
+      }
 
   apply_return_prediction ();
 
@@ -1535,7 +1570,8 @@ tree_bb_level_predictions (void)
 
          if (is_gimple_call (stmt))
            {
-             if (gimple_call_flags (stmt) & ECF_NORETURN)
+             if ((gimple_call_flags (stmt) & ECF_NORETURN)
+                 && has_return_edges)
                predict_paths_leading_to (bb, PRED_NORETURN,
                                          NOT_TAKEN);
              decl = gimple_call_fndecl (stmt);