OSDN Git Service

* expr.c (expand_expr): Use gen_int_mode for the argument
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index a85d250..441a447 100644 (file)
@@ -1,6 +1,6 @@
 /* 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "machmode.h"
 #include "hard-reg-set.h"
@@ -139,7 +141,7 @@ static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
    when reg_reloaded_valid is set for this register.  */
 static rtx reg_reloaded_insn[FIRST_PSEUDO_REGISTER];
 
-/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
+/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
 static HARD_REG_SET reg_reloaded_valid;
 /* Indicate if the register was dead at the end of the reload.
    This is only valid if reg_reloaded_contents is set and valid.  */
@@ -303,7 +305,7 @@ struct elim_table
   int from;                    /* Register number to be eliminated.  */
   int to;                      /* Register number used as replacement.  */
   int initial_offset;          /* Initial difference between values.  */
-  int can_eliminate;           /* Non-zero if this elimination can be done.  */
+  int can_eliminate;           /* Nonzero if this elimination can be done.  */
   int can_eliminate_previous;  /* Value of CAN_ELIMINATE in previous scan over
                                   insns made by reload.  */
   int offset;                  /* Current offset between the two regs.  */
@@ -340,7 +342,7 @@ static const struct elim_table_1
 #define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1)
 
 /* Record the number of pending eliminations that have an offset not equal
-   to their initial offset.  If non-zero, we use a new copy of each
+   to their initial offset.  If nonzero, we use a new copy of each
    replacement result in any insns encountered.  */
 int num_not_at_initial_offset;
 
@@ -352,11 +354,14 @@ static int num_eliminable_invariants;
 
 /* For each label, we record the offset of each elimination.  If we reach
    a label by more than one path and an offset differs, we cannot do the
-   elimination.  This information is indexed by the number of the label.
-   The first table is an array of flags that records whether we have yet
-   encountered a label and the second table is an array of arrays, one
-   entry in the latter array for each elimination.  */
-
+   elimination.  This information is indexed by the difference of the
+   number of the label and the first label number.  We can't offset the
+   pointer itself as this can cause problems on machines with segmented
+   memory.  The first table is an array of flags that records whether we
+   have yet encountered a label and the second table is an array of arrays,
+   one entry in the latter array for each elimination.  */
+
+static int first_label_num;
 static char *offsets_known_at;
 static int (*offsets_at)[NUM_ELIMINABLE_REGS];
 
@@ -673,11 +678,6 @@ reload (first, global)
   struct elim_table *ep;
   basic_block bb;
 
-  /* The two pointers used to track the true location of the memory used
-     for label offsets.  */
-  char *real_known_ptr = NULL;
-  int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
-
   /* Make sure even insns with volatile mem refs are recognizable.  */
   init_recog ();
 
@@ -817,8 +817,12 @@ reload (first, global)
                      else if (LEGITIMATE_CONSTANT_P (x))
                        reg_equiv_constant[i] = x;
                      else
-                       reg_equiv_memory_loc[i]
-                         = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                       {
+                         reg_equiv_memory_loc[i]
+                           = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                         if (!reg_equiv_memory_loc[i])
+                           continue;
+                       }
                    }
                  else
                    continue;
@@ -852,21 +856,18 @@ reload (first, global)
 
   init_elim_table ();
 
-  num_labels = max_label_num () - get_first_label_num ();
+  first_label_num = get_first_label_num ();
+  num_labels = max_label_num () - first_label_num;
 
   /* Allocate the tables used to store offset information at labels.  */
   /* We used to use alloca here, but the size of what it would try to
      allocate would occasionally cause it to exceed the stack limit and
      cause a core dump.  */
-  real_known_ptr = xmalloc (num_labels);
-  real_at_ptr
+  offsets_known_at = xmalloc (num_labels);
+  offsets_at
     = (int (*)[NUM_ELIMINABLE_REGS])
     xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
 
-  offsets_known_at = real_known_ptr - get_first_label_num ();
-  offsets_at
-    = (int (*)[NUM_ELIMINABLE_REGS]) (real_at_ptr - get_first_label_num ());
-
   /* Alter each pseudo-reg rtx to contain its hard reg number.
      Assign stack slots to the pseudos that lack hard regs or equivalents.
      Do not touch virtual registers.  */
