Commit 9cb65f92 by Kaveh R. Ghazi Committed by Kaveh Ghazi

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
parent f4f4610e
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> 2003-04-13 Nick Clifton <nickc@redhat.com>
* config/rs6000/rs6000.c: Replace occurrences of "GNU CC" with * config/rs6000/rs6000.c: Replace occurrences of "GNU CC" with
......
...@@ -125,9 +125,11 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx, ...@@ -125,9 +125,11 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx,
static rtx expand_builtin_strcspn PARAMS ((tree, rtx, static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_memcpy PARAMS ((tree, rtx, static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode, int));
static rtx expand_builtin_strcpy PARAMS ((tree, rtx, static rtx expand_builtin_strcpy PARAMS ((tree, rtx,
enum machine_mode)); 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, static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx, static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
...@@ -2252,15 +2254,18 @@ builtin_memcpy_read_str (data, offset, mode) ...@@ -2252,15 +2254,18 @@ builtin_memcpy_read_str (data, offset, mode)
} }
/* Expand a call to the memcpy builtin, with arguments in ARGLIST. /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
Return 0 if we failed, the caller should emit a normal call, otherwise Return 0 if we failed, the caller should emit a normal call,
try to get the result in TARGET, if convenient (and in mode MODE if otherwise try to get the result in TARGET, if convenient (and in
that's convenient). */ 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 static rtx
expand_builtin_memcpy (arglist, target, mode) expand_builtin_memcpy (arglist, target, mode, endp)
tree arglist; tree arglist;
rtx target; rtx target;
enum machine_mode mode; enum machine_mode mode;
int endp;
{ {
if (!validate_arglist (arglist, if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
...@@ -2316,7 +2321,15 @@ expand_builtin_memcpy (arglist, target, mode) ...@@ -2316,7 +2321,15 @@ expand_builtin_memcpy (arglist, target, mode)
if (GET_MODE (dest_mem) != ptr_mode) if (GET_MODE (dest_mem) != ptr_mode)
dest_mem = convert_memory_address (ptr_mode, dest_mem); dest_mem = convert_memory_address (ptr_mode, dest_mem);
#endif #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); src_mem = get_memory_rtx (src);
...@@ -2335,7 +2348,15 @@ expand_builtin_memcpy (arglist, target, mode) ...@@ -2335,7 +2348,15 @@ expand_builtin_memcpy (arglist, target, mode)
#endif #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) ...@@ -2370,6 +2391,31 @@ expand_builtin_strcpy (exp, target, mode)
target, mode, EXPAND_NORMAL); 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) /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
bytes from constant string DATA + OFFSET and return it as target bytes from constant string DATA + OFFSET and return it as target
constant. */ constant. */
...@@ -4036,10 +4082,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -4036,10 +4082,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_MEMSET: case BUILT_IN_MEMSET:
case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY:
case BUILT_IN_MEMCMP: case BUILT_IN_MEMCMP:
case BUILT_IN_MEMPCPY:
case BUILT_IN_BCMP: case BUILT_IN_BCMP:
case BUILT_IN_BZERO: case BUILT_IN_BZERO:
case BUILT_IN_INDEX: case BUILT_IN_INDEX:
case BUILT_IN_RINDEX: case BUILT_IN_RINDEX:
case BUILT_IN_STPCPY:
case BUILT_IN_STRCHR: case BUILT_IN_STRCHR:
case BUILT_IN_STRRCHR: case BUILT_IN_STRRCHR:
case BUILT_IN_STRLEN: case BUILT_IN_STRLEN:
...@@ -4303,6 +4351,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -4303,6 +4351,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target; return target;
break; break;
case BUILT_IN_STPCPY:
target = expand_builtin_stpcpy (arglist, target, mode);
if (target)
return target;
break;
case BUILT_IN_STRCAT: case BUILT_IN_STRCAT:
target = expand_builtin_strcat (arglist, target, mode); target = expand_builtin_strcat (arglist, target, mode);
if (target) if (target)
...@@ -4354,7 +4408,13 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -4354,7 +4408,13 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break; break;
case BUILT_IN_MEMCPY: 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) if (target)
return target; return target;
break; break;
......
...@@ -388,6 +388,10 @@ DEF_LIB_BUILTIN(BUILT_IN_MEMSET, ...@@ -388,6 +388,10 @@ DEF_LIB_BUILTIN(BUILT_IN_MEMSET,
"__builtin_memset", "__builtin_memset",
BT_FN_PTR_PTR_INT_SIZE, BT_FN_PTR_PTR_INT_SIZE,
ATTR_NOTHROW_LIST) 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, DEF_LIB_BUILTIN(BUILT_IN_STRCAT,
"__builtin_strcat", "__builtin_strcat",
...@@ -397,6 +401,10 @@ DEF_LIB_BUILTIN(BUILT_IN_STRNCAT, ...@@ -397,6 +401,10 @@ DEF_LIB_BUILTIN(BUILT_IN_STRNCAT,
"__builtin_strncat", "__builtin_strncat",
BT_FN_STRING_STRING_CONST_STRING_SIZE, BT_FN_STRING_STRING_CONST_STRING_SIZE,
ATTR_NOTHROW_LIST) 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, DEF_LIB_BUILTIN(BUILT_IN_STRCPY,
"__builtin_strcpy", "__builtin_strcpy",
BT_FN_STRING_STRING_CONST_STRING, BT_FN_STRING_STRING_CONST_STRING,
......
...@@ -4598,6 +4598,7 @@ v4si f (v4si a, v4si b, v4si c) ...@@ -4598,6 +4598,7 @@ v4si f (v4si a, v4si b, v4si c)
@findex logl @findex logl
@findex memcmp @findex memcmp
@findex memcpy @findex memcpy
@findex mempcpy
@findex memset @findex memset
@findex nearbyint @findex nearbyint
@findex nearbyintf @findex nearbyintf
...@@ -4623,6 +4624,7 @@ v4si f (v4si a, v4si b, v4si c) ...@@ -4623,6 +4624,7 @@ v4si f (v4si a, v4si b, v4si c)
@findex sqrtf @findex sqrtf
@findex sqrtl @findex sqrtl
@findex sscanf @findex sscanf
@findex stpcpy
@findex strcat @findex strcat
@findex strchr @findex strchr
@findex strcmp @findex strcmp
...@@ -4667,8 +4669,8 @@ be emitted. ...@@ -4667,8 +4669,8 @@ be emitted.
Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or
@option{-std=c99}), the functions @code{alloca}, @code{bcmp}, @option{-std=c99}), the functions @code{alloca}, @code{bcmp},
@code{bzero}, @code{_exit}, @code{ffs}, @code{fprintf_unlocked}, @code{bzero}, @code{_exit}, @code{ffs}, @code{fprintf_unlocked},
@code{fputs_unlocked}, @code{index}, @code{printf_unlocked}, @code{fputs_unlocked}, @code{index}, @code{mempcpy}, @code{printf_unlocked},
and @code{rindex} may be handled as built-in functions. @code{rindex}, and @code{stpcpy} may be handled as built-in functions.
All these functions have corresponding versions All these functions have corresponding versions
prefixed with @code{__builtin_}, which may be used even in strict C89 prefixed with @code{__builtin_}, which may be used even in strict C89
mode. mode.
......
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> 2003-04-13 Mark Mitchell <mark@codesourcery.com>
PR c++/10300 PR c++/10300
......
#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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment