Bug 31786

Summary: [avr] error: unable to find a register to spill in class 'BASE_POINTER_REGS'
Product: gcc Reporter: Ralf Corsepius <ralf_corsepius>
Component: targetAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: aesok, eric.weddington, gcc-bugs, hutchinsonandy, j.w.r.degoede, joel.sherrill, joel
Priority: P5 Keywords: ice-on-valid-code
Version: 4.2.0   
Target Milestone: 4.4.0   
Host: Target: avr-*-*
Build: Known to work: 4.0.3
Known to fail: 4.1.2 4.2.0 Last reconfirmed: 2007-05-30 20:40:03
Attachments: *.i of the breakdown above
Patch to current HEAD

Description Ralf Corsepius 2007-05-02 14:13:54 UTC
bootstrapping avr-rtems* gcc-4.2.0-200704030 fails with:

/builddir/build/BUILD/rtems-4.8-avr-rtems4.8-gcc-4.2.0/build/./gcc/xgcc -B/builddir/build/BUILD/rtems-4.8-avr-rtems4.8-gcc-4.2.0/build/./gcc/ -nostdinc -B/builddir/build/BUILD/rtems-4.8-avr-rtems4.8-gcc-4.2.0/build/avr-rtems4.8/newlib/ -isystem /builddir/build/BUILD/rtems-4.8-avr-rtems4.8-gcc-4.2.0/build/avr-rtems4.8/newlib/targ-include -isystem /builddir/build/BUILD/rtems-4.8-avr-rtems4.8-gcc-4.2.0/gcc-4.2.0-20070430/newlib/libc/include -B/opt/rtems-4.8/avr-rtems4.8/bin/ -B/opt/rtems-4.8/avr-rtems4.8/lib/ -isystem /opt/rtems-4.8/avr-rtems4.8/include -isystem /opt/rtems-4.8/avr-rtems4.8/sys-include -DPACKAGE_NAME=\"newlib\" -DPACKAGE_TARNAME=\"newlib\" -DPACKAGE_VERSION=\"1.15.0\" -DPACKAGE_STRING=\"newlib\ 1.15.0\" -DPACKAGE_BUGREPORT=\"\"  -I. -I../../../../../../gcc-4.2.0-20070430/newlib/libc/misc -Os -DPREFER_SIZE_OVER_SPEED -mcall-prologues -DMALLOC_PROVIDED -DEXIT_PROVIDED -DMISSING_SYSCALL_NAMES -DSIGNAL_PROVIDED -DREENTRANT_SYSCALLS_PROVIDED -DHAVE_OPENDIR -DNO_EXEC -DHAVE_FCNTL -fno-builtin      -O2 -g -O2   -mmcu=avr25 -c -o lib_a-init.o `test -f 'init.c' || echo '../../../../../../gcc-4.2.0-20070430/newlib/libc/misc/'`init.c
../../../../../../gcc-4.2.0-20070430/newlib/libc/misc/init.c: In function '__libc_fini_array':
../../../../../../gcc-4.2.0-20070430/newlib/libc/misc/init.c:59: error: unable to find a register to spill in class 'BASE_POINTER_REGS'
../../../../../../gcc-4.2.0-20070430/newlib/libc/misc/init.c:59: error: this is the insn:
(insn 84 55 56 4 ../../../../../../gcc-4.2.0-20070430/newlib/libc/misc/init.c:56 (set (mem/c:HI (plus:HI (reg/f:HI 28 r28)
                (const_int 1 [0x1])) [5 S2 A8])
        (reg:HI 24 r24)) 12 {*movhi} (nil)
    (nil))
../../../../../../gcc-4.2.0-20070430/newlib/libc/misc/init.c:59: confused by earlier errors, bailing out
Comment 1 Eric Weddington 2007-05-02 20:34:35 UTC
This must be specific to RTEMS/newlib, as 4.2.0-20070430 (RC2) builds without error with:

CFLAGS=-D__USE_MINGW_ACCESS  \
../gcc-$version/configure \
    --prefix=$installdir \
    --target=avr \
    --enable-languages=c,c++ \
    --with-dwarf2 \
    --enable-win32-registry=WinAVR-$release \
    --disable-nls \
    --with-gmp=/usr/local \
    --with-mpfr=/usr/local \
    --enable-doc \
    --disable-libssp \
    2>&1 | tee $package-configure.log 

