I realize this is a feature with a somewhat niche use-case, but I'd really like to have it in gcc 13, if possible. Any feedback is appreciated.
On 2022-10-17 16:44, J.W. Jagersma wrote: > Recently I tried to set a function's target attribute conditionally > based on template parameters, eg.: > > template<bool enable_sse> > [[gnu::target (enable_sse ? "sse" : "")]] > void func () { /* ... */ } > > I then discovered that this is currently not possible. This small patch > resolves that. > > A possible alternative solution is to do this globally, eg. in > decl_attributes. But doing so would trigger empty-string warnings from > handle_target_attribute, and I don't know how safe it is to remove that. > There likely isn't much use for this with other attributes, anyway. > > 2022-10-17 Jan W. Jagersma <jwjager...@gmail.com> > > gcc/ChangeLog: > * config/i386/i386-options.cc > (ix86_valid_target_attribute_inner_p): Dereference args string > from ADDR_EXPR. > > gcc/testsuite/ChangeLog: > * g++.target/i386/target-attr-conditional.C: New test. > --- > gcc/config/i386/i386-options.cc | 9 ++++ > .../g++.target/i386/target-attr-conditional.C | 53 +++++++++++++++++++ > 2 files changed, 62 insertions(+) > create mode 100644 gcc/testsuite/g++.target/i386/target-attr-conditional.C > > diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc > index acb2291e70f..915f3b0c1f0 100644 > --- a/gcc/config/i386/i386-options.cc > +++ b/gcc/config/i386/i386-options.cc > @@ -1123,6 +1123,15 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree > args, char *p_strings[], > = fndecl == NULL ? UNKNOWN_LOCATION : DECL_SOURCE_LOCATION (fndecl); > const char *attr_name = target_clone_attr ? "target_clone" : "target"; > > + args = tree_strip_nop_conversions (args); > + > + if (TREE_CODE (args) == ADDR_EXPR) > + { > + /* Attribute string is given by a constexpr function or conditional > + expression. Dereference ADDR_EXPR, operand should be a STRING_CST. */ > + args = TREE_OPERAND (args, 0); > + } > + > /* If this is a list, recurse to get the options. */ > if (TREE_CODE (args) == TREE_LIST) > { > diff --git a/gcc/testsuite/g++.target/i386/target-attr-conditional.C > b/gcc/testsuite/g++.target/i386/target-attr-conditional.C > new file mode 100644 > index 00000000000..2d418ed90bf > --- /dev/null > +++ b/gcc/testsuite/g++.target/i386/target-attr-conditional.C > @@ -0,0 +1,53 @@ > +/* { dg-do compile } */ > +/* { dg-options "-Wno-psabi -m32 -march=i386 -std=c++20" } */ > + > +#pragma GCC push_options > +#pragma GCC target("sse") > + > +typedef int __m64 __attribute__ ((__vector_size__ (8), __may_alias__)); > +typedef short __v4hi __attribute__ ((__vector_size__ (8))); > + > +extern __inline int __attribute__((__gnu_inline__, __always_inline__, > __artificial__)) > +_mm_extract_pi16 (__m64 const __A, int const __N) > +{ > + return (unsigned short) __builtin_ia32_vec_ext_v4hi ((__v4hi)__A, __N); > +} > + > +#pragma GCC pop_options > + > +consteval const char* > +target_string (bool enable_sse) > +{ > + return enable_sse ? "sse" : ""; > +} > + > +// Via consteval function > +template<bool enable_sse> > +[[gnu::target (target_string (enable_sse))]] > +int > +extract1 (__m64 const src) > +{ > + if constexpr (enable_sse) > + return _mm_extract_pi16 (src, 0); > + else > + return reinterpret_cast<__v4hi>(src)[1]; > +} > + > +// Via ternary operator > +template<bool enable_sse> > +[[gnu::target (enable_sse ? "sse" : "")]] > +int > +extract2 (__m64 const src) > +{ > + if constexpr (enable_sse) > + return _mm_extract_pi16 (src, 2); > + else > + return reinterpret_cast<__v4hi>(src)[3]; > +} > + > +int > +test (__m64 const src) > +{ > + return extract1<true>(src) + extract1<false>(src) > + + extract2<true>(src) + extract2<false>(src); > +}