This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Improve pow (C, x) -> exp (log (C) * x) optimization (PR middle-end/84309)
- From: Richard Biener <rguenther at suse dot de>
- To: Jakub Jelinek <jakub at redhat dot com>,Jeff Law <law at redhat dot com>,Wilco Dijkstra <Wilco dot Dijkstra at arm dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sat, 10 Feb 2018 08:00:04 +0100
- Subject: Re: [PATCH] Improve pow (C, x) -> exp (log (C) * x) optimization (PR middle-end/84309)
- Authentication-results: sourceware.org; auth=none
- References: <20180209233738.GQ5867@tucnak>
On February 10, 2018 12:37:38 AM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>Apparently the new pow(C,x) -> exp(log(C)*x) if C > 0 optimization
>breaks some package (Marek should know which), as it has 7ulp error.
>Generally one should be prepared for some errors with -ffast-math.
>
>Though, in this case, if the target has c99 runtime and C is
>a positive 0x1pNN it seems much better to use exp2 over exp, for
>C being 2 pow (2, x) is optimized into exp2 (x) and even for other
>values log2(C) will still be some positive or negative integer, so
>in many cases there won't be any rounding errors in the multiplication.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. I wonder whether there are vectorized variants in libmvec?
Richard.
>Perhaps we should do something similar if C is a power of 10 (use exp10
>and log10).
>
>2018-02-10 Jakub Jelinek <jakub@redhat.com>
>
> PR middle-end/84309
> * match.pd (pow(C,x) -> exp(log(C)*x)): Optimize instead into
> exp2(log2(C)*x) if C is a power of 2 and c99 runtime is available.
>
> * gcc.dg/pr84309.c: New test.
>
>--- gcc/match.pd.jj 2018-01-26 12:43:23.208922420 +0100
>+++ gcc/match.pd 2018-02-09 18:48:26.412021408 +0100
>@@ -3992,15 +3992,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (logs (pows @0 @1))
> (mult @1 (logs @0))))
>
>- /* pow(C,x) -> exp(log(C)*x) if C > 0. */
>+ /* 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). */
> (for pows (POW)
> exps (EXP)
> logs (LOG)
>+ exp2s (EXP2)
>+ log2s (LOG2)
> (simplify
> (pows REAL_CST@0 @1)
>- (if (real_compare (GT_EXPR, TREE_REAL_CST_PTR (@0), &dconst0)
>- && real_isfinite (TREE_REAL_CST_PTR (@0)))
>- (exps (mult (logs @0) @1)))))
>+ (if (real_compare (GT_EXPR, TREE_REAL_CST_PTR (@0), &dconst0)
>+ && real_isfinite (TREE_REAL_CST_PTR (@0)))
>+ (with {
>+ const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (@0);
>+ bool use_exp2 = false;
>+ if (targetm.libc_has_function (function_c99_misc)
>+ && value->cl == rvc_normal)
>+ {
>+ REAL_VALUE_TYPE frac_rvt = *value;
>+ SET_REAL_EXP (&frac_rvt, 1);
>+ if (real_equal (&frac_rvt, &dconst1))
>+ use_exp2 = true;
>+ }
>+ }
>+ (if (use_exp2)
>+ (exp2s (mult (log2s @0) @1))
>+ (exps (mult (logs @0) @1)))))))
>
> (for sqrts (SQRT)
> cbrts (CBRT)
>--- gcc/testsuite/gcc.dg/pr84309.c.jj 2018-02-09 18:54:52.254787678
>+0100
>+++ gcc/testsuite/gcc.dg/pr84309.c 2018-02-09 18:59:02.343636178 +0100
>@@ -0,0 +1,14 @@
>+/* PR middle-end/84309 */
>+/* { dg-do run { target c99_runtime } } */
>+/* { dg-options "-O2 -ffast-math" } */
>+
>+int
>+main ()
>+{
>+ unsigned long a = 1024;
>+ unsigned long b = 16 * 1024;
>+ unsigned long c = __builtin_pow (2, (__builtin_log2 (a) +
>__builtin_log2 (b)) / 2);
>+ if (c != 4096)
>+ __builtin_abort ();
>+ return 0;
>+}
>
> Jakub