OSDN Git Service

2001-11-11 H.J. Lu <hjl@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 861e73b..9242e79 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC 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 version.
+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
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 /* Middle-to-low level generation of rtx code and insns.
@@ -54,6 +54,8 @@ Boston, MA 02111-1307, USA.  */
 #include "bitmap.h"
 #include "basic-block.h"
 #include "ggc.h"
+#include "debug.h"
+#include "langhooks.h"
 
 /* Commonly used modes.  */
 
@@ -143,6 +145,9 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
 
 static htab_t const_int_htab;
 
+/* A hash table storing memory attribute structures.  */
+static htab_t mem_attrs_htab;
+
 /* start_sequence and gen_sequence can make a lot of rtx expressions which are
    shortly thrown away.  We use two mechanisms to prevent this waste:
 
@@ -174,6 +179,8 @@ static rtx make_jump_insn_raw               PARAMS ((rtx));
 static rtx make_call_insn_raw          PARAMS ((rtx));
 static rtx find_line_note              PARAMS ((rtx));
 static void mark_sequence_stack         PARAMS ((struct sequence_stack *));
+static rtx change_address_1            PARAMS ((rtx, enum machine_mode, rtx,
+                                                int));
 static void unshare_all_rtl_1          PARAMS ((rtx));
 static void unshare_all_decls          PARAMS ((tree));
 static void reset_used_decls           PARAMS ((tree));
@@ -181,9 +188,17 @@ 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 *));
-static int rtx_htab_mark_1              PARAMS ((void **, void *));
-static void rtx_htab_mark               PARAMS ((void *));
-
+static hashval_t mem_attrs_htab_hash    PARAMS ((const void *));
+static int mem_attrs_htab_eq            PARAMS ((const void *,
+                                                const void *));
+static void mem_attrs_mark             PARAMS ((const void *));
+static mem_attrs *get_mem_attrs                PARAMS ((HOST_WIDE_INT, tree, rtx,
+                                                rtx, unsigned int,
+                                                enum machine_mode));
+
+/* Probability of the conditional branch currently proceeded by try_split.
+   Set to -1 otherwise.  */
+int split_branch_probability = -1;
 \f
 /* Returns a hash code for X (which is a really a CONST_INT).  */
 
@@ -206,26 +221,93 @@ const_int_htab_eq (x, y)
   return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) y));
 }
 
-/* Mark the hash-table element X (which is really a pointer to an
-   rtx).  */
+/* Returns a hash code for X (which is a really a mem_attrs *).  */
+
+static hashval_t
+mem_attrs_htab_hash (x)
+     const void *x;
+{
+  mem_attrs *p = (mem_attrs *) x;
+
+  return (p->alias ^ (p->align * 1000)
+         ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
+         ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
+         ^ (long) p->decl);
+}
+
+/* Returns non-zero if the value represented by X (which is really a
+   mem_attrs *) is the same as that given by Y (which is also really a
+   mem_attrs *).  */
 
 static int
-rtx_htab_mark_1 (x, data)
-     void **x;
-     void *data ATTRIBUTE_UNUSED;
+mem_attrs_htab_eq (x, y)
+     const void *x;
+     const void *y;
 {
-  ggc_mark_rtx (*x);
-  return 1;
+  mem_attrs *p = (mem_attrs *) x;
+  mem_attrs *q = (mem_attrs *) y;
+
+  return (p->alias == q->alias && p->decl == q->decl && p->offset == q->offset
+         && p->size == q->size && p->align == q->align);
 }
 
-/* Mark all the elements of HTAB (which is really an htab_t full of
-   rtxs).  */
+/* This routine is called when we determine that we need a mem_attrs entry.
+   It marks the associated decl and RTL as being used, if present.  */
 
 static void
-rtx_htab_mark (htab)
-     void *htab;
+mem_attrs_mark (x)
+     const void *x;
 {
-  htab_traverse (*((htab_t *) htab), rtx_htab_mark_1, NULL);
+  mem_attrs *p = (mem_attrs *) x;
+
+  if (p->decl)
+    ggc_mark_tree (p->decl);
+
+  if (p->offset)
+    ggc_mark_rtx (p->offset);
+
+  if (p->size)
+    ggc_mark_rtx (p->size);
+}
+
+/* Allocate a new mem_attrs structure and insert it into the hash table if
+   one identical to it is not already in the table.  We are doing this for
+   MEM of mode MODE.  */
+
+static mem_attrs *
+get_mem_attrs (alias, decl, offset, size, align, mode)
+     HOST_WIDE_INT alias;
+     tree decl;
+     rtx offset;
+     rtx size;
+     unsigned int align;
+     enum machine_mode mode;
+{
+  mem_attrs attrs;
+  void **slot;
+
+  /* If everything is the default, we can just return zero.  */
+  if (alias == 0 && decl == 0 && offset == 0
+      && (size == 0
+         || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
+      && (align == 1
+         || (mode != BLKmode && align == GET_MODE_ALIGNMENT (mode))))
+    return 0;
+
+  attrs.alias = alias;
+  attrs.decl = decl;
+  attrs.offset = offset;
+  attrs.size = size;
+  attrs.align = align;
+
+  slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT);
+  if (*slot == 0)
+    {
+      *slot = ggc_alloc (sizeof (mem_attrs));
+      memcpy (*slot, &attrs, sizeof (mem_attrs));
+    }
+
+  return *slot;
 }
 
 /* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
@@ -274,21 +356,19 @@ gen_rtx_CONST_INT (mode, arg)
    only at run-time.  */
 
 rtx
-gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2)
+gen_rtx_CONST_DOUBLE (mode, arg0, arg1)
      enum machine_mode mode;
-     rtx arg0;
-     HOST_WIDE_INT arg1, arg2;
+     HOST_WIDE_INT arg0, arg1;
 {
   rtx r = rtx_alloc (CONST_DOUBLE);
   int i;
 
   PUT_MODE (r, mode);
-  XEXP (r, 0) = arg0;
-  X0EXP (r, 1) = NULL_RTX;
+  X0EXP (r, 0) = NULL_RTX;
+  XWINT (r, 1) = arg0;
   XWINT (r, 2) = arg1;
-  XWINT (r, 3) = arg2;
 
-  for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 3; --i)
+  for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 2; --i)
     XWINT (r, i) = 0;
 
   return r;
@@ -345,7 +425,7 @@ gen_rtx_MEM (mode, addr)
 
   /* This field is not cleared by the mere allocation of the rtx, so
      we clear it here.  */
-  MEM_ALIAS_SET (rt) = 0;
+  MEM_ATTRS (rt) = 0;
 
   return rt;
 }
@@ -372,9 +452,9 @@ gen_rtx_SUBREG (mode, reg, offset)
   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. */
+/* 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;
@@ -419,21 +499,13 @@ gen_lowpart_SUBREG (mode, reg)
 rtx
 gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  enum rtx_code code;
-  enum machine_mode mode;
-#endif
-  va_list p;
-  register int i;              /* Array indices...                     */
-  register const char *fmt;    /* Current rtx's format...              */
-  register rtx rt_val;         /* RTX to return to caller...           */
+  int i;               /* Array indices...                     */
+  const char *fmt;     /* Current rtx's format...              */
+  rtx rt_val;          /* RTX to return to caller...           */
 
-  VA_START (p, mode);
-
-#ifndef ANSI_PROTOTYPES
-  code = va_arg (p, enum rtx_code);
-  mode = va_arg (p, enum machine_mode);
-#endif
+  VA_OPEN (p, mode);
+  VA_FIXEDARG (p, enum rtx_code, code);
+  VA_FIXEDARG (p, enum machine_mode, mode);
 
   switch (code)
     {
@@ -443,10 +515,10 @@ gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
 
     case CONST_DOUBLE:
       {
-       rtx arg0 = va_arg (p, rtx);
+       HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
        HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
-       HOST_WIDE_INT arg2 = va_arg (p, HOST_WIDE_INT);
-        rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2);
+
+        rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1);
       }
       break;
 
@@ -506,7 +578,7 @@ gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
       break;
     }
 
-  va_end (p);
+  VA_CLOSE (p);
   return rt_val;
 }
 
