aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-11-18 13:03:46 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-11-18 13:03:46 +0000
commitbee1d478578db03924bf2505092db9ee967190da (patch)
tree41bc9661bf4c4b0f4a1663b999f73d3a69378d74
parent60dcf0e05338baa02e0857cfca2742072994817a (diff)
downloadgcc-bee1d478578db03924bf2505092db9ee967190da.zip
gcc-bee1d478578db03924bf2505092db9ee967190da.tar.gz
gcc-bee1d478578db03924bf2505092db9ee967190da.tar.bz2
re PR tree-optimization/63914 (ICE in set_lattice_value, at tree-ssa-ccp.c:517)
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr63914.c45
-rw-r--r--gcc/tree-ssa-ccp.c90
4 files changed, 105 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2bce0f1..0bce05a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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".
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c4f26ef..679db5b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..fe57288
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr63914.c
@@ -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;
+}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index b3efa99..2c8f6b9 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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. */