This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Optimize strchr (s, 0) to strlen
- From: Wilco Dijkstra <Wilco dot Dijkstra at arm dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: nd <nd at arm dot com>
- Date: Mon, 18 Apr 2016 17:00:45 +0000
- Subject: [PATCH] Optimize strchr (s, 0) to strlen
- Authentication-results: sourceware.org; auth=none
- Nodisclaimer: True
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:23
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?
ChangeLog:
2016-04-18 Wilco Dijkstra <wdijkstr@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..150e707178a3e119d42ef630b384da3eaf7b2182 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..7b483eaeac1aa47278111a92148a16f00b2aaa2d 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..05b85a49dde0a7f5d269174fd4269e40be910dbd 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..b4ef772f0e59252f10a5419ede6837b3c8ca8265 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..da2f465a5b5003fa5dca05f3a6ee00e97b98b5dd 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..a24aea44e8b00ff7b35a907aaa941b4c509642c4 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..aa53d7e75254dfe56c93172afc49f95e5b7901e6 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..e5e276210ba4b7d75867605f1ecf5c06eb970ef5 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" } } */