diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/builtins.c | 62 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-18.c | 14 |
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; } |