aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra.cc
diff options
context:
space:
mode:
authorVladimir N. Makarov <vmakarov@redhat.com>2023-05-30 15:54:28 -0400
committerVladimir N. Makarov <vmakarov@redhat.com>2023-05-30 15:57:18 -0400
commit30038a207c10a2783fa2695b62c7c8458ef05e73 (patch)
treebbed5f80b155622418f26839285dc843d83846b3 /gcc/lra.cc
parent2720bbd597f56742a17119dfe80edc2ba86af255 (diff)
downloadgcc-30038a207c10a2783fa2695b62c7c8458ef05e73.zip
gcc-30038a207c10a2783fa2695b62c7c8458ef05e73.tar.gz
gcc-30038a207c10a2783fa2695b62c7c8458ef05e73.tar.bz2
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.
Diffstat (limited to 'gcc/lra.cc')
-rw-r--r--gcc/lra.cc29
1 files changed, 25 insertions, 4 deletions
diff --git a/gcc/lra.cc b/gcc/lra.cc
index eb3ee1f..c8b3f13 100644
--- a/gcc/lra.cc
+++ b/gcc/lra.cc
@@ -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)
{