https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94356
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Given struct S { char a[37]; }; int f1 (struct S *s, int a) { struct S *sa = s + a; return s < sa; } int f2 (struct S *s, int a, int b) { struct S *sa = s + a; return sa < s + b; } int f3 (struct S *s, int a) { struct S *sa = s + a; return s == sa; } int f4 (struct S *s, int a, int b) { struct S *sa = s + a; return sa == s + b; } f3 is optimized in: /* X + Y < Y is the same as X < 0 when there is no overflow. */ ... /* For equality, this is also true with wrapping overflow. */ ... (simplify (op:c (nop_convert?@3 (pointer_plus@2 (convert1? @0) @1)) (convert2? @0)) (if (tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0)) && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0)) && (CONSTANT_CLASS_P (@1) || (single_use (@2) && single_use (@3)))) (op @1 { build_zero_cst (TREE_TYPE (@1)); })))) f4 is optimized too, but not exactly sure where, partly e.g. in /* For integral types with wrapping overflow and C odd fold x * C EQ/NE y * C into x EQ/NE y. */ (for cmp (eq ne) (simplify (cmp (mult @0 INTEGER_CST@1) (mult @2 @1)) (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)) && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)) && (TREE_INT_CST_LOW (@1) & 1) != 0) (cmp @0 @2)))) For f1/f2 we likely only optimize the ptr + x < ptr + y into x < y at RTL time, and in any case, the multiplications are done right now in sizetype which is unsigned type.