[PATCH] S390: Refactor ifunc handling

Stefan Liebler stli@linux.ibm.com
Fri Dec 7 13:09:00 GMT 2018


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.



More information about the Libc-alpha mailing list