Kaveh R. GHAZI - [PATCH]: fold cabs(x+xi) and (x,0)-(0,y) (original) (raw)
This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
- From: "Kaveh R. GHAZI"
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 3 Feb 2007 09:48:00 -0500 (EST)
- Subject: [PATCH]: fold cabs(x+xi) and (x,0)-(0,y)
This patch adds two bits of functionality. First I add folding of cabs(x+xi) -> fabs(x)*sqrt(2). We already do the same for hypot(x,x). I slightly reorganized fold_builtin_cabs to only check that TREE_CODE (arg) == COMPLEX_EXPR one time.
Second I add folding of complex expressions like (x,0)-(0,y) into (x,-y) and also (0,y)-(x,0) into (-x,y). We already do a similar folding for the analogous PLUS expression.
I also noticed two comment typos which I corrected below.
I'm doing these two seemingly unrelated functional bits together because the testcases I came up with make use of both transformations in some cases to resolve correctly.
Tested on sparc-sun-solaris2.10, no regressions.
Okay for mainline?
Thanks,
--Kaveh
2007-02-02 Kaveh R. Ghazi ghazi@caip.rutgers.edu
* 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.
diff -rup orig/egcc-SVN20070202/gcc/builtins.c egcc-SVN20070202/gcc/builtins.c --- orig/egcc-SVN20070202/gcc/builtins.c 2007-02-02 12:46:46.000000000 -0500 +++ egcc-SVN20070202/gcc/builtins.c 2007-02-02 14:35:16.628127104 -0500 @@ -7143,13 +7143,30 @@ fold_builtin_cabs (tree arglist, tree ty 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 -rup orig/egcc-SVN20070202/gcc/fold-const.c egcc-SVN20070202/gcc/fold-const.c --- orig/egcc-SVN20070202/gcc/fold-const.c 2007-02-02 12:46:47.000000000 -0500 +++ egcc-SVN20070202/gcc/fold-const.c 2007-02-02 14:16:48.906222070 -0500 @@ -8923,7 +8923,7 @@ fold_binary (enum tree_code code, tree t
/* 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 t 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 t }
/* 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 -rup orig/egcc-SVN20070202/gcc/testsuite/gcc.dg/builtins-54.c egcc-SVN20070202/gcc/testsuite/gcc.dg/builtins-54.c --- orig/egcc-SVN20070202/gcc/testsuite/gcc.dg/builtins-54.c 2006-05-31 20:00:17.000000000 -0400 +++ egcc-SVN20070202/gcc/testsuite/gcc.dg/builtins-54.c 2007-02-02 14:29:28.791920612 -0500 @@ -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(ab) * __builtin_sqrt(2) != cabs (ab-(-ba1i)))
- link_error();
- if (fabs(ab) * __builtin_sqrt(2) != cabs (ab1i-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(ab) * __builtin_sqrtf(2) != cabsf (ab-(-ba1i)))
- link_error();
- if (fabsf(ab) * __builtin_sqrtf(2) != cabsf (ab1i-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(ab) * __builtin_sqrtl(2) != cabsl (ab-(-ba1i)))
- link_error();
- if (fabsl(ab) * __builtin_sqrtl(2) != cabsl (ab1i-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; }
- Follow-Ups:
- Re: [PATCH]: fold cabs(x+xi) and (x,0)-(0,y)
* From: Roger Sayle
- Re: [PATCH]: fold cabs(x+xi) and (x,0)-(0,y)
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |