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.

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);

Reply via email to