OSDN Git Service

Fix install doc problems reported by Jean-Paul Rigault
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 71c1afa..06df026 100644 (file)
@@ -268,15 +268,15 @@ enum insn_code reload_out_optab[NUM_MACHINE_MODES];
 /* This obstack is used for allocation of rtl during register elimination.
    The allocated storage can be freed once find_reloads has processed the
    insn.  */
-struct obstack reload_obstack;
+static struct obstack reload_obstack;
 
 /* Points to the beginning of the reload_obstack.  All insn_chain structures
    are allocated first.  */
-char *reload_startobj;
+static char *reload_startobj;
 
 /* The point after all insn_chain structures.  Used to quickly deallocate
    memory allocated in copy_reloads during calculate_needs_all_insns.  */
-char *reload_firstobj;
+static char *reload_firstobj;
 
 /* This points before all local rtl generated by register elimination.
    Used to quickly free all memory after processing one insn.  */
@@ -615,7 +615,7 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
 /* Set during calculate_needs if an insn needs register elimination.  */
 static int something_needs_elimination;
 /* Set during calculate_needs if an insn needs an operand changed.  */
-int something_needs_operands_changed;
+static int something_needs_operands_changed;
 
 /* Nonzero means we couldn't get enough spill regs.  */
 static int failure;
@@ -740,8 +740,20 @@ reload (rtx first, int global)
                     that is not a legitimate memory operand.  As later
                     stages of reload assume that all addresses found
                     in the reg_equiv_* arrays were originally legitimate,
-                    we ignore such REG_EQUIV notes.  */
-                 if (memory_operand (x, VOIDmode))
+
+                    It can also happen that a REG_EQUIV note contains a
+                    readonly memory location.  If the destination pseudo
+                    is set from some other value (typically a different
+                    pseudo), and the destination pseudo does not get a
+                    hard reg, then reload will replace the destination
+                    pseudo with its equivalent memory location.  This
+                    is horribly bad as it creates a store to a readonly
+                    memory location and a runtime segfault.  To avoid
+                    this problem we reject readonly memory locations
+                    for equivalences.  This is overly conservative as
+                    we could find all sets of the destination pseudo
+                    and remove them as they should be redundant.  */
+                 if (memory_operand (x, VOIDmode) && ! MEM_READONLY_P (x))
                    {
                      /* Always unshare the equivalence, so we can
                         substitute into this insn without touching the
@@ -1078,8 +1090,8 @@ reload (rtx first, int global)
       CLEAR_REGNO_REG_SET (bb->global_live_at_start,
                           HARD_FRAME_POINTER_REGNUM);
 
-  /* Come here (with failure set nonzero) if we can't get enough spill regs
-     and we decide not to abort about it.  */
+  /* Come here (with failure set nonzero) if we can't get enough spill
+     regs.  */
  failed:
 
   CLEAR_REG_SET (&spilled_pseudos);
@@ -1174,6 +1186,19 @@ reload (rtx first, int global)
          replace_pseudos_in (& XEXP (PATTERN (insn), 0),
                              VOIDmode, PATTERN (insn));
 
+       /* Discard obvious no-ops, even without -O.  This optimization
+          is fast and doesn't interfere with debugging.  */
+       if (NONJUMP_INSN_P (insn)
+           && GET_CODE (PATTERN (insn)) == SET
+           && REG_P (SET_SRC (PATTERN (insn)))
+           && REG_P (SET_DEST (PATTERN (insn)))
+           && (REGNO (SET_SRC (PATTERN (insn)))
+               == REGNO (SET_DEST (PATTERN (insn)))))
+         {
+           delete_insn (insn);
+           continue;
+         }
+
        pnote = &REG_NOTES (insn);
        while (*pnote != 0)
          {
@@ -1208,10 +1233,10 @@ reload (rtx first, int global)
 
       if (size > STACK_CHECK_MAX_FRAME_SIZE)
        {
-         warning ("frame size too large for reliable stack checking");
+         warning (0, "frame size too large for reliable stack checking");
          if (! verbose_warned)
            {
-             warning ("try reducing the number of local variables");
+             warning (0, "try reducing the number of local variables");
              verbose_warned = 1;
            }
        }
@@ -1861,7 +1886,6 @@ delete_caller_save_insns (void)
 static void
 spill_failure (rtx insn, enum reg_class class)
 {
-  static const char *const reg_class_names[] = REG_CLASS_NAMES;
   if (asm_noperands (PATTERN (insn)) >= 0)
     error_for_asm (insn, "can't find a register in class %qs while "
                   "reloading %<asm%>",
@@ -4035,7 +4059,7 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
   unsigned int nr;
 
   /* note_stores does give us subregs of hard regs,
-     subreg_regno_offset will abort if it is not a hard reg.  */
+     subreg_regno_offset requires a hard reg.  */
   while (GET_CODE (x) == SUBREG)
     {
       /* We ignore the subreg offset when calculating the regno,
@@ -4667,19 +4691,19 @@ reloads_conflict (int r1, int r2)
 \f
 /* Indexed by reload number, 1 if incoming value
    inherited from previous insns.  */
-char reload_inherited[MAX_RELOADS];
+static char reload_inherited[MAX_RELOADS];
 
 /* For an inherited reload, this is the insn the reload was inherited from,
    if we know it.  Otherwise, this is 0.  */
-rtx reload_inheritance_insn[MAX_RELOADS];
+static rtx reload_inheritance_insn[MAX_RELOADS];
 
 /* If nonzero, this is a place to get the value of the reload,
    rather than using reload_in.  */
-rtx reload_override_in[MAX_RELOADS];
+static rtx reload_override_in[MAX_RELOADS];
 
 /* For each reload, the hard register number of the register used,
    or -1 if we did not need a register for this reload.  */
-int reload_spill_index[MAX_RELOADS];
+static int reload_spill_index[MAX_RELOADS];
 
 /* Subroutine of free_for_value_p, used to check a single register.
    START_REGNO is the starting regno of the full reload register
@@ -4939,11 +4963,11 @@ free_for_value_p (int regno, enum machine_mode mode, int opnum,
 }
 
 /* Return nonzero if the rtx X is invariant over the current function.  */
-/* ??? Actually, the places where we use this expect exactly what
* is tested here, and not everything that is function invariant.  In
* particular, the frame pointer and arg pointer are special cased;
- * pic_offset_table_rtx is not, and this will cause aborts when we
*             go to spill these things to memory.  */
+/* ??? Actually, the places where we use this expect exactly what is
  tested here, and not everything that is function invariant.  In
  particular, the frame pointer and arg pointer are special cased;
+   pic_offset_table_rtx is not, and we must not spill these things to
  memory.  */
 
 static int
 function_invariant_p (rtx x)
@@ -5412,19 +5436,18 @@ choose_reload_regs (struct insn_chain *chain)
                    need_mode = mode;
                  else
                    need_mode
-                     = smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
+                     = smallest_mode_for_size (GET_MODE_BITSIZE (mode)
+                                               + byte * BITS_PER_UNIT,
                                                GET_MODE_CLASS (mode));
 
-                 if (
-#ifdef CANNOT_CHANGE_MODE_CLASS
-                     (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
-                                                 need_mode)
-                      &&
-#endif
-                     (GET_MODE_SIZE (GET_MODE (last_reg))
+                 if ((GET_MODE_SIZE (GET_MODE (last_reg))
                       >= GET_MODE_SIZE (need_mode))
 #ifdef CANNOT_CHANGE_MODE_CLASS
-                     )
+                     /* Verify that the register in "i" can be obtained
+                        from LAST_REG.  */
+                     && !REG_CANNOT_CHANGE_MODE_P (REGNO (last_reg),
+                                                   GET_MODE (last_reg),
+                                                   mode)
 #endif
                      && reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
@@ -5590,6 +5613,15 @@ choose_reload_regs (struct insn_chain *chain)
                      gcc_assert (GET_CODE (equiv) == SUBREG);
                      regno = subreg_regno (equiv);
                      equiv = gen_rtx_REG (rld[r].mode, regno);
+                     /* If we choose EQUIV as the reload register, but the
+                        loop below decides to cancel the inheritance, we'll
+                        end up reloading EQUIV in rld[r].mode, not the mode
+                        it had originally.  That isn't safe when EQUIV isn't
+                        available as a spill register since its value might
+                        still be live at this point.  */
+                     for (i = regno; i < regno + (int) rld[r].nregs; i++)
+                       if (TEST_HARD_REG_BIT (reload_reg_unavailable, i))
+                         equiv = 0;
                    }
                }
 
@@ -6055,10 +6087,10 @@ merge_assigned_reloads (rtx insn)
                        || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
                       ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
 
-                 /* Check to see if we accidentally converted two reloads
-                    that use the same reload register with different inputs
-                    to the same type.  If so, the resulting code won't work,
-                    so abort.  */
+                 /* Check to see if we accidentally converted two
+                    reloads that use the same reload register with
+                    different inputs to the same type.  If so, the
+                    resulting code won't work.  */
                  if (rld[j].reg_rtx)
                    for (k = 0; k < j; k++)
                      gcc_assert (rld[k].in == 0 || rld[k].reg_rtx == 0