OSDN Git Service

Add new test - do not warn about (non-)redundant friend declaration.
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 5d60100..3452a68 100644 (file)
@@ -1,6 +1,6 @@
 /* Emit RTL for the GNU C-Compiler expander.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -54,7 +54,6 @@ Boston, MA 02111-1307, USA.  */
 #include "bitmap.h"
 #include "basic-block.h"
 #include "ggc.h"
-#include "defaults.h"
 
 /* Commonly used modes.  */
 
@@ -178,6 +177,7 @@ static void mark_sequence_stack         PARAMS ((struct sequence_stack *));
 static void unshare_all_rtl_1          PARAMS ((rtx));
 static void unshare_all_decls          PARAMS ((tree));
 static void reset_used_decls           PARAMS ((tree));
+static void mark_label_nuses           PARAMS ((rtx));
 static hashval_t const_int_htab_hash    PARAMS ((const void *));
 static int const_int_htab_eq            PARAMS ((const void *,
                                                 const void *));
@@ -228,6 +228,20 @@ rtx_htab_mark (htab)
   htab_traverse (*((htab_t *) htab), rtx_htab_mark_1, NULL);
 }
 
+/* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
+   don't attempt to share with the various global pieces of rtl (such as
+   frame_pointer_rtx).  */
+
+rtx
+gen_raw_REG (mode, regno)
+     enum machine_mode mode;
+     int regno;
+{
+  rtx x = gen_rtx_raw_REG (mode, regno);
+  ORIGINAL_REGNO (x) = regno;
+  return x;
+}
+
 /* There are some RTL codes that require special attention; the generation
    functions do the raw handling.  If you add to this list, modify
    special_rtx in gengenrtl.c as well.  */
@@ -319,7 +333,7 @@ gen_rtx_REG (mode, regno)
        return stack_pointer_rtx;
     }
 
-  return gen_rtx_raw_REG (mode, regno);
+  return gen_raw_REG (mode, regno);
 }
 
 rtx
@@ -335,6 +349,55 @@ gen_rtx_MEM (mode, addr)
 
   return rt;
 }
+
+rtx
+gen_rtx_SUBREG (mode, reg, offset)
+     enum machine_mode mode;
+     rtx reg;
+     int offset;
+{
+  /* This is the most common failure type.
+     Catch it early so we can see who does it.  */
+  if ((offset % GET_MODE_SIZE (mode)) != 0)
+    abort ();
+
+  /* This check isn't usable right now because combine will
+     throw arbitrary crap like a CALL into a SUBREG in
+     gen_lowpart_for_combine so we must just eat it.  */
+#if 0
+  /* Check for this too.  */
+  if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
+    abort ();
+#endif
+  return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
+}
+
+/* Generate a SUBREG representing the least-significant part
+ * of REG if MODE is smaller than mode of REG, otherwise
+ * paradoxical SUBREG. */
+rtx
+gen_lowpart_SUBREG (mode, reg)
+     enum machine_mode mode;
+     rtx reg;
+{
+  enum machine_mode inmode;
+  int offset;
+
+  inmode = GET_MODE (reg);
+  if (inmode == VOIDmode)
+    inmode = mode;
+  offset = 0;
+  if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (inmode)
+      && (WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN))
+    {
+      offset = GET_MODE_SIZE (inmode) - GET_MODE_SIZE (mode);
+      if (! BYTES_BIG_ENDIAN)
+       offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+      else if (! WORDS_BIG_ENDIAN)
+       offset %= UNITS_PER_WORD;
+    }
+  return gen_rtx_SUBREG (mode, reg, offset);
+}
 \f
 /* rtx gen_rtx (code, mode, [element1, ..., elementn])
 **
@@ -569,7 +632,7 @@ gen_reg_rtx (mode)
       f->emit->regno_pointer_align_length = old_size * 2;
     }
 
-  val = gen_rtx_raw_REG (mode, reg_rtx_no);
+  val = gen_raw_REG (mode, reg_rtx_no);
   regno_reg_rtx[reg_rtx_no++] = val;
   return val;
 }
@@ -637,6 +700,38 @@ get_first_label_num ()
   return first_label_num;
 }
 \f
+/* Return the final regno of X, which is a SUBREG of a hard
+   register.  */
+int
+subreg_hard_regno (x, check_mode)
+     register rtx x;
+     int check_mode;
+{
+  enum machine_mode mode = GET_MODE (x);
+  unsigned int byte_offset, base_regno, final_regno;
+  rtx reg = SUBREG_REG (x);
+
+  /* This is where we attempt to catch illegal subregs
+     created by the compiler.  */
+  if (GET_CODE (x) != SUBREG
+      || GET_CODE (reg) != REG)
+    abort ();
+  base_regno = REGNO (reg);
+  if (base_regno >= FIRST_PSEUDO_REGISTER)
+    abort ();
+  if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
+    abort ();
+
+  /* Catch non-congruent offsets too.  */
+  byte_offset = SUBREG_BYTE (x);
+  if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
+    abort ();
+
+  final_regno = subreg_regno (x);
+
+  return final_regno;
+}
+
 /* Return a value representing some low-order bits of X, where the number
    of low-order bits is given by MODE.  Note that no conversion is done
    between floating-point and fixed-point values, rather, the bit 
@@ -653,22 +748,29 @@ gen_lowpart_common (mode, x)
      enum machine_mode mode;
      register rtx x;
 {
-  int word = 0;
+  int msize = GET_MODE_SIZE (mode);
+  int xsize = GET_MODE_SIZE (GET_MODE (x));
+  int offset = 0;
 
   if (GET_MODE (x) == mode)
     return x;
 
   /* MODE must occupy no more words than the mode of X.  */
   if (GET_MODE (x) != VOIDmode
-      && ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
-         > ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
-            / UNITS_PER_WORD)))
+      && ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
+         > ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
     return 0;
 
