Small reload cleanups
authorcrux <crux@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Oct 1999 13:45:31 +0000 (13:45 +0000)
committercrux <crux@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Oct 1999 13:45:31 +0000 (13:45 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30193 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/reload.c
gcc/reload1.c

index aaa3007..8351057 100644 (file)
@@ -1,3 +1,16 @@
+Tue Oct 26 15:42:56 1999  Bernd Schmidt  <bernds@cygnus.co.uk>
+
+       * reload.c (find_reloads): Compute mode and nregs fields of all
+       reloads.
+       * reload1.c (calculate_needs_all_insns): Simplify a bit.
+       (calculate_needs): Use precomputed mode/nregs values.
+       (allocate_reload_reg): Likewise.
+       Break out two...
+       (failed_reload, set_reload_reg): ... new functions.
+       (choose_reload_regs_init): New function, mostly broken out from...
+       (choose_reload_regs): ... here.  Lose all the save_xxx nonsense.
+       Also lose one #if 0 block.
+
 Tue Oct 26 02:48:32 1999  Marc Espie <espie@cvs.openbsd.org>
 
        * Makefile.in (AR_FOR_TARGET, RANLIB_FOR_TARGET):  Fix target name 
index 011d0a9..bd32ba3 100644 (file)
@@ -4174,6 +4174,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        }
     }
 
+  /* Compute reload_mode and reload_nregs.  */
+  for (i = 0; i < n_reloads; i++)
+    {
+      rld[i].mode
+       = (rld[i].inmode == VOIDmode
+          || (GET_MODE_SIZE (rld[i].outmode)
+              > GET_MODE_SIZE (rld[i].inmode)))
+         ? rld[i].outmode : rld[i].inmode;
+
+      rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
+    }
+
   return retval;
 }
 
index 94aea4a..0528860 100644 (file)
@@ -424,6 +424,7 @@ static int reload_reg_free_for_value_p      PROTO((int, int, enum reload_type, rtx, r
 static int reload_reg_reaches_end_p    PROTO((int, int, enum reload_type));
 static int allocate_reload_reg         PROTO((struct insn_chain *, int, int,
                                               int));
+static void choose_reload_regs_init    PROTO((struct insn_chain *, rtx *));
 static void choose_reload_regs         PROTO((struct insn_chain *));
 static void merge_assigned_reloads     PROTO((rtx));
 static void emit_reload_insns          PROTO((struct insn_chain *));
@@ -1325,17 +1326,18 @@ calculate_needs_all_insns (global)
      int global;
 {
   struct insn_chain **pprev_reload = &insns_need_reload;
-  struct insn_chain **pchain;
+  struct insn_chain *chain;
 
   something_needs_elimination = 0;
 
-  for (pchain = &reload_insn_chain; *pchain != 0; pchain = &(*pchain)->next)
+  for (chain = reload_insn_chain; chain != 0; chain = chain->next)
     {
-      rtx insn;
-      struct insn_chain *chain;
+      rtx insn = chain->insn;
 
-      chain = *pchain;
-      insn = chain->insn;
+      /* Clear out the shortcuts, in case they were set last time through.  */
+      chain->need_elim = 0;
+      chain->need_reload = 0;
+      chain->need_operand_change = 0;
 
       /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
         include REG_LABEL), we need to see what effects this has on the
@@ -1359,14 +1361,7 @@ calculate_needs_all_insns (global)
          if (set && GET_CODE (SET_DEST (set)) == REG
              && reg_renumber[REGNO (SET_DEST (set))] < 0
              && reg_equiv_constant[REGNO (SET_DEST (set))])
-           {
-             /* Must clear out the shortcuts, in case they were set last
-                time through.  */
-             chain->need_elim = 0;
-             chain->need_reload = 0;
-             chain->need_operand_change = 0;
-             continue;
-           }
+           continue;
 
          /* If needed, eliminate any eliminable registers.  */
          if (num_eliminable || num_eliminable_invariants)
@@ -1495,10 +1490,8 @@ calculate_needs (chain)
              && ! rld[i].secondary_p))
        continue;
 
-      mode = rld[i].inmode;
-      if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-       mode = rld[i].outmode;
-      size = CLASS_MAX_NREGS (class, mode);
+      mode = rld[i].mode;
+      size = rld[i].nregs;
 
       /* Decide which time-of-use to count this reload for.  */
       switch (rld[i].when_needed)
@@ -5488,6 +5481,78 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
   return 1;
 }
 
