The following patch fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120169

The patch was successfully bootstrapped and tested on x86-64 and checked on m68k using the test case.

commit a169450924cea718f7bb847f2cac70c2d781440d
Author: Vladimir N. Makarov <[email protected]>
Date:   Wed Feb 18 13:00:58 2026 -0500

    [PR120169, LRA]: Fix up REG_ARGS_SIZE note for output reloads
    
    In this test case, LRA reloads arg push insn but does not move original
    REG_ARGS_SIZE note to the reload insn which becomes a new arg push.  The
    patch fixes it.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/120169
            * lra-int.h (lra_process_new_insns): Modify the prototype.
            * lra.cc (lra_process_new_insns): Add arg fixup_reg_args_size with
            implicit value.  Move REG_ARGS_SIZE note if necessary.
            * lra-constraints.cc (curr_insn_transform): Pass the new arg value.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/120169
            * gcc.target/m68k/pr120169.c: New.

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 2b5b4ba1bbd..ccd68efc956 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -5082,7 +5082,8 @@ curr_insn_transform (bool check_only_p)
 	  const_insn = prev;
 	}
     }
-  lra_process_new_insns (curr_insn, before, after, "Inserting insn reload");
+  lra_process_new_insns (curr_insn, before, after,
+			 "Inserting insn reload", true);
   if (const_regno >= 0) {
     bool move_p = true;
     for (rtx_insn *insn = before; insn != curr_insn; insn = NEXT_INSN (insn))
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index bdcbf0cd2bf..1c0561f496c 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -328,8 +328,9 @@ extern void lra_asm_insn_error (rtx_insn *insn);
 extern void lra_dump_insns (FILE *f);
 extern void lra_dump_insns_if_possible (const char *title);
 
-extern void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *,
-				   const char *);
+extern void lra_process_new_insns (rtx_insn *insn, rtx_insn *before,
+				   rtx_insn *after, const char *title,
+				   bool fixup_reg_args_size = false);
 
 extern bool lra_substitute_pseudo (rtx *, int, rtx, bool, bool);
 extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx, bool);
diff --git a/gcc/lra.cc b/gcc/lra.cc
index 33b5f07ef99..20a3db45747 100644
--- a/gcc/lra.cc
+++ b/gcc/lra.cc
@@ -1920,12 +1920,12 @@ lra_dump_insns_if_possible (const char *title)
   lra_dump_insns (lra_dump_file);
 }
 
-/* Emit insns BEFORE before INSN and insns AFTER after INSN.  Put the
-   insns onto the stack.  Print about emitting the insns with
-   TITLE.  */
+/* Emit insns BEFORE before INSN and insns AFTER after INSN.  Put the insns
+   onto the stack.  Print about emitting the insns with TITLE.  Move insn
+   REG_ARGS_SIZE note to AFTER insns if FIXUP_REG_ARGS_SIZE.  */
 void
 lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
-		       const char *title)
+		       const char *title, bool fixup_reg_args_size)
 {
   if (before == NULL_RTX && after == NULL_RTX)
     return;
@@ -1983,6 +1983,25 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
 	  emit_insn_after (after, insn);
 	  push_insns (last, insn);
 	  setup_sp_offset (after, last);
+	  if (fixup_reg_args_size)
+	    {
+	      rtx note = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
+	      if (note)
+		{
+		  remove_note (insn, note);
+		  fixup_args_size_notes (insn, last,
+					 get_args_size (note));
+		  if (lra_dump_file != NULL)
+		    {
+		      fprintf (lra_dump_file,
+			       "    fixing up REG_SIZE_NOTE for:\n");
+		      dump_rtl_slim (lra_dump_file, insn, insn, -1, 0);
+		      fprintf (lra_dump_file, "    fixed insns after:\n");
+		      dump_rtl_slim (lra_dump_file,
+				     NEXT_INSN (insn), last, -1, 0);
+		    }
+		}
+	    }
 	}
       else
 	{
diff --git a/gcc/testsuite/gcc.target/m68k/pr120169.c b/gcc/testsuite/gcc.target/m68k/pr120169.c
new file mode 100644
index 00000000000..a84c1e9482e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr120169.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -fPIC" } */
+
+typedef void *decl_node;
+bool decl_isRecordField(decl_node);
+void decl_lookupSym(int);
+void mcDebug_assert(bool);
+typedef enum { decl_varient } decl_nodeT;
+typedef struct decl_nodeRec_r *decl_node__opaque;
+struct decl_nodeRec_r {
+  decl_nodeT kind;
+};
+decl_node__opaque tag, putVarientTag_tag, putVarientTag_v,
+    decl_buildVarientSelector_f;
+int decl_buildVarientSelector_tag;
+decl_node decl_buildVarientSelector_type;
+void decl_buildVarientSelector() {
+  mcDebug_assert(0);
+  if (decl_buildVarientSelector_type) {
+    decl_lookupSym(decl_buildVarientSelector_tag);
+    mcDebug_assert(0);
+    switch (putVarientTag_v->kind)
+    case decl_varient:
+      tag = putVarientTag_tag;
+  } else {
+    bool __trans_tmp_2 = decl_isRecordField(decl_buildVarientSelector_f);
+    mcDebug_assert(__trans_tmp_2);
+    mcDebug_assert(0);
+    switch (putVarientTag_v->kind)
+    case decl_varient:
+      tag = putVarientTag_tag;
+  }
+}

Reply via email to