From 675d86b2a33c6783fd1c21ae44d47b4fee9e95ea Mon Sep 17 00:00:00 2001 From: spop Date: Wed, 12 Aug 2009 14:19:33 +0000 Subject: Recompute profile after Graphite. 2009-08-05 Sebastian Pop * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150684 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 ++++ gcc/ChangeLog.graphite | 14 ++++ gcc/Makefile.in | 2 +- gcc/graphite.c | 8 +- gcc/predict.c | 202 ++++++++++++++++++++++++++++--------------------- gcc/predict.h | 1 + 6 files changed, 151 insertions(+), 90 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b72bfd7a4e..a06a556e81b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-08-12 Sebastian Pop + + * 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 * graphite-clast-to-gimple.c (gloog): Add time to TV_GRAPHITE_CODE_GEN. diff --git a/gcc/ChangeLog.graphite b/gcc/ChangeLog.graphite index 3762a0b6261..3688216a3c4 100644 --- a/gcc/ChangeLog.graphite +++ b/gcc/ChangeLog.graphite @@ -1,3 +1,17 @@ +2009-08-05 Sebastian Pop + + * 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 * graphite-clast-to-gimple.c (gloog): Add time to TV_GRAPHITE_CODE_GEN. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 7951d29492f..3ab17715c24 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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) \ $(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_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 \ graphite-scop-detection.h graphite-clast-to-gimple.h \ graphite-poly.h graphite-sese-to-poly.h diff --git a/gcc/graphite.c b/gcc/graphite.c index 0c0b60793d8..819116d3c36 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "pointer-set.h" #include "gimple.h" #include "sese.h" +#include "predict.h" #ifdef HAVE_cloog @@ -229,7 +230,12 @@ static void graphite_finalize (bool 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 (); free_original_copy_tables (); diff --git a/gcc/predict.c b/gcc/predict.c index e3b4b83b863..6353fb96a56 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -916,8 +916,6 @@ predict_loops (void) loop_iterator li; struct loop *loop; - scev_initialize (); - /* Try to predict out blocks in a loop that are not part of a natural loop. */ FOR_EACH_LOOP (li, loop, 0) @@ -1040,8 +1038,6 @@ predict_loops (void) /* Free basic blocks from get_loop_body. */ free (bbs); } - - scev_finalize (); } /* 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 -/* Predict branch probabilities and estimate profile of the tree CFG. */ -static unsigned int +/* Predict branch probabilities and estimate profile for basic block BB. */ + +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) { 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 (); connect_infinite_loops_to_exit (); /* 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 (); tree_bb_level_predictions (); - - mark_irreducible_loops (); record_loop_exits (); + if (number_of_loops () > 1) predict_loops (); FOR_EACH_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); - } + tree_estimate_probability_bb (bb); - /* 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) combine_predictions_for_bb (bb); @@ -1722,6 +1723,31 @@ tree_estimate_probability (void) estimate_bb_frequencies (); free_dominance_info (CDI_POST_DOMINATORS); 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 (); if (dump_file && (dump_flags & TDF_DETAILS)) gimple_dump_cfg (dump_file, dump_flags); @@ -2203,7 +2229,7 @@ struct gimple_opt_pass pass_profile = GIMPLE_PASS, "profile", /* name */ gate_estimate_probability, /* gate */ - tree_estimate_probability, /* execute */ + tree_estimate_probability_driver, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ diff --git a/gcc/predict.h b/gcc/predict.h index e115bb511f8..0e040410768 100644 --- a/gcc/predict.h +++ b/gcc/predict.h @@ -40,5 +40,6 @@ extern int counts_to_freqs (void); extern void estimate_bb_frequencies (void); extern const char *predictor_name (enum br_predictor); extern tree build_predict_expr (enum br_predictor, enum prediction); +extern void tree_estimate_probability (void); #endif /* GCC_PREDICT_H */ -- cgit v1.2.3