mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-10 18:57:17 +08:00
builtins.def (BUILT_IN_BCOPY, [...]): New.
* builtins.def (BUILT_IN_BCOPY, BUILT_IN_MEMMOVE): New. * builtin-types.def (BT_FN_VOID_CONST_PTR_PTR_SIZE): New. * builtins.c (expand_builtin_memmove, expand_builtin_bcopy): New functions. (expand_builtin): Handle BUILT_IN_BCOPY and BUILT_IN_MEMMOVE. * gcc.c-torture/execute/string-opt-19.c: New test. From-SVN: r66169
This commit is contained in:
parent
dbe983a84b
commit
e31603c46c
@ -1,3 +1,11 @@
|
||||
2003-04-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* builtins.def (BUILT_IN_BCOPY, BUILT_IN_MEMMOVE): New.
|
||||
* builtin-types.def (BT_FN_VOID_CONST_PTR_PTR_SIZE): New.
|
||||
* builtins.c (expand_builtin_memmove, expand_builtin_bcopy): New
|
||||
functions.
|
||||
(expand_builtin): Handle BUILT_IN_BCOPY and BUILT_IN_MEMMOVE.
|
||||
|
||||
2003-04-28 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* config/arm/elf.h (ASM_OUTPUT_ALIGNED_COMMON): Remove definition.
|
||||
|
@ -174,6 +174,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_INT_SIZE,
|
||||
BT_PTR, BT_PTR, BT_INT, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT,
|
||||
BT_VOID, BT_PTR, BT_INT, BT_INT)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_CONST_PTR_PTR_SIZE,
|
||||
BT_VOID, BT_CONST_PTR, BT_PTR, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_STRING, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
|
||||
|
@ -126,6 +126,9 @@ 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_memmove PARAMS ((tree, rtx,
|
||||
enum machine_mode));
|
||||
static rtx expand_builtin_bcopy PARAMS ((tree));
|
||||
static rtx expand_builtin_strcpy PARAMS ((tree, rtx,
|
||||
enum machine_mode));
|
||||
static rtx expand_builtin_stpcpy PARAMS ((tree, rtx,
|
||||
@ -2364,6 +2367,84 @@ expand_builtin_memcpy (arglist, target, mode, endp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand expression EXP, which is a call to the memmove builtin. Return 0
|
||||
if we failed the caller should emit a normal call. */
|
||||
|
||||
static rtx
|
||||
expand_builtin_memmove (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
|
||||
{
|
||||
tree dest = TREE_VALUE (arglist);
|
||||
tree src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
|
||||
unsigned int dest_align
|
||||
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
|
||||
|
||||
/* If DEST is not a pointer type, call the normal function. */
|
||||
if (dest_align == 0)
|
||||
return 0;
|
||||
|
||||
/* If the LEN parameter is zero, return DEST. */
|
||||
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
|
||||
{
|
||||
/* Evaluate and ignore SRC in case it has side-effects. */
|
||||
expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
return expand_expr (dest, target, mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
/* If either SRC is not a pointer type, don't do this
|
||||
operation in-line. */
|
||||
if (src_align == 0)
|
||||
return 0;
|
||||
|
||||
/* If src is a string constant and strings are not writable,
|
||||
we can use normal memcpy. */
|
||||
if (!flag_writable_strings && c_getstr (src))
|
||||
return expand_builtin_memcpy (arglist, target, mode, 0);
|
||||
|
||||
/* Otherwise, call the normal function. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand expression EXP, which is a call to the bcopy builtin. Return 0
|
||||
if we failed the caller should emit a normal call. */
|
||||
|
||||
static rtx
|
||||
expand_builtin_bcopy (arglist)
|
||||
tree arglist;
|
||||
{
|
||||
tree src, dest, size, newarglist;
|
||||
|
||||
if (!validate_arglist (arglist,
|
||||
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
|
||||
return NULL_RTX;
|
||||
|
||||
src = TREE_VALUE (arglist);
|
||||
dest = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
|
||||
/* New argument list transforming bcopy(ptr x, ptr y, int z) to
|
||||
memmove(ptr y, ptr x, size_t z). This is done this way
|
||||
so that if it isn't expanded inline, we fallback to
|
||||
calling bcopy instead of memmove. */
|
||||
|
||||
newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
|
||||
newarglist = tree_cons (NULL_TREE, src, newarglist);
|
||||
newarglist = tree_cons (NULL_TREE, dest, newarglist);
|
||||
|
||||
return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
|
||||
}
|
||||
|
||||
/* Expand expression EXP, which is a call to the strcpy builtin. 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
|
||||
@ -4177,8 +4258,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|
||||
case BUILT_IN_MEMCPY:
|
||||
case BUILT_IN_MEMCMP:
|
||||
case BUILT_IN_MEMPCPY:
|
||||
case BUILT_IN_MEMMOVE:
|
||||
case BUILT_IN_BCMP:
|
||||
case BUILT_IN_BZERO:
|
||||
case BUILT_IN_BCOPY:
|
||||
case BUILT_IN_INDEX:
|
||||
case BUILT_IN_RINDEX:
|
||||
case BUILT_IN_STPCPY:
|
||||
@ -4543,6 +4626,18 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|
||||
return target;
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMMOVE:
|
||||
target = expand_builtin_memmove (arglist, target, mode);
|
||||
if (target)
|
||||
return target;
|
||||
break;
|
||||
|
||||
case BUILT_IN_BCOPY:
|
||||
target = expand_builtin_bcopy (arglist);
|
||||
if (target)
|
||||
return target;
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMSET:
|
||||
target = expand_builtin_memset (exp, target, mode);
|
||||
if (target)
|
||||
|
@ -286,9 +286,9 @@ DEF_C99_BUILTIN(BUILT_IN_CIMAGL,
|
||||
BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE,
|
||||
ATTR_CONST_NOTHROW_LIST)
|
||||
|
||||
/* The system prototypes for `bzero' and `bcmp' functions have many
|
||||
variations, so don't specify parameters to avoid conflicts. The
|
||||
expand_* functions check the argument types anyway. */
|
||||
/* The system prototypes for `bzero', 'bcopy' and `bcmp' functions
|
||||
have many variations, so don't specify parameters to avoid conflicts.
|
||||
The expand_* functions check the argument types anyway. */
|
||||
DEF_BUILTIN (BUILT_IN_BZERO,
|
||||
"__builtin_bzero",
|
||||
BUILT_IN_NORMAL,
|
||||
@ -296,6 +296,13 @@ DEF_BUILTIN (BUILT_IN_BZERO,
|
||||
BT_FN_VOID_VAR,
|
||||
true, true, true,
|
||||
ATTR_NOTHROW_LIST, false)
|
||||
DEF_BUILTIN (BUILT_IN_BCOPY,
|
||||
"__builtin_bcopy",
|
||||
BUILT_IN_NORMAL,
|
||||
BT_FN_VOID_CONST_PTR_PTR_SIZE,
|
||||
BT_FN_VOID_VAR,
|
||||
true, true, true,
|
||||
ATTR_NOTHROW_LIST, false)
|
||||
DEF_BUILTIN (BUILT_IN_BCMP,
|
||||
"__builtin_bcmp",
|
||||
BUILT_IN_NORMAL,
|
||||
@ -380,6 +387,10 @@ DEF_LIB_BUILTIN(BUILT_IN_MEMCPY,
|
||||
"__builtin_memcpy",
|
||||
BT_FN_PTR_PTR_CONST_PTR_SIZE,
|
||||
ATTR_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN(BUILT_IN_MEMMOVE,
|
||||
"__builtin_memmove",
|
||||
BT_FN_PTR_PTR_CONST_PTR_SIZE,
|
||||
ATTR_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN(BUILT_IN_MEMCMP,
|
||||
"__builtin_memcmp",
|
||||
BT_FN_INT_CONST_PTR_CONST_PTR_SIZE,
|
||||
|
@ -1,3 +1,7 @@
|
||||
2003-04-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/string-opt-19.c: New test.
|
||||
|
||||
2003-04-27 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/10506
|
||||
|
89
gcc/testsuite/gcc.c-torture/execute/string-opt-19.c
Normal file
89
gcc/testsuite/gcc.c-torture/execute/string-opt-19.c
Normal file
@ -0,0 +1,89 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Ensure builtin memmove and bcopy perform correctly.
|
||||
|
||||
Written by Jakub Jelinek, 4/26/2003. */
|
||||
|
||||
extern void abort (void);
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
extern void *memmove (void *, const void *, size_t);
|
||||
extern void bcopy (const void *, 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 (memmove (p, "abcde", 6) != p || memcmp (p, "abcde", 6))
|
||||
abort ();
|
||||
s = s1;
|
||||
if (memmove (p + 2, ++s, 0) != p + 2 || memcmp (p, "abcde", 6) || s != s1 + 1)
|
||||
abort ();
|
||||
if (__builtin_memmove (p + 3, "", 1) != p + 3 || memcmp (p, "abc\0e", 6))
|
||||
abort ();
|
||||
bcopy ("fghijk", p + 2, 4);
|
||||
if (memcmp (p, "abfghi", 7))
|
||||
abort ();
|
||||
s = s1 + 1;
|
||||
bcopy (s++, p + 1, 0);
|
||||
if (memcmp (p, "abfghi", 7) || s != s1 + 2)
|
||||
abort ();
|
||||
__builtin_bcopy ("ABCDE", p + 4, 1);
|
||||
if (memcmp (p, "abfgAi", 7))
|
||||
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, provide memmove/bcopy implementation
|
||||
just in case target lacks these in its libc. */
|
||||
__attribute__ ((noinline))
|
||||
static void *
|
||||
memmove (void *d, const void *s, size_t n)
|
||||
{
|
||||
#ifdef __OPTIMIZE__
|
||||
abort ();
|
||||
#else
|
||||
char *dst = (char *) d;
|
||||
const char *src = (const char *) s;
|
||||
if (src < dst)
|
||||
{
|
||||
dst += n;
|
||||
src += n;
|
||||
while (n--)
|
||||
*--dst = *--src;
|
||||
}
|
||||
else
|
||||
while (n--)
|
||||
*dst++ = *src++;
|
||||
return (char *) d;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__ ((noinline))
|
||||
static void
|
||||
bcopy (const void *s, void *d, size_t n)
|
||||
{
|
||||
#ifdef __OPTIMIZE__
|
||||
abort ();
|
||||
#else
|
||||
char *dst = (char *) d;
|
||||
const char *src = (const char *) s;
|
||||
if (src < dst)
|
||||
{
|
||||
dst += n;
|
||||
src += n;
|
||||
while (n--)
|
||||
*--dst = *--src;
|
||||
}
|
||||
else
|
||||
while (n--)
|
||||
*dst++ = *src++;
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue
Block a user