summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-05 14:17:33 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-05 14:17:33 +0000
commit300c6ceec3d8a1a5f898c399e63381e3203c24bc (patch)
treeff433ccdf462aa7465faa04380de59abd9507cd5
parentf5ea8c530cdc4e8a16a7f69f38b0eaa613a35036 (diff)
downloadppe42-gcc-300c6ceec3d8a1a5f898c399e63381e3203c24bc.tar.gz
ppe42-gcc-300c6ceec3d8a1a5f898c399e63381e3203c24bc.zip
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204394 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/doc/md.texi7
-rw-r--r--gcc/expr.c16
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr58981.c55
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;
+}
OpenPOWER on IntegriCloud