summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/builtins.c62
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-18.c14
4 files changed, 86 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a28796eb99f..0b57087b438 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2003-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ * builtins.c (expand_builtin_mempcpy): New function.
+ (expand_builtin_stpcpy): Optimize stpcpy whose return value is
+ ignored into strcpy no matter what arguments it has.
+ (expand_builtin) <case BUILT_IN_MEMPCPY>: Call
+ expand_builtin_mempcpy.
+
2003-05-05 Aldy Hernandez <aldyh@redhat.com>
* testsuite/gcc.dg/20030505.c: New.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index e0a6dea3ce7..dfc17e569fd 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -126,6 +126,8 @@ static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
enum machine_mode, int));
+static rtx expand_builtin_mempcpy PARAMS ((tree, rtx,
+ enum machine_mode));
static rtx expand_builtin_memmove PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_bcopy PARAMS ((tree));
@@ -2345,6 +2347,43 @@ expand_builtin_memcpy (arglist, target, mode, endp)
}
}
+/* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
+ Return 0 if we failed the caller should emit a normal call,
+ otherwise try to get the result in TARGET, if convenient (and in
+ mode MODE if that's convenient). */
+
+static rtx
+expand_builtin_mempcpy (arglist, target, mode)
+ tree arglist;
+ rtx target;
+ enum machine_mode mode;
+{
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ /* If return value is ignored, transform mempcpy into memcpy. */
+ if (target == const0_rtx)
+ {
+ tree fn;
+ rtx ret = expand_builtin_memcpy (arglist, target, mode, /*endp=*/0);
+
+ if (ret)
+ return ret;
+
+ fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ if (!fn)
+ return 0;
+
+ return expand_expr (build_function_call_expr (fn, arglist),
+ target, mode, EXPAND_NORMAL);
+ }
+
+ return expand_builtin_memcpy (arglist, target, mode, /*endp=*/1);
+ }
+}
+
/* Expand expression EXP, which is a call to the memmove builtin. Return 0
if we failed the caller should emit a normal call. */
@@ -2469,7 +2508,26 @@ expand_builtin_stpcpy (arglist, target, mode)
else
{
tree newarglist;
- tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
+ tree len;
+
+ /* If return value is ignored, transform stpcpy into strcpy. */
+ if (target == const0_rtx)
+ {
+ tree fn;
+ rtx ret = expand_builtin_strcpy (arglist, target, mode);
+
+ if (ret)
+ return ret;
+
+ fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ if (!fn)
+ return 0;
+
+ return expand_expr (build_function_call_expr (fn, arglist),
+ target, mode, EXPAND_NORMAL);
+ }
+
+ len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
if (len == 0)
return 0;
@@ -4586,7 +4644,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break;
case BUILT_IN_MEMPCPY:
- target = expand_builtin_memcpy (arglist, target, mode, /*endp=*/1);
+ target = expand_builtin_mempcpy (arglist, target, mode);
if (target)
return target;
break;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 92a767911e1..536043aba92 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/string-opt-18.c (main): Add 3 new tests.
+
2003-05-05 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/unused-5.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
index 0ba2be6e628..dfa5c169e2d 100644
--- a/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
+++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
@@ -15,6 +15,9 @@ extern int memcmp (const void *, const void *, size_t);
const char s1[] = "123";
char p[32] = "";
+char *s2 = "defg";
+char *s3 = "FGH";
+size_t l1 = 1;
int main()
{
@@ -60,6 +63,17 @@ int main()
if (__builtin_mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
abort ();
+ /* If the result of stpcpy/mempcpy is ignored, gcc should use
+ strcpy/memcpy. */
+ stpcpy (p + 3, s2);
+ if (memcmp (p, "ABCdefg", 8))
+ abort ();
+ mempcpy (p + 5, s3, 1);
+ if (memcmp (p, "ABCdeFg", 8))
+ abort ();
+ mempcpy (p + 6, s3 + 1, l1);
+ if (memcmp (p, "ABCdeFG", 8))
+ abort ();
return 0;
}