diff mbox

Move more cproj simplifications to match.pd

Message ID 87eggpzzbk.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Oct. 20, 2015, 9:03 a.m. UTC
Richi and I both had patches for cproj.  I thought I might as well
post a rebased version of what I had, since for the other patches I'd
been moving the constant handling into fold_builtin_1 (where functions
without combinatorial folds also handled constants).  I'm hoping the
switch statement there will eventually become the switch statement
for folding a function with constant arguments.

The patch also makes build_complex_cproj available globally and uses it
for the existing match.pd rules.

Certainly not a big deal or a big improvement, but... tested on
x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.  OK to install?

Thanks,
Richard


gcc/
	* builtins.c (fold_builtin_cproj): Delete.
	(fold_builtin_1): Handle constant arguments here.
	(build_complex_cproj): Move to...
	* tree.c: ...here.
	* tree.h (build_complex_cproj): Declare.
	* match.pd: Fold cproj(x)->x if x has no infinity.
	Use build_complex_cproj for existing cproj rules.

Comments

Richard Biener Oct. 20, 2015, 9:41 a.m. UTC | #1
On Tue, Oct 20, 2015 at 11:03 AM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> Richi and I both had patches for cproj.  I thought I might as well
> post a rebased version of what I had, since for the other patches I'd
> been moving the constant handling into fold_builtin_1 (where functions
> without combinatorial folds also handled constants).  I'm hoping the
> switch statement there will eventually become the switch statement
> for folding a function with constant arguments.
>
> The patch also makes build_complex_cproj available globally and uses it
> for the existing match.pd rules.
>
> Certainly not a big deal or a big improvement, but... tested on
> x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.  OK to install?

Ok with build_complex_cproj renamed to sth more descriptive - build_complex_inf?
After all it builds a complex Inf with an imag -0 eventually.

Richard.

