The following patch solves https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123796
The patch was successfully bootstrapped on x86-64 and manually tested on the test case.
commit a28fa991f042291d389a961aa1cf3750d48cd037 Author: Vladimir N. Makarov <[email protected]> Date: Mon Feb 9 09:04:05 2026 -0500 [PR123796, LRA]: Propagate pointer flag from the equivalence target Some targets can use pointer (frame related) flag to generate the correct code and improve the code. Substitution of equivalence in an insn and reloading it resulted in loosing pointer flag of the original equivalence target in the reload register. The patch solves this problem by using set of equivalences whose original targets have the pointer flags and propagating this flag to equivalence copies and reload registers. gcc/ChangeLog: PR rtl-optimization/123796 * lra-int.h (lra_pointer_equiv_set_add): Add prototype. (lra_pointer_equiv_set_in, lra_finish_equiv): Ditto. * lra.cc (lra_emit_move): Set up pointer flag of the destination if necessary. (lra): Call lra_finish_equiv. * lra-constraints.cc: Include hash-set.h. (pointer_equiv_set, lra_pointer_equiv_set_add): New. (lra_pointer_equiv_set_in, lra_finish_equiv): New. (get_equiv_with_elimination): Propagate pointer flag by adding to pointer_equiv_set. (process_addr_reg, curr_insn_transform): Ditto. diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index a25487be299..87b18f30c98 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -134,6 +134,7 @@ #include "print-rtl.h" #include "function-abi.h" #include "rtl-iter.h" +#include "hash-set.h" /* Value of LRA_CURR_RELOAD_NUM at the beginning of BB of the current insn. Remember that LRA_CURR_RELOAD_NUM is the number of emitted @@ -495,6 +496,23 @@ satisfies_address_constraint_p (rtx op, enum constraint_num constraint) return satisfies_address_constraint_p (&ad, constraint); } +/* Set of equivalences whose original targets have set up pointer flag. */ +static hash_set <rtx> *pointer_equiv_set; + +/* Add x to pointer_equiv_set. */ +void +lra_pointer_equiv_set_add (rtx x) +{ + pointer_equiv_set->add (x); +} + +/* Return true if x is in pointer_equiv_set. */ +bool +lra_pointer_equiv_set_in (rtx x) +{ + return pointer_equiv_set->contains (x); +} + /* Initiate equivalences for LRA. As we keep original equivalences before any elimination, we need to make copies otherwise any change in insns might change the equivalences. */ @@ -511,6 +529,14 @@ lra_init_equiv (void) if ((res = ira_reg_equiv[i].invariant) != NULL_RTX) ira_reg_equiv[i].invariant = copy_rtx (res); } + pointer_equiv_set = new hash_set <rtx>; +} + +/* Finish equivalence data for LRA. */ +void +lra_finish_equiv (void) +{ + delete pointer_equiv_set; } static rtx loc_equivalence_callback (rtx, const_rtx, void *); @@ -560,9 +586,9 @@ get_equiv (rtx x) gcc_unreachable (); } -/* If we have decided to substitute X with the equivalent value, - return that value after elimination for INSN, otherwise return - X. */ +/* If we have decided to substitute X with the equivalent value, return that + value after elimination for INSN, otherwise return X. Add the result to + pointer_equiv_set if X has set up pointer flag. */ static rtx get_equiv_with_elimination (rtx x, rtx_insn *insn) { @@ -570,8 +596,11 @@ get_equiv_with_elimination (rtx x, rtx_insn *insn) if (x == res || CONSTANT_P (res)) return res; - return lra_eliminate_regs_1 (insn, res, GET_MODE (res), - false, false, 0, true); + res = lra_eliminate_regs_1 (insn, res, GET_MODE (res), + false, false, 0, true); + if (REG_POINTER (x)) + lra_pointer_equiv_set_add (res); + return res; } /* Set up curr_operand_mode. */ @@ -1605,7 +1634,10 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **aft dump_value_slim (lra_dump_file, *loc, 1); fprintf (lra_dump_file, "\n"); } - *loc = copy_rtx (*loc); + rtx new_equiv = copy_rtx (*loc); + if (lra_pointer_equiv_set_in (*loc)) + lra_pointer_equiv_set_add (new_equiv); + *loc = new_equiv; } if (*loc != reg || ! in_class_p (reg, cl, &new_class)) { @@ -4333,7 +4365,10 @@ curr_insn_transform (bool check_only_p) if (subst != old) { equiv_substition_p[i] = true; - subst = copy_rtx (subst); + rtx new_subst = copy_rtx (subst); + if (lra_pointer_equiv_set_in (subst)) + lra_pointer_equiv_set_add (new_subst); + subst = new_subst; lra_assert (REG_P (old)); if (GET_CODE (op) != SUBREG) *curr_id->operand_loc[i] = subst; diff --git a/gcc/lra-int.h b/gcc/lra-int.h index 59f4f9a1ea0..bdcbf0cd2bf 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -359,6 +359,9 @@ extern bitmap_head lra_optional_reload_pseudos; /* lra-constraints.cc: */ extern void lra_init_equiv (void); +extern void lra_pointer_equiv_set_add (rtx); +extern bool lra_pointer_equiv_set_in (rtx); +extern void lra_finish_equiv (void); extern int lra_constraint_offset (int, machine_mode); extern int lra_constraint_iter; diff --git a/gcc/lra.cc b/gcc/lra.cc index 3c501c51c52..33b5f07ef99 100644 --- a/gcc/lra.cc +++ b/gcc/lra.cc @@ -489,16 +489,25 @@ int lra_curr_reload_num; static void remove_insn_scratches (rtx_insn *insn); -/* Emit x := y, processing special case when y = u + v or y = u + v * - scale + w through emit_add (Y can be an address which is base + - index reg * scale + displacement in general case). X may be used - as intermediate result therefore it should be not in Y. */ +/* Emit x := y, processing special case when y = u + v or y = u + v * scale + w + through emit_add (Y can be an address which is base + index reg * scale + + displacement in general case). X may be used as intermediate result + therefore it should be not in Y. Set up pointer flag of X if Y is + equivalence whose original target has setup pointer flag. */ void lra_emit_move (rtx x, rtx y) { int old; rtx_insn *insn; + if ((REG_P (x) || MEM_P (x)) && lra_pointer_equiv_set_in (y)) + { + /* Set up pointer flag from original equivalence target: */ + if (REG_P (x)) + REG_POINTER (x) = 1; + else + MEM_POINTER (x) = 1; + } if (GET_CODE (y) != PLUS) { if (rtx_equal_p (x, y)) @@ -2608,6 +2617,7 @@ lra (FILE *f, int verbose) sbitmap_free (lra_constraint_insn_stack_bitmap); lra_constraint_insn_stack.release (); finish_insn_recog_data (); + lra_finish_equiv (); regstat_free_n_sets_and_refs (); regstat_free_ri (); reload_completed = 1;
