From: Jakub Jelinek Date: Tue, 19 Dec 2017 16:43:04 +0000 (+0100) Subject: re PR middle-end/81914 (gcc 7.1 generates branch for code which was branchless in... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=972027748c2aa9f59ef1ab534763b0d6ed37b76d;p=gcc.git re PR middle-end/81914 (gcc 7.1 generates branch for code which was branchless in earlier gcc version) PR middle-end/81914 * predict.c (zero_one_minusone): New function. (apply_return_prediction): Avoid return prediction for functions returning only -1, 0 and 1 values, unless they only return -1 and 0 or 0 and 1. From-SVN: r255829 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index caa6d51100c..31277b9a9f4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-12-18 Jakub Jelinek + + PR middle-end/81914 + * predict.c (zero_one_minusone): New function. + (apply_return_prediction): Avoid return prediction for functions + returning only -1, 0 and 1 values, unless they only return -1 and 0 + or 0 and 1. + 2017-12-19 Claudiu Zissulescu * config/arc/arc.c (legitimate_scaled_address_p): Clean diff --git a/gcc/predict.c b/gcc/predict.c index 0f34956f699..2de9d241833 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -2639,6 +2639,64 @@ return_prediction (tree val, enum prediction *prediction) return PRED_NO_PREDICTION; } +/* Return zero if phi result could have values other than -1, 0 or 1, + otherwise return a bitmask, with bits 0, 1 and 2 set if -1, 0 and 1 + values are used or likely. */ + +static int +zero_one_minusone (gphi *phi, int limit) +{ + int phi_num_args = gimple_phi_num_args (phi); + int ret = 0; + for (int i = 0; i < phi_num_args; i++) + { + tree t = PHI_ARG_DEF (phi, i); + if (TREE_CODE (t) != INTEGER_CST) + continue; + wide_int w = wi::to_wide (t); + if (w == -1) + ret |= 1; + else if (w == 0) + ret |= 2; + else if (w == 1) + ret |= 4; + else + return 0; + } + for (int i = 0; i < phi_num_args; i++) + { + tree t = PHI_ARG_DEF (phi, i); + if (TREE_CODE (t) == INTEGER_CST) + continue; + if (TREE_CODE (t) != SSA_NAME) + return 0; + gimple *g = SSA_NAME_DEF_STMT (t); + if (gimple_code (g) == GIMPLE_PHI && limit > 0) + if (int r = zero_one_minusone (as_a (g), limit - 1)) + { + ret |= r; + continue; + } + if (!is_gimple_assign (g)) + return 0; + if (gimple_assign_cast_p (g)) + { + tree rhs1 = gimple_assign_rhs1 (g); + if (TREE_CODE (rhs1) != SSA_NAME + || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) + || TYPE_PRECISION (TREE_TYPE (rhs1)) != 1 + || !TYPE_UNSIGNED (TREE_TYPE (rhs1))) + return 0; + ret |= (2 | 4); + continue; + } + if (TREE_CODE_CLASS (gimple_assign_rhs_code (g)) != tcc_comparison) + return 0; + ret |= (2 | 4); + } + return ret; +} + /* Find the basic block with return expression and look up for possible return value trying to apply RETURN_PREDICTION heuristics. */ static void @@ -2676,6 +2734,19 @@ apply_return_prediction (void) phi_num_args = gimple_phi_num_args (phi); pred = return_prediction (PHI_ARG_DEF (phi, 0), &direction); + /* Avoid the case where the function returns -1, 0 and 1 values and + nothing else. Those could be qsort etc. comparison functions + where the negative return isn't less probable than positive. + For this require that the function returns at least -1 or 1 + or -1 and a boolean value or comparison result, so that functions + returning just -1 and 0 are treated as if -1 represents error value. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (return_val)) + && !TYPE_UNSIGNED (TREE_TYPE (return_val)) + && TYPE_PRECISION (TREE_TYPE (return_val)) > 1) + if (int r = zero_one_minusone (phi, 3)) + if ((r & (1 | 4)) == (1 | 4)) + return; + /* Avoid the degenerate case where all return values form the function belongs to same category (ie they are all positive constants) so we can hardly say something about them. */