Hello!

Attached patch further improves ix86_decompose_address to allow
(zero_extend:DI (subreg:SI (...))) addresses and prevent zero extended
CONST_INT operands (as was previously the case with LEA operands
only). This improvement allows us to put quite some asserts to
strategic places, in order to detect invalid addresses before they
generate invalid code.

2012-07-23  Uros Bizjak  <ubiz...@gmail.com>

        PR target/53961
        * config/i386/i386.md (*lea): Add asserts to detect invalid addresses.
        * config/i386/i386.c (ix86_print_operand_address): Ditto.
        (ix86_decompose_address): Allow (zero_extend:DI (subreg:SI (...)))
        addresses.  Prevent zero extensions of CONST_INT operands.

Tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN. I
will again watch x32 autotesters for possible breakage.

Uros.
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 189786)
+++ config/i386/i386.md (working copy)
@@ -5458,10 +5458,19 @@
   rtx addr = operands[1];
 
   if (GET_CODE (addr) == SUBREG)
-    return "lea{l}\t{%E1, %0|%0, %E1}";
+    {
+      gcc_assert (TARGET_64BIT);
+      gcc_assert (<MODE>mode == SImode);
+      gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+      return "lea{l}\t{%E1, %0|%0, %E1}";
+    }
   else if (GET_CODE (addr) == ZERO_EXTEND
           || GET_CODE (addr) == AND)
-    return "lea{l}\t{%E1, %k0|%k0, %E1}";
+    {
+      gcc_assert (TARGET_64BIT);
+      gcc_assert (<MODE>mode == DImode);
+      return "lea{l}\t{%E1, %k0|%k0, %E1}";
+    }
   else 
     return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
 }
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c  (revision 189786)
+++ config/i386/i386.c  (working copy)
@@ -11576,22 +11576,17 @@ ix86_decompose_address (rtx addr, struct ix86_addr
   int retval = 1;
   enum ix86_address_seg seg = SEG_DEFAULT;
 
-  /* Allow SImode subregs of DImode addresses,
-     they will be emitted with addr32 prefix.  */
-  if (TARGET_64BIT && GET_MODE (addr) == SImode)
-    {
-      if (GET_CODE (addr) == SUBREG
-         && GET_MODE (XEXP (addr, 0)) == DImode)
-       addr = SUBREG_REG (addr);
-    }
-
   /* Allow zero-extended SImode addresses,
      they will be emitted with addr32 prefix.  */
-  else if (TARGET_64BIT && GET_MODE (addr) == DImode)
+  if (TARGET_64BIT && GET_MODE (addr) == DImode)
     {
       if (GET_CODE (addr) == ZERO_EXTEND
          && GET_MODE (XEXP (addr, 0)) == SImode)
-       addr = XEXP (addr, 0);
+       {
+         addr = XEXP (addr, 0);
+         if (CONST_INT_P (addr))
+           return 0;
+       }             
       else if (GET_CODE (addr) == AND
               && const_32bit_mask (XEXP (addr, 1), DImode))
        {
@@ -11600,7 +11595,11 @@ ix86_decompose_address (rtx addr, struct ix86_addr
          /* Adjust SUBREGs.  */
          if (GET_CODE (addr) == SUBREG
              && GET_MODE (SUBREG_REG (addr)) == SImode)
-           addr = SUBREG_REG (addr);
+           {
+             addr = SUBREG_REG (addr);
+             if (CONST_INT_P (addr))
+               return 0;
+           }
          else if (GET_MODE (addr) == DImode)
            addr = gen_rtx_SUBREG (SImode, addr, 0);
          else if (GET_MODE (addr) != VOIDmode)
@@ -11608,6 +11607,19 @@ ix86_decompose_address (rtx addr, struct ix86_addr
        }
     }
 
+  /* Allow SImode subregs of DImode addresses,
+     they will be emitted with addr32 prefix.  */
+  if (TARGET_64BIT && GET_MODE (addr) == SImode)
+    {
+      if (GET_CODE (addr) == SUBREG
+         && GET_MODE (SUBREG_REG (addr)) == DImode)
+       {
+         addr = SUBREG_REG (addr);
+         if (CONST_INT_P (addr))
+           return 0;
+       }
+    }
+
   if (REG_P (addr))
     base = addr;
   else if (GET_CODE (addr) == SUBREG)
@@ -14765,14 +14777,22 @@ ix86_print_operand_address (FILE *file, rtx addr)
   else
     {
       /* Print SImode register names to force addr32 prefix.  */
-      if (TARGET_64BIT
-         && (GET_CODE (addr) == SUBREG
-             || GET_CODE (addr) == ZERO_EXTEND
-             || GET_CODE (addr) == AND))
+      if (GET_CODE (addr) == SUBREG)
        {
+         gcc_assert (TARGET_64BIT);
+         gcc_assert (GET_MODE (addr) == SImode);
+         gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
          gcc_assert (!code);
          code = 'l';
        }
+      else if (GET_CODE (addr) == ZERO_EXTEND
+              || GET_CODE (addr) == AND)
+       {
+         gcc_assert (TARGET_64BIT);
+         gcc_assert (GET_MODE (addr) == DImode);
+         gcc_assert (!code);
+         code = 'l';
+       }
 
       if (ASSEMBLER_DIALECT == ASM_ATT)
        {

Reply via email to