mirror of git://gcc.gnu.org/git/gcc.git
Recompute profile after Graphite.
2009-08-05 Sebastian Pop <sebastian.pop@amd.com> * Makefile.in (graphite.o): Depends on PREDICT_H. * graphite.c: Include predict.h. (graphite_finalize): Call tree_estimate_probability. * predict.c (predict_loops): Do not call scev_initialize and scev_finalize. (tree_estimate_probability_bb): New. (tree_estimate_probability): Do not initialize loops: move that code to the driver. Call tree_estimate_probability_bb. (tree_estimate_probability_driver): New. (pass_profile): Use tree_estimate_probability_driver. * predict.h (tree_estimate_probability): Declared. From-SVN: r150684
This commit is contained in:
parent
87d4d0ee25
commit
8e88f9fddf
|
@ -1,3 +1,17 @@
|
||||||
|
2009-08-12 Sebastian Pop <sebastian.pop@amd.com>
|
||||||
|
|
||||||
|
* Makefile.in (graphite.o): Depends on PREDICT_H.
|
||||||
|
* graphite.c: Include predict.h.
|
||||||
|
(graphite_finalize): Call tree_estimate_probability.
|
||||||
|
* predict.c (predict_loops): Do not call scev_initialize and
|
||||||
|
scev_finalize.
|
||||||
|
(tree_estimate_probability_bb): New.
|
||||||
|
(tree_estimate_probability): Do not initialize loops: move that
|
||||||
|
code to the driver. Call tree_estimate_probability_bb.
|
||||||
|
(tree_estimate_probability_driver): New.
|
||||||
|
(pass_profile): Use tree_estimate_probability_driver.
|
||||||
|
* predict.h (tree_estimate_probability): Declared.
|
||||||
|
|
||||||
2009-08-12 Sebastian Pop <sebastian.pop@amd.com>
|
2009-08-12 Sebastian Pop <sebastian.pop@amd.com>
|
||||||
|
|
||||||
* graphite-clast-to-gimple.c (gloog): Add time to TV_GRAPHITE_CODE_GEN.
|
* graphite-clast-to-gimple.c (gloog): Add time to TV_GRAPHITE_CODE_GEN.
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
2009-08-05 Sebastian Pop <sebastian.pop@amd.com>
|
||||||
|
|
||||||
|
* Makefile.in (graphite.o): Depends on PREDICT_H.
|
||||||
|
* graphite.c: Include predict.h.
|
||||||
|
(graphite_finalize): Call tree_estimate_probability.
|
||||||
|
* predict.c (predict_loops): Do not call scev_initialize and
|
||||||
|
scev_finalize.
|
||||||
|
(tree_estimate_probability_bb): New.
|
||||||
|
(tree_estimate_probability): Do not initialize loops: move that
|
||||||
|
code to the driver. Call tree_estimate_probability_bb.
|
||||||
|
(tree_estimate_probability_driver): New.
|
||||||
|
(pass_profile): Use tree_estimate_probability_driver.
|
||||||
|
* predict.h (tree_estimate_probability): Declared.
|
||||||
|
|
||||||
2009-08-05 Sebastian Pop <sebastian.pop@amd.com>
|
2009-08-05 Sebastian Pop <sebastian.pop@amd.com>
|
||||||
|
|
||||||
* graphite-clast-to-gimple.c (gloog): Add time to TV_GRAPHITE_CODE_GEN.
|
* graphite-clast-to-gimple.c (gloog): Add time to TV_GRAPHITE_CODE_GEN.
|
||||||
|
|
|
@ -2466,7 +2466,7 @@ sese.o: sese.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||||
graphite.o: graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
graphite.o: graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||||
$(GGC_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TOPLEV_H) \
|
$(GGC_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TOPLEV_H) \
|
||||||
$(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) $(GIMPLE_H) \
|
$(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) $(GIMPLE_H) \
|
||||||
$(TREE_DATA_REF_H) tree-pass.h graphite.h \
|
$(PREDICT_H) $(TREE_DATA_REF_H) tree-pass.h graphite.h \
|
||||||
pointer-set.h value-prof.h graphite-ppl.h sese.h \
|
pointer-set.h value-prof.h graphite-ppl.h sese.h \
|
||||||
graphite-scop-detection.h graphite-clast-to-gimple.h \
|
graphite-scop-detection.h graphite-clast-to-gimple.h \
|
||||||
graphite-poly.h graphite-sese-to-poly.h
|
graphite-poly.h graphite-sese-to-poly.h
|
||||||
|
|
|
@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "pointer-set.h"
|
#include "pointer-set.h"
|
||||||
#include "gimple.h"
|
#include "gimple.h"
|
||||||
#include "sese.h"
|
#include "sese.h"
|
||||||
|
#include "predict.h"
|
||||||
|
|
||||||
#ifdef HAVE_cloog
|
#ifdef HAVE_cloog
|
||||||
|
|
||||||
|
@ -229,7 +230,12 @@ static void
|
||||||
graphite_finalize (bool need_cfg_cleanup_p)
|
graphite_finalize (bool need_cfg_cleanup_p)
|
||||||
{
|
{
|
||||||
if (need_cfg_cleanup_p)
|
if (need_cfg_cleanup_p)
|
||||||
cleanup_tree_cfg ();
|
{
|
||||||
|
cleanup_tree_cfg ();
|
||||||
|
profile_status = PROFILE_ABSENT;
|
||||||
|
release_recorded_exits ();
|
||||||
|
tree_estimate_probability ();
|
||||||
|
}
|
||||||
|
|
||||||
cloog_finalize ();
|
cloog_finalize ();
|
||||||
free_original_copy_tables ();
|
free_original_copy_tables ();
|
||||||
|
|
202
gcc/predict.c
202
gcc/predict.c
|
@ -916,8 +916,6 @@ predict_loops (void)
|
||||||
loop_iterator li;
|
loop_iterator li;
|
||||||
struct loop *loop;
|
struct loop *loop;
|
||||||
|
|
||||||
scev_initialize ();
|
|
||||||
|
|
||||||
/* 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. */
|
||||||
FOR_EACH_LOOP (li, loop, 0)
|
FOR_EACH_LOOP (li, loop, 0)
|
||||||
|
@ -1040,8 +1038,6 @@ predict_loops (void)
|
||||||
/* Free basic blocks from get_loop_body. */
|
/* Free basic blocks from get_loop_body. */
|
||||||
free (bbs);
|
free (bbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
scev_finalize ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to predict probabilities of BB outgoing edges using local
|
/* Attempt to predict probabilities of BB outgoing edges using local
|
||||||
|
@ -1608,16 +1604,96 @@ assert_is_empty (const void *key ATTRIBUTE_UNUSED, void **value,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Predict branch probabilities and estimate profile of the tree CFG. */
|
/* Predict branch probabilities and estimate profile for basic block BB. */
|
||||||
static unsigned int
|
|
||||||
|
static void
|
||||||
|
tree_estimate_probability_bb (basic_block bb)
|
||||||
|
{
|
||||||
|
edge e;
|
||||||
|
edge_iterator ei;
|
||||||
|
gimple last;
|
||||||
|
|
||||||
|
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||||
|
{
|
||||||
|
/* Predict early returns to be probable, as we've already taken
|
||||||
|
care for error returns and other cases are often used for
|
||||||
|
fast paths through function.
|
||||||
|
|
||||||
|
Since we've already removed the return statements, we are
|
||||||
|
looking for CFG like:
|
||||||
|
|
||||||
|
if (conditional)
|
||||||
|
{
|
||||||
|
..
|
||||||
|
goto return_block
|
||||||
|
}
|
||||||
|
some other blocks
|
||||||
|
return_block:
|
||||||
|
return_stmt. */
|
||||||
|
if (e->dest != bb->next_bb
|
||||||
|
&& e->dest != EXIT_BLOCK_PTR
|
||||||
|
&& single_succ_p (e->dest)
|
||||||
|
&& single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR
|
||||||
|
&& (last = last_stmt (e->dest)) != NULL
|
||||||
|
&& gimple_code (last) == GIMPLE_RETURN)
|
||||||
|
{
|
||||||
|
edge e1;
|
||||||
|
edge_iterator ei1;
|
||||||
|
|
||||||
|
if (single_succ_p (bb))
|
||||||
|
{
|
||||||
|
FOR_EACH_EDGE (e1, ei1, bb->preds)
|
||||||
|
if (!predicted_by_p (e1->src, PRED_NULL_RETURN)
|
||||||
|
&& !predicted_by_p (e1->src, PRED_CONST_RETURN)
|
||||||
|
&& !predicted_by_p (e1->src, PRED_NEGATIVE_RETURN))
|
||||||
|
predict_edge_def (e1, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!predicted_by_p (e->src, PRED_NULL_RETURN)
|
||||||
|
&& !predicted_by_p (e->src, PRED_CONST_RETURN)
|
||||||
|
&& !predicted_by_p (e->src, PRED_NEGATIVE_RETURN))
|
||||||
|
predict_edge_def (e, PRED_TREE_EARLY_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
|
||||||
|
&& dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
|
||||||
|
&& !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
|
||||||
|
{
|
||||||
|
gimple_stmt_iterator bi;
|
||||||
|
|
||||||
|
/* 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 (bi = gsi_start_bb (e->dest); !gsi_end_p (bi);
|
||||||
|
gsi_next (&bi))
|
||||||
|
{
|
||||||
|
gimple stmt = gsi_stmt (bi);
|
||||||
|
if (is_gimple_call (stmt)
|
||||||
|
/* Constant and pure calls are hardly used to signalize
|
||||||
|
something exceptional. */
|
||||||
|
&& gimple_has_side_effects (stmt))
|
||||||
|
{
|
||||||
|
predict_edge_def (e, PRED_CALL, NOT_TAKEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree_predict_by_opcode (bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Predict branch probabilities and estimate profile of the tree CFG.
|
||||||
|
This function can be called from the loop optimizers to recompute
|
||||||
|
the profile information. */
|
||||||
|
|
||||||
|
void
|
||||||
tree_estimate_probability (void)
|
tree_estimate_probability (void)
|
||||||
{
|
{
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
|
|
||||||
loop_optimizer_init (0);
|
|
||||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
||||||
flow_loops_dump (dump_file, NULL, 0);
|
|
||||||
|
|
||||||
add_noreturn_fake_exit_edges ();
|
add_noreturn_fake_exit_edges ();
|
||||||
connect_infinite_loops_to_exit ();
|
connect_infinite_loops_to_exit ();
|
||||||
/* We use loop_niter_by_eval, which requires that the loops have
|
/* We use loop_niter_by_eval, which requires that the loops have
|
||||||
|
@ -1627,89 +1703,14 @@ tree_estimate_probability (void)
|
||||||
|
|
||||||
bb_predictions = pointer_map_create ();
|
bb_predictions = pointer_map_create ();
|
||||||
tree_bb_level_predictions ();
|
tree_bb_level_predictions ();
|
||||||
|
|
||||||
mark_irreducible_loops ();
|
|
||||||
record_loop_exits ();
|
record_loop_exits ();
|
||||||
|
|
||||||
if (number_of_loops () > 1)
|
if (number_of_loops () > 1)
|
||||||
predict_loops ();
|
predict_loops ();
|
||||||
|
|
||||||
FOR_EACH_BB (bb)
|
FOR_EACH_BB (bb)
|
||||||
{
|
tree_estimate_probability_bb (bb);
|
||||||
edge e;
|
|
||||||
edge_iterator ei;
|
|
||||||
gimple last;
|
|
||||||
|
|
||||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
|
||||||
{
|
|
||||||
/* Predict early returns to be probable, as we've already taken
|
|
||||||
care for error returns and other cases are often used for
|
|
||||||
fast paths through function.
|
|
||||||
|
|
||||||
Since we've already removed the return statements, we are
|
|
||||||
looking for CFG like:
|
|
||||||
|
|
||||||
if (conditional)
|
|
||||||
{
|
|
||||||
..
|
|
||||||
goto return_block
|
|
||||||
}
|
|
||||||
some other blocks
|
|
||||||
return_block:
|
|
||||||
return_stmt. */
|
|
||||||
if (e->dest != bb->next_bb
|
|
||||||
&& e->dest != EXIT_BLOCK_PTR
|
|
||||||
&& single_succ_p (e->dest)
|
|
||||||
&& single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR
|
|
||||||
&& (last = last_stmt (e->dest)) != NULL
|
|
||||||
&& gimple_code (last) == GIMPLE_RETURN)
|
|
||||||
{
|
|
||||||
edge e1;
|
|
||||||
edge_iterator ei1;
|
|
||||||
|
|
||||||
if (single_succ_p (bb))
|
|
||||||
{
|
|
||||||
FOR_EACH_EDGE (e1, ei1, bb->preds)
|
|
||||||
if (!predicted_by_p (e1->src, PRED_NULL_RETURN)
|
|
||||||
&& !predicted_by_p (e1->src, PRED_CONST_RETURN)
|
|
||||||
&& !predicted_by_p (e1->src, PRED_NEGATIVE_RETURN))
|
|
||||||
predict_edge_def (e1, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (!predicted_by_p (e->src, PRED_NULL_RETURN)
|
|
||||||
&& !predicted_by_p (e->src, PRED_CONST_RETURN)
|
|
||||||
&& !predicted_by_p (e->src, PRED_NEGATIVE_RETURN))
|
|
||||||
predict_edge_def (e, PRED_TREE_EARLY_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
|
|
||||||
&& dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
|
|
||||||
&& !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
|
|
||||||
{
|
|
||||||
gimple_stmt_iterator bi;
|
|
||||||
|
|
||||||
/* 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 (bi = gsi_start_bb (e->dest); !gsi_end_p (bi);
|
|
||||||
gsi_next (&bi))
|
|
||||||
{
|
|
||||||
gimple stmt = gsi_stmt (bi);
|
|
||||||
if (is_gimple_call (stmt)
|
|
||||||
/* Constant and pure calls are hardly used to signalize
|
|
||||||
something exceptional. */
|
|
||||||
&& gimple_has_side_effects (stmt))
|
|
||||||
{
|
|
||||||
predict_edge_def (e, PRED_CALL, NOT_TAKEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tree_predict_by_opcode (bb);
|
|
||||||
}
|
|
||||||
FOR_EACH_BB (bb)
|
FOR_EACH_BB (bb)
|
||||||
combine_predictions_for_bb (bb);
|
combine_predictions_for_bb (bb);
|
||||||
|
|
||||||
|
@ -1722,6 +1723,31 @@ tree_estimate_probability (void)
|
||||||
estimate_bb_frequencies ();
|
estimate_bb_frequencies ();
|
||||||
free_dominance_info (CDI_POST_DOMINATORS);
|
free_dominance_info (CDI_POST_DOMINATORS);
|
||||||
remove_fake_exit_edges ();
|
remove_fake_exit_edges ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Predict branch probabilities and estimate profile of the tree CFG.
|
||||||
|
This is the driver function for PASS_PROFILE. */
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
tree_estimate_probability_driver (void)
|
||||||
|
{
|
||||||
|
unsigned nb_loops;
|
||||||
|
|
||||||
|
loop_optimizer_init (0);
|
||||||
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||||
|
flow_loops_dump (dump_file, NULL, 0);
|
||||||
|
|
||||||
|
mark_irreducible_loops ();
|
||||||
|
|
||||||
|
nb_loops = number_of_loops ();
|
||||||
|
if (nb_loops > 1)
|
||||||
|
scev_initialize ();
|
||||||
|
|
||||||
|
tree_estimate_probability ();
|
||||||
|
|
||||||
|
if (nb_loops > 1)
|
||||||
|
scev_finalize ();
|
||||||
|
|
||||||
loop_optimizer_finalize ();
|
loop_optimizer_finalize ();
|
||||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||||
gimple_dump_cfg (dump_file, dump_flags);
|
gimple_dump_cfg (dump_file, dump_flags);
|
||||||
|
@ -2203,7 +2229,7 @@ struct gimple_opt_pass pass_profile =
|
||||||
GIMPLE_PASS,
|
GIMPLE_PASS,
|
||||||
"profile", /* name */
|
"profile", /* name */
|
||||||
gate_estimate_probability, /* gate */
|
gate_estimate_probability, /* gate */
|
||||||
tree_estimate_probability, /* execute */
|
tree_estimate_probability_driver, /* execute */
|
||||||
NULL, /* sub */
|
NULL, /* sub */
|
||||||
NULL, /* next */
|
NULL, /* next */
|
||||||
0, /* static_pass_number */
|
0, /* static_pass_number */
|
||||||
|
|
|
@ -40,5 +40,6 @@ extern int counts_to_freqs (void);
|
||||||
extern void estimate_bb_frequencies (void);
|
extern void estimate_bb_frequencies (void);
|
||||||
extern const char *predictor_name (enum br_predictor);
|
extern const char *predictor_name (enum br_predictor);
|
||||||
extern tree build_predict_expr (enum br_predictor, enum prediction);
|
extern tree build_predict_expr (enum br_predictor, enum prediction);
|
||||||
|
extern void tree_estimate_probability (void);
|
||||||
|
|
||||||
#endif /* GCC_PREDICT_H */
|
#endif /* GCC_PREDICT_H */
|
||||||
|
|
Loading…
Reference in New Issue