https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87376
Georg-Johann Lay <gjl at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Last reconfirmed| |2018-10-11
Ever confirmed|0 |1
Known to fail| |8.0.1
--- Comment #1 from Georg-Johann Lay <gjl at gcc dot gnu.org> ---
Hi Senthil, confirmed with v8.0.1 and -O2 -mmcu=atmega128 and test case
extern const __memx long long a asm ("a2");
const long long b = 0x1122334455667788;
const __memx long long a2 = 0x123456789abcdef1;
__attribute((noinline,noclone))
long long add (void) { return a + b; }
int main()
{
if (add() != a2 + b)
__builtin_abort();
return 0;
}
TER propagates parameter register DI:18 into QImode subregs of DI, and we get
the following insn in expand:
(insn ... (parallel [
(set (reg:QI 21 r21 [+3 ])
(mem/u/c:QI (reg/f:PSI 51) [1 a+3 S1 A8 AS7]))
(clobber (reg:QI 22 r22))
(clobber (reg:QI 21 r21))
(clobber (reg:HI 30 r30))]))
and a similar insn for R22. R21 and R22 correspond to a+3 and a+4,
respectively. The insn is xloadqi_A and emit by movqi expander.
An (untested) fix is to avoid overlaps of the destination register and a
clobbered register, e.g. by means of loading the destination into a new pseudo:
if (!avr_xload_libgcc_p (<MODE>mode))
...
else
{
if (REG_P (dest)
&& (reg_operlaps_mentioned_p (dest, all_regs_rtx[21])
|| reg_operlaps_mentioned_p (dest, gen_rtx_REG (<MODE>mode, 22))
|| reg_operlaps_mentioned_p (dest, reg_z)))
{
// PR87376: Avoid overlaps of hard reg destination and clobber(s).
rtx reg = gen_reg_rtx (<MODE>mode);
emit_insn (gen_xload<mode>_A (reg, src));
emit_move_insn (dest, reg);
}
else
emit_insn (gen_xload<mode>_A (dest, src));
}