x86: Add support for building str{c|p}{brk|spn} with explicit ISA level

The changes for these functions are different than the others because
the best implementation (sse4_2) requires the generic
implementation as a fallback to be built as well.

Changes are:

1. Add non-multiarch functions for str{c|p}{brk|spn}.c to statically
   select the best implementation based on the configured ISA build
   level.

2. Add stubs for str{c|p}{brk|spn}-generic and varshift.c to in the
   sysdeps/x86_64 directory so that the the sse4 implementation will
   have all of its dependencies for the non-multiarch / rtld build
   when ISA level >= 2.

3. Add new multiarch/rtld-strcspn.c that just include the
   non-multiarch strcspn.c which will in turn select the best
   implementation based on the compiled ISA level.

4. Refactor the ifunc selector and ifunc implementation list to use
   the ISA level aware wrapper macros that allow functions below the
   compiled ISA level (with a guranteed replacement) to be skipped.

Tested with and without multiarch on x86_64 for ISA levels:
{generic, x86-64-v2, x86-64-v3, x86-64-v4}

And m32 with and without multiarch.
This commit is contained in:
Noah Goldstein 2022-07-03 21:28:07 -07:00
parent baeae86fb8
commit c69f960b01
18 changed files with 247 additions and 13 deletions

View File

@ -14,7 +14,14 @@ sysdep_noprof += _mcount
endif
ifeq ($(subdir),string)
sysdep_routines += strcasecmp_l-nonascii strncase_l-nonascii
sysdep_routines += \
strcasecmp_l-nonascii \
strcspn-generic \
strncase_l-nonascii \
strpbrk-generic \
strspn-generic \
varshift \
# sysdep_routines
gen-as-const-headers += locale-defines.sym
tests += \
tst-rsi-strlen

View File

@ -533,6 +533,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
/* Support sysdeps/x86_64/multiarch/strcspn.c. */
IFUNC_IMPL (i, name, strcspn,
/* All implementations of strcspn are built at all ISA
levels. */
IFUNC_IMPL_ADD (array, i, strcspn, CPU_FEATURE_USABLE (SSE4_2),
__strcspn_sse42)
IFUNC_IMPL_ADD (array, i, strcspn, 1, __strcspn_generic))
@ -609,6 +611,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
/* Support sysdeps/x86_64/multiarch/strpbrk.c. */
IFUNC_IMPL (i, name, strpbrk,
/* All implementations of strpbrk are built at all ISA
levels. */
IFUNC_IMPL_ADD (array, i, strpbrk, CPU_FEATURE_USABLE (SSE4_2),
__strpbrk_sse42)
IFUNC_IMPL_ADD (array, i, strpbrk, 1, __strpbrk_generic))
@ -616,6 +620,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
/* Support sysdeps/x86_64/multiarch/strspn.c. */
IFUNC_IMPL (i, name, strspn,
/* All implementations of strspn are built at all ISA
levels. */
IFUNC_IMPL_ADD (array, i, strspn, CPU_FEATURE_USABLE (SSE4_2),
__strspn_sse42)
IFUNC_IMPL_ADD (array, i, strspn, 1, __strspn_generic))

View File

@ -33,7 +33,7 @@ IFUNC_SELECTOR (void)
implementation its best to keep it regardless. If an optimized
fallback is added add a X86_ISA_CPU_FEATURE_ARCH_P (cpu_features,
Slow_SSE4_2) check. */
if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2))
if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, SSE4_2))
return OPTIMIZE (sse42);
return OPTIMIZE (generic);

View File

@ -0,0 +1,18 @@
/* Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "../strcspn.c"

View File

@ -16,8 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if IS_IN (libc)
/* We always need to build this implementation as strcspn-sse4 needs
to be able to fallback to it. */
#include <isa-level.h>
#if IS_IN (libc) || MINIMUM_X86_ISA_LEVEL >= 2
# include <sysdep.h>
# define STRCSPN __strcspn_generic

View File

@ -16,7 +16,8 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if IS_IN (libc)
#include <isa-level.h>
#if IS_IN (libc) || MINIMUM_X86_ISA_LEVEL >= 2
# include <nmmintrin.h>
# include <string.h>
@ -54,9 +55,11 @@
when either CFlag or ZFlag is 1. If CFlag == 1, ECX has the offset
X for case 1. */
# ifndef STRCSPN
# define STRCSPN __strcspn_sse42
# endif
# ifndef STRCSPN_GENERIC
# define STRCSPN_GENERIC __strcspn_generic
# define STRCSPN_SSE42 __strcspn_sse42
# endif
# ifdef USE_AS_STRPBRK
@ -80,7 +83,7 @@ char *
size_t
# endif
__attribute__ ((section (".text.sse4.2")))
STRCSPN_SSE42 (const char *s, const char *a)
STRCSPN (const char *s, const char *a)
{
if (*a == 0)
RETURN (NULL, strlen (s));

View File

@ -16,8 +16,11 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if IS_IN (libc)
/* We always need to build this implementation as strpbrk-sse4 needs
to be able to fallback to it. */
#include <isa-level.h>
#if IS_IN (libc) || MINIMUM_X86_ISA_LEVEL >= 2
# include <sysdep.h>
# define STRPBRK __strpbrk_generic

View File

@ -16,7 +16,11 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef STRPBRK
# define STRPBRK __strpbrk_sse42
#endif
#define USE_AS_STRPBRK
#define STRCSPN_GENERIC __strpbrk_generic
#define STRCSPN_SSE42 __strpbrk_sse42
#define STRCSPN STRPBRK
#include "strcspn-sse4.c"

View File

@ -16,13 +16,16 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if IS_IN (libc)
/* We always need to build this implementation as strspn-sse4 needs to
be able to fallback to it. */
#include <isa-level.h>
#if IS_IN (libc) || MINIMUM_X86_ISA_LEVEL >= 2
# include <sysdep.h>
# define STRSPN __strspn_generic
# undef libc_hidden_builtin_def
# define libc_hidden_builtin_def(STRSPN)
#endif
#include <string/strspn.c>

View File

@ -53,10 +53,13 @@
extern size_t __strspn_generic (const char *, const char *) attribute_hidden;
#ifndef STRSPN
# define STRSPN __strspn_sse42
#endif
size_t
__attribute__ ((section (".text.sse4.2")))
__strspn_sse42 (const char *s, const char *a)
STRSPN (const char *s, const char *a)
{
if (*a == 0)
return 0;

View File

@ -16,7 +16,9 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if IS_IN (libc)
#include <isa-level.h>
#if IS_IN (libc) || MINIMUM_X86_ISA_LEVEL >= 2
# include <stdint.h>
const int8_t ___m128i_shift_right[31] attribute_hidden

View File

@ -0,0 +1,25 @@
/* Hook for build strcspn-generic for non-multiarch build. Needed for
the ISA level >= 2 because strcspn-sse4 has a dependency on
strcspn-generic.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL >= 2
# include "multiarch/strcspn-generic.c"
#endif

27
sysdeps/x86_64/strcspn.c Normal file
View File

@ -0,0 +1,27 @@
/* strcspn hook for non-multiarch and RTLD build.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL == 1
#include <string/strcspn.c>
#else
#define STRCSPN strcspn
#include "multiarch/strcspn-sse4.c"
libc_hidden_builtin_def (strcspn)
#endif

View File

@ -0,0 +1,25 @@
/* Hook for build strpbrk-generic for non-multiarch build. Needed for
the ISA level >= 2 because strpbrk-sse4 has a dependency on
strpbrk-generic.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL >= 2
# include "multiarch/strpbrk-generic.c"
#endif

27
sysdeps/x86_64/strpbrk.c Normal file
View File

@ -0,0 +1,27 @@
/* strpbrk hook for non-multiarch and RTLD build.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL == 1
#include <string/strpbrk.c>
#else
#define STRPBRK strpbrk
#include "multiarch/strpbrk-sse4.c"
libc_hidden_builtin_def (strpbrk)
#endif

View File

@ -0,0 +1,26 @@
/* Hook for build strspn-generic for non-multiarch build. Needed for
the ISA level >= 2 because strspn-sse4 has a dependency on
strspn-generic.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL >= 2
# include "multiarch/strspn-generic.c"
#endif

27
sysdeps/x86_64/strspn.c Normal file
View File

@ -0,0 +1,27 @@
/* strspn hook for non-multiarch and RTLD build.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL == 1
#include <string/strspn.c>
#else
#define STRSPN strspn
#include "multiarch/strspn-sse4.c"
libc_hidden_builtin_def (strspn)
#endif

26
sysdeps/x86_64/varshift.c Normal file
View File

@ -0,0 +1,26 @@
/* Hook for build varshift for non-multiarch build. Needed for the
ISA level >= 2 because strspn-sse4, strcspn-sse4, and strpbrk-sse4
all have a dependency on varshift.c.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <isa-level.h>
#if MINIMUM_X86_ISA_LEVEL >= 2
# include "multiarch/varshift.c"
#endif