OSDN Git Service

* doc/invoke.texi (-fdump-unnumbered): Update docs when line number
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 351c70b..17f8c2d 100644 (file)
@@ -1,6 +1,7 @@
 /* Emit RTL for the GCC expander.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -104,7 +105,7 @@ REAL_VALUE_TYPE dconstm1;
 REAL_VALUE_TYPE dconstm2;
 REAL_VALUE_TYPE dconsthalf;
 REAL_VALUE_TYPE dconstthird;
-REAL_VALUE_TYPE dconstpi;
+REAL_VALUE_TYPE dconstsqrt2;
 REAL_VALUE_TYPE dconste;
 
 /* All references to the following fixed hard registers go through
@@ -164,11 +165,8 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
 #define last_location (cfun->emit->x_last_location)
 #define first_label_num (cfun->emit->x_first_label_num)
 
-static rtx make_jump_insn_raw (rtx);
 static rtx make_call_insn_raw (rtx);
-static rtx find_line_note (rtx);
 static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
-static void unshare_all_decls (tree);
 static void reset_used_decls (tree);
 static void mark_label_nuses (rtx);
 static hashval_t const_int_htab_hash (const void *);
@@ -254,7 +252,7 @@ mem_attrs_htab_hash (const void *x)
   return (p->alias ^ (p->align * 1000)
          ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
          ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
-         ^ (size_t) p->expr);
+         ^ (size_t) iterative_hash_expr (p->expr, 0));
 }
 
 /* Returns nonzero if the value represented by X (which is really a
@@ -267,8 +265,11 @@ mem_attrs_htab_eq (const void *x, const void *y)
   mem_attrs *p = (mem_attrs *) x;
   mem_attrs *q = (mem_attrs *) y;
 
-  return (p->alias == q->alias && p->expr == q->expr && p->offset == q->offset
-         && p->size == q->size && p->align == q->align);
+  return (p->alias == q->alias && p->offset == q->offset
+         && p->size == q->size && p->align == q->align
+         && (p->expr == q->expr
+             || (p->expr != NULL_TREE && q->expr != NULL_TREE
+                 && operand_equal_p (p->expr, q->expr, 0))));
 }
 
 /* Allocate a new mem_attrs structure and insert it into the hash table if
@@ -426,7 +427,7 @@ const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode)
   rtx real = rtx_alloc (CONST_DOUBLE);
   PUT_MODE (real, mode);
 
-  memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE));
+  real->u.rv = value;
 
   return lookup_const_double (real);
 }
@@ -442,64 +443,28 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode)
   rtx value;
   unsigned int i;
 
+  /* There are the following cases (note that there are no modes with
+     HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode) < 2 * HOST_BITS_PER_WIDE_INT):
+
+     1) If GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT, then we use
+       gen_int_mode.
+     2) GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT, but the value of
+       the integer fits into HOST_WIDE_INT anyway (i.e., i1 consists only
+       from copies of the sign bit, and sign of i0 and i1 are the same),  then 
+       we return a CONST_INT for i0.
+     3) Otherwise, we create a CONST_DOUBLE for i0 and i1.  */
   if (mode != VOIDmode)
     {
-      int width;
-      
       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
                  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
                  /* We can get a 0 for an error mark.  */
                  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
                  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
 
-      /* We clear out all bits that don't belong in MODE, unless they and
-        our sign bit are all one.  So we get either a reasonable negative
-        value or a reasonable unsigned value for this mode.  */
-      width = GET_MODE_BITSIZE (mode);
-      if (width < HOST_BITS_PER_WIDE_INT
-         && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
-             != ((HOST_WIDE_INT) (-1) << (width - 1))))
-       i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
-      else if (width == HOST_BITS_PER_WIDE_INT
-              && ! (i1 == ~0 && i0 < 0))
-       i1 = 0;
-      else
-       /* We should be able to represent this value as a constant.  */
-       gcc_assert (width <= 2 * HOST_BITS_PER_WIDE_INT);
-
-      /* If this would be an entire word for the target, but is not for
-        the host, then sign-extend on the host so that the number will
-        look the same way on the host that it would on the target.
-
-        For example, when building a 64 bit alpha hosted 32 bit sparc
-        targeted compiler, then we want the 32 bit unsigned value -1 to be
-        represented as a 64 bit value -1, and not as 0x00000000ffffffff.
-        The latter confuses the sparc backend.  */
-
-      if (width < HOST_BITS_PER_WIDE_INT
-         && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
-       i0 |= ((HOST_WIDE_INT) (-1) << width);
-
-      /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a
-        CONST_INT.
-
-        ??? Strictly speaking, this is wrong if we create a CONST_INT for
-        a large unsigned constant with the size of MODE being
-        HOST_BITS_PER_WIDE_INT and later try to interpret that constant
-        in a wider mode.  In that case we will mis-interpret it as a
-        negative number.
-
-        Unfortunately, the only alternative is to make a CONST_DOUBLE for
-        any constant in any mode if it is an unsigned constant larger
-        than the maximum signed integer in an int on the host.  However,
-        doing this will break everyone that always expects to see a
-        CONST_INT for SImode and smaller.
-
-        We have always been making CONST_INTs in this case, so nothing
-        new is being broken.  */
-
-      if (width <= HOST_BITS_PER_WIDE_INT)
-       i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0;
+      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+       return gen_int_mode (i0, mode);
+
+      gcc_assert (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT);
     }
 
   /* If this integer fits in one word, return a CONST_INT.  */
