aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-ccp.c
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 /gcc/tree-ssa-ccp.c
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
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r--gcc/tree-ssa-ccp.c90
1 files changed, 45 insertions, 45 deletions
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. */