aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-12-19 17:43:04 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-12-19 17:43:04 +0100
commit972027748c2aa9f59ef1ab534763b0d6ed37b76d (patch)
tree4b28276b4df98bc91aaec6e977cad6164d0e067c /gcc
parent41bc2c0b217d727aa516978cac54594d00498411 (diff)
downloadgcc-972027748c2aa9f59ef1ab534763b0d6ed37b76d.zip
gcc-972027748c2aa9f59ef1ab534763b0d6ed37b76d.tar.gz
gcc-972027748c2aa9f59ef1ab534763b0d6ed37b76d.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/predict.c71
2 files changed, 79 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index caa6d51..31277b9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2017-12-18 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <claziss@synopsys.com>
* config/arc/arc.c (legitimate_scaled_address_p): Clean
diff --git a/gcc/predict.c b/gcc/predict.c
index 0f34956..2de9d24 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 <gphi *> (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. */