This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
ARM port bug
- To: gcc at gcc dot gnu dot org
- Subject: ARM port bug
- From: Denis Chertykov <denisc at overta dot ru>
- Date: Fri, 1 Jun 2001 00:16:30 +0400
I have founded a bug in ARM port (testcase at end of mail).
gcc version 3.0 20010525 (prerelease)
As I understand the ARM port have a `(define_expand "epilogue" ...)'
And this `define_expand' don't emit the moves on RTL level for restoring
a call-saved registers.
While `update_life_info' executed after reload the `mark_regs_live_at_end'
mark all registers used by the epilogue as being live at the end of
the function and don't unmark it because RTL version of epilogue
havn't a moves.
What's right ?
1. emit a RTL moves in epilogue;
2. remove `(define_expand "epilogue" ...)' (Why it's needed ?)
Fragment from flow.c:mark_regs_live_at_end:
/* Mark all global registers, and all registers used by the epilogue
as being live at the end of the function since they may be
referenced by our caller. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i] || EPILOGUE_USES (i))
SET_REGNO_REG_SET (set, i);
if (HAVE_epilogue && reload_completed)
{
/* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i] && ! call_used_regs[i] && ! LOCAL_REGNO (i))
SET_REGNO_REG_SET (set, i);
}
Command line: arm-elf-linux-gcc -mcpu=strongarm -O2 -S m.i
^^^important^^^
m.i: In function `__dbl_mp':
m.i:46: Internal compiler error in print_rtl_and_abort, at flow.c:6471
Testcase (it's a part of glibc/sysdeps/ieee754/dbl-64/mpa.c):
typedef struct {
int e;
double d[40];
} mp_no;
typedef union { int i[2]; double d; } number;
static const number
radix = {{0x41700000, 0x00000000} },
zero = {{0x00000000, 0x00000000} },
one = {{0x3ff00000, 0x00000000} },
mone = {{0xbff00000, 0x00000000} };
void __dbl_mp(double x, mp_no *y, int p)
{
int i,n;
double u;
if (x == zero.d)
return;
else if (x > zero.d)
y->d[0] = one.d;
else
{
y->d[0] = mone.d;
x=-x;
}
for ( ; x < one.d; y->e -= one.d)
x *= radix.d;
}