diff mbox

Move cexp simplifications to match.pd

Message ID 87611xy6ch.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Oct. 23, 2015, 3:03 p.m. UTC
This required reinstating support for captures in the result
of a simplification.  That part (genmatch.c) is by Richard B.

Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.
OK to install?

Thanks,
Richard


gcc/
2015-10-20  Richard Sandiford  <richard.sandiford@arm.com>
	    Richard Biener  <rguenther@suse.de>

	* genmatch.c (dt_simplify::gen): Skip captures that are
	part of the result.
	(parser::parse_expr): Allow captures in results too.
	* builtins.c (fold_builtin_cexp): Delete.
	(fold_builtin_1): Handle constant cexp arguments here.
	* match.pd: Fold cexp(x+yi) to exp(x) * cexpi(y).

Comments

Richard Biener Oct. 26, 2015, 8:55 a.m. UTC | #1
On Fri, Oct 23, 2015 at 5:03 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> This required reinstating support for captures in the result
> of a simplification.  That part (genmatch.c) is by Richard B.
>
> Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.
> OK to install?
>
> Thanks,
> Richard
>
>
> gcc/
> 2015-10-20  Richard Sandiford  <richard.sandiford@arm.com>
>             Richard Biener  <rguenther@suse.de>
>
>         * genmatch.c (dt_simplify::gen): Skip captures that are
>         part of the result.
>         (parser::parse_expr): Allow captures in results too.
>         * builtins.c (fold_builtin_cexp): Delete.
>         (fold_builtin_1): Handle constant cexp arguments here.
>         * match.pd: Fold cexp(x+yi) to exp(x) * cexpi(y).
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index 02bf9f6..e5e65ba 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -7577,74 +7577,6 @@ fold_builtin_sincos (location_t loc,
>                          build1 (REALPART_EXPR, type, call)));
>  }
>
> -/* Fold function call to builtin cexp, cexpf, or cexpl.  Return
> -   NULL_TREE if no simplification can be made.  */
> -
> -static tree
> -fold_builtin_cexp (location_t loc, tree arg0, tree type)
> -{
> -  tree rtype;
> -  tree realp, imagp, ifn;
> -  tree res;
> -
> -  if (!validate_arg (arg0, COMPLEX_TYPE)
> -      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
> -    return NULL_TREE;
> -
> -  /* Calculate the result when the argument is a constant.  */
> -  if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
> -    return res;
> -
> -  rtype = TREE_TYPE (TREE_TYPE (arg0));
> -
> -  /* In case we can figure out the real part of arg0 and it is constant zero
> -     fold to cexpi.  */
> -  if (!targetm.libc_has_function (function_c99_math_complex))
> -    return NULL_TREE;
> -  ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
> -  if (!ifn)
> -    return NULL_TREE;
> -
> -  if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
> -      && real_zerop (realp))
> -    {
> -      tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
> -      return build_call_expr_loc (loc, ifn, 1, narg);
> -    }
> -
> -  /* In case we can easily decompose real and imaginary parts split cexp
> -     to exp (r) * cexpi (i).  */
> -  if (flag_unsafe_math_optimizations
> -      && realp)
> -    {
> -      tree rfn, rcall, icall;
> -
> -      rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
> -      if (!rfn)
> -       return NULL_TREE;
> -
> -      imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
> -      if (!imagp)
> -       return NULL_TREE;
> -
> -      icall = build_call_expr_loc (loc, ifn, 1, imagp);
> -      icall = builtin_save_expr (icall);
> -      rcall = build_call_expr_loc (loc, rfn, 1, realp);
> -      rcall = builtin_save_expr (rcall);
> -      return fold_build2_loc (loc, COMPLEX_EXPR, type,
> -                         fold_build2_loc (loc, MULT_EXPR, rtype,
> -                                      rcall,
> -                                      fold_build1_loc (loc, REALPART_EXPR,
> -                                                   rtype, icall)),
> -                         fold_build2_loc (loc, MULT_EXPR, rtype,
> -                                      rcall,
> -                                      fold_build1_loc (loc, IMAGPART_EXPR,
> -                                                   rtype, icall)));
> -    }
> -
> -  return NULL_TREE;
> -}
> -
>  /* Fold function call to builtin trunc, truncf or truncl with argument ARG.
>     Return NULL_TREE if no simplification can be made.  */
>
> @@ -9589,7 +9521,10 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
>        break;
>
>      CASE_FLT_FN (BUILT_IN_CEXP):
> -      return fold_builtin_cexp (loc, arg0, type);
> +      if (validate_arg (arg0, COMPLEX_TYPE)
> +         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
> +       return do_mpc_arg1 (arg0, type, mpc_exp);
> +      break;
>
>      CASE_FLT_FN (BUILT_IN_CEXPI):
>        if (validate_arg (arg0, REAL_TYPE))
> diff --git a/gcc/genmatch.c b/gcc/genmatch.c
> index b05760e..b5a0fff 100644
> --- a/gcc/genmatch.c
> +++ b/gcc/genmatch.c
> @@ -3163,7 +3163,11 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
>                       s->capture_max + 1, indexes[0]->get_name (opname));
>
>        for (int i = 1; i <= s->capture_max; ++i)
> -       fprintf (f, ", %s", indexes[i]->get_name (opname));
> +       {
> +         if (!indexes[i])
> +           break;
> +         fprintf (f, ", %s", indexes[i]->get_name (opname));
> +       }
>        fprintf (f, " };\n");
>      }
>
> @@ -3831,7 +3835,7 @@ parser::parse_expr ()
>
>    if (token->type == CPP_ATSIGN
>        && !(token->flags & PREV_WHITE))
> -    op = parse_capture (e, !parsing_match_operand);
> +    op = parse_capture (e, false);
>    else if (force_capture)
>      {
>        unsigned num = capture_ids->elements ();
> diff --git a/gcc/match.pd b/gcc/match.pd
> index b399786..98bb903 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3.  If not see
>  (define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL)
>  (define_operator_list ATAN BUILT_IN_ATANF BUILT_IN_ATAN BUILT_IN_ATANL)
>  (define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL)
> +(define_operator_list CEXP BUILT_IN_CEXPF BUILT_IN_CEXP BUILT_IN_CEXPL)
>  (define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL)
>  (define_operator_list CPROJ BUILT_IN_CPROJF BUILT_IN_CPROJ BUILT_IN_CPROJL)
>  (define_operator_list CCOS BUILT_IN_CCOSF BUILT_IN_CCOS BUILT_IN_CCOSL)
> @@ -1530,6 +1531,11 @@ along with GCC; see the file COPYING3.  If not see
>   (mult @0 integer_minus_onep)
>   (negate @0))
>
> +/* True if we can easily extract the real and imaginary parts of a complex
> +   number.  */
> +(match (compositional_complex)

argument-less predicates should have their name not parentized

> + (convert?:s (complex @0 @1)))

