From: david.laight.linux@gmail.com
To: Andrew Morton <akpm@linux-foundation.org>,
Andy Shevchenko <andy@kernel.org>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Uros Bizjak <ubizjak@gmail.com>,
linux-kernel@vger.kernel.org, Kees Cook <kees@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>
Cc: David Laight <david.laight.linux@gmail.com>
Subject: [PATCH next] i386: Remove string functions that use 'rep scasb'
Date: Fri, 27 Mar 2026 19:57:47 +0000 [thread overview]
Message-ID: <20260327195747.89556-1-david.laight.linux@gmail.com> (raw)
From: David Laight <david.laight.linux@gmail.com>
The fixed overhead of all the 'rep xxx' instructions is rather more
that might expect.
While 'rep movs' is getting better on more recent CPU, the same is
not true for 'rep scasb'.
On my Zen-5 it has a fixed overhead of 150 clocks and then takes 3
clocks for each byte.
I've not measured any Intel CPU, but the cost might be 'only' 40 + 2n.
Remove the asm versions of strcat() strncat() strlen() memchr()
and memscan(), the generic C versions will be faster.
It is quite likely that all these functions are slower than the generic
code on pretty much all CPU since the 486.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
arch/x86/include/asm/string_32.h | 18 -------
arch/x86/lib/string_32.c | 89 --------------------------------
2 files changed, 107 deletions(-)
diff --git a/arch/x86/include/asm/string_32.h b/arch/x86/include/asm/string_32.h
index e9cce169bb4c..b245db5d7f3c 100644
--- a/arch/x86/include/asm/string_32.h
+++ b/arch/x86/include/asm/string_32.h
@@ -12,12 +12,6 @@ extern char *strcpy(char *dest, const char *src);
#define __HAVE_ARCH_STRNCPY
extern char *strncpy(char *dest, const char *src, size_t count);
-#define __HAVE_ARCH_STRCAT
-extern char *strcat(char *dest, const char *src);
-
-#define __HAVE_ARCH_STRNCAT
-extern char *strncat(char *dest, const char *src, size_t count);
-
#define __HAVE_ARCH_STRCMP
extern int strcmp(const char *cs, const char *ct);
@@ -27,9 +21,6 @@ extern int strncmp(const char *cs, const char *ct, size_t count);
#define __HAVE_ARCH_STRCHR
extern char *strchr(const char *s, int c);
-#define __HAVE_ARCH_STRLEN
-extern size_t strlen(const char *s);
-
static __always_inline void *__memcpy(void *to, const void *from, size_t n)
{
int d0, d1, d2;
@@ -159,9 +150,6 @@ extern int memcmp(const void *, const void *, size_t);
#define memcmp __builtin_memcmp
#endif
-#define __HAVE_ARCH_MEMCHR
-extern void *memchr(const void *cs, int c, size_t count);
-
static inline void *__memset_generic(void *s, char c, size_t count)
{
int d0, d1;
@@ -216,12 +204,6 @@ static inline void *memset32(uint32_t *s, uint32_t v, size_t n)
return s;
}
-/*
- * find the first occurrence of byte 'c', or 1 past the area if none
- */
-#define __HAVE_ARCH_MEMSCAN
-extern void *memscan(void *addr, int c, size_t size);
-
#endif /* __KERNEL__ */
#endif /* _ASM_X86_STRING_32_H */
diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c
index f87ec24fa579..3602e808b584 100644
--- a/arch/x86/lib/string_32.c
+++ b/arch/x86/lib/string_32.c
@@ -49,46 +49,6 @@ char *strncpy(char *dest, const char *src, size_t count)
EXPORT_SYMBOL(strncpy);
#endif
-#ifdef __HAVE_ARCH_STRCAT
-char *strcat(char *dest, const char *src)
-{
- int d0, d1, d2, d3;
- asm volatile("repne scasb\n\t"
- "decl %1\n"
- "1:\tlodsb\n\t"
- "stosb\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b"
- : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
- : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory");
- return dest;
-}
-EXPORT_SYMBOL(strcat);
-#endif
-
-#ifdef __HAVE_ARCH_STRNCAT
-char *strncat(char *dest, const char *src, size_t count)
-{
- int d0, d1, d2, d3;
- asm volatile("repne scasb\n\t"
- "decl %1\n\t"
- "movl %8,%3\n"
- "1:\tdecl %3\n\t"
- "js 2f\n\t"
- "lodsb\n\t"
- "stosb\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b\n"
- "2:\txorl %2,%2\n\t"
- "stosb"
- : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
- : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
- : "memory");
- return dest;
-}
-EXPORT_SYMBOL(strncat);
-#endif
-
#ifdef __HAVE_ARCH_STRCMP
int strcmp(const char *cs, const char *ct)
{
@@ -159,55 +119,6 @@ char *strchr(const char *s, int c)
EXPORT_SYMBOL(strchr);
#endif
-#ifdef __HAVE_ARCH_STRLEN
-size_t strlen(const char *s)
-{
- int d0;
- size_t res;
- asm volatile("repne scasb"
- : "=c" (res), "=&D" (d0)
- : "1" (s), "a" (0), "0" (0xffffffffu)
- : "memory");
- return ~res - 1;
-}
-EXPORT_SYMBOL(strlen);
-#endif
-
-#ifdef __HAVE_ARCH_MEMCHR
-void *memchr(const void *cs, int c, size_t count)
-{
- int d0;
- void *res;
- if (!count)
- return NULL;
- asm volatile("repne scasb\n\t"
- "je 1f\n\t"
- "movl $1,%0\n"
- "1:\tdecl %0"
- : "=D" (res), "=&c" (d0)
- : "a" (c), "0" (cs), "1" (count)
- : "memory");
- return res;
-}
-EXPORT_SYMBOL(memchr);
-#endif
-
-#ifdef __HAVE_ARCH_MEMSCAN
-void *memscan(void *addr, int c, size_t size)
-{
- if (!size)
- return addr;
- asm volatile("repnz scasb\n\t"
- "jnz 1f\n\t"
- "dec %%edi\n"
- "1:"
- : "=D" (addr), "=c" (size)
- : "0" (addr), "1" (size), "a" (c)
- : "memory");
- return addr;
-}
-EXPORT_SYMBOL(memscan);
-#endif
#ifdef __HAVE_ARCH_STRNLEN
size_t strnlen(const char *s, size_t count)
--
2.39.5
next reply other threads:[~2026-03-27 19:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-27 19:57 david.laight.linux [this message]
2026-03-30 16:58 ` [PATCH next] i386: Remove string functions that use 'rep scasb' Dave Hansen
2026-03-30 17:21 ` Andy Shevchenko
2026-03-30 19:20 ` David Laight
2026-03-30 19:47 ` Dave Hansen
2026-03-31 0:27 ` Maciej W. Rozycki
2026-03-31 6:59 ` Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260327195747.89556-1-david.laight.linux@gmail.com \
--to=david.laight.linux@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=andy@kernel.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=ubizjak@gmail.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.