Patchwork [i386] : Allow subregs of multi-word values in addresses

login
register
mail settings
Submitter Uros Bizjak
Date July 20, 2011, 9:41 p.m.
Message ID <CAFULd4ZVrEdK+3+cDG1wJ7OHyMMiXxJqx9GNeX5pSYNS2A2Yjw@mail.gmail.com>
Download mbox | patch
Permalink /patch/105841/
State New
Headers show

Comments

Uros Bizjak - July 20, 2011, 9:41 p.m.
On Wed, Jul 20, 2011 at 9:46 PM, Uros Bizjak <ubizjak@gmail.com> wrote:

>> Note that SUBREG_PROMOTED_UNSIGNED_P wasn't designed for paradoxical subregs,
>> but for regular subregs (typically of word-sized objects).  You should check
>> that the ones created for x32 (because of POINTERS_EXTEND_UNSIGNED I guess)
>> are legitimate.

I have left out paradoxical subreg stuff ATM and committed following
patch that allows subregs of multi-word values in addresses.

2011-07-20  Uros Bizjak  <ubizjak@gmail.com>

	* config/i386/i386.c (ix86_decompose_address): Allow only subregs
	of DImode hard registers in index.
	(ix86_legitimate_address_p): Allow subregs of base and index to span
	more than a word.  Assert that subregs of base and index satisfy
	register_no_elim_operand predicates.  Reject addresses where
	base and index have different modes.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu
{,-m32} and committed to mainline SVN.

(I will prepare a followup [RFC] patch that also allows paradoxical
(?) subregs for experimenting and testing on x32 target).

Uros.

Patch

Index: i386.c
===================================================================
--- i386.c	(revision 176533)
+++ i386.c	(working copy)
@@ -11197,6 +11197,16 @@  ix86_decompose_address (rtx addr, struct
   else
     disp = addr;			/* displacement */
 
+  if (index)
+    {
+      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))
+	return 0;
+    }
+
   /* Extract the integral value of scale.  */
   if (scale_rtx)
     {
@@ -11630,23 +11640,18 @@  ix86_legitimate_address_p (enum machine_
   disp = parts.disp;
   scale = parts.scale;
 
-  /* Validate base register.
-
-     Don't allow SUBREG's that span more than a word here.  It can lead to spill
-     failures when the base is one word out of a two word structure, which is
-     represented internally as a DImode int.  */
-
+  /* Validate base register.  */
   if (base)
     {
       rtx reg;
 
       if (REG_P (base))
   	reg = base;
-      else if (GET_CODE (base) == SUBREG
-	       && REG_P (SUBREG_REG (base))
-	       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (base)))
-		  <= UNITS_PER_WORD)
-  	reg = SUBREG_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));
+	}
       else
 	/* Base is not a register.  */
 	return false;
@@ -11660,21 +11665,18 @@  ix86_legitimate_address_p (enum machine_
 	return false;
     }
 
-  /* Validate index register.
-
-     Don't allow SUBREG's that span more than a word here -- same as above.  */
-
+  /* Validate index register.  */
   if (index)
     {
       rtx reg;
 
       if (REG_P (index))
   	reg = index;
-      else if (GET_CODE (index) == SUBREG
-	       && REG_P (SUBREG_REG (index))
-	       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (index)))
-		  <= UNITS_PER_WORD)
-  	reg = SUBREG_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));
+	}
       else
 	/* Index is not a register.  */
 	return false;
@@ -11688,6 +11690,11 @@  ix86_legitimate_address_p (enum machine_
 	return false;
     }
 
+  /* Index and base should have the same mode.  */
+  if (base && index
+      && GET_MODE (base) != GET_MODE (index))
+    return false;
+
   /* Validate scale factor.  */
   if (scale != 1)
     {