> Thanks,
> Richard
>
>
> gcc/
>         * builtins.c (fold_builtin_cproj): Delete.
>         (fold_builtin_1): Handle constant arguments here.
>         (build_complex_cproj): Move to...
>         * tree.c: ...here.
>         * tree.h (build_complex_cproj): Declare.
>         * match.pd: Fold cproj(x)->x if x has no infinity.
>         Use build_complex_cproj for existing cproj rules.
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index a9872c4..16f3bfd 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -7539,50 +7539,6 @@ fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
>    return NULL_TREE;
>  }
>
> -/* Build a complex (inf +- 0i) for the result of cproj.  TYPE is the
> -   complex tree type of the result.  If NEG is true, the imaginary
> -   zero is negative.  */
> -
> -static tree
> -build_complex_cproj (tree type, bool neg)
> -{
> -  REAL_VALUE_TYPE rinf, rzero = dconst0;
> -
> -  real_inf (&rinf);
> -  rzero.sign = neg;
> -  return build_complex (type, build_real (TREE_TYPE (type), rinf),
> -                       build_real (TREE_TYPE (type), rzero));
> -}
> -
> -/* Fold call to builtin cproj, cprojf or cprojl with argument ARG.  TYPE is the
> -   return type.  Return NULL_TREE if no simplification can be made.  */
> -
> -static tree
> -fold_builtin_cproj (location_t loc, tree arg, tree type)
> -{
> -  if (!validate_arg (arg, COMPLEX_TYPE)
> -      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
> -    return NULL_TREE;
> -
> -  /* If there are no infinities, return arg.  */
> -  if (! HONOR_INFINITIES (type))
> -    return non_lvalue_loc (loc, arg);
> -
> -  /* Calculate the result when the argument is a constant.  */
> -  if (TREE_CODE (arg) == COMPLEX_CST)
> -    {
> -      const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
> -      const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
> -
> -      if (real_isinf (real) || real_isinf (imag))
> -       return build_complex_cproj (type, imag->sign);
> -      else
> -       return arg;
> -    }
> -
> -  return NULL_TREE;
> -}
> -
>  /* Fold function call to builtin tan, tanf, or tanl with argument ARG.
>     Return NULL_TREE if no simplification can be made.  */
>
> @@ -9505,7 +9461,20 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
>        break;
>
>      CASE_FLT_FN (BUILT_IN_CPROJ):
> -      return fold_builtin_cproj (loc, arg0, type);
> +      if (TREE_CODE (arg0) == COMPLEX_CST
> +         && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
> +       {
> +         const REAL_VALUE_TYPE *real
> +           = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
> +         const REAL_VALUE_TYPE *imag
> +           = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
> +
> +         if (real_isinf (real) || real_isinf (imag))
> +           return build_complex_cproj (type, imag->sign);
> +         else
> +           return arg0;
> +       }
> +      break;
>
>      CASE_FLT_FN (BUILT_IN_CSIN):
>        if (validate_arg (arg0, COMPLEX_TYPE)
> diff --git a/gcc/match.pd b/gcc/match.pd
> index aaca3a0..7d16c52 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -2448,30 +2448,24 @@ along with GCC; see the file COPYING3.  If not see
>    (CABS (complex @0 @0))
>    (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })))
>
> +/* cproj(x) -> x if we're ignoring infinities.  */
> +(simplify
> + (CPROJ @0)
> + (if (!HONOR_INFINITIES (type))
> +   @0))
> +
>  /* If the real part is inf and the imag part is known to be
>     nonnegative, return (inf + 0i).  */
>  (simplify
>   (CPROJ (complex REAL_CST@0 tree_expr_nonnegative_p@1))
>   (if (real_isinf (TREE_REAL_CST_PTR (@0)))
> -  (with
> -    {
> -      REAL_VALUE_TYPE rinf;
> -      real_inf (&rinf);
> -    }
> -   { build_complex (type, build_real (TREE_TYPE (type), rinf),
> -                   build_zero_cst (TREE_TYPE (type))); })))
> +  { build_complex_cproj (type, false); }))
> +
>  /* If the imag part is inf, return (inf+I*copysign(0,imag)).  */
>  (simplify
>   (CPROJ (complex @0 REAL_CST@1))
>   (if (real_isinf (TREE_REAL_CST_PTR (@1)))
> -  (with
> -    {
> -      REAL_VALUE_TYPE rinf, rzero = dconst0;
> -      real_inf (&rinf);
> -      rzero.sign = TREE_REAL_CST_PTR (@1)->sign;
> -    }
> -   { build_complex (type, build_real (TREE_TYPE (type), rinf),
> -                   build_real (TREE_TYPE (type), rzero)); })))
> +  { build_complex_cproj (type, TREE_REAL_CST_PTR (@1)->sign); }))
>
>
>  /* Narrowing of arithmetic and logical operations.
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 9d0e9de..1405328 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -1986,6 +1986,21 @@ build_complex (tree type, tree real, tree imag)
>    return t;
>  }
>
> +/* Build a complex (inf +- 0i) for the result of cproj.  TYPE is the
> +   complex tree type of the result.  If NEG is true, the imaginary
> +   zero is negative.  */
> +
> +tree
> +build_complex_cproj (tree type, bool neg)
> +{
> +  REAL_VALUE_TYPE rinf, rzero = dconst0;
> +
> +  real_inf (&rinf);
> +  rzero.sign = neg;
> +  return build_complex (type, build_real (TREE_TYPE (type), rinf),
> +                       build_real (TREE_TYPE (type), rzero));
> +}
> +
>  /* Return the constant 1 in type TYPE.  If TYPE has several elements, each
>     element is set to 1.  In particular, this is 1 + i for complex types.  */
>
> diff --git a/gcc/tree.h b/gcc/tree.h
> index f62cd27..2dbd81b 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -3847,6 +3847,7 @@ extern tree build_constructor_from_list (tree, tree);
>  extern tree build_constructor_va (tree, int, ...);
>  extern tree build_real_from_int_cst (tree, const_tree);
>  extern tree build_complex (tree, tree, tree);
> +extern tree build_complex_cproj (tree, bool);
>  extern tree build_each_one_cst (tree);
>  extern tree build_one_cst (tree);
>  extern tree build_minus_one_cst (tree);
>
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index a9872c4..16f3bfd 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -7539,50 +7539,6 @@  fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
   return NULL_TREE;
 }
 
-/* Build a complex (inf +- 0i) for the result of cproj.  TYPE is the
-   complex tree type of the result.  If NEG is true, the imaginary
-   zero is negative.  */
-
-static tree
-build_complex_cproj (tree type, bool neg)
-{
-  REAL_VALUE_TYPE rinf, rzero = dconst0;
-  
-  real_inf (&rinf);
-  rzero.sign = neg;
-  return build_complex (type, build_real (TREE_TYPE (type), rinf),
-			build_real (TREE_TYPE (type), rzero));
-}
-
-/* Fold call to builtin cproj, cprojf or cprojl with argument ARG.  TYPE is the
-   return type.  Return NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_cproj (location_t loc, tree arg, tree type)
-{
-  if (!validate_arg (arg, COMPLEX_TYPE)
-      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
-    return NULL_TREE;
-
-  /* If there are no infinities, return arg.  */
-  if (! HONOR_INFINITIES (type))
-    return non_lvalue_loc (loc, arg);
-
-  /* Calculate the result when the argument is a constant.  */
-  if (TREE_CODE (arg) == COMPLEX_CST)
-    {
-      const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
-      const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
-      
-      if (real_isinf (real) || real_isinf (imag))
-	return build_complex_cproj (type, imag->sign);
-      else
-	return arg;
-    }
-
-  return NULL_TREE;
-}
-
 /* Fold function call to builtin tan, tanf, or tanl with argument ARG.
    Return NULL_TREE if no simplification can be made.  */
 