for host=mingw.
Comment 2 Ralf Corsepius 2007-05-03 10:27:24 UTC
I can also reproduce the bug with 4.2.0-20070501.

It also is related to optimization levels. Newlib is being compiled with -O2, which triggers this breakdown. Using -O1 or -Os to build init.c lets the breakdown vanish.

Eric, due to bugzilla's current brokenness, I am sending you the *.i on PM.
Comment 3 Ralf Corsepius 2007-05-03 10:43:42 UTC
Created attachment 13501 [details]
*.i of the breakdown above
Comment 4 Eric Weddington 2007-05-03 13:05:41 UTC
Subject: RE:  error: unable to find a register to spill in
 class 'BASE_POINTER_REGS'

 

> ------- Comment #2 from ralf_corsepius at rtems dot org  
> 2007-05-03 10:27 -------
> I can also reproduce the bug with 4.2.0-20070501.
> 
> It also is related to optimization levels. Newlib is being 
> compiled with -O2,
> which triggers this breakdown. Using -O1 or -Os to build 
> init.c lets the
> breakdown vanish.
> 
> Eric, due to bugzilla's current brokenness, I am sending you 
> the *.i on PM.

Hi Ralf,
All public distros use avr-libc instead of newlib to build an AVR toolchain:
<http://savannah.nongnu.org/projects/avr-libc>
AFAIK, it is only RTEMS that attempts to use newlib. And because of this the
only testing that is done is when you do it, so I'm not surprised that
newlib is broken for the avr.

Eric

Comment 5 Ralf Corsepius 2007-05-03 13:12:02 UTC
Subject: RE:  error: unable to find a register to spill
	in class 'BASE_POINTER_REGS'

On Thu, 2007-05-03 at 06:05 -0600, Eric Weddington wrote:
>  
> > ------- Comment #2 from ralf_corsepius at rtems dot org  
> > 2007-05-03 10:27 -------
> > I can also reproduce the bug with 4.2.0-20070501.
> > 
> > It also is related to optimization levels. Newlib is being 
> > compiled with -O2,
> > which triggers this breakdown. Using -O1 or -Os to build 
> > init.c lets the
> > breakdown vanish.
> > 
> > Eric, due to bugzilla's current brokenness, I am sending you 
> > the *.i on PM.
> 
> Hi Ralf,
> All public distros use avr-libc instead of newlib to build an AVR toolchain:
> <http://savannah.nongnu.org/projects/avr-libc>
> AFAIK, it is only RTEMS that attempts to use newlib. And because of this the
> only testing that is done is when you do it, so I'm not surprised that
> newlib is broken for the avr.
Though what you say is true, the file avr bombs out on is mere "c", i.e.
a bug in GCC.

Ralf


Comment 6 Ralf Corsepius 2007-05-03 14:07:34 UTC
This is the minimised *.c having been extracted from newlib's file exposing the bug:
-- snip --
extern void (*array_start []) (void);
extern void (*array_end []) (void);

void
init_array (void)
{
  int count;
  int i;
  count = array_end - array_start;
  for (i = 0; i < count; i++)
    array_start[i] ();
}
-- snip --

Pretty trivial code, isn't it?
Comment 7 Ralf Corsepius 2007-05-03 15:20:39 UTC
FYI: Vanilla gcc-4.1.2 without newlib also exposes this issue with the code fragment from comment #6:

./avr-gcc -o tmp.o -c init.c -O2
init.c: In function 'init_array':
init.c:12: error: unable to find a register to spill in class 'BASE_POINTER_REGS'
init.c:12: error: this is the insn:
(insn 61 30 31 2 (set (mem/c:HI (plus:HI (reg/f:HI 28 r28)
                (const_int 1 [0x1])) [4 S2 A8])
        (reg:HI 24 r24)) 12 {*movhi} (nil)
    (nil))
init.c:12: confused by earlier errors, bailing out

Comment 8 Eric Weddington 2007-05-03 16:40:04 UTC
Confirmed. Code snippet fails for 4.1.2 when compiling for -O2 and -O3. Note that compiling with -O[0,1,s] is successful.

Changing target to all avr.
Comment 9 Eric Weddington 2007-05-04 16:06:26 UTC
From Bjoern Haase:

Hi all,

I think that we could resolve this ICE by adding an unnamed pattern like

