This is a (tiny) piece of fixing PR14541 which basically complains
that most math function simplification doesn't happen on GIMPLE.
This is of course because nobody re-builds the nested GENERIC
call expressions that would be necessary to trigger the various
simplifications implemneted in builtins.c.

The following patch thus moves the simplifications from
fold_builtin_logarithm to match.pd patterns, removing
the corresponding code from builtins.c.

Note that this results in those patterns no longer applying
at -O0 (or in C/C++ constant expression simplification) as
currently there is no builtin folding implemented in the
GENERIC code-path of match-and-simplify.  I am considering
that premature optimization (even more so at -O0...).
Note that the machinery only omits support for "outermost"
calls, thus we cannot simplify log (exp (x)) but we can
simplify x * pow (x, CST) to pow (x, CST+1) for example.
The simplifications also won't apply during gimplification
but only after SSA is built.

On the branch there are also complete implementations of
the fold_builtin_pow and fold_builtin_sqrt simplifications.

I'd like to get a little bit coverage of builtin simplification
in the wild and wonder if the following is a piece that would
be acceptable for trunk at this point (well, it fixes part of
a bug which is fine in stage3).  Eventually also merging
the builtin bits from the branch.

Are there otherwise any opinions on not handling these for GENERIC?
Of course in the end I was just lazy and support shouldn't be too
difficult.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Thanks,
Richard.

2014-12-02  Richard Biener  <rguent...@suse.de>

        PR middle-end/14541
        * builtins.c (fold_builtin_logarithm): Implement simplifications ...
        * match.pd: ... here as patterns.

Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 218265)
+++ gcc/match.pd        (working copy)
@@ -916,3 +916,90 @@ (define_operator_list inverted_tcc_compa
     (icmp @0 @1))
    (if (ic == ncmp)
     (ncmp @0 @1)))))
