predict.c: Include pointer-set.h.

* predict.c: Include pointer-set.h.
	(bb_predictions): New variable.
	(tree_predicted_by_p, tree_predict_edge,
	remove_predictions_associated_with_edge): Use bb_predictions map
	instead of bb->predictions.
	(clear_bb_predictions, assert_is_empty): New functions.
	(combine_predictions_for_bb): Use bb_predictions map.  Call
	clear_bb_predictions.
	(tree_estimate_probability): Create and free bb_predictions map.
	* Makefile.in (predict.o): Add pointer-set.h dependency.
	* basic-block.h (struct basic_block_def): Remove predictions
	field.
	* cfgrtl.c (rtl_verify_flow_info_1): Do not check bb->predictions.

From-SVN: r124032
This commit is contained in:
Zdenek Dvorak 2007-04-22 02:51:38 +02:00 committed by Zdenek Dvorak
parent e919dfe284
commit f06b0a10f9
5 changed files with 127 additions and 46 deletions

View File

@ -1,3 +1,19 @@
2007-04-21 Zdenek Dvorak <dvorakz@suse.cz>
* predict.c: Include pointer-set.h.
(bb_predictions): New variable.
(tree_predicted_by_p, tree_predict_edge,
remove_predictions_associated_with_edge): Use bb_predictions map
instead of bb->predictions.
(clear_bb_predictions, assert_is_empty): New functions.
(combine_predictions_for_bb): Use bb_predictions map. Call
clear_bb_predictions.
(tree_estimate_probability): Create and free bb_predictions map.
* Makefile.in (predict.o): Add pointer-set.h dependency.
* basic-block.h (struct basic_block_def): Remove predictions
field.
* cfgrtl.c (rtl_verify_flow_info_1): Do not check bb->predictions.
2007-04-21 Kaz Kojima <kkojima@gcc.gnu.org> 2007-04-21 Kaz Kojima <kkojima@gcc.gnu.org>
PR target/31480 PR target/31480

View File

@ -2685,7 +2685,7 @@ predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
hard-reg-set.h output.h toplev.h $(RECOG_H) $(FUNCTION_H) except.h \ hard-reg-set.h output.h toplev.h $(RECOG_H) $(FUNCTION_H) except.h \
$(TM_P_H) $(PREDICT_H) sreal.h $(PARAMS_H) $(TARGET_H) $(CFGLOOP_H) \ $(TM_P_H) $(PREDICT_H) sreal.h $(PARAMS_H) $(TARGET_H) $(CFGLOOP_H) \
$(COVERAGE_H) $(SCEV_H) $(GGC_H) predict.def $(TIMEVAR_H) $(TREE_DUMP_H) \ $(COVERAGE_H) $(SCEV_H) $(GGC_H) predict.def $(TIMEVAR_H) $(TREE_DUMP_H) \
$(TREE_FLOW_H) tree-pass.h $(EXPR_H) $(TREE_FLOW_H) tree-pass.h $(EXPR_H) pointer-set.h
lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \ lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
$(RTL_H) $(GGC_H) gt-lists.h $(RTL_H) $(GGC_H) gt-lists.h
bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \

View File

@ -240,9 +240,6 @@ struct basic_block_def GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb")
/* Chain of PHI nodes for this block. */ /* Chain of PHI nodes for this block. */
tree phi_nodes; tree phi_nodes;
/* A list of predictions. */
struct edge_prediction *predictions;
/* Expected number of executions: calculated in profile.c. */ /* Expected number of executions: calculated in profile.c. */
gcov_type count; gcov_type count;

View File

@ -1716,12 +1716,6 @@ rtl_verify_flow_info_1 (void)
bb->index); bb->index);
err = 1; err = 1;
} }
if (bb->predictions)
{
error ("bb prediction set for block %d, but it is not used in RTL land", bb->index);
err = 1;
}
} }
/* Now check the basic blocks (boundaries etc.) */ /* Now check the basic blocks (boundaries etc.) */

View File

