diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/doc/md.texi | 7 | ||||
-rw-r--r-- | gcc/expr.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr58981.c | 55 |
5 files changed, 83 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6dd16fc34f1..9b21a3a5445 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index ac10a0ad03c..1e22b88f608 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -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 diff --git a/gcc/expr.c b/gcc/expr.c index 551a66059b9..8ef28709a4e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 75abe6d1711..21864c690c7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/gcc.dg/pr58981.c b/gcc/testsuite/gcc.dg/pr58981.c new file mode 100644 index 00000000000..1c8293e4985 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58981.c @@ -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; +} |