OSDN Git Service

* config/avr/avr-protos.h (avr_output_addr_vec_elt): Prototype.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index dbf1052..86d80c1 100644 (file)
@@ -647,7 +647,7 @@ get_secondary_mem (x, mode, opnum, type)
 void
 clear_secondary_mem ()
 {
-  bzero ((char *) secondary_memlocs, sizeof secondary_memlocs);
+  memset ((char *) secondary_memlocs, 0, sizeof secondary_memlocs);
 }
 #endif /* SECONDARY_MEMORY_NEEDED */
 \f
@@ -1558,7 +1558,7 @@ remove_address_replacements (in_rtx)
   char reload_flags[MAX_RELOADS];
   int something_changed = 0;
 
-  bzero (reload_flags, sizeof reload_flags);
+  memset (reload_flags, 0, sizeof reload_flags);
   for (i = 0, j = 0; i < n_replacements; i++)
     {
       if (loc_mentioned_in_p (replacements[i].where, in_rtx))
@@ -2399,6 +2399,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int no_input_reloads = 0, no_output_reloads = 0;
   int n_alternatives;
   int this_alternative[MAX_RECOG_OPERANDS];
+  char this_alternative_match_win[MAX_RECOG_OPERANDS];
   char this_alternative_win[MAX_RECOG_OPERANDS];
   char this_alternative_offmemok[MAX_RECOG_OPERANDS];
   char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
@@ -2410,6 +2411,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int operand_reloadnum[MAX_RECOG_OPERANDS];
   int goal_alternative_matches[MAX_RECOG_OPERANDS];
   int goal_alternative_matched[MAX_RECOG_OPERANDS];
+  char goal_alternative_match_win[MAX_RECOG_OPERANDS];
   char goal_alternative_win[MAX_RECOG_OPERANDS];
   char goal_alternative_offmemok[MAX_RECOG_OPERANDS];
   char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
@@ -2449,7 +2451,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 ((char *) secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+  memset ((char *) secondary_memlocs_elim, 0, sizeof secondary_memlocs_elim);
 #endif
 
   /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
@@ -2741,6 +2743,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        {
          register char *p = constraints[i];
          register int win = 0;
+         int did_match = 0;
          /* 0 => this operand can be reloaded somehow for this alternative */
          int badop = 1;
          /* 0 => this operand can be reloaded if the alternative allows regs.  */
@@ -2839,6 +2842,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
          this_alternative[i] = (int) NO_REGS;
          this_alternative_win[i] = 0;
+         this_alternative_match_win[i] = 0;
          this_alternative_offmemok[i] = 0;
          this_alternative_earlyclobber[i] = 0;
          this_alternative_matches[i] = -1;
@@ -2917,7 +2921,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                        && ! this_alternative_win[c])
                      bad = 1;
 
-                   win = this_alternative_win[c];
+                   did_match = this_alternative_win[c];
                  }
                else
                  {
@@ -2953,12 +2957,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                   operand also had to match the same thing as this
                   operand, we don't know how to do that.  So reject this
                   alternative.  */
-               if (! win || force_reload)
+               if (! did_match || force_reload)
                  for (j = 0; j < i; j++)
                    if (this_alternative_matches[j]
                        == this_alternative_matches[i])
                      badop = 1;
-
                break;
 
              case 'p':
@@ -3175,6 +3178,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          this_alternative_earlyclobber[i] = earlyclobber;
          if (win && ! force_reload)
            this_alternative_win[i] = 1;
+         else if (did_match && ! force_reload)
+           this_alternative_match_win[i] = 1;
          else
            {
              int const_to_mem = 0;
@@ -3276,7 +3281,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
             Don't do this if the preferred class has only one register
             because we might otherwise exhaust the class.  */
 
-         if (! win && this_alternative[i] != (int) NO_REGS
+         if (! win && ! did_match
+             && this_alternative[i] != (int) NO_REGS
              && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
              && reg_class_size[(int) preferred_class[i]] > 1)
            {
@@ -3302,7 +3308,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
       for (i = 0; i < noperands; i++)
        if (this_alternative_earlyclobber[i]
-           && this_alternative_win[i])
+           && (this_alternative_win[i] || this_alternative_match_win[i]))
          {
            struct decomposition early_data;
 
@@ -3345,6 +3351,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                    {
                      losers++;
                      this_alternative_win[j] = 0;
+                     this_alternative_match_win[j] = 0;
                    }
                  else
                    break;
@@ -3355,11 +3362,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              {
                losers++;
                this_alternative_win[i] = 0;
+               this_alternative_match_win[j] = 0;
                for (j = 0; j < noperands; j++)
                  if (this_alternative_matches[j] == i
-                     && this_alternative_win[j])
+                     && this_alternative_match_win[j])
                    {
                      this_alternative_win[j] = 0;
+                     this_alternative_match_win[j] = 0;
                      losers++;
                    }
              }
@@ -3378,7 +3387,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            }
          for (i = 0; i < noperands; i++)
            {
-             goal_alternative_win[i] = 1;
+             goal_alternative_win[i] = this_alternative_win[i];
+             goal_alternative_match_win[i] = this_alternative_match_win[i];
              goal_alternative[i] = this_alternative[i];
              goal_alternative_offmemok[i] = this_alternative_offmemok[i];
              goal_alternative_matches[i] = this_alternative_matches[i];
@@ -3406,6 +3416,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
            {
              goal_alternative[i] = this_alternative[i];
              goal_alternative_win[i] = this_alternative_win[i];
+             goal_alternative_match_win[i] = this_alternative_match_win[i];
              goal_alternative_offmemok[i] = this_alternative_offmemok[i];
              goal_alternative_matches[i] = this_alternative_matches[i];
              goal_alternative_earlyclobber[i]
@@ -3487,12 +3498,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
   for (i = 0; i < noperands; i++)
     goal_alternative_matched[i] = -1;
-
   for (i = 0; i < noperands; i++)
     if (! goal_alternative_win[i]
        && goal_alternative_matches[i] >= 0)
       goal_alternative_matched[goal_alternative_matches[i]] = i;
 
+  for (i = 0; i < noperands; i++)
+    goal_alternative_win[i] |= goal_alternative_match_win[i];
+
   /* If the best alternative is with operands 1 and 2 swapped,
      consider them swapped before reporting the reloads.  Update the
      operand numbers of any reloads already pushed.  */
@@ -4522,7 +4536,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
 
       else if (regno < FIRST_PSEUDO_REGISTER
               && REGNO_MODE_OK_FOR_BASE_P (regno, mode)
-              && ! regno_clobbered_p (regno, this_insn, mode))
+              && ! regno_clobbered_p (regno, this_insn, mode, 0))
        return 0;
 
       /* If we do not have one of the cases above, we must do the reload.  */
@@ -5141,7 +5155,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
 
        if (REG_P (XEXP (op1, 0)))
          {
-           register int regno = REGNO (XEXP (op1, 0));
+           rtx link;
+           int regno = REGNO (XEXP (op1, 0));
+           int reloadnum;
 
            /* A register that is incremented cannot be constant!  */
            if (regno >= FIRST_PSEUDO_REGISTER
@@ -5164,15 +5180,17 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                       write back the value after reading it, hence we actually
                       need two registers.  */
                    find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
-                                         &XEXP (tem, 0), opnum, type,
+                                         &XEXP (tem, 0), opnum,
+                                         RELOAD_OTHER,
                                          ind_levels, insn);
 
                    /* Then reload the memory location into a base
                       register.  */
-                   push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0),
-                                BASE_REG_CLASS, GET_MODE (x), GET_MODE (x),
-                                0, 0, opnum, RELOAD_OTHER);
-                   break;
+                   reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+                                            &XEXP (op1, 0), BASE_REG_CLASS,
+                                            GET_MODE (x), GET_MODE (x), 0,
+                                            0, opnum, RELOAD_OTHER);
+                   goto reg_inc;
                  }
              }
 
@@ -5182,12 +5200,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
            /* We require a base register here...  */
            if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
              {
-               push_reload (XEXP (op1, 0), XEXP (x, 0),
-                            &XEXP (op1, 0), &XEXP (x, 0),
-                            BASE_REG_CLASS,
-                            GET_MODE (x), GET_MODE (x), 0, 0,
-                            opnum, RELOAD_OTHER);
+               reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+                                        &XEXP (op1, 0), &XEXP (x, 0),
+                                        BASE_REG_CLASS,
+                                        GET_MODE (x), GET_MODE (x), 0, 0,
+                                        opnum, RELOAD_OTHER);
              }
+
+           /* Update the REG_INC notes.  */
+         reg_inc:
+           for (link = REG_NOTES (this_insn); link; link = XEXP (link, 1))
+             if (REG_NOTE_KIND (link) == REG_INC
+                 && REGNO (XEXP (link, 0)) == regno)
+               push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
          }
        else
          abort ();
@@ -5427,7 +5452,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
           in this insn, reload it into some other register to be safe.
           The CLOBBER is supposed to make the register unavailable
           from before this insn to after it.  */
-       if (regno_clobbered_p (regno, this_insn, GET_MODE (x)))
+       if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
          {
            push_reload (x, NULL_RTX, loc, NULL_PTR,
                         (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
@@ -6171,16 +6196,29 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
                      && (valtry
                          = operand_subword (SET_DEST (pat), 1, 0, VOIDmode))
                      && (valueno = true_regnum (valtry)) >= 0)))
