diff options
author | Roger Sayle <roger@eyesopen.com> | 2001-12-27 23:34:31 +0000 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-12-27 15:34:31 -0800 |
commit | fe85f179e895686974d32e66d26e321647dd1519 (patch) | |
tree | b184d011cb0a84a8f17030c368d557336ab31867 | |
parent | 30d7b5f4139259ea367158d33c40924826b407fd (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/builtins.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-16.c | 45 |
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 + |