re PR rtl-optimization/3508 (builtin memcmp() could be optimised)
authorRoger Sayle <roger@eyesopen.com>
Thu, 27 Dec 2001 23:34:31 +0000 (23:34 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 27 Dec 2001 23:34:31 +0000 (15:34 -0800)
        * builtins.c (expand_builtin_memcmp): Optimize memcmp built-in
        when all arguments are known constant.  Fixes PR opt/3508.

        * gcc.c-torture/execute/string-opt-16.c: New testcase.

From-SVN: r48335

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

index ea4b4943d05bbce146a5ad3d343710e0e6475c69..d1327b7cd7e82831e5f6e028a29e6600756769fb 100644 (file)
@@ -1,3 +1,8 @@
+2001-12-27  Roger Sayle <roger@eyesopen.com>
+
+       * builtins.c (expand_builtin_memcmp): Optimize memcmp built-in
+       when all arguments are known constant.  Fixes PR opt/3508.
+
 2001-12-27  Kazu Hirata  <kazu@hxi.com>
 
        * config/h8300/h8300.md (two anonymous patterns): Remove.
index 1df7a0d0b5a4bfe88f155f8978488755ed587633..d7d83e847ba116684e365ab80b44c3770767664a 100644 (file)
@@ -2252,6 +2252,7 @@ expand_builtin_memcmp (exp, arglist, target, mode)
      enum machine_mode mode;
 {
   tree arg1, arg2, len;
+  const char *p1, *p2;
 
   if (!validate_arglist (arglist,
                      POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -2271,6 +2272,19 @@ expand_builtin_memcmp (exp, arglist, target, mode)
       return const0_rtx;
     }
 
+  p1 = c_getstr (arg1);
+  p2 = c_getstr (arg2);
+
+  /* If all arguments are constant, and the value of len is not greater
+     than the lengths of arg1 and arg2, evaluate at compile-time.  */
+  if (host_integerp (len, 1) && p1 && p2
+      && compare_tree_int (len, strlen (p1)+1) <= 0
+      && compare_tree_int (len, strlen (p2)+1) <= 0)
+    {
+      const int r = memcmp (p1, p2, tree_low_cst (len, 1));
+      return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
+    }
+
   /* If len parameter is one, return an expression corresponding to
      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
index 915a148a432aed7188b505b4100ce17ac6915d6c..24abc584bc2ff53517563c4fad99329ab28a4eeb 100644 (file)
@@ -1,3 +1,7 @@
+2001-12-27  Roger Sayle <roger@eyesopen.com>
+
+       * gcc.c-torture/execute/string-opt-16.c: New testcase.
+
 2001-12-27  Richard Henderson  <rth@redhat.com>
 
        * gcc.dg/debug-1.c, gcc.dg/debug-2.c: New.
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c
new file mode 100644 (file)
index 0000000..a28cdb0
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (C) 2001  Free Software Foundation.
+
+   Ensure that builtin memcmp operations when all three arguments
+   are constant is optimized and performs correctly.  Taken from
+   PR optimize/3508.
+
+   Written by Roger Sayle, 12/26/2001.  */
+
+extern void abort (void);
+extern void link_error (void);
+
+typedef __SIZE_TYPE__ size_t;
+extern int memcmp (const void *, const void *, size_t);
+
+int
+main (int argc)
+{
+  if (memcmp ("abcd", "efgh", 4) >= 0)
+     link_error ();
+  if (memcmp ("abcd", "abcd", 4) != 0)
+     link_error ();
+  if (memcmp ("efgh", "abcd", 4) <= 0)
+     link_error ();
+  return 0;
+}
+
+#ifdef __OPTIMIZE__
+/* When optimizing, all the above cases should be transformed into
+   something else.  So any remaining calls to the original function
+   should abort.  */
+static int
+memcmp (const void *s1, const void *s2, size_t len)
+{
+  abort ();
+}
+#else
+/* When not optimizing, the above tests may generate references to
+   the function link_error, but should never actually call it.  */
+static void
+link_error ()
+{
+  abort ();
+}
+#endif
+