diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4748fd64a78..fad6cfb746c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2007-01-02 Joseph Myers + + PR middle-end/30311 + * caller-save.c (add_stored_regs): Only handle SUBREGs if inner + REG is a hard register. Do not modify REG before calling + subreg_nregs. + * rtlanal.c (subreg_get_info): Don't assert size of XMODE is a + multiple of the size of YMODE for certain lowpart cases. + 2007-01-01 Andrew Pinski PR middle-end/30253 diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 86d74ee1726..54f88a14d40 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -1,6 +1,6 @@ /* Save and restore call-clobbered registers which are live across a call. - Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -537,14 +537,15 @@ add_stored_regs (rtx reg, rtx setter, void *data) if (GET_CODE (setter) == CLOBBER) return; - if (GET_CODE (reg) == SUBREG && REG_P (SUBREG_REG (reg))) + if (GET_CODE (reg) == SUBREG + && REG_P (SUBREG_REG (reg)) + && REGNO (SUBREG_REG (reg)) < FIRST_PSEUDO_REGISTER) { offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)), GET_MODE (SUBREG_REG (reg)), SUBREG_BYTE (reg), GET_MODE (reg)); - reg = SUBREG_REG (reg); - regno = REGNO (reg) + offset; + regno = REGNO (SUBREG_REG (reg)) + offset; endregno = regno + subreg_nregs (reg); } else diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index bc2da3c7e2a..2d156638b6d 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1,6 +1,6 @@ /* Analyze RTL for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -3057,6 +3057,13 @@ subreg_get_info (unsigned int xregno, enum machine_mode xmode, { info->representable_p = true; rknown = true; + + if (offset == 0 || nregs_xmode == nregs_ymode) + { + info->offset = 0; + info->nregs = nregs_ymode; + return; + } } /* This should always pass, otherwise we don't know how to verify diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ea08e48e492..b636d4802a2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-01-02 Joseph Myers + + PR middle-end/30311 + * gcc.c-torture/compile/pr30311.c: New test. + 2007-01-01 Andrew Pinski PR middle-end/30253 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr30311.c b/gcc/testsuite/gcc.c-torture/compile/pr30311.c new file mode 100644 index 00000000000..85ce75099cf --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr30311.c @@ -0,0 +1,16 @@ +/* ICE in subreg_get_info: bug 30311. */ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +inline double bar(double x) +{ + long double d; + __asm__ ("" : "=t" (d) : "0" (x)); + return d; +} + +double foo(double x) +{ + if (x) + return bar(x); + else + return bar(x); +}