aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2003-04-13 23:46:11 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2003-04-13 23:46:11 +0000
commit9cb65f923c1dbf2012a31e90a08e8876ca01dc32 (patch)
tree6fe1e0659b55250f63aa29ca0be6aeef5e0dfe2a
parentf4f4610e036e239fb770127439d276439a621e3f (diff)
downloadgcc-9cb65f923c1dbf2012a31e90a08e8876ca01dc32.zip
gcc-9cb65f923c1dbf2012a31e90a08e8876ca01dc32.tar.gz
gcc-9cb65f923c1dbf2012a31e90a08e8876ca01dc32.tar.bz2
builtins.c (expand_builtin_memcpy): Add `endp' argument, use it.
gcc: * builtins.c (expand_builtin_memcpy): Add `endp' argument, use it. (expand_builtin_stpcpy): New. (expand_builtin): Add BUILT_IN_MEMPCPY & BUILT_IN_STPCPY. * builtins.def: Add mempcpy & stpcpy support. * doc/extend.texi (mempcpy, stpcpy): Document new builtins. testsuite: * gcc.c-torture/execute/string-opt-18.c: New test. From-SVN: r65551
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/builtins.c78
-rw-r--r--gcc/builtins.def8
-rw-r--r--gcc/doc/extend.texi6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-18.c91
6 files changed, 184 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c6a5117..25c09aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2003-04-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * builtins.c (expand_builtin_memcpy): Add `endp' argument, use it.
+ (expand_builtin_stpcpy): New.
+ (expand_builtin): Add BUILT_IN_MEMPCPY & BUILT_IN_STPCPY.
+ * builtins.def: Add mempcpy & stpcpy support.
+ * doc/extend.texi (mempcpy, stpcpy): Document new builtins.
+
2003-04-13 Nick Clifton <nickc@redhat.com>
* config/rs6000/rs6000.c: Replace occurrences of "GNU CC" with
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 667de5f..51e8976 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -125,9 +125,11 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx,
static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
- enum machine_mode));
+ enum machine_mode, int));
static rtx expand_builtin_strcpy PARAMS ((tree, rtx,
enum machine_mode));
+static rtx expand_builtin_stpcpy PARAMS ((tree, rtx,
+ enum machine_mode));
static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
@@ -2252,15 +2254,18 @@ builtin_memcpy_read_str (data, offset, mode)
}
/* Expand a call to the memcpy 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). */
-
+ 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). If ENDP is 0 return the
+ destination pointer, if ENDP is 1 return the end pointer ala
+ mempcpy, and if ENDP is 2 return the end pointer minus one ala
+ stpcpy. */
static rtx
-expand_builtin_memcpy (arglist, target, mode)
+expand_builtin_memcpy (arglist, target, mode, endp)
tree arglist;
rtx target;
enum machine_mode mode;
+ int endp;
{
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -2316,7 +2321,15 @@ expand_builtin_memcpy (arglist, target, mode)
if (GET_MODE (dest_mem) != ptr_mode)
dest_mem = convert_memory_address (ptr_mode, dest_mem);
#endif
- return dest_mem;
+ if (endp)
+ {
+ rtx result = gen_rtx_PLUS (GET_MODE(dest_mem), dest_mem, len_rtx);
+ if (endp == 2)
+ result = simplify_gen_binary (MINUS, GET_MODE(result), result, const1_rtx);
+ return result;
+ }
+ else
+ return dest_mem;
}
src_mem = get_memory_rtx (src);
@@ -2335,7 +2348,15 @@ expand_builtin_memcpy (arglist, target, mode)
#endif
}
- return dest_addr;
+ if (endp)
+ {
+ rtx result = gen_rtx_PLUS (GET_MODE (dest_addr), dest_addr, len_rtx);
+ if (endp == 2)
+ result = simplify_gen_binary (MINUS, GET_MODE(result), result, const1_rtx);
+ return result;
+ }
+ else
+ return dest_addr;
}
}
@@ -2370,6 +2391,31 @@ expand_builtin_strcpy (exp, target, mode)
target, mode, EXPAND_NORMAL);
}
+/* Expand a call to the stpcpy 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_stpcpy (arglist, target, mode)
+ tree arglist;
+ rtx target;
+ enum machine_mode mode;
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
+ if (len == 0)
+ return 0;
+
+ len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
+ chainon (arglist, build_tree_list (NULL_TREE, len));
+ return expand_builtin_memcpy (arglist, target, mode, /*endp=*/2);
+ }
+}
+
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
bytes from constant string DATA + OFFSET and return it as target
constant. */
@@ -4036,10 +4082,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_MEMSET:
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMCMP:
+ case BUILT_IN_MEMPCPY:
case BUILT_IN_BCMP:
case BUILT_IN_BZERO:
case BUILT_IN_INDEX:
case BUILT_IN_RINDEX:
+ case BUILT_IN_STPCPY:
case BUILT_IN_STRCHR:
case BUILT_IN_STRRCHR:
case BUILT_IN_STRLEN:
@@ -4303,6 +4351,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target;
break;
+ case BUILT_IN_STPCPY:
+ target = expand_builtin_stpcpy (arglist, target, mode);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_STRCAT:
target = expand_builtin_strcat (arglist, target, mode);
if (target)
@@ -4354,7 +4408,13 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break;
case BUILT_IN_MEMCPY:
- target = expand_builtin_memcpy (arglist, target, mode);
+ target = expand_builtin_memcpy (arglist, target, mode, /*endp=*/0);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_MEMPCPY:
+ target = expand_builtin_memcpy (arglist, target, mode, /*endp=*/1);
if (target)
return target;
break;
diff --git a/gcc/builtins.def b/gcc/builtins.def
index f0df8bb..1d456e9 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -388,6 +388,10 @@ DEF_LIB_BUILTIN(BUILT_IN_MEMSET,
"__builtin_memset",
BT_FN_PTR_PTR_INT_SIZE,
ATTR_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN(BUILT_IN_MEMPCPY,
+ "__builtin_mempcpy",
+ BT_FN_PTR_PTR_CONST_PTR_SIZE,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCAT,
"__builtin_strcat",
@@ -397,6 +401,10 @@ DEF_LIB_BUILTIN(BUILT_IN_STRNCAT,
"__builtin_strncat",
BT_FN_STRING_STRING_CONST_STRING_SIZE,
ATTR_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN(BUILT_IN_STPCPY,
+ "__builtin_stpcpy",
+ BT_FN_STRING_STRING_CONST_STRING,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCPY,
"__builtin_strcpy",
BT_FN_STRING_STRING_CONST_STRING,
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ad2a02f..b61a718 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4598,6 +4598,7 @@ v4si f (v4si a, v4si b, v4si c)
@findex logl
@findex memcmp
@findex memcpy
+@findex mempcpy
@findex memset
@findex nearbyint
@findex nearbyintf
@@ -4623,6 +4624,7 @@ v4si f (v4si a, v4si b, v4si c)
@findex sqrtf
@findex sqrtl
@findex sscanf
+@findex stpcpy
@findex strcat
@findex strchr
@findex strcmp
@@ -4667,8 +4669,8 @@ be emitted.
Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or
@option{-std=c99}), the functions @code{alloca}, @code{bcmp},
@code{bzero}, @code{_exit}, @code{ffs}, @code{fprintf_unlocked},
-@code{fputs_unlocked}, @code{index}, @code{printf_unlocked},
-and @code{rindex} may be handled as built-in functions.
+@code{fputs_unlocked}, @code{index}, @code{mempcpy}, @code{printf_unlocked},
+@code{rindex}, and @code{stpcpy} may be handled as built-in functions.
All these functions have corresponding versions
prefixed with @code{__builtin_}, which may be used even in strict C89
mode.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b7366d6..3b8b5c5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-04-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.c-torture/execute/string-opt-18.c: New test.
+
2003-04-13 Mark Mitchell <mark@codesourcery.com>
PR c++/10300
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
new file mode 100644
index 0000000..cc74489
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
@@ -0,0 +1,91 @@
+#include <stdio.h>
+/* Copyright (C) 2000 Free Software Foundation.
+
+ Ensure builtin mempcpy and stpcpy perform correctly.
+
+ Written by Kaveh Ghazi, 4/11/2003. */
+
+extern void abort (void);
+extern char *strcpy (char *, const char *);
+extern char *stpcpy (char *, const char *);
+/*typedef __SIZE_TYPE__ size_t;*/
+extern size_t strlen(const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *mempcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+const char s1[] = "123";
+char p[32] = "";
+
+int main()
+{
+ int i;
+ const char *s;
+
+ if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+ abort ();
+ if (stpcpy (p + 16, "vwxyz" + 1) != p + 16 + 4 || memcmp (p + 16, "wxyz", 5))
+ abort ();
+ if (stpcpy (p + 1, "") != p + 1 + 0 || memcmp (p, "a\0cde", 6))
+ abort ();
+ if (stpcpy (p + 3, "fghij") != p + 3 + 5 || memcmp (p, "a\0cfghij", 9))
+ abort ();
+ if (mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+ abort ();
+ if (mempcpy (p + 16, "VWX" + 1, 2) != p + 16 + 2 || memcmp (p + 16, "WXyz", 5))
+ abort ();
+ if (mempcpy (p + 1, "", 1) != p + 1 + 1 || memcmp (p, "A\0CDE", 6))
+ abort ();
+ if (mempcpy (p + 3, "FGHI", 4) != p + 3 + 4 || memcmp (p, "A\0CFGHIj", 9))
+ abort ();
+
+ i = 8;
+ memcpy (p + 20, "qrstu", 6);
+ if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2) || i != 9 || memcmp (p + 20, "q23\0u", 6))
+ abort ();
+
+ s = s1; i = 3;
+ memcpy (p + 25, "QRSTU", 6);
+ if (mempcpy (p + 25 + 1, s++, i++) != (p + 25 + 1 + 3) || i != 4 || s != s1 + 1 || memcmp (p + 25, "Q123U", 6))
+ abort ();
+
+ if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8))
+ abort();
+ if (mempcpy (mempcpy (p, "abcdEFG", 4), "efg", 4) != p + 8 || memcmp (p, "abcdefg", 8))
+ abort();
+
+ /* Test at least one instance of the __builtin_ style. We do this
+ to ensure that it works and that the prototype is correct. */
+ if (__builtin_stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
+ abort ();
+ if (__builtin_mempcpy (p, "ABCDE", 6) != p + 6 || memcmp (p, "ABCDE", 6))
+ abort ();
+
+ return 0;
+}
+
+/* When optimizing, all the above cases should be transformed into
+ something else. So any remaining calls to the original function
+ should abort. When not optimizing, we provide fallback funcs for
+ platforms that don't have mempcpy or stpcpy in libc.*/
+__attribute__ ((noinline))
+static char *
+stpcpy (char *d, const char *s)
+{
+#ifdef __OPTIMIZE__
+ abort ();
+#else
+ return strcpy (d, s) + strlen (s);
+#endif
+}
+
+__attribute__ ((noinline))
+static void *
+mempcpy (void *dst, const void *src, size_t sz)
+{
+#ifdef __OPTIMIZE__
+ abort ();
+#else
+ return (char *) memcpy (dst, src, sz) + sz;
+#endif
+}