]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2006-12-14 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Dec 2006 13:12:11 +0000 (13:12 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Dec 2006 13:12:11 +0000 (13:12 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119859 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr30172-1.c [new file with mode: 0644]

index aeb9d19f81bde9793722bd6c5ceb85e3a53c349e..c81598c1d4387c44bdc16a5eac02f163eec5b642 100644 (file)
@@ -1,3 +1,10 @@
+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
index 751ef2e6157cde00c8409b6bf31440c07269b1e1..18746096b5a3cac28c3d2be43a583860b66f91c0 100644 (file)
@@ -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.  */
index b99415c9d8c9fc4217bdd483a644e23fc226df80..296a34ca7c3081beaf31dba7a1fe509fd09eace9 100644 (file)
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/gcc.dg/pr30172-1.c b/gcc/testsuite/gcc.dg/pr30172-1.c
new file mode 100644 (file)
index 0000000..14b5fa5
--- /dev/null
@@ -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" } } */