-  if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
-    word = ((GET_MODE_SIZE (GET_MODE (x))
-            - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
-           / UNITS_PER_WORD);
+  if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+      && xsize > msize)
+    {
+      int difference = xsize - msize;
+
+      if (WORDS_BIG_ENDIAN)
+       offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+      if (BYTES_BIG_ENDIAN)
+       offset += difference % UNITS_PER_WORD;
+    }
 
   if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
       && (GET_MODE_CLASS (mode) == MODE_INT
@@ -690,39 +792,40 @@ gen_lowpart_common (mode, x)
        return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
     }
   else if (GET_CODE (x) == SUBREG
-          && (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
-              || GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+          && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
               || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
-    return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
-           ? SUBREG_REG (x)
-           : gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + word));
+    {
+      int final_offset;
+
+      if (GET_MODE (SUBREG_REG (x)) == mode && subreg_lowpart_p (x))
+       return SUBREG_REG (x);
+
+      /* When working with SUBREGs the rule is that the byte
+        offset must be a multiple of the SUBREG's mode.  */
+      final_offset = SUBREG_BYTE (x) + offset;
+      final_offset = (final_offset / GET_MODE_SIZE (mode));
+      final_offset = (final_offset * GET_MODE_SIZE (mode));
+      return gen_rtx_SUBREG (mode, SUBREG_REG (x), final_offset);   
+    }
   else if (GET_CODE (x) == REG)
     {
-      /* Let the backend decide how many registers to skip.  This is needed
-         in particular for Sparc64 where fp regs are smaller than a word.  */
-      /* ??? Note that subregs are now ambiguous, in that those against
-        pseudos are sized by the Word Size, while those against hard
-        regs are sized by the underlying register size.  Better would be
-        to always interpret the subreg offset parameter as bytes or bits.  */
-
-      if (WORDS_BIG_ENDIAN && REGNO (x) < FIRST_PSEUDO_REGISTER
-         && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode))
-       word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
-               - HARD_REGNO_NREGS (REGNO (x), mode));
-
-      /* If the register is not valid for MODE, return 0.  If we don't
-        do this, there is no way to fix up the resulting REG later.  
-        But we do do this if the current REG is not valid for its
-        mode.  This latter is a kludge, but is required due to the
-        way that parameters are passed on some machines, most
-        notably Sparc.  */
-      if (REGNO (x) < FIRST_PSEUDO_REGISTER
-         && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode)
-         && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
-       return 0;
-      else if (REGNO (x) < FIRST_PSEUDO_REGISTER
+      /* Hard registers are done specially in certain cases.  */  
+      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+        {
+         int final_regno = REGNO (x) +
+                           subreg_regno_offset (REGNO (x), GET_MODE (x), 
+                                                offset, mode);
+
+         /* If the final regno is not valid for MODE, punt.  */
+         /* ??? We do allow it if the current REG is not valid for
+            ??? it's mode.  It is a kludge to work around how float/complex
+            ??? arguments are passed on 32-bit Sparc and should be fixed.  */
+         if (! HARD_REGNO_MODE_OK (final_regno, mode)
+             && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
+           return 0;
+
               /* integrate.c can't handle parts of a return value register. */
-              && (! REG_FUNCTION_VALUE_P (x)
+         if ((! REG_FUNCTION_VALUE_P (x)
                   || ! rtx_equal_function_value_matters)
 #ifdef CLASS_CANNOT_CHANGE_MODE
               && ! (CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (x))
@@ -739,9 +842,9 @@ gen_lowpart_common (mode, x)
               && x != arg_pointer_rtx
 #endif
               && x != stack_pointer_rtx)
-       return gen_rtx_REG (mode, REGNO (x) + word);
-      else
-       return gen_rtx_SUBREG (mode, x, word);
+           return gen_rtx_REG (mode, final_regno);
+         }
+      return gen_rtx_SUBREG (mode, x, offset);
     }
   /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
      from the low-order part of the constant.  */
@@ -834,7 +937,7 @@ gen_lowpart_common (mode, x)
           && GET_CODE (x) == CONST_DOUBLE
           && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
           && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
-    return operand_subword (x, word, 0, GET_MODE (x));
+    return constant_subword (x, (offset / UNITS_PER_WORD), GET_MODE (x));
 
   /* Similarly, if this is converting a floating-point value into a
      two-word integer, we can do this one word at a time and make an
@@ -850,11 +953,14 @@ gen_lowpart_common (mode, x)
           && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
           && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
     {
-      rtx lowpart
-       = operand_subword (x, word + WORDS_BIG_ENDIAN, 0, GET_MODE (x));
-      rtx highpart
-       = operand_subword (x, word + ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
-
+      rtx lowpart, highpart;
+
+      lowpart = constant_subword (x,
+                                 (offset / UNITS_PER_WORD) + WORDS_BIG_ENDIAN,
+                                 GET_MODE (x));
+      highpart = constant_subword (x,
+                                  (offset / UNITS_PER_WORD) + (! WORDS_BIG_ENDIAN),
+                                  GET_MODE (x));
       if (lowpart && GET_CODE (lowpart) == CONST_INT
          && highpart && GET_CODE (highpart) == CONST_INT)
        return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
@@ -988,7 +1094,8 @@ gen_realpart (mode, x)
           && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
           && REG_P (x)
           && REGNO (x) < FIRST_PSEUDO_REGISTER)
-    fatal ("Unable to access real part of complex value in a hard register on this target");
+    internal_error
+      ("Can't access real part of complex value in hard register");
   else if (WORDS_BIG_ENDIAN)
     return gen_highpart (mode, x);
   else
@@ -1007,11 +1114,12 @@ gen_imagpart (mode, x)
     return XEXP (x, 1);
   else if (WORDS_BIG_ENDIAN)
     return gen_lowpart (mode, x);
-  else if (!WORDS_BIG_ENDIAN
+  else if (! WORDS_BIG_ENDIAN
           && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
           && REG_P (x)
           && REGNO (x) < FIRST_PSEUDO_REGISTER)
-    fatal ("Unable to access imaginary part of complex value in a hard register on this target");
+    internal_error
+      ("can't access imaginary part of complex value in hard register");
   else
     return gen_highpart (mode, x);
 }
@@ -1028,7 +1136,7 @@ subreg_realpart_p (x)
   if (GET_CODE (x) != SUBREG)
     abort ();
 
-  return ((unsigned int) SUBREG_WORD (x) * UNITS_PER_WORD
+  return ((unsigned int) SUBREG_BYTE (x)
          < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
 }
 \f
@@ -1086,10 +1194,13 @@ gen_highpart (mode, x)
      enum machine_mode mode;
      register rtx x;
 {
+  unsigned int msize = GET_MODE_SIZE (mode);
+  unsigned int xsize = GET_MODE_SIZE (GET_MODE (x));
+
   /* This case loses if X is a subreg.  To catch bugs early,
      complain if an invalid MODE is used even in other cases.  */
-  if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
-      && GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
+  if (msize > UNITS_PER_WORD
+      && msize != GET_MODE_UNIT_SIZE (GET_MODE (x)))
     abort ();
   if (GET_CODE (x) == CONST_DOUBLE
 #if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
@@ -1106,15 +1217,14 @@ gen_highpart (mode, x)
   else if (GET_CODE (x) == MEM)
     {
       register int offset = 0;
+
       if (! WORDS_BIG_ENDIAN)
-       offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
-                 - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
+       offset = (MAX (xsize, UNITS_PER_WORD)
+                 - MAX (msize, UNITS_PER_WORD));
 
       if (! BYTES_BIG_ENDIAN
-         && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
-       offset -= (GET_MODE_SIZE (mode)
-                  - MIN (UNITS_PER_WORD,
-                         GET_MODE_SIZE (GET_MODE (x))));
+         && msize < UNITS_PER_WORD)
+       offset -= (msize - MIN (UNITS_PER_WORD, xsize));
 
       return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
     }
@@ -1123,46 +1233,47 @@ gen_highpart (mode, x)
       /* The only time this should occur is when we are looking at a
         multi-word item with a SUBREG whose mode is the same as that of the
         item.  It isn't clear what we would do if it wasn't.  */
-      if (SUBREG_WORD (x) != 0)
+      if (SUBREG_BYTE (x) != 0)
        abort ();
       return gen_highpart (mode, SUBREG_REG (x));
     }
   else if (GET_CODE (x) == REG)
     {
-      int word;
-
-      /* Let the backend decide how many registers to skip.  This is needed
-         in particular for sparc64 where fp regs are smaller than a word.  */
-      /* ??? Note that subregs are now ambiguous, in that those against
-        pseudos are sized by the word size, while those against hard
-        regs are sized by the underlying register size.  Better would be
-        to always interpret the subreg offset parameter as bytes or bits.  */
+      int offset = 0;
 
       if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
        abort ();
-      else if (WORDS_BIG_ENDIAN)
-       word = 0;
-      else if (REGNO (x) < FIRST_PSEUDO_REGISTER)
-       word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
-               - HARD_REGNO_NREGS (REGNO (x), mode));
-      else
-       word = ((GET_MODE_SIZE (GET_MODE (x))
-                - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
-               / UNITS_PER_WORD);
-
-      if (REGNO (x) < FIRST_PSEUDO_REGISTER
-         /* integrate.c can't handle parts of a return value register.  */
-         && (! REG_FUNCTION_VALUE_P (x)
-             || ! rtx_equal_function_value_matters)
+
+      if ((! WORDS_BIG_ENDIAN || ! BYTES_BIG_ENDIAN)
+         && xsize > msize)
+       {
+         int difference = xsize - msize;
+
+         if (! WORDS_BIG_ENDIAN)
+           offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+         if (! BYTES_BIG_ENDIAN)
+           offset += difference % UNITS_PER_WORD;
+       }
+      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+       {
+         int final_regno = REGNO (x) +
+           subreg_regno_offset (REGNO (x), GET_MODE (x), offset, mode);
+
+         /* integrate.c can't handle parts of a return value register.
+            ??? Then integrate.c should be fixed!
+            ??? What about CLASS_CANNOT_CHANGE_SIZE?  */
+         if ((! REG_FUNCTION_VALUE_P (x)
+              || ! rtx_equal_function_value_matters)
          /* We want to keep the stack, frame, and arg pointers special.  */
-         && x != frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-         && x != arg_pointer_rtx
+             && x != frame_pointer_rtx
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM 
+             && x != arg_pointer_rtx
 #endif
-         && x != stack_pointer_rtx)
-       return gen_rtx_REG (mode, REGNO (x) + word);
-      else
-       return gen_rtx_SUBREG (mode, x, word);
+             && x != stack_pointer_rtx)
+           return gen_rtx_REG (mode, final_regno);
+       }
+      /* Just generate a normal SUBREG.  */
+      return gen_rtx_SUBREG (mode, x, offset); 
     }
   else
     abort ();
@@ -1176,154 +1287,44 @@ int
 subreg_lowpart_p (x)
      rtx x;
 {
+  unsigned int offset = 0;
+  int difference = (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+                   - GET_MODE_SIZE (GET_MODE (x)));
+
   if (GET_CODE (x) != SUBREG)
     return 1;
   else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
     return 0;
 
-  if (WORDS_BIG_ENDIAN
-      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)
-    return (SUBREG_WORD (x)
-           == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
-                - MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))
-               / UNITS_PER_WORD));
+  if (difference > 0)
+    {
+      if (WORDS_BIG_ENDIAN)
+       offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+      if (BYTES_BIG_ENDIAN)
+       offset += difference % UNITS_PER_WORD;
+    }
 
