https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84873
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
Or rather it looks like a tree sharing issue. The COND_EXPR is created via
fold_binary_op_with_conditional_arg when folding
(unsigned int) (long int) (1.0e+0 +
1.000000000000000055511151231257827021181583404541015625e-1) - (unsigned int)
(n9 == 0)
which is created via
/* Contract negates. */
/* A + (-B) -> A - B */
(simplify
(plus:c @0 (convert? (negate @1)))
/* Apply STRIP_NOPS on the negate. */
(if (tree_nop_conversion_p (type, TREE_TYPE (@1))
&& !TYPE_OVERFLOW_SANITIZED (type))
(with
{
tree t1 = type;
if (INTEGRAL_TYPE_P (type)
&& TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1);
}
(convert (minus (convert:t1 @0) (convert:t1 @1))))))
which in the end is reached via the gimplify_expr langhook doing
243 if (!VECTOR_TYPE_P (TREE_TYPE (*op1_p))
244 && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE
(*op1_p)),
245 unsigned_type_node)
246 && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE
(*op1_p)),
247 integer_type_node))
248 *op1_p = convert (unsigned_type_node, *op1_p);
and
#9 0x0000000000a40070 in convert_to_integer_1 (
type=<integer_type 0x7ffff68ac690 unsigned int>,
expr=<plus_expr 0x7ffff69c1938>, dofold=true)
at /space/rguenther/src/svn/early-lto-debug/gcc/convert.c:889
889 expr, inprec, outprec, dofold);
(gdb) l
884 || targetm.truly_noop_truncation (outprec, inprec)
885 || inprec > TYPE_PRECISION (TREE_TYPE (arg0))
886 || inprec > TYPE_PRECISION (TREE_TYPE (arg1)))
887 {
888 tree tem = do_narrow (loc, ex_form, type, arg0, arg1,
889 expr, inprec, outprec, dofold);
and this folding ends up creating tree sharing of
(unsigned int) (long int) (1.0e+0 +
1.000000000000000055511151231257827021181583404541015625e-1)
which is TREE_CONSTANT:
/* This transformation is only worthwhile if we don't have to wrap ARG
in a SAVE_EXPR and the operation can be simplified without recursing
on at least one of the branches once its pushed inside the COND_EXPR. */
if (!TREE_CONSTANT (arg)
&& (TREE_SIDE_EFFECTS (arg)
|| TREE_CODE (arg) == COND_EXPR || TREE_CODE (arg) == VEC_COND_EXPR
|| TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
return NULL_TREE;
...
/* Check that we have simplified at least one of the branches. */
if (!TREE_CONSTANT (arg) && !TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
return NULL_TREE;
but of course saying this is TREE_CONSTANT is somewhat of a lie because
with -frounding-math it depends on the rounding mode!
Which also means in this case the folding isn't quite worthwhile.
I'm somewhat hesitant to do sth like
Index: gcc/tree.c
===================================================================
--- gcc/tree.c (revision 258552)
+++ gcc/tree.c (working copy)
@@ -4682,8 +4682,9 @@ build2 (enum tree_code code, tree tt, tr
/* Expressions without side effects may be constant if their
arguments are as well. */
- constant = (TREE_CODE_CLASS (code) == tcc_comparison
- || TREE_CODE_CLASS (code) == tcc_binary);
+ constant = ((TREE_CODE_CLASS (code) == tcc_comparison
+ || TREE_CODE_CLASS (code) == tcc_binary)
+ && (!FLOAT_TYPE_P (TREE_TYPE (arg1)) || !flag_rounding_math));
read_only = 1;
side_effects = TREE_SIDE_EFFECTS (t);
at this point though. A better localized fix would be
Index: gcc/c-family/c-gimplify.c
===================================================================
--- gcc/c-family/c-gimplify.c (revision 258552)
+++ gcc/c-family/c-gimplify.c (working copy)
@@ -245,7 +245,15 @@ c_gimplify_expr (tree *expr_p, gimple_se
unsigned_type_node)
&& !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
integer_type_node))
- *op1_p = convert (unsigned_type_node, *op1_p);
+ {
+ /* ??? Do not use convert () here or fold arbitrary trees
+ since folding can introduce tree sharing which is not
+ allowed during gimplification. */
+ if (TREE_CODE (*op1_p) == INTEGER_CST)
+ *op1_p = fold_convert (unsigned_type_node, *op1_p);
+ else
+ *op1_p = build1 (NOP_EXPR, unsigned_type_node, *op1_p);
+ }
break;
}