@@ -520,18 +592,11 @@ gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
 rtvec
 gen_rtvec VPARAMS ((int n, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  int n;
-#endif
-  int i;
-  va_list p;
+  int i, save_n;
   rtx *vector;
 
-  VA_START (p, n);
-
-#ifndef ANSI_PROTOTYPES
-  n = va_arg (p, int);
-#endif
+  VA_OPEN (p, n);
+  VA_FIXEDARG (p, int, n);
 
   if (n == 0)
     return NULL_RTVEC;         /* Don't allocate an empty rtvec...     */
@@ -540,9 +605,12 @@ gen_rtvec VPARAMS ((int n, ...))
 
   for (i = 0; i < n; i++)
     vector[i] = va_arg (p, rtx);
-  va_end (p);
 
-  return gen_rtvec_v (n, vector);
+  /* The definition of VA_* in K&R C causes `n' to go out of scope.  */
+  save_n = n;
+  VA_CLOSE (p);
+
+  return gen_rtvec_v (save_n, vector);
 }
 
 rtvec
@@ -550,8 +618,8 @@ gen_rtvec_v (n, argp)
      int n;
      rtx *argp;
 {
-  register int i;
-  register rtvec rt_val;
+  int i;
+  rtvec rt_val;
 
   if (n == 0)
     return NULL_RTVEC;         /* Don't allocate an empty rtvec...     */
@@ -563,7 +631,6 @@ gen_rtvec_v (n, argp)
 
   return rt_val;
 }
-
 \f
 /* Generate a REG rtx for a new pseudo register of mode MODE.
    This pseudo is assigned the next sequential register number.  */
@@ -573,7 +640,7 @@ gen_reg_rtx (mode)
      enum machine_mode mode;
 {
   struct function *f = cfun;
-  register rtx val;
+  rtx val;
 
   /* Don't let anything called after initial flow analysis create new
      registers.  */
@@ -602,14 +669,16 @@ gen_reg_rtx (mode)
       return gen_rtx_CONCAT (mode, realpart, imagpart);
     }
 
-  /* Make sure regno_pointer_align and regno_reg_rtx are large enough
-     to have an element for this pseudo reg number.  */
+  /* Make sure regno_pointer_align, regno_decl, and regno_reg_rtx are large
+     enough to have an element for this pseudo reg number.  */
 
   if (reg_rtx_no == f->emit->regno_pointer_align_length)
     {
       int old_size = f->emit->regno_pointer_align_length;
-      rtx *new1;
       char *new;
+      rtx *new1;
+      tree *new2;
+
       new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
       memset (new + old_size, 0, old_size);
       f->emit->regno_pointer_align = (unsigned char *) new;
@@ -619,6 +688,11 @@ gen_reg_rtx (mode)
       memset (new1 + old_size, 0, old_size * sizeof (rtx));
       regno_reg_rtx = new1;
 
+      new2 = (tree *) xrealloc (f->emit->regno_decl,
+                               old_size * 2 * sizeof (tree));
+      memset (new2 + old_size, 0, old_size * sizeof (tree));
+      f->emit->regno_decl = new2;
+
       f->emit->regno_pointer_align_length = old_size * 2;
     }
 
@@ -694,7 +768,7 @@ get_first_label_num ()
    register.  */
 int
 subreg_hard_regno (x, check_mode)
-     register rtx x;
+     rtx x;
      int check_mode;
 {
   enum machine_mode mode = GET_MODE (x);
@@ -736,7 +810,7 @@ subreg_hard_regno (x, check_mode)
 rtx
 gen_lowpart_common (mode, x)
      enum machine_mode mode;
-     register rtx x;
+     rtx x;
 {
   int msize = GET_MODE_SIZE (mode);
   int xsize = GET_MODE_SIZE (GET_MODE (x));
@@ -1020,7 +1094,7 @@ gen_lowpart_common (mode, x)
 rtx
 gen_realpart (mode, x)
      enum machine_mode mode;
-     register rtx x;
+     rtx x;
 {
   if (WORDS_BIG_ENDIAN
       && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
@@ -1040,7 +1114,7 @@ gen_realpart (mode, x)
 rtx
 gen_imagpart (mode, x)
      enum machine_mode mode;
-     register rtx x;
+     rtx x;
 {
   if (WORDS_BIG_ENDIAN)
     return gen_lowpart (mode, x);
@@ -1080,7 +1154,7 @@ subreg_realpart_p (x)
 rtx
 gen_lowpart (mode, x)
      enum machine_mode mode;
-     register rtx x;
+     rtx x;
 {
   rtx result = gen_lowpart_common (mode, x);
 
@@ -1097,7 +1171,7 @@ gen_lowpart (mode, x)
   else if (GET_CODE (x) == MEM)
     {
       /* The only additional case we can do is MEM.  */
-      register int offset = 0;
+      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));
@@ -1122,7 +1196,7 @@ gen_lowpart (mode, x)
 rtx
 gen_highpart (mode, x)
      enum machine_mode mode;
-     register rtx x;
+     rtx x;
 {
   unsigned int msize = GET_MODE_SIZE (mode);
   rtx result;
@@ -1146,6 +1220,23 @@ gen_highpart (mode, x)
     abort ();
   return result;
 }
+
+/* Like gen_highpart_mode, but accept mode of EXP operand in case EXP can
+   be VOIDmode constant.  */
+rtx
+gen_highpart_mode (outermode, innermode, exp)
+    enum machine_mode outermode, innermode;
+    rtx exp;
+{
+  if (GET_MODE (exp) != VOIDmode)
+    {
+      if (GET_MODE (exp) != innermode)
+       abort ();
+      return gen_highpart (outermode, exp);
+    }
+  return simplify_gen_subreg (outermode, exp, innermode,
+                             subreg_highpart_offset (outermode, innermode));
+}
 /* Return offset in bytes to get OUTERMODE low part
    of the value in mode INNERMODE stored in memory in target format.  */
 
@@ -1461,12 +1552,12 @@ operand_subword (op, offset, validate_address, mode)
   if (mode == VOIDmode)
     abort ();
 
-  /* If OP is narrower than a word, fail. */
+  /* 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 we want a word outside OP, return zero.  */
   if (mode != BLKmode
       && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
     return const0_rtx;
@@ -1474,23 +1565,18 @@ operand_subword (op, offset, 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;
+      rtx new = adjust_address_nv (op, word_mode, offset * UNITS_PER_WORD);
+
+      if (! validate_address)
+       return new;
 
-      if (validate_address)
+      else if (reload_completed)
        {
-         if (reload_completed)
-           {
-             if (! strict_memory_address_p (word_mode, addr))
-               return 0;
-           }
-         else
-           addr = memory_address (word_mode, addr);
+         if (! strict_memory_address_p (word_mode, XEXP (new, 0)))
+           return 0;
        }
-
-      new = gen_rtx_MEM (word_mode, addr);
-      MEM_COPY_ATTRIBUTES (new, op);
-      return new;
+      else
+       return replace_equiv_address (new, XEXP (new, 0));
     }
 
   /* Rest can be handled by simplify_subreg.  */
@@ -1564,16 +1650,173 @@ reverse_comparison (insn)
     }
 }
 \f
-/* Return a memory reference like MEMREF, but with its mode changed
-   to MODE and its address changed to ADDR.
-   (VOIDmode means don't change the mode.
-   NULL for ADDR means don't change the address.)  */
 
-rtx
-change_address (memref, mode, addr)
+/* Given REF, a MEM, and T, either the type of X or the expression
+   corresponding to REF, set the memory attributes.  OBJECTP is nonzero
+   if we are making a new object of this type.  */
+
+void
+set_mem_attributes (ref, t, objectp)
+     rtx ref;
+     tree t;
+     int objectp;
+{
+  HOST_WIDE_INT alias = MEM_ALIAS_SET (ref);
+  tree decl = MEM_DECL (ref);
+  rtx offset = MEM_OFFSET (ref);
+  rtx size = MEM_SIZE (ref);
+  unsigned int align = MEM_ALIGN (ref);
+  tree type;
+
+  /* It can happen that type_for_mode was given a mode for which there
+     is no language-level type.  In which case it returns NULL, which
+     we can see here.  */
+  if (t == NULL_TREE)
+    return;
+
+  type = TYPE_P (t) ? t : TREE_TYPE (t);
+
+  /* If we have already set DECL_RTL = ref, get_alias_set will get the
+     wrong answer, as it assumes that DECL_RTL already has the right alias
+     info.  Callers should not set DECL_RTL until after the call to
+     set_mem_attributes.  */
+  if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
+    abort ();
+
+  /* Get the alias set from the expression or type (perhaps using a
+     front-end routine) and use it.  */
+  alias = get_alias_set (t);
+
+  MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
+  MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
+  RTX_UNCHANGING_P (ref)
+    |= ((lang_hooks.honor_readonly
+        && (TYPE_READONLY (type) || TREE_READONLY (t)))
+       || (! TYPE_P (t) && TREE_CONSTANT (t)));
+
+  /* If we are making an object of this type, or if this is a DECL, we know
+     that it is a scalar if the type is not an aggregate.  */
+  if ((objectp || DECL_P (t)) && ! AGGREGATE_TYPE_P (type))
+    MEM_SCALAR_P (ref) = 1;
+
+  /* If the size is known, we can set that.  */
+  if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
+    size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1));
+
+  /* If T is not a type, we may be able to deduce some more information about
+     the expression.  */
+  if (! TYPE_P (t))
+    {
+      maybe_set_unchanging (ref, t);
+      if (TREE_THIS_VOLATILE (t))
+       MEM_VOLATILE_P (ref) = 1;
+
+      /* Now remove any NOPs: they don't change what the underlying object is.
+        Likewise for SAVE_EXPR.  */
+      while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
+            || TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
+       t = TREE_OPERAND (t, 0);
+
+      /* If this expression can't be addressed (e.g., it contains a reference
+        to a non-addressable field), show we don't change its alias set.  */
+      if (! can_address_p (t))
+       MEM_KEEP_ALIAS_SET_P (ref) = 1;
+
+      /* If this is a decl, set the attributes of the MEM from it.  */
+      if (DECL_P (t))
+       {
+         decl = t;
+         offset = GEN_INT (0);
+         size = (DECL_SIZE_UNIT (t)
+                 && host_integerp (DECL_SIZE_UNIT (t), 1)
+                 ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
+         align =  DECL_ALIGN (t);
+       }
+
+      /* If this is an INDIRECT_REF, we know its alignment.  */
+      else if (TREE_CODE (t) == INDIRECT_REF)
+       align = TYPE_ALIGN (type);
+
+      /* Likewise for constants.  */
+      else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
+       {
+         align = TYPE_ALIGN (type);
+#ifdef CONSTANT_ALIGNMENT
+         align = CONSTANT_ALIGNMENT (t, align);
+#endif
+       }
+    }
+
+  /* Now set the attributes we computed above.  */
+  MEM_ATTRS (ref)
+    = get_mem_attrs (alias, decl, offset, size, align, GET_MODE (ref));
+
+  /* If this is already known to be a scalar or aggregate, we are done.  */
+  if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
+    return;
+
+  /* If it is a reference into an aggregate, this is part of an aggregate.
+     Otherwise we don't know.  */
+  else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
+          || TREE_CODE (t) == ARRAY_RANGE_REF
+          || TREE_CODE (t) == BIT_FIELD_REF)
+    MEM_IN_STRUCT_P (ref) = 1;
+}
+
+/* Set the alias set of MEM to SET.  */
+
+void
+set_mem_alias_set (mem, set)
+     rtx mem;
+     HOST_WIDE_INT set;
+{
+#ifdef ENABLE_CHECKING 
+  /* If the new and old alias sets don't conflict, something is wrong.  */
+  if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
+    abort ();
+#endif
+
+  MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
+                                  MEM_SIZE (mem), MEM_ALIGN (mem),
+                                  GET_MODE (mem));
+}
+
+/* Set the alignment of MEM to ALIGN bits.  */
+
+void
+set_mem_align (mem, align)
+     rtx mem;
+     unsigned int align;
+{
+  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_DECL (mem),
+                                  MEM_OFFSET (mem), MEM_SIZE (mem), align,
+                                  GET_MODE (mem));
+}
+
+/* Set the decl for MEM to DECL.  */
+
+void
+set_mem_decl (mem, decl)
+     rtx mem;
+     tree decl;
+{
+  MEM_ATTRS (mem)
+    = get_mem_attrs (MEM_ALIAS_SET (mem), decl, MEM_OFFSET (mem),
+                    MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
+}
+\f
+/* Return a memory reference like MEMREF, but with its mode changed to MODE
+   and its address changed to ADDR.  (VOIDmode means don't change the mode.
+   NULL for ADDR means don't change the address.)  VALIDATE is nonzero if the
+   returned memory location is required to be valid.  The memory
+   attributes are not changed.  */
+
+static rtx
+change_address_1 (memref, mode, addr, validate)
      rtx memref;
      enum machine_mode mode;
      rtx addr;
+     int validate;
 {
   rtx new;
 
@@ -1584,15 +1827,16 @@ change_address (memref, mode, addr)
   if (addr == 0)
     addr = XEXP (memref, 0);
 
-  /* If reload is in progress or has completed, ADDR must be valid.
-     Otherwise, we can call memory_address to make it valid.  */
-  if (reload_completed || reload_in_progress)
+  if (validate)
     {
-      if (! memory_address_p (mode, addr))
-       abort ();
+      if (reload_in_progress || reload_completed)
+       {
+         if (! memory_address_p (mode, addr))
+           abort ();
+       }
+      else
+       addr = memory_address (mode, addr);
     }
-  else
-    addr = memory_address (mode, addr);
 
   if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
     return memref;
@@ -1601,19 +1845,133 @@ change_address (memref, mode, addr)
   MEM_COPY_ATTRIBUTES (new, memref);
   return new;
 }
+
+/* Like change_address_1 with VALIDATE nonzero, but we are not saying in what
+   way we are changing MEMREF, so we only preserve the alias set.  */
+
+rtx
+change_address (memref, mode, addr)
+     rtx memref;
+     enum machine_mode mode;
+     rtx addr;
+{
+  rtx new = change_address_1 (memref, mode, addr, 1);
+  enum machine_mode mmode = GET_MODE (new);
+
+  MEM_ATTRS (new)
+    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0,
+                    mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode)),
+                    (mmode == BLKmode ? 1
+                     : GET_MODE_ALIGNMENT (mmode) / BITS_PER_UNIT),
+                    mmode);
+
+  return new;
+}
+
 /* Return a memory reference like MEMREF, but with its mode changed
-   to MODE and its address offset by OFFSET bytes.  */
+   to MODE and its address offset by OFFSET bytes.  If VALIDATE is
+   nonzero, the memory address is forced to be valid.  */
 
 rtx
