diff options
author | Richard Guenther <rguenther@suse.de> | 2006-12-14 13:12:11 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2006-12-14 13:12:11 +0000 |
commit | 9f5396713d9e188bad160c5816f3bfd21b6f32ca (patch) | |
tree | 7529cb235a0fc6106fa9a66695f0d7ae23d8c60f | |
parent | 85aef79f75e6be8e8a8d7a1111f6110b98a609ca (diff) | |
download | gcc-9f5396713d9e188bad160c5816f3bfd21b6f32ca.zip gcc-9f5396713d9e188bad160c5816f3bfd21b6f32ca.tar.gz gcc-9f5396713d9e188bad160c5816f3bfd21b6f32ca.tar.bz2 |
re PR middle-end/30172 (Operations with partly constant complex values not folded)
2006-12-14 Richard Guenther <rguenther@suse.de>
PR middle-end/30172
* fold-const.c (fold_binary): Fold __complex__ ( x, 0 )
+ __complex__ ( 0, y ) to __complex__ ( x, y ).
Fold __complex__ (x, y) * +-I to __complex__ (-+y, +-x).
* gcc.dg/pr30172-1.c: New testcase.
From-SVN: r119859
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 57 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr30172-1.c | 15 |
4 files changed, 84 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aeb9d19..c81598c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2006-12-14 Richard Guenther <rguenther@suse.de> + PR middle-end/30172 + * fold-const.c (fold_binary): Fold __complex__ ( x, 0 ) + + __complex__ ( 0, y ) to __complex__ ( x, y ). + Fold __complex__ (x, y) * +-I to __complex__ (-+y, +-x). + +2006-12-14 Richard Guenther <rguenther@suse.de> + PR tree-optimization/30198 * fold-const.c (fold_unary): Fold REALPART_EXPR of cexpi to cos. Fold IMAGPART_EXPR of cexpi to sin. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 751ef2e..1874609 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8755,6 +8755,41 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) fold_convert (type, tem)); } + /* 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 (!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 = 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 = arg1i ? arg1i + : build1 (IMAGPART_EXPR, rtype, arg1); + return fold_build2 (COMPLEX_EXPR, type, rp, ip); + } + } + } + if (flag_unsafe_math_optimizations && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR) && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR) @@ -9207,6 +9242,28 @@ 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 + involved. */ + if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) + && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))) + && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)) + && TREE_CODE (arg1) == COMPLEX_CST + && real_zerop (TREE_REALPART (arg1))) + { + tree rtype = TREE_TYPE (TREE_TYPE (arg0)); + if (real_onep (TREE_IMAGPART (arg1))) + return fold_build2 (COMPLEX_EXPR, type, + negate_expr (fold_build1 (IMAGPART_EXPR, + rtype, arg0)), + fold_build1 (REALPART_EXPR, rtype, arg0)); + else if (real_minus_onep (TREE_IMAGPART (arg1))) + return fold_build2 (COMPLEX_EXPR, type, + fold_build1 (IMAGPART_EXPR, rtype, arg0), + negate_expr (fold_build1 (REALPART_EXPR, + rtype, arg0))); + } + /* Optimize z * conj(z) for floating point complex numbers. Guarded by flag_unsafe_math_optimizations as non-finite imaginary components don't produce scalar results. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b99415c..296a34c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2006-12-14 Richard Guenther <rguenther@suse.de> + PR middle-end/30172 + * gcc.dg/pr30172-1.c: New testcase. + +2006-12-14 Richard Guenther <rguenther@suse.de> + PR tree-optimization/30198 * gcc.dg/builtins-60.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/pr30172-1.c b/gcc/testsuite/gcc.dg/pr30172-1.c new file mode 100644 index 0000000..14b5fa5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr30172-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-funsafe-math-optimizations -ffinite-math-only -fdump-tree-gimple" } */ + +_Complex double test1 (double x) { return x + 1.i; } +_Complex double test2 (double x) { return 1 + x * 1.i; } +_Complex double test3 (double x, double y) { return x + y * 1.i; } +_Complex double test4 (double x, double y) { return (x + y * 1.i) * 1.i; } +_Complex double test5 (double x, double y) { return (x + y * 1.i) * -1.i; } + +/* { dg-final { scan-tree-dump "COMPLEX_EXPR <x, 1.0e\\+0>" "gimple" } } */ +/* { dg-final { scan-tree-dump "COMPLEX_EXPR <1.0e\\+0, x>" "gimple" } } */ +/* { dg-final { scan-tree-dump "COMPLEX_EXPR <x, y>" "gimple" } } */ +/* { dg-final { scan-tree-dump "D.* = -y;\n.*COMPLEX_EXPR <D.*, x>" "gimple" } } */ +/* { dg-final { scan-tree-dump "D.* = -x;\n.*COMPLEX_EXPR <y, D.*>" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ |