OSDN Git Service

* tree-ssa-alias.c (compute_memory_partitions): Use
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 353eeec..319ba13 100644 (file)
@@ -1,13 +1,13 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-   Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -45,7 +44,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "toplev.h"
 #include "except.h"
 #include "tree.h"
+#include "df.h"
 #include "target.h"
+#include "dse.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -394,7 +395,7 @@ static void check_eliminable_occurrences (rtx);
 static void elimination_effects (rtx, enum machine_mode);
 static int eliminate_regs_in_insn (rtx, int);
 static void update_eliminable_offsets (void);
-static void mark_not_eliminable (rtx, rtx, void *);
+static void mark_not_eliminable (rtx, const_rtx, void *);
 static void set_initial_elim_offsets (void);
 static bool verify_initial_elim_offsets (void);
 static void set_initial_label_offsets (void);
@@ -407,7 +408,7 @@ static void scan_paradoxical_subregs (rtx);
 static void count_pseudo (int);
 static void order_regs_for_reload (struct insn_chain *);
 static void reload_as_needed (int);
-static void forget_old_reloads_1 (rtx, rtx, void *);
+static void forget_old_reloads_1 (rtx, const_rtx, void *);
 static void forget_marked_reloads (regset);
 static int reload_reg_class_lower (const void *, const void *);
 static void mark_reload_reg_in_use (unsigned int, int, enum reload_type,
@@ -542,22 +543,17 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
   EXECUTE_IF_SET_IN_REG_SET (from, FIRST_PSEUDO_REGISTER, regno, rsi)
     {
       int r = reg_renumber[regno];
-      int nregs;
 
       if (r < 0)
        {
          /* reload_combine uses the information from
-            BASIC_BLOCK->global_live_at_start, which might still
+            DF_RA_LIVE_IN (BASIC_BLOCK), which might still
             contain registers that have not actually been allocated
             since they have an equivalence.  */
          gcc_assert (reload_completed);
        }
       else
-       {
-         nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
-         while (nregs-- > 0)
-           SET_HARD_REG_BIT (*to, r + nregs);
-       }
+       add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
     }
 }
 
@@ -622,6 +618,61 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
        replace_pseudos_in (& XVECEXP (x, i, j), mem_mode, usage);
 }
 
+/* Determine if the current function has an exception receiver block
+   that reaches the exit block via non-exceptional edges  */
+
+static bool
+has_nonexceptional_receiver (void)
+{
+  edge e;
+  edge_iterator ei;
+  basic_block *tos, *worklist, bb;
+
+  /* If we're not optimizing, then just err on the safe side.  */
+  if (!optimize)
+    return true;
+  
+  /* First determine which blocks can reach exit via normal paths.  */
+  tos = worklist = xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
+
+  FOR_EACH_BB (bb)
+    bb->flags &= ~BB_REACHABLE;
+
+  /* Place the exit block on our worklist.  */
+  EXIT_BLOCK_PTR->flags |= BB_REACHABLE;
+  *tos++ = EXIT_BLOCK_PTR;
+  
+  /* Iterate: find everything reachable from what we've already seen.  */
+  while (tos != worklist)
+    {
+      bb = *--tos;
+
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (!(e->flags & EDGE_ABNORMAL))
+         {
+           basic_block src = e->src;
+
+           if (!(src->flags & BB_REACHABLE))
+             {
+               src->flags |= BB_REACHABLE;
+               *tos++ = src;
+             }
+         }
+    }
+  free (worklist);
+
+  /* Now see if there's a reachable block with an exceptional incoming
+     edge.  */
+  FOR_EACH_BB (bb)
+    if (bb->flags & BB_REACHABLE)
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (e->flags & EDGE_ABNORMAL)
+         return true;
+
+  /* No exceptional block reached exit unexceptionally.  */
+  return false;
+}
+
 \f
 /* Global variables used by reload and its subroutines.  */
 
@@ -688,12 +739,15 @@ reload (rtx first, int global)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     mark_home_live (i);
 
-  /* A function that receives a nonlocal goto must save all call-saved
+  /* A function that has a nonlocal label that can reach the exit
+     block via non-exceptional paths must save all call-saved
      registers.  */
-  if (current_function_has_nonlocal_label)
+  if (current_function_calls_unwind_init
+      || (current_function_has_nonlocal_label
+         && has_nonexceptional_receiver ()))
     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
-       regs_ever_live[i] = 1;
+       df_set_regs_ever_live (i, true);
 
   /* Find all the pseudo registers that didn't get hard regs
      but do have known equivalent constants or memory slots.
@@ -888,16 +942,8 @@ reload (rtx first, int global)
     {
       int something_changed;
       int did_spill;
-
       HOST_WIDE_INT starting_frame_size;
 
-      /* Round size of stack frame to stack_alignment_needed.  This must be done
-        here because the stack size may be a part of the offset computation
-        for register elimination, and there might have been new stack slots
-        created in the last iteration of this loop.  */
-      if (cfun->stack_alignment_needed)
-        assign_stack_local (BLKmode, 0, cfun->stack_alignment_needed);
-
       starting_frame_size = get_frame_size ();
 
       set_initial_elim_offsets ();
@@ -964,6 +1010,20 @@ reload (rtx first, int global)
       /* If we allocated another stack slot, redo elimination bookkeeping.  */
       if (starting_frame_size != get_frame_size ())
        continue;
+      if (starting_frame_size && cfun->stack_alignment_needed)
+       {
+         /* If we have a stack frame, we must align it now.  The
+            stack size may be a part of the offset computation for
+            register elimination.  So if this changes the stack size,
+            then repeat the elimination bookkeeping.  We don't
+            realign when there is no stack, as that will cause a
+            stack frame when none is needed should
+            STARTING_FRAME_OFFSET not be already aligned to
+            STACK_BOUNDARY.  */
+         assign_stack_local (BLKmode, 0, cfun->stack_alignment_needed);
+         if (starting_frame_size != get_frame_size ())
+           continue;
+       }
 
       if (caller_save_needed)
        {
@@ -1095,9 +1155,11 @@ reload (rtx first, int global)
 
   if (! frame_pointer_needed)
     FOR_EACH_BB (bb)
-      CLEAR_REGNO_REG_SET (bb->il.rtl->global_live_at_start,
-                          HARD_FRAME_POINTER_REGNUM);
-
+      {
+       bitmap_clear_bit (df_get_live_in (bb), HARD_FRAME_POINTER_REGNUM);
+       bitmap_clear_bit (df_get_live_top (bb), HARD_FRAME_POINTER_REGNUM);
+      }
+       
   /* Come here (with failure set nonzero) if we can't get enough spill
      regs.  */
  failed:
@@ -1167,20 +1229,6 @@ reload (rtx first, int global)
       {
        rtx *pnote;
 
-       /* Clean up invalid ASMs so that they don't confuse later passes.
-          See PR 21299.  */
-       if (asm_noperands (PATTERN (insn)) >= 0)
-         {
-           extract_insn (insn);
-           if (!constrain_operands (1))
-             {
-               error_for_asm (insn,
-                              "%<asm%> operand has impossible constraints");
-               delete_insn (insn);
-               continue;
-             }
-         }
-
        if (CALL_P (insn))
          replace_pseudos_in (& CALL_INSN_FUNCTION_USAGE (insn),
                              VOIDmode, CALL_INSN_FUNCTION_USAGE (insn));
@@ -1229,6 +1277,7 @@ reload (rtx first, int global)
                || REG_NOTE_KIND (*pnote) == REG_UNUSED
                || REG_NOTE_KIND (*pnote) == REG_INC
                || REG_NOTE_KIND (*pnote) == REG_RETVAL
+               || REG_NOTE_KIND (*pnote) == REG_LIBCALL_ID
                || REG_NOTE_KIND (*pnote) == REG_LIBCALL)
              *pnote = XEXP (*pnote, 1);
            else
@@ -1239,8 +1288,22 @@ reload (rtx first, int global)
        add_auto_inc_notes (insn, PATTERN (insn));
 #endif
 
-       /* And simplify (subreg (reg)) if it appears as an operand.  */
+       /* Simplify (subreg (reg)) if it appears as an operand.  */
        cleanup_subreg_operands (insn);
+
+       /* Clean up invalid ASMs so that they don't confuse later passes.
+          See PR 21299.  */
+       if (asm_noperands (PATTERN (insn)) >= 0)
+         {
+           extract_insn (insn);
+           if (!constrain_operands (1))
+             {
+               error_for_asm (insn,
+                              "%<asm%> operand has impossible constraints");
+               delete_insn (insn);
+               continue;
+             }
+         }
       }
 
   /* If we are doing stack checking, give a warning if this function's
@@ -1251,7 +1314,7 @@ reload (rtx first, int global)
       static int verbose_warned = 0;
 
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
+       if (df_regs_ever_live_p (i) && ! fixed_regs[i] && call_used_regs[i])
          size += UNITS_PER_WORD;
 
       if (size > STACK_CHECK_MAX_FRAME_SIZE)
@@ -1359,7 +1422,7 @@ maybe_fix_stack_asms (void)
 
       /* Get the operand values and constraints out of the insn.  */
       decode_asm_operands (pat, recog_data.operand, recog_data.operand_loc,
-                          constraints, operand_mode);
+                          constraints, operand_mode, NULL);
 
       /* For every operand, see what registers are allowed.  */
       for (i = 0; i < noperands; i++)
@@ -1983,8 +2046,8 @@ alter_reg (int i, int from_reg)
 
   /* Modify the reg-rtx to contain the new hard reg
      number or else to contain its pseudo reg number.  */
-  REGNO (regno_reg_rtx[i])
-    = reg_renumber[i] >= 0 ? reg_renumber[i] : i;
+  SET_REGNO (regno_reg_rtx[i],
+            reg_renumber[i] >= 0 ? reg_renumber[i] : i);
 
   /* If we have a pseudo that is needed but has no hard reg or equivalent,
      allocate a stack slot for it.  */
@@ -2013,6 +2076,8 @@ alter_reg (int i, int from_reg)
         inherent space, and no less total space, then the previous slot.  */
       if (from_reg == -1)
        {
+         alias_set_type alias_set = new_alias_set ();
+
          /* No known place to spill from => no slot to reuse.  */
          x = assign_stack_local (mode, total_size,
                                  min_align > inherent_align
@@ -2025,7 +2090,8 @@ alter_reg (int i, int from_reg)
            adjust = inherent_size - total_size;
 
          /* Nothing can alias this slot except this pseudo.  */
-         set_mem_alias_set (x, new_alias_set ());
+         set_mem_alias_set (x, alias_set);
+         dse_record_singleton_alias_set (alias_set, mode);
        }
 
       /* Reuse a stack slot if possible.  */
@@ -2035,7 +2101,6 @@ alter_reg (int i, int from_reg)
                   >= inherent_size)
               && MEM_ALIGN (spill_stack_slot[from_reg]) >= min_align)
        x = spill_stack_slot[from_reg];
-
       /* Allocate a bigger slot.  */
       else
        {
@@ -2062,9 +2127,18 @@ alter_reg (int i, int from_reg)
 
          /* All pseudos mapped to this slot can alias each other.  */
          if (spill_stack_slot[from_reg])
-           set_mem_alias_set (x, MEM_ALIAS_SET (spill_stack_slot[from_reg]));
+           {
+             alias_set_type alias_set 
+               = MEM_ALIAS_SET (spill_stack_slot[from_reg]);
+             set_mem_alias_set (x, alias_set);
+             dse_invalidate_singleton_alias_set (alias_set);
+           }
          else
-           set_mem_alias_set (x, new_alias_set ());
+           {
+             alias_set_type alias_set = new_alias_set ();
+             set_mem_alias_set (x, alias_set);
+             dse_record_singleton_alias_set (alias_set, mode);
+           }
 
          if (BYTES_BIG_ENDIAN)
            {
@@ -2119,20 +2193,30 @@ alter_reg (int i, int from_reg)
     }
 }
 
-/* Mark the slots in regs_ever_live for the hard regs
-   used by pseudo-reg number REGNO.  */
+/* Mark the slots in regs_ever_live for the hard regs used by
+   pseudo-reg number REGNO, accessed in MODE.  */
 
-void
-mark_home_live (int regno)
+static void
+mark_home_live_1 (int regno, enum machine_mode mode)
 {
   int i, lim;
 
   i = reg_renumber[regno];
   if (i < 0)
     return;
-  lim = i + hard_regno_nregs[i][PSEUDO_REGNO_MODE (regno)];
+  lim = end_hard_regno (mode, i);
   while (i < lim)
-    regs_ever_live[i++] = 1;
+    df_set_regs_ever_live(i++, true);
+}
+
+/* Mark the slots in regs_ever_live for the hard regs
+   used by pseudo-reg number REGNO.  */
+
+void
+mark_home_live (int regno)
+{
+  if (reg_renumber[regno] >= 0)
+    mark_home_live_1 (regno, PSEUDO_REGNO_MODE (regno));
 }
 \f
 /* This function handles the tracking of elimination offsets around branches.
@@ -2542,6 +2626,30 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case POST_INC:
     case PRE_DEC:
     case POST_DEC:
+      /* We do not support elimination of a register that is modified.
+        elimination_effects has already make sure that this does not
+        happen.  */
+      return x;
+
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      /* We do not support elimination of a register that is modified.
+        elimination_effects has already make sure that this does not
+        happen.  The only remaining case we need to consider here is
+        that the increment value may be an eliminable register.  */
+      if (GET_CODE (XEXP (x, 1)) == PLUS
+         && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
+       {
+         rtx new = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
+                                     insn, true);
+
+         if (new != XEXP (XEXP (x, 1), 1))
+           return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
+                                  gen_rtx_PLUS (GET_MODE (x),
+                                                XEXP (x, 0), new));
+       }
+      return x;
+
     case STRICT_LOW_PART:
     case NEG:          case NOT:
     case SIGN_EXTEND:  case ZERO_EXTEND:
@@ -2555,6 +2663,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case CTZ:
     case POPCOUNT:
     case PARITY:
+    case BSWAP:
       new = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
       if (new != XEXP (x, 0))
        return gen_rtx_fmt_e (code, GET_MODE (x), new);
@@ -2736,6 +2845,14 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
     case POST_DEC:
     case POST_MODIFY:
     case PRE_MODIFY:
+      /* If we modify the source of an elimination rule, disable it.  */
+      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+       if (ep->from_rtx == XEXP (x, 0))
+         ep->can_eliminate = 0;
+
+      /* If we modify the target of an elimination rule by adding a constant,
+        update its offset.  If we modify the target in any other way, we'll
+        have to disable the rule as well.  */
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        if (ep->to_rtx == XEXP (x, 0))
          {
@@ -2750,11 +2867,15 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
              ep->offset += size;
            else if (code == PRE_INC || code == POST_INC)
              ep->offset -= size;
-           else if ((code == PRE_MODIFY || code == POST_MODIFY)
-                    && GET_CODE (XEXP (x, 1)) == PLUS
-                    && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
-                    && CONSTANT_P (XEXP (XEXP (x, 1), 1)))
-             ep->offset -= INTVAL (XEXP (XEXP (x, 1), 1));
+           else if (code == PRE_MODIFY || code == POST_MODIFY)
+             {
+               if (GET_CODE (XEXP (x, 1)) == PLUS
+                   && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
+                   && CONST_INT_P (XEXP (XEXP (x, 1), 1)))
+                 ep->offset -= INTVAL (XEXP (XEXP (x, 1), 1));
+               else
+                 ep->can_eliminate = 0;
+             }
          }
 
       /* These two aren't unary operators.  */
@@ -2775,6 +2896,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
     case CTZ:
     case POPCOUNT:
     case PARITY:
+    case BSWAP:
       elimination_effects (XEXP (x, 0), mem_mode);
       return;
 