-adjust_address (memref, mode, offset)
+adjust_address_1 (memref, mode, offset, validate)
      rtx memref;
      enum machine_mode mode;
      HOST_WIDE_INT offset;
+     int validate;
 {
-  /* For now, this is just a wrapper for change_address, but eventually
-     will do memref tracking.  */
-  return
-    change_address (memref, mode, plus_constant (XEXP (memref, 0), offset));
+  rtx addr = XEXP (memref, 0);
+  rtx new;
+  rtx memoffset = MEM_OFFSET (memref);
+  rtx size = 0;
+  unsigned int memalign = MEM_ALIGN (memref);
+
+  /* If MEMREF is a LO_SUM and the offset is within the alignment of the
+     object, we can merge it into the LO_SUM.  */
+  if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM
+      && offset >= 0
+      && (unsigned HOST_WIDE_INT) offset
+         < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
+    addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
+                          plus_constant (XEXP (addr, 1), offset));
+  else if (offset == 0)
+    /* ??? Prefer to create garbage instead of creating shared rtl.  */
+    addr = copy_rtx (addr);
+  else
+    addr = plus_constant (addr, offset);
+
+  new = change_address_1 (memref, mode, addr, validate);
+
+  /* Compute the new values of the memory attributes due to this adjustment.
+     We add the offsets and update the alignment.  */
+  if (memoffset)
+    memoffset = GEN_INT (offset + INTVAL (memoffset));
+
+  /* Compute the new alignment by taking the MIN of the alignment and the
+     lowest-order set bit in OFFSET, but don't change the alignment if OFFSET
+     if zero.  */
+  if (offset != 0)
+    memalign = MIN (memalign, (offset & -offset) * BITS_PER_UNIT);
+
+  /* We can compute the size in a number of ways.  */
+  if (mode != BLKmode)
+    size = GEN_INT (GET_MODE_SIZE (mode));
+  else if (MEM_SIZE (memref))
+    size = plus_constant (MEM_SIZE (memref), -offset);
+
+  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
+                                  memoffset, size, memalign, GET_MODE (new));
+
+  /* At some point, we should validate that this offset is within the object,
+     if all the appropriate values are known.  */
+  return new;
+}
+
+/* Return a memory reference like MEMREF, but whose address is changed by
+   adding OFFSET, an RTX, to it.  POW2 is the highest power of two factor
+   known to be in OFFSET (possibly 1).  */
+
+rtx
+offset_address (memref, offset, pow2)
+     rtx memref;
+     rtx offset;
+     HOST_WIDE_INT pow2;
+{
+  rtx new = change_address_1 (memref, VOIDmode,
+                             gen_rtx_PLUS (Pmode, XEXP (memref, 0),
+                                           force_reg (Pmode, offset)), 1);
+
+  /* Update the alignment to reflect the offset.  Reset the offset, which
+     we don't know.  */
+  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
+                                  0, 0, MIN (MEM_ALIGN (memref),
+                                             pow2 * BITS_PER_UNIT),
+                                  GET_MODE (new));
+  return new;
+}
+  
+/* Return a memory reference like MEMREF, but with its address changed to
+   ADDR.  The caller is asserting that the actual piece of memory pointed
+   to is the same, just the form of the address is being changed, such as
+   by putting something into a register.  */
+
+rtx
+replace_equiv_address (memref, addr)
+     rtx memref;
+     rtx addr;
+{
+  /* change_address_1 copies the memory attribute structure without change
+     and that's exactly what we want here.  */
+  return change_address_1 (memref, VOIDmode, addr, 1);
+}
+
+/* Likewise, but the reference is not required to be valid.  */
+
+rtx
+replace_equiv_address_nv (memref, addr)
+     rtx memref;
+     rtx addr;
+{
+  return change_address_1 (memref, VOIDmode, addr, 0);
 }
 \f
 /* Return a newly created CODE_LABEL rtx with a unique label number.  */
