Don't use mode wider than Pmode for size in movmem/setmem

gcc/

	PR middle-end/58981
	* doc/md.texi (@code{movmem@var{m}}): Specify Pmode as mode of
	pattern, instead of word_mode.

	* expr.c (emit_block_move_via_movmem): Don't use mode wider than
	Pmode for size.
	(set_storage_via_setmem): Likewise.

gcc/testsuite/

	PR middle-end/58981
	* gcc.dg/pr58981.c: New test.

From-SVN: r204394
This commit is contained in:
H.J. Lu 2013-11-05 14:17:33 +00:00 committed by H.J. Lu
parent c8d97db2cc
commit 5689294cd9
5 changed files with 83 additions and 10 deletions

View File

@ -1,3 +1,13 @@
2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/58981
* doc/md.texi (@code{movmem@var{m}}): Specify Pmode as mode of
pattern, instead of word_mode.
* expr.c (emit_block_move_via_movmem): Don't use mode wider than
Pmode for size.
(set_storage_via_setmem): Likewise.
2013-11-05 Andrew MacLeod <amacleod@redhat.com>
* tree-outof-ssa.c (queue_phi_copy_p): Combine phi_ssa_name_p from

View File

@ -5291,12 +5291,13 @@ are the first two operands, and both are @code{mem:BLK}s with an
address in mode @code{Pmode}.
The number of bytes to move is the third operand, in mode @var{m}.
Usually, you specify @code{word_mode} for @var{m}. However, if you can
Usually, you specify @code{Pmode} for @var{m}. However, if you can
generate better code knowing the range of valid lengths is smaller than
those representable in a full word, you should provide a pattern with a
those representable in a full Pmode pointer, you should provide
a pattern with a
mode corresponding to the range of values you can handle efficiently
(e.g., @code{QImode} for values in the range 0--127; note we avoid numbers
that appear negative) and also a pattern with @code{word_mode}.
that appear negative) and also a pattern with @code{Pmode}.
The fourth operand is the known shared alignment of the source and
destination, in the form of a @code{const_int} rtx. Thus, if the

View File

@ -1297,11 +1297,12 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
/* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
here because if SIZE is less than the mode mask, as it is
returned by the macro, it will definitely be less than the
actual mode mask. */
actual mode mask. Since SIZE is within the Pmode address
space, we limit MODE to Pmode. */
&& ((CONST_INT_P (size)
&& ((unsigned HOST_WIDE_INT) INTVAL (size)
<= (GET_MODE_MASK (mode) >> 1)))
|| GET_MODE_BITSIZE (mode) >= BITS_PER_WORD))
|| GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode)))
{
struct expand_operand ops[6];
unsigned int nops;
@ -2879,14 +2880,15 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
enum insn_code code = direct_optab_handler (setmem_optab, mode);
if (code != CODE_FOR_nothing
/* We don't need MODE to be narrower than
BITS_PER_HOST_WIDE_INT here because if SIZE is less than
the mode mask, as it is returned by the macro, it will
definitely be less than the actual mode mask. */
/* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
here because if SIZE is less than the mode mask, as it is
returned by the macro, it will definitely be less than the
actual mode mask. Since SIZE is within the Pmode address
space, we limit MODE to Pmode. */
&& ((CONST_INT_P (size)
&& ((unsigned HOST_WIDE_INT) INTVAL (size)
<= (GET_MODE_MASK (mode) >> 1)))
|| GET_MODE_BITSIZE (mode) >= BITS_PER_WORD))
|| GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode)))
{
struct expand_operand ops[6];
unsigned int nops;

View File

@ -1,3 +1,8 @@
2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/58981
* gcc.dg/pr58981.c: New test.
2013-11-05 Richard Biener <rguenther@suse.de>
PR middle-end/58941

View File

@ -0,0 +1,55 @@
/* { dg-do run } */
/* { dg-options "-O2" } */
/* { dg-additional-options "-minline-all-stringops" { target { i?86-*-* x86_64-*-* } } } */
extern void abort (void);
#define MAX_OFFSET (sizeof (long long))
#define MAX_COPY (8 * sizeof (long long))
#define MAX_EXTRA (sizeof (long long))
#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
static union {
char buf[MAX_LENGTH];
long long align_int;
long double align_fp;
} u;
char A[MAX_LENGTH];
int
main ()
{
int off, len, i;
char *p, *q;
for (i = 0; i < MAX_LENGTH; i++)
A[i] = 'A';
for (off = 0; off < MAX_OFFSET; off++)
for (len = 1; len < MAX_COPY; len++)
{
for (i = 0; i < MAX_LENGTH; i++)
u.buf[i] = 'a';
p = __builtin_memcpy (u.buf + off, A, len);
if (p != u.buf + off)
abort ();
q = u.buf;
for (i = 0; i < off; i++, q++)
if (*q != 'a')
abort ();
for (i = 0; i < len; i++, q++)
if (*q != 'A')
abort ();
for (i = 0; i < MAX_EXTRA; i++, q++)
if (*q != 'a')
abort ();
}
return 0;
}