OSDN Git Service

* real.c (real_copysign): New function to implement libm's copysign.
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Jun 2004 20:50:14 +0000 (20:50 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 7 Jun 2004 20:50:14 +0000 (20:50 +0000)
* real.h (real_copysign): Prototype here.
* fold-const.c (tree_expr_nonnegative_p): The result of sqrt, sqrtf
and sqrtl can be negative, as sqrt(-0.0) = -0.0.  Correct whitespace.
* builtins.c (fold_builtin_isascii, fold_builtin_toascii,
fold_builtin_isdigit): Add function prototypes.
(fold_builtin_copysign): New function to fold copysign, copysignf
and copysignl.  Optimize copysign(x,x) as x.  Evaluate copysign of
constant arguments at compile-time using real_copysign.  Fold
copysign(X,Y) as fabs(X) if Y is always non-negative.
(fold_builtin_1): Correct minor whitespace/style issues.  Call
fold_builtin_copysign for BUILT_IN_COPYSIGN{,F,L}.

* gcc.dg/builtins-41.c: New test case.
* gcc.dg/builtins-42.c: New test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@82721 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/fold-const.c
gcc/real.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-41.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-42.c [new file with mode: 0644]

index d15e179..a119116 100644 (file)
@@ -1,3 +1,18 @@
+2004-06-07  Roger Sayle  <roger@eyesopen.com>
+
+       * real.c (real_copysign): New function to implement libm's copysign.
+       * real.h (real_copysign): Prototype here.
+       * fold-const.c (tree_expr_nonnegative_p): The result of sqrt, sqrtf
+       and sqrtl can be negative, as sqrt(-0.0) = -0.0.  Correct whitespace.
+       * builtins.c (fold_builtin_isascii, fold_builtin_toascii,
+       fold_builtin_isdigit): Add function prototypes.
+       (fold_builtin_copysign): New function to fold copysign, copysignf
+       and copysignl.  Optimize copysign(x,x) as x.  Evaluate copysign of
+       constant arguments at compile-time using real_copysign.  Fold
+       copysign(X,Y) as fabs(X) if Y is always non-negative.
+       (fold_builtin_1): Correct minor whitespace/style issues.  Call
+       fold_builtin_copysign for BUILT_IN_COPYSIGN{,F,L}.
+
 2004-06-07  J"orn Rennecke <joern.rennecke@superh.com>
 
        * tree.c (iterative_hash_expr): Use real_hash.
index e265186..d10924f 100644 (file)
@@ -162,6 +162,10 @@ static tree fold_builtin_memcmp (tree);
 static tree fold_builtin_strcmp (tree);
 static tree fold_builtin_strncmp (tree);
 static tree fold_builtin_signbit (tree);
+static tree fold_builtin_copysign (tree, tree);
+static tree fold_builtin_isascii (tree);
+static tree fold_builtin_toascii (tree);
+static tree fold_builtin_isdigit (tree);
 
 static tree simplify_builtin_memcmp (tree);
 static tree simplify_builtin_strcmp (tree);
@@ -7298,6 +7302,49 @@ fold_builtin_signbit (tree exp)
   return NULL_TREE;
 }
 
+/* Fold function call to builtin copysign, copysignf or copysignl.
+   Return NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_copysign (tree arglist, tree type)
+{
+  tree arg1, arg2;
+
+  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+    return NULL_TREE;
+
+  arg1 = TREE_VALUE (arglist);
+  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+
+  /* copysign(X,X) is X.  */
+  if (operand_equal_p (arg1, arg2, 0))
+    return fold_convert (type, arg1);
+
+  /* If ARG1 and ARG2 are compile-time constants, determine the result.  */
+  if (TREE_CODE (arg1) == REAL_CST
+      && TREE_CODE (arg2) == REAL_CST
+      && !TREE_CONSTANT_OVERFLOW (arg1)
+      && !TREE_CONSTANT_OVERFLOW (arg2))
+    {
+      REAL_VALUE_TYPE c1, c2;
+
+      c1 = TREE_REAL_CST (arg1);
+      c2 = TREE_REAL_CST (arg2);
+      real_copysign (&c1, &c2);
+      return build_real (type, c1);
+      c1.sign = c2.sign;
+    }
+
+  /* copysign(X, Y) is fabs(X) when Y is always non-negative.
+     Remember to evaluate Y for side-effects.  */
+  if (tree_expr_nonnegative_p (arg2))
+    return omit_one_operand (type,
+                            fold (build1 (ABS_EXPR, type, arg1)),
+                            arg2);
+
+  return NULL_TREE;
+}
+
 /* Fold a call to builtin isascii.  */
 
 static tree
