From e31603c46cf2d4fc62993fe9f626d8004c2d903a Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 28 Apr 2003 14:10:35 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 8 ++ gcc/builtin-types.def | 2 + gcc/builtins.c | 95 ++++++++++++++++++++++ gcc/builtins.def | 17 +++- gcc/testsuite/ChangeLog | 4 + .../gcc.c-torture/execute/string-opt-19.c | 89 ++++++++++++++++++++ 6 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/string-opt-19.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4768d57..f7a7d93 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2003-04-28 Jakub Jelinek + + * 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 * config/arm/elf.h (ASM_OUTPUT_ALIGNED_COMMON): Remove definition. diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index a9db4a3..d9b98f1 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -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, diff --git a/gcc/builtins.c b/gcc/builtins.c index b24ecd3..94db6a3 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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) diff --git a/gcc/builtins.def b/gcc/builtins.def index f0d118b..1806434 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 210cff6..ee090a7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-04-28 Jakub Jelinek + + * gcc.c-torture/execute/string-opt-19.c: New test. + 2003-04-27 Mark Mitchell PR c++/10506 diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-19.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-19.c new file mode 100644 index 0000000..92b84c6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-19.c @@ -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 +} -- 2.7.4