X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fpredict.c;h=f00424c3b1c00377d240e77397addc59c5e8a645;hb=5f0d36be6d31b78172bb45c0dbba9b1dc7f6ae84;hp=5d61140e4e679d7ada5058cde521134a6760055d;hpb=555e8b05fce3ebfad73e482925e3fc55e8d2ae74;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/predict.c b/gcc/predict.c index 5d61140e4e6..f00424c3b1c 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -1,5 +1,5 @@ /* Branch prediction routines for the GNU compiler. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -43,7 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "function.h" #include "except.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "recog.h" #include "expr.h" #include "predict.h" @@ -77,7 +77,7 @@ static sreal real_zero, real_one, real_almost_one, real_br_prob_base, static void combine_predictions_for_insn (rtx, basic_block); static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int); static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction); -static void choose_function_section (void); +static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction); static bool can_predict_insn_p (const_rtx); /* Information we hold about each branch predictor. @@ -126,7 +126,7 @@ maybe_hot_frequency_p (int freq) if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE && freq <= (ENTRY_BLOCK_PTR->frequency * 2 / 3)) return false; - if (freq < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)) + if (freq < ENTRY_BLOCK_PTR->frequency / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)) return false; return true; } @@ -388,6 +388,15 @@ rtl_predicted_by_p (const_basic_block bb, enum br_predictor predictor) static struct pointer_map_t *bb_predictions; +/* Structure representing predictions in tree level. */ + +struct edge_prediction { + struct edge_prediction *ep_next; + edge ep_edge; + enum br_predictor ep_predictor; + int ep_probability; +}; + /* Return true if the one of outgoing edges is already predicted by PREDICTOR. */ @@ -941,7 +950,7 @@ predict_loops (void) exits = get_loop_exit_edges (loop); n_exits = VEC_length (edge, exits); - for (j = 0; VEC_iterate (edge, exits, j, ex); j++) + FOR_EACH_VEC_ELT (edge, exits, j, ex) { tree niter = NULL; HOST_WIDE_INT nitercst; @@ -1179,9 +1188,8 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code, tree op1, bitma def = SSA_NAME_DEF_STMT (op0); /* If we were already here, break the infinite cycle. */ - if (bitmap_bit_p (visited, SSA_NAME_VERSION (op0))) + if (!bitmap_set_bit (visited, SSA_NAME_VERSION (op0))) return NULL; - bitmap_set_bit (visited, SSA_NAME_VERSION (op0)); if (gimple_code (def) == GIMPLE_PHI) { @@ -1329,9 +1337,17 @@ strip_predict_hints (void) && gimple_call_num_args (stmt) == 2) { var = gimple_call_lhs (stmt); - ass_stmt = gimple_build_assign (var, gimple_call_arg (stmt, 0)); - - gsi_replace (&bi, ass_stmt, true); + if (var) + { + ass_stmt + = gimple_build_assign (var, gimple_call_arg (stmt, 0)); + gsi_replace (&bi, ass_stmt, true); + } + else + { + gsi_remove (&bi, true); + continue; + } } } gsi_next (&bi); @@ -1543,8 +1559,8 @@ apply_return_prediction (void) { pred = return_prediction (PHI_ARG_DEF (phi, i), &direction); if (pred != PRED_NO_PREDICTION) - predict_paths_leading_to (gimple_phi_arg_edge (phi, i)->src, pred, - direction); + predict_paths_leading_to_edge (gimple_phi_arg_edge (phi, i), pred, + direction); } } @@ -1774,7 +1790,8 @@ tree_estimate_probability_driver (void) static void predict_paths_for_bb (basic_block cur, basic_block bb, enum br_predictor pred, - enum prediction taken) + enum prediction taken, + bitmap visited) { edge e; edge_iterator ei; @@ -1786,13 +1803,42 @@ predict_paths_for_bb (basic_block cur, basic_block bb, if (e->src->index >= NUM_FIXED_BLOCKS && !dominated_by_p (CDI_POST_DOMINATORS, e->src, bb)) { + edge e2; + edge_iterator ei2; + bool found = false; + + /* Ignore fake edges and eh, we predict them as not taken anyway. */ + if (e->flags & (EDGE_EH | EDGE_FAKE)) + continue; gcc_assert (bb == cur || dominated_by_p (CDI_POST_DOMINATORS, cur, bb)); - predict_edge_def (e, pred, taken); + + /* See if there is an edge from e->src that is not abnormal + and does not lead to BB. */ + FOR_EACH_EDGE (e2, ei2, e->src->succs) + if (e2 != e + && !(e2->flags & (EDGE_EH | EDGE_FAKE)) + && !dominated_by_p (CDI_POST_DOMINATORS, e2->dest, bb)) + { + found = true; + break; + } + + /* If there is non-abnormal path leaving e->src, predict edge + using predictor. Otherwise we need to look for paths + leading to e->src. + + The second may lead to infinite loop in the case we are predicitng + regions that are only reachable by abnormal edges. We simply + prevent visiting given BB twice. */ + if (found) + predict_edge_def (e, pred, taken); + else if (bitmap_set_bit (visited, e->src->index)) + predict_paths_for_bb (e->src, e->src, pred, taken, visited); } for (son = first_dom_son (CDI_POST_DOMINATORS, cur); son; son = next_dom_son (CDI_POST_DOMINATORS, son)) - predict_paths_for_bb (son, bb, pred, taken); + predict_paths_for_bb (son, bb, pred, taken, visited); } /* Sets branch probabilities according to PREDiction and @@ -1802,7 +1848,38 @@ static void predict_paths_leading_to (basic_block bb, enum br_predictor pred, enum prediction taken) { - predict_paths_for_bb (bb, bb, pred, taken); + bitmap visited = BITMAP_ALLOC (NULL); + predict_paths_for_bb (bb, bb, pred, taken, visited); + BITMAP_FREE (visited); +} + +/* Like predict_paths_leading_to but take edge instead of basic block. */ + +static void +predict_paths_leading_to_edge (edge e, enum br_predictor pred, + enum prediction taken) +{ + bool has_nonloop_edge = false; + edge_iterator ei; + edge e2; + + basic_block bb = e->src; + FOR_EACH_EDGE (e2, ei, bb->succs) + if (e2->dest != e->src && e2->dest != e->dest + && !(e->flags & (EDGE_EH | EDGE_FAKE)) + && !dominated_by_p (CDI_POST_DOMINATORS, e->src, e2->dest)) + { + has_nonloop_edge = true; + break; + } + if (!has_nonloop_edge) + { + bitmap visited = BITMAP_ALLOC (NULL); + predict_paths_for_bb (bb, bb, pred, taken, visited); + BITMAP_FREE (visited); + } + else + predict_edge_def (e, pred, taken); } /* This is used to carry information about basic blocks. It is @@ -2152,8 +2229,6 @@ estimate_bb_frequencies (void) free_aux_for_edges (); } compute_function_frequency (); - if (flag_reorder_functions) - choose_function_section (); } /* Decide whether function is hot, cold or unlikely executed. */ @@ -2162,6 +2237,11 @@ compute_function_frequency (void) { basic_block bb; struct cgraph_node *node = cgraph_node (current_function_decl); + if (DECL_STATIC_CONSTRUCTOR (current_function_decl) + || MAIN_NAME_P (DECL_NAME (current_function_decl))) + node->only_called_at_startup = true; + if (DECL_STATIC_DESTRUCTOR (current_function_decl)) + node->only_called_at_exit = true; if (!profile_info || !flag_branch_probabilities) { @@ -2194,35 +2274,6 @@ compute_function_frequency (void) } } -/* Choose appropriate section for the function. */ -static void -choose_function_section (void) -{ - struct cgraph_node *node = cgraph_node (current_function_decl); - if (DECL_SECTION_NAME (current_function_decl) - || !targetm.have_named_sections - /* Theoretically we can split the gnu.linkonce text section too, - but this requires more work as the frequency needs to match - for all generated objects so we need to merge the frequency - of all instances. For now just never set frequency for these. */ - || DECL_ONE_ONLY (current_function_decl)) - return; - - /* If we are doing the partitioning optimization, let the optimization - choose the correct section into which to put things. */ - - if (flag_reorder_blocks_and_partition) - return; - - if (node->frequency == NODE_FREQUENCY_HOT) - DECL_SECTION_NAME (current_function_decl) = - build_string (strlen (HOT_TEXT_SECTION_NAME), HOT_TEXT_SECTION_NAME); - if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED) - DECL_SECTION_NAME (current_function_decl) = - build_string (strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME), - UNLIKELY_EXECUTED_TEXT_SECTION_NAME); -} - static bool gate_estimate_probability (void) { @@ -2291,6 +2342,7 @@ struct gimple_opt_pass pass_strip_predict_hints = void rebuild_frequencies (void) { + timevar_push (TV_REBUILD_FREQUENCIES); if (profile_status == PROFILE_GUESSED) { loop_optimizer_init (0); @@ -2305,4 +2357,5 @@ rebuild_frequencies (void) counts_to_freqs (); else gcc_unreachable (); + timevar_pop (TV_REBUILD_FREQUENCIES); }