@@ -7577,10 +7624,12 @@ fold_builtin_1 (tree exp)
     case BUILT_IN_EXPF:
     case BUILT_IN_EXPL:
       return fold_builtin_exponent (exp, &dconste);
+
     case BUILT_IN_EXP2:
     case BUILT_IN_EXP2F:
     case BUILT_IN_EXP2L:
       return fold_builtin_exponent (exp, &dconst2);
+
     case BUILT_IN_EXP10:
     case BUILT_IN_EXP10F:
     case BUILT_IN_EXP10L:
@@ -7588,21 +7637,21 @@ fold_builtin_1 (tree exp)
     case BUILT_IN_POW10F:
     case BUILT_IN_POW10L:
       return fold_builtin_exponent (exp, &dconst10);
+
     case BUILT_IN_LOG:
     case BUILT_IN_LOGF:
     case BUILT_IN_LOGL:
       return fold_builtin_logarithm (exp, &dconste);
-      break;
+
     case BUILT_IN_LOG2:
     case BUILT_IN_LOG2F:
     case BUILT_IN_LOG2L:
       return fold_builtin_logarithm (exp, &dconst2);
-      break;
+
     case BUILT_IN_LOG10:
     case BUILT_IN_LOG10F:
     case BUILT_IN_LOG10L:
       return fold_builtin_logarithm (exp, &dconst10);
-      break;
 
     case BUILT_IN_TAN:
     case BUILT_IN_TANF:
@@ -7884,6 +7933,11 @@ fold_builtin_1 (tree exp)
     case BUILT_IN_ISDIGIT:
       return fold_builtin_isdigit (arglist);
 
+    case BUILT_IN_COPYSIGN:
+    case BUILT_IN_COPYSIGNF:
+    case BUILT_IN_COPYSIGNL:
+      return fold_builtin_copysign (arglist, type);
+
     default:
       break;
     }
index b0d1db2..6eee710 100644 (file)
@@ -9024,13 +9024,18 @@ tree_expr_nonnegative_p (tree t)
            CASE_BUILTIN_F (BUILT_IN_FREXP)
            CASE_BUILTIN_F (BUILT_IN_HYPOT)
            CASE_BUILTIN_F (BUILT_IN_POW10)
-           CASE_BUILTIN_F (BUILT_IN_SQRT)
            CASE_BUILTIN_I (BUILT_IN_FFS)
            CASE_BUILTIN_I (BUILT_IN_PARITY)
            CASE_BUILTIN_I (BUILT_IN_POPCOUNT)
              /* Always true.  */
              return 1;
 
+           CASE_BUILTIN_F (BUILT_IN_SQRT)
+             /* sqrt(-0.0) is -0.0.  */
+             if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (t))))
+               return 1;
+             return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+
            CASE_BUILTIN_F (BUILT_IN_ASINH)
            CASE_BUILTIN_F (BUILT_IN_ATAN)
            CASE_BUILTIN_F (BUILT_IN_ATANH)
@@ -9057,17 +9062,17 @@ tree_expr_nonnegative_p (tree t)
              /* True if the 1st argument is nonnegative.  */
              return tree_expr_nonnegative_p (TREE_VALUE (arglist));
 
-           CASE_BUILTIN_F(BUILT_IN_FMAX)
+           CASE_BUILTIN_F (BUILT_IN_FMAX)
              /* True if the 1st OR 2nd arguments are nonnegative.  */
              return tree_expr_nonnegative_p (TREE_VALUE (arglist))
                || tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
 
-           CASE_BUILTIN_F(BUILT_IN_FMIN)
+           CASE_BUILTIN_F (BUILT_IN_FMIN)
              /* True if the 1st AND 2nd arguments are nonnegative.  */
              return tree_expr_nonnegative_p (TREE_VALUE (arglist))
                && tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
 
-           CASE_BUILTIN_F(BUILT_IN_COPYSIGN)
+           CASE_BUILTIN_F (BUILT_IN_COPYSIGN)
              /* True if the 2nd argument is nonnegative.  */
              return tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
 
index e702b2d..65d57c3 100644 (file)
@@ -4587,3 +4587,11 @@ real_round (REAL_VALUE_TYPE *r, enum machine_mode mode,
     real_convert (r, mode, r);
 }
 
