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:
Jakub Jelinek 2003-04-28 14:10:35 +02:00 committed by Jakub Jelinek
parent dbe983a84b
commit e31603c46c
6 changed files with 212 additions and 3 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

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