diff options
author | Vladimir N. Makarov <vmakarov@redhat.com> | 2023-05-30 15:54:28 -0400 |
---|---|---|
committer | Vladimir N. Makarov <vmakarov@redhat.com> | 2023-05-30 15:57:18 -0400 |
commit | 30038a207c10a2783fa2695b62c7c8458ef05e73 (patch) | |
tree | bbed5f80b155622418f26839285dc843d83846b3 /gcc/lra.cc | |
parent | 2720bbd597f56742a17119dfe80edc2ba86af255 (diff) | |
download | gcc-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.cc | 29 |
1 files changed, 25 insertions, 4 deletions
@@ -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) { |