(define_insn "*strangeMovhi"
  [(set (mem:HI (plus:HI (reg:HI 28)
                         (const_int 1)))
        (match_operand:HI 0 "general_operand" "r"))]
  ""
  "st %A0,y+1 \n\t st %B0,y+2"
  [(set_attr "length" "2")])


to the machine description "avr.md" . That might cure the symptoms and does not resolve the underlying problem with reload, but this might be a fix for the immediate issue.

Note that above remark is untested pseudo-code.

Yours,

Bjoern.

P.S.: Eric, you might add this remark to the bugzilla entry.

Comment 10 Eric Weddington 2007-05-30 20:40:03 UTC
Fails for 4.3-20070525
Comment 11 Eric Weddington 2007-06-10 16:43:44 UTC
*** Bug 24894 has been marked as a duplicate of this bug. ***
Comment 12 Eric Weddington 2007-06-10 16:50:32 UTC
According to a comment in duplicate bug #24894, bug #19636 may be related.

Ralf, can you try the test case using a 4.3 snapshot?
Comment 13 Andy Hutchinson 2008-01-02 13:36:29 UTC
Problem occurs because 1 base pointer is used for function pointer and the other is used for frame pointer. (There are only 2). Backend LEGITIMIZE_RELOAD_ADDRESS tells reload to use a base pointer for reload pass of mem(SP+1). This fails.
Unfortunately reload does not figure out that it can use frame pointer and gives ICE. (Ironically the frame pointer would be eliminated in this testcase latter)

The problem potentially occurs whenever R30,R31 is tied up. (EEPROM macros are other example)

Reload calls LEGITIMIZE_RELOAD_ADDRESS when strict address check fails legitimate_address_p on SP+1 - since AVR has no way of indexing from stack pointer.

Potential fix is to stop LEGITIMIZE_RELOAD_ADDRESS from telling reload (push_reload)  to use BASE_POINTER class. POINTER CLASS is one wider and target macros have pattern to use register 'REG_X' as index (with addition). Alternatively don't suggest any substitution (ie not GOTO WIN) and reload finds answer.

The latter solution has been tested and caused ICE in GCC library building as 'REG_X' is not allowable with strict address checking (legitimate_address_p ) - so we get no pattern match ICE for MOVQI (REG_X+1),Rxx. However, backend does contain such patterns. Changing legitimate_address_p to accept REG_X solves problem.
In the testcase, the instruction that caused the ICE is eliminated - so the newly allowable pattern is never used.

The build ICE caused by first change does indicate that on occasion GCC will really use REG_X as index. Potentially producing sub-optimal code compared with REG_Y or REG_Z. However, the incidence is clearly low and may well be offset by other side effect improvements.




Comment 14 Andy Hutchinson 2008-01-02 23:29:09 UTC
Created attachment 14862 [details]
Patch to current HEAD

This will patch avr.h and avr.c to allow REG_X as valid BASE_POINTER.
Comment 15 Richard Biener 2008-01-13 15:44:21 UTC
Adjusting target milestone.
Comment 16 Joseph S. Myers 2008-07-04 22:02:48 UTC
Closing 4.1 branch.
Comment 17 aesok 2008-09-14 12:51:48 UTC
Subject: Bug 31786

Author: aesok
Date: Sun Sep 14 12:50:10 2008
New Revision: 140360

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=140360
Log:
	PR target/19636
	PR target/24894
	PR target/31644
	PR target/31786
	* config/avr/avr.c (legitimate_address_p): Fix problem where subreg
	is not recognized as a valid register usage. Allow REG_X to be used
	as a base pointer.
	* config/avr/avr.h (LEGITIMIZE_RELOAD_ADDRESS): Remove code that
	forces a reload when using a base register.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/avr/avr.c
    trunk/gcc/config/avr/avr.h

Comment 18 Joseph S. Myers 2009-03-31 20:09:20 UTC
Closing 4.2 branch.  Is the patch committed on 14 September 2008 a complete
fix?  If so, the 4.4 and 4.5 regression markers should be removed from the
summary.
Comment 19 Richard Biener 2009-08-04 12:28:04 UTC
GCC 4.3.4 is being released, adjusting target milestone.
Comment 20 Eric Weddington 2010-01-29 17:45:50 UTC
I have in my list that this bug as fixed in 4.4.0. Closing.