re PR rtl-optimization/13424 (gcc.dg/20031202-1.c is miscompiled)
authorJakub Jelinek <jakub@redhat.com>
Thu, 29 Jan 2004 08:05:47 +0000 (09:05 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 29 Jan 2004 08:05:47 +0000 (09:05 +0100)
PR optimization/13424
* expr.c (store_constructor): Revert 2003-12-03 change.

* emit-rtl.c (change_address): Check also if MEM_ATTRS is set as
expected before returning early.  Avoid sharing RTL if they
need to be changed.

* config/i386/i386.c (ix86_expand_movstr): Rework rep_mov and strmov
handling so that memory attributes are preserved.  Don't call
ix86_set_move_mem_attrs.
(ix86_set_move_mem_attrs_1, ix86_set_move_mem_attrs): Removed.
(ix86_expand_clrstr): Rename src argument to
dst.  Rework rep_stos and strset handling so that memory attributes
are preserved.
(ix86_expand_strlen): Pass src argument to
ix86_expand_strlensi_unroll_1.  Rework strlenqi_1 handling so that
memory attributes are preserved.
(ix86_expand_strlensi_unroll_1): Add src argument.  Use
change_address instead of gen_rtx_MEM.
* config/i386/i386.md (strmov, strmov_singleop, rep_mov): New
expanders.
(strmovdi_rex64, strmovsi, strmovsi_rex64, strmovhi, strmovhi_rex64,
strmovqi, strmovqi_rex64): Remove.
(rep_mov*, strmov*): Prefix insn names with *.
(strset, strset_singleop, rep_stos): New expanders.
(strsetdi_rex64, strsetsi, strsetsi_rex64, strsethi, strsethi_rex64,
strsetqi, strsetqi_rex64): Remove.
(rep_stos*, strset*): Prefix insn names with *.
(rep_stosqi_rex64): Likewise.  Fix mode of dirflag reg from DImode
to SImode.
(cmpstrsi): Rework cmpstrqi_1 handling so that memory attributes
are preserved.
(cmpstrqi_nz_1, cmpstrqi_nz_rex_1, cmpstrqi_1, cmpstrqi_rex_1):
Prefix insn names with *.
(cmpstrqi_nz_1, cmpstrqi_1): New expanders.
(strlenqi_1, strlenqi_rex_1): Prefix insn names with *.
(strlenqi_1): New expander.
* config/i386/i386.h (ix86_set_move_mem_attrs): Remove prototype.

From-SVN: r76852

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/emit-rtl.c
gcc/expr.c

index 39e5a4b..25fdc65 100644 (file)
@@ -1,3 +1,44 @@
+2004-01-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR optimization/13424
+       * expr.c (store_constructor): Revert 2003-12-03 change.
+
+       * emit-rtl.c (change_address): Check also if MEM_ATTRS is set as
+       expected before returning early.  Avoid sharing RTL if they
+       need to be changed.
+
+       * config/i386/i386.c (ix86_expand_movstr): Rework rep_mov and strmov
+       handling so that memory attributes are preserved.  Don't call
+       ix86_set_move_mem_attrs.
+       (ix86_set_move_mem_attrs_1, ix86_set_move_mem_attrs): Removed.
+       (ix86_expand_clrstr): Rename src argument to
+       dst.  Rework rep_stos and strset handling so that memory attributes
+       are preserved.
+       (ix86_expand_strlen): Pass src argument to
+       ix86_expand_strlensi_unroll_1.  Rework strlenqi_1 handling so that
+       memory attributes are preserved.
+       (ix86_expand_strlensi_unroll_1): Add src argument.  Use
+       change_address instead of gen_rtx_MEM.
+       * config/i386/i386.md (strmov, strmov_singleop, rep_mov): New
+       expanders.
+       (strmovdi_rex64, strmovsi, strmovsi_rex64, strmovhi, strmovhi_rex64,
+       strmovqi, strmovqi_rex64): Remove.
+       (rep_mov*, strmov*): Prefix insn names with *.
+       (strset, strset_singleop, rep_stos): New expanders.
+       (strsetdi_rex64, strsetsi, strsetsi_rex64, strsethi, strsethi_rex64,
+       strsetqi, strsetqi_rex64): Remove.
+       (rep_stos*, strset*): Prefix insn names with *.
+       (rep_stosqi_rex64): Likewise.  Fix mode of dirflag reg from DImode
+       to SImode.
+       (cmpstrsi): Rework cmpstrqi_1 handling so that memory attributes
+       are preserved.
+       (cmpstrqi_nz_1, cmpstrqi_nz_rex_1, cmpstrqi_1, cmpstrqi_rex_1):
+       Prefix insn names with *.
+       (cmpstrqi_nz_1, cmpstrqi_1): New expanders.
+       (strlenqi_1, strlenqi_rex_1): Prefix insn names with *.
+       (strlenqi_1): New expander.
+       * config/i386/i386.h (ix86_set_move_mem_attrs): Remove prototype.
+
 2004-01-29  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
 
        * Makefile.in (cfghooks.o): Add TIMEVAR_H and toplev.h dependency.
index cc04a68..24d7d6a 100644 (file)
@@ -178,7 +178,6 @@ extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class,
                                         enum machine_mode, int);
 extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class);
 extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
-extern void ix86_set_move_mem_attrs (rtx, rtx, rtx, rtx, rtx);
 extern void emit_i387_cw_initialization (rtx, rtx);
 extern bool ix86_fp_jump_nontrivial_p (enum rtx_code);
 extern void x86_order_regs_for_local_alloc (void);
index df7efd1..9e6f9b3 100644 (file)
@@ -813,12 +813,11 @@ static void ix86_emit_save_regs (void);
 static void ix86_emit_save_regs_using_mov (rtx, HOST_WIDE_INT);
 static void ix86_emit_restore_regs_using_mov (rtx, HOST_WIDE_INT, int);
 static void ix86_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void ix86_set_move_mem_attrs_1 (rtx, rtx, rtx, rtx, rtx);
 static void ix86_sched_reorder_ppro (rtx *, rtx *);
 static HOST_WIDE_INT ix86_GOT_alias_set (void);
 static void ix86_adjust_counter (rtx, HOST_WIDE_INT);
 static rtx ix86_expand_aligntest (rtx, int);
-static void ix86_expand_strlensi_unroll_1 (rtx, rtx);
+static void ix86_expand_strlensi_unroll_1 (rtx, rtx, rtx);
 static int ix86_issue_rate (void);
 static int ix86_adjust_cost (rtx, rtx, rtx, int);
 static void ix86_sched_init (FILE *, int, int);
@@ -11020,11 +11019,10 @@ ix86_zero_extend_to_Pmode (rtx exp)
 int
 ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
 {
-  rtx srcreg, destreg, countreg;
+  rtx srcreg, destreg, countreg, srcexp, destexp;
   enum machine_mode counter_mode;
   HOST_WIDE_INT align = 0;
   unsigned HOST_WIDE_INT count = 0;
-  rtx insns;
 
   if (GET_CODE (align_exp) == CONST_INT)
     align = INTVAL (align_exp);
@@ -11053,28 +11051,27 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
   else
     counter_mode = DImode;
 
-  start_sequence ();
-
   if (counter_mode != SImode && counter_mode != DImode)
     abort ();
 
   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
+  if (destreg != XEXP (dst, 0))
+    dst = replace_equiv_address_nv (dst, destreg);
   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
-
-  emit_insn (gen_cld ());
+  if (srcreg != XEXP (src, 0))
+    src = replace_equiv_address_nv (src, srcreg);
 
   /* When optimizing for size emit simple rep ; movsb instruction for
      counts not divisible by 4.  */
 
   if ((!optimize || optimize_size) && (count == 0 || (count & 0x03)))
     {
+      emit_insn (gen_cld ());
       countreg = ix86_zero_extend_to_Pmode (count_exp);
-      if (TARGET_64BIT)
-       emit_insn (gen_rep_movqi_rex64 (destreg, srcreg, countreg,
-                                       destreg, srcreg, countreg));
-      else
-       emit_insn (gen_rep_movqi (destreg, srcreg, countreg,
-                                 destreg, srcreg, countreg));
+      destexp = gen_rtx_PLUS (Pmode, destreg, countreg);
+      srcexp = gen_rtx_PLUS (Pmode, srcreg, countreg);
+      emit_insn (gen_rep_mov (destreg, dst, srcreg, src, countreg,
+                             destexp, srcexp));
     }
 
   /* For constant aligned (or small unaligned) copies use rep movsl
@@ -11086,32 +11083,53 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
               || (!TARGET_PENTIUMPRO && !TARGET_64BIT && align >= 4)
               || optimize_size || count < (unsigned int) 64))
     {
+      unsigned HOST_WIDE_INT offset = 0;
       int size = TARGET_64BIT && !optimize_size ? 8 : 4;
+      rtx srcmem, dstmem;
+
+      emit_insn (gen_cld ());
       if (count & ~(size - 1))
        {
          countreg = copy_to_mode_reg (counter_mode,
                                       GEN_INT ((count >> (size == 4 ? 2 : 3))
                                                & (TARGET_64BIT ? -1 : 0x3fffffff)));
          countreg = ix86_zero_extend_to_Pmode (countreg);
-         if (size == 4)
-           {
-             if (TARGET_64BIT)
-               emit_insn (gen_rep_movsi_rex64 (destreg, srcreg, countreg,
-                                               destreg, srcreg, countreg));
-             else
-               emit_insn (gen_rep_movsi (destreg, srcreg, countreg,
-                                         destreg, srcreg, countreg));
-           }
-         else
-           emit_insn (gen_rep_movdi_rex64 (destreg, srcreg, countreg,
-                                           destreg, srcreg, countreg));
+         
+         destexp = gen_rtx_ASHIFT (Pmode, countreg,
+                                   GEN_INT (size == 4 ? 2 : 3));
+         srcexp = gen_rtx_PLUS (Pmode, destexp, srcreg);
+         destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
+
+         emit_insn (gen_rep_mov (destreg, dst, srcreg, src,
+                                 countreg, destexp, srcexp));
+         offset = count & ~(size - 1);
        }
       if (size == 8 && (count & 0x04))
-       emit_insn (gen_strmovsi (destreg, srcreg));
+       {
+         srcmem = adjust_automodify_address_nv (src, SImode, srcreg,
+                                                offset);
+         dstmem = adjust_automodify_address_nv (dst, SImode, destreg,
+                                                offset);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
+         offset += 4;
+       }
       if (count & 0x02)
-       emit_insn (gen_strmovhi (destreg, srcreg));
+       {
+         srcmem = adjust_automodify_address_nv (src, HImode, srcreg,
+                                                offset);
+         dstmem = adjust_automodify_address_nv (dst, HImode, destreg,
+                                                offset);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
+         offset += 2;
+       }
       if (count & 0x01)
-       emit_insn (gen_strmovqi (destreg, srcreg));
+       {
+         srcmem = adjust_automodify_address_nv (src, QImode, srcreg,
+                                                offset);
+         dstmem = adjust_automodify_address_nv (dst, QImode, destreg,
+                                                offset);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
+       }
     }
   /* The generic code based on the glibc implementation:
      - align destination to 4 bytes (8 byte alignment is used for PentiumPro
@@ -11122,9 +11140,13 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
     {
       rtx countreg2;
       rtx label = NULL;
+      rtx srcmem, dstmem;
       int desired_alignment = (TARGET_PENTIUMPRO
                               && (count == 0 || count >= (unsigned int) 260)
                               ? 8 : UNITS_PER_WORD);
+      /* Get rid of MEM_OFFSETs, they won't be accurate.  */
+      dst = change_address (dst, BLKmode, destreg);
+      src = change_address (src, BLKmode, srcreg);
 
       /* In case we don't know anything about the alignment, default to
          library version, since it is usually equally fast and result in
@@ -11134,10 +11156,7 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
         will not be important.  */
       if (!TARGET_INLINE_ALL_STRINGOPS
          && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
-       {
-         end_sequence ();
-         return 0;
-       }
+       return 0;
 
       if (TARGET_SINGLE_STRINGOP)
        emit_insn (gen_cld ());
@@ -11167,7 +11186,9 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
       if (align <= 1)
        {
          rtx label = ix86_expand_aligntest (destreg, 1);
-         emit_insn (gen_strmovqi (destreg, srcreg));
+         srcmem = change_address (src, QImode, srcreg);
+         dstmem = change_address (dst, QImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
          ix86_adjust_counter (countreg, 1);
          emit_label (label);
          LABEL_NUSES (label) = 1;
@@ -11175,7 +11196,9 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
       if (align <= 2)
        {
          rtx label = ix86_expand_aligntest (destreg, 2);
-         emit_insn (gen_strmovhi (destreg, srcreg));
+         srcmem = change_address (src, HImode, srcreg);
+         dstmem = change_address (dst, HImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
          ix86_adjust_counter (countreg, 2);
          emit_label (label);
          LABEL_NUSES (label) = 1;
@@ -11183,7 +11206,9 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
       if (align <= 4 && desired_alignment > 4)
        {
          rtx label = ix86_expand_aligntest (destreg, 4);
-         emit_insn (gen_strmovsi (destreg, srcreg));
+         srcmem = change_address (src, SImode, srcreg);
+         dstmem = change_address (dst, SImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
          ix86_adjust_counter (countreg, 4);
          emit_label (label);
          LABEL_NUSES (label) = 1;
@@ -11201,15 +11226,17 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
        {
          emit_insn (gen_lshrdi3 (countreg2, ix86_zero_extend_to_Pmode (countreg),
                                  GEN_INT (3)));
-         emit_insn (gen_rep_movdi_rex64 (destreg, srcreg, countreg2,
-                                         destreg, srcreg, countreg2));
+         destexp = gen_rtx_ASHIFT (Pmode, countreg2, GEN_INT (3));
        }
       else
        {
-         emit_insn (gen_lshrsi3 (countreg2, countreg, GEN_INT (2)));
-         emit_insn (gen_rep_movsi (destreg, srcreg, countreg2,
-                                   destreg, srcreg, countreg2));
+         emit_insn (gen_lshrsi3 (countreg2, countreg, const2_rtx));
+         destexp = gen_rtx_ASHIFT (Pmode, countreg2, const2_rtx);
        }
+      srcexp = gen_rtx_PLUS (Pmode, destexp, srcreg);
+      destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
+      emit_insn (gen_rep_mov (destreg, dst, srcreg, src,
+                             countreg2, destexp, srcexp));
 
       if (label)
        {
@@ -11217,48 +11244,61 @@ ix86_expand_movstr (rtx dst, rtx src, rtx count_exp, rtx align_exp)
          LABEL_NUSES (label) = 1;
        }
       if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
-       emit_insn (gen_strmovsi (destreg, srcreg));
+       {
+         srcmem = change_address (src, SImode, srcreg);
+         dstmem = change_address (dst, SImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
+       }
       if ((align <= 4 || count == 0) && TARGET_64BIT)
        {
          rtx label = ix86_expand_aligntest (countreg, 4);
-         emit_insn (gen_strmovsi (destreg, srcreg));
+         srcmem = change_address (src, SImode, srcreg);
+         dstmem = change_address (dst, SImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
          emit_label (label);
          LABEL_NUSES (label) = 1;
        }
       if (align > 2 && count != 0 && (count & 2))
-       emit_insn (gen_strmovhi (destreg, srcreg));
+       {
+         srcmem = change_address (src, HImode, srcreg);
+         dstmem = change_address (dst, HImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
+       }
       if (align <= 2 || count == 0)
        {
          rtx label = ix86_expand_aligntest (countreg, 2);
-         emit_insn (gen_strmovhi (destreg, srcreg));
+         srcmem = change_address (src, HImode, srcreg);
+         dstmem = change_address (dst, HImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
          emit_label (label);
          LABEL_NUSES (label) = 1;
        }
       if (align > 1 && count != 0 && (count & 1))
-       emit_insn (gen_strmovqi (destreg, srcreg));
+       {
+         srcmem = change_address (src, QImode, srcreg);
+         dstmem = change_address (dst, QImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
+       }
       if (align <= 1 || count == 0)
        {
          rtx label = ix86_expand_aligntest (countreg, 1);
-         emit_insn (gen_strmovqi (destreg, srcreg));
+         srcmem = change_address (src, QImode, srcreg);
+         dstmem = change_address (dst, QImode, destreg);
+         emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
          emit_label (label);
          LABEL_NUSES (label) = 1;
        }
     }
 
-  insns = get_insns ();
-  end_sequence ();
-
-  ix86_set_move_mem_attrs (insns, dst, src, destreg, srcreg);
-  emit_insn (insns);
   return 1;
 }
 
 /* Expand string clear operation (bzero).  Use i386 string operations when
    profitable.  expand_movstr contains similar code.  */
 int
-ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
+ix86_expand_clrstr (rtx dst, rtx count_exp, rtx align_exp)
 {
-  rtx destreg, zeroreg, countreg;
+  rtx destreg, zeroreg, countreg, destexp;
   enum machine_mode counter_mode;
   HOST_WIDE_INT align = 0;
   unsigned HOST_WIDE_INT count = 0;
@@ -11289,7 +11329,9 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
   else
     counter_mode = DImode;
 
-  destreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
+  destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
+  if (destreg != XEXP (dst, 0))
+    dst = replace_equiv_address_nv (dst, destreg);
 
   emit_insn (gen_cld ());
 
@@ -11300,12 +11342,8 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
     {
       countreg = ix86_zero_extend_to_Pmode (count_exp);
       zeroreg = copy_to_mode_reg (QImode, const0_rtx);
-      if (TARGET_64BIT)
-       emit_insn (gen_rep_stosqi_rex64 (destreg, countreg, zeroreg,
-                                        destreg, countreg));
-      else
-       emit_insn (gen_rep_stosqi (destreg, countreg, zeroreg,
-                                  destreg, countreg));
+      destexp = gen_rtx_PLUS (Pmode, destreg, countreg);
+      emit_insn (gen_rep_stos (destreg, countreg, dst, zeroreg, destexp));
     }
   else if (count != 0
           && (align >= 8
@@ -11313,6 +11351,8 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
               || optimize_size || count < (unsigned int) 64))
     {
       int size = TARGET_64BIT && !optimize_size ? 8 : 4;
+      unsigned HOST_WIDE_INT offset = 0;
+
       zeroreg = copy_to_mode_reg (size == 4 ? SImode : DImode, const0_rtx);
       if (count & ~(size - 1))
        {
@@ -11320,28 +11360,34 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
                                       GEN_INT ((count >> (size == 4 ? 2 : 3))
                                                & (TARGET_64BIT ? -1 : 0x3fffffff)));
          countreg = ix86_zero_extend_to_Pmode (countreg);
-         if (size == 4)
-           {
-             if (TARGET_64BIT)
-               emit_insn (gen_rep_stossi_rex64 (destreg, countreg, zeroreg,
-                                                destreg, countreg));
-             else
-               emit_insn (gen_rep_stossi (destreg, countreg, zeroreg,
-                                          destreg, countreg));
-           }
-         else
-           emit_insn (gen_rep_stosdi_rex64 (destreg, countreg, zeroreg,
-                                            destreg, countreg));
+         destexp = gen_rtx_ASHIFT (Pmode, countreg, GEN_INT (size == 4 ? 2 : 3));
+         destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
+         emit_insn (gen_rep_stos (destreg, countreg, dst, zeroreg, destexp));
+         offset = count & ~(size - 1);
        }
       if (size == 8 && (count & 0x04))
-       emit_insn (gen_strsetsi (destreg,
+       {
+         rtx mem = adjust_automodify_address_nv (dst, SImode, destreg,
+                                                 offset);
+         emit_insn (gen_strset (destreg, mem,
                                 gen_rtx_SUBREG (SImode, zeroreg, 0)));
+         offset += 4;
+       }
       if (count & 0x02)
-       emit_insn (gen_strsethi (destreg,
+       {
+         rtx mem = adjust_automodify_address_nv (dst, HImode, destreg,
+                                                 offset);
+         emit_insn (gen_strset (destreg, mem,
                                 gen_rtx_SUBREG (HImode, zeroreg, 0)));
+         offset += 2;
+       }
       if (count & 0x01)
-       emit_insn (gen_strsetqi (destreg,
+       {
+         rtx mem = adjust_automodify_address_nv (dst, QImode, destreg,
+                                                 offset);
+         emit_insn (gen_strset (destreg, mem,
                                 gen_rtx_SUBREG (QImode, zeroreg, 0)));
+       }
     }
   else
     {
@@ -11368,6 +11414,8 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
       countreg2 = gen_reg_rtx (Pmode);
       countreg = copy_to_mode_reg (counter_mode, count_exp);
       zeroreg = copy_to_mode_reg (Pmode, const0_rtx);
+      /* Get rid of MEM_OFFSET, it won't be accurate.  */
+      dst = change_address (dst, BLKmode, destreg);
 
       if (count == 0 && align < desired_alignment)
        {
@@ -11378,8 +11426,8 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
       if (align <= 1)
        {
          rtx label = ix86_expand_aligntest (destreg, 1);
-         emit_insn (gen_strsetqi (destreg,
-                                  gen_rtx_SUBREG (QImode, zeroreg, 0)));
+         emit_insn (gen_strset (destreg, dst,
+                                gen_rtx_SUBREG (QImode, zeroreg, 0)));
          ix86_adjust_counter (countreg, 1);
          emit_label (label);
          LABEL_NUSES (label) = 1;
@@ -11387,8 +11435,8 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
       if (align <= 2)
        {
          rtx label = ix86_expand_aligntest (destreg, 2);
-         emit_insn (gen_strsethi (destreg,
-                                  gen_rtx_SUBREG (HImode, zeroreg, 0)));
+         emit_insn (gen_strset (destreg, dst,
+                                gen_rtx_SUBREG (HImode, zeroreg, 0)));
          ix86_adjust_counter (countreg, 2);
          emit_label (label);
          LABEL_NUSES (label) = 1;
@@ -11396,9 +11444,10 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
       if (align <= 4 && desired_alignment > 4)
        {
          rtx label = ix86_expand_aligntest (destreg, 4);
-         emit_insn (gen_strsetsi (destreg, (TARGET_64BIT
-                                            ? gen_rtx_SUBREG (SImode, zeroreg, 0)
-                                            : zeroreg)));
+         emit_insn (gen_strset (destreg, dst,
+                                (TARGET_64BIT
+                                 ? gen_rtx_SUBREG (SImode, zeroreg, 0)
+                                 : zeroreg)));
          ix86_adjust_counter (countreg, 4);
          emit_label (label);
          LABEL_NUSES (label) = 1;
@@ -11417,15 +11466,16 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
        {
          emit_insn (gen_lshrdi3 (countreg2, ix86_zero_extend_to_Pmode (countreg),
                                  GEN_INT (3)));
-         emit_insn (gen_rep_stosdi_rex64 (destreg, countreg2, zeroreg,
-                                          destreg, countreg2));
+         destexp = gen_rtx_ASHIFT (Pmode, countreg2, GEN_INT (3));
        }
       else
        {
-         emit_insn (gen_lshrsi3 (countreg2, countreg, GEN_INT (2)));
-         emit_insn (gen_rep_stossi (destreg, countreg2, zeroreg,
-                                    destreg, countreg2));
+         emit_insn (gen_lshrsi3 (countreg2, countreg, const2_rtx));
+         destexp = gen_rtx_ASHIFT (Pmode, countreg2, const2_rtx);
        }
+      destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
+      emit_insn (gen_rep_stos (destreg, countreg2, dst, zeroreg, destexp));
+
       if (label)
        {
          emit_label (label);
@@ -11433,41 +11483,42 @@ ix86_expand_clrstr (rtx src, rtx count_exp, rtx align_exp)
        }
 
       if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
-       emit_insn (gen_strsetsi (destreg,
-                                gen_rtx_SUBREG (SImode, zeroreg, 0)));
+       emit_insn (gen_strset (destreg, dst,
+                              gen_rtx_SUBREG (SImode, zeroreg, 0)));
       if (TARGET_64BIT && (align <= 4 || count == 0))
        {
          rtx label = ix86_expand_aligntest (countreg, 4);
-         emit_insn (gen_strsetsi (destreg,
-                                  gen_rtx_SUBREG (SImode, zeroreg, 0)));
+         emit_insn (gen_strset (destreg, dst,
+                                gen_rtx_SUBREG (SImode, zeroreg, 0)));
          emit_label (label);
          LABEL_NUSES (label) = 1;
        }
       if (align > 2 && count != 0 && (count & 2))
-       emit_insn (gen_strsethi (destreg,
-                                gen_rtx_SUBREG (HImode, zeroreg, 0)));
+       emit_insn (gen_strset (destreg, dst,
+                              gen_rtx_SUBREG (HImode, zeroreg, 0)));
       if (align <= 2 || count == 0)
        {
          rtx label = ix86_expand_aligntest (countreg, 2);
-         emit_insn (gen_strsethi (destreg,
-                                  gen_rtx_SUBREG (HImode, zeroreg, 0)));
+         emit_insn (gen_strset (destreg, dst,
+                                gen_rtx_SUBREG (HImode, zeroreg, 0)));
          emit_label (label);
          LABEL_NUSES (label) = 1;
        }
       if (align > 1 && count != 0 && (count & 1))
-       emit_insn (gen_strsetqi (destreg,
-                                gen_rtx_SUBREG (QImode, zeroreg, 0)));
+       emit_insn (gen_strset (destreg, dst,
+                              gen_rtx_SUBREG (QImode, zeroreg, 0)));
       if (align <= 1 || count == 0)
        {
          rtx label = ix86_expand_aligntest (countreg, 1);
-         emit_insn (gen_strsetqi (destreg,
-                                  gen_rtx_SUBREG (QImode, zeroreg, 0)));
+         emit_insn (gen_strset (destreg, dst,
+                                gen_rtx_SUBREG (QImode, zeroreg, 0)));
          emit_label (label);
          LABEL_NUSES (label) = 1;
        }
     }
   return 1;
 }
+
 /* Expand strlen.  */
 int
 ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
@@ -11499,7 +11550,7 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
 
       emit_move_insn (out, addr);
 
-      ix86_expand_strlensi_unroll_1 (out, align);
+      ix86_expand_strlensi_unroll_1 (out, src, align);
 
       /* strlensi_unroll_1 returns the address of the zero at the end of
          the string, like memchr(), so compute the length by subtracting
@@ -11511,6 +11562,7 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
     }
   else
     {
+      rtx unspec;
       scratch2 = gen_reg_rtx (Pmode);
       scratch3 = gen_reg_rtx (Pmode);
       scratch4 = force_reg (Pmode, constm1_rtx);
@@ -11519,17 +11571,19 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
       eoschar = force_reg (QImode, eoschar);
 
       emit_insn (gen_cld ());
+      src = replace_equiv_address_nv (src, scratch3);
+
+      /* If .md starts supporting :P, this can be done in .md.  */
+      unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (4, src, eoschar, align,
+                                                scratch4), UNSPEC_SCAS);
+      emit_insn (gen_strlenqi_1 (scratch1, scratch3, unspec));
       if (TARGET_64BIT)
        {
-         emit_insn (gen_strlenqi_rex_1 (scratch1, scratch3, eoschar,
-                                        align, scratch4, scratch3));
          emit_insn (gen_one_cmpldi2 (scratch2, scratch1));
          emit_insn (gen_adddi3 (out, scratch2, constm1_rtx));
        }
       else
        {
-         emit_insn (gen_strlenqi_1 (scratch1, scratch3, eoschar,
-                                    align, scratch4, scratch3));
          emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
          emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
        }
@@ -11549,7 +11603,7 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
    some address computing at the end.  These things are done in i386.md.  */
 
 static void
-ix86_expand_strlensi_unroll_1 (rtx out, rtx align_rtx)
+ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
 {
   int align;
   rtx tmp;
@@ -11602,7 +11656,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx align_rtx)
                                   Pmode, 1, align_4_label);
         }
 
-      mem = gen_rtx_MEM (QImode, out);
+      mem = change_address (src, QImode, out);
 
       /* Now compare the bytes.  */
 
@@ -11646,7 +11700,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx align_rtx)
      speed up.  */
   emit_label (align_4_label);
 
-  mem = gen_rtx_MEM (SImode, out);
+  mem = change_address (src, SImode, out);
   emit_move_insn (scratch, mem);
   if (TARGET_64BIT)
     emit_insn (gen_adddi3 (out, out, GEN_INT (4)));
@@ -12511,50 +12565,6 @@ ia32_multipass_dfa_lookahead (void)
 }
 
 \f
-/* Walk through INSNS and look for MEM references whose address is DSTREG or
-   SRCREG and set the memory attribute to those of DSTREF and SRCREF, as
-   appropriate.  */
-
-void
-ix86_set_move_mem_attrs (rtx insns, rtx dstref, rtx srcref, rtx dstreg,
-                        rtx srcreg)
-{
-  rtx insn;
-
-  for (insn = insns; insn != 0 ; insn = NEXT_INSN (insn))
-    if (INSN_P (insn))
-      ix86_set_move_mem_attrs_1 (PATTERN (insn), dstref, srcref,
-                                dstreg, srcreg);
-}
-
-/* Subroutine of above to actually do the updating by recursively walking
-   the rtx.  */
-
-static void
-ix86_set_move_mem_attrs_1 (rtx x, rtx dstref, rtx srcref, rtx dstreg,
-                          rtx srcreg)
-{
-  enum rtx_code code = GET_CODE (x);
-  const char *format_ptr = GET_RTX_FORMAT (code);
-  int i, j;
-
-  if (code == MEM && XEXP (x, 0) == dstreg)
-    MEM_COPY_ATTRIBUTES (x, dstref);
-  else if (code == MEM && XEXP (x, 0) == srcreg)
-    MEM_COPY_ATTRIBUTES (x, srcref);
-
-  for (i = 0; i < GET_RTX_LENGTH (code); i++, format_ptr++)
-    {
-      if (*format_ptr == 'e')
-       ix86_set_move_mem_attrs_1 (XEXP (x, i), dstref, srcref,
-                                  dstreg, srcreg);
-      else if (*format_ptr == 'E')
-       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         ix86_set_move_mem_attrs_1 (XVECEXP (x, i, j), dstref, srcref,
-                                    dstreg, srcreg);
-    }
-}
-\f
 /* Compute the alignment given to a constant that is being placed in memory.
    EXP is the constant and ALIGN is the alignment that the object would
    ordinarily have.
index 938a40e..aa2e623 100644 (file)
 ;; Most CPUs don't like single string operations
 ;; Handle this case here to simplify previous expander.
 
-(define_expand "strmovdi_rex64"
-  [(set (match_dup 2)
-       (mem:DI (match_operand:DI 1 "register_operand" "")))
-   (set (mem:DI (match_operand:DI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 8)))
+(define_expand "strmov"
+  [(set (match_dup 4) (match_operand 3 "memory_operand" ""))
+   (set (match_operand 1 "memory_operand" "") (match_dup 4))
+   (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5))
              (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 8)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strmovdi_rex_1 (operands[0], operands[1], operands[0],
-                                    operands[1]));
-      DONE;
-    }
-  else 
-    operands[2] = gen_reg_rtx (DImode);
-})
-
-
-(define_expand "strmovsi"
-  [(set (match_dup 2)
-       (mem:SI (match_operand:SI 1 "register_operand" "")))
-   (set (mem:SI (match_operand:SI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 4)))
-             (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))
+   (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6))
              (clobber (reg:CC 17))])]
   ""
 {
-  if (TARGET_64BIT)
-    {
-      emit_insn (gen_strmovsi_rex64 (operands[0], operands[1]));
-      DONE;
-    }
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strmovsi_1 (operands[0], operands[1], operands[0],
-                               operands[1]));
-      DONE;
-    }
-  else 
-    operands[2] = gen_reg_rtx (SImode);
-})
+  rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
 
-(define_expand "strmovsi_rex64"
-  [(set (match_dup 2)
-       (mem:SI (match_operand:DI 1 "register_operand" "")))
-   (set (mem:SI (match_operand:DI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 4)))
-             (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 4)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strmovsi_rex_1 (operands[0], operands[1], operands[0],
-                                    operands[1]));
-      DONE;
-    }
-  else 
-    operands[2] = gen_reg_rtx (SImode);
-})
+  /* If .md ever supports :P for Pmode, these can be directly
+     in the pattern above.  */
+  operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust);
+  operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust);
 
-(define_expand "strmovhi"
-  [(set (match_dup 2)
-       (mem:HI (match_operand:SI 1 "register_operand" "")))
-   (set (mem:HI (match_operand:SI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 2)))
-             (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 2)))
-             (clobber (reg:CC 17))])]
-  ""
-{
-  if (TARGET_64BIT)
-    {
-      emit_insn (gen_strmovhi_rex64 (operands[0], operands[1]));
-      DONE;
-    }
   if (TARGET_SINGLE_STRINGOP || optimize_size)
     {
-      emit_insn (gen_strmovhi_1 (operands[0], operands[1], operands[0],
-                               operands[1]));
+      emit_insn (gen_strmov_singleop (operands[0], operands[1],
+                                     operands[2], operands[3],
+                                     operands[5], operands[6]));
       DONE;
     }
-  else 
-    operands[2] = gen_reg_rtx (HImode);
-})
-
-(define_expand "strmovhi_rex64"
-  [(set (match_dup 2)
-       (mem:HI (match_operand:DI 1 "register_operand" "")))
-   (set (mem:HI (match_operand:DI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 2)))
-             (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 2)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strmovhi_rex_1 (operands[0], operands[1], operands[0],
-                                    operands[1]));
-      DONE;
-    }
-  else 
-    operands[2] = gen_reg_rtx (HImode);
-})
 
-(define_expand "strmovqi"
-  [(set (match_dup 2)
-       (mem:QI (match_operand:SI 1 "register_operand" "")))
-   (set (mem:QI (match_operand:SI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
-             (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 1)))
-             (clobber (reg:CC 17))])]
-  ""
-{
-  if (TARGET_64BIT)
-    {
-      emit_insn (gen_strmovqi_rex64 (operands[0], operands[1]));
-      DONE;
-    }
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strmovqi_1 (operands[0], operands[1], operands[0],
-                               operands[1]));
-      DONE;
-    }
-  else 
-    operands[2] = gen_reg_rtx (QImode);
+  operands[4] = gen_reg_rtx (GET_MODE (operands[1]));
 })
 
-(define_expand "strmovqi_rex64"
-  [(set (match_dup 2)
-       (mem:QI (match_operand:DI 1 "register_operand" "")))
-   (set (mem:QI (match_operand:DI 0 "register_operand" ""))
-        (match_dup 2))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
-             (clobber (reg:CC 17))])
-   (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 1)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strmovqi_rex_1 (operands[0], operands[1], operands[0],
-                                    operands[1]));
-      DONE;
-    }
-  else 
-    operands[2] = gen_reg_rtx (QImode);
-})
+(define_expand "strmov_singleop"
+  [(parallel [(set (match_operand 1 "memory_operand" "")
+                  (match_operand 3 "memory_operand" ""))
+             (set (match_operand 0 "register_operand" "")
+                  (match_operand 4 "" ""))
+             (set (match_operand 2 "register_operand" "")
+                  (match_operand 5 "" ""))
+             (use (reg:SI 19))])]
+  "TARGET_SINGLE_STRINGOP || optimize_size"
+  "")
 
