This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] S390: Refactor ifunc handling
On 12/06/2018 09:47 PM, Joseph Myers wrote:
On Thu, 6 Dec 2018, Adhemerval Zanella wrote:
builds with loader selecting the path depending of the hwcap value). I really
would like we we move to deprecate and remove the --with-cpu option, so we
have basically just two variants (enable and disable multiarch).
I'd like to deprecate and remove --with-cpu - but replace it with the
default CPU being automatically determined by how the compiler behaves
(see <https://sourceware.org/ml/libc-alpha/2017-02/msg00154.html>).
The current approach on s390 is not to use submachine but to have
configure checks for each needed CPU which are responsible for setting
macro defines in config.h. Those checks are e.g. using an inline
assembly with a vector instruction to determine if z13 vector
instructions are supported as default. E.g. gcc -march=z13 -msoft-float
would lead to frecord-gcc-switches-output:
.ascii "-march=z13"
...
.ascii "-msoft-float"
But the assembler fails with "Error: Unrecognized opcode
<vector-instruction>" as the vector instructions are implicitly disabled
by -msoft-float.
Avoiding building in lots of function variants for CPUs older than the
minimum supported still seems appropriate to me. What I don't know is if
there is a good way to design things with the following properties:
* IFUNC function variants are handled the same way for all architectures.
I assume all are using the __ifunc macros from include/libc-symbols.h.
Some archs are using an ifunc'ed __GI_* symbol which jumps over
plt-stub. Some archs like s390-32 can't do that as the plt-stub needs a
setuped GOT pointer in r12. But r12 does not need to be setuped for
usual internal calls. Thus the __GI_* symbol is equivalent to the oldest
available ifunc variant.
Unfortunately defining the __GI_* symbol needs to be done in the compile
unit of the used ifunc variant or the ifunc'ed symbol itself. Therefore
this logic is spread over multiple places instead of one common place
(perhaps within the __ifunc macro).
* A function is automatically not an IFUNC if the minimum supported CPU
implies one particular version would always be used.
* If more than one function might be used based on the minimum supported
CPU, all those that wouldn't ever be used automatically get compiled out.
* A single optimal version (choice based on the compiler's code
generation) is automatically selected in the non-multiarch case.
My patches are introducing ifunc-*.h files which decides if ifunc is
needed for a specific function depending on no-/multiarch, libc/ldso and
the minimum supported CPU. At the end there is one macro
HAVE_<FUNCTION>_IFUNC with the value 0 or 1.
Afterwards there is a decision which ifunc variants will be available
depending on the minimum supported CPU and if we have ifunc or not.
Older variants than the minimum supported CPU won't be available. At the
end there are multiple macros HAVE_<FUNCTION>_<VARIANT> with value 0 or
1. E.g. if multiarch is not available there is only one macro per
function with 1 and all others are 0.
The ifunc-*.h files are included in several files and those macros are
used to:
-compile or not compile a specific variant
-generating ifunc-resolver expressions which only choose between the
available ifunc variants and generating the ifunc-symbol or just an
alias to the one available variant.
-using the minimum available ifunc variant as the "__GI_* symbol".
-if ifunc is needed, the available ifunc variants are added in
ifunc-impl-list.
As it depends on the used gcc/binutils which parts (variants,
ifunc-resolver, ...) will be needed, either all the stuff needs to be in
one file like sysdeps/arch/function.x or there will be multiple files
specified as sysdep_routines in the Makefile.
As you can't mix a function implementation (in an assembler file) and
the __ifunc macro (c-code) you'll automatically need multiple files.
The multiarch subdirectory cannot be used to distinguish "default"- vs
"enhanced"-ifunc-variants. There is not the one "default"-variant as
this depends on the used gcc/binutils. Thus all files are moved to
sysdeps/s390/ and will always be build. But depending on the needed
parts some resulting object-files can be empty.