aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <>2003-04-28 11:10:35 +0000
committerjakub <>2003-04-28 11:10:35 +0000
commitae4f466e7040222b152c72538ff38bf6db442721 (patch)
tree724aa570916638d254b686a7dfa1cfb24f55c7f2 /gcc
parent18b841a80c347643d9510b0ae2add72fc9e5b4b2 (diff)
* 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/builtin-types.def2
-rw-r--r--gcc/builtins.c95
-rw-r--r--gcc/builtins.def17
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-19.c89
6 files changed, 212 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4768d57f338..f7a7d93579c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index a9db4a32be5..d9b98f11174 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 b24ecd32b3c..94db6a3ba3f 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 f0d118b0dc3..1806434b1ab 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 210cff6677c..ee090a74e6f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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 00000000000..92b84c6d843
--- /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
+}