This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/21990] New: Wrong code for 4.0 and head: Reload clobbers the frame pointer by using it as spill register without recognizing the clobbering
- From: "bjoern dot m dot haase at web dot de" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 9 Jun 2005 22:28:11 -0000
- Subject: [Bug middle-end/21990] New: Wrong code for 4.0 and head: Reload clobbers the frame pointer by using it as spill register without recognizing the clobbering
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
Hi,
I have observed a wrong code bug that I judge to be so serious that IMHO one
should discourage use of the avr port for 4.x.x until it is resolved.
Unfortunately the bug showed up in a deeply embedded code segment of *really*
confidential code owned by my employer. I unfortunately cannot pass the test
case I am having to the public. I am working hard for reproducing the bug in a
non-confidential stripped file. Meanwhile, I have the following diagnosis: ( I,
know that this will be difficult, but maybe someone could never the less give
me an indication already on this base.)
1.) Background info for those not too familiar with the AVR port:
AVR uses the hard reg 28 (also called Y-Register) as frame pointer,
when necessary. If a pseudo happens to end up on a stack slot and needs to be
loaded into a register of class POINTER_REG (one of the hard regs 26 (reg X),
28 (reg Y) or 30(reg Z)), reload sometimes generates code where the frame
pointer 28 (reg Y) itself is used as spill register. GCC, however, still uses
the Y register as frame pointer and does not recognize that it no longer points
to the stack.
2.) Description of the bug:
Excerpt from the debugging dump originating from the reload pass
for my testcase (test.c.23.greg):
Reload 0: reload_in (HI) = (reg/v/f:HI 65 [ pointer_to_next_C ])
reload_out (HI) = (reg/v/f:HI 65 [ pointer_to_next_C ])
POINTER_REGS, RELOAD_OTHER (opnum = 1)
reload_in_reg: (reg/v/f:HI 65 [ pointer_to_next_C ])
reload_out_reg: (reg/v/f:HI 65 [ pointer_to_next_C ])
reload_reg_rtx: (reg:HI 28 r28)
The corresponding asm output reads (Problem case plus part of the prologue for
illustration. descriptive comments added by me):
;; Section of the prologue allocating space on the stack for a HImode
;; variable.
in r28,__SP_L__
in r29,__SP_H__
sbiw r28,2
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
;; Stack pointer and frame pointer r28:r29 are now increased by 2 for
;; making place for a pointer variable. Y+1 and Y+2 point to the
;; lsb and the msb of this pointer variable.
... some complicated code ...
;; Now the variable on the stack slot is needed in a spill register
;; of class "pointer registers" (i.e. r26-r31).
;; GCC chooses to use the Frame pointer r28 as spill register.
;; r28 is overwritten by the value of the variable on the stack
;; (GCC uses special pattern for loading Y from an address Y is
;; pointing to by use of the tmp reg.
ldd __tmp_reg__,Y+1
ldd r29,Y+2
mov r28,__tmp_reg__
; Now the frame pointer no longer points to the stack!
; Use Y for accessing the memory the pointer variable on the stack
; points to.
ld r18,Y+
ld r19,Y+
ld r20,Y+
ld r21,Y+
;; GCC now assumes that it could write Y back to the stack
;; by the following two commands. BUG!!! Also all of the subsequent
;; Accesses to the stack by the frame pointer will fail.
std Y+2,r29
std Y+1,r28
The bug exists already in January 05 and in today's head 4.1. It was present in
all of the intermediate snapshots I have analyzed so far. I was able to
reproduce the problem identically on a cygwin-woe200 host, an i386-linux host
and an amd64-linux host.
I am working hard to reduce the test case so that it will be possible for me to
post it here. Meanwhile, I'd appreciate very much any advice on where to look
for the origin.
Yours,
Björn
--
Summary: Wrong code for 4.0 and head: Reload clobbers the frame
pointer by using it as spill register without
recognizing the clobbering
Product: gcc
Version: 4.0.0
Status: UNCONFIRMED
Severity: critical
Priority: P2
Component: middle-end
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: bjoern dot m dot haase at web dot de
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: cygwin-x86 and linux-x86
GCC host triplet: cygwin-x86 and linux-x86
GCC target triplet: avr-*-*
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21990