:s has no effect in (match ...), so you can drop it.

Ok with those changes.

Richard.

> +
>  /* COMPLEX_EXPR and REALPART/IMAGPART_EXPR cancellations.  */
>  (simplify
>   (complex (realpart @0) (imagpart @0))
> @@ -2535,7 +2541,18 @@ along with GCC; see the file COPYING3.  If not see
>   /* cabs(x+xi) -> fabs(x)*sqrt(2).  */
>   (simplify
>    (CABS (complex @0 @0))
> -  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })))
> +  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))
> +
> + /* cexp(x+yi) -> exp(x)*cexpi(y).  */
> + (for cexps (CEXP)
> +      exps (EXP)
> +      cexpis (CEXPI)
> +  (simplify
> +   (cexps compositional_complex@0)
> +   (if (targetm.libc_has_function (function_c99_math_complex))
> +    (complex
> +     (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0))))
> +     (mult @1 (imagpart @2)))))))
>
>  /* cproj(x) -> x if we're ignoring infinities.  */
>  (simplify
>
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 02bf9f6..e5e65ba 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -7577,74 +7577,6 @@  fold_builtin_sincos (location_t loc,
 			 build1 (REALPART_EXPR, type, call)));
 }
 
-/* Fold function call to builtin cexp, cexpf, or cexpl.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_cexp (location_t loc, tree arg0, tree type)
-{
-  tree rtype;
-  tree realp, imagp, ifn;
-  tree res;
-
-  if (!validate_arg (arg0, COMPLEX_TYPE)
-      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
-    return NULL_TREE;
-
-  /* Calculate the result when the argument is a constant.  */
-  if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
-    return res;
-
-  rtype = TREE_TYPE (TREE_TYPE (arg0));
-
-  /* In case we can figure out the real part of arg0 and it is constant zero
-     fold to cexpi.  */
-  if (!targetm.libc_has_function (function_c99_math_complex))
-    return NULL_TREE;
-  ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
-  if (!ifn)
-    return NULL_TREE;
-
-  if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
-      && real_zerop (realp))
-    {
-      tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
-      return build_call_expr_loc (loc, ifn, 1, narg);
-    }
-
-  /* In case we can easily decompose real and imaginary parts split cexp
-     to exp (r) * cexpi (i).  */
-  if (flag_unsafe_math_optimizations
-      && realp)
-    {
-      tree rfn, rcall, icall;
-
-      rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
-      if (!rfn)
-	return NULL_TREE;
-
-      imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
-      if (!imagp)
-	return NULL_TREE;
-
-      icall = build_call_expr_loc (loc, ifn, 1, imagp);
-      icall = builtin_save_expr (icall);
-      rcall = build_call_expr_loc (loc, rfn, 1, realp);
-      rcall = builtin_save_expr (rcall);
-      return fold_build2_loc (loc, COMPLEX_EXPR, type,
-			  fold_build2_loc (loc, MULT_EXPR, rtype,
-				       rcall,
-			 	       fold_build1_loc (loc, REALPART_EXPR,
-						    rtype, icall)),
-			  fold_build2_loc (loc, MULT_EXPR, rtype,
-				       rcall,
-				       fold_build1_loc (loc, IMAGPART_EXPR,
-						    rtype, icall)));
-    }
-
-  return NULL_TREE;
-}
-
 /* Fold function call to builtin trunc, truncf or truncl with argument ARG.
    Return NULL_TREE if no simplification can be made.  */
 
