On Mon, 2016-04-18 at 17:00 +0000, Wilco Dijkstra wrote: > Optimize strchr (s, 0) to s + strlen (s). strchr (s, 0) appears a > common > idiom for finding the end of a string, however it is not a very > efficient > way of doing so. Strlen is a much simpler operation which is > significantly > faster (eg. on x86 strlen is 50% faster for strings of 8 bytes and > about > twice as fast as strchr on strings of 1KB). > > OK for trunk?
Can you please file this as PR 61056? https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61056 Cheers, Oleg > > ChangeLog: > 2016-04-18 Wilco Dijkstra <wdijk...@arm.com> > > gcc/ > * gcc/builtins.c (fold_builtin_strchr): Optimize strchr (s, 0) > into > strlen. > > testsuite/ > * gcc/testsuite/gcc.dg/strlenopt-20.c: Update test. > * gcc/testsuite/gcc.dg/strlenopt-21.c: Likewise. > * gcc/testsuite/gcc.dg/strlenopt-22.c: Likewise. > * gcc/testsuite/gcc.dg/strlenopt-26.c: Likewise. > * gcc/testsuite/gcc.dg/strlenopt-5.c: Likewise. > * gcc/testsuite/gcc.dg/strlenopt-7.c: Likewise. > * gcc/testsuite/gcc.dg/strlenopt-9.c: Likewise. > > -- > > diff --git a/gcc/builtins.c b/gcc/builtins.c > index > 058ecc39aab205099713e503861103ce6ba5ee6d..150e707178a3e119d42ef630b38 > 4da3eaf7b2182 100644 > --- a/gcc/builtins.c > +++ b/gcc/builtins.c > @@ -8567,20 +8567,20 @@ fold_builtin_strchr (location_t loc, tree s1, > tree s2, tree type) > else > { > const char *p1; > + char c; > > if (TREE_CODE (s2) != INTEGER_CST) > return NULL_TREE; > > + if (target_char_cast (s2, &c)) > + return NULL_TREE; > + > p1 = c_getstr (s1); > if (p1 != NULL) > { > - char c; > const char *r; > tree tem; > > - if (target_char_cast (s2, &c)) > - return NULL_TREE; > - > r = strchr (p1, c); > > if (r == NULL) > @@ -8590,6 +8590,20 @@ fold_builtin_strchr (location_t loc, tree s1, > tree s2, tree type) > tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1); > return fold_convert_loc (loc, type, tem); > } > + else if (c == 0) > + { > + tree fn = builtin_decl_implicit (BUILT_IN_STRLEN); > + if (!fn) > + return NULL_TREE; > + > + s1 = builtin_save_expr (s1); > + > + /* Transform strchr (s1, '\0') to s1 + strlen (s1). */ > + fn = build_call_expr_loc (loc, fn, 1, s1); > + tree tem = fold_build_pointer_plus (s1, fn); > + return fold_convert_loc (loc, type, tem); > + } > + > return NULL_TREE; > } > } > diff --git a/gcc/testsuite/gcc.dg/strlenopt-20.c > b/gcc/testsuite/gcc.dg/strlenopt-20.c > index > a83e845c26d88e5acdcabf142f7b319136663488..7b483eaeac1aa47278111a92148 > a16f00b2aaa2d 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-20.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-20.c > @@ -86,9 +86,9 @@ main () > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ > -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ > diff --git a/gcc/testsuite/gcc.dg/strlenopt-21.c > b/gcc/testsuite/gcc.dg/strlenopt-21.c > index > e22fa9fca9ba14354db2cd5f602283b64bd8dcac..05b85a49dde0a7f5d269174fd42 > 69e40be910dbd 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-21.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-21.c > @@ -57,9 +57,9 @@ main () > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ > -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ > diff --git a/gcc/testsuite/gcc.dg/strlenopt-22.c > b/gcc/testsuite/gcc.dg/strlenopt-22.c > index > aa55f5ebd6a2d4803ee9a7fd60fc538d86f47124..b4ef772f0e59252f10a5419ede6 > 837b3c8ca8265 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-22.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-22.c > @@ -31,9 +31,9 @@ main () > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ > -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ > diff --git a/gcc/testsuite/gcc.dg/strlenopt-26.c > b/gcc/testsuite/gcc.dg/strlenopt-26.c > index > 4bd54bef540806ca90d2b9bcfc33eb531991c967..da2f465a5b5003fa5dca05f3a6e > e00e97b98b5dd 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-26.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-26.c > @@ -21,4 +21,5 @@ main (void) > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > diff --git a/gcc/testsuite/gcc.dg/strlenopt-5.c > b/gcc/testsuite/gcc.dg/strlenopt-5.c > index > 1b006a93045599a75bdb10a39e86ffa59b475c83..a24aea44e8b00ff7b35a907aaa9 > 41b4c509642c4 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-5.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-5.c > @@ -48,9 +48,9 @@ main () > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ > -/* { dg-final { scan-tree-dump-times "strchr \\(" 2 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ > diff --git a/gcc/testsuite/gcc.dg/strlenopt-7.c > b/gcc/testsuite/gcc.dg/strlenopt-7.c > index > 3ae1e2cb3f0d08c8b05107c4e65b67bdb39cf7ab..aa53d7e75254dfe56c93172afc4 > 9f95e5b7901e6 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-7.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-7.c > @@ -40,11 +40,11 @@ main () > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ > -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "\\*r_\[0-9\]* = 0;" 1 "strlen" > } } */ > /* { dg-final { scan-tree-dump-times "return 3;" 1 "optimized" } } > */ > diff --git a/gcc/testsuite/gcc.dg/strlenopt-9.c > b/gcc/testsuite/gcc.dg/strlenopt-9.c > index > b0406b162d48fca375883035043b0c50b9db61a1..e5e276210ba4b7d75867605f1ec > f5c06eb970ef5 100644 > --- a/gcc/testsuite/gcc.dg/strlenopt-9.c > +++ b/gcc/testsuite/gcc.dg/strlenopt-9.c > @@ -98,10 +98,10 @@ main () > return 0; > } > > -/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strlen \\(" 5 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ > -/* { dg-final { scan-tree-dump-times "strchr \\(" 3 "strlen" } } */ > +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ > /* { dg-final { scan-tree-dump-times "return 4;" 1 "optimized" } } > */ >