aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2010-12-16 02:27:23 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2010-12-16 01:27:23 +0000
commit5210bbc5aad878af293a6535973a635c98c6ac47 (patch)
treee41c4607d39b103e09dc0d95fc1780e5e66e11e3 /gcc/predict.c
parent7a2d845d3e116031530ae201dfb5e75edf995f31 (diff)
downloadgcc-5210bbc5aad878af293a6535973a635c98c6ac47.zip
gcc-5210bbc5aad878af293a6535973a635c98c6ac47.tar.gz
gcc-5210bbc5aad878af293a6535973a635c98c6ac47.tar.bz2
re PR tree-optimization/46939 (http://blog.regehr.org/archives/320 example 6)
PR middle-end/46939 * predic.c (predict_paths_leading_to_edge): New function. (apply_return_prediction): Use it. (predict_paths_for_bb): Do not special case abnormals. * gcc.target/i386/pr46939.c: New testcase. From-SVN: r167893
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index c691990..a86708a 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -77,6 +77,7 @@ static sreal real_zero, real_one, real_almost_one, real_br_prob_base,
static void combine_predictions_for_insn (rtx, basic_block);
static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction);
+static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction);
static bool can_predict_insn_p (const_rtx);
/* Information we hold about each branch predictor.
@@ -1558,8 +1559,8 @@ apply_return_prediction (void)
{
pred = return_prediction (PHI_ARG_DEF (phi, i), &direction);
if (pred != PRED_NO_PREDICTION)
- predict_paths_leading_to (gimple_phi_arg_edge (phi, i)->src, pred,
- direction);
+ predict_paths_leading_to_edge (gimple_phi_arg_edge (phi, i), pred,
+ direction);
}
}
@@ -1805,8 +1806,8 @@ predict_paths_for_bb (basic_block cur, basic_block bb,
edge_iterator ei2;
bool found = false;
- /* Ignore abnormals, we predict them as not taken anyway. */
- if (e->flags & (EDGE_EH | EDGE_FAKE | EDGE_ABNORMAL))
+ /* Ignore fake edges and eh, we predict them as not taken anyway. */
+ if (e->flags & (EDGE_EH | EDGE_FAKE))
continue;
gcc_assert (bb == cur || dominated_by_p (CDI_POST_DOMINATORS, cur, bb));
@@ -1814,7 +1815,7 @@ predict_paths_for_bb (basic_block cur, basic_block bb,
and does not lead to BB. */
FOR_EACH_EDGE (e2, ei2, e->src->succs)
if (e2 != e
- && !(e2->flags & (EDGE_EH | EDGE_FAKE | EDGE_ABNORMAL))
+ && !(e2->flags & (EDGE_EH | EDGE_FAKE))
&& !dominated_by_p (CDI_POST_DOMINATORS, e2->dest, bb))
{
found = true;
@@ -1844,6 +1845,31 @@ predict_paths_leading_to (basic_block bb, enum br_predictor pred,
{
predict_paths_for_bb (bb, bb, pred, taken);
}
+
+/* Like predict_paths_leading_to but take edge instead of basic block. */
+
+static void
+predict_paths_leading_to_edge (edge e, enum br_predictor pred,
+ enum prediction taken)
+{
+ bool has_nonloop_edge = false;
+ edge_iterator ei;
+ edge e2;
+
+ basic_block bb = e->src;
+ FOR_EACH_EDGE (e2, ei, bb->succs)
+ if (e2->dest != e->src && e2->dest != e->dest
+ && !(e->flags & (EDGE_EH | EDGE_FAKE))
+ && !dominated_by_p (CDI_POST_DOMINATORS, e->src, e2->dest))
+ {
+ has_nonloop_edge = true;
+ break;
+ }
+ if (!has_nonloop_edge)
+ predict_paths_for_bb (bb, bb, pred, taken);
+ else
+ predict_edge_def (e, pred, taken);
+}
/* This is used to carry information about basic blocks. It is
attached to the AUX field of the standard CFG block. */