@@ -9589,7 +9521,10 @@  fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
       break;
 
     CASE_FLT_FN (BUILT_IN_CEXP):
-      return fold_builtin_cexp (loc, arg0, type);
+      if (validate_arg (arg0, COMPLEX_TYPE)
+	  && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+	return do_mpc_arg1 (arg0, type, mpc_exp);
+      break;
 
     CASE_FLT_FN (BUILT_IN_CEXPI):
       if (validate_arg (arg0, REAL_TYPE))
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index b05760e..b5a0fff 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -3163,7 +3163,11 @@  dt_simplify::gen (FILE *f, int indent, bool gimple)
 		      s->capture_max + 1, indexes[0]->get_name (opname));
 
       for (int i = 1; i <= s->capture_max; ++i)
-	fprintf (f, ", %s", indexes[i]->get_name (opname));
+	{
+	  if (!indexes[i])
+	    break;
+	  fprintf (f, ", %s", indexes[i]->get_name (opname));
+	}
       fprintf (f, " };\n");
     }
 
@@ -3831,7 +3835,7 @@  parser::parse_expr ()
 
   if (token->type == CPP_ATSIGN
       && !(token->flags & PREV_WHITE))
-    op = parse_capture (e, !parsing_match_operand);
+    op = parse_capture (e, false);
   else if (force_capture)
     {
       unsigned num = capture_ids->elements ();
diff --git a/gcc/match.pd b/gcc/match.pd
index b399786..98bb903 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -61,6 +61,7 @@  along with GCC; see the file COPYING3.  If not see
 (define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL)
 (define_operator_list ATAN BUILT_IN_ATANF BUILT_IN_ATAN BUILT_IN_ATANL)
 (define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL)
+(define_operator_list CEXP BUILT_IN_CEXPF BUILT_IN_CEXP BUILT_IN_CEXPL)
 (define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL)
 (define_operator_list CPROJ BUILT_IN_CPROJF BUILT_IN_CPROJ BUILT_IN_CPROJL)
 (define_operator_list CCOS BUILT_IN_CCOSF BUILT_IN_CCOS BUILT_IN_CCOSL)
@@ -1530,6 +1531,11 @@  along with GCC; see the file COPYING3.  If not see
  (mult @0 integer_minus_onep)
  (negate @0))
 
+/* True if we can easily extract the real and imaginary parts of a complex
+   number.  */
+(match (compositional_complex)
+ (convert?:s (complex @0 @1)))
+
 /* COMPLEX_EXPR and REALPART/IMAGPART_EXPR cancellations.  */
 (simplify
  (complex (realpart @0) (imagpart @0))
@@ -2535,7 +2541,18 @@  along with GCC; see the file COPYING3.  If not see
  /* cabs(x+xi) -> fabs(x)*sqrt(2).  */
  (simplify
   (CABS (complex @0 @0))
-  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })))
+  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))
+
+ /* cexp(x+yi) -> exp(x)*cexpi(y).  */
+ (for cexps (CEXP)
+      exps (EXP)
+      cexpis (CEXPI)
+  (simplify
+   (cexps compositional_complex@0)
+   (if (targetm.libc_has_function (function_c99_math_complex))
+    (complex
+     (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0))))
+     (mult @1 (imagpart @2)))))))
 
 /* cproj(x) -> x if we're ignoring infinities.  */
 (simplify