@@ -3057,7 +3179,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
          rtx links;
          for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
            {
-             if (REG_NOTE_KIND (links) == REG_EQUAL
+             if ((REG_NOTE_KIND (links) == REG_EQUAL
+                  || REG_NOTE_KIND (links) == REG_EQUIV)
                  && GET_CODE (XEXP (links, 0)) == PLUS
                  && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT)
                {
@@ -3092,39 +3215,20 @@ eliminate_regs_in_insn (rtx insn, int replace)
          {
            rtx to_rtx = ep->to_rtx;
            offset += ep->offset;
+           offset = trunc_int_for_mode (offset, GET_MODE (reg));
 
            if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
              to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),
                                    to_rtx);
-           if (offset == 0)
-             {
-               int num_clobbers;
-               /* We assume here that if we need a PARALLEL with
-                  CLOBBERs for this assignment, we can do with the
-                  MATCH_SCRATCHes that add_clobbers allocates.
-                  There's not much we can do if that doesn't work.  */
-               PATTERN (insn) = gen_rtx_SET (VOIDmode,
-                                             SET_DEST (old_set),
-                                             to_rtx);
-               num_clobbers = 0;
-               INSN_CODE (insn) = recog (PATTERN (insn), insn, &num_clobbers);
-               if (num_clobbers)
-                 {
-                   rtvec vec = rtvec_alloc (num_clobbers + 1);
-
-                   vec->elem[0] = PATTERN (insn);
-                   PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
-                   add_clobbers (PATTERN (insn), INSN_CODE (insn));
-                 }
-               gcc_assert (INSN_CODE (insn) >= 0);
-             }
            /* If we have a nonzero offset, and the source is already
               a simple REG, the following transformation would
               increase the cost of the insn by replacing a simple REG
               with (plus (reg sp) CST).  So try only when we already
               had a PLUS before.  */
-           else if (plus_src)
+           if (offset == 0 || plus_src)
              {
+               rtx new_src = plus_constant (to_rtx, offset);
+
                new_body = old_body;
                if (! replace)
                  {
@@ -3135,8 +3239,20 @@ eliminate_regs_in_insn (rtx insn, int replace)
                PATTERN (insn) = new_body;
                old_set = single_set (insn);
 
-               XEXP (SET_SRC (old_set), 0) = to_rtx;
-               XEXP (SET_SRC (old_set), 1) = GEN_INT (offset);
+               /* First see if this insn remains valid when we make the
+                  change.  If not, try to replace the whole pattern with
+                  a simple set (this may help if the original insn was a
+                  PARALLEL that was only recognized as single_set due to 
+                  REG_UNUSED notes).  If this isn't valid either, keep
+                  the INSN_CODE the same and let reload fix it up.  */
+               if (!validate_change (insn, &SET_SRC (old_set), new_src, 0))
+                 {
+                   rtx new_pat = gen_rtx_SET (VOIDmode,
+                                              SET_DEST (old_set), new_src);
+
+                   if (!validate_change (insn, &PATTERN (insn), new_pat, 0))
+                     SET_SRC (old_set) = new_src;
+                 }
              }
            else
              break;
@@ -3361,7 +3477,7 @@ update_eliminable_offsets (void)
    the insns of the function.  */
 
 static void
-mark_not_eliminable (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED)
+mark_not_eliminable (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
 {
   unsigned int i;
 
@@ -3569,6 +3685,20 @@ update_eliminables (HARD_REG_SET *pset)
     SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
 }
 
+/* Return true if X is used as the target register of an elimination.  */
+
+bool
+elimination_target_reg_p (rtx x)
+{
+  struct elim_table *ep;
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    if (ep->to_rtx == x && ep->can_eliminate)
+      return true;
+
+  return false;
+}
+
 /* Initialize the table of registers to eliminate.  */
 
 static void
@@ -3644,7 +3774,7 @@ spill_hard_reg (unsigned int regno, int cant_eliminate)
   if (cant_eliminate)
     {
       SET_HARD_REG_BIT (bad_spill_regs_global, regno);
-      regs_ever_live[regno] = 1;
+      df_set_regs_ever_live (regno, true);
     }
 
   /* Spill every pseudo reg that was allocated to this reg
@@ -3653,10 +3783,7 @@ spill_hard_reg (unsigned int regno, int cant_eliminate)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_renumber[i] >= 0
        && (unsigned int) reg_renumber[i] <= regno
-       && ((unsigned int) reg_renumber[i]
-           + hard_regno_nregs[(unsigned int) reg_renumber[i]]
-                             [PSEUDO_REGNO_MODE (i)]
-           > regno))
+       && end_hard_regno (PSEUDO_REGNO_MODE (i), reg_renumber[i]) > regno)
       SET_REGNO_REG_SET (&spilled_pseudos, i);
 }
 
@@ -3691,9 +3818,9 @@ finish_spills (int global)
       {
        spill_reg_order[i] = n_spills;
        spill_regs[n_spills++] = i;
-       if (num_eliminable && ! regs_ever_live[i])
+       if (num_eliminable && ! df_regs_ever_live_p (i))
          something_changed = 1;
-       regs_ever_live[i] = 1;
+       df_set_regs_ever_live (i, true);
       }
     else
       spill_reg_order[i] = -1;
@@ -3781,9 +3908,8 @@ finish_spills (int global)
          AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
 
          /* Make sure we only enlarge the set.  */
-         GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
-         gcc_unreachable ();
-       ok:;
+         gcc_assert (hard_reg_set_subset_p (used_by_pseudos2,
+                                           chain->used_spill_regs));
        }
     }
 
@@ -3837,8 +3963,11 @@ scan_paradoxical_subregs (rtx x)
       if (REG_P (SUBREG_REG (x))
          && (GET_MODE_SIZE (GET_MODE (x))
              > reg_max_ref_width[REGNO (SUBREG_REG (x))]))
-       reg_max_ref_width[REGNO (SUBREG_REG (x))]
-         = GET_MODE_SIZE (GET_MODE (x));
+       {
+         reg_max_ref_width[REGNO (SUBREG_REG (x))]
+           = GET_MODE_SIZE (GET_MODE (x));
+         mark_home_live_1 (REGNO (SUBREG_REG (x)), GET_MODE (x));
+       }
       return;
 
     default:
@@ -4198,7 +4327,7 @@ reload_as_needed (int live_known)
    to be forgotten later.  */
 
 static void
-forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
+forget_old_reloads_1 (rtx x, const_rtx ignored ATTRIBUTE_UNUSED,
                      void *data)
 {
   unsigned int regno;
@@ -4477,8 +4606,7 @@ clear_reload_reg_in_use (unsigned int regno, int opnum,
            {
              unsigned int conflict_start = true_regnum (rld[i].reg_rtx);
              unsigned int conflict_end
-               = (conflict_start
-                  + hard_regno_nregs[conflict_start][rld[i].mode]);
+               = end_hard_regno (rld[i].mode, conflict_start);
 
              /* If there is an overlap with the first to-be-freed register,
                 adjust the interval start.  */
@@ -4792,6 +4920,51 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
     }
 }
 \f
+
+/*  Returns whether R1 and R2 are uniquely chained: the value of one
+    is used by the other, and that value is not used by any other
+    reload for this insn.  This is used to partially undo the decision
+    made in find_reloads when in the case of multiple
+    RELOAD_FOR_OPERAND_ADDRESS reloads it converts all
+    RELOAD_FOR_OPADDR_ADDR reloads into RELOAD_FOR_OPERAND_ADDRESS
+    reloads.  This code tries to avoid the conflict created by that
+    change.  It might be cleaner to explicitly keep track of which
+    RELOAD_FOR_OPADDR_ADDR reload is associated with which
+    RELOAD_FOR_OPERAND_ADDRESS reload, rather than to try to detect
+    this after the fact. */
+static bool
+reloads_unique_chain_p (int r1, int r2)
+{
+  int i;
+
+  /* We only check input reloads.  */
+  if (! rld[r1].in || ! rld[r2].in)
+    return false;
+
+  /* Avoid anything with output reloads.  */
+  if (rld[r1].out || rld[r2].out)
+    return false;
+
+  /* "chained" means one reload is a component of the other reload,
+     not the same as the other reload.  */
+  if (rld[r1].opnum != rld[r2].opnum
+      || rtx_equal_p (rld[r1].in, rld[r2].in)
+      || rld[r1].optional || rld[r2].optional
+      || ! (reg_mentioned_p (rld[r1].in, rld[r2].in)
+           || reg_mentioned_p (rld[r2].in, rld[r1].in)))
+    return false;
+
+  for (i = 0; i < n_reloads; i ++)
+    /* Look for input reloads that aren't our two */
+    if (i != r1 && i != r2 && rld[i].in)
+      {
+       /* If our reload is mentioned at all, it isn't a simple chain.  */
+       if (reg_mentioned_p (rld[r1].in, rld[i].in))
+         return false;
+      }
+  return true;
+}
+
 /* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
    Return 0 otherwise.
 
@@ -4840,7 +5013,8 @@ reloads_conflict (int r1, int r2)
 
     case RELOAD_FOR_OPERAND_ADDRESS:
       return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
-             || r2_type == RELOAD_FOR_OPERAND_ADDRESS);
+             || (r2_type == RELOAD_FOR_OPERAND_ADDRESS
+                 && !reloads_unique_chain_p (r1, r2)));
 
     case RELOAD_FOR_OPADDR_ADDR:
       return (r2_type == RELOAD_FOR_INPUT
@@ -5149,7 +5323,7 @@ free_for_value_p (int regno, enum machine_mode mode, int opnum,
    memory.  */
 
 int
-function_invariant_p (rtx x)
+function_invariant_p (const_rtx x)
 {
   if (CONSTANT_P (x))
     return 1;
@@ -5458,7 +5632,14 @@ choose_reload_regs (struct insn_chain *chain)
   for (j = 0; j < n_reloads; j++)
     {
       reload_order[j] = j;
-      reload_spill_index[j] = -1;
+      if (rld[j].reg_rtx != NULL_RTX)
+       {
+         gcc_assert (REG_P (rld[j].reg_rtx)
+                     && HARD_REGISTER_P (rld[j].reg_rtx));
+         reload_spill_index[j] = REGNO (rld[j].reg_rtx);
+       }
+      else
+       reload_spill_index[j] = -1;
 
       if (rld[j].nregs > 1)
        {
@@ -5574,10 +5755,11 @@ choose_reload_regs (struct insn_chain *chain)
              else if (GET_CODE (rld[r].in_reg) == SUBREG
                       && REG_P (SUBREG_REG (rld[r].in_reg)))
                {
-                 byte = SUBREG_BYTE (rld[r].in_reg);
                  regno = REGNO (SUBREG_REG (rld[r].in_reg));
                  if (regno < FIRST_PSEUDO_REGISTER)
                    regno = subreg_regno (rld[r].in_reg);
+                 else
+                   byte = SUBREG_BYTE (rld[r].in_reg);
                  mode = GET_MODE (rld[r].in_reg);
                }
 #ifdef AUTO_INC_DEC
@@ -5598,7 +5780,16 @@ choose_reload_regs (struct insn_chain *chain)
                regno = subreg_regno (rld[r].in);
 #endif
 
-             if (regno >= 0 && reg_last_reload_reg[regno] != 0)
+             if (regno >= 0
+                 && reg_last_reload_reg[regno] != 0
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                 /* Verify that the register it's in can be used in
+                    mode MODE.  */
+                 && !REG_CANNOT_CHANGE_MODE_P (REGNO (reg_last_reload_reg[regno]),
+                                               GET_MODE (reg_last_reload_reg[regno]),
+                                               mode)
+#endif
+                 )
                {
                  enum reg_class class = rld[r].class, last_class;
                  rtx last_reg = reg_last_reload_reg[regno];
@@ -5618,13 +5809,6 @@ choose_reload_regs (struct insn_chain *chain)
 
                  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)
                      && HARD_REGNO_MODE_OK (i, rld[r].mode)
@@ -6236,15 +6420,23 @@ merge_assigned_reloads (rtx insn)
                transfer_replacements (i, j);
              }
 
-         /* If this is now RELOAD_OTHER, look for any reloads that load
-            parts of this operand and set them to RELOAD_FOR_OTHER_ADDRESS
-            if they were for inputs, RELOAD_OTHER for outputs.  Note that
-            this test is equivalent to looking for reloads for this operand
-            number.  */
-         /* We must take special care with RELOAD_FOR_OUTPUT_ADDRESS; it may
-            share registers with a RELOAD_FOR_INPUT, so we can not change it
-            to RELOAD_FOR_OTHER_ADDRESS.  We should never need to, since we
-            do not modify RELOAD_FOR_OUTPUT.  */
+         /* If this is now RELOAD_OTHER, look for any reloads that
+            load parts of this operand and set them to
+            RELOAD_FOR_OTHER_ADDRESS if they were for inputs,
+            RELOAD_OTHER for outputs.  Note that this test is
+            equivalent to looking for reloads for this operand
+            number.
+
+            We must take special care with RELOAD_FOR_OUTPUT_ADDRESS;
+            it may share registers with a RELOAD_FOR_INPUT, so we can
+            not change it to RELOAD_FOR_OTHER_ADDRESS.  We should
+            never need to, since we do not modify RELOAD_FOR_OUTPUT.
+
+            It is possible that the RELOAD_FOR_OPERAND_ADDRESS
+            instruction is assigned the same register as the earlier
+            RELOAD_FOR_OTHER_ADDRESS instruction.  Merging these two
+            instructions will cause the RELOAD_FOR_OTHER_ADDRESS
+            instruction to be deleted later on.  */
 
          if (rld[i].when_needed == RELOAD_OTHER)
            for (j = 0; j < n_reloads; j++)
@@ -6252,6 +6444,7 @@ merge_assigned_reloads (rtx insn)
                  && rld[j].when_needed != RELOAD_OTHER
                  && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
                  && rld[j].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
+                 && rld[j].when_needed != RELOAD_FOR_OPERAND_ADDRESS
                  && (! conflicting_input
                      || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
                      || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
@@ -7070,10 +7263,6 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
      actually no need to store the old value in it.  */
 
   if (optimize
-      /* Only attempt this for input reloads; for RELOAD_OTHER we miss
-        that there may be multiple uses of the previous output reload.
-        Restricting to RELOAD_FOR_INPUT is mostly paranoia.  */
-      && rl->when_needed == RELOAD_FOR_INPUT
       && (reload_inherited[j] || reload_override_in[j])
       && rl->reg_rtx
       && REG_P (rl->reg_rtx)
@@ -7506,6 +7695,23 @@ emit_reload_insns (struct insn_chain *chain)
          rtx out = ((rld[r].out && REG_P (rld[r].out))
                     ? rld[r].out : rld[r].out_reg);
          int nregno = REGNO (out);
+
+         /* REG_RTX is now set or clobbered by the main instruction.
+            As the comment above explains, forget_old_reloads_1 only
+            sees the original instruction, and there is no guarantee
+            that the original instruction also clobbered REG_RTX.
+            For example, if find_reloads sees that the input side of
+            a matched operand pair dies in this instruction, it may
+            use the input register as the reload register.
+
+            Calling forget_old_reloads_1 is a waste of effort if
+            REG_RTX is also the output register.
+
+            If we know that REG_RTX holds the value of a pseudo
+            register, the code after the call will record that fact.  */
+         if (rld[r].reg_rtx && rld[r].reg_rtx != out)
+           forget_old_reloads_1 (rld[r].reg_rtx, NULL_RTX, NULL);
+
          if (nregno >= FIRST_PSEUDO_REGISTER)
            {
              rtx src_reg, store_insn = NULL_RTX;
@@ -7734,7 +7940,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
         DEFINE_PEEPHOLE should be specified that recognizes the sequence
         we emit below.  */
 
-      code = (int) add_optab->handlers[(int) GET_MODE (out)].insn_code;
+      code = (int) optab_handler (add_optab, GET_MODE (out))->insn_code;
 
       if (CONSTANT_P (op1) || MEM_P (op1) || GET_CODE (op1) == SUBREG
          || (REG_P (op1)
@@ -7757,17 +7963,17 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       if (insn)
        {
          /* Add a REG_EQUIV note so that find_equiv_reg can find it.  */
-         REG_NOTES (insn)
-           = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn));
+         set_unique_reg_note (insn, REG_EQUIV, in);
          return insn;
        }
 
       /* If that failed, copy the address register to the reload register.
         Then add the constant to the reload register.  */
 
+      gcc_assert (!reg_overlap_mentioned_p (out, op0));
       gen_reload (out, op1, opnum, type);
       insn = emit_insn (gen_add2_insn (out, op0));
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn));
+      set_unique_reg_note (insn, REG_EQUIV, in);
     }
 
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -7827,8 +8033,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       insn = emit_insn_if_valid_for_reload (insn);
       if (insn)
        {
-         REG_NOTES (insn)
-           = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn));
+         set_unique_reg_note (insn, REG_EQUIV, in);
          return insn;
        }
 
@@ -7909,21 +8114,15 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
       if (rtx_equal_p (reg2, reg))
        {
          if (reload_inherited[k] || reload_override_in[k] || k == j)
-           {
-             n_inherited++;
-             reg2 = rld[k].out_reg;
-             if (! reg2)
-               continue;
-             while (GET_CODE (reg2) == SUBREG)
-               reg2 = XEXP (reg2, 0);
-             if (rtx_equal_p (reg2, reg))
-               n_inherited++;
-           }
+           n_inherited++;
          else
            return;
        }
     }
   n_occurrences = count_occurrences (PATTERN (insn), reg, 0);
+  if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
+    n_occurrences += count_occurrences (CALL_INSN_FUNCTION_USAGE (insn),
+                                       reg, 0);
   if (substed)
     n_occurrences += count_occurrences (PATTERN (insn),
                                        eliminate_regs (substed, 0,
@@ -7980,7 +8179,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
   if (rld[j].out != rld[j].in
       && REG_N_DEATHS (REGNO (reg)) == 1
       && REG_N_SETS (REGNO (reg)) == 1
-      && REG_BASIC_BLOCK (REGNO (reg)) >= 0
+      && REG_BASIC_BLOCK (REGNO (reg)) >= NUM_FIXED_BLOCKS
       && find_regno_note (insn, REG_DEAD, REGNO (reg)))
     {
       rtx i2;
@@ -8399,7 +8598,7 @@ fixup_abnormal_edges (void)
                  next = NEXT_INSN (insn);
                  if (INSN_P (insn))
                    {
-                     delete_insn (insn);
+                     delete_insn (insn);
 
                      /* Sometimes there's still the return value USE.
                         If it's placed after a trapping call (i.e. that
@@ -8417,6 +8616,8 @@ fixup_abnormal_edges (void)
                          inserted = true;
                        }
                    }
+                 else if (!BARRIER_P (insn))
+                   set_block_for_insn (insn, NULL);
                  insn = next;
                }
            }
@@ -8437,6 +8638,7 @@ fixup_abnormal_edges (void)
       blocks = sbitmap_alloc (last_basic_block);
       sbitmap_ones (blocks);
       find_many_sub_basic_blocks (blocks);
+      sbitmap_free (blocks);
     }
 
   if (inserted)