aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2016-06-26 22:03:35 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2016-06-26 20:03:35 +0000
commit9bb86f403f3085d0d9b344127f7603d4559370a5 (patch)
tree758291fab73082c64f9ab653eec592aa1da221c4 /gcc/predict.c
parent445f9a500ddf8fd6673e87b525c8f38cd742af26 (diff)
downloadgcc-9bb86f403f3085d0d9b344127f7603d4559370a5.zip
gcc-9bb86f403f3085d0d9b344127f7603d4559370a5.tar.gz
gcc-9bb86f403f3085d0d9b344127f7603d4559370a5.tar.bz2
predict-12.c: New testcase.
* gcc.dg/predict-12.c: New testcase. * predict.c: Include gimple-pretty-print.h (predicted_by_loop_heuristics_p): Check also PRED_LOOP_EXIT_WITH_RECURSION (predict_loops): Find self recursive calls and use special purpose predictors for them; dump log about decisions. (pass_profile::execute): Dump info about #of iterations. * predict.def (PRED_LOOP_EXIT_WITH_RECURSION, (PRED_LOOP_GUARD_WITH_RECURSION): New predictors. From-SVN: r237791
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c118
1 files changed, 103 insertions, 15 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index 5a841dd..01f5cfc 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-loop.h"
#include "tree-scalar-evolution.h"
#include "ipa-utils.h"
+#include "gimple-pretty-print.h"
/* Enum with reasons why a predictor is ignored. */
@@ -1407,6 +1408,7 @@ predicted_by_loop_heuristics_p (basic_block bb)
|| i->ep_predictor == PRED_LOOP_ITERATIONS_MAX
|| i->ep_predictor == PRED_LOOP_ITERATIONS
|| i->ep_predictor == PRED_LOOP_EXIT
+ || i->ep_predictor == PRED_LOOP_EXIT_WITH_RECURSION
|| i->ep_predictor == PRED_LOOP_EXTRA_EXIT)
return true;
return false;
@@ -1686,6 +1688,24 @@ static void
predict_loops (void)
{
struct loop *loop;
+ basic_block bb;
+ hash_set <struct loop *> with_recursion(10);
+
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ gimple_stmt_iterator gsi;
+ tree decl;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ if (is_gimple_call (gsi_stmt (gsi))
+ && (decl = gimple_call_fndecl (gsi_stmt (gsi))) != NULL
+ && recursive_call_p (current_function_decl, decl))
+ {
+ loop = bb->loop_father;
+ while (loop && !with_recursion.add (loop))
+ loop = loop_outer (loop);
+ }
+ }
/* Try to predict out blocks in a loop that are not part of a
natural loop. */
@@ -1702,6 +1722,7 @@ predict_loops (void)
tree loop_bound_var = NULL;
tree loop_iv_base = NULL;
gcond *stmt = NULL;
+ bool recursion = with_recursion.contains (loop);
exits = get_loop_exit_edges (loop);
FOR_EACH_VEC_ELT (exits, j, ex)
@@ -1713,6 +1734,23 @@ predict_loops (void)
continue;
}
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predicting loop %i%s with %i exits.\n",
+ loop->num, recursion ? " (with recursion)":"", n_exits);
+ if (dump_file && (dump_flags & TDF_DETAILS)
+ && max_loop_iterations_int (loop) >= 0)
+ {
+ fprintf (dump_file,
+ "Loop %d iterates at most %i times.\n", loop->num,
+ (int)max_loop_iterations_int (loop));
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS)
+ && likely_max_loop_iterations_int (loop) >= 0)
+ {
+ fprintf (dump_file, "Loop %d likely iterates at most %i times.\n",
+ loop->num, (int)likely_max_loop_iterations_int (loop));
+ }
+
FOR_EACH_VEC_ELT (exits, j, ex)
{
tree niter = NULL;
@@ -1727,13 +1765,28 @@ predict_loops (void)
/* Loop heuristics do not expect exit conditional to be inside
inner loop. We predict from innermost to outermost loop. */
if (predicted_by_loop_heuristics_p (ex->src))
- continue;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Skipping exit %i->%i because "
+ "it is already predicted.\n",
+ ex->src->index, ex->dest->index);
+ continue;
+ }
predict_extra_loop_exits (ex);
if (number_of_iterations_exit (loop, ex, &niter_desc, false, false))
niter = niter_desc.niter;
if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST)
niter = loop_niter_by_eval (loop, ex);
+ if (dump_file && (dump_flags & TDF_DETAILS)
+ && TREE_CODE (niter) == INTEGER_CST)
+ {
+ fprintf (dump_file, "Exit %i->%i %d iterates ",
+ ex->src->index, ex->dest->index,
+ loop->num);
+ print_generic_expr (dump_file, niter, TDF_SLIM);
+ fprintf (dump_file, " times.\n");
+ }
if (TREE_CODE (niter) == INTEGER_CST)
{
@@ -1766,14 +1819,24 @@ predict_loops (void)
RDIV (REG_BR_PROB_BASE,
REG_BR_PROB_BASE
- predictor_info
- [PRED_LOOP_EXIT].hitrate)))
+ [recursion
+ ? PRED_LOOP_EXIT_WITH_RECURSION
+ : PRED_LOOP_EXIT].hitrate)))
{
nitercst = nit.to_shwi ();
predictor = PRED_LOOP_ITERATIONS_MAX;
}
else
- continue;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Nothing known about exit %i->%i.\n",
+ ex->src->index, ex->dest->index);
+ continue;
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Recording prediction to %i iterations by %s.\n",
+ (int)nitercst, predictor_info[predictor].name);
/* If the prediction for number of iterations is zero, do not
predict the exit edges. */
if (nitercst == 0)
@@ -1807,7 +1870,6 @@ predict_loops (void)
for (j = 0; j < loop->num_nodes; j++)
{
- int header_found = 0;
edge e;
edge_iterator ei;
@@ -1818,14 +1880,16 @@ predict_loops (void)
in the source language and are better to be handled
separately. */
if (predicted_by_p (bb, PRED_CONTINUE))
- continue;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "BB %i predicted by continue.\n",
+ bb->index);
+ continue;
+ }
- /* Loop exit heuristics - predict an edge exiting the loop if the
- conditional has no loop header successors as not taken. */
- if (!header_found
- /* If we already used more reliable loop exit predictors, do not
- bother with PRED_LOOP_EXIT. */
- && !predicted_by_loop_heuristics_p (bb))
+ /* If we already used more reliable loop exit predictors, do not
+ bother with PRED_LOOP_EXIT. */
+ if (!predicted_by_loop_heuristics_p (bb))
{
/* For loop with many exits we don't want to predict all exits
with the pretty large probability, because if all exits are
@@ -1842,14 +1906,25 @@ predict_loops (void)
a wide loop. */
int probability = ((REG_BR_PROB_BASE
- - predictor_info [(int) PRED_LOOP_EXIT].hitrate)
+ - predictor_info
+ [recursion
+ ? PRED_LOOP_EXIT_WITH_RECURSION
+ : PRED_LOOP_EXIT].hitrate)
/ n_exits);
if (probability < HITRATE (2))
probability = HITRATE (2);
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest->index < NUM_FIXED_BLOCKS
|| !flow_bb_inside_loop_p (loop, e->dest))
- predict_edge (e, PRED_LOOP_EXIT, probability);
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Predicting exit %i->%i with prob %i.\n",
+ e->src->index, e->dest->index, probability);
+ predict_edge (e,
+ recursion ? PRED_LOOP_EXIT_WITH_RECURSION
+ : PRED_LOOP_EXIT, probability);
+ }
}
if (loop_bound_var)
predict_iv_comparison (loop, bb, loop_bound_var, loop_iv_base,
@@ -1910,7 +1985,9 @@ predict_loops (void)
if (!dominated_by_p (CDI_DOMINATORS,
loop_outer (loop)->latch, loop->header))
predict_paths_leading_to_edge (loop_preheader_edge (loop),
- PRED_LOOP_GUARD,
+ recursion
+ ? PRED_LOOP_GUARD_WITH_RECURSION
+ : PRED_LOOP_GUARD,
NOT_TAKEN,
loop_outer (loop));
}
@@ -1919,7 +1996,9 @@ predict_loops (void)
if (!dominated_by_p (CDI_DOMINATORS,
loop_outer (loop)->latch, bb))
predict_paths_leading_to (bb,
- PRED_LOOP_GUARD,
+ recursion
+ ? PRED_LOOP_GUARD_WITH_RECURSION
+ : PRED_LOOP_GUARD,
NOT_TAKEN,
loop_outer (loop));
}
@@ -3367,6 +3446,15 @@ pass_profile::execute (function *fun)
gimple_dump_cfg (dump_file, dump_flags);
if (profile_status_for_fn (fun) == PROFILE_ABSENT)
profile_status_for_fn (fun) = PROFILE_GUESSED;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ struct loop *loop;
+ FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+ if (loop->header->frequency)
+ fprintf (dump_file, "Loop got predicted %d to iterate %i times.\n",
+ loop->num,
+ (int)expected_loop_iterations_unbounded (loop));
+ }
return 0;
}