+/* Give an error message saying we failed to find a reload for INSN,
+   and clear out reload R.  */
+static void
+failed_reload (insn, r)
+     rtx insn;
+     int r;
+{
+  if (asm_noperands (PATTERN (insn)) < 0)
+    /* It's the compiler's fault.  */
+    fatal_insn ("Could not find a spill register", insn);
+
+  /* It's the user's fault; the operand's mode and constraint
+     don't match.  Disable this reload so we don't crash in final.  */
+  error_for_asm (insn,
+                "`asm' operand constraint incompatible with operand size");
+  rld[r].in = 0;
+  rld[r].out = 0;
+  rld[r].reg_rtx = 0;
+  rld[r].optional = 1;
+  rld[r].secondary_p = 1;
+}
+
+/* I is the index in SPILL_REG_RTX of the reload register we are to allocate
+   for reload R.  If it's valid, get an rtx for it.  Return nonzero if
+   successful.  */
+static int
+set_reload_reg (i, r)
+     int i, r;
+{
+  int regno;
+  rtx reg = spill_reg_rtx[i];
+
+  if (reg == 0 || GET_MODE (reg) != rld[r].mode)
+    spill_reg_rtx[i] = reg
+      = gen_rtx_REG (rld[r].mode, spill_regs[i]);
+
+  regno = true_regnum (reg);
+
+  /* Detect when the reload reg can't hold the reload mode.
+     This used to be one `if', but Sequent compiler can't handle that.  */
+  if (HARD_REGNO_MODE_OK (regno, rld[r].mode))
+    {
+      enum machine_mode test_mode = VOIDmode;
+      if (rld[r].in)
+       test_mode = GET_MODE (rld[r].in);
+      /* If rld[r].in has VOIDmode, it means we will load it
+        in whatever mode the reload reg has: to wit, rld[r].mode.
+        We have already tested that for validity.  */
+      /* Aside from that, we need to test that the expressions
+        to reload from or into have modes which are valid for this
+        reload register.  Otherwise the reload insns would be invalid.  */
+      if (! (rld[r].in != 0 && test_mode != VOIDmode
+            && ! HARD_REGNO_MODE_OK (regno, test_mode)))
+       if (! (rld[r].out != 0
+              && ! HARD_REGNO_MODE_OK (regno, GET_MODE (rld[r].out))))
+         {
+           /* The reg is OK.  */
+           last_spill_reg = i;
+
+           /* Mark as in use for this insn the reload regs we use
+              for this.  */
+           mark_reload_reg_in_use (spill_regs[i], rld[r].opnum,
+                                   rld[r].when_needed, rld[r].mode);
+
+           rld[r].reg_rtx = reg;
+           reload_spill_index[r] = spill_regs[i];
+           return 1;
+         }
+    }
+  return 0;
+}
+
 /* Find a spill register to use as a reload register for reload R.
    LAST_RELOAD is non-zero if this is the last reload for the insn being
    processed.
@@ -5505,8 +5570,7 @@ allocate_reload_reg (chain, r, last_reload, noerror)
      int noerror;
 {
   rtx insn = chain->insn;
-  int i, pass, count, regno;
-  rtx new;
+  int i, pass, count;
 
   /* If we put this reload ahead, thinking it is a group,
      then insist on finding a group.  Otherwise we can grab a
@@ -5589,7 +5653,7 @@ allocate_reload_reg (chain, r, last_reload, noerror)
                 (on 68000) got us two FP regs.  If NR is 1,
                 we would reject both of them.  */
              if (force_group)
-               nr = CLASS_MAX_NREGS (rld[r].class, rld[r].mode);
+               nr = rld[r].nregs;
              /* If we need only one reg, we have already won.  */
              if (nr == 1)
                {
@@ -5605,7 +5669,7 @@ allocate_reload_reg (chain, r, last_reload, noerror)
              if (! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regnum))
                while (nr > 1)
                  {
-                   regno = regnum + nr - 1;
+                   int regno = regnum + nr - 1;
                    if (!(TEST_HARD_REG_BIT (reg_class_contents[class], regno)
                          && spill_reg_order[regno] >= 0
                          && reload_reg_free_p (regno, rld[r].opnum,
@@ -5633,106 +5697,31 @@ allocate_reload_reg (chain, r, last_reload, noerror)
       goto failure;
     }
 
-  /* I is the index in SPILL_REG_RTX of the reload register we are to
-     allocate.  Get an rtx for it and find its register number.  */
-
-  new = spill_reg_rtx[i];
-
-  if (new == 0 || GET_MODE (new) != rld[r].mode)
-    spill_reg_rtx[i] = new
-      = gen_rtx_REG (rld[r].mode, spill_regs[i]);
-
-  regno = true_regnum (new);
-
-  /* Detect when the reload reg can't hold the reload mode.
-     This used to be one `if', but Sequent compiler can't handle that.  */
-  if (HARD_REGNO_MODE_OK (regno, rld[r].mode))
-    {
-      enum machine_mode test_mode = VOIDmode;
-      if (rld[r].in)
-       test_mode = GET_MODE (rld[r].in);
-      /* If rld[r].in has VOIDmode, it means we will load it
-        in whatever mode the reload reg has: to wit, rld[r].mode.
-        We have already tested that for validity.  */
-      /* Aside from that, we need to test that the expressions
-        to reload from or into have modes which are valid for this
-        reload register.  Otherwise the reload insns would be invalid.  */
-      if (! (rld[r].in != 0 && test_mode != VOIDmode
-            && ! HARD_REGNO_MODE_OK (regno, test_mode)))
-       if (! (rld[r].out != 0
-              && ! HARD_REGNO_MODE_OK (regno, GET_MODE (rld[r].out))))
-         {
-           /* The reg is OK.  */
-           last_spill_reg = i;
-
-           /* Mark as in use for this insn the reload regs we use
-              for this.  */
-           mark_reload_reg_in_use (spill_regs[i], rld[r].opnum,
-                                   rld[r].when_needed, rld[r].mode);
-
-           rld[r].reg_rtx = new;
-           reload_spill_index[r] = spill_regs[i];
-           return 1;
-         }
-    }
+  if (set_reload_reg (i, r))
+    return 1;
 
   /* The reg is not OK.  */
   if (noerror)
     return 0;
 
  failure:
-  if (asm_noperands (PATTERN (insn)) < 0)
-    /* It's the compiler's fault.  */
-    fatal_insn ("Could not find a spill register", insn);
-
-  /* It's the user's fault; the operand's mode and constraint
-     don't match.  Disable this reload so we don't crash in final.  */
-  error_for_asm (insn,
-                "`asm' operand constraint incompatible with operand size");
-  rld[r].in = 0;
-  rld[r].out = 0;
-  rld[r].reg_rtx = 0;
-  rld[r].optional = 1;
-  rld[r].secondary_p = 1;
+  failed_reload (insn, r);
 
   return 1;
 }
 \f
-/* Assign hard reg targets for the pseudo-registers we must reload
-   into hard regs for this insn.
-   Also output the instructions to copy them in and out of the hard regs.
-
-   For machines with register classes, we are responsible for
-   finding a reload reg in the proper class.  */
-
+/* Initialize all the tables needed to allocate reload registers.
+   CHAIN is the insn currently being processed; SAVE_RELOAD_REG_RTX
+   is the array we use to restore the reg_rtx field for every reload.  */
 static void
-choose_reload_regs (chain)
+choose_reload_regs_init (chain, save_reload_reg_rtx)
      struct insn_chain *chain;
+     rtx *save_reload_reg_rtx;
 {
-  rtx insn = chain->insn;
-  register int i, j;
-  int max_group_size = 1;
-  enum reg_class group_class = NO_REGS;
-  int inheritance;
-  int pass;
+  int i;
 
-  rtx save_reload_reg_rtx[MAX_RELOADS];
-  char save_reload_inherited[MAX_RELOADS];
-  rtx save_reload_inheritance_insn[MAX_RELOADS];
-  rtx save_reload_override_in[MAX_RELOADS];
-  int save_reload_spill_index[MAX_RELOADS];
-  HARD_REG_SET save_reload_reg_used;
-  HARD_REG_SET save_reload_reg_used_in_input_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_inpaddr_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_output_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_outaddr_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_input[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_output[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_op_addr;
-  HARD_REG_SET save_reload_reg_used_in_op_addr_reload;
-  HARD_REG_SET save_reload_reg_used_in_insn;
-  HARD_REG_SET save_reload_reg_used_in_other_addr;
-  HARD_REG_SET save_reload_reg_used_at_all;
+  for (i = 0; i < n_reloads; i++)
+    rld[i].reg_rtx = save_reload_reg_rtx[i];
 
   bzero (reload_inherited, MAX_RELOADS);
   bzero ((char *) reload_inheritance_insn, MAX_RELOADS * sizeof (rtx));
@@ -5767,27 +5756,35 @@ choose_reload_regs (chain)
 
   IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
 
-#if 0  /* Not needed, now that we can always retry without inheritance.  */
-  /* See if we have more mandatory reloads than spill regs.
-     If so, then we cannot risk optimizations that could prevent
-     reloads from sharing one spill register.
+  CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
 
-     Since we will try finding a better register than reload_reg_rtx
-     unless it is equal to reload_in or reload_out, count such reloads.  */
+  for (i = 0; i < n_reloads; i++)
+    /* If we have already decided to use a certain register,
+       don't use it in another way.  */
+    if (rld[i].reg_rtx)
+      mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
+                             rld[i].when_needed, rld[i].mode);
+}
 
-  {
-    int tem = 0;
-    for (j = 0; j < n_reloads; j++)
-      if (! rld[j].optional
-         && (rld[j].in != 0 || rld[j].out != 0 || rld[j].secondary_p)
-         && (rld[j].reg_rtx == 0
-             || (! rtx_equal_p (rld[j].reg_rtx, rld[j].in)
-                 && ! rtx_equal_p (rld[j].reg_rtx, rld[j].out))))
-       tem++;
-    if (tem > n_spills)
-      must_reuse = 1;
-  }
-#endif
+/* Assign hard reg targets for the pseudo-registers we must reload
+   into hard regs for this insn.
+   Also output the instructions to copy them in and out of the hard regs.
+
+   For machines with register classes, we are responsible for
+   finding a reload reg in the proper class.  */
+
+static void
+choose_reload_regs (chain)
+     struct insn_chain *chain;
+{
+  rtx insn = chain->insn;
+  register int i, j;
+  int max_group_size = 1;
+  enum reg_class group_class = NO_REGS;
+  int inheritance;
+  int pass;
+
+  rtx save_reload_reg_rtx[MAX_RELOADS];
 
   /* In order to be certain of getting the registers we need,
      we must sort the reloads into order of increasing register class.
@@ -5803,13 +5800,6 @@ choose_reload_regs (chain)
       reload_order[j] = j;
       reload_spill_index[j] = -1;
 
-      rld[j].mode = ((rld[j].inmode == VOIDmode
-                     || (GET_MODE_SIZE (rld[j].outmode)
-                         > GET_MODE_SIZE (rld[j].inmode)))
-                    ? rld[j].outmode : rld[j].inmode);
-
-      rld[j].nregs = CLASS_MAX_NREGS (rld[j].class, rld[j].mode);
-
       if (rld[j].nregs > 1)
        {
          max_group_size = MAX (rld[j].nregs, max_group_size);
@@ -5817,53 +5807,11 @@ choose_reload_regs (chain)
        }
 
       save_reload_reg_rtx[j] = rld[j].reg_rtx;
-      /* If we have already decided to use a certain register,
-        don't use it in another way.  */
-      if (rld[j].reg_rtx)
-       mark_reload_reg_in_use (REGNO (rld[j].reg_rtx), rld[j].opnum,
-                               rld[j].when_needed, rld[j].mode);
     }
 
   if (n_reloads > 1)
     qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower);
 
-  bcopy (reload_inherited, save_reload_inherited, sizeof reload_inherited);
-  bcopy ((char *) reload_inheritance_insn,
-        (char *) save_reload_inheritance_insn,
-        sizeof reload_inheritance_insn);
-  bcopy ((char *) reload_override_in, (char *) save_reload_override_in,
-        sizeof reload_override_in);
-  bcopy ((char *) reload_spill_index, (char *) save_reload_spill_index,
-        sizeof reload_spill_index);
-  COPY_HARD_REG_SET (save_reload_reg_used, reload_reg_used);
-  COPY_HARD_REG_SET (save_reload_reg_used_at_all, reload_reg_used_at_all);
-  COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr,
-                    reload_reg_used_in_op_addr);
-
-  COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr_reload,
-                    reload_reg_used_in_op_addr_reload);
-
-  COPY_HARD_REG_SET (save_reload_reg_used_in_insn,
-                    reload_reg_used_in_insn);
-  COPY_HARD_REG_SET (save_reload_reg_used_in_other_addr,
-                    reload_reg_used_in_other_addr);
-
-  for (i = 0; i < reload_n_operands; i++)
-    {
-      COPY_HARD_REG_SET (save_reload_reg_used_in_output[i],
-                        reload_reg_used_in_output[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_input[i],
-                        reload_reg_used_in_input[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_input_addr[i],
-                        reload_reg_used_in_input_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_inpaddr_addr[i],
-                        reload_reg_used_in_inpaddr_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_output_addr[i],
-                        reload_reg_used_in_output_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_outaddr_addr[i],
-                        reload_reg_used_in_outaddr_addr[i]);
-    }
-
   /* If -O, try first with inheritance, then turning it off.
      If not -O, don't do inheritance.
      Using inheritance when not optimizing leads to paradoxes
@@ -5872,6 +5820,8 @@ choose_reload_regs (chain)
 
   for (inheritance = optimize > 0; inheritance >= 0; inheritance--)
     {
+      choose_reload_regs_init (chain, save_reload_reg_rtx);
+
       /* Process the reloads in order of preference just found.
         Beyond this point, subregs can be found in reload_reg_rtx.
 
@@ -5890,8 +5840,6 @@ choose_reload_regs (chain)
         Then make a second pass over the reloads to allocate any reloads
         that haven't been given registers yet.  */
 
-      CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
-
       for (j = 0; j < n_reloads; j++)
        {
          register int r = reload_order[j];
@@ -6070,8 +6018,7 @@ choose_reload_regs (chain)
                                  && rld[r].out
                                  && ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
                              /* Don't clobber the frame pointer.  */
-                             || (i == HARD_FRAME_POINTER_REGNUM
-                                 && rld[r].out)
+                             || (i == HARD_FRAME_POINTER_REGNUM && rld[r].out)
                              /* Don't really use the inherited spill reg
                                 if we need it wider than we've got it.  */
                              || (GET_MODE_SIZE (rld[r].mode)
@@ -6083,8 +6030,7 @@ choose_reload_regs (chain)
                                 register, stay with it - that leaves the
                                 inherited register for subsequent reloads.  */
                              || (rld[r].out && rld[r].reg_rtx
-                                 && rtx_equal_p (rld[r].out,
-                                                 rld[r].reg_rtx)))
+                                 && rtx_equal_p (rld[r].out, rld[r].reg_rtx)))
                            {
                              reload_override_in[r] = last_reg;
                              reload_inheritance_insn[r]
@@ -6314,45 +6260,6 @@ choose_reload_regs (chain)
        break;
 
       /* Loop around and try without any inheritance.  */
-      /* First undo everything done by the failed attempt
-        to allocate with inheritance.  */
-      for (i = 0; i < n_reloads; i++)
-       rld[i].reg_rtx = save_reload_reg_rtx[i];
-      bcopy ((char *) save_reload_inherited, (char *) reload_inherited,
-            sizeof reload_inherited);
-      bcopy ((char *) save_reload_inheritance_insn,
-            (char *) reload_inheritance_insn,
-            sizeof reload_inheritance_insn);
-      bcopy ((char *) save_reload_override_in, (char *) reload_override_in,
-            sizeof reload_override_in);
-      bcopy ((char *) save_reload_spill_index, (char *) reload_spill_index,
-            sizeof reload_spill_index);
-      COPY_HARD_REG_SET (reload_reg_used, save_reload_reg_used);
-      COPY_HARD_REG_SET (reload_reg_used_at_all, save_reload_reg_used_at_all);
-      COPY_HARD_REG_SET (reload_reg_used_in_op_addr,
-                        save_reload_reg_used_in_op_addr);
-      COPY_HARD_REG_SET (reload_reg_used_in_op_addr_reload,
-                        save_reload_reg_used_in_op_addr_reload);
-      COPY_HARD_REG_SET (reload_reg_used_in_insn,
-                        save_reload_reg_used_in_insn);
-      COPY_HARD_REG_SET (reload_reg_used_in_other_addr,
-                        save_reload_reg_used_in_other_addr);
-
-      for (i = 0; i < reload_n_operands; i++)
-       {
-         COPY_HARD_REG_SET (reload_reg_used_in_input[i],
-                            save_reload_reg_used_in_input[i]);
-         COPY_HARD_REG_SET (reload_reg_used_in_output[i],
-                            save_reload_reg_used_in_output[i]);
-         COPY_HARD_REG_SET (reload_reg_used_in_input_addr[i],
-                            save_reload_reg_used_in_input_addr[i]);
-         COPY_HARD_REG_SET (reload_reg_used_in_inpaddr_addr[i],
-                            save_reload_reg_used_in_inpaddr_addr[i]);
-         COPY_HARD_REG_SET (reload_reg_used_in_output_addr[i],
-                            save_reload_reg_used_in_output_addr[i]);
-         COPY_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i],
-                            save_reload_reg_used_in_outaddr_addr[i]);
-       }
     }
 
   /* If we thought we could inherit a reload, because it seemed that