aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-10-11 14:09:44 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-10-11 14:09:44 +0000
commitea82015ce986194da3d0f20d48accede0174d3e2 (patch)
tree1553338bbed938f4292236cb778a152c34cc82d4
parent2981fafefcc843ed133c328e4f0f0187d661f186 (diff)
downloadgcc-ea82015ce986194da3d0f20d48accede0174d3e2.zip
gcc-ea82015ce986194da3d0f20d48accede0174d3e2.tar.gz
gcc-ea82015ce986194da3d0f20d48accede0174d3e2.tar.bz2
builtins.c (expand_builtin_memcpy): Optimize case when the two pointer arguments are the equal...
* builtins.c (expand_builtin_memcpy): Optimize case when the two pointer arguments are the equal, non-volatile and side-effect free. (expand_builtin_mempcpy): Likewise. (expand_builtin_memmove): Likewise. (expand_builtin_strcpy): Likewise. (expand_builtin_memcmp): Likewise. (expand_builtin_strcmp): Likewise. (expand_builtin_strncmp): Likewise. * gcc.c-torture/execute/string-opt-18.c: New testcase. From-SVN: r72335
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/builtins.c74
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-18.c76
4 files changed, 160 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f5bec02..3cfe32a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
2003-10-11 Roger Sayle <roger@eyesopen.com>
+ * builtins.c (expand_builtin_memcpy): Optimize case when the two
+ pointer arguments are the equal, non-volatile and side-effect free.
+ (expand_builtin_mempcpy): Likewise.
+ (expand_builtin_memmove): Likewise.
+ (expand_builtin_strcpy): Likewise.
+ (expand_builtin_memcmp): Likewise.
+ (expand_builtin_strcmp): Likewise.
+ (expand_builtin_strncmp): Likewise.
+
+2003-10-11 Roger Sayle <roger@eyesopen.com>
+
* combine.c (apply_distributive_law): Enable "distributive" floating
point optimizations with -funsafe-math-optimizations.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index dc20088..1af2a2d 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2561,11 +2561,34 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, len_rtx;
- /* If DEST is not a pointer type or LEN is not constant,
- call the normal function. */
- if (dest_align == 0 || !host_integerp (len, 1))
+ /* If DEST is not a pointer type, call the normal function. */
+ if (dest_align == 0)
return 0;
+ /* If SRC and DEST are the same (and not volatile), do nothing. */
+ if (operand_equal_p (src, dest, 0))
+ {
+ tree expr;
+
+ if (endp == 0)
+ {
+ /* Evaluate and ignore LEN in case it has side-effects. */
+ expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ }
+
+ if (endp == 2)
+ len = fold (build (MINUS_EXPR, TREE_TYPE (len), dest,
+ integer_one_node));
+ len = convert (TREE_TYPE (dest), len);
+ expr = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
+ return expand_expr (expr, target, mode, EXPAND_NORMAL);
+ }
+
+ /* If LEN is not constant, call the normal function. */
+ if (! host_integerp (len, 1))
+ return 0;
+
/* If the LEN parameter is zero, return DEST. */
if (tree_low_cst (len, 1) == 0)
{
@@ -2574,6 +2597,14 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
return expand_expr (dest, target, mode, EXPAND_NORMAL);
}
+ /* If SRC and DEST are the same (and not volatile), return DEST. */
+ if (operand_equal_p (src, dest, 0))
+ {
+ /* Evaluate and ignore LEN in case it has side-effects. */
+ expand_expr (len, 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)
@@ -2651,6 +2682,14 @@ expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
return expand_expr (dest, target, mode, EXPAND_NORMAL);
}
+ /* If SRC and DEST are the same (and not volatile), return DEST. */
+ if (operand_equal_p (src, dest, 0))
+ {
+ /* Evaluate and ignore LEN in case it has side-effects. */
+ expand_expr (len, 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)
@@ -2713,16 +2752,21 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ dst = TREE_VALUE (arglist);
+
+ /* If SRC and DST are equal (and not volatile), return DST. */
+ if (operand_equal_p (src, dst, 0))
+ return expand_expr (dst, target, mode, EXPAND_NORMAL);
+
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
- src = TREE_VALUE (TREE_CHAIN (arglist));
len = c_strlen (src, 1);
if (len == 0 || TREE_SIDE_EFFECTS (len))
return 0;
- dst = TREE_VALUE (arglist);
len = size_binop (PLUS_EXPR, len, ssize_int (1));
arglist = build_tree_list (NULL_TREE, len);
arglist = tree_cons (NULL_TREE, src, arglist);
@@ -3063,6 +3107,14 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
return const0_rtx;
}
+ /* If both arguments are equal (and not volatile), return zero. */
+ if (operand_equal_p (arg1, arg2, 0))
+ {
+ /* Evaluate and ignore len in case it has side-effects. */
+ expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return const0_rtx;
+ }
+
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
@@ -3192,6 +3244,10 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
arg1 = TREE_VALUE (arglist);
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+ /* If both arguments are equal (and not volatile), return zero. */
+ if (operand_equal_p (arg1, arg2, 0))
+ return const0_rtx;
+
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
@@ -3332,6 +3388,14 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
return const0_rtx;
}
+ /* If arg1 and arg2 are equal (and not volatile), return zero. */
+ if (operand_equal_p (arg1, arg2, 0))
+ {
+ /* Evaluate and ignore arg3 in case it has side-effects. */
+ expand_expr (arg3, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return const0_rtx;
+ }
+
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b8d1d8a..86c18ce 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-10-11 Roger Sayle <roger@eyesopen.com>
+
+ * gcc.c-torture/execute/string-opt-18.c: New testcase.
+
2003-10-10 Ian Lance Taylor <ian@wasabisystems.com>
* gcc.c-torture/compile/20031010-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
new file mode 100644
index 0000000..610c4ca
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+ Test equal pointer optimizations don't break anything.
+
+ Written by Roger Sayle, July 14, 2003. */
+
+extern void abort ();
+typedef __SIZE_TYPE__ size_t;
+
+extern void *memcpy(void*, const void*, size_t);
+extern void *mempcpy(void*, const void*, size_t);
+extern void *memmove(void*, const void*, size_t);
+extern char *strcpy(char*, const char*);
+extern int memcmp(const void*, const void*, size_t);
+extern int strcmp(const char*, const char*);
+extern int strncmp(const char*, const char*, size_t);
+
+
+void test1 (void *ptr)
+{
+ if (memcpy(ptr,ptr,8) != ptr)
+ abort ();
+}
+
+void test2 (char *ptr)
+{
+ if (mempcpy(ptr,ptr,8) != ptr+8)
+ abort ();
+}
+
+void test3 (void *ptr)
+{
+ if (memmove(ptr,ptr,8) != ptr)
+ abort ();
+}
+
+void test4 (char *ptr)
+{
+ if (strcpy(ptr,ptr) != ptr)
+ abort ();
+}
+
+void test5 (void *ptr)
+{
+ if (memcmp(ptr,ptr,8) != 0)
+ abort ();
+}
+
+void test6 (const char *ptr)
+{
+ if (strcmp(ptr,ptr) != 0)
+ abort ();
+}
+
+void test7 (const char *ptr)
+{
+ if (strncmp(ptr,ptr,8) != 0)
+ abort ();
+}
+
+
+int main ()
+{
+ char buf[10];
+
+ test1 (buf);
+ test2 (buf);
+ test3 (buf);
+ test4 (buf);
+ test5 (buf);
+ test6 (buf);
+ test7 (buf);
+
+ return 0;
+}
+