Commit 67057c53 by Roger Sayle Committed by Roger Sayle

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
parent f29b9db9
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.
......
......@@ -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;
}
......
......@@ -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)));
......
......@@ -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;
}
......@@ -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 */
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*.
......
/* 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;
}
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment