ppv-lite86 uses a combination of #[target_feature(enable...)] wrappers, #[inline(always)] impls, and using the strongest applicable intrinsics in impls, to build functions with different levels of SIMD support including SSE2 [ + SSSE3 [ + SSE4 [ + AES ] ] ]. This way when rustc lowers the code to LLVM it emits the strong intrinsics unconditionally, but they're inlined into functions that either do or do not enable the feature, so from there LLVM lowers them appropriately to the context. Unfortunately, it's not clear that this is allowed by RFC2045:
This [target_feature] attribute extends the feature set of a function beyond its default feature set, which allows the compiler to generate code under the assumption that the function's code will only be reached on hardware that supports its feature set.
The straightforward reading of this is that "the compiler", i.e. the whole shebang frontend-to-backend, "generates code", i.e. outputs a binary, assuming that it will only be reached "on hardware that supports its feature set", i.e. AESNI/SSE4/whathaveyou.
The approach I've been using is only valid given a more nuanced reading: "the compiler", i.e. the rustlang frontend, "generates code", i.e. emits llvm bitcode, assuming that it will only be reached "on hardware that supports its feature set", i.e. on hardware that llvm supports the intrinsic. Practically speaking, this interpretation corresponds to how it actually works and is unlikely to break in the future; LLVM has a soft implementation for aesenc for non-AESNI x86-64 CPUs and will gladly use it. As this seems to be the only practical way to do runtime feature selection in current stable, my hope is that the RFC can be amended with consideration for the existence and usefulness of LLVM's software implementations.
ppv-lite86 uses a combination of
#[target_feature(enable...)]wrappers,#[inline(always)]impls, and using the strongest applicable intrinsics in impls, to build functions with different levels of SIMD support including SSE2 [ + SSSE3 [ + SSE4 [ + AES ] ] ]. This way when rustc lowers the code to LLVM it emits the strong intrinsics unconditionally, but they're inlined into functions that either do or do not enable the feature, so from there LLVM lowers them appropriately to the context. Unfortunately, it's not clear that this is allowed by RFC2045:The straightforward reading of this is that "the compiler", i.e. the whole shebang frontend-to-backend, "generates code", i.e. outputs a binary, assuming that it will only be reached "on hardware that supports its feature set", i.e. AESNI/SSE4/whathaveyou.
The approach I've been using is only valid given a more nuanced reading: "the compiler", i.e. the rustlang frontend, "generates code", i.e. emits llvm bitcode, assuming that it will only be reached "on hardware that supports its feature set", i.e. on hardware that llvm supports the intrinsic. Practically speaking, this interpretation corresponds to how it actually works and is unlikely to break in the future; LLVM has a soft implementation for
aesencfor non-AESNI x86-64 CPUs and will gladly use it. As this seems to be the only practical way to do runtime feature selection in current stable, my hope is that the RFC can be amended with consideration for the existence and usefulness of LLVM's software implementations.