]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR120169, LRA]: Fix up REG_ARGS_SIZE note for output reloads
authorVladimir N. Makarov <vmakarov@redhat.com>
Wed, 18 Feb 2026 18:00:58 +0000 (13:00 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Wed, 18 Feb 2026 18:06:51 +0000 (13:06 -0500)
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.

gcc/lra-constraints.cc
gcc/lra-int.h
gcc/lra.cc
gcc/testsuite/gcc.target/m68k/pr120169.c [new file with mode: 0644]

index 2b5b4ba1bbd4064f98f870f1165f79ab4b290d83..ccd68efc9561ecf780f2aa71927b4b76fcfce51a 100644 (file)
@@ -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))
index bdcbf0cd2bf3370b3d8c4a51c2cbaf744c50686d..1c0561f496cfbc2f2aa5fd7df7c892f87a942ed5 100644 (file)
@@ -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);
index 33b5f07ef991557b591e587b531f4556c95d1177..20a3db45747682d464905a7c266259095662216b 100644 (file)
@@ -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 (file)
index 0000000..a84c1e9
--- /dev/null
@@ -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;
+  }
+}