about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-09-27 16:56:33 -0400
committerRich Felker <dalias@aerifal.cx>2012-09-27 16:56:33 -0400
commit3f9ff1514e49b06c20a61af9ae9e52bd53b48d9a (patch)
tree697589451e3d75da05df6e2dd38fcdabf5b4a138 /src
parent507faa63cb12571c14d66eb37dedbe6adbbf40a8 (diff)
downloadmusl-3f9ff1514e49b06c20a61af9ae9e52bd53b48d9a.tar.gz
musl-3f9ff1514e49b06c20a61af9ae9e52bd53b48d9a.tar.xz
musl-3f9ff1514e49b06c20a61af9ae9e52bd53b48d9a.zip
slightly cleaner strlen, also seems to compile to better code
testing with gcc 4.6.3 on x86, -Os, the old version does a duplicate
null byte check after the first loop. this is purely the compiler
being stupid, but the old code was also stupid and unintuitive in how
it expressed the check.
Diffstat (limited to 'src')
-rw-r--r--src/string/strlen.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/src/string/strlen.c b/src/string/strlen.c
index 936fb5cf..d6f8631d 100644
--- a/src/string/strlen.c
+++ b/src/string/strlen.c
@@ -3,7 +3,7 @@
 #include <stdint.h>
 #include <limits.h>
 
-#define ALIGN (sizeof(size_t)-1)
+#define ALIGN (sizeof(size_t))
 #define ONES ((size_t)-1/UCHAR_MAX)
 #define HIGHS (ONES * (UCHAR_MAX/2+1))
 #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
@@ -12,10 +12,8 @@ size_t strlen(const char *s)
 {
 	const char *a = s;
 	const size_t *w;
-	for (; ((uintptr_t)s & ALIGN) && *s; s++);
-	if (*s) {
-		for (w = (const void *)s; !HASZERO(*w); w++);
-		for (s = (const void *)w; *s; s++);
-	}
+	for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
+	for (w = (const void *)s; !HASZERO(*w); w++);
+	for (s = (const void *)w; *s; s++);
 	return s-a;
 }