This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: unit-at-a-time build failure on arm-elf
- From: Richard Earnshaw <rearnsha at arm dot com>
- To: gcc at gcc dot gnu dot org, Jan Hubicka <jh at suse dot cz>
- Cc: Richard dot Earnshaw at arm dot com, rth at redhat dot com
- Date: Sat, 22 Feb 2003 16:26:14 +0000
- Subject: Re: unit-at-a-time build failure on arm-elf
- Organization: ARM Ltd.
- Reply-to: Richard dot Earnshaw at arm dot com
rearnsha at arm dot com said:
> The new unit-at-once code is causing a build failure on an arm-elf
> cross when building newlib.
> cc1 -fpreprocessed ldtoa.i -quiet -dumpbase ldtoa.c -auxbase ldtoa -g
> -O2 -fno-builtin -o ldtoa.s GNU C version 3.4 20030221 (experimental)
> (arm-elf)
> compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.1
> 2.96-98). /home/rearnsha/gnusrc/egcs-cross/newlib/libc/stdlib/ldtoa.c:
> In function `asctoeg': /home/rearnsha/gnusrc/egcs-cross/newlib/libc/
> stdlib/ldtoa.c:3561: internal compiler error: in verify_local_live_at_
> start, at flow.c:590 Please submit a full bug report,
> The pre-processed source is attached.
I've just spent a couple of hours digging into this one and I'm not sure
what the solution here is going to be. The problem seems to be creeping
in during basic block reordering.
if_convert is generating a basic block of the form
... // unconditional insns not mentioning r0
(gtu CC 0) r0 = xxx
(if_then_else (gtu CC 0) (label) (pc))
Now r0 is dead if we fall through, but live if we take the branch, so the
bb's liveness information is
global-live-at-start: some_regs_not_r0
global-live-at-end: r0 some_other_regs_not_r0
Now the branch reordering pass is for some reason splitting the final
cond-jump above into a separate block, when we calculate the register
life info for this we then get
bb A
... // unconditional insns not altering r0
(gtu CC 0) r0 = xxx
global-live-at-start: r0 some_regs_not_r0
global-live-at-end: r0 some_other_regs_not_r0
bb B
(label)
(if_then_else (gtu CC 0) (label) (pc))
global-live-at-start: r0 some_other_regs_not_r0
global-live-at-end: r0 some_other_regs_not_r0
This is believable, for this configuration. bb B neither sets nor uses
r0, so if it's possibly live at the end (it is on one successor, but not
on another) then we must mark it live at the start; *but note that we
can't mark it conditionally live*, so we mark r0 as unconditionally live
at the end of bb A and must now propagate that up to the beginning.
The problems really manifest themselves during the second half of
bb_reorder. In that phase we kill the label and merge the two blocks back
together again. However, this time we don't recalculate the register life
information of the merged block, so we fail to notice that r0 should now
be marked as dead on entry. The net result is that we then abort during
scheduling because the life info is incorrect.
So how do we approach this? I'm not entirely sure, but I suspect that
whatever we do, short of maintaining full conditional life information at
block boundaries, is going to be some sort of hack -- I'd be happy to be
proved wrong though :-)
R.