OSDN Git Service

Don't include sys/file.h for winnt; use process.h instead.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index cd4d754..57c238e 100644 (file)
@@ -671,7 +671,7 @@ get_secondary_mem (x, mode, opnum, type)
 void
 clear_secondary_mem ()
 {
-  bzero (secondary_memlocs, sizeof secondary_memlocs);
+  bzero ((char *) secondary_memlocs, sizeof secondary_memlocs);
 }
 #endif /* SECONDARY_MEMORY_NEEDED */
 \f
@@ -777,8 +777,8 @@ push_reload (in, out, inloc, outloc, class,
      a pseudo and hence will become a MEM) with M1 wider than M2 and the
      register is a pseudo, also reload the inside expression.
      For machines that extend byte loads, do this for any SUBREG of a pseudo
-     where both M1 and M2 are a word or smaller unless they are the same
-     size.
+     where both M1 and M2 are a word or smaller, M1 is wider than M2, and
+     M2 is an integral mode that gets extended when loaded.
      Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
      either M1 is not valid for R or M2 is wider than a word but we only
      need one word to store an M2-sized quantity in R.
@@ -792,7 +792,11 @@ push_reload (in, out, inloc, outloc, class,
      STRICT_LOW_PART (presumably, in == out in the cas).
 
      Also reload the inner expression if it does not require a secondary
-     reload but the SUBREG does.  */
+     reload but the SUBREG does.
+
+     Finally, reload the inner expression if it is a register that is in
+     the class whose registers cannot be referenced in a different size
+     and M1 is not the same size as M2.  */
 
   if (in != 0 && GET_CODE (in) == SUBREG
       && (CONSTANT_P (SUBREG_REG (in))
@@ -808,7 +812,9 @@ push_reload (in, out, inloc, outloc, class,
                      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
                          <= UNITS_PER_WORD)
                      && (GET_MODE_SIZE (inmode)
-                         != GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))))
+                         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+                     && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
+                     && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL)
 #endif
                  ))
          || (GET_CODE (SUBREG_REG (in)) == REG
@@ -833,6 +839,15 @@ push_reload (in, out, inloc, outloc, class,
                                                SUBREG_REG (in))
                  == NO_REGS))
 #endif
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+         || (GET_CODE (SUBREG_REG (in)) == REG
+             && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+             && (TEST_HARD_REG_BIT
+                 (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
+                  REGNO (SUBREG_REG (in))))
+             && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
+                 != GET_MODE_SIZE (inmode)))
+#endif
          ))
     {
       in_subreg_loc = inloc;
@@ -885,15 +900,7 @@ push_reload (in, out, inloc, outloc, class,
                && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
               || GET_CODE (SUBREG_REG (out)) == MEM)
              && ((GET_MODE_SIZE (outmode)
-                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
-#ifdef LOAD_EXTEND_OP
-                 || (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
-                     && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
-                         <= UNITS_PER_WORD)
-                     && (GET_MODE_SIZE (outmode)
-                         != GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))))
-#endif
-                 ))
+                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))))
          || (GET_CODE (SUBREG_REG (out)) == REG
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
              && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
@@ -913,6 +920,15 @@ push_reload (in, out, inloc, outloc, class,
                                                 SUBREG_REG (out))
                  == NO_REGS))
 #endif
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+         || (GET_CODE (SUBREG_REG (out)) == REG
+             && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
+             && (TEST_HARD_REG_BIT
+                 (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
+                  REGNO (SUBREG_REG (out))))
+             && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
+                 != GET_MODE_SIZE (outmode)))
+#endif
          ))
     {
       out_subreg_loc = outloc;
@@ -1881,7 +1897,7 @@ operands_match_p (x, y)
 
 int
 n_occurrences (c, s)
-     char c;
+     int c;
      char *s;
 {
   int n = 0;
@@ -2180,7 +2196,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   /* The eliminated forms of any secondary memory locations are per-insn, so
      clear them out here.  */
 
-  bzero (secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+  bzero ((char *) secondary_memlocs_elim, sizeof secondary_memlocs_elim);
 #endif
 
   /* Find what kind of insn this is.  NOPERANDS gets number of operands.
@@ -2231,7 +2247,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                               constraints, operand_mode);
          if (noperands > 0)
            {
-             bcopy (constraints, constraints1, noperands * sizeof (char *));
+             bcopy ((char *) constraints, (char *) constraints1,
+                    noperands * sizeof (char *));
              n_alternatives = n_occurrences (',', constraints[0]) + 1;
              for (i = 1; i < noperands; i++)
                if (n_alternatives != n_occurrences (',', constraints[i]) + 1)
@@ -2530,6 +2547,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
             regardless of what the constraint says.  */
          int force_reload = 0;
          int offmemok = 0;
+         /* Nonzero if a constant forced into memory would be OK for this
+            operand.  */
+         int constmemok = 0;
          int earlyclobber = 0;
 
          /* If the operand is a SUBREG, extract
@@ -2546,12 +2566,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  || GET_CODE (operand) == PLUS
                  /* We must force a reload of paradoxical SUBREGs
                     of a MEM because the alignment of the inner value
-                    may not be enough to do the outer reference.
+                    may not be enough to do the outer reference.  On
+                    big-endian machines, it may also reference outside
+                    the object.
 
                     On machines that extend byte operations and we have a
-                    SUBREG where both the inner and outer modes are different
-                    size but no wider than a word, combine.c has made
-                    assumptions about the behavior of the machine in such
+                    SUBREG where both the inner and outer modes are no wider
+                    than a word and the inner mode is narrower, is integral,
+                    and gets extended when loaded from memory, combine.c has
+                    made assumptions about the behavior of the machine in such
                     register access.  If the data is, in fact, in memory we
                     must always load using the size assumed to be in the
                     register and let the insn do the different-sized 
@@ -2563,12 +2586,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                            < BIGGEST_ALIGNMENT)
                           && (GET_MODE_SIZE (operand_mode[i])
                               > GET_MODE_SIZE (GET_MODE (operand))))
+                         || (GET_CODE (operand) == MEM && BYTES_BIG_ENDIAN)
 #ifdef LOAD_EXTEND_OP
                          || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
                              && (GET_MODE_SIZE (GET_MODE (operand))
                                  <= UNITS_PER_WORD)
                              && (GET_MODE_SIZE (operand_mode[i])
-                                 != GET_MODE_SIZE (GET_MODE (operand))))
+                                 > GET_MODE_SIZE (GET_MODE (operand)))
+                             && INTEGRAL_MODE_P (GET_MODE (operand))
+                             && LOAD_EXTEND_OP (GET_MODE (operand)) != NIL)
 #endif
                          ))
                  /* Subreg of a hard reg which can't handle the subreg's mode
@@ -2704,7 +2730,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              case 'p':
                /* All necessary reloads for an address_operand
                   were handled in find_reloads_address.  */
-               this_alternative[i] = (int) ALL_REGS;
+               this_alternative[i] = (int) BASE_REG_CLASS;
                win = 1;
                break;
 
@@ -2718,6 +2744,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  win = 1;
                if (CONSTANT_P (operand))
                  badop = 0;
+               constmemok = 1;
                break;
 
              case '<':
@@ -2784,6 +2811,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  win = 1;
                if (CONSTANT_P (operand) || GET_CODE (operand) == MEM)
                  badop = 0;
+               constmemok = 1;
                offmemok = 1;
                break;
 
@@ -2917,6 +2945,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            this_alternative_win[i] = 1;
          else
            {
+             int const_to_mem = 0;
+
              this_alternative_offmemok[i] = offmemok;
              losers++;
              if (badop)
@@ -2946,12 +2976,17 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                 precisely the same as in the code below that calls
                 force_const_mem.  */
              if (CONSTANT_P (operand)
+                 /* force_const_mem does not accept HIGH.  */
+                 && GET_CODE (operand) != HIGH
                  && (PREFERRED_RELOAD_CLASS (operand,
                                              (enum reg_class) this_alternative[i])
                      == NO_REGS)
-                 && this_alternative[i] != (int) NO_REGS
                  && operand_mode[i] != VOIDmode)
-               losers++;
+               {
+                 const_to_mem = 1;
+                 if (this_alternative[i] != (int) NO_REGS)
+                   losers++;
+               }
 
              /* If we can't reload this value at all, reject this
                 alternative.  Note that we could also lose due to
@@ -2959,6 +2994,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                 here.  */
 
              if (! CONSTANT_P (operand)
+                 && (enum reg_class) this_alternative[i] != NO_REGS
                  && (PREFERRED_RELOAD_CLASS (operand,
                                              (enum reg_class) this_alternative[i])
                      == NO_REGS))
@@ -2968,10 +3004,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                 since such reloads may be able to be eliminated later.
                 If we are reloading a SCRATCH, we won't be generating any
                 insns, just using a register, so it is also preferred. 
-                So bump REJECT in other cases.  */
+                So bump REJECT in other cases.  Don't do this in the
+                case where we are forcing a constant into memory and
+                it will then win since we don't want to have a different
+                alternative match then.  */
              if (! (GET_CODE (operand) == REG
                     && REGNO (operand) >= FIRST_PSEUDO_REGISTER)
-                 && GET_CODE (operand) != SCRATCH)
+                 && GET_CODE (operand) != SCRATCH
+                 && ! (const_to_mem && constmemok))
                reject++;
            }
 
@@ -3172,7 +3212,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
          pref_or_nothing[commutative + 1] = t;
 
-         bcopy (constraints1, constraints, noperands * sizeof (char *));
+         bcopy ((char *) constraints1, (char *) constraints,
+                noperands * sizeof (char *));
          goto try_swapped;
        }
       else
@@ -3277,6 +3318,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   for (i = 0; i < noperands; i++)
     if (! goal_alternative_win[i]
        && CONSTANT_P (recog_operand[i])
+       /* force_const_mem does not accept HIGH.  */
+       && GET_CODE (recog_operand[i]) != HIGH
        && (PREFERRED_RELOAD_CLASS (recog_operand[i],
                                    (enum reg_class) goal_alternative[i])
            == NO_REGS)
@@ -3566,9 +3609,42 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
           || reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS)
          && (operand_reloadnum[reload_opnum[i]] < 0
-             || reload_optional[operand_reloadnum[reload_opnum[i]]])
-         && ! reload_secondary_p[i])
-       reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+             || reload_optional[operand_reloadnum[reload_opnum[i]]]))
+       {
+         /* If we have a secondary reload to go along with this reload,
+            change its type to RELOAD_FOR_OPADDR_ADDR. */
+
+         if (reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
+             && reload_secondary_in_reload[i] != -1)
+           {
+             int secondary_in_reload = reload_secondary_in_reload[i];
+
+             reload_when_needed[secondary_in_reload] = 
+               RELOAD_FOR_OPADDR_ADDR;
+
+             /* If there's a tertiary reload we have to change it also. */
+             if (secondary_in_reload > 0
+                 && reload_secondary_in_reload[secondary_in_reload] != -1)
+               reload_when_needed[reload_secondary_in_reload[secondary_in_reload]] 
+                 = RELOAD_FOR_OPADDR_ADDR;
+           }
+
+         if (reload_when_needed[i] == RELOAD_FOR_OUTPUT_ADDRESS
+             && reload_secondary_out_reload[i] != -1)
+           {
+             int secondary_out_reload = reload_secondary_out_reload[i];
+
+             reload_when_needed[secondary_out_reload] = 
+               RELOAD_FOR_OPADDR_ADDR;
+
+             /* If there's a tertiary reload we have to change it also. */
+             if (secondary_out_reload
+                 && reload_secondary_out_reload[secondary_out_reload] != -1)
+               reload_when_needed[reload_secondary_out_reload[secondary_out_reload]] 
+                 = RELOAD_FOR_OPADDR_ADDR;
+           }
+         reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+       }
 
       if (reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
          && operand_reloadnum[reload_opnum[i]] >= 0
@@ -4179,12 +4255,12 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
           && ! memory_address_p (mode, ad))
     {
       *loc = ad = gen_rtx (PLUS, GET_MODE (ad),
+                          XEXP (XEXP (ad, 0), 0),
                           plus_constant (XEXP (XEXP (ad, 0), 1),
-                                         INTVAL (XEXP (ad, 1))),
-                          XEXP (XEXP (ad, 0), 0));
-      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0), BASE_REG_CLASS,
+                                         INTVAL (XEXP (ad, 1))));
+      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1), BASE_REG_CLASS,
                                 GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (XEXP (ad, 1), 1, &XEXP (ad, 1), opnum, type, 0);
+      find_reloads_address_1 (XEXP (ad, 0), 1, &XEXP (ad, 0), opnum, type, 0);
 
       return 1;
     }