diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ea4b4943d05..d1327b7cd7e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2001-12-27 Roger Sayle + + * builtins.c (expand_builtin_memcmp): Optimize memcmp built-in + when all arguments are known constant. Fixes PR opt/3508. + 2001-12-27 Kazu Hirata * config/h8300/h8300.md (two anonymous patterns): Remove. diff --git a/gcc/builtins.c b/gcc/builtins.c index 1df7a0d0b5a..d7d83e847ba 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 915a148a432..24abc584bc2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-12-27 Roger Sayle + + * gcc.c-torture/execute/string-opt-16.c: New testcase. + 2001-12-27 Richard Henderson * 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 00000000000..a28cdb04271 --- /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 +