+
+
+/* Simplification of math builtins.  */
+
+(define_operator_list LOG BUILT_IN_LOGF BUILT_IN_LOG BUILT_IN_LOGL)
+(define_operator_list EXP BUILT_IN_EXPF BUILT_IN_EXP BUILT_IN_EXPL)
+(define_operator_list LOG2 BUILT_IN_LOG2F BUILT_IN_LOG2 BUILT_IN_LOG2L)
+(define_operator_list EXP2 BUILT_IN_EXP2F BUILT_IN_EXP2 BUILT_IN_EXP2L)
+(define_operator_list LOG10 BUILT_IN_LOG10F BUILT_IN_LOG10 BUILT_IN_LOG10L)
+(define_operator_list EXP10 BUILT_IN_EXP10F BUILT_IN_EXP10 BUILT_IN_EXP10L)
+(define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
+(define_operator_list POW10 BUILT_IN_POW10F BUILT_IN_POW10 BUILT_IN_POW10L)
+(define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL)
+(define_operator_list CBRT BUILT_IN_CBRTF BUILT_IN_CBRT BUILT_IN_CBRTL)
+
+
+/* fold_builtin_logarithm */
+(if (flag_unsafe_math_optimizations)
+ /* Special case, optimize logN(expN(x)) = x.  */
+ (for logs (LOG LOG2 LOG10)
+      exps (EXP EXP2 EXP10)
+  (simplify
+   (logs (exps @0))
+    @0))
+ /* Optimize logN(func()) for various exponential functions.  We
+    want to determine the value "x" and the power "exponent" in
+    order to transform logN(x**exponent) into exponent*logN(x).  */
+ (for logs (LOG LOG LOG LOG
+            LOG2 LOG2 LOG2 LOG2
+           LOG10 LOG10 LOG10 LOG10)
+      exps (EXP EXP2 EXP10 POW10)
+  (simplify
+   (logs (exps @0))
+   (with {
+     tree x;
+     switch (exps)
+       {
+       CASE_FLT_FN (BUILT_IN_EXP):
+         /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
+        x = build_real (type, real_value_truncate (TYPE_MODE (type),
+                                                   dconst_e ()));
+         break;
+       CASE_FLT_FN (BUILT_IN_EXP2):
+         /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
+         x = build_real (type, dconst2);
+         break;
+       CASE_FLT_FN (BUILT_IN_EXP10):
+       CASE_FLT_FN (BUILT_IN_POW10):
+        /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
+        {
+          REAL_VALUE_TYPE dconst10;
+          real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
+          x = build_real (type, dconst10);
+        }
+         break;
+       }
+     }
+    (mult (logs { x; }) @0))))
+ (for logs (LOG LOG
+            LOG2 LOG2
+           LOG10 LOG10)
+      exps (SQRT CBRT)
+  (simplify
+   (logs (exps @0))
+   (with {
+     tree x;
+     switch (exps)
+       {
+       CASE_FLT_FN (BUILT_IN_SQRT):
+        /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
+        x = build_real (type, dconsthalf);
+         break;
+       CASE_FLT_FN (BUILT_IN_CBRT):
+        /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
+         x = build_real (type, real_value_truncate (TYPE_MODE (type),
+                                                   dconst_third ()));
+         break;
+       }
+     }
+    (mult { x; } (logs @0)))))
+ /* logN(pow(x,exponent) -> exponent*logN(x).  */
+ (for logs (LOG LOG2 LOG10)
+      pows (POW)
+  (simplify
+   (logs (pows @0 @1))
+   (mult @1 (logs @0)))))
+
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c      (revision 218265)
+++ gcc/builtins.c      (working copy)
@@ -8375,99 +8375,6 @@ fold_builtin_bswap (tree fndecl, tree ar
   return NULL_TREE;
 }
 
-/* A subroutine of fold_builtin to fold the various logarithmic
-   functions.  Return NULL_TREE if no simplification can me made.
-   FUNC is the corresponding MPFR logarithm function.  */
-
-static tree
-fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
-                       int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
-{
-  if (validate_arg (arg, REAL_TYPE))
-    {
-      tree type = TREE_TYPE (TREE_TYPE (fndecl));
-      tree res;
-      const enum built_in_function fcode = builtin_mathfn_code (arg);
-
-      /* Calculate the result when the argument is a constant.  */
-      if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
-       return res;
-
-      /* Special case, optimize logN(expN(x)) = x.  */
-      if (flag_unsafe_math_optimizations
-         && ((func == mpfr_log
-              && (fcode == BUILT_IN_EXP
-                  || fcode == BUILT_IN_EXPF
-                  || fcode == BUILT_IN_EXPL))
-             || (func == mpfr_log2
-                 && (fcode == BUILT_IN_EXP2
-                     || fcode == BUILT_IN_EXP2F
-                     || fcode == BUILT_IN_EXP2L))
-             || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
-       return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
-
-      /* Optimize logN(func()) for various exponential functions.  We
-        want to determine the value "x" and the power "exponent" in
-        order to transform logN(x**exponent) into exponent*logN(x).  */
-      if (flag_unsafe_math_optimizations)
-       {
-         tree exponent = 0, x = 0;
-
-         switch (fcode)
-         {
-         CASE_FLT_FN (BUILT_IN_EXP):
-           /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
-           x = build_real (type, real_value_truncate (TYPE_MODE (type),
-                                                       dconst_e ()));
-           exponent = CALL_EXPR_ARG (arg, 0);
-           break;
-         CASE_FLT_FN (BUILT_IN_EXP2):
-           /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
-           x = build_real (type, dconst2);
-           exponent = CALL_EXPR_ARG (arg, 0);
-           break;
-         CASE_FLT_FN (BUILT_IN_EXP10):
-         CASE_FLT_FN (BUILT_IN_POW10):
-           /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
-           {
-             REAL_VALUE_TYPE dconst10;
-             real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
-             x = build_real (type, dconst10);
-           }
-           exponent = CALL_EXPR_ARG (arg, 0);
-           break;
-         CASE_FLT_FN (BUILT_IN_SQRT):
-           /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
-           x = CALL_EXPR_ARG (arg, 0);
-           exponent = build_real (type, dconsthalf);
-           break;
-         CASE_FLT_FN (BUILT_IN_CBRT):
-           /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
-           x = CALL_EXPR_ARG (arg, 0);
-           exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
-                                                             dconst_third ()));
-           break;
-         CASE_FLT_FN (BUILT_IN_POW):
-           /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
-           x = CALL_EXPR_ARG (arg, 0);
-           exponent = CALL_EXPR_ARG (arg, 1);
-           break;
-         default:
-           break;
-         }
-
-         /* Now perform the optimization.  */
-         if (x && exponent)
-           {
-             tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
-             return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
-           }
-       }
-    }
-
-  return NULL_TREE;
-}
-
 /* Fold a builtin function call to hypot, hypotf, or hypotl.  Return
    NULL_TREE if no simplification can be made.  */
 
@@ -10226,16 +10133,22 @@ fold_builtin_1 (location_t loc, tree fnd
     CASE_FLT_FN (BUILT_IN_EXPM1):
       if (validate_arg (arg0, REAL_TYPE))
        return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
-    break;
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG):
-    return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
+      if (validate_arg (arg0, REAL_TYPE))
+        return do_mpfr_arg1 (arg0, type, mpfr_log, &dconst0, NULL, false);
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG2):
-      return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
+      if (validate_arg (arg0, REAL_TYPE))
+        return do_mpfr_arg1 (arg0, type, mpfr_log2, &dconst0, NULL, false);
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG10):
-      return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
+      if (validate_arg (arg0, REAL_TYPE))
+        return do_mpfr_arg1 (arg0, type, mpfr_log10, &dconst0, NULL, false);
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG1P):
       if (validate_arg (arg0, REAL_TYPE))

Reply via email to