One way is to use the Function Multiversioning feature in GCC, write a test program, and see what version of the function (dependent on your CPU arch
) will it pick.
The foo
function from the program below will create multiple symbols in the binary, and the "best" version will be picked at runtime
$ nm a.out | grep foo
0000000000402236 T _Z3foov
000000000040224c T _Z3foov.arch_x86_64
0000000000402257 T _Z3foov.arch_x86_64_v2
0000000000402262 T _Z3foov.arch_x86_64_v3
000000000040226d T _Z3foov.arch_x86_64_v4
0000000000402290 W _Z3foov.resolver
0000000000402241 T _Z3foov.sse4.2
0000000000402290 i _Z7_Z3foovv
// multiversioning.c
#include <stdio.h>
__attribute__ ((target ("default")))
const char* foo () { return "default"; }
__attribute__ ((target ("sse4.2")))
const char* foo () { return "sse4.2"; }
__attribute__ ((target ("arch=x86-64")))
const char* foo () { return "x86-64-v1"; }
__attribute__ ((target ("arch=x86-64-v2")))
const char* foo () { return "x86-64-v2"; }
__attribute__ ((target ("arch=x86-64-v3")))
const char* foo () { return "x86-64-v3"; }
__attribute__ ((target ("arch=x86-64-v4")))
const char* foo () { return "x86-64-v4"; }
int main ()
{
printf("%s\n", foo());
return 0;
}
On my laptop, this prints
$ g++ multiversioning.c
$ ./a.out
x86-64-v3
Note that the use of g++
is intentional here.
If I used gcc
to compile, it would fail with error: redefinition of ‘foo’
.