-           if (other >= 0
-               ? valueno == other
-               : ((unsigned) valueno < FIRST_PSEUDO_REGISTER
-                  && TEST_HARD_REG_BIT (reg_class_contents[(int) class],
-                                        valueno)))
-             {
-               value = valtry;
-               where = p;
-               break;
-             }
+           {
+             if (other >= 0)
+               {
+                 if (valueno != other)
+                   continue;
+               }
+             else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
+               continue;
+             else
+               {
+                 int i;
+
+                 for (i = HARD_REGNO_NREGS (valueno, mode) - 1; i >= 0; i--)
+                   if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+                                            valueno + i))
+                     break;
+                 if (i >= 0)
+                   continue;
+               }
+             value = valtry;
+             where = p;
+             break;
+           }
        }
     }
 
@@ -6525,18 +6563,21 @@ find_inc_amount (x, inced)
   return 0;
 }
 \f
-/* Return 1 if register REGNO is the subject of a clobber in insn INSN.  */
+/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
+   If SETS is nonzero, also consider SETs.  */
 
 int
-regno_clobbered_p (regno, insn, mode)
+regno_clobbered_p (regno, insn, mode, sets)
      unsigned int regno;
      rtx insn;
      enum machine_mode mode;
+     int sets;
 {
   int nregs = HARD_REGNO_NREGS (regno, mode);
   int endregno = regno + nregs;
 
-  if (GET_CODE (PATTERN (insn)) == CLOBBER
+  if ((GET_CODE (PATTERN (insn)) == CLOBBER
+       || (sets && GET_CODE (PATTERN (insn)) == SET))
       && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
     {
       int test = REGNO (XEXP (PATTERN (insn), 0));
@@ -6551,7 +6592,9 @@ regno_clobbered_p (regno, insn, mode)
       for (; i >= 0; i--)
        {
          rtx elt = XVECEXP (PATTERN (insn), 0, i);
-         if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG)
+         if ((GET_CODE (elt) == CLOBBER
+              || (sets && GET_CODE (PATTERN (insn)) == SET))
+             && GET_CODE (XEXP (elt, 0)) == REG)
            {
              int test = REGNO (XEXP (elt, 0));