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

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #3)
> I think when overflow wraps we cannot do this transform at all, independent
> on the "sign" of 'c'.
> 
> Maybe
> 
> @@ -6970,8 +6972,11 @@ extract_muldiv_1 (tree t, tree c, enum tree_code
> code, tree wide_type,
>  
>        /* MIN (a, b) / 5 -> MIN (a / 5, b / 5)  */
>        sub_strict_overflow_p = false;
> -      if ((t1 = extract_muldiv (op0, c, code, wide_type,
> -                               &sub_strict_overflow_p)) != 0
> +      if ((wide_type
> +          ? TYPE_OVERFLOW_UNDEFINED (wide_type)
> +          : TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))) 
> +         && (t1 = extract_muldiv (op0, c, code, wide_type,
> +                                  &sub_strict_overflow_p)) != 0
>           && (t2 = extract_muldiv (op1, c, code, wide_type,
>                                    &sub_strict_overflow_p)) != 0)
>         {

but even when overflow is undefined we don't know whether we introduce
additional overflow then.  Consider MAX (INT_MIN, 0) * -1 where we compute
0 * -1 (fine) but after the transform we'd do MIN (INT_MIN * -1, 0)
which isn't valid.

And when overflow wraps consider MAX (UINT_MAX, 1) * 2 which
will compute UINT_MAX * 2 == 0 while MAX (UINT_MAX * 2, 1 * 2) will compute 2.

Unless I'm missing something.

What we'd need to know is whether the inner operations are known to not
overflow/wrap (or whether they change sign consistently).  But without
range info we can't know this unless op0 and op1 are constants.

So - scrap that whole sub-rule?

Reply via email to