Patchwork [i386] : Fix PR49927, ice in spill_failure, at reload1.c:2120

login
register
mail settings
Submitter Uros Bizjak
Date Aug. 1, 2011, 5:10 p.m.
Message ID <CAFULd4brzNaR3q6DXBbRx0u3RQXfxZHPHz9Hk4vZS4S+847ztQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/107786/
State New
Headers show

Comments

Uros Bizjak - Aug. 1, 2011, 5:10 p.m.
Hello!

On a register starved i686, the relaxation that we allow DImode values
in addresses can lead to register shortages and spill failures.

Attached patch puts back the requirement that we allow subregs up to
and including WORD_MODE width, nicely packed in a new function.

2011-08-01  Uros Bizjak  <ubizjak@gmail.com>

	PR target/49927
	* config/i386/i386.c (ix86_address_subreg_operand): New.
	(ix86_decompose_address): Use ix86_address_subreg_operand.
	(ix86_legitimate_address_p): Do not assert that subregs satisfy
	register_no_elim_operand in DImode.

testsuite/ChangeLog:

2011-08-01  Uros Bizjak  <ubizjak@gmail.com>

	PR target/49927
	* gcc.target/i386/pr49927.c: New test.

Tested on x86_64-pc-linux-gnu {,-m32}, committed to mainline SVN.

Uros.

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 177036)
+++ config/i386/i386.c	(working copy)
@@ -11096,6 +11096,30 @@  ix86_live_on_entry (bitmap regs)
     }
 }
 
+/* Determine if op is suitable SUBREG RTX for address.  */
+
+static bool
+ix86_address_subreg_operand (rtx op)
+{
+  enum machine_mode mode;
+
+  if (!REG_P (op))
+    return false;
+
+  mode = GET_MODE (op);
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return false;
+
+  /* Don't allow SUBREGs that span more than a word.  It can lead to spill
+     failures when the register is one word out of a two word structure.  */
+  if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+    return false;
+
+  /* Allow only SUBREGs of non-eliminable hard registers.  */
+  return register_no_elim_operand (op, mode);
+}
+
 /* Extract the parts of an RTL expression that is a valid memory address
    for an instruction.  Return 0 if the structure of the address is
    grossly off.  Return -1 if the address contains ASHIFT, so it is not
@@ -11116,8 +11140,7 @@  ix86_decompose_address (rtx addr, struct
     base = addr;
   else if (GET_CODE (addr) == SUBREG)
     {
-      /* Allow only subregs of DImode hard regs.  */
-      if (register_no_elim_operand (SUBREG_REG (addr), DImode))
+      if (ix86_address_subreg_operand (SUBREG_REG (addr)))
 	base = addr;
       else
 	return 0;
@@ -11175,8 +11198,7 @@  ix86_decompose_address (rtx addr, struct
 	      break;
 
 	    case SUBREG:
-	      /* Allow only subregs of DImode hard regs in PLUS chains.  */
-	      if (!register_no_elim_operand (SUBREG_REG (op), DImode))
+	      if (!ix86_address_subreg_operand (SUBREG_REG (op)))
 		return 0;
 	      /* FALLTHRU */
 
@@ -11228,9 +11250,8 @@  ix86_decompose_address (rtx addr, struct
     {
       if (REG_P (index))
 	;
-      /* Allow only subregs of DImode hard regs.  */
       else if (GET_CODE (index) == SUBREG
-	       && register_no_elim_operand (SUBREG_REG (index), DImode))
+	       && ix86_address_subreg_operand (SUBREG_REG (index)))
 	;
       else
 	return 0;
@@ -11677,10 +11698,7 @@  ix86_legitimate_address_p (enum machine_
       if (REG_P (base))
   	reg = base;
       else if (GET_CODE (base) == SUBREG && REG_P (SUBREG_REG (base)))
-	{
-	  reg = SUBREG_REG (base);
-	  gcc_assert (register_no_elim_operand (reg, DImode));
-	}
+	reg = SUBREG_REG (base);
       else
 	/* Base is not a register.  */
 	return false;
@@ -11702,10 +11720,7 @@  ix86_legitimate_address_p (enum machine_
       if (REG_P (index))
   	reg = index;
       else if (GET_CODE (index) == SUBREG && REG_P (SUBREG_REG (index)))
-	{
-	  reg = SUBREG_REG (index);
-	  gcc_assert (register_no_elim_operand (reg, DImode));
-	}
+	reg = SUBREG_REG (index);
       else
 	/* Index is not a register.  */
 	return false;
Index: testsuite/gcc.target/i386/pr49927.c
===================================================================
--- testsuite/gcc.target/i386/pr49927.c	(revision 0)
+++ testsuite/gcc.target/i386/pr49927.c	(revision 0)
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+char a[1][1];
+long long b;
+
+void
+foo (void)
+{
+  --a[b][b];
+}