diff options
author | H.J. Lu <hjl@gcc.gnu.org> | 2006-12-01 06:49:15 -0800 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2006-12-01 06:49:15 -0800 |
commit | fbb5445b5d23fddeda2a08ed95c63adb12f9a5d0 (patch) | |
tree | aa1dba69bcd0e050b46624384b26f68ddf848913 /gcc/tree-ssa-ccp.c | |
parent | b66b813d47ff264118b496f2e086591813049ba8 (diff) | |
download | gcc-fbb5445b5d23fddeda2a08ed95c63adb12f9a5d0.zip gcc-fbb5445b5d23fddeda2a08ed95c63adb12f9a5d0.tar.gz gcc-fbb5445b5d23fddeda2a08ed95c63adb12f9a5d0.tar.bz2 |
[multiple changes]
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.
From-SVN: r119401
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r-- | gcc/tree-ssa-ccp.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 2acd62e..8da29e4 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. */ |