* builtins.c (expand_builtin_memcpy): Optimize case when the two
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 11 Oct 2003 14:09:44 +0000 (14:09 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 11 Oct 2003 14:09:44 +0000 (14:09 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72335 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/string-opt-18.c [new file with mode: 0644]

index f5bec02..3cfe32a 100644 (file)
@@ -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.
 
index dc20088..1af2a2d 100644 (file)
@@ -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);
 
index b8d1d8a..86c18ce 100644 (file)
@@ -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 (file)
index 0000000..610c4ca
--- /dev/null
@@ -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;
+}
+