aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2006-12-01 14:49:15 +0000
committerH.J. Lu <hongjiu.lu@intel.com>2006-12-01 14:49:15 +0000
commit92fec92bebac43854f521b6e3cad5e0cd3a5c4f3 (patch)
treeaa1dba69bcd0e050b46624384b26f68ddf848913
parent50ba5bd002b3076c6c74d5d9084f817920b5b014 (diff)
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-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: https://gcc.gnu.org/svn/gcc/trunk@119401 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr29921-2.c27
-rw-r--r--gcc/tree-ssa-ccp.c50
4 files changed, 89 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4995449c4fc..52452d51629 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f16250dfb44..a7149088e55 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..8cf665eede0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr29921-2.c
@@ -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;
+}
+
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 2acd62e3691..8da29e4be51 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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. */