aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c274
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);
}