predict.def (PRED_CALL, [...]): New.
authorJan Hubicka <jh@suse.cz>
Sun, 10 Jun 2001 08:01:57 +0000 (10:01 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 10 Jun 2001 08:01:57 +0000 (08:01 +0000)
* predict.def (PRED_CALL, PRED_ERROR_RETURN): New.
* predict.c (estimate_probability): Calculate dominance
information; improve detection of NORETURN heuristics;
add call/error_return heuiristics; tweak comparison heuristics
to recognize -1.

From-SVN: r43130

gcc/ChangeLog
gcc/predict.c
gcc/predict.def

index ca22a3112d0a530c17f879d1e8d8f1adeeebed3e..954d6a5abe906f23b39e528a4326ba04f71e456d 100644 (file)
@@ -1,3 +1,11 @@
+Sun Jun 10 10:00:17 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * predict.def (PRED_CALL, PRED_ERROR_RETURN): New.
+       * predict.c (estimate_probability): Calculate dominance
+       information; improve detection of NORETURN heuristics;
+       add call/error_return heuiristics; tweak comparison heuristics
+       to recognize -1.
+
 2001-06-09  Alexandre Oliva  <aoliva@redhat.com>
 
        * doc/invoke.texi (C Dialect Options): Document -aux-info.
index d4210e030cb969fcf615e32464becd0efc022be2..21c7149070f17d7fa68c15501caf4c90d9af1b2b 100644 (file)
@@ -240,8 +240,14 @@ void
 estimate_probability (loops_info)
      struct loops *loops_info;
 {
+  sbitmap *dominators, *post_dominators;
   int i;
 
+  dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
+  post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
+  calculate_dominance_info (NULL, dominators, 0);
+  calculate_dominance_info (NULL, post_dominators, 1);
+
   /* Try to predict out blocks in a loop that are not part of a
      natural loop.  */
   for (i = 0; i < loops_info->num; i++)
@@ -282,10 +288,27 @@ estimate_probability (loops_info)
      is used as the prediction for the branch.  */
   for (i = 0; i < n_basic_blocks - 1; i++)
     {
-      rtx last_insn = BLOCK_END (i);
+      basic_block bb = BASIC_BLOCK (i);
+      rtx last_insn = bb->end;
       rtx cond, earliest;
       edge e;
 
+      /* If block has no sucessor, predict all possible paths to
+         it as improbable, as the block contains a call to a noreturn
+        function and thus can be executed only once.  */
+      if (bb->succ == NULL)
+       {
+         int y;
+         for (y = 0; y < n_basic_blocks; y++)
+           if (!TEST_BIT (post_dominators[y], i))
+             {
+               for (e = BASIC_BLOCK (y)->succ; e; e = e->succ_next)
+               if (e->dest->index >= 0
+                   && TEST_BIT (post_dominators[e->dest->index], i))
+                 predict_edge_def (e, PRED_NORETURN, NOT_TAKEN);
+             }
+       }
+
       if (GET_CODE (last_insn) != JUMP_INSN
          || ! any_condjump_p (last_insn))
        continue;
@@ -293,12 +316,39 @@ estimate_probability (loops_info)
       if (find_reg_note (last_insn, REG_BR_PROB, 0))
        continue;
 
-      /* If one of the successor blocks has no successors, predict
-        that side not taken.  */
-      /* ??? Ought to do the same for any subgraph with no exit.  */
-      for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
-       if (e->dest->succ == NULL)
-         predict_edge_def (e, PRED_NORETURN, NOT_TAKEN);
+      for (e = bb->succ; e; e = e->succ_next)
+       {
+         /* Predict edges to blocks that return immediately to be
+            improbable.  These are usually used to signal error states.  */
+         if (e->dest == EXIT_BLOCK_PTR
+             || (e->dest->succ && !e->dest->succ->succ_next
+                 && e->dest->succ->dest == EXIT_BLOCK_PTR))
+           predict_edge_def (e, PRED_ERROR_RETURN, NOT_TAKEN);
+
+         /* Look for block we are guarding (ie we dominate it,
+            but it doesn't postdominate us).  */
+         if (e->dest != EXIT_BLOCK_PTR
+             && e->dest != bb
+             && TEST_BIT (dominators[e->dest->index], e->src->index)
+             && !TEST_BIT (post_dominators[e->src->index], e->dest->index))
+           {
+             rtx insn;
+             /* The call heuristic claims that a guarded function call
+                is improbable.  This is because such calls are often used
+                to signal exceptional situations such as printing error
+                messages.  */
+             for (insn = e->dest->head; insn != NEXT_INSN (e->dest->end);
+                  insn = NEXT_INSN (insn))
+               if (GET_CODE (insn) == CALL_INSN
+                   /* Constant and pure calls are hardly used to signalize
+                      something exceptional.  */
+                   && ! CONST_CALL_P (insn))
+                 {
+                   predict_edge_def (e, PRED_CALL, NOT_TAKEN);
+                   break;
+                 }
+           }
+       }
 
       cond = get_condition (last_insn, &earliest);
       if (! cond)
@@ -359,7 +409,9 @@ estimate_probability (loops_info)
          break;
        case LE:
        case LT:
-         if (XEXP (cond, 1) == const0_rtx)
+         if (XEXP (cond, 1) == const0_rtx
+             || (GET_CODE (XEXP (cond, 1)) == CONST_INT
+                 && INTVAL (XEXP (cond, 1)) == -1))
            predict_insn_def (last_insn, PRED_OPCODE, NOT_TAKEN);
          break;
        case GE:
@@ -385,6 +437,8 @@ estimate_probability (loops_info)
        continue;
       combine_predictions_for_insn (last_insn, BASIC_BLOCK (i));
     }
+  sbitmap_vector_free (post_dominators);
+  sbitmap_vector_free (dominators);
 }
 \f
 /* __builtin_expect dropped tokens into the insn stream describing
index ce0fbbdf7733ba3a3149733b5146f425151235ba..9f000b95ca85c187e7a66a16737f3d710e81faf3 100644 (file)
@@ -44,4 +44,6 @@ DEF_PREDICTOR (PRED_LOOP_BRANCH, "loop branch", PROB_VERY_LIKELY)
 DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", PROB_LIKELY)
 DEF_PREDICTOR (PRED_LOOP_HEADER, "loop header", PROB_LIKELY)
 DEF_PREDICTOR (PRED_POINTER, "pointer", PROB_LIKELY)
+DEF_PREDICTOR (PRED_CALL, "call", PROB_LIKELY)
+DEF_PREDICTOR (PRED_ERROR_RETURN, "error return", PROB_LIKELY)
 DEF_PREDICTOR (PRED_OPCODE, "opcode", PROB_LIKELY)