*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Fri, 17 Jul 1992 09:57:24 +0000 (05:57 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Fri, 17 Jul 1992 09:57:24 +0000 (05:57 -0400)
From-SVN: r1614

gcc/cse.c
gcc/libgcc2.c
gcc/reload.c
gcc/reload1.c

index 5b98cb82a4c21c0c0d4cd344b22754df9da0a5a0..e1c320973ed84d0eb0ed15e5d799e8cc1ac3e503 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -5814,6 +5814,10 @@ cse_insn (insn, in_libcall_block)
       sets[i].src_in_memory = hash_arg_in_memory;
       sets[i].src_in_struct = hash_arg_in_struct;
 
+#if 0
+      /* It is no longer clear why we used to do this, but it doesn't
+        appear to still be needed.  So let's try without it since this
+        code hurts cse'ing widened ops.  */
       /* If source is a perverse subreg (such as QI treated as an SI),
         treat it as volatile.  It may do the work of an SI in one context
         where the extra bits are not being used, but cannot replace an SI
@@ -5822,6 +5826,7 @@ cse_insn (insn, in_libcall_block)
          && (GET_MODE_SIZE (GET_MODE (src))
              > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
        sets[i].src_volatile = 1;
+#endif
 
       /* Locate all possible equivalent forms for SRC.  Try to replace
          SRC in the insn with each cheaper equivalent.
index 381cfd15d17949bf5857d89f14614218bcf7aac8..8a136c696f426aeebb63708522a94a6a6627f69b 100644 (file)
@@ -28,7 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    compiled for the target, and hence definitions concerning only the host
    do not apply.  */
 
-#include "tm.h"
+#include "tconfig.h"
 #ifndef L_trampoline
 #include "gstddef.h"
 #endif
@@ -1495,7 +1495,7 @@ __do_global_dtors ()
 #ifdef DO_GLOBAL_DTORS_BODY
   DO_GLOBAL_DTORS_BODY;
 #else
-  unsigned nptrs = (unsigned) __DTOR_LIST__[0];
+  unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
   unsigned i;
 
   /* Some systems place the number of pointers
index 62f8d673d8fdcda5bb391aa0d9f1c03505572c2c..c10672bc5705c5417983b60971dc87a99924a1b3 100644 (file)
@@ -207,6 +207,17 @@ static int n_replacements;
 static rtx memlocs[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
 static int n_memlocs;
 
+#ifdef SECONDARY_MEMORY_NEEDED
+
+/* Save MEMs needed to copy from one class of registers to another.  One MEM
+   is used per mode, but normally only one or two modes are ever used.  
+
+   We keep two versions, before and after register elimination.  */
+
+static rtx secondary_memlocs[NUM_MACHINE_MODES];
+static rtx secondary_memlocs_elim[NUM_MACHINE_MODES];
+#endif
+
 /* The instruction we are doing reloads for;
    so we can test whether a register dies in it.  */
 static rtx this_insn;
@@ -369,6 +380,73 @@ find_secondary_reload (x, reload_class, reload_mode, in_p, picode, pmode,
 }
 #endif /* HAVE_SECONDARY_RELOADS */
 \f
+#ifdef SECONDARY_MEMORY_NEEDED
+
+/* Return a memory location that will be used to copy X in mode MODE.  
+   If we haven't already made a location for this mode in this insn,
+   call find_reloads_address on the location being returned.  */
+
+rtx
+get_secondary_mem (x, mode)
+     rtx x;
+     enum machine_mode mode;
+{
+  rtx loc;
+  int mem_valid;
+
+  /* If MODE is narrower than a word, widen it.  This is required because
+     most machines that require these memory locations do not support
+     short load and stores from all registers (e.g., FP registers).  We could
+     possibly conditionalize this, but we lose nothing by doing the wider
+     mode.  */
+
+  if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
+    mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
+
+  /* If we already have made a MEM for this insn, return it.  */
+  if (secondary_memlocs_elim[(int) mode] != 0)
+    return secondary_memlocs_elim[(int) mode];
+
+  /* If this is the first time we've tried to get a MEM for this mode, 
+     allocate a new one.  `something_changed' in reload will get set
+     by noticing that the frame size has changed.  */
+
+  if (secondary_memlocs[(int) mode] == 0)
+    secondary_memlocs[(int) mode]
+      = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
+
+  /* Get a version of the address doing any eliminations needed.  If that
+     didn't give us a new MEM, make a new one if it isn't valid.  */
+
+  loc = eliminate_regs (secondary_memlocs[(int) mode], 0, NULL_RTX);
+  mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
+
+  if (! mem_valid && loc == secondary_memlocs[(int) mode])
+    loc = copy_rtx (loc);
+
+  /* The only time the call below will do anything is if the stack
+     offset is too large.  In that case IND_LEVELS doesn't matter, so we
+     can just pass a zero.  */
+  if (! mem_valid)
+    find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0), x, 0);
+
+  secondary_memlocs_elim[(int) mode] = loc;
+
+  return loc;
+}
+
+/* Clear any secondary memory locations we've made.  */
+
+void
+clear_secondary_mem ()
+{
+  int i;
+
+  for (i = 0; i < NUM_MACHINE_MODES; i++)
+    secondary_memlocs[i] = 0;
+}
+#endif /* SECONDARY_MEMORY_NEEDED */
+\f
 /* Record one (sometimes two) reload that needs to be performed.
    IN is an rtx saying where the data are to be found before this instruction.
    OUT says where they must be stored after the instruction.
@@ -569,6 +647,21 @@ push_reload (in, out, inloc, outloc, class,
       && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
     dont_share = 1;
 
+  /* If IN is a SUBREG of a hard register, make a new REG.  This
+     simplifies some of the cases below.  */
+
+  if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
+      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
+    in = gen_rtx (REG, GET_MODE (in),
+                 REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
+
+  /* Similarly for OUT.  */
+  if (out != 0 && GET_CODE (out) == SUBREG
+      && GET_CODE (SUBREG_REG (out)) == REG
+      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
+    out = gen_rtx (REG, GET_MODE (out),
+                 REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
+
   /* Narrow down the class of register wanted if that is
      desirable on this machine for efficiency.  */
   if (in != 0)
@@ -858,6 +951,19 @@ push_reload (in, out, inloc, outloc, class,
 
              n_reloads++;
              i = n_reloads;
+
+#ifdef SECONDARY_MEMORY_NEEDED
+             /* If we need a memory location to copy between the two
+                reload regs, set it up now.  */
+
+             if (in != 0 && secondary_icode == CODE_FOR_nothing
+                 && SECONDARY_MEMORY_NEEDED (secondary_class, class, inmode))
+               get_secondary_mem (in, inmode);
+
+             if (out != 0 && secondary_icode == CODE_FOR_nothing
+                 && SECONDARY_MEMORY_NEEDED (class, secondary_class, outmode))
+               get_secondary_mem (out, outmode);
+#endif
            }
        }
 #endif
@@ -883,6 +989,21 @@ push_reload (in, out, inloc, outloc, class,
       reload_secondary_p[i] = 0;
 
       n_reloads++;
+
+#ifdef SECONDARY_MEMORY_NEEDED
+      /* If a memory location is needed for the copy, make one.  */
+      if (in != 0 && GET_CODE (in) == REG
+         && REGNO (in) < FIRST_PSEUDO_REGISTER
+         && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
+                                    class, inmode))
+       get_secondary_mem (in, inmode);
+
+      if (out != 0 && GET_CODE (out) == REG
+         && REGNO (out) < FIRST_PSEUDO_REGISTER
+         && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),
+                                     outmode))
+       get_secondary_mem (out, outmode);
+#endif
     }
   else
     {
@@ -1829,6 +1950,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
     no_output_reloads = 1;
 #endif
      
+#ifdef SECONDARY_MEMORY_NEEDED
+  /* The eliminated forms of any secondary memory locations are per-insn, so
+     clear them out here.  */
+
+  bzero (secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+#endif
+
   /* Find what kind of insn this is.  NOPERANDS gets number of operands.
      Make OPERANDS point to a vector of operand values.
      Make OPERAND_LOCS point to a vector of pointers to
index 37b7cd749a880348b77c1bf385c6021ec75dd33b..5451ab6590b7cc336fbab112a1c47393f3f4cca2 100644 (file)
@@ -513,6 +513,11 @@ reload (first, global, dumpfile)
   for (i = 0; i < N_REG_CLASSES; i++)
     basic_block_needs[i] = 0;
 
+#ifdef SECONDARY_MEMORY_NEEDED
+  /* Initialize the secondary memory table.  */
+  clear_secondary_mem ();
+#endif
+
   /* Remember which hard regs appear explicitly
      before we merge into `regs_ever_live' the ones in which
      pseudo regs have been allocated.  */
@@ -786,6 +791,7 @@ reload (first, global, dumpfile)
       rtx max_groups_insn[N_REG_CLASSES];
       rtx max_nongroups_insn[N_REG_CLASSES];
       rtx x;
+      int starting_frame_size = get_frame_size ();
 
       something_changed = 0;
       bzero (max_needs, sizeof max_needs);
@@ -1302,6 +1308,11 @@ reload (first, global, dumpfile)
          /* Note that there is a continue statement above.  */
        }
 
+      /* If we allocated any new memory locations, make another pass
+        since it might have changed elimination offsets.  */
+      if (starting_frame_size != get_frame_size ())
+       something_changed = 1;
+
       /* If we have caller-saves, set up the save areas and see if caller-save
         will need a spill register.  */
 
@@ -5298,8 +5309,35 @@ emit_reload_insns (insn)
 
          /* Output the last reload insn.  */
          if (! special)
-           emit_insn_before (gen_move_insn (old, reloadreg),
-                             first_output_reload_insn);
+           {
+#ifdef SECONDARY_MEMORY_NEEDED
+             /* If we need a memory location to do the move, do it that way.  */
+             if (GET_CODE (old) == REG && REGNO (old) < FIRST_PSEUDO_REGISTER
+                 && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (old)),
+                                             REGNO_REG_CLASS (REGNO (reloadreg)),
+                                             GET_MODE (reloadreg)))
+               {
+                 /* Get the memory to use and rewrite both registers to
+                    its mode.  */
+                 rtx loc = get_secondary_mem (old, GET_MODE (reloadreg));
+
+                 if (GET_MODE (loc) != GET_MODE (reloadreg))
+                   reloadreg = gen_rtx (REG, GET_MODE (loc),
+                                        REGNO (reloadreg));
+
+                 if (GET_MODE (loc) != GET_MODE (old))
+                   old = gen_rtx (REG, GET_MODE (loc), REGNO (old));
+
+                 emit_insn_before (gen_move_insn (loc, reloadreg),
+                                   first_output_reload_insn);
+                 emit_insn_before (gen_move_insn (old, loc),
+                                   first_output_reload_insn);
+               }
+             else
+#endif
+               emit_insn_before (gen_move_insn (old, reloadreg),
+                                 first_output_reload_insn);
+           }
 
 #ifdef PRESERVE_DEATH_INFO_REGNO_P
          /* If final will look at death notes for this reg,
@@ -5608,6 +5646,27 @@ gen_input_reload (reloadreg, in, before_insn)
       emit_insn_before (gen_add2_insn (reloadreg, op1), before_insn);
     }
 
+#ifdef SECONDARY_MEMORY_NEEDED
+  /* If we need a memory location to do the move, do it that way.  */
+  else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
+          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
+                                      REGNO_REG_CLASS (REGNO (reloadreg)),
+                                      GET_MODE (reloadreg)))
+    {
+      /* Get the memory to use and rewrite both registers to its mode.  */
+      rtx loc = get_secondary_mem (in, GET_MODE (reloadreg));
+
+      if (GET_MODE (loc) != GET_MODE (reloadreg))
+       reloadreg = gen_rtx (REG, GET_MODE (loc), REGNO (reloadreg));
+
+      if (GET_MODE (loc) != GET_MODE (in))
+       in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
+
+      emit_insn_before (gen_move_insn (reloadreg, loc), before_insn);
+      emit_insn_before (gen_move_insn (loc, in), before_insn);
+    }
+#endif
+
   /* If IN is a simple operand, use gen_move_insn.  */
   else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
     emit_insn_before (gen_move_insn (reloadreg, in), before_insn);