This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Update newlib to support efficient string operation functions for Thumb.
- From: "Hale Wang" <Hale dot Wang at arm dot com>
- To: <newlib at sourceware dot org>
- Date: Thu, 14 Aug 2014 10:11:19 +0800
- Subject: Update newlib to support efficient string operation functions for Thumb.
- Authentication-results: sourceware.org; auth=none
Hi,
The source files in newlib/libc/machine/arm/ are not so efficient enough to
sopport Thumb.
For Cortex-M0, if we don't define '__OPTIMIZE_SIZE__' or
'PREFER_SIZE_OVER_SPEED' which means size is not preferred, inefficient code
will be used. This may result in pool benchmark performance.
In this case, we can include newlib/libc/string/strcmp.c to improve the
performance. And if size is preferred, the original code will be used.
I have done some tests on Dhrystone benchmark, and the performance of
Cortex-M0 can be improved to 13% with this solution.
The strlen.c can be improved in the similar way.
Bootstrap and no make check regression on X86-64.
Patch also attached for convenience.
Thanks and Best Regards,
Hale Wang
newlib/ChangeLog:
2014-08-14 Hale Wang <hale.wang@arm.com>
* libc/machine/arm/strcmp-stub.c: New file.
* libc/machine/arm/strcmp.S: Replace with wrapper.
* libc/machine/arm/strlen.c: Likewise.
* libc/machine/arm/Makefile.am: Add dependencies.
* libc/machine/arm/Makefile.in: Regenerated.
============================================================================
=
diff --git a/newlib/libc/machine/arm/Makefile.am
b/newlib/libc/machine/arm/Makefile.am
index fb33926..9940eec 100644
--- a/newlib/libc/machine/arm/Makefile.am
+++ b/newlib/libc/machine/arm/Makefile.am
@@ -8,7 +8,7 @@ AM_CCASFLAGS = $(INCLUDES)
noinst_LIBRARIES = lib.a
-lib_a_SOURCES = setjmp.S access.c strlen.c strcmp.S strcpy.c \
+lib_a_SOURCES = setjmp.S access.c strlen.c strcmp-stub.c strcmp.S strcpy.c
\
memcpy.S memcpy-stub.c memchr-stub.c memchr.S \
strlen.c strlen-armv7.S
lib_a_CCASFLAGS=$(AM_CCASFLAGS)
diff --git a/newlib/libc/machine/arm/Makefile.in
b/newlib/libc/machine/arm/Makefile.in
index 1ccfac5..ba088a6 100644
--- a/newlib/libc/machine/arm/Makefile.in
+++ b/newlib/libc/machine/arm/Makefile.in
@@ -70,7 +70,7 @@ ARFLAGS = cru
lib_a_AR = $(AR) $(ARFLAGS)
lib_a_LIBADD =
am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-access.$(OBJEXT) \
- lib_a-strlen.$(OBJEXT) lib_a-strcmp.$(OBJEXT) \
+ lib_a-strlen.$(OBJEXT) lib_a-strcmp.$(OBJEXT)
lib_a-strcmp-stub.$(OBJEXT)\
lib_a-strcpy.$(OBJEXT) lib_a-memcpy.$(OBJEXT) \
lib_a-memcpy-stub.$(OBJEXT) lib_a-memchr-stub.$(OBJEXT) \
lib_a-memchr.$(OBJEXT) lib_a-strlen.$(OBJEXT) \
@@ -200,7 +200,7 @@ AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
AM_CCASFLAGS = $(INCLUDES)
noinst_LIBRARIES = lib.a
-lib_a_SOURCES = setjmp.S access.c strlen.c strcmp.S strcpy.c \
+lib_a_SOURCES = setjmp.S access.c strlen.c strcmp-stub.c strcmp.S strcpy.c
\
memcpy.S memcpy-stub.c memchr-stub.c memchr.S \
strlen.c strlen-armv7.S
@@ -336,6 +336,12 @@ lib_a-memchr-stub.o: memchr-stub.c
lib_a-memchr-stub.obj: memchr-stub.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memchr-stub.obj `if test
-f 'memchr-stub.c'; then $(CYGPATH_W) 'memchr-stub.c'; else $(CYGPATH_W)
'$(srcdir)/memchr-stub.c'; fi`
+lib_a-strcmp-stub.o: strcmp-stub.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcmp-stub.o `test -f
'strcmp-stub.c' || echo '$(srcdir)/'`strcmp-stub.c
+
+lib_a-strcmp-stub.obj: strcmp-stub.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS)
$(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcmp-stub.obj `if test
-f 'strcmp-stub.c'; then $(CYGPATH_W) 'strcmp-stub.c'; else $(CYGPATH_W)
'$(srcdir)/strcmp-stub.c'; fi`
+
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
diff --git a/newlib/libc/machine/arm/strcmp-stub.c
b/newlib/libc/machine/arm/strcmp-stub.c
new file mode 100644
index 0000000..1533205
--- /dev/null
+++ b/newlib/libc/machine/arm/strcmp-stub.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR
IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* The sole purpose of this file is to include the plain strcmp provided
+ in newlib. An optimized version of strcmp is provided in the c
+ file strcmp.c in "../../string/." */
+#if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) \
+ || (__ARM_ARCH == 6 && __ARM_ARCH_PROFILE == 'M')
+
+# if defined (__thumb__) && !defined (__thumb2__)
+/* Thumb1 only variant. If size is preferred, see strcmp.S.
+ If speed is preferred, use "../../string/strcmp.c." */
+
+# if !defined (__OPTIMIZE_SIZE__) && !defined (PREFER_SIZE_OVER_SPEED)
+# include "../../string/strcmp.c"
+# endif
+
+# endif
+#endif
diff --git a/newlib/libc/machine/arm/strcmp.S
b/newlib/libc/machine/arm/strcmp.S
index 1742322..7bcb838 100644
--- a/newlib/libc/machine/arm/strcmp.S
+++ b/newlib/libc/machine/arm/strcmp.S
@@ -64,8 +64,13 @@
|| (__ARM_ARCH == 6 && __ARM_ARCH_PROFILE == 'M')
# if defined (__thumb__) && !defined (__thumb2__)
-/* Thumb1 only variant. */
-# include "strcmp-armv4t.S"
+/* Thumb1 only variant. If size is preferred, use strcmp-armv4t.S.
+ If speed is preferred, see strcmp-stub.c in the same directory. */
+
+# if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED)
+# include "strcmp-armv4t.S"
+# endif
+
# else
# include "strcmp-arm-tiny.S"
# endif
diff --git a/newlib/libc/machine/arm/strlen.c
b/newlib/libc/machine/arm/strlen.c
index b8de229..9945fee 100644
--- a/newlib/libc/machine/arm/strlen.c
+++ b/newlib/libc/machine/arm/strlen.c
@@ -32,8 +32,13 @@
#include <limits.h>
#if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
- (defined (__thumb__) && !defined (__thumb2__))
+ (defined (__thumb__) && !defined (__thumb2__))
+# if !defined (PREFER_SIZE_OVER_SPEED) && !defined (__OPTIMIZE_SIZE__)
+/* Thumb1 only variant.
+ If speed is preferred, use "../../string/strlen.c". */
+# include "../../string/strlen.c"
+# else
size_t
strlen (const char* str)
{
@@ -43,7 +48,7 @@ strlen (const char* str)
asm ("mov %0, #0\n"
"1:\n\t"
"ldrb %1, [%2, %0]\n\t"
- "add %0, %0, #1\n\t"
+ "add %0, %0, #1\n\t"
"cmp %1, #0\n\t"
"bne 1b"
: "=&r" (len), "=&r" (scratch) : "r" (str) : "memory", "cc");
@@ -58,6 +63,7 @@ strlen (const char* str)
return end - str - 1;
#endif
}
+#endif
#else
#if !(defined(_ISA_ARM_7) || defined(__ARM_ARCH_6T2__))