@@ -1023,7 +1024,7 @@ reload (first, global)
              did_spill = 1;
 
              /* Regardless of the state of spills, if we previously had
-                a register that we thought we could eliminate, but no can
+                a register that we thought we could eliminate, but now can
                 not eliminate, we must run another pass.
 
                 Consider pseudos which have an entry in reg_equiv_* which
@@ -1265,10 +1266,10 @@ reload (first, global)
     free (reg_equiv_memory_loc);
   reg_equiv_memory_loc = 0;
 
-  if (real_known_ptr)
-    free (real_known_ptr);
-  if (real_at_ptr)
-    free (real_at_ptr);
+  if (offsets_known_at)
+    free (offsets_known_at);
+  if (offsets_at)
+    free (offsets_at);
 
   free (reg_equiv_mem);
   free (reg_equiv_init);
@@ -1349,7 +1350,7 @@ maybe_fix_stack_asms ()
 
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
 
              if (c == '\0' || c == ',' || c == '#')
                {
@@ -1357,6 +1358,7 @@ maybe_fix_stack_asms ()
                     class, and reset the class.  */
                  IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
                  cls = NO_REGS;
+                 p++;
                  if (c == '#')
                    do {
                      c = *p++;
@@ -1387,13 +1389,14 @@ maybe_fix_stack_asms ()
                  break;
 
                default:
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    cls = (int) reg_class_subunion[cls]
                      [(int) MODE_BASE_REG_CLASS (VOIDmode)];
                  else
                    cls = (int) reg_class_subunion[cls]
-                     [(int) REG_CLASS_FROM_LETTER (c)];
+                     [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
                }
+             p += CONSTRAINT_LEN (c, p);
            }
        }
       /* Those of the registers which are clobbered, but allowed by the
@@ -1497,7 +1500,7 @@ calculate_needs_all_insns (global)
                  && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
                {
                  delete_insn (insn);
-                 /* Delete it from the reload chain */
+                 /* Delete it from the reload chain */
                  if (chain->prev)
                    chain->prev->next = next;
                  else
@@ -2073,9 +2076,10 @@ alter_reg (i, from_reg)
 
       /* If we have a decl for the original register, set it for the
         memory.  If this is a shared MEM, make a copy.  */
