i386.c (ix86_decompose_address): Allow only subregs of DImode hard registers in index.
authorUros Bizjak <ubizjak@gmail.com>
Wed, 20 Jul 2011 21:43:38 +0000 (23:43 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Wed, 20 Jul 2011 21:43:38 +0000 (23:43 +0200)
* 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.

From-SVN: r176536

gcc/ChangeLog
gcc/config/i386/i386.c

index a33530ab70511f8f67cb7d998ab6df85c39ede85..0451e1bd73956b25018076fa245fc1751521472a 100644 (file)
@@ -1,3 +1,12 @@
+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.
+
 2011-07-20  Robert Millan  <rmh@gnu.org>
 
        * config.gcc (mips*-*-linux*): Remove redundant tm_file entry.
        memory address space to the type's address space.
 
 2011-07-20  Georg-Johann Lay  <avr@gjlay.de>
-       
+
        PR target/36467
        PR target/49687
-       * config/avr/avr.md (mulhi3): Use register_or_s9_operand for
-       operand2 and expand appropriately if there is a CONST_INT in
-       operand2.
+       * config/avr/avr.md (mulhi3): Use register_or_s9_operand for operand2
+       and expand appropriately if there is a CONST_INT in operand2.
        (usmulqihi3): New insn.
        (*sumulqihi3): New insn.
        (*osmulqihi3): New insn.
index 22f756b47fd4b10b7a6b35320534dc67efaf6af7..fbebd4c48cba4b2ea28576cffbd08f2c63c83259 100644 (file)
@@ -11197,6 +11197,16 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
   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_mode mode ATTRIBUTE_UNUSED,
   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_mode mode ATTRIBUTE_UNUSED,
        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_mode mode ATTRIBUTE_UNUSED,
        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)
     {