aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2003-08-11 03:15:15 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2003-08-11 03:15:15 +0000
commit0235f85590001ba2433f5c4937ff43b66d9575e9 (patch)
tree30025456f87120a80d1959a53a8aa0f7a0e94393 /gcc
parentd9148cf498826028803b6e00a2ca60ac83113cfb (diff)
downloadgcc-0235f85590001ba2433f5c4937ff43b66d9575e9.zip
gcc-0235f85590001ba2433f5c4937ff43b66d9575e9.tar.gz
gcc-0235f85590001ba2433f5c4937ff43b66d9575e9.tar.bz2
builtins.c (expand_builtin_strcat): Optimize constant strings.
* builtins.c (expand_builtin_strcat): Optimize constant strings. testsuite: * gcc.c-torture/execute/string-opt-9.c: Add more strcat cases. From-SVN: r70317
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/builtins.c49
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-9.c39
4 files changed, 87 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 407250f..2c4e5de 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index f9d953c..a7265bf 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9580129..d4bd22d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c
index 889425d..0c21957 100644
--- a/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c
+++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-9.c
@@ -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();