re PR tree-optimization/63914 (ICE in set_lattice_value, at tree-ssa-ccp.c:517)
authorRichard Biener <rguenther@suse.de>
Tue, 18 Nov 2014 13:03:46 +0000 (13:03 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 18 Nov 2014 13:03:46 +0000 (13:03 +0000)
2014-11-18  Richard Biener  <rguenther@suse.de>

PR tree-optimization/63914
* tree-ssa-ccp.c (canonicalize_value): Remove float value
canonicalization.
(valid_lattice_transition): Allow (partial) transition
from NaN to non-NaN if !HONOR_NANS.
(set_lattice_value): Check for valid lattice transitions
only when checking is enabled.

* gcc.dg/pr63914.c: New testcase.

From-SVN: r217712

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

index 2bce0f1baa8cfe5dd89963e398771add554e90d1..0bce05ab31711c519ba9b08ffbed294c1f945fec 100644 (file)
@@ -1,3 +1,13 @@
+2014-11-18  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/63914
+       * tree-ssa-ccp.c (canonicalize_value): Remove float value
+       canonicalization.
+       (valid_lattice_transition): Allow (partial) transition
+       from NaN to non-NaN if !HONOR_NANS.
+       (set_lattice_value): Check for valid lattice transitions
+       only when checking is enabled.
+
 2014-11-18  Bernd Schmidt  <bernds@codesourcery.com>
 
        * config/nvptx/nvptx.c: Include <sstream> directly after "config.h".
index c4f26efba9cd9d3af0bbdba815c364e9b8ebfcd3..679db5b350e346e4362b7fc039ff729b4c3021ca 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-18  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/63914
+       * gcc.dg/pr63914.c: New testcase.
+
 2014-11-18  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/55443
diff --git a/gcc/testsuite/gcc.dg/pr63914.c b/gcc/testsuite/gcc.dg/pr63914.c
new file mode 100644 (file)
index 0000000..fe57288
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+typedef float __m128 __attribute__ ((__vector_size__ (16)));
+__m128 a, d, e;
+int b;
+struct dt_interpolation c;
+__m128
+fn1 (float p1)
+{
+  return (__attribute__ ((__vector_size__ (4 * sizeof 0))) float){ p1 };
+}
+__m128
+fn2 (float p1)
+{
+  return fn1 (p1);
+}
+struct dt_interpolation
+{
+  int width;
+};
+void
+fn3 (struct dt_interpolation *p1, int *p2)
+{
+  int i = 0, n = 0;
+  while (i < 2 * p1->width)
+    n = i++;
+  *p2 = n;
+}
+void
+fn4 ()
+{
+  __m128 f;
+  fn3 (&c, &b);
+  __m128 g = fn2 (1.f / b);
+  e = (__m128){};
+  __m128 h = e;
+  for (int i = 0; i < 2 * c.width; i++)
+    {
+      for (; c.width;)
+       f = a;
+      h = f;
+    }
+  d = h * g;
+}
index b3efa99f6f65dd54e1ae6e0e392378087f1b9c18..2c8f6b9effd779f288a951ad291c499d35e8bfb0 100644 (file)
@@ -402,58 +402,16 @@ set_value_varying (tree var)
   val->mask = -1;
 }
 
-/* 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.
-
-  For other constants, make sure to drop TREE_OVERFLOW.  */
+/* For integer constants, make sure to drop TREE_OVERFLOW.  */
 
 static void
 canonicalize_value (ccp_prop_value_t *val)
 {
-  machine_mode mode;
-  tree type;
-  REAL_VALUE_TYPE d;
-
   if (val->lattice_val != CONSTANT)
     return;
 
   if (TREE_OVERFLOW_P (val->value))
     val->value = drop_tree_overflow (val->value);
-
-  if (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;
-      return;
-    }
 }
 
 /* Return whether the lattice transition is valid.  */
@@ -487,7 +445,49 @@ valid_lattice_transition (ccp_prop_value_t old_val, ccp_prop_value_t new_val)
            == wi::bit_and_not (wi::to_widest (new_val.value), new_val.mask));
 
   /* Otherwise constant values have to agree.  */
-  return operand_equal_p (old_val.value, new_val.value, 0);
+  if (operand_equal_p (old_val.value, new_val.value, 0))
+    return true;
+
+  /* At least the kinds and types should agree now.  */
+  if (TREE_CODE (old_val.value) != TREE_CODE (new_val.value)
+      || !types_compatible_p (TREE_TYPE (old_val.value),
+                             TREE_TYPE (new_val.value)))
+    return false;
+
+  /* For floats and !HONOR_NANS allow transitions from (partial) NaN
+     to non-NaN.  */
+  tree type = TREE_TYPE (new_val.value);
+  if (SCALAR_FLOAT_TYPE_P (type)
+      && !HONOR_NANS (TYPE_MODE (type)))
+    {
+      if (REAL_VALUE_ISNAN (TREE_REAL_CST (old_val.value)))
+       return true;
+    }
+  else if (VECTOR_FLOAT_TYPE_P (type)
+          && !HONOR_NANS (TYPE_MODE (TREE_TYPE (type))))
+    {
+      for (unsigned i = 0; i < VECTOR_CST_NELTS (old_val.value); ++i)
+       if (!REAL_VALUE_ISNAN
+              (TREE_REAL_CST (VECTOR_CST_ELT (old_val.value, i)))
+           && !operand_equal_p (VECTOR_CST_ELT (old_val.value, i),
+                                VECTOR_CST_ELT (new_val.value, i), 0))
+         return false;
+      return true;
+    }
+  else if (COMPLEX_FLOAT_TYPE_P (type)
+          && !HONOR_NANS (TYPE_MODE (TREE_TYPE (type))))
+    {
+      if (!REAL_VALUE_ISNAN (TREE_REAL_CST (TREE_REALPART (old_val.value)))
+         && !operand_equal_p (TREE_REALPART (old_val.value),
+                              TREE_REALPART (new_val.value), 0))
+       return false;
+      if (!REAL_VALUE_ISNAN (TREE_REAL_CST (TREE_IMAGPART (old_val.value)))
+         && !operand_equal_p (TREE_IMAGPART (old_val.value),
+                              TREE_IMAGPART (new_val.value), 0))
+       return false;
+      return true;
+    }
+  return false;
 }
 
 /* Set the value for variable VAR to NEW_VAL.  Return true if the new
@@ -514,7 +514,7 @@ set_lattice_value (tree var, ccp_prop_value_t new_val)
       new_val.mask = new_val.mask | old_val->mask | diff;
     }
 
-  gcc_assert (valid_lattice_transition (*old_val, new_val));
+  gcc_checking_assert (valid_lattice_transition (*old_val, new_val));
 
   /* If *OLD_VAL and NEW_VAL are the same, return false to inform the
      caller that this was a non-transition.  */