-      if (REGNO_DECL (i))
+      if (REG_EXPR (regno_reg_rtx[i])
+         && TREE_CODE_CLASS (TREE_CODE (REG_EXPR (regno_reg_rtx[i]))) == 'd')
        {
-         rtx decl = DECL_RTL_IF_SET (REGNO_DECL (i));
+         rtx decl = DECL_RTL_IF_SET (REG_EXPR (regno_reg_rtx[i]));
 
          /* We can do this only for the DECLs home pseudo, not for
             any copies of it, since otherwise when the stack slot
@@ -2086,7 +2090,7 @@ alter_reg (i, from_reg)
              if (from_reg != -1 && spill_stack_slot[from_reg] == x)
                x = copy_rtx (x);
 
-             set_mem_expr (x, REGNO_DECL (i));
+             set_mem_attrs_from_reg (x, regno_reg_rtx[i]);
            }
        }
 
@@ -2118,7 +2122,7 @@ mark_home_live (regno)
 
    INSN is the insn that it came from, if any.
 
-   INITIAL_P is non-zero if we are to set the offset to be the initial
+   INITIAL_P is nonzero if we are to set the offset to be the initial
    offset and zero if we are setting the offset of the label to be the
    current offset.  */
 
@@ -2151,13 +2155,13 @@ set_label_offsets (x, insn, initial_p)
         we guessed wrong, we will suppress an elimination that might have
         been possible had we been able to guess correctly.  */
 
-      if (! offsets_known_at[CODE_LABEL_NUMBER (x)])
+      if (! offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num])
        {
          for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-           offsets_at[CODE_LABEL_NUMBER (x)][i]
+           offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              = (initial_p ? reg_eliminate[i].initial_offset
                 : reg_eliminate[i].offset);
-         offsets_known_at[CODE_LABEL_NUMBER (x)] = 1;
+         offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num] = 1;
        }
 
       /* Otherwise, if this is the definition of a label and it is
@@ -2174,7 +2178,7 @@ set_label_offsets (x, insn, initial_p)
           where the offsets disagree.  */
 
        for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-         if (offsets_at[CODE_LABEL_NUMBER (x)][i]
+         if (offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              != (initial_p ? reg_eliminate[i].initial_offset
                  : reg_eliminate[i].offset))
            reg_eliminate[i].can_eliminate = 0;
@@ -2273,7 +2277,7 @@ set_label_offsets (x, insn, initial_p)
    to record the fact that a register is referenced outside a MEM.
 
    If INSN is an insn, it is the insn containing X.  If we replace a REG
-   in a SET_DEST with an equivalent MEM and INSN is non-zero, write a
+   in a SET_DEST with an equivalent MEM and INSN is nonzero, write a
    CLOBBER of the pseudo after INSN so find_equiv_regs will know that
    the REG is being modified.
 
@@ -2536,6 +2540,10 @@ eliminate_regs (x, mem_mode, insn)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:
+    case CTZ:
+    case POPCOUNT:
+    case PARITY:
       new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
       if (new != XEXP (x, 0))
        return gen_rtx_fmt_e (code, GET_MODE (x), new);
@@ -2767,6 +2775,10 @@ elimination_effects (x, mem_mode)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:
+    case CTZ:
+    case POPCOUNT:
+    case PARITY:
       elimination_effects (XEXP (x, 0), mem_mode);
       return;
 
@@ -2929,7 +2941,7 @@ eliminate_regs_in_insn (insn, replace)
   rtx old_set = single_set (insn);
   rtx new_body;
   int val = 0;
-  int i, any_changes;
+  int i;
   rtx substed_operand[MAX_RECOG_OPERANDS];
   rtx orig_operand[MAX_RECOG_OPERANDS];
   struct elim_table *ep;
@@ -3104,7 +3116,6 @@ eliminate_regs_in_insn (insn, replace)
   /* Eliminate all eliminable registers occurring in operands that
      can be handled by reload.  */
   extract_insn (insn);
-  any_changes = 0;
   for (i = 0; i < recog_data.n_operands; i++)
     {
       orig_operand[i] = recog_data.operand[i];
@@ -3130,7 +3141,7 @@ eliminate_regs_in_insn (insn, replace)
          substed_operand[i] = eliminate_regs (recog_data.operand[i], 0,
                                               replace ? insn : NULL_RTX);
          if (substed_operand[i] != orig_operand[i])
-           val = any_changes = 1;
+           val = 1;
          /* Terminate the search in check_eliminable_occurrences at
             this point.  */
          *recog_data.operand_loc[i] = 0;
@@ -3229,7 +3240,7 @@ eliminate_regs_in_insn (insn, replace)
      insn.  The changes we make were determined by the earlier call to
      elimination_effects.
 
-     We also detect cases where register elimination cannot be done,
+     We also detect cases where register elimination cannot be done,
      namely, if a register would be both changed and referenced outside a MEM
      in the resulting insn since such an insn is often undefined and, even if
      not, we cannot know what meaning will be given to it.  Note that it is
@@ -3383,7 +3394,7 @@ static void
 set_initial_label_offsets ()
 {
   rtx x;
-  memset ((char *) &offsets_known_at[get_first_label_num ()], 0, num_labels);
+  memset (offsets_known_at, 0, num_labels);
 
   for (x = forced_labels; x; x = XEXP (x, 1))
     if (XEXP (x, 0))
@@ -3404,14 +3415,15 @@ set_offsets_for_label (insn)
   num_not_at_initial_offset = 0;
   for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
     {
-      ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+      ep->offset = ep->previous_offset
+                = offsets_at[label_nr - first_label_num][i];
       if (ep->can_eliminate && ep->offset != ep->initial_offset)
        num_not_at_initial_offset++;
     }
 }
 
 /* See if anything that happened changes which eliminations are valid.
-   For example, on the Sparc, whether or not the frame pointer can
+   For example, on the SPARC, whether or not the frame pointer can
    be eliminated can depend on what registers have been used.  We need
    not check some conditions again (such as flag_omit_frame_pointer)
    since they can't have changed.  */
@@ -3420,9 +3432,7 @@ static void
 update_eliminables (pset)
      HARD_REG_SET *pset;
 {
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   int previous_frame_pointer_needed = frame_pointer_needed;
-#endif
   struct elim_table *ep;
 
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
@@ -3487,12 +3497,10 @@ update_eliminables (pset)
        }
     }
 
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   /* If we didn't need a frame pointer last time, but we do now, spill
      the hard frame pointer.  */
   if (frame_pointer_needed && ! previous_frame_pointer_needed)
     SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
-#endif
 }
 
 /* Initialize the table of registers to eliminate.  */
