On Wed, Jul 20, 2011 at 9:46 PM, Uros Bizjak <ubiz...@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  <ubiz...@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.
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)
     {

Reply via email to