-  return SUBREG_WORD (x) == 0;
+  return SUBREG_BYTE (x) == offset;
 }
 \f
-/* Return subword I of operand OP.
-   The word number, I, is interpreted as the word number starting at the
-   low-order address.  Word 0 is the low-order word if not WORDS_BIG_ENDIAN,
-   otherwise it is the high-order word.
 
-   If we cannot extract the required word, we return zero.  Otherwise, an
-   rtx corresponding to the requested word will be returned.
-
-   VALIDATE_ADDRESS is nonzero if the address should be validated.  Before
-   reload has completed, a valid address will always be returned.  After
-   reload, if a valid address cannot be returned, we return zero.
-
-   If VALIDATE_ADDRESS is zero, we simply form the required address; validating
-   it is the responsibility of the caller.
-
-   MODE is the mode of OP in case it is a CONST_INT.  */
+/* Helper routine for all the constant cases of operand_subword.
+   Some places invoke this directly.  */
 
 rtx
-operand_subword (op, i, validate_address, mode)
+constant_subword (op, offset, mode)
      rtx op;
-     unsigned int i;
-     int validate_address;
+     int offset;
      enum machine_mode mode;
 {
-  HOST_WIDE_INT val;
   int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
-
-  if (mode == VOIDmode)
-    mode = GET_MODE (op);
-
-  if (mode == VOIDmode)
-    abort ();
-
-  /* If OP is narrower than a word, fail. */
-  if (mode != BLKmode
-      && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
-    return 0;
-
-  /* If we want a word outside OP, return zero. */
-  if (mode != BLKmode
-      && (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
-    return const0_rtx;
+  HOST_WIDE_INT val;
 
   /* If OP is already an integer word, return it.  */
   if (GET_MODE_CLASS (mode) == MODE_INT
       && GET_MODE_SIZE (mode) == UNITS_PER_WORD)
     return op;
 
-  /* If OP is a REG or SUBREG, we can handle it very simply.  */
-  if (GET_CODE (op) == REG)
-    {
-      /* ??? There is a potential problem with this code.  It does not
-        properly handle extractions of a subword from a hard register
-        that is larger than word_mode.  Presumably the check for
-        HARD_REGNO_MODE_OK catches these most of these cases.  */
-
-      /* If OP is a hard register, but OP + I is not a hard register,
-        then extracting a subword is impossible.
-
-        For example, consider if OP is the last hard register and it is
-        larger than word_mode.  If we wanted word N (for N > 0) because a
-        part of that hard register was known to contain a useful value,
-        then OP + I would refer to a pseudo, not the hard register we
-        actually wanted.  */
-      if (REGNO (op) < FIRST_PSEUDO_REGISTER
-         && REGNO (op) + i >= FIRST_PSEUDO_REGISTER)
-       return 0;
-
-      /* If the register is not valid for MODE, return 0.  Note we
-        have to check both OP and OP + I since they may refer to
-        different parts of the register file.
-
-        Consider if OP refers to the last 96bit FP register and we want
-        subword 3 because that subword is known to contain a value we
-        needed.  */
-      if (REGNO (op) < FIRST_PSEUDO_REGISTER
-         && (! HARD_REGNO_MODE_OK (REGNO (op), word_mode)
-             || ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)))
-       return 0;
-      else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
-              || (REG_FUNCTION_VALUE_P (op)
-                  && rtx_equal_function_value_matters)
-              /* We want to keep the stack, frame, and arg pointers
-                 special.  */
-              || op == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-              || op == arg_pointer_rtx
-#endif
-              || op == stack_pointer_rtx)
-       return gen_rtx_SUBREG (word_mode, op, i);
-      else
-       return gen_rtx_REG (word_mode, REGNO (op) + i);
-    }
-  else if (GET_CODE (op) == SUBREG)
-    return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), i + SUBREG_WORD (op));
-  else if (GET_CODE (op) == CONCAT)
-    {
-      unsigned int partwords
-       = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
-
-      if (i < partwords)
-       return operand_subword (XEXP (op, 0), i, validate_address, mode);
-      return operand_subword (XEXP (op, 1), i - partwords,
-                             validate_address, mode);
-    }
-
-  /* Form a new MEM at the requested address.  */
-  if (GET_CODE (op) == MEM)
-    {
-      rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD);
-      rtx new;
-
-      if (validate_address)
-       {
-         if (reload_completed)
-           {
-             if (! strict_memory_address_p (word_mode, addr))
-               return 0;
-           }
-         else
-           addr = memory_address (word_mode, addr);
-       }
-
-      new = gen_rtx_MEM (word_mode, addr);
-      MEM_COPY_ATTRIBUTES (new, op);
-      return new;
-    }
-
-  /* The only remaining cases are when OP is a constant.  If the host and
-     target floating formats are the same, handling two-word floating
-     constants are easy.  Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
-     are defined as returning one or two 32 bit values, respectively,
-     and not values of BITS_PER_WORD bits.  */
 #ifdef REAL_ARITHMETIC
   /* The output is some bits, the width of the target machine's word.
      A wider-word host can surely hold them in a CONST_INT. A narrower-word
@@ -1350,12 +1351,12 @@ operand_subword (op, i, validate_address, mode)
         So we explicitly mask and sign-extend as necessary.  */
       if (BITS_PER_WORD == 32)
        {
-         val = k[i];
+         val = k[offset];
          val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
          return GEN_INT (val);
        }
 #if HOST_BITS_PER_WIDE_INT >= 64
