[pushed] LRA: Update insn sp offset if its input reload changes SP
Checks
Commit Message
The following patch fixes an LRA bug triggered by switching H8300 target
from reload to LRA. The description of the problem is in the commit
message.
The patch was successfully bootstrapped and tested on x86-64, aarch64,
and ppc64le.
commit 30038a207c10a2783fa2695b62c7c8458ef05e73
Author: Vladimir N. Makarov <vmakarov@redhat.com>
Date: Tue May 30 15:54:28 2023 -0400
LRA: Update insn sp offset if its input reload changes SP
The patch fixes a bug when there is input reload changing SP. The bug was
triggered by switching H8300 target to LRA. The insn in question is
(insn 21 20 22 2 (set (mem/f:SI (pre_dec:SI (reg/f:SI 7 sp)) [3 S4 A32])
(reg/f:SI 31)) "j.c":10:3 19 {*movsi}
(expr_list:REG_DEAD (reg/f:SI 31)
(expr_list:REG_ARGS_SIZE (const_int 4 [0x4])
(nil))))
The memory address is reloaded but the SP offset for the original insn was not updated.
gcc/ChangeLog:
* lra-int.h (lra_update_sp_offset): Add the prototype.
* lra.cc (setup_sp_offset): Change the return type. Use
lra_update_sp_offset.
* lra-eliminations.cc (lra_update_sp_offset): New function.
(lra_process_new_insns): Push the current insn to reprocess if the
input reload changes sp offset.
Comments
On 5/30/23 14:05, Vladimir Makarov wrote:
> The following patch fixes an LRA bug triggered by switching H8300 target
> from reload to LRA. The description of the problem is in the commit
> message.
>
> The patch was successfully bootstrapped and tested on x86-64, aarch64,
> and ppc64le.
THanks. We should have H8 test data with this patch and LRA enabled
about this time tomorrow.
Jeff
@@ -1308,6 +1308,16 @@ init_elimination (void)
setup_elimination_map ();
}
+/* Update and return stack pointer OFFSET after processing X. */
+poly_int64
+lra_update_sp_offset (rtx x, poly_int64 offset)
+{
+ curr_sp_change = offset;
+ mark_not_eliminable (x, VOIDmode);
+ return curr_sp_change;
+}
+
+
/* Eliminate hard reg given by its location LOC. */
void
lra_eliminate_reg_if_possible (rtx *loc)
@@ -412,6 +412,7 @@ extern rtx lra_eliminate_regs_1 (rtx_insn *, rtx, machine_mode,
extern void eliminate_regs_in_insn (rtx_insn *insn, bool, bool, poly_int64);
extern void lra_eliminate (bool, bool);
+extern poly_int64 lra_update_sp_offset (rtx, poly_int64);
extern void lra_eliminate_reg_if_possible (rtx *);
@@ -1838,10 +1838,10 @@ push_insns (rtx_insn *from, rtx_insn *to)
lra_push_insn (insn);
}
-/* Set up sp offset for insn in range [FROM, LAST]. The offset is
+/* Set up and return sp offset for insns in range [FROM, LAST]. The offset is
taken from the next BB insn after LAST or zero if there in such
insn. */
-static void
+static poly_int64
setup_sp_offset (rtx_insn *from, rtx_insn *last)
{
rtx_insn *before = next_nonnote_nondebug_insn_bb (last);
@@ -1849,7 +1849,11 @@ setup_sp_offset (rtx_insn *from, rtx_insn *last)
? 0 : lra_get_insn_recog_data (before)->sp_offset);
for (rtx_insn *insn = from; insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
- lra_get_insn_recog_data (insn)->sp_offset = offset;
+ {
+ lra_get_insn_recog_data (insn)->sp_offset = offset;
+ offset = lra_update_sp_offset (PATTERN (insn), offset);
+ }
+ return offset;
}
/* Emit insns BEFORE before INSN and insns AFTER after INSN. Put the
@@ -1875,8 +1879,25 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
if (cfun->can_throw_non_call_exceptions)
copy_reg_eh_region_note_forward (insn, before, NULL);
emit_insn_before (before, insn);
+ poly_int64 old_sp_offset = lra_get_insn_recog_data (insn)->sp_offset;
+ poly_int64 new_sp_offset = setup_sp_offset (before, PREV_INSN (insn));
+ if (maybe_ne (old_sp_offset, new_sp_offset))
+ {
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " Changing sp offset from ");
+ print_dec (old_sp_offset, lra_dump_file);
+ fprintf (lra_dump_file, " to ");
+ print_dec (new_sp_offset, lra_dump_file);
+ fprintf (lra_dump_file, " for insn");
+ dump_rtl_slim (lra_dump_file, insn, NULL, -1, 0);
+ }
+ lra_get_insn_recog_data (insn)->sp_offset = new_sp_offset;
+ eliminate_regs_in_insn (insn, false, false,
+ old_sp_offset - new_sp_offset);
+ lra_push_insn (insn);
+ }
push_insns (PREV_INSN (insn), PREV_INSN (before));
- setup_sp_offset (before, PREV_INSN (insn));
}
if (after != NULL_RTX)
{