https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81281
--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Corresponding diff -upbd for better readability: --- gcc/match.pd.jj 2017-11-28 09:40:08.000000000 +0100 +++ gcc/match.pd 2017-12-05 11:36:58.855074420 +0100 @@ -1783,9 +1783,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (bit_not @0)) /* (T)(P + A) - (T)P -> (T) A */ - (for add (plus pointer_plus) (simplify - (minus (convert (add @@0 @1)) + (minus (convert (plus:c @@0 @1)) (convert @0)) (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For integer types, if A has a smaller type @@ -1796,7 +1795,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) undefined behavior, we can assume that there is no overflow. */ || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))) + (convert @1))) + (simplify + (minus (convert (pointer_plus @@0 @1)) + (convert @0)) + (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For pointer types, if the conversion of A to the final type requires a sign- or zero-extension, then we have to punt - it is not defined which @@ -1804,7 +1808,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || (POINTER_TYPE_P (TREE_TYPE (@0)) && TREE_CODE (@1) == INTEGER_CST && tree_int_cst_sign_bit (@1) == 0)) - (convert @1)))) + (convert @1))) (simplify (pointer_diff (pointer_plus @@0 @1) @0) /* The second argument of pointer_plus must be interpreted as signed, and @@ -1813,10 +1817,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (convert (convert:stype @1)))) /* (T)P - (T)(P + A) -> -(T) A */ - (for add (plus pointer_plus) (simplify (minus (convert @0) - (convert (add @@0 @1))) + (convert (plus:c @@0 @1))) + (if (INTEGRAL_TYPE_P (type) + && TYPE_OVERFLOW_UNDEFINED (type) + && element_precision (type) <= element_precision (TREE_TYPE (@1))) + (with { tree utype = unsigned_type_for (type); } + (convert (negate (convert:utype @1)))) (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For integer types, if A has a smaller type than T the result depends on the possible @@ -1826,7 +1834,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) undefined behavior, we can assume that there is no overflow. */ || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))) + (negate (convert @1))))) + (simplify + (minus (convert @0) + (convert (pointer_plus @@0 @1))) + (if (INTEGRAL_TYPE_P (type) + && TYPE_OVERFLOW_UNDEFINED (type) + && element_precision (type) <= element_precision (TREE_TYPE (@1))) + (with { tree utype = unsigned_type_for (type); } + (convert (negate (convert:utype @1)))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For pointer types, if the conversion of A to the final type requires a sign- or zero-extension, then we have to punt - it is not defined which @@ -1843,10 +1861,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (negate (convert (convert:stype @1))))) /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */ - (for add (plus pointer_plus) (simplify - (minus (convert (add @@0 @1)) - (convert (add @0 @2))) + (minus (convert (plus:c @@0 @1)) + (convert (plus:c @0 @2))) + (if (INTEGRAL_TYPE_P (type) + && TYPE_OVERFLOW_UNDEFINED (type) + && element_precision (type) <= element_precision (TREE_TYPE (@1))) + (with { tree utype = unsigned_type_for (type); } + (convert (minus (convert:utype @1) (convert:utype @2)))) (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For integer types, if A has a smaller type than T the result depends on the possible @@ -1856,7 +1878,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) undefined behavior, we can assume that there is no overflow. */ || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))) + (minus (convert @1) (convert @2))))) + (simplify + (minus (convert (pointer_plus @@0 @1)) + (convert (pointer_plus @0 @2))) + (if (INTEGRAL_TYPE_P (type) + && TYPE_OVERFLOW_UNDEFINED (type) + && element_precision (type) <= element_precision (TREE_TYPE (@1))) + (with { tree utype = unsigned_type_for (type); } + (convert (minus (convert:utype @1) (convert:utype @2)))) + (if (element_precision (type) <= element_precision (TREE_TYPE (@1)) /* For pointer types, if the conversion of A to the final type requires a sign- or zero-extension, then we have to punt - it is not defined which @@ -1866,13 +1898,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && tree_int_cst_sign_bit (@1) == 0 && TREE_CODE (@2) == INTEGER_CST && tree_int_cst_sign_bit (@2) == 0)) - (minus (convert @1) (convert @2))))))) + (minus (convert @1) (convert @2))))) (simplify (pointer_diff (pointer_plus @@0 @1) (pointer_plus @0 @2)) /* The second argument of pointer_plus must be interpreted as signed, and thus sign-extended if necessary. */ (with { tree stype = signed_type_for (TREE_TYPE (@1)); } - (minus (convert (convert:stype @1)) (convert (convert:stype @2))))) + (minus (convert (convert:stype @1)) (convert (convert:stype @2))))))) /* Simplifications of MIN_EXPR, MAX_EXPR, fmin() and fmax(). */