From e3bb43c0fef35c410538453c6a70a22822e03b10 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Wed, 9 Feb 2005 21:56:35 +0000 Subject: [PATCH] fold-const.c (fold_strip_sign_ops): New function to simplify a floating point expression ignoring the sign of the... * fold-const.c (fold_strip_sign_ops): New function to simplify a floating point expression ignoring the sign of the result. (fold) : Use it to simplify fabs(x). (fold) : Use it to simplify x*x. * tree.h (fold_strip_sign_ops): Prototype here. * builtins.c (fold_builtin_copysign): Take an additional FNDECL argument. Use fold_strip_sign_ops to simplify the first argument. (fold_builtin_pow): Use fold_strip_sign_ops to simplify the first argument when the second argument is an even integer constant, but only with -funsafe_math_optimizations. (fold_builtin_1): Update call to fold_builtin_copysign. * gcc.dg/builtins-48.c: New test case. * gcc.dg/builtins-49.c: New test case. * gcc.dg/builtins-50.c: New test case. * gcc.dg/builtins-51.c: New test case. From-SVN: r94779 --- gcc/ChangeLog | 15 ++- gcc/builtins.c | 48 +++++--- gcc/fold-const.c | 54 +++++++++ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.dg/builtins-48.c | 181 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/builtins-49.c | 181 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/builtins-50.c | 159 +++++++++++++++++++++++++ gcc/testsuite/gcc.dg/builtins-51.c | 157 +++++++++++++++++++++++++ gcc/tree.h | 3 +- 9 files changed, 789 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtins-48.c create mode 100644 gcc/testsuite/gcc.dg/builtins-49.c create mode 100644 gcc/testsuite/gcc.dg/builtins-50.c create mode 100644 gcc/testsuite/gcc.dg/builtins-51.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 37d3e05899a..f9d60dfd78d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-02-09 Roger Sayle + + * fold-const.c (fold_strip_sign_ops): New function to simplify a + floating point expression ignoring the sign of the result. + (fold) : Use it to simplify fabs(x). + (fold) : Use it to simplify x*x. + * tree.h (fold_strip_sign_ops): Prototype here. + * builtins.c (fold_builtin_copysign): Take an additional FNDECL + argument. Use fold_strip_sign_ops to simplify the first argument. + (fold_builtin_pow): Use fold_strip_sign_ops to simplify the + first argument when the second argument is an even integer + constant, but only with -funsafe_math_optimizations. + (fold_builtin_1): Update call to fold_builtin_copysign. + 2005-02-09 Ian Lance Taylor PR middle-end/19583 @@ -9,7 +23,6 @@ * gcc/haifa-sched.c (schedule_block): Make queued sched group insns return to ready list in the next turn. - 2005-02-09 Richard Guenther PR middle-end/19402 diff --git a/gcc/builtins.c b/gcc/builtins.c index 36316156c5f..56e7eb00e39 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -169,7 +169,7 @@ 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_copysign (tree, tree, tree); static tree fold_builtin_isascii (tree); static tree fold_builtin_toascii (tree); static tree fold_builtin_isdigit (tree); @@ -6844,7 +6844,10 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) if (TREE_CODE (arg1) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg1)) { + REAL_VALUE_TYPE cint; REAL_VALUE_TYPE c; + HOST_WIDE_INT n; + c = TREE_REAL_CST (arg1); /* Optimize pow(x,0.0) = 1.0. */ @@ -6874,17 +6877,14 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) } } - /* Attempt to evaluate pow at compile-time. */ - if (TREE_CODE (arg0) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (arg0)) + /* Check for an integer exponent. */ + n = real_to_integer (&c); + real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0); + if (real_identical (&c, &cint)) { - REAL_VALUE_TYPE cint; - HOST_WIDE_INT n; - - n = real_to_integer (&c); - real_from_integer (&cint, VOIDmode, n, - n < 0 ? -1 : 0, 0); - if (real_identical (&c, &cint)) + /* Attempt to evaluate pow at compile-time. */ + if (TREE_CODE (arg0) == REAL_CST + && ! TREE_CONSTANT_OVERFLOW (arg0)) { REAL_VALUE_TYPE x; bool inexact; @@ -6894,6 +6894,18 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) if (flag_unsafe_math_optimizations || !inexact) return build_real (type, x); } + + /* Strip sign ops from even integer powers. */ + if ((n & 1) == 0 && flag_unsafe_math_optimizations) + { + tree narg0 = fold_strip_sign_ops (arg0); + if (narg0) + { + arglist = build_tree_list (NULL_TREE, arg1); + arglist = tree_cons (NULL_TREE, narg0, arglist); + return build_function_call_expr (fndecl, arglist); + } + } } } @@ -7447,9 +7459,9 @@ fold_builtin_signbit (tree exp) Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_copysign (tree arglist, tree type) +fold_builtin_copysign (tree fndecl, tree arglist, tree type) { - tree arg1, arg2; + tree arg1, arg2, tem; if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) return NULL_TREE; @@ -7483,6 +7495,14 @@ fold_builtin_copysign (tree arglist, tree type) fold (build1 (ABS_EXPR, type, arg1)), arg2); + /* Strip sign changing operations for the first argument. */ + tem = fold_strip_sign_ops (arg1); + if (tem) + { + arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist)); + return build_function_call_expr (fndecl, arglist); + } + return NULL_TREE; } @@ -8056,7 +8076,7 @@ fold_builtin_1 (tree exp, bool ignore) case BUILT_IN_COPYSIGN: case BUILT_IN_COPYSIGNF: case BUILT_IN_COPYSIGNL: - return fold_builtin_copysign (arglist, type); + return fold_builtin_copysign (fndecl, arglist, type); case BUILT_IN_FINITE: case BUILT_IN_FINITEF: diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 294f94cbf1b..de54258c2a4 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6776,6 +6776,14 @@ fold (tree expr) } else if (tree_expr_nonnegative_p (arg0)) return arg0; + + /* Strip sign ops from argument. */ + if (TREE_CODE (type) == REAL_TYPE) + { + tem = fold_strip_sign_ops (arg0); + if (tem) + return fold (build1 (ABS_EXPR, type, fold_convert (type, tem))); + } return t; case CONJ_EXPR: @@ -7429,6 +7437,17 @@ fold (tree expr) TREE_OPERAND (arg0, 1))); } + /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y. */ + if (operand_equal_p (arg0, arg1, 0)) + { + tree tem = fold_strip_sign_ops (arg0); + if (tem != NULL_TREE) + { + tem = fold_convert (type, tem); + return fold (build2 (MULT_EXPR, type, tem, tem)); + } + } + if (flag_unsafe_math_optimizations) { enum built_in_function fcode0 = builtin_mathfn_code (arg0); @@ -11229,3 +11248,38 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff) *diff += (bitpos1 - bitpos2) / BITS_PER_UNIT; return true; } + +/* Simplify the floating point expression EXP when the sign of the + result is not significant. Return NULL_TREE if no simplification + is possible. */ + +tree +fold_strip_sign_ops (tree exp) +{ + tree arg0, arg1; + + switch (TREE_CODE (exp)) + { + case ABS_EXPR: + case NEGATE_EXPR: + arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0)); + return arg0 ? arg0 : TREE_OPERAND (exp, 0); + + case MULT_EXPR: + case RDIV_EXPR: + if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp)))) + return NULL_TREE; + arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0)); + arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1)); + if (arg0 != NULL_TREE || arg1 != NULL_TREE) + return fold (build2 (TREE_CODE (exp), TREE_TYPE (exp), + arg0 ? arg0 : TREE_OPERAND (exp, 0), + arg1 ? arg1 : TREE_OPERAND (exp, 1))); + break; + + default: + break; + } + return NULL_TREE; +} + diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 12f30ebd53c..17a555818a3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-02-09 Roger Sayle + + * gcc.dg/builtins-48.c: New test case. + * gcc.dg/builtins-49.c: New test case. + * gcc.dg/builtins-50.c: New test case. + * gcc.dg/builtins-51.c: New test case. + 2005-02-09 Ian Lance Taylor PR middle-end/19583 diff --git a/gcc/testsuite/gcc.dg/builtins-48.c b/gcc/testsuite/gcc.dg/builtins-48.c new file mode 100644 index 00000000000..43710b868b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-48.c @@ -0,0 +1,181 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern double fabs(double); +extern float fabsf(float); +extern void abort(void); + + +double test1(double x) +{ + return (-x)*(-x); +} + +float test1f(float x) +{ + return (-x)*(-x); +} + +double test2(double x) +{ + return fabs(x)*fabs(x); +} + +float test2f(float x) +{ + return fabsf(x)*fabsf(x); +} + +double test3(double x, double y) +{ + return (x*-y)*(x*-y); +} + +float test3f(float x, float y) +{ + return (x*-y)*(x*-y); +} + +double test4(double x, double y) +{ + return (x/-y)*(x/-y); +} + +float test4f(float x, float y) +{ + return (x/-y)*(x/-y); +} + +int main() +{ + if (test1(1.0) != 1.0) + abort(); + if (test1(2.0) != 4.0) + abort(); + if (test1(0.0) != 0.0) + abort(); + if (test1(-1.0) != 1.0) + abort(); + if (test1(-2.0) != 4.0) + abort(); + + if (test1f(1.0f) != 1.0f) + abort(); + if (test1f(2.0f) != 4.0f) + abort(); + if (test1f(0.0f) != 0.0f) + abort(); + if (test1f(-1.0f) != 1.0f) + abort(); + if (test1f(-2.0f) != 4.0f) + abort(); + + if (test2(1.0) != 1.0) + abort(); + if (test2(2.0) != 4.0) + abort(); + if (test2(0.0) != 0.0) + abort(); + if (test2(-1.0) != 1.0) + abort(); + if (test2(-2.0) != 4.0) + abort(); + + if (test2f(1.0f) != 1.0f) + abort(); + if (test2f(2.0f) != 4.0f) + abort(); + if (test2f(0.0f) != 0.0f) + abort(); + if (test2f(-1.0f) != 1.0f) + abort(); + if (test2f(-2.0f) != 4.0f) + abort(); + + if (test3(1.0,1.0) != 1.0) + abort(); + if (test3(1.0,-1.0) != 1.0) + abort(); + if (test3(1.0,2.0) != 4.0) + abort(); + if (test3(1.0,-2.0) != 4.0) + abort(); + if (test3(2.0,1.0) != 4.0) + abort(); + if (test3(2.0,-1.0) != 4.0) + abort(); + if (test3(2.0,2.0) != 16.0) + abort(); + if (test3(2.0,-2.0) != 16.0) + abort(); + if (test3(-2.0,1.0) != 4.0) + abort(); + if (test3(-2.0,-1.0) != 4.0) + abort(); + if (test3(-2.0,2.0) != 16.0) + abort(); + if (test3(-2.0,-2.0) != 16.0) + abort(); + + if (test3f(1.0f,1.0f) != 1.0f) + abort(); + if (test3f(1.0f,-1.0f) != 1.0f) + abort(); + if (test3f(1.0f,2.0f) != 4.0f) + abort(); + if (test3f(1.0f,-2.0f) != 4.0f) + abort(); + if (test3f(2.0f,1.0f) != 4.0f) + abort(); + if (test3f(2.0f,-1.0f) != 4.0f) + abort(); + if (test3f(2.0f,2.0f) != 16.0f) + abort(); + if (test3f(2.0f,-2.0f) != 16.0f) + abort(); + if (test3f(-2.0f,1.0f) != 4.0f) + abort(); + if (test3f(-2.0f,-1.0f) != 4.0f) + abort(); + if (test3f(-2.0f,2.0f) != 16.0f) + abort(); + if (test3f(-2.0f,-2.0f) != 16.0f) + abort(); + + if (test4(1.0,1.0) != 1.0) + abort(); + if (test4(1.0,-1.0) != 1.0) + abort(); + if (test4(-1.0,1.0) != 1.0) + abort(); + if (test4(-1.0,-1.0) != 1.0) + abort(); + if (test4(6.0,3.0) != 4.0) + abort(); + if (test4(6.0,-3.0) != 4.0) + abort(); + if (test4(-6.0,3.0) != 4.0) + abort(); + if (test4(-6.0,-3.0) != 4.0) + abort(); + + if (test4f(1.0f,1.0f) != 1.0f) + abort(); + if (test4f(1.0f,-1.0f) != 1.0f) + abort(); + if (test4f(-1.0f,1.0f) != 1.0f) + abort(); + if (test4f(-1.0f,-1.0f) != 1.0f) + abort(); + if (test4f(6.0f,3.0f) != 4.0f) + abort(); + if (test4f(6.0f,-3.0f) != 4.0f) + abort(); + if (test4f(-6.0f,3.0f) != 4.0f) + abort(); + if (test4f(-6.0f,-3.0f) != 4.0f) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-49.c b/gcc/testsuite/gcc.dg/builtins-49.c new file mode 100644 index 00000000000..fdeaad467fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-49.c @@ -0,0 +1,181 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern double fabs(double); +extern float fabsf(float); +extern void abort(void); + + +double test1(double x) +{ + return fabs(-x); +} + +float test1f(float x) +{ + return fabsf(-x); +} + +double test2(double x) +{ + return fabs(fabs(x)); +} + +float test2f(float x) +{ + return fabsf(fabsf(x)); +} + +double test3(double x, double y) +{ + return fabs(x*-y); +} + +float test3f(float x, float y) +{ + return fabsf(x*-y); +} + +double test4(double x, double y) +{ + return fabs(x/-y); +} + +float test4f(float x, float y) +{ + return fabsf(x/-y); +} + +int main() +{ + if (test1(1.0) != 1.0) + abort(); + if (test1(2.0) != 2.0) + abort(); + if (test1(0.0) != 0.0) + abort(); + if (test1(-1.0) != 1.0) + abort(); + if (test1(-2.0) != 2.0) + abort(); + + if (test1f(1.0f) != 1.0f) + abort(); + if (test1f(2.0f) != 2.0f) + abort(); + if (test1f(0.0f) != 0.0f) + abort(); + if (test1f(-1.0f) != 1.0f) + abort(); + if (test1f(-2.0f) != 2.0f) + abort(); + + if (test2(1.0) != 1.0) + abort(); + if (test2(2.0) != 2.0) + abort(); + if (test2(0.0) != 0.0) + abort(); + if (test2(-1.0) != 1.0) + abort(); + if (test2(-2.0) != 2.0) + abort(); + + if (test2f(1.0f) != 1.0f) + abort(); + if (test2f(2.0f) != 2.0f) + abort(); + if (test2f(0.0f) != 0.0f) + abort(); + if (test2f(-1.0f) != 1.0f) + abort(); + if (test2f(-2.0f) != 2.0f) + abort(); + + if (test3(1.0,1.0) != 1.0) + abort(); + if (test3(1.0,-1.0) != 1.0) + abort(); + if (test3(1.0,2.0) != 2.0) + abort(); + if (test3(1.0,-2.0) != 2.0) + abort(); + if (test3(2.0,1.0) != 2.0) + abort(); + if (test3(2.0,-1.0) != 2.0) + abort(); + if (test3(2.0,2.0) != 4.0) + abort(); + if (test3(2.0,-2.0) != 4.0) + abort(); + if (test3(-2.0,1.0) != 2.0) + abort(); + if (test3(-2.0,-1.0) != 2.0) + abort(); + if (test3(-2.0,2.0) != 4.0) + abort(); + if (test3(-2.0,-2.0) != 4.0) + abort(); + + if (test3f(1.0f,1.0f) != 1.0f) + abort(); + if (test3f(1.0f,-1.0f) != 1.0f) + abort(); + if (test3f(1.0f,2.0f) != 2.0f) + abort(); + if (test3f(1.0f,-2.0f) != 2.0f) + abort(); + if (test3f(2.0f,1.0f) != 2.0f) + abort(); + if (test3f(2.0f,-1.0f) != 2.0f) + abort(); + if (test3f(2.0f,2.0f) != 4.0f) + abort(); + if (test3f(2.0f,-2.0f) != 4.0f) + abort(); + if (test3f(-2.0f,1.0f) != 2.0f) + abort(); + if (test3f(-2.0f,-1.0f) != 2.0f) + abort(); + if (test3f(-2.0f,2.0f) != 4.0f) + abort(); + if (test3f(-2.0f,-2.0f) != 4.0f) + abort(); + + if (test4(1.0,1.0) != 1.0) + abort(); + if (test4(1.0,-1.0) != 1.0) + abort(); + if (test4(-1.0,1.0) != 1.0) + abort(); + if (test4(-1.0,-1.0) != 1.0) + abort(); + if (test4(6.0,3.0) != 2.0) + abort(); + if (test4(6.0,-3.0) != 2.0) + abort(); + if (test4(-6.0,3.0) != 2.0) + abort(); + if (test4(-6.0,-3.0) != 2.0) + abort(); + + if (test4f(1.0f,1.0f) != 1.0f) + abort(); + if (test4f(1.0f,-1.0f) != 1.0f) + abort(); + if (test4f(-1.0f,1.0f) != 1.0f) + abort(); + if (test4f(-1.0f,-1.0f) != 1.0f) + abort(); + if (test4f(6.0f,3.0f) != 2.0f) + abort(); + if (test4f(6.0f,-3.0f) != 2.0f) + abort(); + if (test4f(-6.0f,3.0f) != 2.0f) + abort(); + if (test4f(-6.0f,-3.0f) != 2.0f) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-50.c b/gcc/testsuite/gcc.dg/builtins-50.c new file mode 100644 index 00000000000..2d32d1ed960 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-50.c @@ -0,0 +1,159 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern double copysign(double,double); +extern float copysignf(float,float); +extern double fabs(double); +extern float fabsf(float); +extern void abort(void); + + +double test1(double x, double y) +{ + return copysign(-x,y); +} + +float test1f(float x, float y) +{ + return copysignf(-x,y); +} + +double test2(double x, double y) +{ + return copysign(fabs(x),y); +} + +float test2f(float x, float y) +{ + return copysignf(fabsf(x),y); +} + +double test3(double x, double y, double z) +{ + return copysign(x*-y,z); +} + +float test3f(float x, float y, float z) +{ + return copysignf(x*-y,z); +} + +double test4(double x, double y, double z) +{ + return copysign(x/-y,z); +} + +float test4f(float x, float y, float z) +{ + return copysignf(x/-y,z); +} + +int main() +{ + if (test1(3.0,2.0) != 3.0) + abort(); + if (test1(3.0,-2.0) != -3.0) + abort(); + if (test1(-3.0,2.0) != 3.0) + abort(); + if (test1(-3.0,-2.0) != -3.0) + abort(); + + if (test1f(3.0f,2.0f) != 3.0f) + abort(); + if (test1f(3.0f,-2.0f) != -3.0f) + abort(); + if (test1f(-3.0f,2.0f) != 3.0f) + abort(); + if (test1f(-3.0f,-2.0f) != -3.0f) + abort(); + + if (test2(3.0,2.0) != 3.0) + abort(); + if (test2(3.0,-2.0) != -3.0) + abort(); + if (test2(-3.0,2.0) != 3.0) + abort(); + if (test2(-3.0,-2.0) != -3.0) + abort(); + + if (test2f(3.0f,2.0f) != 3.0f) + abort(); + if (test2f(3.0f,-2.0f) != -3.0f) + abort(); + if (test2f(-3.0f,2.0f) != 3.0f) + abort(); + if (test2f(-3.0f,-2.0f) != -3.0f) + abort(); + + if (test3(2.0,3.0,4.0) != 6.0) + abort(); + if (test3(2.0,3.0,-4.0) != -6.0) + abort(); + if (test3(2.0,-3.0,4.0) != 6.0) + abort(); + if (test3(2.0,-3.0,-4.0) != -6.0) + abort(); + if (test3(-2.0,3.0,4.0) != 6.0) + abort(); + if (test3(-2.0,3.0,-4.0) != -6.0) + abort(); + if (test3(-2.0,-3.0,4.0) != 6.0) + abort(); + if (test3(-2.0,-3.0,-4.0) != -6.0) + abort(); + + if (test3f(2.0f,3.0f,4.0f) != 6.0f) + abort(); + if (test3f(2.0f,3.0f,-4.0f) != -6.0f) + abort(); + if (test3f(2.0f,-3.0f,4.0f) != 6.0f) + abort(); + if (test3f(2.0f,-3.0f,-4.0f) != -6.0f) + abort(); + if (test3f(-2.0f,3.0f,4.0f) != 6.0f) + abort(); + if (test3f(-2.0f,3.0f,-4.0f) != -6.0f) + abort(); + if (test3f(-2.0f,-3.0f,4.0f) != 6.0f) + abort(); + if (test3f(-2.0f,-3.0f,-4.0f) != -6.0f) + abort(); + + if (test4(8.0,2.0,3.0) != 4.0) + abort(); + if (test4(8.0,2.0,-3.0) != -4.0) + abort(); + if (test4(8.0,-2.0,3.0) != 4.0) + abort(); + if (test4(8.0,-2.0,-3.0) != -4.0) + abort(); + if (test4(-8.0,2.0,3.0) != 4.0) + abort(); + if (test4(-8.0,2.0,-3.0) != -4.0) + abort(); + if (test4(-8.0,-2.0,3.0) != 4.0) + abort(); + if (test4(-8.0,-2.0,-3.0) != -4.0) + abort(); + + if (test4f(8.0f,2.0f,3.0f) != 4.0f) + abort(); + if (test4f(8.0f,2.0f,-3.0f) != -4.0f) + abort(); + if (test4f(8.0f,-2.0f,3.0f) != 4.0f) + abort(); + if (test4f(8.0f,-2.0f,-3.0f) != -4.0f) + abort(); + if (test4f(-8.0f,2.0f,3.0f) != 4.0f) + abort(); + if (test4f(-8.0f,2.0f,-3.0f) != -4.0f) + abort(); + if (test4f(-8.0f,-2.0f,3.0f) != 4.0f) + abort(); + if (test4f(-8.0f,-2.0f,-3.0f) != -4.0f) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-51.c b/gcc/testsuite/gcc.dg/builtins-51.c new file mode 100644 index 00000000000..fdfc9bec7f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-51.c @@ -0,0 +1,157 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ffast-math" } */ + +extern double pow(double, double); +extern double fabs(double); +extern void abort(void); + +double test2_1(double x) +{ + return pow(x,2.0); +} + +double test2_2(double x) +{ + return pow(-x,2.0); +} + +double test2_3(double x) +{ + return pow(fabs(x),2.0); +} + +double test3_1(double x) +{ + return pow(x,3.0); +} + +double test3_2(double x) +{ + return pow(-x,3.0); +} + +double test3_3(double x) +{ + return pow(fabs(x),3.0); +} + +double test6_1(double x) +{ + return pow(x,6.0); +} + +double test6_2(double x) +{ + return pow(-x,6.0); +} + +double test6_3(double x) +{ + return pow(fabs(x),6.0); +} + + +int main() +{ + if (test2_1(1.0) != 1.0) + abort(); + if (test2_1(2.0) != 4.0) + abort(); + if (test2_1(0.0) != 0.0) + abort(); + if (test2_1(-1.0) != 1.0) + abort(); + if (test2_1(-2.0) != 4.0) + abort(); + + if (test2_2(1.0) != 1.0) + abort(); + if (test2_2(2.0) != 4.0) + abort(); + if (test2_2(0.0) != 0.0) + abort(); + if (test2_2(-1.0) != 1.0) + abort(); + if (test2_2(-2.0) != 4.0) + abort(); + + if (test2_3(1.0) != 1.0) + abort(); + if (test2_3(2.0) != 4.0) + abort(); + if (test2_3(0.0) != 0.0) + abort(); + if (test2_3(-1.0) != 1.0) + abort(); + if (test2_3(2.0) != 4.0) + abort(); + + if (test3_1(1.0) != 1.0) + abort(); + if (test3_1(2.0) != 8.0) + abort(); + if (test3_1(0.0) != 0.0) + abort(); + if (test3_1(-1.0) != -1.0) + abort(); + if (test3_1(-2.0) != -8.0) + abort(); + + if (test3_2(1.0) != -1.0) + abort(); + if (test3_2(2.0) != -8.0) + abort(); + if (test3_2(0.0) != -0.0) + abort(); + if (test3_2(-1.0) != 1.0) + abort(); + if (test3_2(-2.0) != 8.0) + abort(); + + if (test3_3(1.0) != 1.0) + abort(); + if (test3_3(2.0) != 8.0) + abort(); + if (test3_3(0.0) != 0.0) + abort(); + if (test3_3(-1.0) != 1.0) + abort(); + if (test3_3(-2.0) != 8.0) + abort(); + + if (test6_1(1.0) != 1.0) + abort(); + if (test6_1(2.0) != 64.0) + abort(); + if (test6_1(0.0) != 0.0) + abort(); + if (test6_1(-1.0) != 1.0) + abort(); + if (test6_1(-2.0) != 64.0) + abort(); + + if (test6_2(1.0) != 1.0) + abort(); + if (test6_2(2.0) != 64.0) + abort(); + if (test6_2(0.0) != 0.0) + abort(); + if (test6_2(-1.0) != 1.0) + abort(); + if (test6_2(-2.0) != 64.0) + abort(); + + if (test6_3(1.0) != 1.0) + abort(); + if (test6_3(2.0) != 64.0) + abort(); + if (test6_3(0.0) != 0.0) + abort(); + if (test6_3(-1.0) != 1.0) + abort(); + if (test6_3(-2.0) != 64.0) + abort(); + + return 0; +} + diff --git a/gcc/tree.h b/gcc/tree.h index 47f65c8f6ff..e64fb99d78d 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3527,7 +3527,8 @@ extern tree fold_binary_to_constant (enum tree_code, tree, tree, tree); extern tree fold_read_from_constant_string (tree); extern tree int_const_binop (enum tree_code, tree, tree, int); extern tree build_fold_addr_expr (tree); -tree fold_build_cleanup_point_expr (tree type, tree expr); +extern tree fold_build_cleanup_point_expr (tree type, tree expr); +extern tree fold_strip_sign_ops (tree); extern tree build_fold_addr_expr_with_type (tree, tree); extern tree build_fold_indirect_ref (tree); extern tree constant_boolean_node (int, tree); -- 2.30.2