OSDN Git Service

2006-12-01 Zdenek Dvorak <dvorakz@suse.cz>
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Dec 2006 14:49:15 +0000 (14:49 +0000)
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Dec 2006 14:49:15 +0000 (14:49 +0000)
PR tree-optimization/29921
* tree-ssa-ccp.c (canonicalize_float_value): New function.
(set_lattice_value): Use canonicalize_float_value.

2006-12-01  H.J. Lu  <hongjiu.lu@intel.com>
    Zdenek Dvorak <dvorakz@suse.cz>

PR tree-optimization/29921
* gcc.dg/pr29921-2.c: New test.

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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr29921-2.c [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index 4995449..52452d5 100644 (file)
@@ -1,3 +1,9 @@
+2006-12-01  Zdenek Dvorak <dvorakz@suse.cz>
+
+       PR tree-optimization/29921
+       * tree-ssa-ccp.c (canonicalize_float_value): New function.
+       (set_lattice_value): Use canonicalize_float_value.
+
 2006-11-30  Andrew Pinski  <andrew_pinski@playstation.sony.com>
 
        * config/spu/spu.c (spu_builtin_range): Move from spu-c.c
index f16250d..a714908 100644 (file)
@@ -1,3 +1,9 @@
+2006-12-01  H.J. Lu  <hongjiu.lu@intel.com>
+           Zdenek Dvorak <dvorakz@suse.cz>
+
+       PR tree-optimization/29921
+       * gcc.dg/pr29921-2.c: New test.
+
 2006-11-30  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gcc.dg/i386-cpuid.h (bit_SSE3): New.
diff --git a/gcc/testsuite/gcc.dg/pr29921-2.c b/gcc/testsuite/gcc.dg/pr29921-2.c
new file mode 100644 (file)
index 0000000..8cf665e
--- /dev/null
@@ -0,0 +1,27 @@
+/* With -ffast-math, the latice value for sum2 used to change from NaN to
+   VARYING, in turn causing the lattice value of sum1 * sum2 change from
+   NaN to 0 (since sum1 is believed to be 0 at that moment, and
+   0 * VARYING = 0 with -ffast-math), which caused an ICE.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+int
+foo (float *array, int end)
+{
+  int i;
+  float sum1, sum2;
+
+  sum2 = 0;
+  for (i = 0; i < end; i++)
+    sum2 = sum2+array[i];
+  sum2 = 1./sum2;
+  sum1 = 0.;
+  for (i = 0; i < end; i++)
+    sum1 = sum1+array[i];
+  sum1 = sum1 * sum2;
+  if (-10.0 / sum1 < 5.E-5)
+    end = 0;
+  return end;
+}
+
index 2acd62e..8da29e4 100644 (file)
@@ -418,6 +418,54 @@ set_value_varying (tree var)
   val->mem_ref = NULL_TREE;
 }
 
+/* For float types, modify the value of VAL to make ccp work correctly
+   for non-standard values (-0, NaN):
+
+   If HONOR_SIGNED_ZEROS is false, and VAL = -0, we canonicalize it to 0.
+   If HONOR_NANS is false, and VAL is NaN, we canonicalize it to UNDEFINED.
+     This is to fix the following problem (see PR 29921): Suppose we have
+
+     x = 0.0 * y
+
+     and we set value of y to NaN.  This causes value of x to be set to NaN.
+     When we later determine that y is in fact VARYING, fold uses the fact
+     that HONOR_NANS is false, and we try to change the value of x to 0,
+     causing an ICE.  With HONOR_NANS being false, the real appearance of
+     NaN would cause undefined behavior, though, so claiming that y (and x)
+     are UNDEFINED initially is correct.  */
+
+static void
+canonicalize_float_value (prop_value_t *val)
+{
+  enum machine_mode mode;
+  tree type;
+  REAL_VALUE_TYPE d;
+
+  if (val->lattice_val != CONSTANT
+      || TREE_CODE (val->value) != REAL_CST)
+    return;
+
+  d = TREE_REAL_CST (val->value);
+  type = TREE_TYPE (val->value);
+  mode = TYPE_MODE (type);
+
+  if (!HONOR_SIGNED_ZEROS (mode)
+      && REAL_VALUE_MINUS_ZERO (d))
+    {
+      val->value = build_real (type, dconst0);
+      return;
+    }
+
+  if (!HONOR_NANS (mode)
+      && REAL_VALUE_ISNAN (d))
+    {
+      val->lattice_val = UNDEFINED;
+      val->value = NULL;
+      val->mem_ref = NULL;
+      return;
+    }
+}
+
 /* Set the value for variable VAR to NEW_VAL.  Return true if the new
    value is different from VAR's previous value.  */
 
@@ -426,6 +474,8 @@ set_lattice_value (tree var, prop_value_t new_val)
 {
   prop_value_t *old_val = get_value (var);
 
+  canonicalize_float_value (&new_val);
+
   /* Lattice transitions must always be monotonically increasing in
      value.  If *OLD_VAL and NEW_VAL are the same, return false to
      inform the caller that this was a non-transition.  */