(ICC solves this in a differently annoying way - where all the intrinsics are available, even if they are incompatible with the platform you are on.)
For some light entertainment, think about what happens with static initializers and compiling for different microarch flavours. If your C++ static init function happens to generate an AVX insn, and you've only got SSE2, welcome to SIGILL before main().
See for example stage 1 here: https://gcc.gnu.org/wiki/FunctionSpecificOpt (that document appears dated, but do things still work that way?) Afaik, clang/llvm have similar functionality.
Plus there are some intrinsics that are just macros, (sets, masks, etc), and you don't get them from the preprocessor just by setting the function target.
As an aside, that page really is dated - it is just early proposals afterall - as SSE5 didn't see light of day like that. VPCMOV ended up in AMD's XOP set.
ICC also has its auto as well as manual dispatch options:
auto: https://software.intel.com/en-us/node/682440 manual: https://software.intel.com/en-us/node/684505
I believe this is the area where Intel had their knuckles rapped for only working on "GenuineIntel" processors, and why there are big disclaimers on everything now. I've not tried using these myself as they aren't portable solutions.