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
This commit is contained in:
Kaveh R. Ghazi 2003-04-13 23:46:11 +00:00 committed by Kaveh Ghazi
parent f4f4610e03
commit 9cb65f923c
6 changed files with 184 additions and 11 deletions

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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
}