OSDN Git Service

* config/sh/sh.c: Replace "gen_rtx (FOO, " with "gen_rtx_FOO (".
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index cdb0c2a..df2a236 100644 (file)
@@ -99,6 +99,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.  */
@@ -660,13 +662,13 @@ gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
 **
 **             ...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)))),
+**             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*/
@@ -1207,7 +1209,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);
 
@@ -1840,6 +1842,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)
     {
@@ -1866,15 +1871,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;
 }
@@ -1895,6 +1914,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.  */
@@ -1985,6 +2009,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)
@@ -2029,6 +2057,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)