-      else if (BITS_PER_WORD >= 64 && i == 0)
+      else if (BITS_PER_WORD >= 64 && offset == 0)
        {
          val = k[! WORDS_BIG_ENDIAN];
          val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
@@ -1365,10 +1366,10 @@ operand_subword (op, i, validate_address, mode)
 #endif
       else if (BITS_PER_WORD == 16)
        {
-         val = k[i >> 1];
-         if ((i & 1) == !WORDS_BIG_ENDIAN)
+         val = k[offset >> 1];
+         if ((offset & 1) == ! WORDS_BIG_ENDIAN)
            val >>= 16;
-         val &= 0xffff;
+         val = ((val & 0xffff) ^ 0x8000) - 0x8000;
          return GEN_INT (val);
        }
       else
@@ -1387,16 +1388,16 @@ operand_subword (op, i, validate_address, mode)
 
       if (BITS_PER_WORD == 32)
        {
-         val = k[i];
+         val = k[offset];
          val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
          return GEN_INT (val);
        }
 #if HOST_BITS_PER_WIDE_INT >= 64
-      else if (BITS_PER_WORD >= 64 && i <= 1)
+      else if (BITS_PER_WORD >= 64 && offset <= 1)
        {
-         val = k[i*2 + ! WORDS_BIG_ENDIAN];
+         val = k[offset * 2 + ! WORDS_BIG_ENDIAN];
          val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
-         val |= (HOST_WIDE_INT) k[i*2 + WORDS_BIG_ENDIAN] & 0xffffffff;
+         val |= (HOST_WIDE_INT) k[offset * 2 + WORDS_BIG_ENDIAN] & 0xffffffff;
          return GEN_INT (val);
        }
 #endif
@@ -1416,10 +1417,10 @@ operand_subword (op, i, validate_address, mode)
         compilers don't like a conditional inside macro args, so we have two
         copies of the return.  */
 #ifdef HOST_WORDS_BIG_ENDIAN
-      return GEN_INT (i == WORDS_BIG_ENDIAN
+      return GEN_INT (offset == WORDS_BIG_ENDIAN
                      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
 #else
-      return GEN_INT (i != WORDS_BIG_ENDIAN
+      return GEN_INT (offset != WORDS_BIG_ENDIAN
                      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
 #endif
     }
@@ -1445,9 +1446,9 @@ operand_subword (op, i, validate_address, mode)
 
       if (BITS_PER_WORD == 16)
        {
-         if ((i & 1) == !WORDS_BIG_ENDIAN)
+         if ((offset & 1) == ! WORDS_BIG_ENDIAN)
            val >>= 16;
-         val &= 0xffff;
+         val = ((val & 0xffff) ^ 0x8000) - 0x8000;
        }
 
       return GEN_INT (val);
@@ -1489,7 +1490,7 @@ operand_subword (op, i, validate_address, mode)
       
   /* The only remaining cases that we can handle are integers.
      Convert to proper endianness now since these cases need it.
-     At this point, i == 0 means the low-order word.  
+     At this point, offset == 0 means the low-order word.  
 
      We do not want to handle the case when BITS_PER_WORD <= HOST_BITS_PER_INT
      in general.  However, if OP is (const_int 0), we can just return
@@ -1504,39 +1505,184 @@ operand_subword (op, i, validate_address, mode)
     return 0;
 
   if (WORDS_BIG_ENDIAN)
-    i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;
+    offset = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - offset;
 
   /* Find out which word on the host machine this value is in and get
      it from the constant.  */
-  val = (i / size_ratio == 0
+  val = (offset / size_ratio == 0
         ? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))
         : (GET_CODE (op) == CONST_INT
            ? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));
 
   /* Get the value we want into the low bits of val.  */
   if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)
-    val = ((val >> ((i % size_ratio) * BITS_PER_WORD)));
+    val = ((val >> ((offset % size_ratio) * BITS_PER_WORD)));
 
   val = trunc_int_for_mode (val, word_mode);
 
   return GEN_INT (val);
 }
 
+/* Return subword OFFSET of operand OP.
+   The word number, OFFSET, is interpreted as the word number starting
+   at the low-order address.  OFFSET 0 is the low-order word if not
+   WORDS_BIG_ENDIAN, otherwise it is the high-order word.
+
+   If we cannot extract the required word, we return zero.  Otherwise,
+   an rtx corresponding to the requested word will be returned.
+
+   VALIDATE_ADDRESS is nonzero if the address should be validated.  Before
+   reload has completed, a valid address will always be returned.  After
+   reload, if a valid address cannot be returned, we return zero.
+
+   If VALIDATE_ADDRESS is zero, we simply form the required address; validating
+   it is the responsibility of the caller.
+
+   MODE is the mode of OP in case it is a CONST_INT.
+
+   ??? This is still rather broken for some cases.  The problem for the
+   moment is that all callers of this thing provide no 'goal mode' to
+   tell us to work with.  This exists because all callers were written
+   in a word based SUBREG world.  */
+
+rtx
+operand_subword (op, offset, validate_address, mode)
+     rtx op;
+     unsigned int offset;
+     int validate_address;
+     enum machine_mode mode;
+{
+  if (mode == VOIDmode)
+    mode = GET_MODE (op);
+
+  if (mode == VOIDmode)
+    abort ();
+
+  /* If OP is narrower than a word, fail. */
+  if (mode != BLKmode
+      && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
+    return 0;
+
+  /* If we want a word outside OP, return zero. */
+  if (mode != BLKmode
+      && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
+    return const0_rtx;
+
+  switch (GET_CODE (op))
+    {
+    case REG:
+    case SUBREG:
+    case CONCAT:
+    case MEM:
+      break;
+
+    default:
+      /* The only remaining cases are when OP is a constant.  If the host and
+        target floating formats are the same, handling two-word floating
+        constants are easy.  Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
+        are defined as returning one or two 32 bit values, respectively,
+        and not values of BITS_PER_WORD bits.  */
+      return constant_subword (op, offset, mode);
+    }
+
+  /* If OP is already an integer word, return it.  */
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_SIZE (mode) == UNITS_PER_WORD)
+    return op;
+
+  /* If OP is a REG or SUBREG, we can handle it very simply.  */
+  if (GET_CODE (op) == REG)
+    {
+      if (REGNO (op) < FIRST_PSEUDO_REGISTER)
+       {
+         int final_regno = REGNO (op) +
+           subreg_regno_offset (REGNO (op), GET_MODE (op),
+                               offset * UNITS_PER_WORD,
+                               word_mode);
+
+         /* If the register is not valid for MODE, return 0.  If we don't
+            do this, there is no way to fix up the resulting REG later.  */
+         if (! HARD_REGNO_MODE_OK (final_regno, word_mode))
+           return 0;
+
+         /* integrate.c can't handle parts of a return value register.
+            ??? Then integrate.c should be fixed!
+            ??? What about CLASS_CANNOT_CHANGE_SIZE?  */
+         if ((! REG_FUNCTION_VALUE_P (op)
+              || ! rtx_equal_function_value_matters)
+             /* ??? What about CLASS_CANNOT_CHANGE_SIZE?  */
+             /* We want to keep the stack, frame, and arg pointers
+                special.  */
+             && op != frame_pointer_rtx
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+             && op != arg_pointer_rtx
+#endif
+             && op != stack_pointer_rtx)
+           return gen_rtx_REG (word_mode, final_regno);
+       }
+
+      /* Just return a normal SUBREG.  */
+      return gen_rtx_SUBREG (word_mode, op,
+                            (offset * UNITS_PER_WORD));
+    }
+  else if (GET_CODE (op) == SUBREG)
+    {
+      int final_offset = ((offset * UNITS_PER_WORD) + SUBREG_BYTE (op));
+
+      /* When working with SUBREGs the rule is that the byte
+        offset must be a multiple of the SUBREG's mode.  */
+      final_offset = (final_offset / GET_MODE_SIZE (word_mode));
+      final_offset = (final_offset * GET_MODE_SIZE (word_mode));
+      return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), final_offset);
+    }
+  else if (GET_CODE (op) == CONCAT)
+    {
+      unsigned int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
+      if (offset < partwords)
+       return operand_subword (XEXP (op, 0), offset, validate_address, mode);
+      return operand_subword (XEXP (op, 1), offset - partwords,
+                             validate_address, mode);
+    }
+
+  /* Form a new MEM at the requested address.  */
+  if (GET_CODE (op) == MEM)
+    {
+      rtx addr = plus_constant (XEXP (op, 0), (offset * UNITS_PER_WORD));
+      rtx new;
+
+      if (validate_address)
+       {
+         if (reload_completed)
+           {
+             if (! strict_memory_address_p (word_mode, addr))
+               return 0;
+           }
+         else
+           addr = memory_address (word_mode, addr);
+       }
+
+      new = gen_rtx_MEM (word_mode, addr);
+      MEM_COPY_ATTRIBUTES (new, op);
+      return new;
+    }
+
+  /* Unreachable... (famous last words) */
+  abort ();
+}
+
 /* Similar to `operand_subword', but never return 0.  If we can't extract
    the required subword, put OP into a register and try again.  If that fails,
-   abort.  We always validate the address in this case.  It is not valid
-   to call this function after reload; it is mostly meant for RTL
-   generation. 
+   abort.  We always validate the address in this case.  
 
    MODE is the mode of OP, in case it is CONST_INT.  */
 
 rtx