@@ -3839,7 +3847,7 @@ reload_as_needed (live_known)
 
   for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      rtx prev;
+      rtx prev = 0;
       rtx insn = chain->insn;
       rtx old_next = NEXT_INSN (insn);
 
@@ -3981,7 +3989,7 @@ reload_as_needed (live_known)
                                            REGNO (rld[i].reg_rtx))
                      /* Make sure it is the inc/dec pseudo, and not
                         some other (e.g. output operand) pseudo.  */
-                     && (reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
+                     && ((unsigned) reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
                          == REGNO (XEXP (in_reg, 0))))
 
                    {
@@ -4048,7 +4056,7 @@ reload_as_needed (live_known)
                                                 REGNO (rld[i].reg_rtx))
                           /* Make sure it is the inc/dec pseudo, and not
                              some other (e.g. output operand) pseudo.  */
-                          && (reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
+                          && ((unsigned) reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
                               == REGNO (XEXP (in_reg, 0))))
                    {
                      SET_HARD_REG_BIT (reg_is_output_reload,
@@ -4752,7 +4760,7 @@ char reload_inherited[MAX_RELOADS];
    if we know it.  Otherwise, this is 0.  */
 rtx reload_inheritance_insn[MAX_RELOADS];
 
-/* If non-zero, this is a place to get the value of the reload,
+/* If nonzero, this is a place to get the value of the reload,
    rather than using reload_in.  */
 rtx reload_override_in[MAX_RELOADS];
 
@@ -4993,7 +5001,7 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
    determine how many hard regs to test.
 
    Other read-only reloads with the same value do not conflict
-   unless OUT is non-zero and these other reloads have to live while
+   unless OUT is nonzero and these other reloads have to live while
    output reloads live.
    If OUT is CONST0_RTX, this is a special case: it means that the
    test should not be for using register REGNO as reload register, but
@@ -5116,7 +5124,7 @@ set_reload_reg (i, r)
 }
 
 /* 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
+   LAST_RELOAD is nonzero if this is the last reload for the insn being
    processed.
 
    Set rld[R].reg_rtx to the register allocated.
@@ -5494,16 +5502,15 @@ choose_reload_regs (chain)
                                                GET_MODE_CLASS (mode));
 
                  if (
-#ifdef CLASS_CANNOT_CHANGE_MODE
-                     (TEST_HARD_REG_BIT
-                      (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
-                      ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
-                                                      need_mode)
-                      : (GET_MODE_SIZE (GET_MODE (last_reg))
-                         >= GET_MODE_SIZE (need_mode)))
-#else
+#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))
                       >= GET_MODE_SIZE (need_mode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                     )
 #endif
                      && reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
@@ -5935,7 +5942,7 @@ choose_reload_regs (chain)
     if (reload_override_in[j])
       rld[j].in = reload_override_in[j];
 
-  /* If this reload won't be done because it has been cancelled or is
+  /* If this reload won't be done because it has been canceled or is
      optional and not inherited, clear reload_reg_rtx so other
      routines (such as subst_reloads) don't get confused.  */
   for (j = 0; j < n_reloads; j++)
@@ -6009,7 +6016,7 @@ deallocate_reload_reg (r)
   reload_spill_index[r] = -1;
 }
 \f
