OSDN Git Service

PR c/39902
authorjanis <janis@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 26 Jun 2009 18:27:30 +0000 (18:27 +0000)
committerjanis <janis@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 26 Jun 2009 18:27:30 +0000 (18:27 +0000)
* tree.c (real_zerop, real_onep, real_twop, real_minus_onep):
Special-case decimal float constants.

* gcc.dg/dfp/pr39902.c: New test.

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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/dfp/pr39902.c [new file with mode: 0644]
gcc/tree.c

index b01fbdd..34db745 100644 (file)
@@ -1,3 +1,9 @@
+2009-06-26  Janis Johnson  <janis187@us.ibm.com>
+
+       PR c/39902
+       * tree.c (real_zerop, real_onep, real_twop, real_minus_onep):
+       Special-case decimal float constants.
+
 2009-06-26  Richard Henderson  <rth@redhat.com>
 
        * function.h (struct function): Add cannot_be_copied_reason,
index bdec9b8..4956bfc 100644 (file)
@@ -1,3 +1,8 @@
+2009-06-26  Janis Johnson  <janis187@us.ibm.com>
+
+       PR c/39902
+       * gcc.dg/dfp/pr39902.c: New test.
+
 2009-06-26  Uros Bizjak  <ubizjak@gmail.com>
 
        PR testsuite/40532
diff --git a/gcc/testsuite/gcc.dg/dfp/pr39902.c b/gcc/testsuite/gcc.dg/dfp/pr39902.c
new file mode 100644 (file)
index 0000000..8c4e7b2
--- /dev/null
@@ -0,0 +1,239 @@
+/* { dg-options "--std=gnu99" } */
+
+/* Check that optimizations like (x * 1) to x, or (x * -1) to -x,
+   do not apply to decimal float computations where trailing zeroes
+   are significant.  */
+
+extern void abort (void);
+int failcnt;
+
+#ifdef DBG
+extern int printf (const char *, ...);
+#define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; }
+#else
+#define FAILURE abort ();
+#endif
+
+#define COMPARE32(A,B) \
+  A.i == B.i
+
+#define COMPARE64(A,B) \
+  A.i[0] == B.i[0] && A.i[1] == B.i[1]
+
+#define COMPARE128(A,B) \
+  A.i[0] == B.i[0] && A.i[1] == B.i[1] && A.i[2] == B.i[2] && A.i[3] == B.i[3]
+
+typedef union {
+  _Decimal32 d;
+  unsigned int i;
+} u32;
+
+typedef union {
+  _Decimal64 d;
+  unsigned int i[2];
+} u64;
+
+typedef union {
+  _Decimal128 d;
+  unsigned int i[4];
+} u128;
+
+volatile u32 p32_1;
+volatile u32 p32_1_0;
+volatile u32 p32_2_0;
+volatile u32 m32_1;
+volatile u32 m32_1_0;
+volatile u32 m32_2_0;
+volatile u32 a32;
+
+volatile u64 p64_1;
+volatile u64 p64_1_0;
+volatile u64 p64_2_0;
+volatile u64 m64_1;
+volatile u64 m64_1_0;
+volatile u64 m64_2_0;
+volatile u64 a64;
+
+volatile u128 p128_1;
+volatile u128 p128_1_0;
+volatile u128 p128_2_0;
+volatile u128 m128_1;
+volatile u128 m128_1_0;
+volatile u128 m128_2_0;
+volatile u128 a128;
+
+void
+init32 (void)
+{
+  p32_1.d = 1.DF;
+  p32_1_0.d = 1.0DF;
+  p32_2_0.d = 2.0DF;
+  m32_1.d = -1.DF;
+  m32_1_0.d = -1.0DF;
+  m32_2_0.d = -2.0DF;
+}
+
+void
+init64 (void)
+{
+  p64_1.d = 1.DD;
+  p64_1_0.d = 1.0DD;
+  p64_2_0.d = 2.0DD;
+  m64_1.d = -1.DD;
+  m64_1_0.d = -1.0DD;
+  m64_2_0.d = -2.0DD;
+}
+
+void
+init128 (void)
+{
+  p128_1.d = 1.DL;
+  p128_1_0.d = 1.0DL;
+  p128_2_0.d = 2.0DL;
+  m128_1.d = -1.DL;
+  m128_1_0.d = -1.0DL;
+  m128_2_0.d = -2.0DL;
+}
+
+void
+doit32 (void)
+{
+  /* Multiplying by a value with no trailing zero should not change the
+     quantum exponent.  */
+
+  a32.d = p32_2_0.d * p32_1.d;
+  if (! (COMPARE32 (a32, p32_2_0)))
+    FAILURE
+
+  a32.d = p32_2_0.d * 1.DF;
+  if (! (COMPARE32 (a32, p32_2_0)))
+    FAILURE
+
+  a32.d = p32_2_0.d * m32_1.d;
+  if (! (COMPARE32 (a32, m32_2_0)))
+    FAILURE
+
+  a32.d = p32_2_0.d * -1.DF;
+  if (! (COMPARE32 (a32, m32_2_0)))
+    FAILURE
+
+  /* Multiplying by a value with a trailing zero should change the
+     quantum exponent.  */
+
+  a32.d = p32_2_0.d * p32_1_0.d;
+  if (COMPARE32 (a32, p32_2_0))
+    FAILURE
+
+  a32.d = p32_2_0.d * 1.0DF;
+  if (COMPARE32 (a32, p32_2_0))
+    FAILURE
+
+  a32.d = p32_2_0.d * m32_1_0.d;
+  if (COMPARE32 (a32, m32_2_0))
+    FAILURE
+
+  a32.d = p32_2_0.d * -1.0DF;
+  if (COMPARE32 (a32, m32_2_0))
+    FAILURE
+}
+
+void
+doit64 (void)
+{
+  /* Multiplying by a value with no trailing zero should not change the
+     quantum exponent.  */
+
+  a64.d = p64_2_0.d * p64_1.d;
+  if (! (COMPARE64 (a64, p64_2_0)))
+    FAILURE
+
+  a64.d = p64_2_0.d * 1.DD;
+  if (! (COMPARE64 (a64, p64_2_0)))
+    FAILURE
+
+  a64.d = p64_2_0.d * m64_1.d;
+  if (! (COMPARE64 (a64, m64_2_0)))
+    FAILURE
+
+  a64.d = p64_2_0.d * -1.DD;
+  if (! (COMPARE64 (a64, m64_2_0)))
+    FAILURE
+
+  /* Multiplying by a value with a trailing zero should change the
+     quantum exponent.  */
+
+  a64.d = p64_2_0.d * p64_1_0.d;
+  if (COMPARE64 (a64, p64_2_0))
+    FAILURE
+
+  a64.d = p64_2_0.d * 1.0DD;
+  if (COMPARE64 (a64, p64_2_0))
+    FAILURE
+
+  a64.d = p64_2_0.d * m64_1_0.d;
+  if (COMPARE64 (a64, m64_2_0))
+    FAILURE
+
+  a64.d = p64_2_0.d * -1.0DD;
+  if (COMPARE64 (a64, m64_2_0))
+    FAILURE
+}
+
+void
+doit128 (void)
+{
+  /* Multiplying by a value with no trailing zero should not change the
+     quantum exponent.  */
+
+  a128.d = p128_2_0.d * p128_1_0.d;
+  if (COMPARE128 (a128, p128_2_0))
+    FAILURE
+
+  a128.d = p128_2_0.d * 1.0DD;
+  if (COMPARE128 (a128, p128_2_0))
+    FAILURE
+
+  a128.d = p128_2_0.d * m128_1_0.d;
+  if (COMPARE128 (a128, m128_2_0))
+    FAILURE
+
+  a128.d = p128_2_0.d * -1.0DD;
+  if (COMPARE128 (a128, m128_2_0))
+    FAILURE
+
+  /* Multiplying by a value with a trailing zero should change the
+     quantum exponent.  */
+
+  a128.d = p128_2_0.d * p128_1.d;
+  if (! (COMPARE128 (a128, p128_2_0)))
+    FAILURE
+
+  a128.d = p128_2_0.d * 1.DD;
+  if (! (COMPARE128 (a128, p128_2_0)))
+    FAILURE
+
+  a128.d = p128_2_0.d * m128_1.d;
+  if (! (COMPARE128 (a128, m128_2_0)))
+    FAILURE
+
+  a128.d = p128_2_0.d * -1.DD;
+  if (! (COMPARE128 (a128, m128_2_0)))
+    FAILURE
+}
+
+int
+main (void)
+{
+  init32 ();
+  init64 ();
+  init128 ();
+
+  doit32 ();
+  doit64 ();
+  doit128 ();
+
+  if (failcnt != 0)
+    abort ();
+
+  return 0;
+}
index 139c1e5..ffdd888 100644 (file)
@@ -1591,7 +1591,8 @@ tree_floor_log2 (const_tree expr)
          : floor_log2 (low));
 }
 