-operand_subword_force (op, i, mode)
+operand_subword_force (op, offset, mode)
      rtx op;
-     unsigned int i;
+     unsigned int offset;
      enum machine_mode mode;
 {
-  rtx result = operand_subword (op, i, 1, mode);
+  rtx result = operand_subword (op, offset, 1, mode);
 
   if (result)
     return result;
@@ -1551,7 +1697,7 @@ operand_subword_force (op, i, mode)
        op = force_reg (mode, op);
     }
 
-  result = operand_subword (op, i, 1, mode);
+  result = operand_subword (op, offset, 1, mode);
   if (result == 0)
     abort ();
 
@@ -1637,7 +1783,7 @@ gen_label_rtx ()
   register rtx label;
 
   label = gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX,
-                             NULL_RTX, label_num++, NULL_PTR, NULL_PTR);
+                             NULL_RTX, label_num++, NULL, NULL);
 
   LABEL_NUSES (label) = 0;
   LABEL_ALTERNATE_NAME (label) = NULL;
@@ -1726,7 +1872,7 @@ unshare_all_rtl (fndecl, insn)
 
   /* Make sure that virtual parameters are not shared.  */
   for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
-    DECL_RTL (decl) = copy_rtx_if_shared (DECL_RTL (decl));
+    SET_DECL_RTL (decl, copy_rtx_if_shared (DECL_RTL (decl)));
 
   /* Make sure that virtual stack slots are not shared.  */
   unshare_all_decls (DECL_INITIAL (fndecl));
