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;
       }

Reply via email to