-/* Return 1 if EXPR is the real constant zero.  */
+/* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
+   decimal float constants, so don't return 1 for them.  */
 
 int
 real_zerop (const_tree expr)
@@ -1599,13 +1600,16 @@ real_zerop (const_tree expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
-          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
+          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
+          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_zerop (TREE_REALPART (expr))
              && real_zerop (TREE_IMAGPART (expr))));
 }
 
-/* Return 1 if EXPR is the real constant one in real or complex form.  */
+/* Return 1 if EXPR is the real constant one in real or complex form.
+   Trailing zeroes matter for decimal float constants, so don't return
+   1 for them.  */
 
 int
 real_onep (const_tree expr)
@@ -1613,13 +1617,15 @@ real_onep (const_tree expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
-          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1))
+          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
+          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_onep (TREE_REALPART (expr))
              && real_zerop (TREE_IMAGPART (expr))));
 }
 
-/* Return 1 if EXPR is the real constant two.  */
+/* Return 1 if EXPR is the real constant two.  Trailing zeroes matter
+   for decimal float constants, so don't return 1 for them.  */
 
 int
 real_twop (const_tree expr)
@@ -1627,13 +1633,15 @@ real_twop (const_tree expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
-          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2))
+          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
+          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_twop (TREE_REALPART (expr))
              && real_zerop (TREE_IMAGPART (expr))));
 }
 
-/* Return 1 if EXPR is the real constant minus one.  */
+/* Return 1 if EXPR is the real constant minus one.  Trailing zeroes
+   matter for decimal float constants, so don't return 1 for them.  */
 
 int
 real_minus_onep (const_tree expr)
@@ -1641,7 +1649,8 @@ real_minus_onep (const_tree expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
-          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1))
+          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
+          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_minus_onep (TREE_REALPART (expr))
              && real_zerop (TREE_IMAGPART (expr))));