diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-15 09:00:30 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-15 09:00:30 +0000 |
commit | 429fa7fa60729329a43f5d6d7b9211692e1cfa5b (patch) | |
tree | 6dab9b09a4ebcfb309dc527384a3d4f4607f240d /gcc/predict.c | |
parent | b674560317eac766d09cb51a33ce9981610701bf (diff) | |
download | gcc-429fa7fa60729329a43f5d6d7b9211692e1cfa5b.tar.gz |
* invoke.texi (-malign-double): Re-add lost warning.
* i386-protos.h (x86_output_mi_thunk): Declare.
* unix.h (ASM_OUTPUT_MI_THUNK): Move offline to ...
* i386.c (x86_output_mi_thunk): ... here; handle 64bits.
* dwarf2out.c (output_call_frame_info): Do not skip unwind info
when flag_asynchronous_unwind_tables is set.
* flags.h (flag_reorder_functions): Declare.
* function.c (prepare_function_start): Initialize frequnecy.
* params.def (HOT_BB_COUNT_FRACTION, HOT_BB_FREQUENCY_FRACTION): New paramters.
* Makefile.in (predict.o): Add dependency on target.h and params.h
* defaults.h (HOT_TEXT_SECTION_NAME,
UNLIKELY_EXECUTED_TEXT_SECTION_NAME): New macros.
* predict.c (choose_function_section): New function.
(estimate_bb_frequencies): Use it.
* toplev.c (flag_reorder_functions): New global variable.
(lang_independent_options): New.
(parse_options_and_default_flags): Set.
* varasm.c (assemble_start_function): Bypass functdion alignment
for never executed functions.
* invoke.texi (-freorder-blocks, -freorder-functions): Document.
(param hot-bb-count-fraction, hot-bb-frequency-fraction): New.
* tm.texi (HOT_TEXT_SECTION_NAME, UNLIKELY_EXECUTED_TEXT_SECTION_NAME):
Document.
Thu Jan 3 21:52:09 CET 2002 Jan Hubicka <jh@suse.cz>
* predict.c: Inlude profile.h
(MIN_COUNT): Rename to MIN_COUNT_FRACTION
(maybe_hot_bb_p, probably_cold_bb_p, probably_never_executed_bb_p):
Use the information about maximal counter in the program.
Thu Dec 20 22:14:00 CET 2001 Jan Hubicka <jh@suse.cz>
* basic-block.h (maybe_hot_bb_p, probably_cold_bb_p,
probably_never_executed_bb_p): New functions.
* cfgcleanup.c (outgoing_edges_match): Use them.
* predict.c (MIN_COUNT, MIN_FREQUENCY): New macros.
(maybe_hot_bb_p, probably_cold_bb_p,
probably_never_executed_bb_p): New functions.
* function.h (function): Add new field function_frequency.
* predict.c (compute_function_frequency): New function.
(estimate_probability): Call it.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53478 138bc75d-0d04-0410-961f-82ee72b054a4
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 5896c10a191..f457817956d 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); } |