@@ -607,6 +572,31 @@ gen_const_mem (enum machine_mode mode, rtx addr)
   return mem;
 }
 
+/* Generate a MEM referring to fixed portions of the frame, e.g., register
+   save areas.  */
+
+rtx
+gen_frame_mem (enum machine_mode mode, rtx addr)
+{
+  rtx mem = gen_rtx_MEM (mode, addr);
+  MEM_NOTRAP_P (mem) = 1;
+  set_mem_alias_set (mem, get_frame_alias_set ());
+  return mem;
+}
+
+/* Generate a MEM referring to a temporary use of the stack, not part
+    of the fixed stack frame.  For example, something which is pushed
+    by a target splitter.  */
+rtx
+gen_tmp_stack_mem (enum machine_mode mode, rtx addr)
+{
+  rtx mem = gen_rtx_MEM (mode, addr);
+  MEM_NOTRAP_P (mem) = 1;
+  if (!current_function_calls_alloca)
+    set_mem_alias_set (mem, get_frame_alias_set ());
+  return mem;
+}
+
 /* We want to create (subreg:OMODE (obj:IMODE) OFFSET).  Return true if
    this construct would be valid, and false otherwise.  */
 
@@ -821,13 +811,12 @@ gen_reg_rtx (enum machine_mode mode)
   return val;
 }
 
-/* Generate a register with same attributes as REG, but offsetted by OFFSET.
+/* Update NEW with the same attributes as REG, but offsetted by OFFSET.
    Do the big endian correction if needed.  */
 
-rtx
-gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int offset)
+static void
+update_reg_offset (rtx new, rtx reg, int offset)
 {
-  rtx new = gen_rtx_REG (mode, regno);
   tree decl;
   HOST_WIDE_INT var_size;
 
@@ -869,7 +858,7 @@ gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int off
   if ((BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
       && decl != NULL
       && offset > 0
-      && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode)
+      && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (GET_MODE (new))
       && ((var_size = int_size_in_bytes (TREE_TYPE (decl))) > 0
          && var_size < GET_MODE_SIZE (GET_MODE (reg))))
     {
@@ -913,6 +902,30 @@ gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int off
 
   REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg),
                                   REG_OFFSET (reg) + offset);
+}
+
+/* Generate a register with same attributes as REG, but offsetted by
+   OFFSET.  */
+
+rtx
+gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno,
+                   int offset)
+{
+  rtx new = gen_rtx_REG (mode, regno);
+
+  update_reg_offset (new, reg, offset);
+  return new;
+}
+
+/* Generate a new pseudo-register with the same attributes as REG, but
+   offsetted by OFFSET.  */
+
+rtx
+gen_reg_rtx_offset (rtx reg, enum machine_mode mode, int offset)
+{
+  rtx new = gen_reg_rtx (mode);
+
+  update_reg_offset (new, reg, offset);
   return new;
 }
 
@@ -954,7 +967,7 @@ set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
 void
 set_decl_rtl (tree t, rtx x)
 {
-  DECL_CHECK (t)->decl.rtl = x;
+  DECL_WRTL_CHECK (t)->decl_with_rtl.rtl = x;
 
   if (!x)
     return;
@@ -1118,7 +1131,8 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
   /* Unfortunately, this routine doesn't take a parameter for the mode of X,
      so we have to make one up.  Yuk.  */
   innermode = GET_MODE (x);
-  if (GET_CODE (x) == CONST_INT && msize <= HOST_BITS_PER_WIDE_INT)
+  if (GET_CODE (x) == CONST_INT
+      && msize * BITS_PER_UNIT <= HOST_BITS_PER_WIDE_INT)
     innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
   else if (innermode == VOIDmode)
     innermode = mode_for_size (HOST_BITS_PER_WIDE_INT * 2, MODE_INT, 0);
@@ -1136,7 +1150,7 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
     return 0;
 
   /* Don't allow generating paradoxical FLOAT_MODE subregs.  */
-  if (GET_MODE_CLASS (mode) == MODE_FLOAT && msize > xsize)
+  if (SCALAR_FLOAT_MODE_P (mode) && msize > xsize)
     return 0;
 
   offset = subreg_lowpart_offset (mode, innermode);
@@ -1466,13 +1480,15 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
   alias = get_alias_set (t);
 
   MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
-  MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
+  MEM_IN_STRUCT_P (ref)
+    = AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE;
   MEM_POINTER (ref) = POINTER_TYPE_P (type);
-  MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (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))
+  if ((objectp || DECL_P (t))
+      && ! AGGREGATE_TYPE_P (type)
+      && TREE_CODE (type) != COMPLEX_TYPE)
     MEM_SCALAR_P (ref) = 1;
 
   /* We can set the alignment from the type if we are making an object,
@@ -1499,16 +1515,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
      the expression.  */
   if (! TYPE_P (t))
     {
-      tree base = get_base_address (t);
-      if (base && DECL_P (base)
-         && TREE_READONLY (base)
-         && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
-       {
-         tree base_type = TREE_TYPE (base);
-         gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type))
-                     || DECL_ARTIFICIAL (base));
-         MEM_READONLY_P (ref) = 1;
-       }
+      tree base;
 
       if (TREE_THIS_VOLATILE (t))
        MEM_VOLATILE_P (ref) = 1;
@@ -1521,6 +1528,36 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
             || TREE_CODE (t) == SAVE_EXPR)
        t = TREE_OPERAND (t, 0);
 
+      /* We may look through structure-like accesses for the purposes of
+        examining TREE_THIS_NOTRAP, but not array-like accesses.  */
+      base = t;
+      while (TREE_CODE (base) == COMPONENT_REF
+            || TREE_CODE (base) == REALPART_EXPR
+            || TREE_CODE (base) == IMAGPART_EXPR
+            || TREE_CODE (base) == BIT_FIELD_REF)
+       base = TREE_OPERAND (base, 0);
+
+      if (DECL_P (base))
+       {
+         if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS))
+           MEM_NOTRAP_P (ref) = !DECL_WEAK (base);
+         else
+           MEM_NOTRAP_P (ref) = 1;
+       }
+      else
+       MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (base);
+
+      base = get_base_address (base);
+      if (base && DECL_P (base)
+         && TREE_READONLY (base)
+         && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
+       {
+         tree base_type = TREE_TYPE (base);
+         gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type))
+                     || DECL_ARTIFICIAL (base));
+         MEM_READONLY_P (ref) = 1;
+       }
+
       /* If this expression uses it's parent's alias set, mark it such
         that we won't change it.  */
       if (component_uses_parent_alias_set (t))
@@ -1584,8 +1621,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
                                     index, low_bound);
 
              off_tree = size_binop (PLUS_EXPR,
-                                    size_binop (MULT_EXPR, convert (sizetype,
-                                                                    index),
+                                    size_binop (MULT_EXPR,
+                                                fold_convert (sizetype,
+                                                              index),
                                                 unit_size),
                                     off_tree);
              t2 = TREE_OPERAND (t2, 0);
@@ -2076,17 +2114,8 @@ set_new_first_and_last_insn (rtx first, rtx last)
    structure.  This routine should only be called once.  */
 
 static void
-unshare_all_rtl_1 (tree fndecl, rtx insn)
+unshare_all_rtl_1 (rtx insn)
 {
-  tree decl;
-
-  /* Make sure that virtual parameters are not shared.  */
-  for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (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));
-
   /* Unshare just about everything else.  */
   unshare_all_rtl_in_chain (insn);
 
@@ -2127,18 +2156,19 @@ unshare_all_rtl_again (rtx insn)
 
   reset_used_flags (stack_slot_list);
 
-  unshare_all_rtl_1 (cfun->decl, insn);
+  unshare_all_rtl_1 (insn);
 }
 
