]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/reload.c
Merge in gcc2 snapshot 19980929. See gcc/ChangeLog and gcc/FSFChangeLog for
[thirdparty/gcc.git] / gcc / reload.c
index 06c34cb79799281be25e22cc1d867aad97c46517..c8331e3f2571361fe432c1951f18a628c94ea5d0 100644 (file)
@@ -869,9 +869,11 @@ push_reload (in, out, inloc, outloc, class,
      the class whose registers cannot be referenced in a different size
      and M1 is not the same size as M2.  If SUBREG_WORD is nonzero, we
      cannot reload just the inside since we might end up with the wrong
-     register class.  */
+     register class.  But if it is inside a STRICT_LOW_PART, we have
+     no choice, so we hope we do get the right register class there.  */
 
-  if (in != 0 && GET_CODE (in) == SUBREG && SUBREG_WORD (in) == 0
+  if (in != 0 && GET_CODE (in) == SUBREG
+      && (SUBREG_WORD (in) == 0 || strict_low)
 #ifdef CLASS_CANNOT_CHANGE_SIZE
       && class != CLASS_CANNOT_CHANGE_SIZE
 #endif
@@ -988,7 +990,8 @@ push_reload (in, out, inloc, outloc, class,
      storing in a subreg is entitled to clobber it all
      (except in the case of STRICT_LOW_PART,
      and in that case the constraint should label it input-output.)  */
-  if (out != 0 && GET_CODE (out) == SUBREG && SUBREG_WORD (out) == 0
+  if (out != 0 && GET_CODE (out) == SUBREG
+      && (SUBREG_WORD (out) == 0 || strict_low)
 #ifdef CLASS_CANNOT_CHANGE_SIZE
       && class != CLASS_CANNOT_CHANGE_SIZE
 #endif
@@ -2602,12 +2605,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        }
       else if (code == MEM)
        {
-         if (find_reloads_address (GET_MODE (recog_operand[i]),
+         address_reloaded[i]
+           = find_reloads_address (GET_MODE (recog_operand[i]),
                                    recog_operand_loc[i],
                                    XEXP (recog_operand[i], 0),
                                    &XEXP (recog_operand[i], 0),
-                                   i, address_type[i], ind_levels, insn))
-           address_reloaded[i] = 1;
+                                   i, address_type[i], ind_levels, insn);
          substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
        }
       else if (code == SUBREG)
@@ -2683,6 +2686,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
           && reg_alternate_class (REGNO (recog_operand[i])) == NO_REGS);
     }
 
+#ifdef HAVE_cc0
+  /* If we made any reloads for addresses, see if they violate a
+     "no input reloads" requirement for this insn.  */
+  if (no_input_reloads)
+    for (i = 0; i < n_reloads; i++)
+      if (reload_in[i] != 0)
+       abort ();
+#endif
+
   /* If this is simply a copy from operand 1 to operand 0, merge the
      preferred classes for the operands.  */
   if (set != 0 && noperands >= 2 && recog_operand[0] == SET_DEST (set)
@@ -3020,24 +3032,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                     /* If IND_LEVELS, find_reloads_address won't reload a
                        pseudo that didn't get a hard reg, so we have to
                        reject that case.  */
-                    && (ind_levels ? offsettable_memref_p (operand)
-                        : offsettable_nonstrict_memref_p (operand)))
-                   /* A reloaded auto-increment address is offsettable,
-                      because it is now just a simple register indirect.  */
-                   || (GET_CODE (operand) == MEM
-                       && address_reloaded[i]
-                       && (GET_CODE (XEXP (operand, 0)) == PRE_INC
-                           || GET_CODE (XEXP (operand, 0)) == PRE_DEC
-                           || GET_CODE (XEXP (operand, 0)) == POST_INC
-                           || GET_CODE (XEXP (operand, 0)) == POST_DEC))
-                   /* Certain mem addresses will become offsettable
-                      after they themselves are reloaded.  This is important;
-                      we don't want our own handling of unoffsettables
-                      to override the handling of reg_equiv_address.  */
-                   || (GET_CODE (operand) == MEM
-                       && GET_CODE (XEXP (operand, 0)) == REG
-                       && (ind_levels == 0
-                           || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0))
+                    && ((ind_levels ? offsettable_memref_p (operand)
+                         : offsettable_nonstrict_memref_p (operand))
+                        /* A reloaded address is offsettable because it is now
+                           just a simple register indirect.  */
+                        || address_reloaded[i]))
                    || (GET_CODE (operand) == REG
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0
@@ -4552,6 +4551,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
      rtx insn;
 {
   register int regno;
+  int removed_and = 0;
   rtx tem;
 
   /* If the address is a register, see if it is a legitimate address and
@@ -4566,7 +4566,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
          && strict_memory_address_p (mode, reg_equiv_constant[regno]))
        {
          *loc = ad = reg_equiv_constant[regno];
-         return 1;
+         return 0;
        }
 
       tem = reg_equiv_memory_loc[regno];
@@ -4671,12 +4671,22 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
   while (0);
 #endif
 
-  /* The address is not valid.  We have to figure out why.  One possibility
-     is that it is itself a MEM.  This can happen when the frame pointer is
-     being eliminated, a pseudo is not allocated to a hard register, and the
-     offset between the frame and stack pointers is not its initial value.
-     In that case the pseudo will have been replaced by a MEM referring to
-     the stack pointer.  */
+  /* The address is not valid.  We have to figure out why.  First see if
+     we have an outer AND and remove it if so.  Then analyze what's inside.  */
+
+  if (GET_CODE (ad) == AND)
+    {
+      removed_and = 1;
+      loc = &XEXP (ad, 0);
+      ad = *loc;
+    }
+
+  /* One possibility for why the address is invalid is that it is itself
+     a MEM.  This can happen when the frame pointer is being eliminated, a
+     pseudo is not allocated to a hard register, and the offset between the
+     frame and stack pointers is not its initial value.  In that case the
+     pseudo will have been replaced by a MEM referring to the
+     stack pointer.  */
   if (GET_CODE (ad) == MEM)
     {
       /* First ensure that the address in this MEM is valid.  Then, unless
@@ -4693,6 +4703,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
          *memrefloc = copy_rtx (*memrefloc);
          copy_replacements (tem, XEXP (*memrefloc, 0));
          loc = &XEXP (*memrefloc, 0);
+         if (removed_and)
+           loc = &XEXP (*loc, 0);
        }
 
       /* Check similar cases as for indirect addresses as above except
@@ -4713,7 +4725,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
                       BASE_REG_CLASS, GET_MODE (tem),
                       VOIDmode, 0,
                       0, opnum, type);
-         return 1;
+         return ! removed_and;
        }
       else
        return 0;
@@ -4735,16 +4747,21 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
        {
          *memrefloc = copy_rtx (*memrefloc);
          loc = &XEXP (*memrefloc, 0);
+         if (removed_and)
+           loc = &XEXP (*loc, 0);
        }
+
       if (double_reg_address_ok)
        {
          /* Unshare the sum as well.  */
          *loc = ad = copy_rtx (ad);
+
          /* Reload the displacement into an index reg.
             We assume the frame pointer or arg pointer is a base reg.  */
          find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
                                     INDEX_REG_CLASS, GET_MODE (ad), opnum,
                                     type, ind_levels);
+         return 0;
        }
       else
        {
@@ -4754,7 +4771,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
          find_reloads_address_part (ad, loc, BASE_REG_CLASS,
                                     Pmode, opnum, type, ind_levels);
        }
-      return 1;
+      return ! removed_and;
     }
 
   /* If we have an indexed stack slot, there are three possible reasons why
@@ -4807,7 +4824,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
       find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
                              type, 0, insn);
 
-      return 1;
+      return 0;
     }
                           
   else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
@@ -4831,7 +4848,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
       find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
                              type, 0, insn);
 
-      return 1;
+      return 0;
     }
                           
   /* See if address becomes valid when an eliminable register
@@ -4868,11 +4885,13 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
        {
          *memrefloc = copy_rtx (*memrefloc);
          loc = &XEXP (*memrefloc, 0);
+         if (removed_and)
+           loc = &XEXP (*loc, 0);
        }
 
       find_reloads_address_part (ad, loc, BASE_REG_CLASS, Pmode, opnum, type,
                                 ind_levels);
-      return 1;
+      return ! removed_and;
     }
 
   return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,