From d1ad84c20452e63a38a6b414a6eb7001711c520a Mon Sep 17 00:00:00 2001 From: "Kaveh R. Ghazi" Date: Sat, 3 Feb 2007 16:13:23 +0000 Subject: [PATCH] builtins.c (fold_builtin_cabs): Fold cabs(x+xi) into fabs(x)*sqrt(2). * builtins.c (fold_builtin_cabs): Fold cabs(x+xi) into fabs(x)*sqrt(2). * fold-const.c (fold_binary): Fix comment typos. Fold complex (x,0)-(0,y) into (x,-y). Likewise (0,y)-(x,0) into (-x,y). testsuite: * gcc.dg/builtins-54.c: Add more cases. From-SVN: r121542 --- gcc/ChangeLog | 7 ++ gcc/builtins.c | 31 ++++++-- gcc/fold-const.c | 41 ++++++++++- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/builtins-54.c | 114 +++++++++++++++++++++++++++-- 5 files changed, 182 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9ef2c72d73c..6fa2af1860f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-02-03 Kaveh R. Ghazi + + * builtins.c (fold_builtin_cabs): Fold cabs(x+xi) into + fabs(x)*sqrt(2). + * fold-const.c (fold_binary): Fix comment typos. Fold complex + (x,0)-(0,y) into (x,-y). Likewise (0,y)-(x,0) into (-x,y). + 2007-02-02 Mike Stump * config/darwin9.h (DARWIN_LINKER_GENERATES_ISLANDS): Add. diff --git a/gcc/builtins.c b/gcc/builtins.c index 5b9a87f8936..b7ce1e4c5d8 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7143,13 +7143,30 @@ fold_builtin_cabs (tree arglist, tree type, tree fndecl) type, mpfr_hypot))) return res; - /* If either part is zero, cabs is fabs of the other. */ - if (TREE_CODE (arg) == COMPLEX_EXPR - && real_zerop (TREE_OPERAND (arg, 0))) - return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)); - if (TREE_CODE (arg) == COMPLEX_EXPR - && real_zerop (TREE_OPERAND (arg, 1))) - return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)); + if (TREE_CODE (arg) == COMPLEX_EXPR) + { + tree real = TREE_OPERAND (arg, 0); + tree imag = TREE_OPERAND (arg, 1); + + /* If either part is zero, cabs is fabs of the other. */ + if (real_zerop (real)) + return fold_build1 (ABS_EXPR, type, imag); + if (real_zerop (imag)) + return fold_build1 (ABS_EXPR, type, real); + + /* cabs(x+xi) -> fabs(x)*sqrt(2). */ + if (flag_unsafe_math_optimizations + && operand_equal_p (real, imag, OEP_PURE_SAME)) + { + REAL_VALUE_TYPE sqrt2; + + real_sqrt (&sqrt2, TYPE_MODE (type), &dconst2); + STRIP_NOPS (real); + return fold_build2 (MULT_EXPR, type, + fold_build1 (ABS_EXPR, type, real), + build_real (type, sqrt2)); + } + } /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */ if (TREE_CODE (arg) == NEGATE_EXPR diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 241e9dc5ea5..085fcd8275b 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8923,7 +8923,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) /* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y ) to __complex__ ( x, y ). This is not the same for SNaNs or - if singed zeros are involved. */ + if signed zeros are involved. */ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))) && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))) @@ -9231,6 +9231,43 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0)) return negate_expr (fold_convert (type, arg1)); + /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to + __complex__ ( x, -y ). This is not the same for SNaNs or if + signed zeros are involved. */ + if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) + && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))) + && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))) + { + tree rtype = TREE_TYPE (TREE_TYPE (arg0)); + tree arg0r = fold_unary (REALPART_EXPR, rtype, arg0); + tree arg0i = fold_unary (IMAGPART_EXPR, rtype, arg0); + bool arg0rz = false, arg0iz = false; + if ((arg0r && (arg0rz = real_zerop (arg0r))) + || (arg0i && (arg0iz = real_zerop (arg0i)))) + { + tree arg1r = fold_unary (REALPART_EXPR, rtype, arg1); + tree arg1i = fold_unary (IMAGPART_EXPR, rtype, arg1); + if (arg0rz && arg1i && real_zerop (arg1i)) + { + tree rp = fold_build1 (NEGATE_EXPR, rtype, + arg1r ? arg1r + : build1 (REALPART_EXPR, rtype, arg1)); + tree ip = arg0i ? arg0i + : build1 (IMAGPART_EXPR, rtype, arg0); + return fold_build2 (COMPLEX_EXPR, type, rp, ip); + } + else if (arg0iz && arg1r && real_zerop (arg1r)) + { + tree rp = arg0r ? arg0r + : build1 (REALPART_EXPR, rtype, arg0); + tree ip = fold_build1 (NEGATE_EXPR, rtype, + arg1i ? arg1i + : build1 (IMAGPART_EXPR, rtype, arg1)); + return fold_build2 (COMPLEX_EXPR, type, rp, ip); + } + } + } + /* Fold &x - &x. This can happen from &x.foo - &x. This is unsafe for certain floats even in non-IEEE formats. In IEEE, it is unsafe because it does wrong for NaNs. @@ -9410,7 +9447,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) } /* Fold z * +-I to __complex__ (-+__imag z, +-__real z). - This is not the same for NaNs or if singed zeros are + This is not the same for NaNs or if signed zeros are involved. */ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 89c44414f1b..7ec593780d2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-02-03 Kaveh R. Ghazi + + * gcc.dg/builtins-54.c: Add more cases. + 2007-02-03 Paul Thomas PR fortran/30514 diff --git a/gcc/testsuite/gcc.dg/builtins-54.c b/gcc/testsuite/gcc.dg/builtins-54.c index 29cdf20663d..2713a3b1d57 100644 --- a/gcc/testsuite/gcc.dg/builtins-54.c +++ b/gcc/testsuite/gcc.dg/builtins-54.c @@ -1,44 +1,146 @@ /* { dg-do link } */ /* { dg-options "-O2 -ffast-math" } */ +double fabs(double); +float fabsf(float); +long double fabsl(long double); double cabs(__complex__ double); float cabsf(__complex__ float); long double cabsl(__complex__ long double); void link_error (void); -void test(__complex__ double x) +void test(__complex__ double x, double a, double b) { if (cabs(x) != cabs(-x)) link_error(); if (cabs(x) != cabs(~x)) link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (a+a*1i)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (a*1i+a)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (-a+a*-1i)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (-a+-a*1i)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (-a-a*1i)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (a*-1i-a)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (-a*1i-a)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (a*-1i+-a)) + link_error(); + + if (fabs(a) * __builtin_sqrt(2) != cabs (-a*1i+-a)) + link_error(); + + if (fabs(a*b) * __builtin_sqrt(2) != cabs (a*b-(-b*a*1i))) + link_error(); + + if (fabs(a*b) * __builtin_sqrt(2) != cabs (a*b*1i-a*-b)) + link_error(); } -void testf(__complex__ float x) +void testf(__complex__ float x, float a, float b) { if (cabsf(x) != cabsf(-x)) link_error(); if (cabsf(x) != cabsf(~x)) link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (a+a*1i)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (a*1i+a)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (-a+a*-1i)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (-a+-a*1i)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (-a-a*1i)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (a*-1i-a)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (-a*1i-a)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (a*-1i+-a)) + link_error(); + + if (fabsf(a) * __builtin_sqrtf(2) != cabsf (-a*1i+-a)) + link_error(); + + if (fabsf(a*b) * __builtin_sqrtf(2) != cabsf (a*b-(-b*a*1i))) + link_error(); + + if (fabsf(a*b) * __builtin_sqrtf(2) != cabsf (a*b*1i-a*-b)) + link_error(); } -void testl(__complex__ long double x) +void testl(__complex__ long double x, long double a, long double b) { if (cabsl(x) != cabsl(-x)) link_error(); if (cabsl(x) != cabsl(~x)) link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (a+a*1i)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (a*1i+a)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (-a+a*-1i)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (-a+-a*1i)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (-a-a*1i)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (a*-1i-a)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (-a*1i-a)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (a*-1i+-a)) + link_error(); + + if (fabsl(a) * __builtin_sqrtl(2) != cabsl (-a*1i+-a)) + link_error(); + + if (fabsl(a*b) * __builtin_sqrtl(2) != cabsl (a*b-(-b*a*1i))) + link_error(); + + if (fabsl(a*b) * __builtin_sqrtl(2) != cabsl (a*b*1i-a*-b)) + link_error(); } int main() { - test(0.0); - testf(0.0); - testl(0.0); + test(0, 0, 0); + testf(0, 0, 0); + testl(0, 0, 0); return 0; }