Commit 9bb86f40 by Jan Hubicka Committed by Jan Hubicka

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
parent 445f9a50
2016-06-26 Jan Hubicka <hubicka@ucw.cz>
* 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.
2016-06-26 John David Anglin <danglin@gcc.gnu.org> 2016-06-26 John David Anglin <danglin@gcc.gnu.org>
* config/pa/pa.c (pa_output_indirect_call): Rework to combine * config/pa/pa.c (pa_output_indirect_call): Rework to combine
......
...@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-loop.h" #include "tree-ssa-loop.h"
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "gimple-pretty-print.h"
/* Enum with reasons why a predictor is ignored. */ /* Enum with reasons why a predictor is ignored. */
...@@ -1407,6 +1408,7 @@ predicted_by_loop_heuristics_p (basic_block bb) ...@@ -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_MAX
|| i->ep_predictor == PRED_LOOP_ITERATIONS || i->ep_predictor == PRED_LOOP_ITERATIONS
|| i->ep_predictor == PRED_LOOP_EXIT || i->ep_predictor == PRED_LOOP_EXIT
|| i->ep_predictor == PRED_LOOP_EXIT_WITH_RECURSION
|| i->ep_predictor == PRED_LOOP_EXTRA_EXIT) || i->ep_predictor == PRED_LOOP_EXTRA_EXIT)
return true; return true;
return false; return false;
...@@ -1686,6 +1688,24 @@ static void ...@@ -1686,6 +1688,24 @@ static void
predict_loops (void) predict_loops (void)
{ {
struct loop *loop; 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 /* Try to predict out blocks in a loop that are not part of a
natural loop. */ natural loop. */
...@@ -1702,6 +1722,7 @@ predict_loops (void) ...@@ -1702,6 +1722,7 @@ predict_loops (void)
tree loop_bound_var = NULL; tree loop_bound_var = NULL;
tree loop_iv_base = NULL; tree loop_iv_base = NULL;
gcond *stmt = NULL; gcond *stmt = NULL;
bool recursion = with_recursion.contains (loop);
exits = get_loop_exit_edges (loop); exits = get_loop_exit_edges (loop);
FOR_EACH_VEC_ELT (exits, j, ex) FOR_EACH_VEC_ELT (exits, j, ex)
...@@ -1713,6 +1734,23 @@ predict_loops (void) ...@@ -1713,6 +1734,23 @@ predict_loops (void)
continue; 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) FOR_EACH_VEC_ELT (exits, j, ex)
{ {
tree niter = NULL; tree niter = NULL;
...@@ -1727,13 +1765,28 @@ predict_loops (void) ...@@ -1727,13 +1765,28 @@ predict_loops (void)
/* Loop heuristics do not expect exit conditional to be inside /* Loop heuristics do not expect exit conditional to be inside
inner loop. We predict from innermost to outermost loop. */ inner loop. We predict from innermost to outermost loop. */
if (predicted_by_loop_heuristics_p (ex->src)) if (predicted_by_loop_heuristics_p (ex->src))
{
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; continue;
}
predict_extra_loop_exits (ex); predict_extra_loop_exits (ex);
if (number_of_iterations_exit (loop, ex, &niter_desc, false, false)) if (number_of_iterations_exit (loop, ex, &niter_desc, false, false))
niter = niter_desc.niter; niter = niter_desc.niter;
if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST) if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST)
niter = loop_niter_by_eval (loop, ex); 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) if (TREE_CODE (niter) == INTEGER_CST)
{ {
...@@ -1766,14 +1819,24 @@ predict_loops (void) ...@@ -1766,14 +1819,24 @@ predict_loops (void)
RDIV (REG_BR_PROB_BASE, RDIV (REG_BR_PROB_BASE,
REG_BR_PROB_BASE REG_BR_PROB_BASE
- predictor_info - predictor_info
[PRED_LOOP_EXIT].hitrate))) [recursion
? PRED_LOOP_EXIT_WITH_RECURSION
: PRED_LOOP_EXIT].hitrate)))
{ {
nitercst = nit.to_shwi (); nitercst = nit.to_shwi ();
predictor = PRED_LOOP_ITERATIONS_MAX; predictor = PRED_LOOP_ITERATIONS_MAX;
} }
else else
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Nothing known about exit %i->%i.\n",
ex->src->index, ex->dest->index);
continue; 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 /* If the prediction for number of iterations is zero, do not
predict the exit edges. */ predict the exit edges. */
if (nitercst == 0) if (nitercst == 0)
...@@ -1807,7 +1870,6 @@ predict_loops (void) ...@@ -1807,7 +1870,6 @@ predict_loops (void)
for (j = 0; j < loop->num_nodes; j++) for (j = 0; j < loop->num_nodes; j++)
{ {
int header_found = 0;
edge e; edge e;
edge_iterator ei; edge_iterator ei;
...@@ -1818,14 +1880,16 @@ predict_loops (void) ...@@ -1818,14 +1880,16 @@ predict_loops (void)
in the source language and are better to be handled in the source language and are better to be handled
separately. */ separately. */
if (predicted_by_p (bb, PRED_CONTINUE)) if (predicted_by_p (bb, PRED_CONTINUE))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "BB %i predicted by continue.\n",
bb->index);
continue; 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 /* If we already used more reliable loop exit predictors, do not
bother with PRED_LOOP_EXIT. */ bother with PRED_LOOP_EXIT. */
&& !predicted_by_loop_heuristics_p (bb)) if (!predicted_by_loop_heuristics_p (bb))
{ {
/* For loop with many exits we don't want to predict all exits /* For loop with many exits we don't want to predict all exits
with the pretty large probability, because if all exits are with the pretty large probability, because if all exits are
...@@ -1842,14 +1906,25 @@ predict_loops (void) ...@@ -1842,14 +1906,25 @@ predict_loops (void)
a wide loop. */ a wide loop. */
int probability = ((REG_BR_PROB_BASE 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); / n_exits);
if (probability < HITRATE (2)) if (probability < HITRATE (2))
probability = HITRATE (2); probability = HITRATE (2);
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest->index < NUM_FIXED_BLOCKS if (e->dest->index < NUM_FIXED_BLOCKS
|| !flow_bb_inside_loop_p (loop, e->dest)) || !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) if (loop_bound_var)
predict_iv_comparison (loop, bb, loop_bound_var, loop_iv_base, predict_iv_comparison (loop, bb, loop_bound_var, loop_iv_base,
...@@ -1910,7 +1985,9 @@ predict_loops (void) ...@@ -1910,7 +1985,9 @@ predict_loops (void)
if (!dominated_by_p (CDI_DOMINATORS, if (!dominated_by_p (CDI_DOMINATORS,
loop_outer (loop)->latch, loop->header)) loop_outer (loop)->latch, loop->header))
predict_paths_leading_to_edge (loop_preheader_edge (loop), predict_paths_leading_to_edge (loop_preheader_edge (loop),
PRED_LOOP_GUARD, recursion
? PRED_LOOP_GUARD_WITH_RECURSION
: PRED_LOOP_GUARD,
NOT_TAKEN, NOT_TAKEN,
loop_outer (loop)); loop_outer (loop));
} }
...@@ -1919,7 +1996,9 @@ predict_loops (void) ...@@ -1919,7 +1996,9 @@ predict_loops (void)
if (!dominated_by_p (CDI_DOMINATORS, if (!dominated_by_p (CDI_DOMINATORS,
loop_outer (loop)->latch, bb)) loop_outer (loop)->latch, bb))
predict_paths_leading_to (bb, predict_paths_leading_to (bb,
PRED_LOOP_GUARD, recursion
? PRED_LOOP_GUARD_WITH_RECURSION
: PRED_LOOP_GUARD,
NOT_TAKEN, NOT_TAKEN,
loop_outer (loop)); loop_outer (loop));
} }
...@@ -3367,6 +3446,15 @@ pass_profile::execute (function *fun) ...@@ -3367,6 +3446,15 @@ pass_profile::execute (function *fun)
gimple_dump_cfg (dump_file, dump_flags); gimple_dump_cfg (dump_file, dump_flags);
if (profile_status_for_fn (fun) == PROFILE_ABSENT) if (profile_status_for_fn (fun) == PROFILE_ABSENT)
profile_status_for_fn (fun) = PROFILE_GUESSED; 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; return 0;
} }
......
...@@ -92,6 +92,10 @@ DEF_PREDICTOR (PRED_COLD_FUNCTION, "cold function call", PROB_VERY_LIKELY, ...@@ -92,6 +92,10 @@ DEF_PREDICTOR (PRED_COLD_FUNCTION, "cold function call", PROB_VERY_LIKELY,
DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", HITRATE (85), DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", HITRATE (85),
PRED_FLAG_FIRST_MATCH) PRED_FLAG_FIRST_MATCH)
/* Same as LOOP_EXIT but for loops containing recursive call. */
DEF_PREDICTOR (PRED_LOOP_EXIT_WITH_RECURSION, "loop exit with recursion",
HITRATE (72), PRED_FLAG_FIRST_MATCH)
/* Edge causing loop to terminate by computing value used by later /* Edge causing loop to terminate by computing value used by later
conditional. */ conditional. */
DEF_PREDICTOR (PRED_LOOP_EXTRA_EXIT, "extra loop exit", HITRATE (83), DEF_PREDICTOR (PRED_LOOP_EXTRA_EXIT, "extra loop exit", HITRATE (83),
...@@ -105,14 +109,17 @@ DEF_PREDICTOR (PRED_TREE_POINTER, "pointer (on trees)", HITRATE (70), 0) ...@@ -105,14 +109,17 @@ DEF_PREDICTOR (PRED_TREE_POINTER, "pointer (on trees)", HITRATE (70), 0)
DEF_PREDICTOR (PRED_OPCODE_POSITIVE, "opcode values positive", HITRATE (64), 0) DEF_PREDICTOR (PRED_OPCODE_POSITIVE, "opcode values positive", HITRATE (64), 0)
DEF_PREDICTOR (PRED_OPCODE_NONEQUAL, "opcode values nonequal", HITRATE (66), 0) DEF_PREDICTOR (PRED_OPCODE_NONEQUAL, "opcode values nonequal", HITRATE (66), 0)
DEF_PREDICTOR (PRED_FPOPCODE, "fp_opcode", HITRATE (90), 0) DEF_PREDICTOR (PRED_FPOPCODE, "fp_opcode", HITRATE (90), 0)
DEF_PREDICTOR (PRED_TREE_OPCODE_POSITIVE, "opcode values positive (on trees)", HITRATE (64), 0) DEF_PREDICTOR (PRED_TREE_OPCODE_POSITIVE, "opcode values positive (on trees)",
DEF_PREDICTOR (PRED_TREE_OPCODE_NONEQUAL, "opcode values nonequal (on trees)", HITRATE (66), 0) HITRATE (64), 0)
DEF_PREDICTOR (PRED_TREE_OPCODE_NONEQUAL, "opcode values nonequal (on trees)",
HITRATE (66), 0)
DEF_PREDICTOR (PRED_TREE_FPOPCODE, "fp_opcode (on trees)", HITRATE (90), 0) DEF_PREDICTOR (PRED_TREE_FPOPCODE, "fp_opcode (on trees)", HITRATE (90), 0)
/* Branch guarding call is probably taken. */ /* Branch guarding call is probably taken. */
DEF_PREDICTOR (PRED_CALL, "call", HITRATE (67), 0) DEF_PREDICTOR (PRED_CALL, "call", HITRATE (67), 0)
/* Recursive calls are usually not taken or the function will recurse indefinitely. */ /* Recursive calls are usually not taken or the function will recurse
indefinitely. */
DEF_PREDICTOR (PRED_RECURSIVE_CALL, "recursive call", HITRATE (75), 0) DEF_PREDICTOR (PRED_RECURSIVE_CALL, "recursive call", HITRATE (75), 0)
/* Branch causing function to terminate is probably not taken. /* Branch causing function to terminate is probably not taken.
...@@ -159,6 +166,10 @@ DEF_PREDICTOR (PRED_LOOP_IV_COMPARE, "loop iv compare", PROB_VERY_LIKELY, ...@@ -159,6 +166,10 @@ DEF_PREDICTOR (PRED_LOOP_IV_COMPARE, "loop iv compare", PROB_VERY_LIKELY,
guess that cond is unlikely. */ guess that cond is unlikely. */
DEF_PREDICTOR (PRED_LOOP_GUARD, "loop guard", HITRATE (66), 0) DEF_PREDICTOR (PRED_LOOP_GUARD, "loop guard", HITRATE (66), 0)
/* Same but for loops containing recursion. */
DEF_PREDICTOR (PRED_LOOP_GUARD_WITH_RECURSION, "loop guard with recursion",
HITRATE (85), 0)
/* Branches to hot labels are likely. */ /* Branches to hot labels are likely. */
DEF_PREDICTOR (PRED_HOT_LABEL, "hot label", HITRATE (85), 0) DEF_PREDICTOR (PRED_HOT_LABEL, "hot label", HITRATE (85), 0)
......
2016-06-26 Jan Hubicka <hubicka@ucw.cz>
* gcc.dg/predict-12.c: New testcase.
2016-06-25 Jerry DeLisle <jvdelisle@gcc.gnu.org> 2016-06-25 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/71649 PR fortran/71649
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
int *a,n,m;
void test(void);
void
t(void)
{
int i,j;
for (i=0;i<n;i++)
if (a[i])
for (j=0;j<m;j++)
if (a[i+j])
t();
}
/* { dg-final { scan-tree-dump-times "loop guard with recursion" 1 "profile_estimate"} } */
/* { dg-final { scan-tree-dump-times "loop exit with recursion" 2 "profile_estimate"} } */
/* { dg-final { scan-tree-dump-times "recursive call" 1 "profile_estimate"} } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment