From 91674b2a37fcc352f837d49fba7c35f781bac967 Mon Sep 17 00:00:00 2001 From: jakub Date: Wed, 28 Mar 2018 19:15:39 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@258930 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++ gcc/gimple-match-head.c | 68 ++++++++++++++++++++++++++++++++++++++++++ gcc/match.pd | 5 +++- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/pr82004.c | 32 ++++++++++++++++++++ 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr82004.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b398a635d96..3ac9f9bdd5c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-03-28 Jakub Jelinek + + 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 PR other/84819 diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index 172ef0a6909..4266fb3d906 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 + 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 (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 (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 3e1636c41a4..7c4c11c4ef7 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 fc1d5d078ed..78a1ebb3c8b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,4 +1,9 @@ 2018-03-28 Jakub Jelinek + + PR tree-optimization/82004 + * gcc.dg/pr82004.c: New test. + +2018-03-28 Jakub Jelinek Martin Liska PR sanitizer/85081 diff --git a/gcc/testsuite/gcc.dg/pr82004.c b/gcc/testsuite/gcc.dg/pr82004.c new file mode 100644 index 00000000000..2dd3eae90a8 --- /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; +} -- 2.11.4.GIT