diff options
Diffstat (limited to 'gcc/predict.c')
-rw-r--r-- | gcc/predict.c | 274 |
1 files changed, 184 insertions, 90 deletions
diff --git a/gcc/predict.c b/gcc/predict.c index 5896c10..f457817 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -45,7 +45,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "recog.h" #include "expr.h" #include "predict.h" +#include "profile.h" #include "real.h" +#include "params.h" +#include "target.h" /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE, 0.5, REAL_BB_FREQ_MAX. */ @@ -75,6 +78,8 @@ static void process_note_predictions PARAMS ((basic_block, int *, int *, static void process_note_prediction PARAMS ((basic_block, int *, int *, sbitmap *, int, int)); static bool last_basic_block_p PARAMS ((basic_block)); +static void compute_function_frequency PARAMS ((void)); +static void choose_function_section PARAMS ((void)); /* Information we hold about each branch predictor. Filled using information from predict.def. */ @@ -103,6 +108,54 @@ static const struct predictor_info predictor_info[]= { {NULL, 0, 0} }; #undef DEF_PREDICTOR + +/* Return true in case BB can be CPU intensive and should be optimized + for maximal perofmrance. */ + +bool +maybe_hot_bb_p (bb) + basic_block bb; +{ + if (profile_info.count_profiles_merged + && flag_branch_probabilities + && (bb->count + < profile_info.max_counter_in_program + / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) + return false; + if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)) + return false; + return true; +} + +/* Return true in case BB is cold and should be optimized for size. */ + +bool +probably_cold_bb_p (bb) + basic_block bb; +{ + if (profile_info.count_profiles_merged + && flag_branch_probabilities + && (bb->count + < profile_info.max_counter_in_program + / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) + 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 (bb) + basic_block bb; +{ + if (profile_info.count_profiles_merged + && flag_branch_probabilities) + return ((bb->count + profile_info.count_profiles_merged / 2) + / profile_info.count_profiles_merged) == 0; + return false; +} + /* Return true if the one of outgoing edges is already predicted by PREDICTOR. */ @@ -1095,118 +1148,159 @@ estimate_bb_frequencies (loops) REAL_VALUE_TYPE freq_max; enum machine_mode double_mode = TYPE_MODE (double_type_node); - REAL_VALUE_FROM_INT (real_zero, 0, 0, double_mode); - REAL_VALUE_FROM_INT (real_one, 1, 0, double_mode); - REAL_VALUE_FROM_INT (real_br_prob_base, REG_BR_PROB_BASE, 0, double_mode); - REAL_VALUE_FROM_INT (real_bb_freq_max, BB_FREQ_MAX, 0, double_mode); - REAL_VALUE_FROM_INT (real_one_half, 2, 0, double_mode); + if (flag_branch_probabilities) + counts_to_freqs (); + else + { + REAL_VALUE_FROM_INT (real_zero, 0, 0, double_mode); + REAL_VALUE_FROM_INT (real_one, 1, 0, double_mode); + REAL_VALUE_FROM_INT (real_br_prob_base, REG_BR_PROB_BASE, 0, double_mode); + REAL_VALUE_FROM_INT (real_bb_freq_max, BB_FREQ_MAX, 0, double_mode); + REAL_VALUE_FROM_INT (real_one_half, 2, 0, double_mode); - REAL_ARITHMETIC (real_one_half, RDIV_EXPR, real_one, real_one_half); + REAL_ARITHMETIC (real_one_half, RDIV_EXPR, real_one, real_one_half); - REAL_ARITHMETIC (real_almost_one, RDIV_EXPR, real_one, real_br_prob_base); - REAL_ARITHMETIC (real_almost_one, MINUS_EXPR, real_one, real_almost_one); + REAL_ARITHMETIC (real_almost_one, RDIV_EXPR, real_one, real_br_prob_base); + REAL_ARITHMETIC (real_almost_one, MINUS_EXPR, real_one, real_almost_one); - mark_dfs_back_edges (); - if (flag_branch_probabilities) - { - counts_to_freqs (); - return; - } + mark_dfs_back_edges (); + /* Fill in the probability values in flowgraph based on the REG_BR_PROB + notes. */ + for (i = 0; i < n_basic_blocks; i++) + { + rtx last_insn = BLOCK_END (i); - /* Fill in the probability values in flowgraph based on the REG_BR_PROB - notes. */ - for (i = 0; i < n_basic_blocks; i++) - { - rtx last_insn = BLOCK_END (i); + if (GET_CODE (last_insn) != JUMP_INSN || !any_condjump_p (last_insn) + /* Avoid handling of conditional jumps jumping to fallthru edge. */ + || BASIC_BLOCK (i)->succ->succ_next == NULL) + { + /* We can predict only conditional jumps at the moment. + Expect each edge to be equally probable. + ?? In the future we want to make abnormal edges improbable. */ + int nedges = 0; + edge e; - if (GET_CODE (last_insn) != JUMP_INSN || !any_condjump_p (last_insn) - /* Avoid handling of conditional jumps jumping to fallthru edge. */ - || BASIC_BLOCK (i)->succ->succ_next == NULL) + for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next) + { + nedges++; + if (e->probability != 0) + break; + } + if (!e) + for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next) + e->probability = (REG_BR_PROB_BASE + nedges / 2) / nedges; + } + } + + ENTRY_BLOCK_PTR->succ->probability = REG_BR_PROB_BASE; + + /* Set up block info for each basic block. */ + alloc_aux_for_blocks (sizeof (struct block_info_def)); + alloc_aux_for_edges (sizeof (struct edge_info_def)); + for (i = -2; i < n_basic_blocks; i++) { - /* We can predict only conditional jumps at the moment. - Expect each edge to be equally probable. - ?? In the future we want to make abnormal edges improbable. */ - int nedges = 0; edge e; + basic_block bb; - for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next) + if (i == -2) + bb = ENTRY_BLOCK_PTR; + else if (i == -1) + bb = EXIT_BLOCK_PTR; + else + bb = BASIC_BLOCK (i); + + BLOCK_INFO (bb)->tovisit = 0; + for (e = bb->succ; e; e = e->succ_next) { - nedges++; - if (e->probability != 0) - break; + + REAL_VALUE_FROM_INT (EDGE_INFO (e)->back_edge_prob, + e->probability, 0, double_mode); + REAL_ARITHMETIC (EDGE_INFO (e)->back_edge_prob, + RDIV_EXPR, EDGE_INFO (e)->back_edge_prob, + real_br_prob_base); } - if (!e) - for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next) - e->probability = (REG_BR_PROB_BASE + nedges / 2) / nedges; } - } - ENTRY_BLOCK_PTR->succ->probability = REG_BR_PROB_BASE; + /* First compute probabilities locally for each loop from innermost + to outermost to examine probabilities for back edges. */ + estimate_loops_at_level (loops->tree_root); - /* Set up block info for each basic block. */ - alloc_aux_for_blocks (sizeof (struct block_info_def)); - alloc_aux_for_edges (sizeof (struct edge_info_def)); - for (i = -2; i < n_basic_blocks; i++) - { - edge e; - basic_block bb; + /* Now fake loop around whole function to finalize probabilities. */ + for (i = 0; i < n_basic_blocks; i++) + BLOCK_INFO (BASIC_BLOCK (i))->tovisit = 1; - if (i == -2) - bb = ENTRY_BLOCK_PTR; - else if (i == -1) - bb = EXIT_BLOCK_PTR; - else - bb = BASIC_BLOCK (i); + BLOCK_INFO (ENTRY_BLOCK_PTR)->tovisit = 1; + BLOCK_INFO (EXIT_BLOCK_PTR)->tovisit = 1; + propagate_freq (ENTRY_BLOCK_PTR); - BLOCK_INFO (bb)->tovisit = 0; - for (e = bb->succ; e; e = e->succ_next) + memcpy (&freq_max, &real_zero, sizeof (real_zero)); + for (i = 0; i < n_basic_blocks; i++) + if (REAL_VALUES_LESS + (freq_max, BLOCK_INFO (BASIC_BLOCK (i))->frequency)) + memcpy (&freq_max, &BLOCK_INFO (BASIC_BLOCK (i))->frequency, + sizeof (freq_max)); + + for (i = -2; i < n_basic_blocks; i++) { - - REAL_VALUE_FROM_INT (EDGE_INFO (e)->back_edge_prob, - e->probability, 0, double_mode); - REAL_ARITHMETIC (EDGE_INFO (e)->back_edge_prob, - RDIV_EXPR, EDGE_INFO (e)->back_edge_prob, - real_br_prob_base); - } - } + basic_block bb; + REAL_VALUE_TYPE tmp; - /* First compute probabilities locally for each loop from innermost - to outermost to examine probabilities for back edges. */ - estimate_loops_at_level (loops->tree_root); + if (i == -2) + bb = ENTRY_BLOCK_PTR; + else if (i == -1) + bb = EXIT_BLOCK_PTR; + else + bb = BASIC_BLOCK (i); - /* Now fake loop around whole function to finalize probabilities. */ - for (i = 0; i < n_basic_blocks; i++) - BLOCK_INFO (BASIC_BLOCK (i))->tovisit = 1; + REAL_ARITHMETIC (tmp, MULT_EXPR, BLOCK_INFO (bb)->frequency, + real_bb_freq_max); + REAL_ARITHMETIC (tmp, RDIV_EXPR, tmp, freq_max); + REAL_ARITHMETIC (tmp, PLUS_EXPR, tmp, real_one_half); + bb->frequency = REAL_VALUE_UNSIGNED_FIX (tmp); + } - BLOCK_INFO (ENTRY_BLOCK_PTR)->tovisit = 1; - BLOCK_INFO (EXIT_BLOCK_PTR)->tovisit = 1; - propagate_freq (ENTRY_BLOCK_PTR); + free_aux_for_blocks (); + free_aux_for_edges (); + } + compute_function_frequency (); + if (flag_reorder_functions) + choose_function_section (); +} - memcpy (&freq_max, &real_zero, sizeof (real_zero)); +/* Decide whether function is hot, cold or unlikely executed. */ +static void +compute_function_frequency () +{ + int i; + if (!profile_info.count_profiles_merged + || !flag_branch_probabilities) + return; + cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED; for (i = 0; i < n_basic_blocks; i++) - if (REAL_VALUES_LESS (freq_max, BLOCK_INFO (BASIC_BLOCK (i))->frequency)) - memcpy (&freq_max, &BLOCK_INFO (BASIC_BLOCK (i))->frequency, - sizeof (freq_max)); - - for (i = -2; i < n_basic_blocks; i++) { - basic_block bb; - REAL_VALUE_TYPE tmp; - - if (i == -2) - bb = ENTRY_BLOCK_PTR; - else if (i == -1) - bb = EXIT_BLOCK_PTR; - else - bb = BASIC_BLOCK (i); - - REAL_ARITHMETIC (tmp, MULT_EXPR, BLOCK_INFO (bb)->frequency, - real_bb_freq_max); - REAL_ARITHMETIC (tmp, RDIV_EXPR, tmp, freq_max); - REAL_ARITHMETIC (tmp, PLUS_EXPR, tmp, real_one_half); - bb->frequency = REAL_VALUE_UNSIGNED_FIX (tmp); + basic_block bb = BASIC_BLOCK (i); + if (maybe_hot_bb_p (bb)) + { + cfun->function_frequency = FUNCTION_FREQUENCY_HOT; + return; + } + if (!probably_never_executed_bb_p (bb)) + cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL; } +} - free_aux_for_blocks (); - free_aux_for_edges (); +/* Choose appropriate section for the function. */ +static void +choose_function_section () +{ + if (DECL_SECTION_NAME (current_function_decl) + || !targetm.have_named_sections) + return; + if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT) + DECL_SECTION_NAME (current_function_decl) = + build_string (strlen (HOT_TEXT_SECTION_NAME), HOT_TEXT_SECTION_NAME); + if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED) + DECL_SECTION_NAME (current_function_decl) = + build_string (strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME), + UNLIKELY_EXECUTED_TEXT_SECTION_NAME); } |