@@ -1801,7 +1947,8 @@ unshare_all_decls (blk)
 
   /* Copy shared decls.  */
   for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t))
-    DECL_RTL (t) = copy_rtx_if_shared (DECL_RTL (t));
+    if (DECL_RTL_SET_P (t))
+      SET_DECL_RTL (t, copy_rtx_if_shared (DECL_RTL (t)));
 
   /* Now process sub-blocks.  */
   for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t))
@@ -1818,7 +1965,8 @@ reset_used_decls (blk)
 
   /* Mark decls.  */
   for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t))
-    reset_used_flags (DECL_RTL (t));
+    if (DECL_RTL_SET_P (t))
+      reset_used_flags (DECL_RTL (t));
 
   /* Now process sub-blocks.  */
   for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t))
@@ -2374,6 +2522,32 @@ prev_cc0_setter (insn)
   return insn;
 }
 #endif
+
+/* Increment the label uses for all labels present in rtx.  */
+
+static void
+mark_label_nuses(x)
+    rtx x;
+{
+  register enum rtx_code code;
+  register int i, j;
+  register const char *fmt;
+
+  code = GET_CODE (x);
+  if (code == LABEL_REF)
+    LABEL_NUSES (XEXP (x, 0))++;
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+        mark_label_nuses (XEXP (x, i));
+      else if (fmt[i] == 'E')
+        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         mark_label_nuses (XVECEXP (x, i, j));
+    }
+}
+
 \f
 /* Try splitting insns that can be split for better scheduling.
    PAT is the pattern which might split.
@@ -2411,7 +2585,8 @@ try_split (pat, trial, last)
       if (GET_CODE (seq) == SEQUENCE)
        {
          int i;
-
+         rtx eh_note;
+         
          /* Avoid infinite loop if any insn of the result matches 
             the original pattern.  */
          for (i = 0; i < XVECLEN (seq, 0); i++)