@@ -9505,7 +9461,20 @@  fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
       break;
 
     CASE_FLT_FN (BUILT_IN_CPROJ):
-      return fold_builtin_cproj (loc, arg0, type);
+      if (TREE_CODE (arg0) == COMPLEX_CST
+	  && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+	{
+	  const REAL_VALUE_TYPE *real
+	    = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
+	  const REAL_VALUE_TYPE *imag
+	    = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
+
+	  if (real_isinf (real) || real_isinf (imag))
+	    return build_complex_cproj (type, imag->sign);
+	  else
+	    return arg0;
+	}
+      break;
 
     CASE_FLT_FN (BUILT_IN_CSIN):
       if (validate_arg (arg0, COMPLEX_TYPE)
diff --git a/gcc/match.pd b/gcc/match.pd
index aaca3a0..7d16c52 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2448,30 +2448,24 @@  along with GCC; see the file COPYING3.  If not see
   (CABS (complex @0 @0))
   (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })))
 
+/* cproj(x) -> x if we're ignoring infinities.  */
+(simplify
+ (CPROJ @0)
+ (if (!HONOR_INFINITIES (type))
+   @0))
+
 /* If the real part is inf and the imag part is known to be
    nonnegative, return (inf + 0i).  */
 (simplify
  (CPROJ (complex REAL_CST@0 tree_expr_nonnegative_p@1))
  (if (real_isinf (TREE_REAL_CST_PTR (@0)))
-  (with
-    {
-      REAL_VALUE_TYPE rinf;
-      real_inf (&rinf);
-    }
-   { build_complex (type, build_real (TREE_TYPE (type), rinf),
-		    build_zero_cst (TREE_TYPE (type))); })))
+  { build_complex_cproj (type, false); }))
+
 /* If the imag part is inf, return (inf+I*copysign(0,imag)).  */
 (simplify
  (CPROJ (complex @0 REAL_CST@1))
  (if (real_isinf (TREE_REAL_CST_PTR (@1)))
-  (with
-    {
-      REAL_VALUE_TYPE rinf, rzero = dconst0;
-      real_inf (&rinf);
-      rzero.sign = TREE_REAL_CST_PTR (@1)->sign;
-    }
-   { build_complex (type, build_real (TREE_TYPE (type), rinf),
-		    build_real (TREE_TYPE (type), rzero)); })))
+  { build_complex_cproj (type, TREE_REAL_CST_PTR (@1)->sign); }))
 
 
 /* Narrowing of arithmetic and logical operations. 
diff --git a/gcc/tree.c b/gcc/tree.c
index 9d0e9de..1405328 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1986,6 +1986,21 @@  build_complex (tree type, tree real, tree imag)
   return t;
 }
 
+/* Build a complex (inf +- 0i) for the result of cproj.  TYPE is the
+   complex tree type of the result.  If NEG is true, the imaginary
+   zero is negative.  */
+
+tree
+build_complex_cproj (tree type, bool neg)
+{
+  REAL_VALUE_TYPE rinf, rzero = dconst0;
+
+  real_inf (&rinf);
+  rzero.sign = neg;
+  return build_complex (type, build_real (TREE_TYPE (type), rinf),
+			build_real (TREE_TYPE (type), rzero));
+}
+
 /* Return the constant 1 in type TYPE.  If TYPE has several elements, each
    element is set to 1.  In particular, this is 1 + i for complex types.  */
 
diff --git a/gcc/tree.h b/gcc/tree.h
index f62cd27..2dbd81b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3847,6 +3847,7 @@  extern tree build_constructor_from_list (tree, tree);
 extern tree build_constructor_va (tree, int, ...);
 extern tree build_real_from_int_cst (tree, const_tree);
 extern tree build_complex (tree, tree, tree);
+extern tree build_complex_cproj (tree, bool);
 extern tree build_each_one_cst (tree);
 extern tree build_one_cst (tree);
 extern tree build_minus_one_cst (tree);