aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2001-12-27 23:34:31 +0000
committerRichard Henderson <rth@gcc.gnu.org>2001-12-27 15:34:31 -0800
commitfe85f179e895686974d32e66d26e321647dd1519 (patch)
treeb184d011cb0a84a8f17030c368d557336ab31867
parent30d7b5f4139259ea367158d33c40924826b407fd (diff)
downloadgcc-fe85f179e895686974d32e66d26e321647dd1519.zip
gcc-fe85f179e895686974d32e66d26e321647dd1519.tar.gz
gcc-fe85f179e895686974d32e66d26e321647dd1519.tar.bz2
re PR rtl-optimization/3508 (builtin memcmp() could be optimised)
* 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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/builtins.c14
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-16.c45
4 files changed, 68 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ea4b494..d1327b7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 1df7a0d..d7d83e8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 915a148..24abc58 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..a28cdb0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c
@@ -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
+