-void
+unsigned int
 unshare_all_rtl (void)
 {
-  unshare_all_rtl_1 (current_function_decl, get_insns ());
+  unshare_all_rtl_1 (get_insns ());
+  return 0;
 }
 
 struct tree_opt_pass pass_unshare_all_rtl =
 {
-  NULL,                                 /* name */
+  "unshare",                            /* name */
   NULL,                                 /* gate */
   unshare_all_rtl,                      /* execute */
   NULL,                                 /* sub */
@@ -2149,7 +2179,7 @@ struct tree_opt_pass pass_unshare_all_rtl =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
+  TODO_dump_func,                       /* todo_flags_finish */
   0                                     /* letter */
 };
 
@@ -2278,6 +2308,20 @@ verify_rtl_sharing (void)
        reset_used_flags (PATTERN (p));
        reset_used_flags (REG_NOTES (p));
        reset_used_flags (LOG_LINKS (p));
+       if (GET_CODE (PATTERN (p)) == SEQUENCE)
+         {
+           int i;
+           rtx q, sequence = PATTERN (p);
+
+           for (i = 0; i < XVECLEN (sequence, 0); i++)
+             {
+               q = XVECEXP (sequence, 0, i);
+               gcc_assert (INSN_P (q));
+               reset_used_flags (PATTERN (q));
+               reset_used_flags (REG_NOTES (q));
+               reset_used_flags (LOG_LINKS (q));
+             }
+         }
       }
 
   for (p = get_insns (); p; p = NEXT_INSN (p))
@@ -2304,23 +2348,6 @@ unshare_all_rtl_in_chain (rtx insn)
       }
 }
 
-/* Go through all virtual stack slots of a function and copy any
-   shared structure.  */
-static void
-unshare_all_decls (tree blk)
-{
-  tree t;
-
-  /* Copy shared decls.  */
-  for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (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))
-    unshare_all_decls (t);
-}
-
 /* Go through all virtual stack slots of a function and mark them as
    not shared.  */
 static void
@@ -2419,11 +2446,7 @@ repeat:
 
   if (RTX_FLAG (x, used))
     {
-      rtx copy;
-
-      copy = rtx_alloc (code);
-      memcpy (copy, x, RTX_SIZE (code));
-      x = copy;
+      x = shallow_copy_rtx (x);
       copied = 1;
     }
   RTX_FLAG (x, used) = 1;
@@ -2759,33 +2782,6 @@ get_max_uid (void)
 {
   return cur_insn_uid;
 }
-
-/* Renumber instructions so that no instruction UIDs are wasted.  */
-
-void
-renumber_insns (FILE *stream)
-{
-  rtx insn;
-
-  /* If we're not supposed to renumber instructions, don't.  */
-  if (!flag_renumber_insns)
-    return;
-
-  /* If there aren't that many instructions, then it's not really
-     worth renumbering them.  */
-  if (flag_renumber_insns == 1 && get_max_uid () < 25000)
-    return;
-
-  cur_insn_uid = 1;
-
-  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    {
-      if (stream)
-       fprintf (stream, "Renumbering insn %d to %d\n",
-                INSN_UID (insn), cur_insn_uid);
-      INSN_UID (insn) = cur_insn_uid++;
-    }
-}
 \f
 /* Return the next insn.  If it is a SEQUENCE, return the first insn
    of the sequence.  */
@@ -3054,6 +3050,37 @@ prev_cc0_setter (rtx insn)
 }
 #endif
 
+#ifdef AUTO_INC_DEC
+/* Find a RTX_AUTOINC class rtx which matches DATA.  */
+
+static int
+find_auto_inc (rtx *xp, void *data)
+{
+  rtx x = *xp;
+  rtx reg = data;
+
+  if (GET_RTX_CLASS (GET_CODE (x)) != RTX_AUTOINC)
+    return 0;
+
+  switch (GET_CODE (x))
+    {
+      case PRE_DEC:
+      case PRE_INC:
+      case POST_DEC:
+      case POST_INC:
+      case PRE_MODIFY:
+      case POST_MODIFY:
+       if (rtx_equal_p (reg, XEXP (x, 0)))
+         return 1;
+       break;
+
+      default:
+       gcc_unreachable ();
+    }
+  return -1;
+}
+#endif
+
 /* Increment the label uses for all labels present in rtx.  */
 
 static void
