OSDN Git Service

Update FSF address.
[pf3gnuchains/gcc-fork.git] / gcc / local-alloc.c
index 60ad072..3ab26ae 100644 (file)
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* Allocation of hard register numbers to pseudo registers is done in
@@ -165,6 +166,11 @@ static enum reg_class *qty_alternate_class;
 
 static rtx *qty_scratch_rtx;
 
+/* Element Q is nonzero if this quantity has been used in a SUBREG
+   that changes its size.  */
+
+static char *qty_changes_size;
+
 /* Element Q is the register number of one pseudo register whose
    reg_qty value is Q, or -1 is this quantity is for a SCRATCH.  This
    register should be the head of the chain maintained in reg_next_in_qty.  */
@@ -263,7 +269,7 @@ static int find_free_reg    PROTO((enum reg_class, enum machine_mode,
 static void mark_life          PROTO((int, enum machine_mode, int));
 static void post_mark_life     PROTO((int, enum machine_mode, int, int, int));
 static int no_conflict_p       PROTO((rtx, rtx, rtx));
-static int requires_inout_p    PROTO((char *));
+static int requires_inout      PROTO((char *));
 \f
 /* Allocate a new quantity (new within current basic block)
    for register number REGNO which is born at index BIRTH
@@ -289,6 +295,7 @@ alloc_qty (regno, mode, size, birth)
   qty_min_class[qty] = reg_preferred_class (regno);
   qty_alternate_class[qty] = reg_alternate_class (regno);
   qty_n_refs[qty] = reg_n_refs[regno];
+  qty_changes_size[qty] = reg_changes_size[regno];
 }
 \f
 /* Similar to `alloc_qty', but allocates a quantity for a SCRATCH rtx
@@ -378,6 +385,7 @@ alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
   qty_min_class[qty] = class;
   qty_alternate_class[qty] = NO_REGS;
   qty_n_refs[qty] = 1;
+  qty_changes_size[qty] = 0;
 }
 \f
 /* Main entry point of this file.  */
@@ -415,26 +423,31 @@ local_alloc ()
 
   scratch_list_length = max_qty;
   scratch_list = (rtx *) xmalloc (scratch_list_length * sizeof (rtx));
-  bzero (scratch_list, scratch_list_length * sizeof (rtx));
+  bzero ((char *) scratch_list, scratch_list_length * sizeof (rtx));
   scratch_block = (int *) xmalloc (scratch_list_length * sizeof (int));
-  bzero (scratch_block, scratch_list_length * sizeof (int));
+  bzero ((char *) scratch_block, scratch_list_length * sizeof (int));
   scratch_index = 0;
 
   qty_phys_reg = (short *) alloca (max_qty * sizeof (short));
-  qty_phys_copy_sugg = (HARD_REG_SET *) alloca (max_qty * sizeof (HARD_REG_SET));
-  qty_phys_num_copy_sugg = (short *) alloca (max_qty * sizeof (char));
+  qty_phys_copy_sugg
+    = (HARD_REG_SET *) alloca (max_qty * sizeof (HARD_REG_SET));
+  qty_phys_num_copy_sugg = (short *) alloca (max_qty * sizeof (short));
   qty_phys_sugg = (HARD_REG_SET *) alloca (max_qty * sizeof (HARD_REG_SET));
-  qty_phys_num_sugg = (short *) alloca (max_qty * sizeof (char));
+  qty_phys_num_sugg = (short *) alloca (max_qty * sizeof (short));
   qty_birth = (int *) alloca (max_qty * sizeof (int));
   qty_death = (int *) alloca (max_qty * sizeof (int));
   qty_scratch_rtx = (rtx *) alloca (max_qty * sizeof (rtx));
   qty_first_reg = (int *) alloca (max_qty * sizeof (int));
   qty_size = (int *) alloca (max_qty * sizeof (int));
-  qty_mode = (enum machine_mode *) alloca (max_qty * sizeof (enum machine_mode));
+  qty_mode
+    = (enum machine_mode *) alloca (max_qty * sizeof (enum machine_mode));
   qty_n_calls_crossed = (int *) alloca (max_qty * sizeof (int));
-  qty_min_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
-  qty_alternate_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
+  qty_min_class
+    = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
+  qty_alternate_class
+    = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
   qty_n_refs = (int *) alloca (max_qty * sizeof (int));
+  qty_changes_size = (char *) alloca (max_qty * sizeof (char));
 
   reg_qty = (int *) alloca (max_regno * sizeof (int));
   reg_offset = (char *) alloca (max_regno * sizeof (char));
@@ -492,7 +505,7 @@ local_alloc ()
       else
        {
 #define CLEAR(vector)  \
-         bzero ((vector), (sizeof (*(vector))) * next_qty);
+         bzero ((char *) (vector), (sizeof (*(vector))) * next_qty);
 
          CLEAR (qty_scratch_rtx);
          CLEAR (qty_phys_copy_sugg);
@@ -937,8 +950,8 @@ update_equiv_regs ()
   rtx *reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
   rtx insn;
 
-  bzero (reg_equiv_init_insn, max_regno * sizeof (rtx *));
-  bzero (reg_equiv_replacement, max_regno * sizeof (rtx *));
+  bzero ((char *) reg_equiv_init_insn, max_regno * sizeof (rtx *));
+  bzero ((char *) reg_equiv_replacement, max_regno * sizeof (rtx *));
 
   init_alias_analysis ();
 
@@ -1139,7 +1152,7 @@ block_alloc (b)
      the birth of a CLOBBER in the first insn.  */
   regs_live_at = (HARD_REG_SET *) alloca ((2 * insn_count + 2)
                                          * sizeof (HARD_REG_SET));
-  bzero (regs_live_at, (2 * insn_count + 2) * sizeof (HARD_REG_SET));
+  bzero ((char *) regs_live_at, (2 * insn_count + 2) * sizeof (HARD_REG_SET));
 
   /* Initialize table of hardware registers currently live.  */
 
@@ -1207,13 +1220,21 @@ block_alloc (b)
              )
            {
 #ifdef REGISTER_CONSTRAINTS
+             /* If non-negative, is an operand that must match operand 0.  */
              int must_match_0 = -1;
-
+             /* Counts number of alternatives that require a match with
+                operand 0.  */
+             int n_matching_alts = 0;
 
              for (i = 1; i < insn_n_operands[insn_code_number]; i++)
-               if (requires_inout_p
-                   (insn_operand_constraint[insn_code_number][i]))
-                 must_match_0 = i;
+               {
+                 char *p = insn_operand_constraint[insn_code_number][i];
+                 int this_match = (requires_inout (p));
+
+                 n_matching_alts += this_match;
+                 if (this_match == insn_n_alternatives[insn_code_number])
+                   must_match_0 = i;
+               }
 #endif
 
              r0 = recog_operand[0];
@@ -1230,6 +1251,16 @@ block_alloc (b)
                      && ! (i == must_match_0 - 1
                            && insn_operand_constraint[insn_code_number][i][0] == '%'))
                    continue;
+
+                 /* Likewise if each alternative has some operand that
+                    must match operand zero.  In that case, skip any 
+                    operand that doesn't list operand 0 since we know that
+                    the operand always conflicts with operand 0.  We
+                    ignore commutatity in this case to keep things simple.  */
+                 if (n_matching_alts == insn_n_alternatives[insn_code_number]
+                     && (0 == requires_inout
+                         (insn_operand_constraint[insn_code_number][i])))
+                   continue;
 #endif
 
                  r1 = recog_operand[i];
@@ -1264,6 +1295,8 @@ block_alloc (b)
                        win = combine_regs (r1, r0, may_save_copy,
                                            insn_number, insn, 0);
                    }
+                 if (win)
+                   break;
                }
            }
 