+/* Set the sign of R to the sign of X.  */
+
+void
+real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x)
+{
+  r->sign = x->sign;
+}
+
index 475ab45..4200e5e 100644 (file)
@@ -384,4 +384,7 @@ extern void real_ceil (REAL_VALUE_TYPE *, enum machine_mode,
 extern void real_round (REAL_VALUE_TYPE *, enum machine_mode,
                        const REAL_VALUE_TYPE *);
 
+/* Set the sign of R to the sign of X.  */
+extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+
 #endif /* ! GCC_REAL_H */
index 1770f63..35bf511 100644 (file)
@@ -1,3 +1,8 @@
+2004-06-07  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/builtins-41.c: New test case.
+       * gcc.dg/builtins-42.c: New test case.
+
 2004-06-07  David Edelsohn  <edelsohn@gnu.org>
 
        * g++.dg/ext/altivec-1.C: XFAIL powerpc-ibm-aix*.
diff --git a/gcc/testsuite/gcc.dg/builtins-41.c b/gcc/testsuite/gcc.dg/builtins-41.c
new file mode 100644 (file)
index 0000000..5b96551
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+   Check that constant folding of copysign, copysignf and copysignl math
+   functions doesn't break anything and produces the expected results.
+
+   Written by Roger Sayle, 6th June 2004.  */
+
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern void link_error(void);
+
+extern double copysign(double, double);
+extern float copysignf(float, float);
+extern long double copysignl(long double, long double);
+
+int main()
+{
+  if (copysign (2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (2.0, -1.0) != -2.0)
+    link_error ();
+  if (copysign (-2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (-2.0, -1.0) != -2.0)
+    link_error ();
+
+  if (copysign (2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (2.0, -1.0) != -2.0)
+    link_error ();
+  if (copysign (-2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (-2.0, -1.0) != -2.0)
+    link_error ();
+
+  if (copysignf (2.0f, 1.0f) != 2.0f)
+    link_error ();
+  if (copysignf (2.0f, -1.0f) != -2.0f)
+    link_error ();
+  if (copysignf (-2.0f, 1.0f) != 2.0f)
+    link_error ();
+  if (copysignf (-2.0f, -1.0f) != -2.0f)
+    link_error ();
+
+  if (copysignl (2.0l, 1.0l) != 2.0l)
+    link_error ();
+  if (copysignl (2.0l, -1.0l) != -2.0l)
+    link_error ();
+  if (copysignl (-2.0l, 1.0l) != 2.0l)
+    link_error ();
+  if (copysignl (-2.0l, -1.0l) != -2.0l)
+    link_error ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/builtins-42.c b/gcc/testsuite/gcc.dg/builtins-42.c
new file mode 100644 (file)
index 0000000..5b96551
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+   Check that constant folding of copysign, copysignf and copysignl math
+   functions doesn't break anything and produces the expected results.
+
+   Written by Roger Sayle, 6th June 2004.  */
+
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern void link_error(void);
+
+extern double copysign(double, double);
+extern float copysignf(float, float);
+extern long double copysignl(long double, long double);
+
+int main()
+{
+  if (copysign (2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (2.0, -1.0) != -2.0)
+    link_error ();
+  if (copysign (-2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (-2.0, -1.0) != -2.0)
+    link_error ();
+
+  if (copysign (2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (2.0, -1.0) != -2.0)
+    link_error ();
+  if (copysign (-2.0, 1.0) != 2.0)
+    link_error ();
+  if (copysign (-2.0, -1.0) != -2.0)
+    link_error ();
+
+  if (copysignf (2.0f, 1.0f) != 2.0f)
+    link_error ();
+  if (copysignf (2.0f, -1.0f) != -2.0f)
+    link_error ();
+  if (copysignf (-2.0f, 1.0f) != 2.0f)
+    link_error ();
+  if (copysignf (-2.0f, -1.0f) != -2.0f)
+    link_error ();
+
+  if (copysignl (2.0l, 1.0l) != 2.0l)
+    link_error ();
+  if (copysignl (2.0l, -1.0l) != -2.0l)
+    link_error ();
+  if (copysignl (-2.0l, 1.0l) != 2.0l)
+    link_error ();
+  if (copysignl (-2.0l, -1.0l) != -2.0l)
+    link_error ();
+
+  return 0;
+}
+