@@ -2419,19 +2594,11 @@ try_split (pat, trial, last)
                && rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat))
              return trial;
 
-         /* If we are splitting a JUMP_INSN, look for the JUMP_INSN in
-            SEQ and copy our JUMP_LABEL to it.  If JUMP_LABEL is non-zero,
-            increment the usage count so we don't delete the label.  */
-
-         if (GET_CODE (trial) == JUMP_INSN)
-           for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
-             if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
-               {
-                 JUMP_LABEL (XVECEXP (seq, 0, i)) = JUMP_LABEL (trial);
-
-                 if (JUMP_LABEL (trial))
-                   LABEL_NUSES (JUMP_LABEL (trial))++;
-               }
+         /* Mark labels.  */
+         for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+           if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
+             mark_jump_label (PATTERN (XVECEXP (seq, 0, i)),
+                              XVECEXP (seq, 0, i), 0, 0);
 
          /* If we are splitting a CALL_INSN, look for the CALL_INSN
             in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it.  */
@@ -2441,6 +2608,26 @@ try_split (pat, trial, last)
                CALL_INSN_FUNCTION_USAGE (XVECEXP (seq, 0, i))
                  = CALL_INSN_FUNCTION_USAGE (trial);
 
+         /* Copy EH notes.  */
+         if ((eh_note = find_reg_note (trial, REG_EH_REGION, NULL_RTX)))
+           for (i = 0; i < XVECLEN (seq, 0); i++)
+             {
+               rtx insn = XVECEXP (seq, 0, i);
+               if (GET_CODE (insn) == CALL_INSN
+                   || (flag_non_call_exceptions 
+                       && may_trap_p (PATTERN (insn))))
+                 REG_NOTES (insn) 
+                   = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
+                                        REG_NOTES (insn));
+             }
+
+         /* If there are LABELS inside the split insns increment the
+            usage count so we don't delete the label.  */
+         if (GET_CODE (trial) == INSN)
+           for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+             if (GET_CODE (XVECEXP (seq, 0, i)) == INSN)
+               mark_label_nuses (PATTERN (XVECEXP (seq, 0, i)));
+
          tem = emit_insn_after (seq, before);
 
          delete_insn (trial);
@@ -2818,8 +3005,11 @@ reorder_insns_with_line_notes (from, to, after)
 void
 remove_unnecessary_notes ()
 {
+  rtx block_stack = NULL_RTX;
+  rtx eh_stack = NULL_RTX;
   rtx insn;
   rtx next;
+  rtx tmp;
 
   /* We must not remove the first instruction in the function because
      the compiler depends on the first instruction being a note.  */
@@ -2832,54 +3022,77 @@ remove_unnecessary_notes ()
       if (GET_CODE (insn) != NOTE)
        continue;
 
-      /* By now, all notes indicating lexical blocks should have
-        NOTE_BLOCK filled in.  */
-      if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
-          || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
-         && NOTE_BLOCK (insn) == NULL_TREE)
-       abort ();
-
-      /* Remove NOTE_INSN_DELETED notes.  */
-      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
-       remove_insn (insn);
-      else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
+      switch (NOTE_LINE_NUMBER (insn))
        {
+       case NOTE_INSN_DELETED:
+         remove_insn (insn);
+         break;
+
+       case NOTE_INSN_EH_REGION_BEG:
+         eh_stack = alloc_INSN_LIST (insn, eh_stack);
+         break;
+
+       case NOTE_INSN_EH_REGION_END:
+         /* Too many end notes.  */
+         if (eh_stack == NULL_RTX)
+           abort ();
+         /* Mismatched nesting.  */
+         if (NOTE_EH_HANDLER (XEXP (eh_stack, 0)) != NOTE_EH_HANDLER (insn))
+           abort ();
+         tmp = eh_stack;
+         eh_stack = XEXP (eh_stack, 1);
+         free_INSN_LIST_node (tmp);
+         break;
+
+       case NOTE_INSN_BLOCK_BEG:
+         /* By now, all notes indicating lexical blocks should have
+            NOTE_BLOCK filled in.  */
+         if (NOTE_BLOCK (insn) == NULL_TREE)
+           abort ();
+         block_stack = alloc_INSN_LIST (insn, block_stack);
+         break;
+
+       case NOTE_INSN_BLOCK_END:
+         /* Too many end notes.  */
+         if (block_stack == NULL_RTX)
+           abort ();
+         /* Mismatched nesting.  */
+         if (NOTE_BLOCK (XEXP (block_stack, 0)) != NOTE_BLOCK (insn))
+           abort ();
+         tmp = block_stack;
+         block_stack = XEXP (block_stack, 1);
+         free_INSN_LIST_node (tmp);
+
          /* Scan back to see if there are any non-note instructions
             between INSN and the beginning of this block.  If not,
             then there is no PC range in the generated code that will
             actually be in this block, so there's no point in
             remembering the existence of the block.  */
-         rtx prev;
-
-         for (prev = PREV_INSN (insn); prev; prev = PREV_INSN (prev))
+         for (tmp = PREV_INSN (insn); tmp ; tmp = PREV_INSN (tmp))
            {
              /* This block contains a real instruction.  Note that we
                 don't include labels; if the only thing in the block
                 is a label, then there are still no PC values that
                 lie within the block.  */
-             if (INSN_P (prev))
+             if (INSN_P (tmp))
                break;
 
              /* We're only interested in NOTEs.  */
-             if (GET_CODE (prev) != NOTE)
+             if (GET_CODE (tmp) != NOTE)
                continue;
 
-             if (NOTE_LINE_NUMBER (prev) == NOTE_INSN_BLOCK_BEG)
+             if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_BEG)
                {
-                 /* If the BLOCKs referred to by these notes don't
-                    match, then something is wrong with our BLOCK
-                    nesting structure.  */
-                 if (NOTE_BLOCK (prev) != NOTE_BLOCK (insn))
-                   abort ();
-
+                 /* We just verified that this BLOCK matches us
+                    with the block_stack check above.  */
                  if (debug_ignore_block (NOTE_BLOCK (insn)))
                    {
-                     remove_insn (prev);
+                     remove_insn (tmp);
                      remove_insn (insn);
                    }
                  break;
                }
-             else if (NOTE_LINE_NUMBER (prev) == NOTE_INSN_BLOCK_END)
+             else if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_END)
                /* There's a nested block.  We need to leave the
                   current block in place since otherwise the debugger
                   wouldn't be able to show symbols from our block in
@@ -2888,6 +3101,10 @@ remove_unnecessary_notes ()
            }
        }
     }
+
+  /* Too many begin notes.  */
+  if (block_stack || eh_stack)
+    abort ();
 }
 
 \f
