Unrepresentable subregs and hard_regno_nregs

Joseph S. Myers joseph@codesourcery.com
Mon Jan 1 21:44:00 GMT 2007


On Wed, 27 Dec 2006, H. J. Lu wrote:

> On Wed, Dec 27, 2006 at 09:47:56AM -0500, Kaveh R. GHAZI wrote:
> > I'm getting a bootstrap failure on sparc-sun-solaris2.10 building libjava
> > with current mainline:
> > 
> 
> I got a similar failure on Linux/i686:
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30311

This patch fixes the x86 bug and I hope it fixes the problem on SPARC
as well (they appear to be different issues); if not, I'll investigate
that further.  Bootstrapped with no regressions on i686-pc-linux-gnu.
OK to commit?

The subreg_get_info change deals with a case (the modes are DFmode and 
XFmode in the x86 case) where the old subreg_offset_representable_p would 
have returned immediately after deciding that the subreg is representable 
(so wouldn't have encountered the assert) and the old subreg_regno_offset 
(which didn't have that assert) would have returned 0 (so avoiding the 
assert is indeed safe).

gcc:
2007-01-01  Joseph Myers  <joseph@codesourcery.com>

	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.

gcc/testsuite:
2007-01-01  Joseph Myers  <joseph@codesourcery.com>

	PR middle-end/30311
	* gcc.c-torture/compile/pr30311.c: New test.

Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	(revision 120310)
+++ gcc/caller-save.c	(working copy)
@@ -537,14 +537,15 @@
   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
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	(revision 120309)
+++ gcc/rtlanal.c	(working copy)
@@ -3057,6 +3057,13 @@
     {
       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
Index: gcc/testsuite/gcc.c-torture/compile/pr30311.c
===================================================================
--- gcc/testsuite/gcc.c-torture/compile/pr30311.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr30311.c	(revision 0)
@@ -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);
+}

-- 
Joseph S. Myers
joseph@codesourcery.com



More information about the Gcc-patches mailing list