]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
builtins.c (expand_builtin_strcat): Optimize constant strings.
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>
Mon, 11 Aug 2003 03:15:15 +0000 (03:15 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Mon, 11 Aug 2003 03:15:15 +0000 (03:15 +0000)
* builtins.c (expand_builtin_strcat): Optimize constant strings.

testsuite:
* gcc.c-torture/execute/string-opt-9.c: Add more strcat cases.

From-SVN: r70317

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/string-opt-9.c

index 407250f70fdc2e7309bc93d5f70705ad23a207e4..2c4e5de420e0b1a746e8c8d466e52fb2e23fb0a2 100644 (file)
@@ -1,3 +1,7 @@
+2003-08-10  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * builtins.c (expand_builtin_strcat): Optimize constant strings.
+
 2003-08-10  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
        * pretty-print.c (pp_base_indent): Rename from pp_indent.
index f9d953cc7d1b8254db1ac98609396e0239dfec12..a7265bf374cdf154af6fad3c154e4a1245c68280 100644 (file)
@@ -3577,9 +3577,52 @@ expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
        src = TREE_VALUE (TREE_CHAIN (arglist));
       const char *p = c_getstr (src);
 
-      /* If the string length is zero, return the dst parameter.  */
-      if (p && *p == '\0')
-       return expand_expr (dst, target, mode, EXPAND_NORMAL);
+      if (p)
+       {
+         /* If the string length is zero, return the dst parameter.  */
+         if (*p == '\0')
+           return expand_expr (dst, target, mode, EXPAND_NORMAL);
+         else if (!optimize_size)
+           {
+             /* Otherwise if !optimize_size, see if we can store by
+                 pieces into (dst + strlen(dst)).  */
+             tree newdst, arglist,
+               strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+             
+             /* This is the length argument.  */
+             arglist = build_tree_list (NULL_TREE,
+                                        fold (size_binop (PLUS_EXPR,
+                                                          c_strlen (src, 0),
+                                                          ssize_int (1))));
+             /* Prepend src argument.  */
+             arglist = tree_cons (NULL_TREE, src, arglist);
+             
+             /* We're going to use dst more than once.  */
+             dst = save_expr (dst);
+
+             /* Create strlen (dst).  */
+             newdst =
+               fold (build_function_call_expr (strlen_fn,
+                                               build_tree_list (NULL_TREE,
+                                                                dst)));
+             /* Create (dst + strlen (dst)).  */
+             newdst = fold (build (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
+
+             /* Prepend the new dst argument.  */
+             arglist = tree_cons (NULL_TREE, newdst, arglist);
+             
+             /* We don't want to get turned into a memcpy if the
+                 target is const0_rtx, i.e. when the return value
+                 isn't used.  That would produce pessimized code so
+                 pass in a target of zero, it should never actually be
+                 used.  If this was successful return the original
+                 dst, not the result of mempcpy.  */
+             if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
+               return expand_expr (dst, target, mode, EXPAND_NORMAL);
+             else
+               return 0;
+           }
+       }
 
       return 0;
     }
index 9580129a8b58c850d2f7f71c007c0f3cf6a5c8af..d4bd22d6b5aa73599302655119164e3d5b0c5a4b 100644 (file)
@@ -1,3 +1,7 @@
+2003-08-10  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.c-torture/execute/string-opt-9.c: Add more strcat cases.
+
 2003-08-10  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/11789.C
index 889425d7dc4a8053aa1932065e65413a59712fa9..0c21957f28642775c0b0c6528e5d7a5c45b05c81 100644 (file)
@@ -10,6 +10,10 @@ typedef __SIZE_TYPE__ size_t;
 extern char *strcat (char *, const char *);
 extern char *strcpy (char *, const char *);
 extern int strcmp (const char *, const char *);
+extern void *memset (void *, int, size_t);
+extern int memcmp (const void *, const void *, size_t);
+#define RESET_DST_WITH(FILLER) \
+  do { memset (dst, 'X', sizeof (dst)); strcpy (dst, (FILLER)); } while (0)
 
 int main ()
 {
@@ -17,25 +21,48 @@ int main ()
   const char *const s2 = "";
   char dst[64], *d2;
   
-  strcpy (dst, s1);
+  RESET_DST_WITH (s1);
   if (strcat (dst, "") != dst || strcmp (dst, s1))
     abort();
-  strcpy (dst, s1);
+  RESET_DST_WITH (s1);
   if (strcat (dst, s2) != dst || strcmp (dst, s1))
     abort();
-  strcpy (dst, s1); d2 = dst;
+  RESET_DST_WITH (s1); d2 = dst;
   if (strcat (++d2, s2) != dst+1 || d2 != dst+1 || strcmp (dst, s1))
     abort();
-  strcpy (dst, s1); d2 = dst;
+  RESET_DST_WITH (s1); d2 = dst;
   if (strcat (++d2+5, s2) != dst+6 || d2 != dst+1 || strcmp (dst, s1))
     abort();
-  strcpy (dst, s1); d2 = dst;
+  RESET_DST_WITH (s1); d2 = dst;
   if (strcat (++d2+5, s1+11) != dst+6 || d2 != dst+1 || strcmp (dst, s1))
     abort();
 
+#ifndef __OPTIMIZE_SIZE__
+  RESET_DST_WITH (s1);
+  if (strcat (dst, " 1111") != dst
+      || memcmp (dst, "hello world 1111\0XXX", 20))
+    abort();
+  
+  RESET_DST_WITH (s1);
+  if (strcat (dst+5, " 2222") != dst+5
+      || memcmp (dst, "hello world 2222\0XXX", 20))
+    abort();
+  
+  RESET_DST_WITH (s1); d2 = dst;
+  if (strcat (++d2+5, " 3333") != dst+6 || d2 != dst+1
+      || memcmp (dst, "hello world 3333\0XXX", 20))
+    abort();
+  
+  RESET_DST_WITH (s1);
+  strcat (strcat (strcat (strcat (strcat (strcat (dst, ": this "), ""),
+                                 "is "), "a "), "test"), ".");
+  if (memcmp (dst, "hello world: this is a test.\0X", 30))
+    abort();
+#endif
+
   /* Test at least one instance of the __builtin_ style.  We do this
      to ensure that it works and that the prototype is correct.  */
-  strcpy (dst, s1);
+  RESET_DST_WITH (s1);
   if (__builtin_strcat (dst, "") != dst || strcmp (dst, s1))
     abort();