@@ -3178,8 +3205,7 @@ try_split (rtx pat, rtx trial, int last)
       switch (REG_NOTE_KIND (note))
        {
        case REG_EH_REGION:
-         insn = insn_last;
-         while (insn != NULL_RTX)
+         for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
            {
              if (CALL_P (insn)
                  || (flag_non_call_exceptions && INSN_P (insn)
@@ -3188,37 +3214,45 @@ try_split (rtx pat, rtx trial, int last)
                  = gen_rtx_EXPR_LIST (REG_EH_REGION,
                                       XEXP (note, 0),
                                       REG_NOTES (insn));
-             insn = PREV_INSN (insn);
            }
          break;
 
        case REG_NORETURN:
        case REG_SETJMP:
-         insn = insn_last;
-         while (insn != NULL_RTX)
+         for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
            {
              if (CALL_P (insn))
                REG_NOTES (insn)
                  = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
                                       XEXP (note, 0),
                                       REG_NOTES (insn));
-             insn = PREV_INSN (insn);
            }
          break;
 
        case REG_NON_LOCAL_GOTO:
-         insn = insn_last;
-         while (insn != NULL_RTX)
+         for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
            {
              if (JUMP_P (insn))
                REG_NOTES (insn)
                  = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
                                       XEXP (note, 0),
                                       REG_NOTES (insn));
-             insn = PREV_INSN (insn);
            }
          break;
 
+#ifdef AUTO_INC_DEC
+       case REG_INC:
+         for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
+           {
+             rtx reg = XEXP (note, 0);
+             if (!FIND_REG_INC_NOTE (insn, reg)
+                 && for_each_rtx (&PATTERN (insn), find_auto_inc, reg) > 0)
+               REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, reg,
+                                                     REG_NOTES (insn));
+           }
+         break;
+#endif
+
        default:
          break;
        }
@@ -3275,7 +3309,7 @@ make_insn_raw (rtx pattern)
   INSN_CODE (insn) = -1;
   LOG_LINKS (insn) = NULL;
   REG_NOTES (insn) = NULL;
-  INSN_LOCATOR (insn) = 0;
+  INSN_LOCATOR (insn) = curr_insn_locator ();
   BLOCK_FOR_INSN (insn) = NULL;
 
 #ifdef ENABLE_RTL_CHECKING
@@ -3295,7 +3329,7 @@ make_insn_raw (rtx pattern)
 
 /* Like `make_insn_raw' but make a JUMP_INSN instead of an insn.  */
 
-static rtx
+rtx
 make_jump_insn_raw (rtx pattern)
 {
   rtx insn;
@@ -3308,7 +3342,7 @@ make_jump_insn_raw (rtx pattern)
   LOG_LINKS (insn) = NULL;
   REG_NOTES (insn) = NULL;
   JUMP_LABEL (insn) = NULL;
-  INSN_LOCATOR (insn) = 0;
+  INSN_LOCATOR (insn) = curr_insn_locator ();
   BLOCK_FOR_INSN (insn) = NULL;
 
   return insn;
@@ -3329,7 +3363,7 @@ make_call_insn_raw (rtx pattern)
   LOG_LINKS (insn) = NULL;
   REG_NOTES (insn) = NULL;
   CALL_INSN_FUNCTION_USAGE (insn) = NULL;
-  INSN_LOCATOR (insn) = 0;
+  INSN_LOCATOR (insn) = curr_insn_locator ();
   BLOCK_FOR_INSN (insn) = NULL;
 
   return insn;
@@ -3403,8 +3437,7 @@ add_insn_after (rtx insn, rtx after)
       if (BB_END (bb) == after
          /* Avoid clobbering of structure when creating new BB.  */
          && !BARRIER_P (insn)
-         && (!NOTE_P (insn)
-             || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
+         && !NOTE_INSN_BASIC_BLOCK_P (insn))
        BB_END (bb) = insn;
     }
 
@@ -3469,8 +3502,7 @@ add_insn_before (rtx insn, rtx before)
       gcc_assert (BB_HEAD (bb) != insn
                  /* Avoid clobbering of structure when creating new BB.  */
                  || BARRIER_P (insn)
-                 || (NOTE_P (insn)
-                     && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK));
+                 || NOTE_INSN_BASIC_BLOCK_P (insn));
     }
 
   PREV_INSN (before) = insn;
@@ -3652,95 +3684,6 @@ reorder_insns (rtx from, rtx to, rtx after)
     }
 }
 
