mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54:07 +08:00
AVR: target/88236, target/115726 - Fix __memx code generation.
PR target/88236
PR target/115726
gcc/
* config/avr/avr.md (mov<mode>) [avr_mem_memx_p]: Expand in such a
way that the destination does not overlap with any hard register
clobbered / used by xload8qi_A resp. xload<mode>_A.
* config/avr/avr.cc (avr_out_xload): Avoid early-clobber
situation for Z by executing just one load when the output register
overlaps with Z.
gcc/testsuite/
* gcc.target/avr/torture/pr88236-pr115726.c: New test.
(cherry picked from commit 3d23abd3dd
)
This commit is contained in:
parent
1d6c409fdf
commit
53305588cf
@ -4071,7 +4071,13 @@ avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
|
||||
xop[2] = lpm_addr_reg_rtx;
|
||||
xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
|
||||
|
||||
avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
|
||||
if (plen)
|
||||
*plen = 0;
|
||||
|
||||
if (reg_overlap_mentioned_p (xop[3], lpm_addr_reg_rtx))
|
||||
avr_asm_len ("sbrs %1,7", xop, plen, 1);
|
||||
|
||||
avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1);
|
||||
|
||||
avr_asm_len ("sbrc %1,7" CR_TAB
|
||||
"ld %3,%a2", xop, plen, 2);
|
||||
|
@ -715,12 +715,26 @@
|
||||
if (!REG_P (addr))
|
||||
src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
|
||||
|
||||
rtx dest2 = reg_overlap_mentioned_p (dest, lpm_addr_reg_rtx)
|
||||
? gen_reg_rtx (<MODE>mode)
|
||||
: dest;
|
||||
|
||||
if (!avr_xload_libgcc_p (<MODE>mode))
|
||||
/* ; No <mode> here because gen_xload8<mode>_A only iterates over ALL1.
|
||||
; insn-emit does not depend on the mode, it's all about operands. */
|
||||
emit_insn (gen_xload8qi_A (dest, src));
|
||||
emit_insn (gen_xload8qi_A (dest2, src));
|
||||
else
|
||||
emit_insn (gen_xload<mode>_A (dest, src));
|
||||
{
|
||||
rtx reg_22 = gen_rtx_REG (<MODE>mode, 22);
|
||||
if (reg_overlap_mentioned_p (dest2, reg_22)
|
||||
|| reg_overlap_mentioned_p (dest2, all_regs_rtx[21]))
|
||||
dest2 = gen_reg_rtx (<MODE>mode);
|
||||
|
||||
emit_insn (gen_xload<mode>_A (dest2, src));
|
||||
}
|
||||
|
||||
if (dest2 != dest)
|
||||
emit_move_insn (dest, dest2);
|
||||
|
||||
DONE;
|
||||
}
|
||||
|
115
gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
Normal file
115
gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
Normal file
@ -0,0 +1,115 @@
|
||||
/* { dg-do run { target { ! avr_tiny } } } */
|
||||
/* { dg-additional-options "-std=gnu99" } */
|
||||
|
||||
const __flash char fvals8[] = { 1, 2, 3 };
|
||||
char rvals8[] = { 0, 2, 4 };
|
||||
|
||||
const __flash int fvals16[] = { 1, 2, 3 };
|
||||
int rvals16[] = { 0, 2, 4 };
|
||||
|
||||
__attribute__((noinline, noclone))
|
||||
char xload8_r30 (const __memx char *pc)
|
||||
{
|
||||
register char c __asm ("r30");
|
||||
c = *pc;
|
||||
__asm (";;" : "+r" (c));
|
||||
return c;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone))
|
||||
int xload16_r30 (const __memx int *pc)
|
||||
{
|
||||
register int c __asm ("r30");
|
||||
c = *pc;
|
||||
__asm (";;" : "+r" (c));
|
||||
return c;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone))
|
||||
char xload8_r22 (const __memx char *pc)
|
||||
{
|
||||
register char c __asm ("r22");
|
||||
c = *pc;
|
||||
__asm (";;" : "+r" (c));
|
||||
return c;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone))
|
||||
int xload16_r22 (const __memx int *pc)
|
||||
{
|
||||
register int c __asm ("r22");
|
||||
c = *pc;
|
||||
__asm (";;" : "+r" (c));
|
||||
return c;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone))
|
||||
int xload16_r20 (const __memx int *pc)
|
||||
{
|
||||
register int c __asm ("r20");
|
||||
c = *pc;
|
||||
__asm (";;" : "+r" (c));
|
||||
return c;
|
||||
}
|
||||
|
||||
void test8 (void)
|
||||
{
|
||||
char c;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
c = xload8_r30 (fvals8 + i);
|
||||
if (c != 1 + i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload8_r22 (fvals8 + i);
|
||||
if (c != 1 + i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload8_r30 (rvals8 + i);
|
||||
if (c != 2 * i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload8_r22 (rvals8 + i);
|
||||
if (c != 2 * i)
|
||||
__builtin_exit (__LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void test16 (void)
|
||||
{
|
||||
int c;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
c = xload16_r30 (fvals16 + i);
|
||||
if (c != 1 + i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload16_r22 (fvals16 + i);
|
||||
if (c != 1 + i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload16_r20 (fvals16 + i);
|
||||
if (c != 1 + i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload16_r30 (rvals16 + i);
|
||||
if (c != 2 * i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload16_r22 (rvals16 + i);
|
||||
if (c != 2 * i)
|
||||
__builtin_exit (__LINE__);
|
||||
|
||||
c = xload16_r20 (rvals16 + i);
|
||||
if (c != 2 * i)
|
||||
__builtin_exit (__LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
test8();
|
||||
test16();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user