@@ -1621,7 +1979,7 @@ adjust_address (memref, mode, offset)
 rtx
 gen_label_rtx ()
 {
-  register rtx label;
+  rtx label;
 
   label = gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX,
                              NULL_RTX, label_num++, NULL, NULL);
@@ -1697,6 +2055,7 @@ free_emit_status (f)
 {
   free (f->emit->x_regno_reg_rtx);
   free (f->emit->regno_pointer_align);
+  free (f->emit->regno_decl);
   free (f->emit);
   f->emit = NULL;
 }
@@ -1797,7 +2156,7 @@ unshare_all_decls (blk)
 }
 
 /* Go through all virtual stack slots of a function and mark them as
-   not shared. */
+   not shared.  */
 static void
 reset_used_decls (blk)
      tree blk;
@@ -1821,10 +2180,10 @@ rtx
 copy_rtx_if_shared (orig)
      rtx orig;
 {
-  register rtx x = orig;
-  register int i;
-  register enum rtx_code code;
-  register const char *format_ptr;
+  rtx x = orig;
+  int i;
+  enum rtx_code code;
+  const char *format_ptr;
   int copied = 0;
 
   if (x == 0)
@@ -1888,7 +2247,7 @@ copy_rtx_if_shared (orig)
 
   if (x->used)
     {
-      register rtx copy;
+      rtx copy;
 
       copy = rtx_alloc (code);
       memcpy (copy, x,
@@ -1917,7 +2276,7 @@ copy_rtx_if_shared (orig)
        case 'E':
          if (XVEC (x, i) != NULL)
            {
-             register int j;
+             int j;
              int len = XVECLEN (x, i);
 
              if (copied && len > 0)
@@ -1938,9 +2297,9 @@ void
 reset_used_flags (x)
      rtx x;
 {
-  register int i, j;
-  register enum rtx_code code;
-  register const char *format_ptr;
+  int i, j;
+  enum rtx_code code;
+  const char *format_ptr;
 
   if (x == 0)
     return;
@@ -2370,9 +2729,9 @@ static void
 mark_label_nuses(x)
     rtx x;
 {
-  register enum rtx_code code;
-  register int i, j;
-  register const char *fmt;
+  enum rtx_code code;
+  int i, j;
+  const char *fmt;
 
   code = GET_CODE (x);
   if (code == LABEL_REF)
@@ -2406,9 +2765,19 @@ try_split (pat, trial, last)
 {
   rtx before = PREV_INSN (trial);
   rtx after = NEXT_INSN (trial);
-  rtx seq = split_insns (pat, trial);
   int has_barrier = 0;
   rtx tem;
+  rtx note, seq;
+  int probability;
+
+  if (any_condjump_p (trial)
+      && (note = find_reg_note (trial, REG_BR_PROB, 0)))
+    split_branch_probability = INTVAL (XEXP (note, 0));
+  probability = split_branch_probability;
+
+  seq = split_insns (pat, trial);
+
+  split_branch_probability = -1;
 
   /* If we are splitting a JUMP_INSN, it might be followed by a BARRIER.
      We may need to handle this specially.  */
@@ -2425,8 +2794,7 @@ try_split (pat, trial, last)
         it, in turn, will be split (SFmode on the 29k is an example).  */
       if (GET_CODE (seq) == SEQUENCE)
        {
-         int i;
-         rtx eh_note;
+         int i, njumps = 0;
 
          /* Avoid infinite loop if any insn of the result matches
             the original pattern.  */
@@ -2438,8 +2806,27 @@ try_split (pat, trial, last)
          /* 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);
+             {
+               rtx insn = XVECEXP (seq, 0, i);
+               mark_jump_label (PATTERN (insn),
+                                XVECEXP (seq, 0, i), 0);
+               njumps++;
+               if (probability != -1
+                   && any_condjump_p (insn)
+                   && !find_reg_note (insn, REG_BR_PROB, 0))
+                 {
+                   /* We can preserve the REG_BR_PROB notes only if exactly
+                      one jump is created, otherwise the machinde description
+                      is responsible for this step using
+                      split_branch_probability variable.  */
+                   if (njumps != 1)
+                     abort ();
+                   REG_NOTES (insn)
+                     = gen_rtx_EXPR_LIST (REG_BR_PROB,
+                                          GEN_INT (probability),
+                                          REG_NOTES (insn));
+                 }
+             }
 
          /* If we are splitting a CALL_INSN, look for the CALL_INSN
             in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it.  */
@@ -2449,18 +2836,55 @@ 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));
-             }
+         /* Copy notes, particularly those related to the CFG.  */
+         for (note = REG_NOTES (trial); note ; note = XEXP (note, 1))
+           {
+             switch (REG_NOTE_KIND (note))
+               {
+               case REG_EH_REGION:
+                 for (i = XVECLEN (seq, 0) - 1; i >= 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 (note, 0),
+                                              REG_NOTES (insn));
+                   }
+                 break;
+
+               case REG_NORETURN:
+               case REG_SETJMP:
+               case REG_ALWAYS_RETURN:
+                 for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+                   {
+                     rtx insn = XVECEXP (seq, 0, i);
+                     if (GET_CODE (insn) == CALL_INSN)
+                       REG_NOTES (insn)
+                         = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
+                                              XEXP (note, 0),
+                                              REG_NOTES (insn));
+                   }
+                 break;
+
+               case REG_NON_LOCAL_GOTO:
+                 for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+                   {
+                     rtx insn = XVECEXP (seq, 0, i);
+                     if (GET_CODE (insn) == JUMP_INSN)
+                       REG_NOTES (insn)
+                         = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
+                                              XEXP (note, 0),
+                                              REG_NOTES (insn));
+                   }
+                 break;
+
+               default:
+                 break;
+               }
+           }
 
          /* If there are LABELS inside the split insns increment the
             usage count so we don't delete the label.  */
