--- /dev/null
+/* 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 ();
+}
{
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);
{
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);
}
}
+/* 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
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);