diff options
author | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-01 14:49:15 +0000 |
---|---|---|
committer | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-01 14:49:15 +0000 |
commit | b31eb493bb0a06f578cdb18d3f98331156b85d9c (patch) | |
tree | aa1dba69bcd0e050b46624384b26f68ddf848913 /gcc | |
parent | 6352eedf086531d547cc82e2e686bada514d9c3d (diff) | |
download | gcc-b31eb493bb0a06f578cdb18d3f98331156b85d9c.tar.gz |
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: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119401 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr29921-2.c | 27 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 50 |
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. */ |