On Tue, Jul 19, 2011 at 6:30 PM, Jakub Jelinek <ja...@redhat.com> wrote:

>> Sometimes, the compiler is really creative in inventing instructions:
>>
>> (insn 47 46 49 7 (set (reg:SI 68 [ D.1686 ])
>>         (subreg:SI (plus:SF (reg:SF 159 [ D.1685 ])
>>                 (reg:SF 159 [ D.1685 ])) 0)) omp_atomic1.f90:17 247 {*lea_2}
>>      (expr_list:REG_DEAD (reg:SF 159 [ D.1685 ])
>>         (nil)))
>>
>> Really funny.
>
> That's the job of combiner to try all kinds of stuff and it is the
> responsibility of the backend to reject those.  I think it would be better
> to get back to testing Pmode in the legitimate address hook, perhaps
> allowing ptr_mode too in addition to Pmode (which for -m32/-m64 won't mean
> any change, just for -mx32).

I agree that we still need to check naked registers. However, for
64bit targets it is OK to pass both, SImode and DImode registers. We
are sure that SImode values in DImode regs have top 32bits equal to 0
in address calculations. This is not true for QImode regs (assignment
to lowpart only). We also have to prevent non-integer registers.

Attached is my final version of the patch.

Uros.
Index: predicates.md
===================================================================
--- predicates.md       (revision 176462)
+++ predicates.md       (working copy)
@@ -796,7 +796,7 @@
 
 ;; Return true if op if a valid address, and does not contain
 ;; a segment override.
-(define_special_predicate "no_seg_address_operand"
+(define_predicate "no_seg_address_operand"
   (match_operand 0 "address_operand")
 {
   struct ix86_address parts;
Index: i386.c
===================================================================
--- i386.c      (revision 176462)
+++ i386.c      (working copy)
@@ -11085,8 +11085,16 @@ ix86_decompose_address (rtx addr, struct
   int retval = 1;
   enum ix86_address_seg seg = SEG_DEFAULT;
 
-  if (REG_P (addr) || GET_CODE (addr) == SUBREG)
+  if (REG_P (addr))
     base = addr;
+  else if (GET_CODE (addr) == SUBREG)
+    {
+      /* Allow only subregs of DImode hard regs.  */
+      if (register_no_elim_operand (SUBREG_REG (addr), DImode))
+       base = addr;
+      else
+       return 0;
+    }
   else if (GET_CODE (addr) == PLUS)
     {
       rtx addends[4], op;
@@ -11643,8 +11651,7 @@ ix86_legitimate_address_p (enum machine_
        /* Base is not a register.  */
        return false;
 
-      if (GET_MODE (base) != Pmode)
-       /* Base is not in Pmode.  */
+      if (GET_MODE (base) != SImode && GET_MODE (base) != DImode)
        return false;
 
       if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
@@ -11672,8 +11679,7 @@ ix86_legitimate_address_p (enum machine_
        /* Index is not a register.  */
        return false;
 
-      if (GET_MODE (index) != Pmode)
-       /* Index is not in Pmode.  */
+      if (GET_MODE (index) != SImode && GET_MODE (index) != DImode)
        return false;
 
       if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))

Reply via email to