From 5210bbc5aad878af293a6535973a635c98c6ac47 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 16 Dec 2010 02:27:23 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 ++ gcc/predict.c | 36 +++++++- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.target/i386/pr46939.c | 118 ++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr46939.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 08d91dbf06c..57de984bcc2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2010-12-16 Jan Hubicka + + 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. + 2010-12-16 Joseph Myers * config.gcc (powerpc-*-lynxos*): Don't add lynx.opt to diff --git a/gcc/predict.c b/gcc/predict.c index c6919908316..a86708a5935 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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c10535cb1a6..8ca61f49918 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-12-16 Jan Hubicka + + PR middle-end/46939 + * gcc.target/i386/pr46939.c: New testcase. + 2010-12-15 Sebastian Pop PR tree-optimization/46404 diff --git a/gcc/testsuite/gcc.target/i386/pr46939.c b/gcc/testsuite/gcc.target/i386/pr46939.c new file mode 100644 index 00000000000..2f50e37ee01 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr46939.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +int +php_filter_parse_int (char const *str, unsigned int str_len, long *ret) +{ + long ctx_value; + int sign; + int digit; + char const *end; + int tmp; + char const *tmp___0; + char const *tmp___1; + + sign = 0; + digit = 0; + end = str + str_len; + switch ((int) *str) + { + case 45: + sign = 1; + case 43: + str++; + default:; + break; + } + if ((unsigned long) str < (unsigned long) end) + { + if ((int const) *str >= 49) + { + if ((int const) *str <= 57) + { + if (sign) + { + tmp = -1; + } + else + { + tmp = 1; + } + tmp___0 = str; + str++; + ctx_value = (long) (tmp * (int) ((int const) *tmp___0 - 48)); + } + else + { + return (-1); + } + } + else + { + return (-1); + } + } + else + { + return (-1); + } + if (end - str > 19) + { + return (-1); + } + while ((unsigned long) str < (unsigned long) end) + { + if ((int const) *str >= 48) + { + if ((int const) *str <= 57) + { + tmp___1 = str; + str++; + digit = (int) ((int const) *tmp___1 - 48); + if (!sign) + { + if (ctx_value <= + (9223372036854775807L - (long) digit) / 10L) + { + ctx_value = ctx_value * 10L + (long) digit; + } + else + { + goto _L; + } + } + else + { + _L: + if (sign) + { + if (ctx_value >= + ((-0x7FFFFFFFFFFFFFFF - 1) + (long) digit) / 10L) + { + ctx_value = ctx_value * 10L - (long) digit; + } + else + { + return (-1); + } + } + else + { + return (-1); + } + } + } + else + { + return (-1); + } + } + else + { + return (-1); + } + } + *ret = ctx_value; + return (1); +} + +/* { dg-final { scan-assembler-not "idiv" } } */ -- 2.30.2