-/* Return the line note insn preceding INSN.  */
-
-static rtx
-find_line_note (rtx insn)
-{
-  if (no_line_numbers)
-    return 0;
-
-  for (; insn; insn = PREV_INSN (insn))
-    if (NOTE_P (insn)
-       && NOTE_LINE_NUMBER (insn) >= 0)
-      break;
-
-  return insn;
-}
-
-/* Remove unnecessary notes from the instruction stream.  */
-
-void
-remove_unnecessary_notes (void)
-{
-  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.  */
-  for (insn = NEXT_INSN (get_insns ()); insn; insn = next)
-    {
-      /* Remember what's next.  */
-      next = NEXT_INSN (insn);
-
-      /* We're only interested in notes.  */
-      if (!NOTE_P (insn))
-       continue;
-
-      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.  */
-         gcc_assert (eh_stack);
-         /* Mismatched nesting.  */
-         gcc_assert (NOTE_EH_HANDLER (XEXP (eh_stack, 0))
-                     == NOTE_EH_HANDLER (insn));
-         tmp = eh_stack;
-         eh_stack = XEXP (eh_stack, 1);
-         free_INSN_LIST_node (tmp);
-         break;
-
-       case NOTE_INSN_BLOCK_BEG:
-       case NOTE_INSN_BLOCK_END:
-          /* BLOCK_END and BLOCK_BEG notes only exist in the `final' pass.  */
-          gcc_unreachable ();
-
-       default:
-         break;
-       }
-    }
-
-  /* Too many EH_REGION_BEG notes.  */
-  gcc_assert (!eh_stack);
-}
-
-struct tree_opt_pass pass_remove_unnecessary_notes =
-{
-  NULL,                                 /* name */ 
-  NULL,                                        /* gate */
-  remove_unnecessary_notes,             /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  0,                                   /* tv_id */ 
-  0,                                   /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  0,                                   /* todo_flags_finish */
-  0                                     /* letter */ 
-};
-
 \f
 /* Emit insn(s) of given code and pattern
    at a specified place within the doubly-linked list.
@@ -3932,15 +3875,13 @@ emit_label_before (rtx label, rtx before)
 /* Emit a note of subtype SUBTYPE before the insn BEFORE.  */
 
 rtx
-emit_note_before (int subtype, rtx before)
+emit_note_before (enum insn_note subtype, rtx before)
 {
   rtx note = rtx_alloc (NOTE);
   INSN_UID (note) = cur_insn_uid++;
-#ifndef USE_MAPPED_LOCATION
-  NOTE_SOURCE_FILE (note) = 0;
-#endif
-  NOTE_LINE_NUMBER (note) = subtype;
+  NOTE_KIND (note) = subtype;
   BLOCK_FOR_INSN (note) = NULL;
+  memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
 
   add_insn_before (note, before);
   return note;
@@ -4025,22 +3966,6 @@ emit_insn_after_noloc (rtx x, rtx after)
   return last;
 }
 
-/* Similar to emit_insn_after, except that line notes are to be inserted so
-   as to act as if this insn were at FROM.  */
-
-void
-emit_insn_after_with_line_notes (rtx x, rtx after, rtx from)
-{
-  rtx from_line = find_line_note (from);
-  rtx after_line = find_line_note (after);
-  rtx insn = emit_insn_after (x, after);
-
-  if (from_line)
-    emit_note_copy_after (from_line, after);
-
-  if (after_line)
-    emit_note_copy_after (after_line, insn);
-}
 
 /* Make an insn of code JUMP_INSN with body X
    and output it after the insn AFTER.  */
@@ -4148,37 +4073,13 @@ emit_label_after (rtx label, rtx after)
 /* Emit a note of subtype SUBTYPE after the insn AFTER.  */
 
 rtx
-emit_note_after (int subtype, rtx after)
+emit_note_after (enum insn_note subtype, rtx after)
 {
   rtx note = rtx_alloc (NOTE);
   INSN_UID (note) = cur_insn_uid++;
-#ifndef USE_MAPPED_LOCATION
-  NOTE_SOURCE_FILE (note) = 0;
-#endif
-  NOTE_LINE_NUMBER (note) = subtype;
-  BLOCK_FOR_INSN (note) = NULL;
-  add_insn_after (note, after);
-  return note;
-}
-
-/* Emit a copy of note ORIG after the insn AFTER.  */
-
-rtx
-emit_note_copy_after (rtx orig, rtx after)
-{
-  rtx note;
-
-  if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers)
-    {
-      cur_insn_uid++;
-      return 0;
-    }
-
-  note = rtx_alloc (NOTE);
-  INSN_UID (note) = cur_insn_uid++;
-  NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig);
-  NOTE_DATA (note) = NOTE_DATA (orig);
+  NOTE_KIND (note) = subtype;
   BLOCK_FOR_INSN (note) = NULL;
