I really like the new feature levels, so I have created the respective binaries for an application. I now want to dispatch to the correct one, so I thought the easiest thing would be to have a small "arch_detect" program that gives me the feature level as return value: __attribute__ ((target ("default"))) int foo () { // The default version of foo. return 0; } __attribute__ ((target ("arch=x86-64"))) int foo () { return 1; } __attribute__ ((target ("arch=x86-64-v2"))) int foo () { return 2; } __attribute__ ((target ("arch=x86-64-v3"))) int foo () { return 3; } __attribute__ ((target ("arch=x86-64-v4"))) int foo () { return 4; } int main () { return foo(); } This builds fine but always returns 0 -- independent of whether I build the binary without -march or with -march=x86-64-v4. Curiously, if I add the following overload: __attribute__ ((target ("sse4.2"))) int foo () { // The default version of foo. return 7; } it will no longer build without -march=x86-64-v4, complaining that "no dispatcher was found for the versioning attributes". If I add -march=x86-64-v4, it will build without errors but always return 7 and not the feature level. What am I missing?
It doesn't work this way, see the target_clones and ifunc attribute documentation. You could eventually use __builtin_cpu_is or __builtin_cpu_supports.
What do you mean with "It doesn't work this way"? Maybe I wasn't clear in my original post; I am not interested in a dispatching mechanism for the application, I just want to have an mini-application that returns 0, 1, 2, 3 or 4 depending on which feature level is available on the current computer. How is my example different from https://gcc.gnu.org/onlinedocs/gcc/Function-Multiversioning.html (other than using the new feature levels)? Thanks
Ah, this only works with the C++ frontend. I can confirm your observation, it looks like the arch=x86-64-vN handling is incomplete.
I can handle this issue.
Right now, the x86-64* are defined as aliases to k8: {"x86-64", PROCESSOR_K8, CPU_K8, PTA_X86_64_BASELINE, 0, P_NONE}, {"x86-64-v2", PROCESSOR_K8, CPU_GENERIC, PTA_X86_64_V2 | PTA_NO_TUNE, 0, P_NONE}, {"x86-64-v3", PROCESSOR_K8, CPU_GENERIC, PTA_X86_64_V3 | PTA_NO_TUNE, 0, P_NONE}, {"x86-64-v4", PROCESSOR_K8, CPU_GENERIC, PTA_X86_64_V4 | PTA_NO_TUNE, 0, P_NONE}, and it has the corresponding pta info: (gdb) p *arch_info $10 = { name = 0x1f96cdc "x86-64", processor = PROCESSOR_K8, schedule = CPU_K8, flags = { low = 0, high = 137445326852 }, model = 0, priority = P_NONE } thus we end up with: pr101696.c:16:5: error: no dispatcher found for the versioning attributes 16 | int foo () | ^~~ So first step that needs to be done is adding support for the march names in: __builtin_cpu_is. @H.J. Can you please add that?
(In reply to Martin Liška from comment #5) > Right now, the x86-64* are defined as aliases to k8: > > {"x86-64", PROCESSOR_K8, CPU_K8, PTA_X86_64_BASELINE, 0, P_NONE}, > {"x86-64-v2", PROCESSOR_K8, CPU_GENERIC, PTA_X86_64_V2 | PTA_NO_TUNE, > 0, P_NONE}, > {"x86-64-v3", PROCESSOR_K8, CPU_GENERIC, PTA_X86_64_V3 | PTA_NO_TUNE, > 0, P_NONE}, > {"x86-64-v4", PROCESSOR_K8, CPU_GENERIC, PTA_X86_64_V4 | PTA_NO_TUNE, > 0, P_NONE}, > > and it has the corresponding pta info: > > (gdb) p *arch_info > $10 = { > name = 0x1f96cdc "x86-64", > processor = PROCESSOR_K8, > schedule = CPU_K8, > flags = { > low = 0, > high = 137445326852 > }, > model = 0, > priority = P_NONE > } > > thus we end up with: > pr101696.c:16:5: error: no dispatcher found for the versioning attributes > 16 | int foo () > | ^~~ > > So first step that needs to be done is adding support for the march names in: > __builtin_cpu_is. > @H.J. Can you please add that? It is very difficult to add them to __builtin_cpu_is since there are no such processors. However, add them to __builtin_cpu_supports is possible.
> It is very difficult to add them to __builtin_cpu_is since there are no > such processors. I see! > However, add them to __builtin_cpu_supports is possible. Please do so we can then leverage that in the target attribute.
Created attachment 51290 [details] A patch Try this.
I've just sent patch to ML: https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577275.html
The master branch has been updated by Martin Liska <marxin@gcc.gnu.org>: https://gcc.gnu.org/g:8ea292591e42aa4d52b4b7a00b86335bfd2e2e85 commit r12-3494-g8ea292591e42aa4d52b4b7a00b86335bfd2e2e85 Author: Martin Liska <mliska@suse.cz> Date: Thu Aug 12 15:20:43 2021 +0200 i386: support micro-levels in target{,_clone} attrs [PR101696] As mentioned in the PR, we do miss supports target micro-architectures in target and target_clone attribute. While the levels x86-64 x86-64-v2 x86-64-v3 x86-64-v4 are supported values by -march option, they are actually only aliases for k8 CPU. That said, they are more closer to __builtin_cpu_supports function and we decided to implement it there. PR target/101696 gcc/ChangeLog: * common/config/i386/cpuinfo.h (cpu_indicator_init): Add support for x86-64 micro levels for __builtin_cpu_supports. * common/config/i386/i386-cpuinfo.h (enum feature_priority): Add priorities for the micro-arch levels. (enum processor_features): Add new features. * common/config/i386/i386-isas.h: Add micro-arch features. * config/i386/i386-builtins.c (get_builtin_code_for_version): Support the micro-arch levels by callsing __builtin_cpu_supports. * doc/extend.texi: Document that the levels are support by __builtin_cpu_supports. gcc/testsuite/ChangeLog: * g++.target/i386/mv30.C: New test. * gcc.target/i386/mvc16.c: New test. * gcc.target/i386/builtin_target.c (CHECK___builtin_cpu_supports): New. Co-Authored-By: H.J. Lu <hjl.tools@gmail.com>
Implemented on master.