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’.