-(define_insn "strmovdi_rex_1"
+(define_insn "*strmovdi_rex_1"
   [(set (mem:DI (match_operand:DI 2 "register_operand" "0"))
        (mem:DI (match_operand:DI 3 "register_operand" "1")))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "mode" "DI")
    (set_attr "memory" "both")])
 
-(define_insn "strmovsi_1"
+(define_insn "*strmovsi_1"
   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
        (mem:SI (match_operand:SI 3 "register_operand" "1")))
    (set (match_operand:SI 0 "register_operand" "=D")
    (set_attr "mode" "SI")
    (set_attr "memory" "both")])
 
-(define_insn "strmovsi_rex_1"
+(define_insn "*strmovsi_rex_1"
   [(set (mem:SI (match_operand:DI 2 "register_operand" "0"))
        (mem:SI (match_operand:DI 3 "register_operand" "1")))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "mode" "SI")
    (set_attr "memory" "both")])
 
-(define_insn "strmovhi_1"
+(define_insn "*strmovhi_1"
   [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
        (mem:HI (match_operand:SI 3 "register_operand" "1")))
    (set (match_operand:SI 0 "register_operand" "=D")
    (set_attr "memory" "both")
    (set_attr "mode" "HI")])
 
-(define_insn "strmovhi_rex_1"
+(define_insn "*strmovhi_rex_1"
   [(set (mem:HI (match_operand:DI 2 "register_operand" "0"))
        (mem:HI (match_operand:DI 3 "register_operand" "1")))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "memory" "both")
    (set_attr "mode" "HI")])
 
-(define_insn "strmovqi_1"
+(define_insn "*strmovqi_1"
   [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
        (mem:QI (match_operand:SI 3 "register_operand" "1")))
    (set (match_operand:SI 0 "register_operand" "=D")
    (set_attr "memory" "both")
    (set_attr "mode" "QI")])
 
-(define_insn "strmovqi_rex_1"
+(define_insn "*strmovqi_rex_1"
   [(set (mem:QI (match_operand:DI 2 "register_operand" "0"))
        (mem:QI (match_operand:DI 3 "register_operand" "1")))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "memory" "both")
    (set_attr "mode" "QI")])
 
-(define_insn "rep_movdi_rex64"
+(define_expand "rep_mov"
+  [(parallel [(set (match_operand 4 "register_operand" "") (const_int 0))
+             (set (match_operand 0 "register_operand" "")
+                  (match_operand 5 "" ""))
+             (set (match_operand 2 "register_operand" "")
+                  (match_operand 6 "" ""))
+             (set (match_operand 1 "memory_operand" "")
+                  (match_operand 3 "memory_operand" ""))
+             (use (match_dup 4))
+             (use (reg:SI 19))])]
+  ""
+  "")
+
+(define_insn "*rep_movdi_rex64"
   [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
    (set (match_operand:DI 0 "register_operand" "=D") 
         (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
    (set_attr "memory" "both")
    (set_attr "mode" "DI")])
 
-(define_insn "rep_movsi"
+(define_insn "*rep_movsi"
   [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
    (set (match_operand:SI 0 "register_operand" "=D") 
         (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
    (set_attr "memory" "both")
    (set_attr "mode" "SI")])
 
-(define_insn "rep_movsi_rex64"
+(define_insn "*rep_movsi_rex64"
   [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
    (set (match_operand:DI 0 "register_operand" "=D") 
         (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2")
    (set_attr "memory" "both")
    (set_attr "mode" "SI")])
 
-(define_insn "rep_movqi"
+(define_insn "*rep_movqi"
   [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
    (set (match_operand:SI 0 "register_operand" "=D") 
         (plus:SI (match_operand:SI 3 "register_operand" "0")
    (set_attr "memory" "both")
    (set_attr "mode" "SI")])
 
-(define_insn "rep_movqi_rex64"
+(define_insn "*rep_movqi_rex64"
   [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0))
    (set (match_operand:DI 0 "register_operand" "=D") 
         (plus:DI (match_operand:DI 3 "register_operand" "0")
 ;; Most CPUs don't like single string operations
 ;; Handle this case here to simplify previous expander.
 
-(define_expand "strsetdi_rex64"
-  [(set (mem:DI (match_operand:DI 0 "register_operand" ""))
-       (match_operand:DI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 8)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strsetdi_rex_1 (operands[0], operands[0], operands[1]));
-      DONE;
-    }
-})
-
-(define_expand "strsetsi"
-  [(set (mem:SI (match_operand:SI 0 "register_operand" ""))
-       (match_operand:SI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 4)))
-             (clobber (reg:CC 17))])]
-  ""
-{
-  if (TARGET_64BIT)
-    {
-      emit_insn (gen_strsetsi_rex64 (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strsetsi_1 (operands[0], operands[0], operands[1]));
-      DONE;
-    }
-})
-
-(define_expand "strsetsi_rex64"
-  [(set (mem:SI (match_operand:DI 0 "register_operand" ""))
-       (match_operand:SI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 4)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strsetsi_rex_1 (operands[0], operands[0], operands[1]));
-      DONE;
-    }
-})
-
-(define_expand "strsethi"
-  [(set (mem:HI (match_operand:SI 0 "register_operand" ""))
-       (match_operand:HI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 2)))
+(define_expand "strset"
+  [(set (match_operand 1 "memory_operand" "")
+       (match_operand 2 "register_operand" ""))
+   (parallel [(set (match_operand 0 "register_operand" "")
+                  (match_dup 3))
              (clobber (reg:CC 17))])]
   ""
 {
-  if (TARGET_64BIT)
-    {
-      emit_insn (gen_strsethi_rex64 (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strsethi_1 (operands[0], operands[0], operands[1]));
-      DONE;
-    }
-})
+  if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
+    operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
 
-(define_expand "strsethi_rex64"
-  [(set (mem:HI (match_operand:DI 0 "register_operand" ""))
-       (match_operand:HI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 2)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
+  /* If .md ever supports :P for Pmode, this can be directly
+     in the pattern above.  */
+  operands[3] = gen_rtx_PLUS (Pmode, operands[0],
+                             GEN_INT (GET_MODE_SIZE (GET_MODE
+                                                     (operands[2]))));
   if (TARGET_SINGLE_STRINGOP || optimize_size)
     {
-      emit_insn (gen_strsethi_rex_1 (operands[0], operands[0], operands[1]));
-      DONE;
-    }
-})
-
-(define_expand "strsetqi"
-  [(set (mem:QI (match_operand:SI 0 "register_operand" ""))
-       (match_operand:QI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
-             (clobber (reg:CC 17))])]
-  ""
-{
-  if (TARGET_64BIT)
-    {
-      emit_insn (gen_strsetqi_rex64 (operands[0], operands[1]));
-      DONE;
-    }
-  else if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strsetqi_1 (operands[0], operands[0], operands[1]));
+      emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
+                                     operands[3]));
       DONE;
     }
 })
 
-(define_expand "strsetqi_rex64"
-  [(set (mem:QI (match_operand:DI 0 "register_operand" ""))
-       (match_operand:QI 1 "register_operand" ""))
-   (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
-             (clobber (reg:CC 17))])]
-  "TARGET_64BIT"
-{
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
-    {
-      emit_insn (gen_strsetqi_rex_1 (operands[0], operands[0], operands[1]));
-      DONE;
-    }
-})
+(define_expand "strset_singleop"
+  [(parallel [(set (match_operand 1 "memory_operand" "")
+                  (match_operand 2 "register_operand" ""))
+             (set (match_operand 0 "register_operand" "")
+                  (match_operand 3 "" ""))
+             (use (reg:SI 19))])]
+  "TARGET_SINGLE_STRINGOP || optimize_size"
+  "")
 
-(define_insn "strsetdi_rex_1"
+(define_insn "*strsetdi_rex_1"
   [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
        (match_operand:SI 2 "register_operand" "a"))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "DI")])
 
-(define_insn "strsetsi_1"
+(define_insn "*strsetsi_1"
   [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
        (match_operand:SI 2 "register_operand" "a"))
    (set (match_operand:SI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "SI")])
 
-(define_insn "strsetsi_rex_1"
+(define_insn "*strsetsi_rex_1"
   [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
        (match_operand:SI 2 "register_operand" "a"))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "SI")])
 
-(define_insn "strsethi_1"
+(define_insn "*strsethi_1"
   [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
        (match_operand:HI 2 "register_operand" "a"))
    (set (match_operand:SI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "HI")])
 
-(define_insn "strsethi_rex_1"
+(define_insn "*strsethi_rex_1"
   [(set (mem:HI (match_operand:DI 1 "register_operand" "0"))
        (match_operand:HI 2 "register_operand" "a"))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "HI")])
 
-(define_insn "strsetqi_1"
+(define_insn "*strsetqi_1"
   [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
        (match_operand:QI 2 "register_operand" "a"))
    (set (match_operand:SI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "QI")])
 
-(define_insn "strsetqi_rex_1"
+(define_insn "*strsetqi_rex_1"
   [(set (mem:QI (match_operand:DI 1 "register_operand" "0"))
        (match_operand:QI 2 "register_operand" "a"))
    (set (match_operand:DI 0 "register_operand" "=D")
    (set_attr "memory" "store")
    (set_attr "mode" "QI")])
 
-(define_insn "rep_stosdi_rex64"
+(define_expand "rep_stos"
+  [(parallel [(set (match_operand 1 "register_operand" "") (const_int 0))
+             (set (match_operand 0 "register_operand" "")
+                  (match_operand 4 "" ""))
+             (set (match_operand 2 "memory_operand" "") (const_int 0))
+             (use (match_operand 3 "register_operand" ""))
+             (use (match_dup 1))
+             (use (reg:SI 19))])]
+  ""
+  "")
+
+(define_insn "*rep_stosdi_rex64"
   [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
    (set (match_operand:DI 0 "register_operand" "=D") 
         (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
    (set_attr "memory" "store")
    (set_attr "mode" "DI")])
 
-(define_insn "rep_stossi"
+(define_insn "*rep_stossi"
   [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
    (set (match_operand:SI 0 "register_operand" "=D") 
         (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
    (set_attr "memory" "store")
    (set_attr "mode" "SI")])
 
-(define_insn "rep_stossi_rex64"
+(define_insn "*rep_stossi_rex64"
   [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
    (set (match_operand:DI 0 "register_operand" "=D") 
         (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1")
    (set_attr "memory" "store")
    (set_attr "mode" "SI")])
 
-(define_insn "rep_stosqi"
+(define_insn "*rep_stosqi"
   [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
    (set (match_operand:SI 0 "register_operand" "=D") 
         (plus:SI (match_operand:SI 3 "register_operand" "0")
    (set_attr "memory" "store")
    (set_attr "mode" "QI")])
 
-(define_insn "rep_stosqi_rex64"
+(define_insn "*rep_stosqi_rex64"
   [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0))
    (set (match_operand:DI 0 "register_operand" "=D") 
         (plus:DI (match_operand:DI 3 "register_operand" "0")
        (const_int 0))
    (use (match_operand:QI 2 "register_operand" "a"))
    (use (match_dup 4))
-   (use (reg:DI 19))]
+   (use (reg:SI 19))]
   "TARGET_64BIT"
   "{rep\;stosb|rep stosb}"
   [(set_attr "type" "str")
 
   addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
   addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
-  
+  if (addr1 != XEXP (operands[1], 0))
+    operands[1] = replace_equiv_address_nv (operands[1], addr1);
+  if (addr2 != XEXP (operands[2], 0))
+    operands[2] = replace_equiv_address_nv (operands[2], addr2);
+
   count = operands[3];
   countreg = ix86_zero_extend_to_Pmode (count);
 
          emit_move_insn (operands[0], const0_rtx);
          DONE;
        }
-      if (TARGET_64BIT)
-       emit_insn (gen_cmpstrqi_nz_rex_1 (addr1, addr2, countreg, align,
-                                         addr1, addr2, countreg));
-      else
-       emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align,
-                                     addr1, addr2, countreg));
+      emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align,
+                                   operands[1], operands[2]));
     }
   else
     {
       if (TARGET_64BIT)
-       {
-         emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
-         emit_insn (gen_cmpstrqi_rex_1 (addr1, addr2, countreg, align,
-                                        addr1, addr2, countreg));
-       }
+       emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
       else
-       {
-         emit_insn (gen_cmpsi_1 (countreg, countreg));
-         emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align,
-                                    addr1, addr2, countreg));
-       }
+       emit_insn (gen_cmpsi_1 (countreg, countreg));
+      emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align,
+                                operands[1], operands[2]));
     }
 
   outlow = gen_lowpart (QImode, out);
 ;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
 ;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
 
-(define_insn "cmpstrqi_nz_1"
+(define_expand "cmpstrqi_nz_1"
+  [(parallel [(set (reg:CC 17)
+                  (compare:CC (match_operand 4 "memory_operand" "")
+                              (match_operand 5 "memory_operand" "")))
+             (use (match_operand 2 "register_operand" ""))
+             (use (match_operand:SI 3 "immediate_operand" ""))
+             (use (reg:SI 19))
+             (clobber (match_operand 0 "register_operand" ""))
+             (clobber (match_operand 1 "register_operand" ""))
+             (clobber (match_dup 2))])]
+  ""
+  "")
+
+(define_insn "*cmpstrqi_nz_1"
   [(set (reg:CC 17)
        (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
                    (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
    (set_attr "mode" "QI")
    (set_attr "prefix_rep" "1")])
 
-(define_insn "cmpstrqi_nz_rex_1"
+(define_insn "*cmpstrqi_nz_rex_1"
   [(set (reg:CC 17)
        (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
                    (mem:BLK (match_operand:DI 5 "register_operand" "1"))))
 
 ;; The same, but the count is not known to not be zero.
 
-(define_insn "cmpstrqi_1"
+(define_expand "cmpstrqi_1"
+  [(parallel [(set (reg:CC 17)
+               (if_then_else:CC (ne (match_operand 2 "register_operand" "")
+                                    (const_int 0))
+                 (compare:CC (match_operand 4 "memory_operand" "")
+                             (match_operand 5 "memory_operand" ""))
+                 (const_int 0)))
+             (use (match_operand:SI 3 "immediate_operand" ""))
+             (use (reg:CC 17))
+             (use (reg:SI 19))
+             (clobber (match_operand 0 "register_operand" ""))
+             (clobber (match_operand 1 "register_operand" ""))
+             (clobber (match_dup 2))])]
+  ""
+  "")
+
+(define_insn "*cmpstrqi_1"
   [(set (reg:CC 17)
        (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
                             (const_int 0))
    (set_attr "mode" "QI")
    (set_attr "prefix_rep" "1")])
 
-(define_insn "cmpstrqi_rex_1"
+(define_insn "*cmpstrqi_rex_1"
   [(set (reg:CC 17)
        (if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
                             (const_int 0))
    FAIL;
 })
 
-(define_insn "strlenqi_1"
+(define_expand "strlenqi_1"
+  [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" ""))
+             (use (reg:SI 19))
+             (clobber (match_operand 1 "register_operand" ""))
+             (clobber (reg:CC 17))])]
+  ""
+  "")
+
+(define_insn "*strlenqi_1"
   [(set (match_operand:SI 0 "register_operand" "=&c")
        (unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
                    (match_operand:QI 2 "register_operand" "a")
    (set_attr "mode" "QI")
    (set_attr "prefix_rep" "1")])
 
-(define_insn "strlenqi_rex_1"
+(define_insn "*strlenqi_rex_1"
   [(set (match_operand:DI 0 "register_operand" "=&c")
        (unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1"))
                    (match_operand:QI 2 "register_operand" "a")
index 294577c..b1429da 100644 (file)
@@ -1869,19 +1869,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)
-    return new;
+    {
+      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, addr);
+      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;
 }
index 861f90c..8bf0732 100644 (file)
@@ -4619,10 +4619,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                                       highest_pow2_factor (offset));
            }
 
-         /* If the constructor has been cleared, setting RTX_UNCHANGING_P
-            on the MEM might lead to scheduling the clearing after the
-            store.  */
-         if (TREE_READONLY (field) && !cleared)
+         if (TREE_READONLY (field))
            {
              if (GET_CODE (to_rtx) == MEM)
                to_rtx = copy_rtx (to_rtx);