OSDN Git Service

2010-08-06 Thomas Koenig <tkoenig@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 3333697..98aaa23 100644 (file)
@@ -94,25 +94,24 @@ a register with any other reload.  */
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "rtl.h"
+#include "rtl-error.h"
 #include "tm_p.h"
 #include "insn-config.h"
 #include "expr.h"
 #include "optabs.h"
 #include "recog.h"
+#include "df.h"
 #include "reload.h"
 #include "regs.h"
 #include "addresses.h"
 #include "hard-reg-set.h"
 #include "flags.h"
-#include "real.h"
 #include "output.h"
 #include "function.h"
-#include "toplev.h"
 #include "params.h"
 #include "target.h"
-#include "df.h"
 #include "ira.h"
+#include "toplev.h" /* exact_log2 may be used by targets */
 
 /* True if X is a constant that can be forced into the constant pool.  */
 #define CONST_POOL_OK_P(X)                     \
@@ -364,7 +363,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
 
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = prev_sri;
-  rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
+  rclass = (enum reg_class) targetm.secondary_reload (in_p, x, reload_class,
+                                                     reload_mode, &sri);
   icode = (enum insn_code) sri.icode;
 
   /* If we don't need any secondary registers, done.  */
@@ -438,7 +438,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
            || (! in_p && rld[s_reload].secondary_out_reload == t_reload))
        && ((in_p && rld[s_reload].secondary_in_icode == t_icode)
            || (! in_p && rld[s_reload].secondary_out_icode == t_icode))