@ -60,6 +60,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "timevar.h" #include "timevar.h"
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "cfgloop.h" #include "cfgloop.h"
#include "pointer-set.h"
/* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE, /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX. */ 1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX. */
@ -174,6 +175,11 @@ rtl_predicted_by_p (basic_block bb, enum br_predictor predictor)
return false; return false;
} }
/* This map contains for a basic block the list of predictions for the
outgoing edges. */
static struct pointer_map_t *bb_predictions;
/* Return true if the one of outgoing edges is already predicted by /* Return true if the one of outgoing edges is already predicted by
PREDICTOR. */ PREDICTOR. */
@ -181,7 +187,12 @@ bool
tree_predicted_by_p (basic_block bb, enum br_predictor predictor) tree_predicted_by_p (basic_block bb, enum br_predictor predictor)
{ {
struct edge_prediction *i; struct edge_prediction *i;
for (i = bb->predictions; i; i = i->ep_next) void **preds = pointer_map_contains (bb_predictions, bb);
if (!preds)
return false;
for (i = *preds; i; i = i->ep_next)
if (i->ep_predictor == predictor) if (i->ep_predictor == predictor)
return true; return true;
return false; return false;
@ -283,10 +294,11 @@ tree_predict_edge (edge e, enum br_predictor predictor, int probability)
if ((e->src != ENTRY_BLOCK_PTR && EDGE_COUNT (e->src->succs) > 1) if ((e->src != ENTRY_BLOCK_PTR && EDGE_COUNT (e->src->succs) > 1)
&& flag_guess_branch_prob && optimize) && flag_guess_branch_prob && optimize)
{ {
struct edge_prediction *i = ggc_alloc (sizeof (struct edge_prediction)); struct edge_prediction *i = XNEW (struct edge_prediction);
void **preds = pointer_map_insert (bb_predictions, e->src);
i->ep_next = e->src->predictions; i->ep_next = *preds;
e->src->predictions = i; *preds = i;
i->ep_probability = probability; i->ep_probability = probability;
i->ep_predictor = predictor; i->ep_predictor = predictor;
i->ep_edge = e; i->ep_edge = e;
@ -298,19 +310,51 @@ tree_predict_edge (edge e, enum br_predictor predictor, int probability)
void void
remove_predictions_associated_with_edge (edge e) remove_predictions_associated_with_edge (edge e)
{ {
if (e->src->predictions) void **preds;
if (!bb_predictions)
return;
preds = pointer_map_contains (bb_predictions, e->src);
if (preds)
{ {
struct edge_prediction **prediction = &e->src->predictions; struct edge_prediction **prediction = (struct edge_prediction **) preds;
struct edge_prediction *next;
while (*prediction) while (*prediction)
{ {
if ((*prediction)->ep_edge == e) if ((*prediction)->ep_edge == e)
*prediction = (*prediction)->ep_next; {
next = (*prediction)->ep_next;
free (*prediction);
*prediction = next;
}
else else
prediction = &((*prediction)->ep_next); prediction = &((*prediction)->ep_next);
} }
} }
} }
/* Clears the list of predictions stored for BB. */
static void
clear_bb_predictions (basic_block bb)
{
void **preds = pointer_map_contains (bb_predictions, bb);
struct edge_prediction *pred, *next;
if (!preds)
return;
for (pred = *preds; pred; pred = next)
{
next = pred->ep_next;
free (pred);
}
*preds = NULL;
}
/* Return true when we can store prediction on insn INSN. /* Return true when we can store prediction on insn INSN.
At the moment we represent predictions only on conditional At the moment we represent predictions only on conditional
jumps, not at computed jump or other complicated cases. */ jumps, not at computed jump or other complicated cases. */
@ -538,6 +582,7 @@ combine_predictions_for_bb (basic_block bb)
int nedges = 0; int nedges = 0;
edge e, first = NULL, second = NULL; edge e, first = NULL, second = NULL;
edge_iterator ei; edge_iterator ei;
void **preds;
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
if (!(e->flags & (EDGE_EH | EDGE_FAKE))) if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
@ -559,7 +604,7 @@ combine_predictions_for_bb (basic_block bb)
{ {
if (!bb->count) if (!bb->count)
set_even_probabilities (bb); set_even_probabilities (bb);
bb->predictions = NULL; clear_bb_predictions (bb);
if (dump_file) if (dump_file)
fprintf (dump_file, "%i edges in bb %i predicted to even probabilities\n", fprintf (dump_file, "%i edges in bb %i predicted to even probabilities\n",
nedges, bb->index); nedges, bb->index);
@ -569,31 +614,36 @@ combine_predictions_for_bb (basic_block bb)
if (dump_file) if (dump_file)
fprintf (dump_file, "Predictions for bb %i\n", bb->index); fprintf (dump_file, "Predictions for bb %i\n", bb->index);
/* We implement "first match" heuristics and use probability guessed preds = pointer_map_contains (bb_predictions, bb);
by predictor with smallest index. */ if (preds)
for (pred = bb->predictions; pred; pred = pred->ep_next)
{ {
int predictor = pred->ep_predictor; /* We implement "first match" heuristics and use probability guessed
int probability = pred->ep_probability; by predictor with smallest index. */
for (pred = *preds; pred; pred = pred->ep_next)
{
int predictor = pred->ep_predictor;
int probability = pred->ep_probability;
if (pred->ep_edge != first) if (pred->ep_edge != first)
probability = REG_BR_PROB_BASE - probability; probability = REG_BR_PROB_BASE - probability;
found = true; found = true;
if (best_predictor > predictor) if (best_predictor > predictor)
best_probability = probability, best_predictor = predictor; best_probability = probability, best_predictor = predictor;
d = (combined_probability * probability d = (combined_probability * probability
+ (REG_BR_PROB_BASE - combined_probability) + (REG_BR_PROB_BASE - combined_probability)
* (REG_BR_PROB_BASE - probability)); * (REG_BR_PROB_BASE - probability));
/* Use FP math to avoid overflows of 32bit integers. */ /* Use FP math to avoid overflows of 32bit integers. */
if (d == 0) if (d == 0)
/* If one probability is 0% and one 100%, avoid division by zero. */ /* If one probability is 0% and one 100%, avoid division by zero. */
combined_probability = REG_BR_PROB_BASE / 2; combined_probability = REG_BR_PROB_BASE / 2;
else else
combined_probability = (((double) combined_probability) * probability combined_probability = (((double) combined_probability)
* REG_BR_PROB_BASE / d + 0.5); * probability
* REG_BR_PROB_BASE / d + 0.5);
}
} }
/* Decide which heuristic to use. In case we didn't match anything, /* Decide which heuristic to use. In case we didn't match anything,
@ -617,17 +667,20 @@ combine_predictions_for_bb (basic_block bb)
combined_probability = best_probability; combined_probability = best_probability;
dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true); dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
for (pred = bb->predictions; pred; pred = pred->ep_next) if (preds)
{ {
int predictor = pred->ep_predictor; for (pred = *preds; pred; pred = pred->ep_next)
int probability = pred->ep_probability; {
int predictor = pred->ep_predictor;
int probability = pred->ep_probability;
if (pred->ep_edge != EDGE_SUCC (bb, 0)) if (pred->ep_edge != EDGE_SUCC (bb, 0))
probability = REG_BR_PROB_BASE - probability; probability = REG_BR_PROB_BASE - probability;
dump_prediction (dump_file, predictor, probability, bb, dump_prediction (dump_file, predictor, probability, bb,
!first_match || best_predictor == predictor); !first_match || best_predictor == predictor);
}
} }
bb->predictions = NULL; clear_bb_predictions (bb);
if (!bb->count) if (!bb->count)
{ {
@ -1278,6 +1331,20 @@ call_expr:;
free (heads); free (heads);
} }
#ifdef ENABLE_CHECKING
/* Callback for pointer_map_traverse, asserts that the pointer map is
empty. */
static bool
assert_is_empty (void *key ATTRIBUTE_UNUSED, void **value,
void *data ATTRIBUTE_UNUSED)
{
gcc_assert (!*value);
return false;
}
#endif
/* Predict branch probabilities and estimate profile of the tree CFG. */ /* Predict branch probabilities and estimate profile of the tree CFG. */
static unsigned int static unsigned int
tree_estimate_probability (void) tree_estimate_probability (void)
@ -1295,6 +1362,7 @@ tree_estimate_probability (void)
create_preheaders (CP_SIMPLE_PREHEADERS); create_preheaders (CP_SIMPLE_PREHEADERS);
calculate_dominance_info (CDI_POST_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS);
bb_predictions = pointer_map_create ();
tree_bb_level_predictions (); tree_bb_level_predictions ();
mark_irreducible_loops (); mark_irreducible_loops ();
@ -1383,6 +1451,12 @@ tree_estimate_probability (void)
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
combine_predictions_for_bb (bb); combine_predictions_for_bb (bb);
#ifdef ENABLE_CHECKING
pointer_map_traverse (bb_predictions, assert_is_empty, NULL);
#endif
pointer_map_destroy (bb_predictions);
bb_predictions = NULL;
strip_builtin_expect (); strip_builtin_expect ();
estimate_bb_frequencies (); estimate_bb_frequencies ();
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);