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:
parent
f29b9db93e
commit
67057c537b
8 changed files with 211 additions and 7 deletions
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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*.
|
||||
|
|
57
gcc/testsuite/gcc.dg/builtins-41.c
Normal file
57
gcc/testsuite/gcc.dg/builtins-41.c
Normal 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;
|
||||
}
|
||||
|
57
gcc/testsuite/gcc.dg/builtins-42.c
Normal file
57
gcc/testsuite/gcc.dg/builtins-42.c
Normal 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;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue