Don't use mode wider than Pmode for size in movmem/setmem
authorH.J. Lu <hongjiu.lu@intel.com>
Tue, 5 Nov 2013 14:17:33 +0000 (14:17 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Tue, 5 Nov 2013 14:17:33 +0000 (06:17 -0800)
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

gcc/ChangeLog
gcc/doc/md.texi
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr58981.c [new file with mode: 0644]

index 6dd16fc34f1b9e36b05d46f38765636fd7989720..9b21a3a544579c73f0f125c7601393572037f935 100644 (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 
index ac10a0ad03c6ca51eb73124c456090644b804996..1e22b88f6081eca91f49f480c1e7f939bf673145 100644 (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
index 551a66059b9a034a922063df90c1b48e6241de57..8ef28709a4e7aa71f052b1afad4f521a4a180a16 100644 (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;
index 75abe6d1711525420a90d527d76ddc18c34dbc0f..21864c690c7c4a869799f3f2f5a1e52a0b28a090 100644 (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
diff --git a/gcc/testsuite/gcc.dg/pr58981.c b/gcc/testsuite/gcc.dg/pr58981.c
new file mode 100644 (file)
index 0000000..1c8293e
--- /dev/null
@@ -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;
+}