Summary: | Output register variable is reloaded into the wrong register for asm | ||
---|---|---|---|
Product: | gcc | Reporter: | Daniel Jacobowitz <drow> |
Component: | middle-end | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | gcc-bugs |
Priority: | P2 | Keywords: | wrong-code |
Version: | 4.1.0 | ||
Target Milestone: | 9.0 | ||
See Also: |
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87600 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86939 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87899 |
||
Host: | Target: | ||
Build: | Known to work: | 9.1.0 | |
Known to fail: | 2.95.3, 3.3.3, 4.1.0, 4.9.0, 8.1.0 | Last reconfirmed: | 2006-01-26 05:37:12 |
Description
Daniel Jacobowitz
2005-04-25 20:49:25 UTC
Confirmed, also on powerpc-darwin. Weird. The reload was created because the earlyclobber operand conflicts with a_oldval2, which is placed in r3 by local-alloc. I think I see why... And here is an x86 testcase: int bar(int *mem) { return ({ register int a_oldval asm ("eax"); register int a_tmp asm ("ebx"); int a_oldval2 = 3; __asm__ __volatile__ ("# Should be eax - %0\n\t" "# Should be ebx - %1\n\t" "# unknown - %2" : "=&r" (a_oldval), "=&r" (a_tmp) : "r" (a_oldval2)); a_tmp; }); } Which shows this fails at -O2 and above too. The problem is in reg_is_set or its caller. Because the output is an earlyclobber operand, it needs to be marked as born before the insn, to conflict with its inputs. I do not see an obvious way to get from note_stores to the recog alternative. I reproduced this bug in 3.4.3 (csl-arm-branch) also. So this is fully fixed in GCC 9+. LRA fixes the problems that reload had. (LRA had a similar bug but had been fixes see the linked bug reports). |