@@ -2469,9 +2893,9 @@ try_split (pat, trial, last)
              if (GET_CODE (XVECEXP (seq, 0, i)) == INSN)
                mark_label_nuses (PATTERN (XVECEXP (seq, 0, i)));
 
-         tem = emit_insn_after (seq, before);
+         tem = emit_insn_after (seq, trial);
 
-         delete_insn (trial);
+         delete_related_insns (trial);
          if (has_barrier)
            emit_barrier_after (tem);
 
@@ -2497,8 +2921,8 @@ try_split (pat, trial, last)
       /* Return either the first or the last insn, depending on which was
         requested.  */
       return last
-               ? (after ? prev_active_insn (after) : last_insn)
-               : next_active_insn (before);
+               ? (after ? PREV_INSN (after) : last_insn)
+               : NEXT_INSN (before);
     }
 
   return trial;
@@ -2511,7 +2935,7 @@ rtx
 make_insn_raw (pattern)
      rtx pattern;
 {
-  register rtx insn;
+  rtx insn;
 
   insn = rtx_alloc (INSN);
 
@@ -2542,7 +2966,7 @@ static rtx
 make_jump_insn_raw (pattern)
      rtx pattern;
 {
-  register rtx insn;
+  rtx insn;
 
   insn = rtx_alloc (JUMP_INSN);
   INSN_UID (insn) = cur_insn_uid++;
@@ -2562,7 +2986,7 @@ static rtx
 make_call_insn_raw (pattern)
      rtx pattern;
 {
-  register rtx insn;
+  rtx insn;
 
   insn = rtx_alloc (CALL_INSN);
   INSN_UID (insn) = cur_insn_uid++;
@@ -2581,7 +3005,7 @@ make_call_insn_raw (pattern)
 
 void
 add_insn (insn)
-     register rtx insn;
+     rtx insn;
 {
   PREV_INSN (insn) = last_insn;
   NEXT_INSN (insn) = 0;
@@ -2605,6 +3029,7 @@ add_insn_after (insn, after)
      rtx insn, after;
 {
   rtx next = NEXT_INSN (after);
+  basic_block bb;
 
   if (optimize && INSN_DELETED_P (after))
     abort ();
@@ -2635,6 +3060,21 @@ add_insn_after (insn, after)
        abort ();
     }
 
+  if (basic_block_for_insn
+      && (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements
+      && (bb = BLOCK_FOR_INSN (after)))
+    {
+      set_block_for_insn (insn, bb);
+      /* Should not happen as first in the BB is always
+        eigther NOTE or LABEL.  */
+      if (bb->end == after
+         /* Avoid clobbering of structure when creating new BB.  */
+         && GET_CODE (insn) != BARRIER
+         && (GET_CODE (insn) != NOTE
+             || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
+       bb->end = insn;
+    }
+
   NEXT_INSN (after) = insn;
   if (GET_CODE (after) == INSN && GET_CODE (PATTERN (after)) == SEQUENCE)
     {
@@ -2653,6 +3093,7 @@ add_insn_before (insn, before)
      rtx insn, before;
 {
   rtx prev = PREV_INSN (before);
+  basic_block bb;
 
   if (optimize && INSN_DELETED_P (before))
     abort ();
@@ -2686,6 +3127,21 @@ add_insn_before (insn, before)
        abort ();
     }
 
+  if (basic_block_for_insn
+      && (unsigned int)INSN_UID (before) < basic_block_for_insn->num_elements
+      && (bb = BLOCK_FOR_INSN (before)))
+    {
+      set_block_for_insn (insn, bb);
+      /* Should not happen as first in the BB is always
+        eigther NOTE or LABEl.  */
+      if (bb->head == insn
+         /* Avoid clobbering of structure when creating new BB.  */
+         && GET_CODE (insn) != BARRIER
+         && (GET_CODE (insn) != NOTE
+             || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
+       abort ();
+    }
+
   PREV_INSN (before) = insn;
   if (GET_CODE (before) == INSN && GET_CODE (PATTERN (before)) == SEQUENCE)
     PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
@@ -2699,6 +3155,8 @@ remove_insn (insn)
 {
   rtx next = NEXT_INSN (insn);
   rtx prev = PREV_INSN (insn);
+  basic_block bb;
+
   if (prev)
     {
       NEXT_INSN (prev) = next;
@@ -2747,6 +3205,21 @@ remove_insn (insn)
       if (stack == 0)
        abort ();
     }
+  if (basic_block_for_insn
+      && (unsigned int)INSN_UID (insn) < basic_block_for_insn->num_elements
+      && (bb = BLOCK_FOR_INSN (insn)))
+    {
+      if (bb->head == insn)
+       {
+         /* Never ever delete the basic block note without deleting whole basic
+            block.  */
+         if (GET_CODE (insn) == NOTE)
+           abort ();
+         bb->head = next;
+       }
+      if (bb->end == insn)
+       bb->end = prev;
+    }
 }
 
 /* Delete all insns made since FROM.
@@ -2774,7 +3247,7 @@ delete_insns_since (from)
    called after delay-slot filling has been done.  */
 
 void
-reorder_insns (from, to, after)
+reorder_insns_nobb (from, to, after)
      rtx from, to, after;
 {
   /* Splice this bunch out of where it is now.  */
@@ -2798,6 +3271,38 @@ reorder_insns (from, to, after)
     last_insn = to;
 }
 
+/* Same as function above, but take care to update BB boundaries.  */
+void
+reorder_insns (from, to, after)
+     rtx from, to, after;
+{
+  rtx prev = PREV_INSN (from);
+  basic_block bb, bb2;
+
+  reorder_insns_nobb (from, to, after);
+
+  if (basic_block_for_insn
+      && (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements
+      && (bb = BLOCK_FOR_INSN (after)))
+    {
+      rtx x;
+      if (basic_block_for_insn
+         && (unsigned int)INSN_UID (from) < basic_block_for_insn->num_elements
+         && (bb2 = BLOCK_FOR_INSN (from)))
+       {
+         if (bb2->end == to)
+           bb2->end = prev;
+       }
+
+      if (bb->end == after)
+       bb->end = to;
+
+      for (x = from; x != NEXT_INSN (to); x = NEXT_INSN (x))
+       set_block_for_insn (x, bb);
+    }
+}
+
 /* Return the line note insn preceding INSN.  */
 
 static rtx
@@ -2924,9 +3429,13 @@ remove_unnecessary_notes ()
 
              if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_BEG)
                {
-                 /* We just verified that this BLOCK matches us
-                    with the block_stack check above.  */
-                 if (debug_ignore_block (NOTE_BLOCK (insn)))
+                 /* We just verified that this BLOCK matches us with
+                    the block_stack check above.  Never delete the
+                    BLOCK for the outermost scope of the function; we
+                    can refer to names from that scope even if the
+                    block notes are messed up.  */
+                 if (! is_body_block (NOTE_BLOCK (insn))
+                     && (*debug_hooks->ignore_block) (NOTE_BLOCK (insn)))
                    {
                      remove_insn (tmp);
                      remove_insn (insn);
@@ -2957,13 +3466,13 @@ remove_unnecessary_notes ()
 
 rtx
 emit_insn_before (pattern, before)
-     register rtx pattern, before;
+     rtx pattern, before;
 {
-  register rtx insn = before;
+  rtx insn = before;
 
   if (GET_CODE (pattern) == SEQUENCE)
     {
-      register int i;
+      int i;
 
       for (i = 0; i < XVECLEN (pattern, 0); i++)
        {
@@ -2980,28 +3489,14 @@ emit_insn_before (pattern, before)
   return insn;
 }
 
-/* Similar to emit_insn_before, but update basic block boundaries as well.  */
-
-rtx
-emit_block_insn_before (pattern, before, block)
-     rtx pattern, before;
-     basic_block block;
-{
-  rtx prev = PREV_INSN (before);
-  rtx r = emit_insn_before (pattern, before);
-  if (block && block->head == before)
-    block->head = NEXT_INSN (prev);
-  return r;
-}
-
 /* Make an instruction with body PATTERN and code JUMP_INSN
    and output it before the instruction BEFORE.  */
 
 rtx
 emit_jump_insn_before (pattern, before)
-     register rtx pattern, before;
+     rtx pattern, before;
 {
-  register rtx insn;
+  rtx insn;
 
   if (GET_CODE (pattern) == SEQUENCE)
     insn = emit_insn_before (pattern, before);
@@ -3019,9 +3514,9 @@ emit_jump_insn_before (pattern, before)
 
 rtx
 emit_call_insn_before (pattern, before)
-     register rtx pattern, before;
+     rtx pattern, before;
 {
-  register rtx insn;
+  rtx insn;
 
   if (GET_CODE (pattern) == SEQUENCE)
     insn = emit_insn_before (pattern, before);
@@ -3040,9 +3535,9 @@ emit_call_insn_before (pattern, before)
 
 rtx
 emit_barrier_before (before)
-     register rtx before;
+     rtx before;
 {
-  register rtx insn = rtx_alloc (BARRIER);
+  rtx insn = rtx_alloc (BARRIER);
 
   INSN_UID (insn) = cur_insn_uid++;
 
@@ -3074,7 +3569,7 @@ emit_note_before (subtype, before)
      int subtype;
      rtx before;
 {
-  register rtx note = rtx_alloc (NOTE);
+  rtx note = rtx_alloc (NOTE);
   INSN_UID (note) = cur_insn_uid++;
   NOTE_SOURCE_FILE (note) = 0;
   NOTE_LINE_NUMBER (note) = subtype;
@@ -3088,13 +3583,13 @@ emit_note_before (subtype, before)
 
 rtx
 emit_insn_after (pattern, after)
-     register rtx pattern, after;
+     rtx pattern, after;
 {
-  register rtx insn = after;
+  rtx insn = after;
 
   if (GET_CODE (pattern) == SEQUENCE)
     {
-      register int i;
+      int i;
 
       for (i = 0; i < XVECLEN (pattern, 0); i++)
        {
@@ -3134,27 +3629,14 @@ emit_insn_after_with_line_notes (pattern, after, from)
                          insn);
 }
 
-/* Similar to emit_insn_after, but update basic block boundaries as well.  */
-
-rtx
-emit_block_insn_after (pattern, after, block)
-     rtx pattern, after;
-     basic_block block;
-{
-  rtx r = emit_insn_after (pattern, after);
-  if (block && block->end == after)
-    block->end = r;
-  return r;
-}
-
 /* Make an insn of code JUMP_INSN with body PATTERN
    and output it after the insn AFTER.  */
 
 rtx
 emit_jump_insn_after (pattern, after)
-     register rtx pattern, after;
+     rtx pattern, after;
 {
-  register rtx insn;
+  rtx insn;
 
   if (GET_CODE (pattern) == SEQUENCE)
     insn = emit_insn_after (pattern, after);
@@ -3172,9 +3654,9 @@ emit_jump_insn_after (pattern, after)
 
 rtx
 emit_barrier_after (after)
-     register rtx after;
+     rtx after;
 {
-  register rtx insn = rtx_alloc (BARRIER);
+  rtx insn = rtx_alloc (BARRIER);
 
   INSN_UID (insn) = cur_insn_uid++;
 
@@ -3207,7 +3689,7 @@ emit_note_after (subtype, after)
      int subtype;
      rtx after;
 {
-  register rtx note = rtx_alloc (NOTE);
+  rtx note = rtx_alloc (NOTE);
   INSN_UID (note) = cur_insn_uid++;
   NOTE_SOURCE_FILE (note) = 0;
   NOTE_LINE_NUMBER (note) = subtype;
@@ -3223,7 +3705,7 @@ emit_line_note_after (file, line, after)
      int line;
      rtx after;
 {
-  register rtx note;
+  rtx note;
 
   if (no_line_numbers && line > 0)
     {
@@ -3254,7 +3736,7 @@ emit_insn (pattern)
 
   if (GET_CODE (pattern) == SEQUENCE)
     {
-      register int i;
+      int i;
 
       for (i = 0; i < XVECLEN (pattern, 0); i++)
        {
@@ -3317,20 +3799,32 @@ emit_insns_before (insn, before)
 
 rtx
 emit_insns_after (first, after)
-     register rtx first;
-     register rtx after;
+     rtx first;
+     rtx after;
 {
-  register rtx last;
-  register rtx after_after;
+  rtx last;
+  rtx after_after;
+  basic_block bb;
 
   if (!after)
     abort ();
 
   if (!first)
-    return first;
+    return after;
 
-  for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
-    continue;
+  if (basic_block_for_insn
+      && (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements
+      && (bb = BLOCK_FOR_INSN (after)))
+    {
+      for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+       set_block_for_insn (last, bb);
+      set_block_for_insn (last, bb);
+      if (bb->end == after)
+       bb->end = last;
+    }
+  else
+    for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+      continue;
 
   after_after = NEXT_INSN (after);
 
@@ -3356,7 +3850,7 @@ emit_jump_insn (pattern)
     return emit_insn (pattern);
   else
     {
-      register rtx insn = make_jump_insn_raw (pattern);
+      rtx insn = make_jump_insn_raw (pattern);
       add_insn (insn);
       return insn;
     }
@@ -3373,7 +3867,7 @@ emit_call_insn (pattern)
     return emit_insn (pattern);
   else
     {
-      register rtx insn = make_call_insn_raw (pattern);
+      rtx insn = make_call_insn_raw (pattern);
       add_insn (insn);
       PUT_CODE (insn, CALL_INSN);
       return insn;
@@ -3403,7 +3897,7 @@ emit_label (label)
 rtx
 emit_barrier ()
 {
-  register rtx barrier = rtx_alloc (BARRIER);
+  rtx barrier = rtx_alloc (BARRIER);
   INSN_UID (barrier) = cur_insn_uid++;
   add_insn (barrier);
   return barrier;
@@ -3439,7 +3933,7 @@ emit_note (file, line)
      const char *file;
      int line;
 {
-  register rtx note;
+  rtx note;
 
   if (line > 0)
     {
@@ -3485,9 +3979,9 @@ force_next_line_note ()
 }
 
 /* Place a note of KIND on insn INSN with DATUM as the datum. If a
-   note of this type already exists, remove it first. */
+   note of this type already exists, remove it first.  */
 
-void
+rtx
 set_unique_reg_note (insn, kind, datum)
      rtx insn;
      enum reg_note kind;
@@ -3495,11 +3989,20 @@ set_unique_reg_note (insn, kind, datum)
 {
   rtx note = find_reg_note (insn, kind, NULL_RTX);
 
-  /* First remove the note if there already is one.  */
+  /* Don't add ASM_OPERAND REG_EQUAL/REG_EQUIV notes.
+     It serves no useful purpose and breaks eliminate_regs.  */
+  if ((kind == REG_EQUAL || kind == REG_EQUIV)
+      && GET_CODE (datum) == ASM_OPERANDS)
+    return NULL_RTX;
+
   if (note)
-    remove_note (insn, note);
+    {
+      XEXP (note, 0) = datum;
+      return note;
+    }
 
   REG_NOTES (insn) = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn));
+  return REG_NOTES (insn);
 }
 \f
 /* Return an indication of which type of insn should have X as a body.
@@ -3526,7 +4029,7 @@ classify_insn (x)
     }
   if (GET_CODE (x) == PARALLEL)
     {
-      register int j;
+      int j;
       for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
        if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
          return CALL_INSN;
@@ -3555,7 +4058,7 @@ emit (x)
     return emit_insn (x);
   else if (code == JUMP_INSN)
     {
-      register rtx insn = emit_jump_insn (x);
+      rtx insn = emit_jump_insn (x);
       if (any_uncondjump_p (insn) || GET_CODE (x) == RETURN)
        return emit_barrier ();
       return insn;
@@ -3746,7 +4249,7 @@ gen_sequence ()
   if (len == 1
       && ! RTX_FRAME_RELATED_P (first_insn)
       && GET_CODE (first_insn) == INSN
-      /* Don't throw away any reg notes. */
+      /* Don't throw away any reg notes.  */
       && REG_NOTES (first_insn) == 0)
     return PATTERN (first_insn);
 
@@ -3812,12 +4315,12 @@ static rtvec copy_asm_constraints_vector;
 
 rtx
 copy_insn_1 (orig)
-     register rtx orig;
+     rtx orig;
 {
-  register rtx copy;
-  register int i, j;
-  register RTX_CODE code;
-  register const char *format_ptr;
+  rtx copy;
+  int i, j;
+  RTX_CODE code;
+  const char *format_ptr;
 
   code = GET_CODE (orig);
 
@@ -3986,8 +4489,10 @@ init_emit ()
                                 sizeof (unsigned char));
 
   regno_reg_rtx
-    = (rtx *) xcalloc (f->emit->regno_pointer_align_length * sizeof (rtx),
-                      sizeof (rtx));
+    = (rtx *) xcalloc (f->emit->regno_pointer_align_length, sizeof (rtx));
+
+  f->emit->regno_decl
+    = (tree *) xcalloc (f->emit->regno_pointer_align_length, sizeof (tree));
 
   /* Put copies of all the virtual register rtx into regno_reg_rtx.  */
   init_virtual_regs (f->emit);
@@ -4044,14 +4549,19 @@ mark_emit_status (es)
      struct emit_status *es;
 {
   rtx *r;
+  tree *t;
   int i;
 
   if (es == 0)
     return;
 
-  for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx;
-       i > 0; --i, ++r)
-    ggc_mark_rtx (*r);
+  for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx,
+       t = es->regno_decl;
+       i > 0; --i, ++r, ++t)
+    {
+      ggc_mark_rtx (*r);
+      ggc_mark_tree (*t);
+    }
 
   mark_sequence_stack (es->sequence_stack);
   ggc_mark_tree (es->sequence_rtl_expr);
@@ -4069,11 +4579,14 @@ init_emit_once (line_numbers)
   enum machine_mode mode;
   enum machine_mode double_mode;
 
-  /* Initialize the CONST_INT hash table.  */
+  /* Initialize the CONST_INT and memory attribute hash tables.  */
   const_int_htab = htab_create (37, const_int_htab_hash,
                                const_int_htab_eq, NULL);
-  ggc_add_root (&const_int_htab, 1, sizeof (const_int_htab),
-               rtx_htab_mark);
+  ggc_add_deletable_htab (const_int_htab, 0, 0);
+
+  mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
+                               mem_attrs_htab_eq, NULL);
+  ggc_add_deletable_htab (mem_attrs_htab, 0, mem_attrs_mark);
 
   no_line_numbers = ! line_numbers;
 
@@ -4178,7 +4691,6 @@ init_emit_once (line_numbers)
            CONST_DOUBLE_HIGH (tem) = 0;
 
          memcpy (&CONST_DOUBLE_LOW (tem), &u, sizeof u);
-         CONST_DOUBLE_MEM (tem) = cc0_rtx;
          CONST_DOUBLE_CHAIN (tem) = NULL_RTX;
          PUT_MODE (tem, mode);