+  memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
   add_insn_after (note, after);
   return note;
 }
@@ -4286,7 +4187,10 @@ emit_insn_before_setloc (rtx pattern, rtx before, int loc)
   if (pattern == NULL_RTX || !loc)
     return last;
 
-  first = NEXT_INSN (first);
+  if (!first)
+    first = get_insns ();
+  else
+    first = NEXT_INSN (first);
   while (1)
     {
       if (active_insn_p (first) && !INSN_LOCATOR (first))
@@ -4523,42 +4427,6 @@ emit_barrier (void)
   return barrier;
 }
 
-/* Make line numbering NOTE insn for LOCATION add it to the end
-   of the doubly-linked list, but only if line-numbers are desired for
-   debugging info and it doesn't match the previous one.  */
-
-rtx
-emit_line_note (location_t location)
-{
-  rtx note;
-  
-#ifdef USE_MAPPED_LOCATION
-  if (location == last_location)
-    return NULL_RTX;
-#else
-  if (location.file && last_location.file
-      && !strcmp (location.file, last_location.file)
-      && location.line == last_location.line)
-    return NULL_RTX;
-#endif
-  last_location = location;
-  
-  if (no_line_numbers)
-    {
-      cur_insn_uid++;
-      return NULL_RTX;
-    }
-
-#ifdef USE_MAPPED_LOCATION
-  note = emit_note ((int) location);
-#else
-  note = emit_note (location.line);
-  NOTE_SOURCE_FILE (note) = location.file;
-#endif
-  
-  return note;
-}
-
 /* Emit a copy of note ORIG.  */
 
 rtx
@@ -4566,17 +4434,11 @@ emit_note_copy (rtx orig)
 {
   rtx note;
   
-  if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers)
-    {
-      cur_insn_uid++;
-      return NULL_RTX;
-    }
-  
   note = rtx_alloc (NOTE);
   
   INSN_UID (note) = cur_insn_uid++;
   NOTE_DATA (note) = NOTE_DATA (orig);
-  NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig);
+  NOTE_KIND (note) = NOTE_KIND (orig);
   BLOCK_FOR_INSN (note) = NULL;
   add_insn (note);
   
@@ -4587,13 +4449,13 @@ emit_note_copy (rtx orig)
    and add it to the end of the doubly-linked list.  */
 
 rtx
-emit_note (int note_no)
+emit_note (enum insn_note kind)
 {
   rtx note;
 
   note = rtx_alloc (NOTE);
   INSN_UID (note) = cur_insn_uid++;
-  NOTE_LINE_NUMBER (note) = note_no;
+  NOTE_KIND (note) = kind;
   memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
   BLOCK_FOR_INSN (note) = NULL;
   add_insn (note);
@@ -4841,7 +4703,7 @@ in_sequence_p (void)
 \f
 /* Put the various virtual registers into REGNO_REG_RTX.  */
 
-void
+static void
 init_virtual_regs (struct emit_status *es)
 {
   rtx *ptr = es->x_regno_reg_rtx;
@@ -4930,13 +4792,11 @@ copy_insn_1 (rtx orig)
       break;
     }
 
-  copy = rtx_alloc (code);
-
-  /* Copy the various flags, and other information.  We assume that
-     all fields need copying, and then clear the fields that should
+  /* Copy the various flags, fields, and other information.  We assume
+     that all fields need copying, and then clear the fields that should
      not be copied.  That is the sensible default behavior, and forces
      us to explicitly document why we are *not* copying a flag.  */
-  memcpy (copy, orig, RTX_HDR_SIZE);
+  copy = shallow_copy_rtx (orig);
 
   /* We do not copy the USED flag, which is used as a mark bit during
      walks over the RTL.  */
@@ -4953,43 +4813,40 @@ copy_insn_1 (rtx orig)
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
-    {
-      copy->u.fld[i] = orig->u.fld[i];
-      switch (*format_ptr++)
-       {
-       case 'e':
-         if (XEXP (orig, i) != NULL)
-           XEXP (copy, i) = copy_insn_1 (XEXP (orig, i));
-         break;
+    switch (*format_ptr++)
+      {
+      case 'e':
+       if (XEXP (orig, i) != NULL)
+         XEXP (copy, i) = copy_insn_1 (XEXP (orig, i));
+       break;
 
-       case 'E':
-       case 'V':
-         if (XVEC (orig, i) == orig_asm_constraints_vector)
-           XVEC (copy, i) = copy_asm_constraints_vector;
-         else if (XVEC (orig, i) == orig_asm_operands_vector)
-           XVEC (copy, i) = copy_asm_operands_vector;
-         else if (XVEC (orig, i) != NULL)
-           {
-             XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
-             for (j = 0; j < XVECLEN (copy, i); j++)
-               XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j));
-           }
-         break;
+      case 'E':
+      case 'V':
+       if (XVEC (orig, i) == orig_asm_constraints_vector)
+         XVEC (copy, i) = copy_asm_constraints_vector;
+       else if (XVEC (orig, i) == orig_asm_operands_vector)
+         XVEC (copy, i) = copy_asm_operands_vector;
+       else if (XVEC (orig, i) != NULL)
+         {
+           XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
+           for (j = 0; j < XVECLEN (copy, i); j++)
+             XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j));
+         }
+       break;
 
