> +/* 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.