Hello!

Attached RFC patch buids on recent x86 improvements in
ix86_legitimate_address_p/ix86_decompose_address functions. With this
patch, we allow SUBREGs with register_no_elim_operand registers in
base, index and PLUS chains. As the consequence, we can relax the
condition that rejects SUBREGs, wider than word mode due to possible
spill failures with double-word SUBREGs. register_no_elim_operand
together with REG_OK_FOR_BASE/REG_OK_FOR_INDEX predicates guarantee,
that there will be no spills since multi-word registers that satisfy
these predicates can easily be decomposed to satisfy SUBREGs.

Another improvement is introduction of SUBREG_PROMOTED_UNSIGNED_P
predicate in the same area to handle paradoxical SUBREGs. When SUBREG
satisfies this predicate, the compiler guarantees, that excess bits
are zero (see the documentation). This is exaclty what we want in
registers that form the address. In theory, we can allow registers of
any integer mode here, but in practice only DImode subreg of SImode
register is important.

IMO, the first optimization is important on i686, while the second is
important on x32 (lots of paradoxical subregs in addresses due to
Pmode != ptr_mode), but they are also nice to have on x86_64.

Any thoughts?

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

        * config/i386/i386.c (ix86_decompose_address): Also allow promoted
        paradoxical subregs in base and PLUS chains.  Allow only paradoxical
        subregs and subregs of DImode hard registers in subregs of 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
        SUBREG_PROMOTED_UNSIGNED_P or register_no_elim_operand predicates.

Patch was bootstrapped and is currently regression testing on
x86_64-pc-linux-gnu {,-m32}.

Uros.
Index: i386.c
===================================================================
--- i386.c      (revision 176512)
+++ i386.c      (working copy)
@@ -11089,8 +11089,10 @@ 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))
+      /* Allow only promoted paradoxical subregs
+        or subregs of DImode hard regs.  */
+      if (SUBREG_PROMOTED_UNSIGNED_P (addr)
+         || register_no_elim_operand (SUBREG_REG (addr), DImode))
        base = addr;
       else
        return 0;
@@ -11148,8 +11150,10 @@ 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))
+             /* Allow only promoted paradoxical subregs
+                or subregs of DImode hard regs in PLUS chains.  */
+             if (!(SUBREG_PROMOTED_UNSIGNED_P (op)
+                   || register_no_elim_operand (SUBREG_REG (op), DImode)))
                return 0;
              /* FALLTHRU */
 
@@ -11197,6 +11201,18 @@ ix86_decompose_address (rtx addr, struct
   else
     disp = addr;                       /* displacement */
 
+  if (index)
+    {
+      if (REG_P (index))
+       ;
+      /* Allow only promoted paradoxical subregs
+        or subregs of DImode hard regs.  */
+      else if (GET_CODE (index) == SUBREG
+              && !(SUBREG_PROMOTED_UNSIGNED_P (index)
+                   || register_no_elim_operand (SUBREG_REG (index), DImode)))
+       return 0;
+    }
+
   /* Extract the integral value of scale.  */
   if (scale_rtx)
     {
@@ -11630,11 +11646,7 @@ 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)
     {
@@ -11642,11 +11654,12 @@ ix86_legitimate_address_p (enum machine_
 
       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 (SUBREG_PROMOTED_UNSIGNED_P (base)
+                     || register_no_elim_operand (reg, DImode));
+       }
       else
        /* Base is not a register.  */
        return false;
@@ -11660,9 +11673,7 @@ 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)
     {
@@ -11670,11 +11681,12 @@ ix86_legitimate_address_p (enum machine_
 
       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 (SUBREG_PROMOTED_UNSIGNED_P (index)
+                     || register_no_elim_operand (reg, DImode));
+       }
       else
        /* Index is not a register.  */
        return false;

Reply via email to