-       case 't':
-       case 'w':
-       case 'i':
-       case 's':
-       case 'S':
-       case 'u':
-       case '0':
-         /* These are left unchanged.  */
-         break;
+      case 't':
+      case 'w':
+      case 'i':
+      case 's':
+      case 'S':
+      case 'u':
+      case '0':
+       /* These are left unchanged.  */
+       break;
 
-       default:
-         gcc_unreachable ();
-       }
-    }
+      default:
+       gcc_unreachable ();
+      }
 
   if (code == SCRATCH)
     {
@@ -5105,6 +4962,8 @@ gen_const_vector (enum machine_mode mode, int constant)
   units = GET_MODE_NUNITS (mode);
   inner = GET_MODE_INNER (mode);
 
+  gcc_assert (!DECIMAL_FLOAT_MODE_P (inner));
+
   v = rtvec_alloc (units);
 
   /* We need to call this function after we set the scalar const_tiny_rtx
@@ -5181,7 +5040,8 @@ init_emit_once (int line_numbers)
   word_mode = VOIDmode;
   double_mode = VOIDmode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+       mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
       if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
@@ -5193,7 +5053,8 @@ init_emit_once (int line_numbers)
        word_mode = mode;
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+       mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
       if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE
@@ -5268,8 +5129,8 @@ init_emit_once (int line_numbers)
 
   /* Initialize mathematical constants for constant folding builtins.
      These constants need to be given to at least 160 bits precision.  */
-  real_from_string (&dconstpi,
-    "3.1415926535897932384626433832795028841971693993751058209749445923078");
+  real_from_string (&dconstsqrt2,
+    "1.4142135623730950488016887242096980785696718753769480731766797379907");
   real_from_string (&dconste,
     "2.7182818284590452353602874713526624977572470936999595749669676277241");
 
@@ -5278,14 +5139,22 @@ init_emit_once (int line_numbers)
       REAL_VALUE_TYPE *r =
        (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
 
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
+      for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+          mode != VOIDmode;
+          mode = GET_MODE_WIDER_MODE (mode))
+       const_tiny_rtx[i][(int) mode] =
+         CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
+
+      for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT);
+          mode != VOIDmode;
           mode = GET_MODE_WIDER_MODE (mode))
        const_tiny_rtx[i][(int) mode] =
          CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
 
       const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);
 
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+          mode != VOIDmode;
           mode = GET_MODE_WIDER_MODE (mode))
        const_tiny_rtx[i][(int) mode] = GEN_INT (i);
 
@@ -5399,14 +5268,12 @@ emit_copy_of_insn_after (rtx insn, rtx after)
       {
        if (GET_CODE (link) == EXPR_LIST)
          REG_NOTES (new)
-           = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
-                                             XEXP (link, 0),
-                                             REG_NOTES (new)));
+               = gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
+                 copy_insn_1 (XEXP (link, 0)),  REG_NOTES (new));
        else
          REG_NOTES (new)
-           = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
-                                             XEXP (link, 0),
-                                             REG_NOTES (new)));
+              = gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
+                XEXP (link, 0),  REG_NOTES (new));
       }
 
   /* Fix the libcall sequences.  */