expr.c (store_expr): Optimize initialization of an array with STRING_CST.
authorJakub Jelinek <jakub@redhat.com>
Fri, 24 Aug 2007 12:29:14 +0000 (14:29 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 24 Aug 2007 12:29:14 +0000 (14:29 +0200)
* expr.c (store_expr): Optimize initialization of an array
with STRING_CST.
* expr.h (builtin_strncpy_read_str): New prototype.
* builtins.c (builtin_strncpy_read_str): Remove prototype.
No longer static.

* gcc.dg/array-init-1.c: New test.

From-SVN: r127769

gcc/ChangeLog
gcc/builtins.c
gcc/expr.c
gcc/expr.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/array-init-1.c [new file with mode: 0644]

index 70b326f78c215592d8a6e71993b67c349d5ff1ab..18e9586769af592858a8b03b43a9ca1a9990415c 100644 (file)
@@ -1,3 +1,11 @@
+2007-08-24  Jakub Jelinek  <jakub@redhat.com>
+
+       * expr.c (store_expr): Optimize initialization of an array
+       with STRING_CST.
+       * expr.h (builtin_strncpy_read_str): New prototype.
+       * builtins.c (builtin_strncpy_read_str): Remove prototype.
+       No longer static.
+
 2007-08-24  Uros Bizjak  <ubizjak@gmail.com>
 
        PR middle-end/33157
index 2814d3079694cee4ab49c0584764480acbe3d002..8d2657b3c8298d02a0c7ad17ae6fc3ba6cd85ac8 100644 (file)
@@ -125,7 +125,6 @@ static rtx expand_builtin_bcopy (tree, int);
 static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
-static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
 static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
@@ -3734,7 +3733,7 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
    bytes from constant string DATA + OFFSET and return it as target
    constant.  */
 
-static rtx
+rtx
 builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
                          enum machine_mode mode)
 {
index a3b8132709f1f47dbf73c567c42ba11fcd49fd98..97116b33daa18c17419f85dc87a9b7c639593049 100644 (file)
@@ -4472,10 +4472,52 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
 
       return NULL_RTX;
     }
+  else if (TREE_CODE (exp) == STRING_CST
+          && !nontemporal && !call_param_p
+          && TREE_STRING_LENGTH (exp) > 0
+          && TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
+    {
+      /* Optimize initialization of an array with a STRING_CST.  */
+      HOST_WIDE_INT exp_len, str_copy_len;
+      rtx dest_mem;
+
+      exp_len = int_expr_size (exp);
+      if (exp_len <= 0)
+       goto normal_expr;
+
+      str_copy_len = strlen (TREE_STRING_POINTER (exp));
+      if (str_copy_len < TREE_STRING_LENGTH (exp) - 1)
+       goto normal_expr;
+
+      str_copy_len = TREE_STRING_LENGTH (exp);
+      if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0)
+       {
+         str_copy_len += STORE_MAX_PIECES - 1;
+         str_copy_len &= ~(STORE_MAX_PIECES - 1);
+       }
+      str_copy_len = MIN (str_copy_len, exp_len);
+      if (!can_store_by_pieces (str_copy_len, builtin_strncpy_read_str,
+                               (void *) TREE_STRING_POINTER (exp),
+                               MEM_ALIGN (target)))
+       goto normal_expr;
+
+      dest_mem = target;
+
+      dest_mem = store_by_pieces (dest_mem,
+                                 str_copy_len, builtin_strncpy_read_str,
+                                 (void *) TREE_STRING_POINTER (exp),
+                                 MEM_ALIGN (target),
+                                 exp_len > str_copy_len ? 1 : 0);
+      if (exp_len > str_copy_len)
+       clear_storage (dest_mem, GEN_INT (exp_len - str_copy_len),
+                      BLOCK_OP_NORMAL);
+      return NULL_RTX;
+    }
   else
     {
       rtx tmp_target;
 
+  normal_expr:
       /* If we want to use a nontemporal store, force the value to
         register first.  */
       tmp_target = nontemporal ? NULL_RTX : target;
index ed5b84b004e028831748555e098591497f772537..242329a37bef7b24cf3a3c3a87a0bd914d641739 100644 (file)
@@ -341,6 +341,7 @@ extern void expand_builtin_setjmp_setup (rtx, rtx);
 extern void expand_builtin_setjmp_receiver (rtx);
 extern rtx expand_builtin_saveregs (void);
 extern void expand_builtin_trap (void);
+extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 \f
 /* Functions from expr.c:  */
 
index e4b7ed24eb5087635787ecc576f2e48bf2b5fbce..f7092ecf2cb10cecbceb18f7623c7a5c4308a21a 100644 (file)
@@ -1,5 +1,7 @@
 2007-08-24  Jakub Jelinek  <jakub@redhat.com>
 
+       * gcc.dg/array-init-1.c: New test.
+
        PR c++/32567
        * g++.dg/parse/crash36.C: New test.
 
diff --git a/gcc/testsuite/gcc.dg/array-init-1.c b/gcc/testsuite/gcc.dg/array-init-1.c
new file mode 100644 (file)
index 0000000..8b866cc
--- /dev/null
@@ -0,0 +1,24 @@
+/* Test that both arrays are initialized by store_by_pieces.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct A { char c[10]; };
+extern void baz (struct A *);
+
+void
+foo (void)
+{
+  struct A a = { "abcdefghi" };
+  baz (&a);
+}
+
+void
+bar (void)
+{
+  struct A a;
+  __builtin_strcpy (&a.c[0], "abcdefghi");
+  baz (&a);
+}
+
+/* { dg-final { scan-assembler-not "abcdefghi" { target i?86-*-* x86_64-*-* ia64-*-* } } } */
+/* { dg-final { scan-assembler-times "7523094288207667809\|6867666564636261\|1684234849\|64636261" 2 { target i?86-*-* x86_64-*-* ia64-*-* } } } */