OSDN Git Service

* config/m68k/m68k.h (REGISTER_NAMES): Prefix each name with
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 0f7e677..6402f43 100644 (file)
@@ -1,6 +1,6 @@
 /* Emit RTL for the GCC expander.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,18 +22,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* Middle-to-low level generation of rtx code and insns.
 
-   This file contains the functions `gen_rtx', `gen_reg_rtx'
-   and `gen_label_rtx' that are the usual ways of creating rtl
-   expressions for most purposes.
-
-   It also has the functions for creating insns and linking
-   them in the doubly-linked chain.
+   This file contains support functions for creating rtl expressions
+   and manipulating them in the doubly-linked chain of insns.
 
    The patterns of the insns are created by machine-dependent
    routines in insn-emit.c, which is generated automatically from
-   the machine description.  These routines use `gen_rtx' to make
-   the individual rtx's of the pattern; what is machine dependent
-   is the kind of rtx's they make and what arguments they use.  */
+   the machine description.  These routines make the individual rtx's
+   of the pattern with `gen_rtx_fmt_ee' and others in genrtl.[ch],
+   which are automatically generated from rtl.def; what is machine
+   dependent is the kind of rtx's they make and what arguments they
+   use.  */
 
 #include "config.h"
 #include "system.h"
@@ -77,7 +75,7 @@ static GTY(()) int label_num = 1;
 
 static int last_label_num;
 
-/* Value label_num had when set_new_first_and_last_label_number was called.
+/* Value label_num had when set_new_last_label_num was called.
    If label_num has not changed since then, last_label_num is valid.  */
 
 static int base_label_num;
@@ -99,6 +97,8 @@ rtx global_rtl[GR_MAX];
    at the beginning of each function.  */
 static GTY(()) rtx static_regno_reg_rtx[FIRST_PSEUDO_REGISTER];
 
+rtx (*gen_lowpart) (enum machine_mode mode, rtx x) = gen_lowpart_general;
+
 /* We record floating-point CONST_DOUBLEs in each floating-point mode for
    the values of 0, 1, and 2.  For the integer entries and VOIDmode, we
    record a copy of const[012]_rtx.  */
@@ -198,6 +198,7 @@ static reg_attrs *get_reg_attrs (tree, int);
 static tree component_ref_for_mem_expr (tree);
 static rtx gen_const_vector_0 (enum machine_mode);
 static rtx gen_complex_constant_part (enum machine_mode, rtx, int);
+static void copy_rtx_if_shared_1 (rtx *orig);
 
 /* Probability of the conditional branch currently proceeded by try_split.
    Set to -1 otherwise.  */
@@ -642,119 +643,6 @@ gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
                         subreg_lowpart_offset (mode, inmode));
 }
 \f
-/* rtx gen_rtx (code, mode, [element1, ..., elementn])
-**
-**         This routine generates an RTX of the size specified by
-**     <code>, which is an RTX code.   The RTX structure is initialized
-**     from the arguments <element1> through <elementn>, which are
-**     interpreted according to the specific RTX type's format.   The
-**     special machine mode associated with the rtx (if any) is specified
-**     in <mode>.
-**
-**         gen_rtx can be invoked in a way which resembles the lisp-like
-**     rtx it will generate.   For example, the following rtx structure:
-**
-**           (plus:QI (mem:QI (reg:SI 1))
-**                    (mem:QI (plusw:SI (reg:SI 2) (reg:SI 3))))
-**
-**             ...would be generated by the following C code:
-**
-**             gen_rtx (PLUS, QImode,
-**                 gen_rtx (MEM, QImode,
-**                     gen_rtx (REG, SImode, 1)),
-**                 gen_rtx (MEM, QImode,
-**                     gen_rtx (PLUS, SImode,
-**                         gen_rtx (REG, SImode, 2),
-**                         gen_rtx (REG, SImode, 3)))),
-*/
-
-/*VARARGS2*/
-rtx
-gen_rtx (enum rtx_code code, enum machine_mode mode, ...)
-{
-  int i;               /* Array indices...                     */
-  const char *fmt;     /* Current rtx's format...              */
-  rtx rt_val;          /* RTX to return to caller...           */
-  va_list p;
-
-  va_start (p, mode);
-
-  switch (code)
-    {
-    case CONST_INT:
-      rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT));
-      break;
-
-    case CONST_DOUBLE:
-      {
-       HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
-       HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
-
-       rt_val = immed_double_const (arg0, arg1, mode);
-      }
-      break;
-
-    case REG:
-      rt_val = gen_rtx_REG (mode, va_arg (p, int));
-      break;
-
-    case MEM:
-      rt_val = gen_rtx_MEM (mode, va_arg (p, rtx));
-      break;
-
-    default:
-      rt_val = rtx_alloc (code);       /* Allocate the storage space.  */
-      rt_val->mode = mode;             /* Store the machine mode...  */
-
-      fmt = GET_RTX_FORMAT (code);     /* Find the right format...  */
-      for (i = 0; i < GET_RTX_LENGTH (code); i++)
-       {
-         switch (*fmt++)
-           {
-           case '0':           /* Field with unknown use.  Zero it.  */
-             X0EXP (rt_val, i) = NULL_RTX;
-             break;
-
-           case 'i':           /* An integer?  */
-             XINT (rt_val, i) = va_arg (p, int);
-             break;
-
-           case 'w':           /* A wide integer? */
-             XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
-             break;
-
-           case 's':           /* A string?  */
-             XSTR (rt_val, i) = va_arg (p, char *);
-             break;
-
-           case 'e':           /* An expression?  */
-           case 'u':           /* An insn?  Same except when printing.  */
-             XEXP (rt_val, i) = va_arg (p, rtx);
-             break;
-
-           case 'E':           /* An RTX vector?  */
-             XVEC (rt_val, i) = va_arg (p, rtvec);
-             break;
-
-           case 'b':           /* A bitmap? */
-             XBITMAP (rt_val, i) = va_arg (p, bitmap);
-             break;
-
-           case 't':           /* A tree? */
-             XTREE (rt_val, i) = va_arg (p, tree);
-             break;
-
-           default:
-             abort ();
-           }
-       }
-      break;
-    }
-
-  va_end (p);
-  return rt_val;
-}
-
 /* gen_rtvec (n, [rt1, ..., rtn])
 **
 **         This routine creates an rtvec and stores within it the
@@ -970,7 +858,7 @@ mark_reg_pointer (rtx reg, int align)
        REGNO_POINTER_ALIGN (REGNO (reg)) = align;
     }
   else if (align && align < REGNO_POINTER_ALIGN (REGNO (reg)))
-    /* We can no-longer be sure just how aligned this pointer is */
+    /* We can no-longer be sure just how aligned this pointer is */
     REGNO_POINTER_ALIGN (REGNO (reg)) = align;
 }
 
@@ -1049,24 +937,36 @@ rtx
 gen_lowpart_common (enum machine_mode mode, rtx x)
 {
   int msize = GET_MODE_SIZE (mode);
-  int xsize = GET_MODE_SIZE (GET_MODE (x));
+  int xsize;
   int offset = 0;
+  enum machine_mode innermode;
+
+  /* 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)
+    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);
+  
+  xsize = GET_MODE_SIZE (innermode);
 
-  if (GET_MODE (x) == mode)
+  if (innermode == VOIDmode || innermode == BLKmode)
+    abort ();
+
+  if (innermode == mode)
     return x;
 
   /* MODE must occupy no more words than the mode of X.  */
-  if (GET_MODE (x) != VOIDmode
-      && ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
-         > ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
+  if ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
+      > ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))
     return 0;
 
   /* Don't allow generating paradoxical FLOAT_MODE subregs.  */
-  if (GET_MODE_CLASS (mode) == MODE_FLOAT
-      && GET_MODE (x) != VOIDmode && msize > xsize)
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT && msize > xsize)
     return 0;
 
-  offset = subreg_lowpart_offset (mode, GET_MODE (x));
+  offset = subreg_lowpart_offset (mode, innermode);
 
   if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
       && (GET_MODE_CLASS (mode) == MODE_INT
@@ -1082,154 +982,15 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
 
       if (GET_MODE (XEXP (x, 0)) == mode)
        return XEXP (x, 0);
-      else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
+      else if (msize < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
        return gen_lowpart_common (mode, XEXP (x, 0));
-      else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))
+      else if (msize < xsize)
        return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
     }
   else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG
-          || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR)
-    return simplify_gen_subreg (mode, x, GET_MODE (x), offset);
-  else if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode)
-    return simplify_gen_subreg (mode, x, int_mode_for_mode (mode), offset);
-  /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
-     from the low-order part of the constant.  */
-  else if ((GET_MODE_CLASS (mode) == MODE_INT
-           || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
-          && GET_MODE (x) == VOIDmode
-          && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
-    {
-      /* If MODE is twice the host word size, X is already the desired
-        representation.  Otherwise, if MODE is wider than a word, we can't
-        do this.  If MODE is exactly a word, return just one CONST_INT.  */
-
-      if (GET_MODE_BITSIZE (mode) >= 2 * HOST_BITS_PER_WIDE_INT)
-       return x;
-      else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
-       return 0;
-      else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
-       return (GET_CODE (x) == CONST_INT ? x
-               : GEN_INT (CONST_DOUBLE_LOW (x)));
-      else
-       {
-         /* MODE must be narrower than HOST_BITS_PER_WIDE_INT.  */
-         HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x)
-                              : CONST_DOUBLE_LOW (x));
-
-         /* Sign extend to HOST_WIDE_INT.  */
-         val = trunc_int_for_mode (val, mode);
-
-         return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x
-                 : GEN_INT (val));
-       }
-    }
-
-  /* The floating-point emulator can handle all conversions between
-     FP and integer operands.  This simplifies reload because it
-     doesn't have to deal with constructs like (subreg:DI
-     (const_double:SF ...)) or (subreg:DF (const_int ...)).  */
-  /* Single-precision floats are always 32-bits and double-precision
-     floats are always 64-bits.  */
-
-  else if (GET_MODE_CLASS (mode) == MODE_FLOAT
-          && GET_MODE_BITSIZE (mode) == 32
-          && GET_CODE (x) == CONST_INT)
-    {
-      REAL_VALUE_TYPE r;
-      long i = INTVAL (x);
-
-      real_from_target (&r, &i, mode);
-      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
-    }
-  else if (GET_MODE_CLASS (mode) == MODE_FLOAT
-          && GET_MODE_BITSIZE (mode) == 64
-          && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
-          && GET_MODE (x) == VOIDmode)
-    {
-      REAL_VALUE_TYPE r;
-      HOST_WIDE_INT low, high;
-      long i[2];
-
-      if (GET_CODE (x) == CONST_INT)
-       {
-         low = INTVAL (x);
-         high = low >> (HOST_BITS_PER_WIDE_INT - 1);
-       }
-      else
-       {
-         low = CONST_DOUBLE_LOW (x);
-         high = CONST_DOUBLE_HIGH (x);
-       }
-
-      if (HOST_BITS_PER_WIDE_INT > 32)
-       high = low >> 31 >> 1;
-
-      /* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
-        target machine.  */
-      if (WORDS_BIG_ENDIAN)
-       i[0] = high, i[1] = low;
-      else
-       i[0] = low, i[1] = high;
-
-      real_from_target (&r, i, mode);
-      return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
-    }
-  else if ((GET_MODE_CLASS (mode) == MODE_INT
-           || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
-          && GET_CODE (x) == CONST_DOUBLE
-          && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-    {
-      REAL_VALUE_TYPE r;
-      long i[4];  /* Only the low 32 bits of each 'long' are used.  */
-      int endian = WORDS_BIG_ENDIAN ? 1 : 0;
-
-      /* Convert 'r' into an array of four 32-bit words in target word
-         order.  */
-      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
-      switch (GET_MODE_BITSIZE (GET_MODE (x)))
-       {
-       case 32:
-         REAL_VALUE_TO_TARGET_SINGLE (r, i[3 * endian]);
-         i[1] = 0;
-         i[2] = 0;
-         i[3 - 3 * endian] = 0;
-         break;
-       case 64:
-         REAL_VALUE_TO_TARGET_DOUBLE (r, i + 2 * endian);
-         i[2 - 2 * endian] = 0;
-         i[3 - 2 * endian] = 0;
-         break;
-       case 96:
-         REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, i + endian);
-         i[3 - 3 * endian] = 0;
-         break;
-       case 128:
-         REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, i);
-         break;
-       default:
-         abort ();
-       }
-      /* Now, pack the 32-bit elements of the array into a CONST_DOUBLE
-        and return it.  */
-#if HOST_BITS_PER_WIDE_INT == 32
-      return immed_double_const (i[3 * endian], i[1 + endian], mode);
-#else
-      if (HOST_BITS_PER_WIDE_INT != 64)
-       abort ();
-
-      return immed_double_const ((((unsigned long) i[3 * endian])
-                                 | ((HOST_WIDE_INT) i[1 + endian] << 32)),
-                                (((unsigned long) i[2 - endian])
-                                 | ((HOST_WIDE_INT) i[3 - 3 * endian] << 32)),
-                                mode);
-#endif
-    }
-  /* If MODE is a condition code and X is a CONST_INT, the value of X
-     must already have been "recognized" by the back-end, and we can
-     assume that it is valid for this mode.  */
-  else if (GET_MODE_CLASS (mode) == MODE_CC
-          && GET_CODE (x) == CONST_INT)
-    return x;
+          || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR
+          || GET_CODE (x) == CONST_DOUBLE || GET_CODE (x) == CONST_INT)
+    return simplify_gen_subreg (mode, x, innermode, offset);
 
   /* Otherwise, we can't do this.  */
   return 0;
@@ -1322,7 +1083,7 @@ subreg_realpart_p (rtx x)
     abort ();
 
   return ((unsigned int) SUBREG_BYTE (x)
-         < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
+         < (unsigned int) GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
 }
 \f
 /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value,
@@ -1333,7 +1094,7 @@ subreg_realpart_p (rtx x)
    If X is a MEM whose address is a QUEUED, the value may be so also.  */
 
 rtx
-gen_lowpart (enum machine_mode mode, rtx x)
+gen_lowpart_general (enum machine_mode mode, rtx x)
 {
   rtx result = gen_lowpart_common (mode, x);
 
@@ -1390,7 +1151,7 @@ gen_highpart (enum machine_mode mode, rtx 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 (msize > UNITS_PER_WORD
-      && msize != GET_MODE_UNIT_SIZE (GET_MODE (x)))
+      && msize != (unsigned int) GET_MODE_UNIT_SIZE (GET_MODE (x)))
     abort ();
 
   result = simplify_gen_subreg (mode, x, GET_MODE (x),
@@ -1480,162 +1241,6 @@ subreg_lowpart_p (rtx x)
          == SUBREG_BYTE (x));
 }
 \f
-
-/* Helper routine for all the constant cases of operand_subword.
-   Some places invoke this directly.  */
-
-rtx
-constant_subword (rtx op, int offset, enum machine_mode mode)
-{
-  int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
-  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;
-
-  /* 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
-     host can't.  */
-  if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
-      && GET_MODE_CLASS (mode) == MODE_FLOAT
-      && GET_MODE_BITSIZE (mode) == 64
-      && GET_CODE (op) == CONST_DOUBLE)
-    {
-      long k[2];
-      REAL_VALUE_TYPE rv;
-
-      REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
-      REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
-
-      /* We handle 32-bit and >= 64-bit words here.  Note that the order in
-        which the words are written depends on the word endianness.
-        ??? This is a potential portability problem and should
-        be fixed at some point.
-
-        We must exercise caution with the sign bit.  By definition there
-        are 32 significant bits in K; there may be more in a HOST_WIDE_INT.
-        Consider a host with a 32-bit long and a 64-bit HOST_WIDE_INT.
-        So we explicitly mask and sign-extend as necessary.  */
-      if (BITS_PER_WORD == 32)
-       {
-         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 && offset == 0)
-       {
-         val = k[! WORDS_BIG_ENDIAN];
-         val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
-         val |= (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN] & 0xffffffff;
-         return GEN_INT (val);
-       }
-#endif
-      else if (BITS_PER_WORD == 16)
-       {
-         val = k[offset >> 1];
-         if ((offset & 1) == ! WORDS_BIG_ENDIAN)
-           val >>= 16;
-         val = ((val & 0xffff) ^ 0x8000) - 0x8000;
-         return GEN_INT (val);
-       }
-      else
-       abort ();
-    }
-  else if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
-          && GET_MODE_CLASS (mode) == MODE_FLOAT
-          && GET_MODE_BITSIZE (mode) > 64
-          && GET_CODE (op) == CONST_DOUBLE)
-    {
-      long k[4];
-      REAL_VALUE_TYPE rv;
-
-      REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
-      REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
-
-      if (BITS_PER_WORD == 32)
-       {
-         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 && offset <= 1)
-       {
-         val = k[offset * 2 + ! WORDS_BIG_ENDIAN];
-         val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
-         val |= (HOST_WIDE_INT) k[offset * 2 + WORDS_BIG_ENDIAN] & 0xffffffff;
-         return GEN_INT (val);
-       }
-#endif
-      else
-       abort ();
-    }
-
-  /* Single word float is a little harder, since single- and double-word
-     values often do not have the same high-order bits.  We have already
-     verified that we want the only defined word of the single-word value.  */
-  if (GET_MODE_CLASS (mode) == MODE_FLOAT
-      && GET_MODE_BITSIZE (mode) == 32
-      && GET_CODE (op) == CONST_DOUBLE)
-    {
-      long l;
-      REAL_VALUE_TYPE rv;
-
-      REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
-      REAL_VALUE_TO_TARGET_SINGLE (rv, l);
-
-      /* Sign extend from known 32-bit value to HOST_WIDE_INT.  */
-      val = l;
-      val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
-
-      if (BITS_PER_WORD == 16)
-       {
-         if ((offset & 1) == ! WORDS_BIG_ENDIAN)
-           val >>= 16;
-         val = ((val & 0xffff) ^ 0x8000) - 0x8000;
-       }
-
-      return GEN_INT (val);
-    }
-
-  /* The only remaining cases that we can handle are integers.
-     Convert to proper endianness now since these cases need it.
-     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
-     it for any word.  */
-
-  if (op == const0_rtx)
-    return op;
-
-  if (GET_MODE_CLASS (mode) != MODE_INT
-      || (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE)
-      || BITS_PER_WORD > HOST_BITS_PER_WIDE_INT)
-    return 0;
-
-  if (WORDS_BIG_ENDIAN)
-    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 = (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 >> ((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
@@ -1826,6 +1431,8 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
     return;
 
   type = TYPE_P (t) ? t : TREE_TYPE (t);
+  if (type == error_mark_node)
+    return;
 
   /* 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
@@ -2120,6 +1727,9 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
     mode = GET_MODE (memref);
   if (addr == 0)
     addr = XEXP (memref, 0);
+  if (mode == GET_MODE (memref) && addr == XEXP (memref, 0)
+      && (!validate || memory_address_p (mode, addr)))
+    return memref;
 
   if (validate)
     {
@@ -2146,15 +1756,29 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
 rtx
 change_address (rtx memref, enum machine_mode mode, rtx addr)
 {
-  rtx new = change_address_1 (memref, mode, addr, 1);
+  rtx new = change_address_1 (memref, mode, addr, 1), size;
   enum machine_mode mmode = GET_MODE (new);
+  unsigned int align;
+
+  size = mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode));
+  align = mmode == BLKmode ? BITS_PER_UNIT : GET_MODE_ALIGNMENT (mmode);
+
+  /* If there are no changes, just return the original memory reference.  */
+  if (new == memref)
+    {
+      if (MEM_ATTRS (memref) == 0
+         || (MEM_EXPR (memref) == NULL
+             && MEM_OFFSET (memref) == NULL
+             && MEM_SIZE (memref) == size
+             && MEM_ALIGN (memref) == align))
+       return new;
+
+      new = gen_rtx_MEM (mmode, XEXP (memref, 0));
+      MEM_COPY_ATTRIBUTES (new, memref);
+    }
 
   MEM_ATTRS (new)
-    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0,
-                    mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode)),
-                    (mmode == BLKmode ? BITS_PER_UNIT
-                     : GET_MODE_ALIGNMENT (mmode)),
-                    mmode);
+    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, mmode);
 
   return new;
 }
@@ -2175,6 +1799,11 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
   rtx size = 0;
   unsigned int memalign = MEM_ALIGN (memref);
 
+  /* If there are no changes, just return the original memory reference.  */
+  if (mode == GET_MODE (memref) && !offset
+      && (!validate || memory_address_p (mode, addr)))
+    return memref;
+
   /* ??? Prefer to create garbage instead of creating shared rtl.
      This may happen even if offset is nonzero -- consider
      (plus (plus reg reg) const_int) -- so do this always.  */
@@ -2265,6 +1894,10 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
   update_temp_slot_address (XEXP (memref, 0), new);
   new = change_address_1 (memref, VOIDmode, new, 1);
 
+  /* If there are no changes, just return the original memory reference.  */
+  if (new == memref)
+    return new;
+
   /* Update the alignment to reflect the offset.  Reset the offset, which
      we don't know.  */
   MEM_ATTRS (new)
@@ -2309,6 +1942,10 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
   rtx memoffset = MEM_OFFSET (new);
   unsigned int size = GET_MODE_SIZE (mode);
 
+  /* If there are no changes, just return the original memory reference.  */
+  if (new == memref)
+    return new;
+
   /* If we don't know what offset we were at within the expression, then
      we can't know if we've overstepped the bounds.  */
   if (! memoffset)
@@ -2403,17 +2040,6 @@ set_new_first_and_last_insn (rtx first, rtx last)
   cur_insn_uid++;
 }
 
-/* Set the range of label numbers found in the current function.
-   This is used when belatedly compiling an inline function.  */
-
-void
-set_new_first_and_last_label_num (int first, int last)
-{
-  base_label_num = label_num;
-  first_label_num = first;
-  last_label_num = last;
-}
-
 /* Set the last label number found in the current function.
    This is used when belatedly compiling an inline function.  */
 
@@ -2522,8 +2148,12 @@ verify_rtx_sharing (rtx orig, rtx insn)
     case PC:
     case CC0:
     case SCRATCH:
-      /* SCRATCH must be shared because they represent distinct values.  */
       return;
+      /* SCRATCH must be shared because they represent distinct values.  */
+    case CLOBBER:
+      if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
+       return;
+      break;
 
     case CONST:
       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
@@ -2559,7 +2189,7 @@ verify_rtx_sharing (rtx orig, rtx insn)
     }
   RTX_FLAG (x, used) = 1;
 
-  /* Now scan the subexpressions recursively. */
+  /* Now scan the subexpressions recursively.  */
 
   format_ptr = GET_RTX_FORMAT (code);
 
@@ -2593,7 +2223,7 @@ verify_rtx_sharing (rtx orig, rtx insn)
   return;
 }
 
-/* Go through all the RTL insn bodies and chec that there is no inexpected
+/* Go through all the RTL insn bodies and check that there is no unexpected
    sharing in between the subexpressions.  */
 
 void
@@ -2768,19 +2398,36 @@ copy_most_rtx (rtx orig, rtx may_share)
 }
 
 /* Mark ORIG as in use, and return a copy of it if it was already in use.
-   Recursively does the same for subexpressions.  */
+   Recursively does the same for subexpressions.  Uses
+   copy_rtx_if_shared_1 to reduce stack space.  */
 
 rtx
 copy_rtx_if_shared (rtx orig)
 {
-  rtx x = orig;
+  copy_rtx_if_shared_1 (&orig);
+  return orig;
+}
+
+/* Mark *ORIG1 as in use, and set it to a copy of it if it was already in
+   use.  Recursively does the same for subexpressions.  */
+
+static void
+copy_rtx_if_shared_1 (rtx *orig1)
+{
+  rtx x;
   int i;
   enum rtx_code code;
+  rtx *last_ptr;
   const char *format_ptr;
   int copied = 0;
+  int length;
+
+  /* Repeat is used to turn tail-recursion into iteration.  */
+repeat:
+  x = *orig1;
 
   if (x == 0)
-    return 0;
+    return;
 
   code = GET_CODE (x);
 
@@ -2800,7 +2447,11 @@ copy_rtx_if_shared (rtx orig)
     case CC0:
     case SCRATCH:
       /* SCRATCH must be shared because they represent distinct values.  */
-      return x;
+      return;
+    case CLOBBER:
+      if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
+       return;
+      break;
 
     case CONST:
       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
@@ -2808,7 +2459,7 @@ copy_rtx_if_shared (rtx orig)
       if (GET_CODE (XEXP (x, 0)) == PLUS
          && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
-       return x;
+       return;
       break;
 
     case INSN:
@@ -2817,7 +2468,7 @@ copy_rtx_if_shared (rtx orig)
     case NOTE:
     case BARRIER:
       /* The chain of insns is not being copied.  */
-      return x;
+      return;
 
     default:
       break;
@@ -2843,13 +2494,17 @@ copy_rtx_if_shared (rtx orig)
      must be copied if X was copied.  */
 
   format_ptr = GET_RTX_FORMAT (code);
-
-  for (i = 0; i < GET_RTX_LENGTH (code); i++)
+  length = GET_RTX_LENGTH (code);
+  last_ptr = NULL;
+  
+  for (i = 0; i < length; i++)
     {
       switch (*format_ptr++)
        {
        case 'e':
-         XEXP (x, i) = copy_rtx_if_shared (XEXP (x, i));
+          if (last_ptr)
+            copy_rtx_if_shared_1 (last_ptr);
+         last_ptr = &XEXP (x, i);
          break;
 
        case 'E':
@@ -2857,16 +2512,30 @@ copy_rtx_if_shared (rtx orig)
            {
              int j;
              int len = XVECLEN (x, i);
-
+              
+              /* Copy the vector iff I copied the rtx and the length
+                is nonzero.  */
              if (copied && len > 0)
                XVEC (x, i) = gen_rtvec_v (len, XVEC (x, i)->elem);
+              
+              /* Call recursively on all inside the vector.  */
              for (j = 0; j < len; j++)
-               XVECEXP (x, i, j) = copy_rtx_if_shared (XVECEXP (x, i, j));
+                {
+                 if (last_ptr)
+                   copy_rtx_if_shared_1 (last_ptr);
+                  last_ptr = &XVECEXP (x, i, j);
+                }
            }
          break;
        }
     }
-  return x;
+  *orig1 = x;
+  if (last_ptr)
+    {
+      orig1 = last_ptr;
+      goto repeat;
+    }
+  return;
 }
 
 /* Clear all the USED bits in X to allow copy_rtx_if_shared to be used
@@ -2878,7 +2547,10 @@ reset_used_flags (rtx x)
   int i, j;
   enum rtx_code code;
   const char *format_ptr;
+  int length;
 
+  /* Repeat is used to turn tail-recursion into iteration.  */
+repeat:
   if (x == 0)
     return;
 
@@ -2916,11 +2588,18 @@ reset_used_flags (rtx x)
   RTX_FLAG (x, used) = 0;
 
   format_ptr = GET_RTX_FORMAT (code);
-  for (i = 0; i < GET_RTX_LENGTH (code); i++)
+  length = GET_RTX_LENGTH (code);
+  
+  for (i = 0; i < length; i++)
     {
       switch (*format_ptr++)
        {
        case 'e':
+          if (i == length-1)
+            {
+              x = XEXP (x, i);
+             goto repeat;
+            }
          reset_used_flags (XEXP (x, i));
          break;
 
@@ -3760,12 +3439,12 @@ add_insn_after (rtx insn, rtx after)
        bb->flags |= BB_DIRTY;
       /* Should not happen as first in the BB is always
         either NOTE or LABEL.  */
-      if (bb->end == after
+      if (BB_END (bb) == 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;
+       BB_END (bb) = insn;
     }
 
   NEXT_INSN (after) = insn;
@@ -3828,7 +3507,7 @@ add_insn_before (rtx insn, rtx before)
        bb->flags |= BB_DIRTY;
       /* Should not happen as first in the BB is always
         either NOTE or LABEl.  */
-      if (bb->head == insn
+      if (BB_HEAD (bb) == insn
          /* Avoid clobbering of structure when creating new BB.  */
          && GET_CODE (insn) != BARRIER
          && (GET_CODE (insn) != NOTE
@@ -3903,16 +3582,16 @@ remove_insn (rtx insn)
     {
       if (INSN_P (insn))
        bb->flags |= BB_DIRTY;
-      if (bb->head == insn)
+      if (BB_HEAD (bb) == insn)
        {
          /* Never ever delete the basic block note without deleting whole
             basic block.  */
          if (GET_CODE (insn) == NOTE)
            abort ();
-         bb->head = next;
+         BB_HEAD (bb) = next;
        }
-      if (bb->end == insn)
-       bb->end = prev;
+      if (BB_END (bb) == insn)
+       BB_END (bb) = prev;
     }
 }
 
@@ -4005,13 +3684,13 @@ reorder_insns (rtx from, rtx to, rtx after)
       if (GET_CODE (from) != BARRIER
          && (bb2 = BLOCK_FOR_INSN (from)))
        {
-         if (bb2->end == to)
-           bb2->end = prev;
+         if (BB_END (bb2) == to)
+           BB_END (bb2) = prev;
          bb2->flags |= BB_DIRTY;
        }
 
-      if (bb->end == after)
-       bb->end = to;
+      if (BB_END (bb) == after)
+       BB_END (bb) = to;
 
       for (x = from; x != NEXT_INSN (to); x = NEXT_INSN (x))
        set_block_for_insn (x, bb);
@@ -4400,8 +4079,8 @@ emit_insn_after_1 (rtx first, rtx after)
          set_block_for_insn (last, bb);
       if (GET_CODE (last) != BARRIER)
        set_block_for_insn (last, bb);
-      if (bb->end == after)
-       bb->end = last;
+      if (BB_END (bb) == after)
+       BB_END (bb) = last;
     }
   else
     for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
@@ -4629,6 +4308,9 @@ emit_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   rtx last = emit_insn_after (pattern, after);
 
+  if (pattern == NULL_RTX)
+    return last;
+
   after = NEXT_INSN (after);
   while (1)
     {
@@ -4647,6 +4329,9 @@ emit_jump_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   rtx last = emit_jump_insn_after (pattern, after);
 
+  if (pattern == NULL_RTX)
+    return last;
+
   after = NEXT_INSN (after);
   while (1)
     {
@@ -4665,6 +4350,9 @@ emit_call_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   rtx last = emit_call_insn_after (pattern, after);
 
+  if (pattern == NULL_RTX)
+    return last;
+
   after = NEXT_INSN (after);
   while (1)
     {
@@ -4684,6 +4372,9 @@ emit_insn_before_setloc (rtx pattern, rtx before, int loc)
   rtx first = PREV_INSN (before);
   rtx last = emit_insn_before (pattern, before);
 
+  if (pattern == NULL_RTX)
+    return last;
+
   first = NEXT_INSN (first);
   while (1)
     {
@@ -5254,6 +4945,10 @@ copy_insn_1 (rtx orig)
     case CC0:
     case ADDRESSOF:
       return orig;
+    case CLOBBER:
+      if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
+       return orig;
+      break;
 
     case SCRATCH:
       for (i = 0; i < copy_insn_n_scratches; i++)
@@ -5545,8 +5240,8 @@ init_emit_once (int line_numbers)
      This must be done at runtime because the register number field
      is in a union and some compilers can't initialize unions.  */
 
-  pc_rtx = gen_rtx (PC, VOIDmode);
-  cc0_rtx = gen_rtx (CC0, VOIDmode);
+  pc_rtx = gen_rtx_PC (VOIDmode);
+  cc0_rtx = gen_rtx_CC0 (VOIDmode);
   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)
@@ -5579,7 +5274,7 @@ init_emit_once (int line_numbers)
 
   /* Create the unique rtx's for certain rtx codes and operand values.  */
 
-  /* Don't use gen_rtx here since gen_rtx in this case
+  /* Don't use gen_rtx_CONST_INT here since gen_rtx_CONST_INT in this case
      tries to use these variables.  */
   for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)
     const_int_rtx[i + MAX_SAVED_CONST_INT] =
@@ -5770,4 +5465,15 @@ emit_copy_of_insn_after (rtx insn, rtx after)
   return new;
 }
 
+static GTY((deletable(""))) rtx hard_reg_clobbers [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+rtx
+gen_hard_reg_clobber (enum machine_mode mode, unsigned int regno)
+{
+  if (hard_reg_clobbers[mode][regno])
+    return hard_reg_clobbers[mode][regno];
+  else
+    return (hard_reg_clobbers[mode][regno] =
+           gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
+}
+
 #include "gt-emit-rtl.h"