X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fpredict.c;h=732283d4c22e70c8c2d360227f9f52e3de081ca2;hb=942b4f9d8364e4ec230c2371ecabeb2b5e70caac;hp=e02f9f890c2fd417bbe94f3c29d37627a5bed436;hpb=fc29fdf52bb38c97e9a509b8a667cc81e741d740;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/predict.c b/gcc/predict.c index e02f9f890c2..732283d4c22 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 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -110,7 +110,8 @@ static const struct predictor_info predictor_info[]= { #undef DEF_PREDICTOR /* Return TRUE if frequency FREQ is considered to be hot. */ -static bool + +static inline bool maybe_hot_frequency_p (int freq) { if (!profile_info || !flag_branch_probabilities) @@ -127,16 +128,28 @@ maybe_hot_frequency_p (int freq) return true; } +/* Return TRUE if frequency FREQ is considered to be hot. */ + +static inline bool +maybe_hot_count_p (gcov_type count) +{ + if (profile_status != PROFILE_READ) + return true; + /* Code executed at most once is not hot. */ + if (profile_info->runs >= count) + return false; + return (count + > profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)); +} + /* Return true in case BB can be CPU intensive and should be optimized for maximal performance. */ bool maybe_hot_bb_p (const_basic_block bb) { - if (profile_info && flag_branch_probabilities - && (bb->count - < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) - return false; + if (profile_status == PROFILE_READ) + return maybe_hot_count_p (bb->count); return maybe_hot_frequency_p (bb->frequency); } @@ -167,30 +180,11 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge) bool maybe_hot_edge_p (edge e) { - if (profile_info && flag_branch_probabilities - && (e->count - < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) - return false; + if (profile_status == PROFILE_READ) + return maybe_hot_count_p (e->count); return maybe_hot_frequency_p (EDGE_FREQUENCY (e)); } -/* Return true in case BB is cold and should be optimized for size. */ - -bool -probably_cold_bb_p (const_basic_block bb) -{ - if (profile_info && flag_branch_probabilities - && (bb->count - < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) - return true; - if ((!profile_info || !flag_branch_probabilities) - && cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED) - return true; - if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)) - return true; - return false; -} - /* Return true in case BB is probably never executed. */ bool probably_never_executed_bb_p (const_basic_block bb) @@ -209,7 +203,8 @@ bool optimize_function_for_size_p (struct function *fun) { return (optimize_size - || fun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED); + || (fun && (fun->function_frequency + == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED))); } /* Return true when current function should always be optimized for speed. */ @@ -659,7 +654,7 @@ combine_predictions_for_insn (rtx insn, basic_block bb) rtx *pnote; rtx note; int best_probability = PROB_EVEN; - int best_predictor = END_PREDICTORS; + enum br_predictor best_predictor = END_PREDICTORS; int combined_probability = REG_BR_PROB_BASE / 2; int d; bool first_match = false; @@ -682,7 +677,8 @@ combine_predictions_for_insn (rtx insn, basic_block bb) for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) if (REG_NOTE_KIND (note) == REG_BR_PRED) { - int predictor = INTVAL (XEXP (XEXP (note, 0), 0)); + enum br_predictor predictor = ((enum br_predictor) + INTVAL (XEXP (XEXP (note, 0), 0))); int probability = INTVAL (XEXP (XEXP (note, 0), 1)); found = true; @@ -728,7 +724,8 @@ combine_predictions_for_insn (rtx insn, basic_block bb) { if (REG_NOTE_KIND (*pnote) == REG_BR_PRED) { - int predictor = INTVAL (XEXP (XEXP (*pnote, 0), 0)); + enum br_predictor predictor = ((enum br_predictor) + INTVAL (XEXP (XEXP (*pnote, 0), 0))); int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1)); dump_prediction (dump_file, predictor, probability, bb, @@ -770,7 +767,7 @@ static void combine_predictions_for_bb (basic_block bb) { int best_probability = PROB_EVEN; - int best_predictor = END_PREDICTORS; + enum br_predictor best_predictor = END_PREDICTORS; int combined_probability = REG_BR_PROB_BASE / 2; int d; bool first_match = false; @@ -818,15 +815,40 @@ combine_predictions_for_bb (basic_block bb) by predictor with smallest index. */ for (pred = (struct edge_prediction *) *preds; pred; pred = pred->ep_next) { - int predictor = pred->ep_predictor; + enum br_predictor predictor = pred->ep_predictor; int probability = pred->ep_probability; if (pred->ep_edge != first) probability = REG_BR_PROB_BASE - probability; found = true; + /* First match heuristics would be widly confused if we predicted + both directions. */ if (best_predictor > predictor) - best_probability = probability, best_predictor = predictor; + { + struct edge_prediction *pred2; + int prob = probability; + + for (pred2 = (struct edge_prediction *) *preds; pred2; pred2 = pred2->ep_next) + if (pred2 != pred && pred2->ep_predictor == pred->ep_predictor) + { + int probability2 = pred->ep_probability; + + if (pred2->ep_edge != first) + probability2 = REG_BR_PROB_BASE - probability2; + + if ((probability < REG_BR_PROB_BASE / 2) != + (probability2 < REG_BR_PROB_BASE / 2)) + break; + + /* If the same predictor later gave better result, go for it! */ + if ((probability >= REG_BR_PROB_BASE / 2 && (probability2 > probability)) + || (probability <= REG_BR_PROB_BASE / 2 && (probability2 < probability))) + prob = probability2; + } + if (!pred2) + best_probability = prob, best_predictor = predictor; + } d = (combined_probability * probability + (REG_BR_PROB_BASE - combined_probability) @@ -868,7 +890,7 @@ combine_predictions_for_bb (basic_block bb) { for (pred = (struct edge_prediction *) *preds; pred; pred = pred->ep_next) { - int predictor = pred->ep_predictor; + enum br_predictor predictor = pred->ep_predictor; int probability = pred->ep_probability; if (pred->ep_edge != EDGE_SUCC (bb, 0)) @@ -1526,6 +1548,16 @@ static void tree_bb_level_predictions (void) { basic_block bb; + bool has_return_edges = false; + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds) + if (!(e->flags & (EDGE_ABNORMAL | EDGE_FAKE | EDGE_EH))) + { + has_return_edges = true; + break; + } apply_return_prediction (); @@ -1540,7 +1572,8 @@ tree_bb_level_predictions (void) if (is_gimple_call (stmt)) { - if (gimple_call_flags (stmt) & ECF_NORETURN) + if ((gimple_call_flags (stmt) & ECF_NORETURN) + && has_return_edges) predict_paths_leading_to (bb, PRED_NORETURN, NOT_TAKEN); decl = gimple_call_fndecl (stmt); @@ -1604,6 +1637,7 @@ tree_estimate_probability (void) { edge e; edge_iterator ei; + gimple last; FOR_EACH_EDGE (e, ei, bb->succs) { @@ -1626,7 +1660,8 @@ tree_estimate_probability (void) && e->dest != EXIT_BLOCK_PTR && single_succ_p (e->dest) && single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR - && gimple_code (last_stmt (e->dest)) == GIMPLE_RETURN) + && (last = last_stmt (e->dest)) != NULL + && gimple_code (last) == GIMPLE_RETURN) { edge e1; edge_iterator ei1; @@ -2019,7 +2054,7 @@ estimate_bb_frequencies (void) basic_block bb; sreal freq_max; - if (!flag_branch_probabilities || !counts_to_freqs ()) + if (profile_status != PROFILE_READ || !counts_to_freqs ()) { static int real_values_initialized = 0; @@ -2152,7 +2187,7 @@ build_predict_expr (enum br_predictor predictor, enum prediction taken) { tree t = build1 (PREDICT_EXPR, void_type_node, build_int_cst (NULL, predictor)); - PREDICT_EXPR_OUTCOME (t) = taken; + SET_PREDICT_EXPR_OUTCOME (t, taken); return t; } @@ -2185,7 +2220,7 @@ struct gimple_opt_pass pass_strip_predict_hints = { { GIMPLE_PASS, - "", /* name */ + NULL, /* name */ NULL, /* gate */ strip_predict_hints, /* execute */ NULL, /* sub */