diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-03-28 21:15:39 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-03-28 21:15:39 +0200 |
commit | 30a2c10eb639f1855fe7e060552f09c706efa532 (patch) | |
tree | 707858c0b19b0db09b4434b773deb95486f2dae0 /gcc | |
parent | cefc09063eb4b0eb572c89c3f0657e5b5e36e77d (diff) | |
download | gcc-30a2c10eb639f1855fe7e060552f09c706efa532.zip gcc-30a2c10eb639f1855fe7e060552f09c706efa532.tar.gz gcc-30a2c10eb639f1855fe7e060552f09c706efa532.tar.bz2 |
re PR middle-end/82004 (SPEC CPU2017 628.pop2_s miscompare)
PR tree-optimization/82004
* gimple-match-head.c (optimize_pow_to_exp): New function.
* match.pd (pow(C,x) -> exp(log(C)*x)): Wrap with #if GIMPLE.
Don't fold to exp if optimize_pow_to_exp is false.
* gcc.dg/pr82004.c: New test.
From-SVN: r258930
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/gimple-match-head.c | 68 | ||||
-rw-r--r-- | gcc/match.pd | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr82004.c | 32 |
5 files changed, 116 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b398a63..3ac9f9b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-03-28 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/82004 + * gimple-match-head.c (optimize_pow_to_exp): New function. + * match.pd (pow(C,x) -> exp(log(C)*x)): Wrap with #if GIMPLE. + Don't fold to exp if optimize_pow_to_exp is false. + 2018-03-28 Martin Liska <mliska@suse.cz> PR other/84819 diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index 172ef0a..4266fb3 100644 --- a/gcc/gimple-match-head.c +++ b/gcc/gimple-match-head.c @@ -840,3 +840,71 @@ canonicalize_math_after_vectorization_p () { return !cfun || (cfun->curr_properties & PROP_gimple_lvec) != 0; } + +/* Return true if pow(cst, x) should be optimized into exp(log(cst) * x). + As a workaround for SPEC CPU2017 628.pop2_s, don't do it if arg0 + is an exact integer, arg1 = phi_res +/- cst1 and phi_res = PHI <cst2, ...> + where cst2 +/- cst1 is an exact integer, because then pow (arg0, arg1) + will likely be exact, while exp (log (arg0) * arg1) might be not. + Also don't do it if arg1 is phi_res above and cst2 is an exact integer. */ + +static bool +optimize_pow_to_exp (tree arg0, tree arg1) +{ + gcc_assert (TREE_CODE (arg0) == REAL_CST); + if (!real_isinteger (TREE_REAL_CST_PTR (arg0), TYPE_MODE (TREE_TYPE (arg0)))) + return true; + + if (TREE_CODE (arg1) != SSA_NAME) + return true; + + gimple *def = SSA_NAME_DEF_STMT (arg1); + gphi *phi = dyn_cast <gphi *> (def); + tree cst1 = NULL_TREE; + enum tree_code code = ERROR_MARK; + if (!phi) + { + if (!is_gimple_assign (def)) + return true; + code = gimple_assign_rhs_code (def); + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + break; + default: + return true; + } + if (TREE_CODE (gimple_assign_rhs1 (def)) != SSA_NAME + || TREE_CODE (gimple_assign_rhs2 (def)) != REAL_CST) + return true; + + cst1 = gimple_assign_rhs2 (def); + + phi = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def))); + if (!phi) + return true; + } + + tree cst2 = NULL_TREE; + int n = gimple_phi_num_args (phi); + for (int i = 0; i < n; i++) + { + tree arg = PHI_ARG_DEF (phi, i); + if (TREE_CODE (arg) != REAL_CST) + continue; + else if (cst2 == NULL_TREE) + cst2 = arg; + else if (!operand_equal_p (cst2, arg, 0)) + return true; + } + + if (cst1 && cst2) + cst2 = const_binop (code, TREE_TYPE (cst2), cst2, cst1); + if (cst2 + && TREE_CODE (cst2) == REAL_CST + && real_isinteger (TREE_REAL_CST_PTR (cst2), + TYPE_MODE (TREE_TYPE (cst2)))) + return false; + return true; +} diff --git a/gcc/match.pd b/gcc/match.pd index 3e1636c..7c4c11c 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4006,6 +4006,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* pow(C,x) -> exp(log(C)*x) if C > 0, or if C is a positive power of 2, pow(C,x) -> exp2(log2(C)*x). */ +#if GIMPLE (for pows (POW) exps (EXP) logs (LOG) @@ -4035,8 +4036,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) } } (if (!use_exp2) - (exps (mult (logs @0) @1)) + (if (optimize_pow_to_exp (@0, @1)) + (exps (mult (logs @0) @1))) (exp2s (mult (log2s @0) @1))))))) +#endif /* pow(C,x)*expN(y) -> expN(logN(C)*x+y) if C > 0. */ (for pows (POW) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc1d5d0..78a1ebb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,4 +1,9 @@ 2018-03-28 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/82004 + * gcc.dg/pr82004.c: New test. + +2018-03-28 Jakub Jelinek <jakub@redhat.com> Martin Liska <mliska@suse.cz> PR sanitizer/85081 diff --git a/gcc/testsuite/gcc.dg/pr82004.c b/gcc/testsuite/gcc.dg/pr82004.c new file mode 100644 index 0000000..2dd3eae --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr82004.c @@ -0,0 +1,32 @@ +/* PR tree-optimization/82004 */ +/* { dg-do run } */ +/* { dg-options "-Ofast" } */ + +extern double log10 (double); +extern double pow (double, double); + +__attribute__((noipa)) void +bar (double x) +{ + if (x < 0.001) + __builtin_abort (); + asm volatile ("" : : : "memory"); +} + +int +main () +{ + double d = 0.001; + double e = 10.0; + double f = (log10 (e) - log10 (d)) / 400.0; + double g = log10 (d) - f; + volatile int q = 0; + int i; + if (__builtin_expect (q == 0, 0)) + for (i = 0; i < 400; ++i) + { + g = g + f; + bar (pow (10.0, g)); + } + return 0; +} |