diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/dfp/pr108068.c | 14 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.cc | 12 | ||||
-rw-r--r-- | gcc/tree.cc | 29 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
4 files changed, 50 insertions, 6 deletions
diff --git a/gcc/testsuite/gcc.dg/dfp/pr108068.c b/gcc/testsuite/gcc.dg/dfp/pr108068.c new file mode 100644 index 0000000..6cbb0fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/pr108068.c @@ -0,0 +1,14 @@ +/* PR tree-optimization/108068 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int +main () +{ + _Decimal64 x = -1; + while (x != 0) + x /= 10; + double d = x; + if (!__builtin_signbit (d)) + __builtin_abort (); +} diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc index c9e52d1..76834fd 100644 --- a/gcc/tree-ssa-dom.cc +++ b/gcc/tree-ssa-dom.cc @@ -615,9 +615,9 @@ record_edge_info (basic_block bb) { tree cond = build2 (code, boolean_type_node, op0, op1); tree inverted = invert_truthvalue_loc (loc, cond); - bool can_infer_simple_equiv - = !(HONOR_SIGNED_ZEROS (op0) - && real_zerop (op0)); + bool can_infer_simple_equiv + = !(HONOR_SIGNED_ZEROS (op0) && real_maybe_zerop (op0)) + && !DECIMAL_FLOAT_MODE_P (element_mode (TREE_TYPE (op0))); class edge_info *edge_info; edge_info = new class edge_info (true_edge); @@ -639,9 +639,9 @@ record_edge_info (basic_block bb) { tree cond = build2 (code, boolean_type_node, op0, op1); tree inverted = invert_truthvalue_loc (loc, cond); - bool can_infer_simple_equiv - = !(HONOR_SIGNED_ZEROS (op1) - && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1))); + bool can_infer_simple_equiv + = !(HONOR_SIGNED_ZEROS (op1) && real_maybe_zerop (op1)) + && !DECIMAL_FLOAT_MODE_P (element_mode (TREE_TYPE (op1))); class edge_info *edge_info; edge_info = new class edge_info (true_edge); diff --git a/gcc/tree.cc b/gcc/tree.cc index 581d448..6b3273e 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -3180,6 +3180,35 @@ real_minus_onep (const_tree expr) } } +/* Return true if T could be a floating point zero. */ + +bool +real_maybe_zerop (const_tree expr) +{ + switch (TREE_CODE (expr)) + { + case REAL_CST: + /* Can't use real_zerop here, as it always returns false for decimal + floats. And can't use TREE_REAL_CST (expr).cl == rvc_zero + either, as decimal zeros are rvc_normal. */ + return real_equal (&TREE_REAL_CST (expr), &dconst0); + case COMPLEX_CST: + return (real_maybe_zerop (TREE_REALPART (expr)) + || real_maybe_zerop (TREE_IMAGPART (expr))); + case VECTOR_CST: + { + unsigned count = vector_cst_encoded_nelts (expr); + for (unsigned int i = 0; i < count; ++i) + if (real_maybe_zerop (VECTOR_CST_ENCODED_ELT (expr, i))) + return true; + return false; + } + default: + /* Perhaps for SSA_NAMEs we could query frange. */ + return true; + } +} + /* Nonzero if EXP is a constant or a cast of a constant. */ bool @@ -5497,6 +5497,7 @@ extern bool needs_to_live_in_memory (const_tree); extern tree reconstruct_complex_type (tree, tree); extern bool real_onep (const_tree); extern bool real_minus_onep (const_tree); +extern bool real_maybe_zerop (const_tree); extern void init_ttree (void); extern void build_common_tree_nodes (bool); extern void build_common_builtin_nodes (void); |