real.c (real_copysign): New function to implement libm's copysign.

* 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}.

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

From-SVN: r82721
This commit is contained in:
Roger Sayle 2004-06-07 20:50:14 +00:00 committed by Roger Sayle
parent f29b9db93e
commit 67057c537b
8 changed files with 211 additions and 7 deletions

View 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.

View 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;
}

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

View 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;
}

View 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 */

View 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*.

View file

@ -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;
}

View file

@ -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;
}