[gcc r17-2979] fold-const, match.pd: Improve ptr_difference_const optimizations
Jakub Jelinek via Gcc-cvs <[email protected]> Wed, 5 Aug 2026 10:16:39 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:141edd02af705696f89ff9a804879dc51834898d commit r17-2979-g141edd02af705696f89ff9a804879dc51834898d Author: Jakub Jelinek <[email protected]> Date: Wed Aug 5 12:15:24 2026 +0200 fold-const, match.pd: Improve ptr_difference_const optimizations As mentioned in https://gcc.gnu.org/pipermail/gcc-patches/2026-July/725438.html at least the /* Convert (T1)(X p+ Y) into ((T1)X p+ Y), for pointer type, when the new cast (T1)X will fold away. We assume that this happens when X itself is a cast. */ fold-const.cc (fold_unary) optimization is highly undesirable in the C++ FE (at least before the cp_fold_function/gimplification). In the above patch I've tried to disable some optimizations (and Jason suggested to disable them even slightly less), but still that can at least in theory (but with the above patch in practice too) result in regressions, in particular in POINTER_DIFF_EXPR constant evaluation. In that testcase, we end up with (((((int*)(& x)) + 12) - (((int*)(& x)) + 4)) / 4) and the current ptr_difference_const match.pd optimizations aren't prepared to handle that. The following patch fixes that by adding STRIP_NOPS (exp); to split_address_to_core_and_offset which ptr_difference_const uses and then just throwing some ADDR_EXPR requirements in the simplification patterns - ptr_difference_const will return true if it is something it can handle, and it doesn't have to be just ADDR_EXPR, it can be also POINTER_PLUS_EXPR with constant offset, or nop conversions around either of those or nop conversions around first POINTER_PLUS_EXPR operand. In some cases after dropping the ADDR_EXPR parts I could throw away one pattern because two adjusted patterns were identical, in one case (minus with casts meant for subtraction of pointers cast to intptr_t/uintptr_t) I had to add another tree_nop_conversion_p check, so that e.g. floating point difference x - x which can't be folded away because it could trap isn't attempted to be folded (as build_int_cst for floating point would ICE). And/or should I try even harder, handle not just SSA_NAME with ADDR_EXPR as def_stmt, but also with nop conversions or POINTER_PLUS, and in case of pointer plus perhaps even recurse and add the two bitpos/offsets together? 2026-08-05 Jakub Jelinek <[email protected]> * fold-const.cc (split_address_to_core_and_offset): Use STRIP_NOPS. * match.pd ((&a + b) !=/== (&a[1] + c) -> (&a[0] - &a[1]) + b !=/== c): Don't require captures to be ADDR_EXPR. ((&a+b) - (&a[1] + c) -> sizeof(a[0]) + (b - c)): Likewise. ((p + b) - &p->d -> offsetof (*p, d) + b): Likewise. (Try folding difference of addresses): Likewise. Remove redundant simplifications because of that. Reviewed-by: Richard Biener <[email protected]> Diff: --- gcc/fold-const.cc | 2 ++ gcc/match.pd | 41 ++++++++++++++++------------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index e1793ac89f25..64d0e7208ce8 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -16166,6 +16166,8 @@ split_address_to_core_and_offset (tree exp, poly_int64 bitsize; location_t loc = EXPR_LOCATION (exp); + STRIP_NOPS (exp); + if (TREE_CODE (exp) == SSA_NAME) if (gassign *def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (exp))) if (gimple_assign_rhs_code (def) == ADDR_EXPR) diff --git a/gcc/match.pd b/gcc/match.pd index 2545d62b4ab4..9bd6d2f7e077 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3089,12 +3089,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (&a + b) !=/== (&a[1] + c) -> (&a[0] - &a[1]) + b !=/== c */ (for neeq (ne eq) (simplify - (neeq:c (pointer_plus @2 @3) ADDR_EXPR@0) + (neeq:c (pointer_plus @2 @3) @0) (with { poly_int64 diff; tree inner_type = TREE_TYPE (@3);} (if (ptr_difference_const (@0, @2, &diff)) (neeq { build_int_cst_type (inner_type, diff); } @3)))) (simplify - (neeq (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3)) + (neeq (pointer_plus @0 @1) (pointer_plus @2 @3)) (with { poly_int64 diff; tree inner_type = TREE_TYPE (@1);} (if (ptr_difference_const (@0, @2, &diff)) (neeq (plus { build_int_cst_type (inner_type, diff); } @1) @3))))) @@ -3310,38 +3310,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Try folding difference of addresses. */ (simplify - (minus (convert ADDR_EXPR@0) (convert (pointer_plus @1 @2))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (minus (convert @0) (convert (pointer_plus @1 @2))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) + && tree_nop_conversion_p (type, TREE_TYPE (@1))) (with { poly_int64 diff; } (if (ptr_difference_const (@0, @1, &diff)) (minus { build_int_cst_type (type, diff); } (convert @2)))))) (simplify - (minus (convert (pointer_plus @0 @2)) (convert ADDR_EXPR@1)) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (minus (convert (pointer_plus @0 @2)) (convert @1)) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) + && tree_nop_conversion_p (type, TREE_TYPE (@1))) (with { poly_int64 diff; } (if (ptr_difference_const (@0, @1, &diff)) (plus (convert @2) { build_int_cst_type (type, diff); }))))) (simplify - (minus (convert ADDR_EXPR@0) (convert @1)) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) - (with { poly_int64 diff; } - (if (ptr_difference_const (@0, @1, &diff)) - { build_int_cst_type (type, diff); })))) -(simplify - (minus (convert @0) (convert ADDR_EXPR@1)) - (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) - (with { poly_int64 diff; } - (if (ptr_difference_const (@0, @1, &diff)) - { build_int_cst_type (type, diff); })))) -(simplify - (pointer_diff (convert?@2 ADDR_EXPR@0) (convert1?@3 @1)) - (if (tree_nop_conversion_p (TREE_TYPE(@2), TREE_TYPE (@0)) - && tree_nop_conversion_p (TREE_TYPE(@3), TREE_TYPE (@1))) + (minus (convert @0) (convert @1)) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) + && tree_nop_conversion_p (type, TREE_TYPE (@1)) + && tree_nop_conversion_p (type, ptr_type_node)) (with { poly_int64 diff; } (if (ptr_difference_const (@0, @1, &diff)) { build_int_cst_type (type, diff); })))) (simplify - (pointer_diff (convert?@2 @0) (convert1?@3 ADDR_EXPR@1)) + (pointer_diff (convert?@2 @0) (convert1?@3 @1)) (if (tree_nop_conversion_p (TREE_TYPE(@2), TREE_TYPE (@0)) && tree_nop_conversion_p (TREE_TYPE(@3), TREE_TYPE (@1))) (with { poly_int64 diff; } @@ -3350,18 +3341,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (&a+b) - (&a[1] + c) -> sizeof(a[0]) + (b - c) */ (simplify - (pointer_diff (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3)) + (pointer_diff (pointer_plus @0 @1) (pointer_plus @2 @3)) (with { poly_int64 diff; } (if (ptr_difference_const (@0, @2, &diff)) (plus { build_int_cst_type (type, diff); } (convert (minus @1 @3)))))) /* (p + b) - &p->d -> offsetof (*p, d) + b */ (simplify - (pointer_diff (pointer_plus @0 @1) ADDR_EXPR@2) + (pointer_diff (pointer_plus @0 @1) @2) (with { poly_int64 diff; } (if (ptr_difference_const (@0, @2, &diff)) (plus { build_int_cst_type (type, diff); } (convert @1))))) (simplify - (pointer_diff ADDR_EXPR@0 (pointer_plus @1 @2)) + (pointer_diff @0 (pointer_plus @1 @2)) (with { poly_int64 diff; } (if (ptr_difference_const (@0, @1, &diff)) (minus { build_int_cst_type (type, diff); } (convert @2)))))