https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81097

--- Comment #4 from rguenther at suse dot de <rguenther at suse dot de> ---
On Tue, 20 Jun 2017, mpolacek at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81097
> 
> --- Comment #3 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
> Well, my fix was
> 
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -850,7 +850,8 @@ split_tree (location_t loc, tree in, tree type, enum
> tree_code code,
>    else if (TREE_CONSTANT (in))
>      *conp = in;
>    else if (TREE_CODE (in) == BIT_NOT_EXPR
> -      && code == PLUS_EXPR)
> +      && code == PLUS_EXPR
> +      && negate_expr_p (TREE_OPERAND (in, 0)))
>      {
>        /* -X - 1 is folded to ~X, undo that here.  Do _not_ do this
>           when IN is constant.  */
> 
> but it has some fallout it seems.
> 
> Also, the comment says
> -X - 1 is folded to ~X, undo that here.
> but there was not -X - 1, the bit not came from
> ~x | ~y -> ~(x & y)
> in match.pd.

Yeah, it's not "undoing" but trying to cleverly combine ~x + 1 to x.
Possibly the fallout testcases you've seen or some archeology will tell.

I think it's really trying to "undo" this transform AFAIR (I remember
adding this code).

Using negate_expr_p is checking for "easily negatable", you could
use a TYPE_OVERFLOW_UNDEFINED check but that would have similar
fallout.  Or just force the negation to use an unsigned type
(my patch does this for the testcase), but I'm not even sure that
will work because if the original expr is int then ~x + ~x
becomes (int)(-(unsigned)x - (unsigned)x) - 2 and supposedly we can
craft x to be so that (int)(-(unsigned)x - (unsigned)x) - 2 will
overflow.  The associate case is somewhat defensive when associating
TYPE_OVERFLOW_UNDEFINED stuff but I'm not sure what it does is enough.

I'm currentlyu testing

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 249397)
+++ gcc/fold-const.c    (working copy)
@@ -853,9 +853,9 @@ split_tree (location_t loc, tree in, tre
           && code == PLUS_EXPR)
     {
       /* -X - 1 is folded to ~X, undo that here.  Do _not_ do this
-         when IN is constant.  */
-      *minus_litp = build_one_cst (TREE_TYPE (in));
-      var = negate_expr (TREE_OPERAND (in, 0));
+         when IN is constant.  Convert to TYPE before negating.  */
+      *minus_litp = build_one_cst (type);
+      var = negate_expr (fold_convert_loc (loc, type, TREE_OPERAND (in, 
0)));
     }
   else
     var = in;

which is, as I said, not enough but another testcase is appreciated ;)

Reply via email to