GCC has a way of doing this that starts by calling __builtin_cpu_init then calling __builtin_cpu_is and __builtin_cpu_supports to check features. https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/X86-Built-in-Functions.html
On x86, when using the C++ frontend, GCC supports "function multiversioning", which allows you to write multiple versions of the function, specify the target it should be used on, and let GCC take care of making sure it is called. https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Function-Multiversioning.html