On 2022-10-13 03:43, Hongtao Liu wrote: > On Thu, Oct 13, 2022 at 5:45 AM J.W. Jagersma via Gcc-help > <gcc-help@xxxxxxxxxxx> wrote: >> >> Consider the following (incomplete) code: >> >> enum simd { mmx = 1, sse = 2 /* , ... */ }; >> >> template<simd flags> >> void simd_func() >> { >> if constexpr (flags & simd::mmx) >> { >> // MMX code here >> } >> else if constexpr (flags & simd::sse) >> { >> // SSE code here >> } >> // etc ... >> } >> >> The idea is to instantiate function templates with optimized SIMD routines >> multiple times, then I can compile all my code with -march=i386, and select the >> best implementation at runtime. > It looks like you want to use function multi-versioning. >> >> However, after already spending a lot of time restructuring my code around this >> idea, I discover that gcc refuses to compile this without having the >> corresponding target options enabled: >> >> error: inlining failed in call to 'always_inline' '__m64 _mm_unpacklo_pi8(__m64, __m64)': target specific option mismatch >> >> That makes no sense to me. I want gcc to emit those SIMD instructions verbatim >> in my code, regardless of what compiler options the user specified. What then >> is the point of feature-test macros (__SSE__, etc)? I don't get it. >> >> Is there any option or attribute I can use to make gcc ignore these target >> option mismatches when inlining? Or any other way to make this work? > maybe you can try > #pragma GCC push_options > #pragma GCC target("sse2") > your codes.. > #pragma GCC pop_options > > https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas Hi, and thanks, While that would work, it would also give the compiler free reign to auto- vectorize any code (__builtin_memcpy, etc) using those target options, right? My goal though is to only generate SIMD code for those targets specified in the template parameter. Another idea I had: template<simd flags> consteval const char* simd_target_options() { // compile-time string wizardry goes here ... return "mmx,sse,sse2"; // just to test } template<simd flags> [[gnu::target(simd_target_options<flags>())]] void simd_func() { /* ... */ } Which also doesn't work: error: attribute 'target' argument is not a string To be expected I suppose, although I know some attributes do take arbitrary expressions. What I'm really looking for is an option to automatically propagate target options from inlined functions, but that just doesn't seem to exist.