@@ -1593,7 +1626,7 @@ qty_compare_1 (q1, q2)
    is called for quantities that have suggested hard registers.  First priority
    goes to quantities that have copy preferences, then to those that have
    normal preferences.  Within those groups, quantities with the lower
-   number of preferenes have the highest priority.  Of those, we use the same
+   number of preferences have the highest priority.  Of those, we use the same
    algorithm as above.  */
 
 static int
@@ -1634,7 +1667,7 @@ qty_sugg_compare_1 (q1, q2)
                        : qty_phys_num_sugg[*q1] * FIRST_PSEUDO_REGISTER);
   register int sugg2 = (qty_phys_num_copy_sugg[*q2]
                        ? qty_phys_num_copy_sugg[*q2]
-                       : qty_phys_num_sugg[*q2] * FIRST_PSUEDO_REGISTER);
+                       : qty_phys_num_sugg[*q2] * FIRST_PSEUDO_REGISTER);
 
   /* Note that the quotient will never be bigger than
      the value of floor_log2 times the maximum number of
@@ -1903,6 +1936,9 @@ update_qty_class (qty, reg)
   rclass = reg_alternate_class (reg);
   if (reg_class_subset_p (rclass, qty_alternate_class[qty]))
     qty_alternate_class[qty] = rclass;
+
+  if (reg_changes_size[reg])
+    qty_changes_size[qty] = 1;
 }
 \f
 /* Handle something which alters the value of an rtx REG.
@@ -2086,6 +2122,12 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
   SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
 #endif
 
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+  if (qty_changes_size[qty])
+    IOR_HARD_REG_SET (used,
+                     reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
+#endif
+
   /* Normally, the registers that can be used for the first register in
      a multi-register quantity are the same as those that can be used for
      subsequent registers.  However, if just trying suggested registers,
@@ -2265,26 +2307,25 @@ no_conflict_p (insn, r0, r1)
 \f
 #ifdef REGISTER_CONSTRAINTS
 
-/* Return 1 if the constraint string P indicates that the a the operand
-   must be equal to operand 0 and that no register is acceptable.  */
+/* Return the number of alternatives for which the constraint string P
+   indicates that the operand must be equal to operand 0 and that no register
+   is acceptable.  */
 
 static int
-requires_inout_p (p)
+requires_inout (p)
      char *p;
 {
   char c;
   int found_zero = 0;
+  int reg_allowed = 0;
+  int num_matching_alts = 0;
 
   while (c = *p++)
     switch (c)
       {
-      case '0':
-       found_zero = 1;
-       break;
-
       case '=':  case '+':  case '?':
       case '#':  case '&':  case '!':
-      case '*':  case '%':  case ',':
+      case '*':  case '%':
       case '1':  case '2':  case '3':  case '4':
       case 'm':  case '<':  case '>':  case 'V':  case 'o':
       case 'E':  case 'F':  case 'G':  case 'H':
@@ -2298,14 +2339,28 @@ requires_inout_p (p)
        /* These don't say anything we care about.  */
        break;
 
+      case ',':
+       if (found_zero && ! reg_allowed)
+         num_matching_alts++;
+
+       found_zero = reg_allowed = 0;
+       break;
+
+      case '0':
+       found_zero = 1;
+       break;
+
       case 'p':
       case 'g': case 'r':
       default:
-       /* These mean a register is allowed.  Fail if so.  */
-       return 0;
+       reg_allowed = 1;
+       break;
       }
 
-  return found_zero;
+  if (found_zero && ! reg_allowed)
+    num_matching_alts++;
+
+  return num_matching_alts;
 }
 #endif /* REGISTER_CONSTRAINTS */
 \f