aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2024-08-08 16:50:39 +0200
committerGeorg-Johann Lay <avr@gjlay.de>2024-08-08 18:39:44 +0200
commitef697f83917e6380e979c196b330ad8ad84b8ce0 (patch)
tree9aaa579c64f837b4f26a081c1061d3a9666fc62b
parent715317331994d3d69395056f77bfe7ac613af009 (diff)
downloadgcc-ef697f83917e6380e979c196b330ad8ad84b8ce0.zip
gcc-ef697f83917e6380e979c196b330ad8ad84b8ce0.tar.gz
gcc-ef697f83917e6380e979c196b330ad8ad84b8ce0.tar.bz2
AVR: Improve POST_INC output in some rare cases.
gcc/ * config/avr/avr.cc (avr_insn_has_reg_unused_note_p): New function. (_reg_unused_after): Use it to recognize more cases. (avr_out_lpm_no_lpmx) [POST_INC]: Use reg_unused_after.
-rw-r--r--gcc/config/avr/avr.cc32
1 files changed, 31 insertions, 1 deletions
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 7229aac..0b3fd7a 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4621,7 +4621,7 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
avr_asm_len ("mov %0,r0", &reg, plen, 1);
}
- if (! _reg_unused_after (insn, xop[2], false))
+ if (! reg_unused_after (insn, xop[2]))
avr_asm_len ("adiw %2,1", xop, plen, 1);
break; /* POST_INC */
@@ -11318,6 +11318,25 @@ avr_adjust_insn_length (rtx_insn *insn, int len)
return len;
}
+
+/* Return true when INSN has a REG_UNUSED note for hard reg REG.
+ rtlanal.cc::find_reg_note() uses == to compare XEXP (link, 0)
+ therefore use a custom function. */
+
+static bool
+avr_insn_has_reg_unused_note_p (rtx_insn *insn, rtx reg)
+{
+ for (rtx link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_UNUSED
+ && REG_P (XEXP (link, 0))
+ && REGNO (reg) >= REGNO (XEXP (link, 0))
+ && END_REGNO (reg) <= END_REGNO (XEXP (link, 0)))
+ return true;
+
+ return false;
+}
+
+
/* Return nonzero if register REG dead after INSN. */
int
@@ -11344,6 +11363,17 @@ _reg_unused_after (rtx_insn *insn, rtx reg, bool look_at_insn)
if (set && !MEM_P (SET_DEST (set))
&& reg_overlap_mentioned_p (reg, SET_DEST (set)))
return 1;
+
+ /* This case occurs when fuse-add introduced a POST_INC addressing,
+ but the address register is unused after. */
+ if (set)
+ {
+ rtx mem = MEM_P (SET_SRC (set)) ? SET_SRC (set) : SET_DEST (set);
+ if (MEM_P (mem)
+ && reg_overlap_mentioned_p (reg, XEXP (mem, 0))
+ && avr_insn_has_reg_unused_note_p (insn, reg))
+ return 1;
+ }
}
while ((insn = NEXT_INSN (insn)))