OSDN Git Service

* fold-const.c (fold_binary): Do not fold multiplication by 1 or
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 May 2009 20:58:26 +0000 (20:58 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 May 2009 20:58:26 +0000 (20:58 +0000)
-1 for complex floating-point types if honoring signed zeros.

testsuite:
* gcc.dg/torture/complex-sign-mul-minus-one.c,
gcc.dg/torture/complex-sign-mul-one.c: New tests.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c [new file with mode: 0644]

index 508436b..026c8ef 100644 (file)
@@ -1,3 +1,8 @@
+2009-05-08  Joseph Myers  <joseph@codesourcery.com>
+
+       * fold-const.c (fold_binary): Do not fold multiplication by 1 or
+       -1 for complex floating-point types if honoring signed zeros.
+
 2009-05-08  Jan Hubicka  <jh@suse.cz>
 
        * cgraphbuild.c (compute_call_stmt_bb_frequency): Accept function argument;
index 14b9f10..fb59049 100644 (file)
@@ -10647,13 +10647,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
              && real_zerop (arg1))
            return omit_one_operand (type, arg1, arg0);
-         /* In IEEE floating point, x*1 is not equivalent to x for snans.  */
+         /* In IEEE floating point, x*1 is not equivalent to x for snans.
+            Likewise for complex arithmetic with signed zeros.  */
          if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+             && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+                 || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
              && real_onep (arg1))
            return non_lvalue (fold_convert (type, arg0));
 
          /* Transform x * -1.0 into -x.  */
          if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+             && (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+                 || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
              && real_minus_onep (arg1))
            return fold_convert (type, negate_expr (arg0));
 
index 2e83302..a03013e 100644 (file)
@@ -1,3 +1,8 @@
+2009-05-08  Joseph Myers  <joseph@codesourcery.com>
+
+       * gcc.dg/torture/complex-sign-mul-minus-one.c,
+       gcc.dg/torture/complex-sign-mul-one.c: New tests.
+
 2009-05-08  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR c/36892
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c b/gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c
new file mode 100644 (file)
index 0000000..6b9a905
--- /dev/null
@@ -0,0 +1,61 @@
+/* Test complex arithmetic with signed zeros.  Pure complex
+   multiplication with -1.0 + 0.0i.  */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99" } */
+
+#include "complex-sign.h"
+
+#define CHECK_MUL_INT(TYPE, COPY, ZERO, ZEROI, ONE, S1, S2, SR, SI)    \
+  do {                                                                 \
+    _Complex TYPE a1, b1, c1;                                          \
+    volatile _Complex TYPE a2, b2, c2;                                 \
+    a1 = ENCODE(ZERO, ZEROI, S1, S2);                                  \
+    CHECK_RES (a1, COPY, S1, S2);                                      \
+    b1 = -ONE + ZEROI;                                                 \
+    c1 = a1 * b1;                                                      \
+    CHECK_RES (c1, COPY, SR, SI);                                      \
+    c1 = a1 * (-ONE + ZEROI);                                          \
+    CHECK_RES (c1, COPY, SR, SI);                                      \
+    a2 = ENCODE(ZERO, ZEROI, S1, S2);                                  \
+    CHECK_RES (a2, COPY, S1, S2);                                      \
+    b2 = -ONE + ZEROI;                                                 \
+    c2 = a2 * b2;                                                      \
+    CHECK_RES (c2, COPY, SR, SI);                                      \
+    c2 = a2 * (-ONE + ZEROI);                                          \
+    CHECK_RES (c2, COPY, SR, SI);                                      \
+  } while (0)
+
+#define CHECK_MUL(TYPE, COPY, ZERO, ZEROI, ONE)                        \
+  do {                                                         \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, +, +, -, +);  \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, +, -, +, +);  \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, -, +, +, -);  \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, -, -, +, +);  \
+  } while (0)
+
+void
+check_mul_float (void)
+{
+  CHECK_MUL (float, __builtin_copysignf, 0.0f, 0.0if, 1.0f);
+}
+
+void
+check_mul_double (void)
+{
+  CHECK_MUL (double, __builtin_copysign, 0.0, 0.0i, 1.0);
+}
+
+void
+check_mul_long_double (void)
+{
+  CHECK_MUL (long double, __builtin_copysignl, 0.0l, 0.0il, 1.0l);
+}
+
+int
+main (void)
+{
+  check_mul_float ();
+  check_mul_double ();
+  check_mul_long_double ();
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c b/gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c
new file mode 100644 (file)
index 0000000..9d1d6c7
--- /dev/null
@@ -0,0 +1,61 @@
+/* Test complex arithmetic with signed zeros.  Pure complex
+   multiplication with 1.0 + 0.0i.  */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99" } */
+
+#include "complex-sign.h"
+
+#define CHECK_MUL_INT(TYPE, COPY, ZERO, ZEROI, ONE, S1, S2, SR, SI)    \
+  do {                                                                 \
+    _Complex TYPE a1, b1, c1;                                          \
+    volatile _Complex TYPE a2, b2, c2;                                 \
+    a1 = ENCODE(ZERO, ZEROI, S1, S2);                                  \
+    CHECK_RES (a1, COPY, S1, S2);                                      \
+    b1 = ONE + ZEROI;                                                  \
+    c1 = a1 * b1;                                                      \
+    CHECK_RES (c1, COPY, SR, SI);                                      \
+    c1 = a1 * (ONE + ZEROI);                                           \
+    CHECK_RES (c1, COPY, SR, SI);                                      \
+    a2 = ENCODE(ZERO, ZEROI, S1, S2);                                  \
+    CHECK_RES (a2, COPY, S1, S2);                                      \
+    b2 = ONE + ZEROI;                                                  \
+    c2 = a2 * b2;                                                      \
+    CHECK_RES (c2, COPY, SR, SI);                                      \
+    c2 = a2 * (ONE + ZEROI);                                           \
+    CHECK_RES (c2, COPY, SR, SI);                                      \
+  } while (0)
+
+#define CHECK_MUL(TYPE, COPY, ZERO, ZEROI, ONE)                        \
+  do {                                                         \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, +, +, +, +);  \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, +, -, +, +);  \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, -, +, -, +);  \
+    CHECK_MUL_INT (TYPE, COPY, ZERO, ZEROI, ONE, -, -, +, -);  \
+  } while (0)
+
+void
+check_mul_float (void)
+{
+  CHECK_MUL (float, __builtin_copysignf, 0.0f, 0.0if, 1.0f);
+}
+
+void
+check_mul_double (void)
+{
+  CHECK_MUL (double, __builtin_copysign, 0.0, 0.0i, 1.0);
+}
+
+void
+check_mul_long_double (void)
+{
+  CHECK_MUL (long double, __builtin_copysignl, 0.0l, 0.0il, 1.0l);
+}
+
+int
+main (void)
+{
+  check_mul_float ();
+  check_mul_double ();
+  check_mul_long_double ();
+  exit (0);
+}