2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-03-26 19:51:12 +08:00

re PR rtl-optimization/13424 (gcc.dg/20031202-1.c is miscompiled)

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
This commit is contained in:
Jakub Jelinek 2004-01-29 09:05:47 +01:00 committed by Jakub Jelinek
parent f470c378ac
commit 4e44c1ef05
6 changed files with 373 additions and 466 deletions

@ -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.

@ -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);

@ -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)));
@ -12510,50 +12564,6 @@ ia32_multipass_dfa_lookahead (void)
return 0;
}
/* 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);
}
}
/* 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

@ -15357,170 +15357,45 @@
;; 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;
}
rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
/* 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);
if (TARGET_SINGLE_STRINGOP || optimize_size)
{
emit_insn (gen_strmovsi_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 (SImode);
operands[4] = gen_reg_rtx (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);
})
(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_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]));
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);
})
(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_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")
@ -15536,7 +15411,7 @@
(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")
@ -15552,7 +15427,7 @@
(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")
@ -15568,7 +15443,7 @@
(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")
@ -15584,7 +15459,7 @@
(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")
@ -15600,7 +15475,7 @@
(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")
@ -15616,7 +15491,7 @@
(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")
@ -15632,7 +15507,20 @@
(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")
@ -15652,7 +15540,7 @@
(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")
@ -15672,7 +15560,7 @@
(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")
@ -15692,7 +15580,7 @@
(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")
@ -15710,7 +15598,7 @@
(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")
@ -15755,120 +15643,40 @@
;; 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)))
(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_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;
}
})
if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
(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 .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_strsetsi_rex_1 (operands[0], operands[0], operands[1]));
emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2],
operands[3]));
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)))
(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;
}
})
(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_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 (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]));
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_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")
@ -15881,7 +15689,7 @@
(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")
@ -15894,7 +15702,7 @@
(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")
@ -15907,7 +15715,7 @@
(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")
@ -15920,7 +15728,7 @@
(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")
@ -15933,7 +15741,7 @@
(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")
@ -15946,7 +15754,7 @@
(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")
@ -15959,7 +15767,18 @@
(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")
@ -15977,7 +15796,7 @@
(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")
@ -15995,7 +15814,7 @@
(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")
@ -16013,7 +15832,7 @@
(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")
@ -16030,7 +15849,7 @@
(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")
@ -16039,7 +15858,7 @@
(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")
@ -16067,7 +15886,11 @@
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);
@ -16084,27 +15907,17 @@
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);
@ -16135,7 +15948,20 @@
;; 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"))))
@ -16151,7 +15977,7 @@
(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"))))
@ -16169,7 +15995,23 @@
;; 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))
@ -16188,7 +16030,7 @@
(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))
@ -16233,7 +16075,15 @@
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")
@ -16248,7 +16098,7 @@
(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")

@ -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;
}

@ -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);