diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2000-12-03 03:34:03 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2000-12-03 03:34:03 +0000 |
commit | ca8034a0ea78638a2c9cdc54b13274fcb78fdfa4 (patch) | |
tree | a7bb3902b985bd7b9ac739d038afd6ef0f0f25a9 /gcc | |
parent | 6c873122ce204fca1fdefa763661147ae239544d (diff) | |
download | gcc-ca8034a0ea78638a2c9cdc54b13274fcb78fdfa4.zip gcc-ca8034a0ea78638a2c9cdc54b13274fcb78fdfa4.tar.gz gcc-ca8034a0ea78638a2c9cdc54b13274fcb78fdfa4.tar.bz2 |
builtins.c (expand_builtin_strcmp): Use const*_rtx when expanding strcmp at compile-time.
* builtins.c (expand_builtin_strcmp): Use const*_rtx when
expanding strcmp at compile-time. Add another transformation.
(expand_builtin_strncmp): Add more transformations. Call
expand_builtin_memcmp, not expand_builtin_strcmp, under
appropriate conditions if HAVE_cmpstrsi.
testsuite:
gcc.c-torture/execute/string-opt-3.c: Add more strcmp checks.
gcc.c-torture/execute/string-opt-8.c: Add more strncmp checks.
From-SVN: r37963
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/builtins.c | 88 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-3.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/string-opt-8.c | 97 |
5 files changed, 186 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92064a0..f6383eb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2000-12-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * builtins.c (expand_builtin_strcmp): Use const*_rtx when + expanding strcmp at compile-time. Add another transformation. + (expand_builtin_strncmp): Add more transformations. Call + expand_builtin_memcmp, not expand_builtin_strcmp, under + appropriate conditions if HAVE_cmpstrsi. + 2000-12-02 David Edelsohn <edelsohn@gnu.org> * rs6000.md (anddi3_internal[23]): Prefer rldic? over andis diff --git a/gcc/builtins.c b/gcc/builtins.c index 154bd70..0ed4707 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2244,14 +2244,28 @@ expand_builtin_strcmp (exp, target, mode) if (p1 && p2) { - int i = strcmp (p1, p2); - - return expand_expr (i < 0 ? build_int_2 (-1, -1) - : i == 0 ? integer_zero_node - : integer_one_node, - target, mode, EXPAND_NORMAL); + const int i = strcmp (p1, p2); + return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx)); } + /* If either arg is "", return an expression corresponding to + (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ + if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) + { + tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); + tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node); + tree ind1 = + fold (build1 (CONVERT_EXPR, integer_type_node, + build1 (INDIRECT_REF, cst_uchar_node, + build1 (NOP_EXPR, cst_uchar_ptr_node, arg1)))); + tree ind2 = + fold (build1 (CONVERT_EXPR, integer_type_node, + build1 (INDIRECT_REF, cst_uchar_node, + build1 (NOP_EXPR, cst_uchar_ptr_node, arg2)))); + tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2)); + return expand_expr (result, target, mode, EXPAND_NORMAL); + } + #ifdef HAVE_cmpstrsi if (! HAVE_cmpstrsi) return 0; @@ -2360,25 +2374,51 @@ expand_builtin_strncmp (exp, target, mode) return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx)); } - /* If either string parameter is constant and its strlen is strictly - less than the length parameter, call expand_builtin_strcmp(). */ - if ((p1 && compare_tree_int (arg3, strlen (p1)) > 0) - || (p2 && compare_tree_int (arg3, strlen (p2)) > 0)) - { - tree newarglist = - tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2)); - rtx result; + /* If len == 1 or (either string parameter is "" and (len >= 1)), + return (*(u_char*)arg1 - *(u_char*)arg2). */ + if (compare_tree_int (arg3, 1) == 0 + || (compare_tree_int (arg3, 1) > 0 + && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))) + { + tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); + tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node); + tree ind1 = + fold (build1 (CONVERT_EXPR, integer_type_node, + build1 (INDIRECT_REF, cst_uchar_node, + build1 (NOP_EXPR, cst_uchar_ptr_node, arg1)))); + tree ind2 = + fold (build1 (CONVERT_EXPR, integer_type_node, + build1 (INDIRECT_REF, cst_uchar_node, + build1 (NOP_EXPR, cst_uchar_ptr_node, arg2)))); + tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2)); + return expand_expr (result, target, mode, EXPAND_NORMAL); + } - /* Call expand_builtin_strcmp with the modified newarglist. If - the expansion does not occur, do not allow strncmp to expand to - strcmp since strcmp requires that both strings be NULL - terminated whereas strncmp does not. */ - TREE_OPERAND (exp, 1) = newarglist; - result = expand_builtin_strcmp (exp, target, mode); - /* Always restore the original arguments. */ - TREE_OPERAND (exp, 1) = arglist; - return result; - } +#ifdef HAVE_cmpstrsi + /* If the length parameter is constant (checked above) and either + string parameter is constant, call expand_builtin_memcmp() using + a length parameter equal to the lesser of the given length and + the strlen+1 of the constant string. */ + if (HAVE_cmpstrsi && (p1 || p2)) + { + /* Exactly one of the strings is constant at this point, because + if both were then we'd have expanded this at compile-time. */ + tree string_len = p1 ? c_strlen (arg1) : c_strlen (arg2); + + string_len = size_binop (PLUS_EXPR, string_len, ssize_int (1)); + + if (tree_int_cst_lt (string_len, arg3)) + { + /* The strlen+1 is strictly shorter, use it. */ + tree newarglist = build_tree_list (NULL_TREE, string_len); + newarglist = tree_cons (NULL_TREE, arg2, newarglist); + newarglist = tree_cons (NULL_TREE, arg1, newarglist); + return expand_builtin_memcmp (exp, newarglist, target); + } + else + return expand_builtin_memcmp (exp, arglist, target); + } +#endif return 0; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00397daa..073697d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2000-12-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + gcc.c-torture/execute/string-opt-3.c: Add more strcmp checks. + gcc.c-torture/execute/string-opt-8.c: Add more strncmp checks. + 2000-12-02 Geoffrey Keating <geoffk@redhat.com> * gcc.dg/cpp/if-6.c: New testcase. diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-3.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-3.c index a623451..5f27399 100644 --- a/gcc/testsuite/gcc.c-torture/execute/string-opt-3.c +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-3.c @@ -37,6 +37,18 @@ int main() abort (); if (strcmp (10 + foo, "dx") >= 0) abort (); + if (strcmp (bar, "") <= 0) + abort (); + if (strcmp ("", bar) >= 0) + abort (); + if (strcmp (bar+8, "") != 0) + abort (); + if (strcmp ("", bar+8) != 0) + abort (); + if (strcmp (bar+(--x), "") <= 0 || x != 6) + abort (); + if (strcmp ("", bar+(++x)) >= 0 || x != 7) + abort (); if (strrchr (foo, 'x')) abort (); if (strrchr (foo, 'o') != foo + 7) diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c index ca386f0..4c3c0d4 100644 --- a/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c @@ -44,6 +44,103 @@ int main () s2 = s1; s3 = s1+4; if (strncmp (++s2, ++s3, 0) != 0 || s2 != s1+1 || s3 != s1+5) abort(); + s2 = s1; + if (strncmp (++s2, "", 1) <= 0 || s2 != s1+1) + abort(); + if (strncmp ("", ++s2, 1) >= 0 || s2 != s1+2) + abort(); + if (strncmp (++s2, "", 100) <= 0 || s2 != s1+3) + abort(); + if (strncmp ("", ++s2, 100) >= 0 || s2 != s1+4) + abort(); + if (strncmp (++s2+6, "", 100) != 0 || s2 != s1+5) + abort(); + if (strncmp ("", ++s2+5, 100) != 0 || s2 != s1+6) + abort(); + if (strncmp ("ozz", ++s2, 1) != 0 || s2 != s1+7) + abort(); + if (strncmp (++s2, "rzz", 1) != 0 || s2 != s1+8) + abort(); + s2 = s1; s3 = s1+4; + if (strncmp (++s2, ++s3+2, 1) >= 0 || s2 != s1+1 || s3 != s1+5) + abort(); +#if defined(__i386__) + /* These tests work on platforms which support cmpstrsi. */ + s2 = s1; + if (strncmp (++s2, "ello", 3) != 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("ello", ++s2, 3) != 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "ello", 4) != 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("ello", ++s2, 4) != 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "ello", 5) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("ello", ++s2, 5) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "ello", 6) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("ello", ++s2, 6) >= 0 || s2 != s1+1) + abort(); + + s2 = s1; + if (strncmp (++s2, "zllo", 3) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("zllo", ++s2, 3) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "zllo", 4) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("zllo", ++s2, 4) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "zllo", 5) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("zllo", ++s2, 5) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "zllo", 6) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("zllo", ++s2, 6) <= 0 || s2 != s1+1) + abort(); + + s2 = s1; + if (strncmp (++s2, "allo", 3) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("allo", ++s2, 3) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "allo", 4) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("allo", ++s2, 4) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "allo", 5) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("allo", ++s2, 5) >= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp (++s2, "allo", 6) <= 0 || s2 != s1+1) + abort(); + s2 = s1; + if (strncmp ("allo", ++s2, 6) >= 0 || s2 != s1+1) + abort(); +#endif return 0; } |