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;

Reply via email to