-/* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
+/* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
    reloads of the same item for fear that we might not have enough reload
    registers. However, normally they will get the same reload register
    and hence actually need not be loaded twice.
@@ -6119,10 +6126,24 @@ merge_assigned_reloads (insn)
                      || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
                  && reg_overlap_mentioned_for_reload_p (rld[j].in,
                                                         rld[i].in))
-               rld[j].when_needed
-                 = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                     || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
-                    ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+               {
+                 int k;
+
+                 rld[j].when_needed
+                   = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+                       || 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 to the same type.
+                    If so, the resulting code won't work, so abort.  */
+                 if (rld[j].reg_rtx)
+                   for (k = 0; k < j; k++)
+                     if (rld[k].in != 0 && rld[k].reg_rtx != 0
+                         && rld[k].when_needed == rld[j].when_needed
+                         && rtx_equal_p (rld[k].reg_rtx, rld[j].reg_rtx))
+                       abort ();
+               }
        }
     }
 }
@@ -6244,7 +6265,7 @@ emit_input_reload_insns (chain, rl, old, j)
         or memory.  */
 
       if (oldequiv != 0
-         && ((REGNO_REG_CLASS (regno) != rl->class
+         && (((enum reg_class) REGNO_REG_CLASS (regno) != rl->class
               && (REGISTER_MOVE_COST (mode, REGNO_REG_CLASS (regno),
                                       rl->class)
                   >= MEMORY_MOVE_COST (mode, rl->class, 1)))
@@ -6858,7 +6879,6 @@ do_input_reload (chain, rl, j)
      struct reload *rl;
      int j;
 {
-  int expect_occurrences = 1;
   rtx insn = chain->insn;
   rtx old = (rl->in && GET_CODE (rl->in) == MEM
             ? rl->in_reg : rl->in);
@@ -6879,11 +6899,7 @@ do_input_reload (chain, rl, j)
       && GET_CODE (rl->in_reg) == MEM
       && reload_spill_index[j] >= 0
       && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
-    {
-      expect_occurrences
-       = count_occurrences (PATTERN (insn), rl->in, 0) == 1 ? 0 : -1;
-      rl->in = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
-    }
+    rl->in = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
 
   /* If we are reloading a register that was recently stored in with an
      output-reload, see if we can prove there was
@@ -7532,10 +7548,12 @@ gen_reload (out, in, opnum, type)
 
 #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
-          && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
-          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
-                                      REGNO_REG_CLASS (REGNO (out)),
+  else if ((GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+          && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
+          && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+          && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
+          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
+                                      REGNO_REG_CLASS (reg_or_subregno (out)),
                                       GET_MODE (out)))
     {
       /* Get the memory to use and rewrite both registers to its mode.  */
@@ -7597,6 +7615,11 @@ delete_output_reload (insn, j, last_reload_reg)
   rtx i1;
   rtx substed;
 
+  /* It is possible that this reload has been only used to set another reload
+     we eliminated earlier and thus deleted this instruction too.  */
+  if (INSN_DELETED_P (output_reload_insn))
+    return;
+
   /* Get the raw pseudo-register referred to.  */
 
   while (GET_CODE (reg) == SUBREG)
@@ -7678,7 +7701,7 @@ delete_output_reload (insn, j, last_reload_reg)
 
   /* The caller has already checked that REG dies or is set in INSN.
      It has also checked that we are optimizing, and thus some
-     inaccurancies in the debugging information are acceptable.
+     inaccuracies in the debugging information are acceptable.
      So we could just delete output_reload_insn.  But in some cases
      we can improve the debugging information without sacrificing
      optimization - maybe even improving the code: See if the pseudo
@@ -7880,7 +7903,7 @@ delete_address_reloads_1 (dead_insn, x, current_insn)
                  return;
              /* ??? We can't finish the loop here, because dst might be
                 allocated to a pseudo in this block if no reload in this
-                block needs any of the clsses containing DST - see
+                block needs any of the classes containing DST - see
                 spill_hard_reg.  There is no easy way to tell this, so we
                 have to scan till the end of the basic block.  */
            }
@@ -7922,7 +7945,7 @@ inc_for_reload (reloadreg, in, value, inc_amount)
   rtx real_in = in == value ? XEXP (in, 0) : in;
 
   /* No hard register is equivalent to this register after
-     inc/dec operation.  If REG_LAST_RELOAD_REG were non-zero,
+     inc/dec operation.  If REG_LAST_RELOAD_REG were nonzero,
      we could inc/dec that register as well (maybe even using it for
      the source), but I'm not sure it's worth worrying about.  */
   if (GET_CODE (incloc) == REG)
@@ -8259,7 +8282,13 @@ reload_cse_simplify_set (set, insn)
        {
 #ifdef LOAD_EXTEND_OP
          if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
-             && extend_op != NIL)
+             && extend_op != NIL
+#ifdef CANNOT_CHANGE_MODE_CLASS
+             && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
+                                           word_mode,
+                                           REGNO_REG_CLASS (REGNO (SET_DEST (set))))
+#endif
+             )
            {
              rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
              ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
@@ -8402,7 +8431,7 @@ reload_cse_simplify_operands (insn, testreg)
          p = constraints[i];
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
 
              switch (c)
                {
@@ -8426,7 +8455,9 @@ reload_cse_simplify_operands (insn, testreg)
 
                default:
                  class
-                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
+                   = (reg_class_subunion
+                      [(int) class]
+                      [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
                  break;
 
                case ',': case '\0':
@@ -8446,6 +8477,7 @@ reload_cse_simplify_operands (insn, testreg)
                  j++;
                  break;
                }
+             p += CONSTRAINT_LEN (c, p);
 
              if (c == '\0')
                break;
@@ -8519,7 +8551,7 @@ reload_cse_simplify_operands (insn, testreg)
 \f
 /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
    addressing now.
-   This code might also be useful when reload gave up on reg+reg addresssing
+   This code might also be useful when reload gave up on reg+reg addressing
    because of clashes between the return register and INDEX_REG_CLASS.  */
 
 /* The maximum number of uses of a register we can keep track of to
@@ -8540,7 +8572,7 @@ struct reg_use { rtx insn, *usep; };
    last, of these uses.
    STORE_RUID is always meaningful if we only want to use a value in a
    register in a different place: it denotes the next insn in the insn
-   stream (i.e. the last ecountered) that sets or clobbers the register.  */
+   stream (i.e. the last encountered) that sets or clobbers the register.  */
 static struct
   {
     struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
@@ -9043,7 +9075,7 @@ static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
 static int reg_base_reg[FIRST_PSEUDO_REGISTER];
 static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
 
-/* move2add_luid is linearily increased while scanning the instructions
+/* move2add_luid is linearly increased while scanning the instructions
    from first to last.  It is used to set reg_set_luid in
    reload_cse_move2add and move2add_note_store.  */
 static int move2add_luid;
@@ -9139,7 +9171,7 @@ reload_cse_move2add (first)
                     use (set (reg) (reg)) instead.
                     We don't delete this insn, nor do we convert it into a
                     note, to avoid losing register notes or the return
-                    value flag.  jump2 already knowns how to get rid of
+                    value flag.  jump2 already knows how to get rid of
                     no-op moves.  */
                  if (new_src == const0_rtx)
                    success = validate_change (insn, &SET_SRC (pat), reg, 0);
@@ -9449,7 +9481,7 @@ fixup_abnormal_edges ()
     {
       edge e;
 
-      /* Look for cases we are interested in - an calls or instructions causing
+      /* Look for cases we are interested in - calls or instructions causing
          exceptions.  */
       for (e = bb->succ; e; e = e->succ_next)
        {
@@ -9488,7 +9520,7 @@ fixup_abnormal_edges ()
                     If it's placed after a trapping call (i.e. that
                     call is the last insn anyway), we have no fallthru
                     edge.  Simply delete this use and don't try to insert
-                    on the non-existant edge.  */
+                    on the non-existent edge.  */
                  if (GET_CODE (PATTERN (insn)) != USE)
                    {
                      /* We're not deleting it, we're moving it.  */
@@ -9503,6 +9535,14 @@ fixup_abnormal_edges ()
            }
        }
     }
+  /* We've possibly turned single trapping insn into multiple ones.  */
+  if (flag_non_call_exceptions)
+    {
+      sbitmap blocks;
+      blocks = sbitmap_alloc (last_basic_block);
+      sbitmap_ones (blocks);
+      find_many_sub_basic_blocks (blocks);
+    }
   if (inserted)
     commit_edge_insertions ();
 }