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; + } +}