-       && (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
+       && (SMALL_REGISTER_CLASS_P (rclass)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        && MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
                             opnum, rld[s_reload].opnum))
       {
@@ -526,7 +527,8 @@ secondary_reload_class (bool in_p, enum reg_class rclass,
 
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = NULL;
-  rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri);
+  rclass
+    = (enum reg_class) targetm.secondary_reload (in_p, x, rclass, mode, &sri);
   icode = (enum insn_code) sri.icode;
 
   /* If there are no secondary reloads at all, we return NO_REGS.
@@ -688,7 +690,7 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
 
       if (bad || !good)
        continue;
-      cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, dest_class);
+      cost = register_move_cost (outer, (enum reg_class) rclass, dest_class);
 
       if ((reg_class_size[rclass] > best_size
           && (best_cost < 0 || best_cost >= cost))
@@ -696,7 +698,7 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
        {
          best_class = (enum reg_class) rclass;
          best_size = reg_class_size[rclass];
-         best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass,
+         best_cost = register_move_cost (outer, (enum reg_class) rclass,
                                          dest_class);
        }
     }
@@ -731,9 +733,9 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
      and the other is at worst neutral.
      (A zero compared against anything is neutral.)
 
-     If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are
-     for the same thing since that can cause us to need more reload registers
-     than we otherwise would.  */
+     For targets with small register classes, don't use existing reloads
+     unless they are for the same thing since that can cause us to need
+     more reload registers than we otherwise would.  */
 
   for (i = 0; i < n_reloads; i++)
     if ((reg_class_subset_p (rclass, rld[i].rclass)
@@ -747,7 +749,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
            || (out != 0 && MATCHES (rld[i].out, out)
                && (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
        && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
-       && (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
+       && (SMALL_REGISTER_CLASS_P (rclass)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
       return i;
 
@@ -772,7 +775,8 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
                && GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
                && MATCHES (XEXP (in, 0), rld[i].in)))
        && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
-       && (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
+       && (SMALL_REGISTER_CLASS_P (rclass)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        && MERGABLE_RELOADS (type, rld[i].when_needed,
                             opnum, rld[i].opnum))
       {
@@ -1286,7 +1290,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
             Returning zero here ought to be safe as we take care in
             find_reloads to not process the reloads when instruction was
             replaced by USE.  */
-           
+
          return 0;
        }
     }
@@ -1770,7 +1774,7 @@ combine_reloads (void)
            || rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
                            secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
 #endif
-       && (SMALL_REGISTER_CLASSES
+       && (targetm.small_register_classes_for_mode_p (VOIDmode)
            ? (rld[i].rclass == rld[output_reload].rclass)
            : (reg_class_subset_p (rld[i].rclass,
                                   rld[output_reload].rclass)
@@ -1794,7 +1798,7 @@ combine_reloads (void)
        && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
                                         rld[i].when_needed != RELOAD_FOR_INPUT)
        && (reg_class_size[(int) rld[i].rclass]
-           || SMALL_REGISTER_CLASSES)
+           || targetm.small_register_classes_for_mode_p (VOIDmode))
        /* We will allow making things slightly worse by combining an
           input and an output, but no worse than that.  */
        && (rld[i].when_needed == RELOAD_FOR_INPUT
@@ -2349,7 +2353,7 @@ decompose (rtx x)
       {
        rtx base = NULL_RTX, offset = 0;
        rtx addr = XEXP (x, 0);
-       
+
        if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
            || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
          {
@@ -2359,7 +2363,7 @@ decompose (rtx x)
            val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
            return val;
          }
-       
+
        if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
          {
            if (GET_CODE (XEXP (addr, 1)) == PLUS
@@ -2373,7 +2377,7 @@ decompose (rtx x)
                return val;
              }
          }
-       
+
        if (GET_CODE (addr) == CONST)
          {
            addr = XEXP (addr, 0);
@@ -2392,7 +2396,7 @@ decompose (rtx x)
                offset = XEXP (addr, 1);
              }
          }
-       
+
        if (offset == 0)
          {
            base = addr;
@@ -2423,18 +2427,18 @@ decompose (rtx x)
            base = gen_rtx_PLUS (GET_MODE (base), base, offset);
            offset = const0_rtx;
          }
-       
+
        if (all_const && GET_CODE (base) == PLUS)
          base = gen_rtx_CONST (GET_MODE (base), base);
-       
+
        gcc_assert (CONST_INT_P (offset));
-       
+
        val.start = INTVAL (offset);
        val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
        val.base = base;
       }
       break;
-      
+
     case REG:
       val.reg_flag = 1;
       val.start = true_regnum (x);
@@ -2565,7 +2569,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      a register.  */
   enum reg_class preferred_class[MAX_RECOG_OPERANDS];
   char pref_or_nothing[MAX_RECOG_OPERANDS];
-  /* Nonzero for a MEM operand whose entire address needs a reload. 
+  /* Nonzero for a MEM operand whose entire address needs a reload.
      May be -1 to indicate the entire address may or may not need a reload.  */
   int address_reloaded[MAX_RECOG_OPERANDS];
   /* Nonzero for an address operand that needs to be completely reloaded.
@@ -2598,7 +2602,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
   char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
   int goal_alternative_swapped;
   int best;
-  int best_small_class_operands_num;
   int commutative;
   char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
   rtx substed_operand[MAX_RECOG_OPERANDS];
@@ -2649,7 +2652,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
       && REG_P (SET_SRC (body))
       && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
-      && REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)),
+      && register_move_cost (GET_MODE (SET_SRC (body)),
                             REGNO_REG_CLASS (REGNO (SET_SRC (body))),
                             REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
     return 0;
@@ -2924,7 +2927,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      all the operands together against the register constraints.  */
 
   best = MAX_RECOG_OPERANDS * 2 + 600;
-  best_small_class_operands_num = 0;
 
   swapped = 0;
   goal_alternative_swapped = 0;
@@ -3466,7 +3468,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
 
          /* If this operand could be handled with a reg,
             and some reg is allowed, then this operand can be handled.  */
-         if (winreg && this_alternative[i] != NO_REGS)
+         if (winreg && this_alternative[i] != NO_REGS
+             && (win || !class_only_fixed_regs[this_alternative[i]]))
            badop = 0;
 
          /* Record which operands fit this alternative.  */
@@ -3631,7 +3634,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                   || modified[j] != RELOAD_WRITE)
                  && j != i
                  /* Ignore things like match_operator operands.  */
-                 && *recog_data.constraints[j] != 0
+                 && !recog_data.is_operator[j]
                  /* Don't count an input operand that is constrained to match
                     the early clobber operand.  */
                  && ! (this_alternative_matches[j] == i
@@ -3710,27 +3713,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
         record it as the chosen goal for reloading.  */
       if (! bad)
        {
-         bool change_p = false;
-         int small_class_operands_num = 0;
-
-         if (best >= losers)
-           {
-             for (i = 0; i < noperands; i++)
-               small_class_operands_num
-                 += SMALL_REGISTER_CLASS_P (this_alternative[i]) ? 1 : 0;
-             if (best > losers
-                 || (best == losers
-                     /* If the cost of the reloads is the same,
-                        prefer alternative which requires minimal
-                        number of small register classes for the
-                        operands.  This improves chances of reloads
-                        for insn requiring small register
-                        classes.  */
-                     && (small_class_operands_num
-                         < best_small_class_operands_num)))
-               change_p = true;
-           }
-         if (change_p)
+         if (best > losers)
            {
              for (i = 0; i < noperands; i++)
                {
@@ -3746,7 +3729,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                }
              goal_alternative_swapped = swapped;
              best = losers;
-             best_small_class_operands_num = small_class_operands_num;
              goal_alternative_number = this_alternative_number;
              goal_earlyclobber = this_earlyclobber;
            }
@@ -5156,7 +5138,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
          continue;
 
       inner_code = GET_CODE (XEXP (ad, 0));
-      if (!(GET_CODE (ad) == PLUS 
+      if (!(GET_CODE (ad) == PLUS
            && CONST_INT_P (XEXP (ad, 1))
            && (inner_code == PLUS || inner_code == LO_SUM)))
        continue;
@@ -5187,17 +5169,17 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
          /* Form the adjusted address.  */
          if (GET_CODE (XEXP (ad, 0)) == PLUS)
-           ad = gen_rtx_PLUS (GET_MODE (ad), 
-                              op_index == 0 ? offset_reg : addend, 
+           ad = gen_rtx_PLUS (GET_MODE (ad),
+                              op_index == 0 ? offset_reg : addend,
                               op_index == 0 ? addend : offset_reg);
          else
-           ad = gen_rtx_LO_SUM (GET_MODE (ad), 
-                                op_index == 0 ? offset_reg : addend, 
+           ad = gen_rtx_LO_SUM (GET_MODE (ad),
+                                op_index == 0 ? offset_reg : addend,
                                 op_index == 0 ? addend : offset_reg);
          *loc = ad;
 
          cls = base_reg_class (mode, MEM, GET_CODE (addend));
-         find_reloads_address_part (XEXP (ad, op_index), 
+         find_reloads_address_part (XEXP (ad, op_index),
                                     &XEXP (ad, op_index), cls,
                                     GET_MODE (ad), opnum, type, ind_levels);
          find_reloads_address_1 (mode,
@@ -5239,7 +5221,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
   if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
     {
       enum machine_mode address_mode = GET_MODE (ad);
-      if (ad == VOIDmode)
+      if (address_mode == VOIDmode)
        address_mode = targetm.addr_space.address_mode (as);
 
       /* If AD is an address in the constant pool, the MEM rtx may be shared.
@@ -5500,7 +5482,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
 #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX)         \
   ((CONTEXT) == 0                                                      \
    ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX)                   \
-   : REGNO_OK_FOR_INDEX_P (REGNO))                                     
+   : REGNO_OK_FOR_INDEX_P (REGNO))
 
   enum reg_class context_reg_class;
   RTX_CODE code = GET_CODE (x);
@@ -5830,8 +5812,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              rtx equiv = (MEM_P (XEXP (x, 0))
                           ? XEXP (x, 0)
                           : reg_equiv_mem[regno]);
-             int icode
-               = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
+             int icode = (int) optab_handler (add_optab, GET_MODE (x));
              if (insn && NONJUMP_INSN_P (insn) && equiv
                  && memory_operand (equiv, GET_MODE (equiv))
 #ifdef HAVE_cc0
@@ -6007,7 +5988,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
              if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x)))
                  > reg_class_size[rclass])
                {
-                 x = find_reloads_subreg_address (x, 0, opnum, 
+                 x = find_reloads_subreg_address (x, 0, opnum,
                                                   ADDR_TYPE (type),
                                                   ind_levels, insn);
                  push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
@@ -6149,6 +6130,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
              PUT_MODE (tem, GET_MODE (x));
              if (MEM_OFFSET (tem))
                set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
+             if (MEM_SIZE (tem)
+                 && INTVAL (MEM_SIZE (tem)) != (HOST_WIDE_INT) outer_size)
+               set_mem_size (tem, GEN_INT (outer_size));
 
              /* If this was a paradoxical subreg that we replaced, the
                 resulting memory must be sufficiently aligned to allow
@@ -6644,7 +6628,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
   else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
           || GET_CODE (x) == CC0)
     return reg_mentioned_p (x, in);
-  else 
+  else
     {
       gcc_assert (GET_CODE (x) == PLUS);
 
@@ -7218,7 +7202,7 @@ find_inc_amount (rtx x, rtx inced)
    REG_INC note in insn INSN.  REGNO must refer to a hard register.  */
 
 #ifdef AUTO_INC_DEC
-static int 
+static int
 reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
                           rtx insn)
 {
@@ -7228,13 +7212,13 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
 
   if (! INSN_P (insn))
     return 0;
-    
+
   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
     if (REG_NOTE_KIND (link) == REG_INC)
       {
        unsigned int test = (int) REGNO (XEXP (link, 0));
        if (test >= regno && test < endregno)
-         return 1; 
+         return 1;
       }
   return 0;
 }
@@ -7242,7 +7226,7 @@ reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
 
 #define reg_inc_found_and_valid_p(regno,endregno,insn) 0
 
-#endif 
+#endif
 
 /* Return 1 if register REGNO is the subject of a clobber in insn INSN.
    If SETS is 1, also consider SETs.  If SETS is 2, enable checking
@@ -7270,8 +7254,8 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
     }
 
   if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn))
-    return 1; 
-  
+    return 1;
+
   if (GET_CODE (PATTERN (insn)) == PARALLEL)
     {
       int i = XVECLEN (PATTERN (insn), 0) - 1;
@@ -7290,7 +7274,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
            }
          if (sets == 2
              && reg_inc_found_and_valid_p (regno, endregno, elt))
-           return 1; 
+           return 1;
        }
     }
 
@@ -7332,7 +7316,7 @@ static const char *const reload_when_needed_name[] =
 
 /* These functions are used to print the variables set by 'find_reloads' */
 
-void
+DEBUG_FUNCTION void
 debug_reload_to_stream (FILE *f)
 {
   int r;
@@ -7427,7 +7411,7 @@ debug_reload_to_stream (FILE *f)
     }
 }
 
-void
+DEBUG_FUNCTION void
 debug_reload (void)
 {
   debug_reload_to_stream (stderr);