> +/* As a special case, X + C < Y + C is the same as X < Y even with wrapping
> +   overflow if X and Y are signed integers of the same size, and C is an
> +   unsigned constant with all bits except MSB set to 0 and size >= that of
> +   X/Y.  */
> +(for op (lt le ge gt)
> + (simplify
> +  (op (plus:c (convert@0 @1) @4) (plus:c (convert@2 @3) @4))
> +  (if (CONSTANT_CLASS_P (@4)
> +       && TYPE_UNSIGNED (TREE_TYPE (@4))
>
> why include (convert ..) here?  It looks like you could do without,
> merging the special case with the preceding pattern and let a followup
> pattern simplify (lt (convert @1) (convert @2)) instead?

Thanks for taking a look at this patch.

It looks like the convert and plus need to be taken into account
together when applying this simplification.

1. 0x80000000 is *just* large enough to be interpreted as an unsigned.

2. So, an expression like...

x + 0x80000000 < y + 0x80000000;

...where x and y are signed actually gets interpreted as:

(unsigned) x + 0x80000000 < (unsigned) y + 0x80000000

3. Now, adding 0x80000000 to (unsigned) INT_MIN gives us 0,
and adding it to (unsigned) INT_MAX gives us UINT_MAX.

4. So, if x < y is true when they are compared as signed integers, then...
(unsigned) x + 0x80000000 < (unsigned) y + 0x80000000
...will also be true.

5. i.e. the unsigned comparison must be replaced by a signed
comparison when we remove the constant, and so the constant and
convert need to be matched and removed together.

Reply via email to