@@ -4053,30 +4270,30 @@ init_emit_once (line_numbers)
 
   pc_rtx = gen_rtx (PC, VOIDmode);
   cc0_rtx = gen_rtx (CC0, VOIDmode);
-  stack_pointer_rtx = gen_rtx_raw_REG (Pmode, STACK_POINTER_REGNUM);
-  frame_pointer_rtx = gen_rtx_raw_REG (Pmode, FRAME_POINTER_REGNUM);
+  stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
+  frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
   if (hard_frame_pointer_rtx == 0)
-    hard_frame_pointer_rtx = gen_rtx_raw_REG (Pmode, 
-                                             HARD_FRAME_POINTER_REGNUM);
+    hard_frame_pointer_rtx = gen_raw_REG (Pmode, 
+                                         HARD_FRAME_POINTER_REGNUM);
   if (arg_pointer_rtx == 0)
-    arg_pointer_rtx = gen_rtx_raw_REG (Pmode, ARG_POINTER_REGNUM);
+    arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM);
   virtual_incoming_args_rtx = 
-    gen_rtx_raw_REG (Pmode, VIRTUAL_INCOMING_ARGS_REGNUM);
+    gen_raw_REG (Pmode, VIRTUAL_INCOMING_ARGS_REGNUM);
   virtual_stack_vars_rtx = 
-    gen_rtx_raw_REG (Pmode, VIRTUAL_STACK_VARS_REGNUM);
+    gen_raw_REG (Pmode, VIRTUAL_STACK_VARS_REGNUM);
   virtual_stack_dynamic_rtx = 
-    gen_rtx_raw_REG (Pmode, VIRTUAL_STACK_DYNAMIC_REGNUM);
+    gen_raw_REG (Pmode, VIRTUAL_STACK_DYNAMIC_REGNUM);
   virtual_outgoing_args_rtx = 
-    gen_rtx_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM); 
-  virtual_cfa_rtx = gen_rtx_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
+    gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM); 
+  virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
 
   /* These rtx must be roots if GC is enabled.  */
   ggc_add_rtx_root (global_rtl, GR_MAX);
 
 #ifdef INIT_EXPANDERS
-  /* This is to initialize save_machine_status and restore_machine_status before
-     the first call to push_function_context_to.  This is needed by the Chill
-     front end which calls push_function_context_to before the first cal to
+  /* This is to initialize {init|mark|free}_machine_status before the first
+     call to push_function_context_to.  This is needed by the Chill front
+     end which calls push_function_context_to before the first cal to
      init_function_start.  */
   INIT_EXPANDERS;
 #endif
@@ -4132,9 +4349,9 @@ init_emit_once (line_numbers)
        const_tiny_rtx[i][(int) mode] = GEN_INT (i);
     }
 
-  for (mode = CCmode; mode < MAX_MACHINE_MODE; ++mode)
-    if (GET_MODE_CLASS (mode) == MODE_CC)
-      const_tiny_rtx[0][(int) mode] = const0_rtx;
+  for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)
+    if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC)
+      const_tiny_rtx[0][i] = const0_rtx;
 
   const_tiny_rtx[0][(int) BImode] = const0_rtx;
   if (STORE_FLAG_VALUE == 1)
@@ -4148,7 +4365,7 @@ init_emit_once (line_numbers)
 
 #ifdef RETURN_ADDRESS_POINTER_REGNUM
   return_address_pointer_rtx
-    = gen_rtx_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
+    = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
 #endif
 
 #ifdef STRUCT_VALUE
@@ -4190,9 +4407,8 @@ init_emit_once (line_numbers)
 #endif
 #endif
 
-#ifdef PIC_OFFSET_TABLE_REGNUM
-  pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
-#endif
+  if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
+    pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
 
   ggc_add_rtx_root (&pic_offset_table_rtx, 1);
   ggc_add_rtx_root (&struct_value_rtx, 1);