On Tue, Oct 24, 2017 at 01:55:58PM -0400, Jason Merrill wrote: > On Tue, Oct 24, 2017 at 11:33 AM, Jakub Jelinek <ja...@redhat.com> wrote: > > On Tue, Oct 24, 2017 at 11:06:51AM -0400, Jason Merrill wrote: > >> On 09/29/2017 08:32 AM, Jakub Jelinek wrote: > >> > + tree b = builtin_decl_explicit (DECL_FUNCTION_CODE (newdecl)); > >> > + if (b) > >> > + duplicate_one_attribute (&DECL_ATTRIBUTES (b), > >> > + DECL_ATTRIBUTES (newdecl), > >> > + "omp declare simd"); > >> > >> It occurs to me that we're likely to want to propagate other attributes to > >> the builtin, too. In the testcase, nothrow and leaf also seem appropriate. > >> Do we want a broader copy_attributes_to_builtin function, even if it only > >> copies this omp attribute for now? > > > > So like this? > > I was thinking that the new function would decide which attributes we > want to copy over, rather than have a "name" parameter.
Like this then? 2017-10-24 Jakub Jelinek <ja...@redhat.com> PR libstdc++/81706 * attribs.c (attribute_value_equal): Use omp_declare_simd_clauses_equal for comparison of OMP_CLAUSEs regardless of flag_openmp{,_simd}. (duplicate_one_attribute, copy_attributes_to_builtin): New functions. * attribs.h (duplicate_one_attribute, copy_attributes_to_builtin): New declarations. * c-decl.c (merge_decls): Copy "omp declare simd" attributes from newdecl to corresponding __builtin_ if any. * decl.c (duplicate_decls): Copy "omp declare simd" attributes from newdecl to corresponding __builtin_ if any. * gcc.target/i386/pr81706.c: New test. * g++.dg/ext/pr81706.C: New test. --- gcc/attribs.c.jj 2017-10-20 16:02:57.013523597 +0200 +++ gcc/attribs.c 2017-10-24 21:22:34.434131849 +0200 @@ -1125,9 +1125,9 @@ attribute_value_equal (const_tree attr1, TREE_VALUE (attr2)) == 1); } - if ((flag_openmp || flag_openmp_simd) - && TREE_VALUE (attr1) && TREE_VALUE (attr2) + if (TREE_VALUE (attr1) && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE + && TREE_VALUE (attr2) && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE) return omp_declare_simd_clauses_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)); @@ -1322,6 +1322,44 @@ merge_decl_attributes (tree olddecl, tre DECL_ATTRIBUTES (newdecl)); } +/* Duplicate all attributes with name NAME in ATTR list to *ATTRS if + they are missing there. */ + +void +duplicate_one_attribute (tree *attrs, tree attr, const char *name) +{ + attr = lookup_attribute (name, attr); + if (!attr) + return; + tree a = lookup_attribute (name, *attrs); + while (attr) + { + tree a2; + for (a2 = a; a2; a2 = lookup_attribute (name, TREE_CHAIN (a2))) + if (attribute_value_equal (attr, a2)) + break; + if (!a2) + { + a2 = copy_node (attr); + TREE_CHAIN (a2) = *attrs; + *attrs = a2; + } + attr = lookup_attribute (name, TREE_CHAIN (attr)); + } +} + +/* Duplicate all attributes from user DECL to the corresponding + builtin that should be propagated. */ + +void +copy_attributes_to_builtin (tree decl) +{ + tree b = builtin_decl_explicit (DECL_FUNCTION_CODE (decl)); + if (b) + duplicate_one_attribute (&DECL_ATTRIBUTES (b), + DECL_ATTRIBUTES (decl), "omp declare simd"); +} + #if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Specialization of merge_decl_attributes for various Windows targets. --- gcc/attribs.h.jj 2017-09-29 19:43:38.879904220 +0200 +++ gcc/attribs.h 2017-10-24 21:22:48.158966401 +0200 @@ -77,6 +77,16 @@ extern tree remove_attribute (const char extern tree merge_attributes (tree, tree); +/* Duplicate all attributes with name NAME in ATTR list to *ATTRS if + they are missing there. */ + +extern void duplicate_one_attribute (tree *, tree, const char *); + +/* Duplicate all attributes from user DECL to the corresponding + builtin that should be propagated. */ + +extern void copy_attributes_to_builtin (tree); + /* Given two Windows decl attributes lists, possibly including dllimport, return a list of their union . */ extern tree merge_dllimport_decl_attributes (tree, tree); --- gcc/c/c-decl.c.jj 2017-10-11 22:37:48.943949030 +0200 +++ gcc/c/c-decl.c 2017-10-24 21:21:34.771851055 +0200 @@ -2569,6 +2569,8 @@ merge_decls (tree newdecl, tree olddecl, set_builtin_decl_declared_p (fncode, true); break; } + + copy_attributes_to_builtin (newdecl); } } else --- gcc/cp/decl.c.jj 2017-10-13 19:02:08.492046895 +0200 +++ gcc/cp/decl.c 2017-10-24 21:21:07.434180598 +0200 @@ -2470,6 +2470,8 @@ next_arg:; break; } } + + copy_attributes_to_builtin (newdecl); } if (new_defines_function) /* If defining a function declared with other language --- gcc/testsuite/gcc.target/i386/pr81706.c.jj 2017-10-24 17:24:17.787844456 +0200 +++ gcc/testsuite/gcc.target/i386/pr81706.c 2017-10-24 17:24:17.787844456 +0200 @@ -0,0 +1,32 @@ +/* PR libstdc++/81706 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -mavx2 -mno-avx512f" } */ +/* { dg-final { scan-assembler "call\[^\n\r]_ZGVdN4v_cos" } } */ +/* { dg-final { scan-assembler "call\[^\n\r]_ZGVdN4v_sin" } } */ + +#ifdef __cplusplus +extern "C" { +#endif +extern double cos (double) __attribute__ ((nothrow, leaf, simd ("notinbranch"))); +extern double sin (double) __attribute__ ((nothrow, leaf, simd ("notinbranch"))); +#ifdef __cplusplus +} +#endif +double p[1024] = { 1.0 }; +double q[1024] = { 1.0 }; + +void +foo (void) +{ + int i; + for (i = 0; i < 1024; i++) + p[i] = cos (q[i]); +} + +void +bar (void) +{ + int i; + for (i = 0; i < 1024; i++) + p[i] = __builtin_sin (q[i]); +} --- gcc/testsuite/g++.dg/ext/pr81706.C.jj 2017-10-24 17:24:17.788844444 +0200 +++ gcc/testsuite/g++.dg/ext/pr81706.C 2017-10-24 17:24:17.787844456 +0200 @@ -0,0 +1,32 @@ +// PR libstdc++/81706 +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "-O3 -mavx2 -mno-avx512f" } +// { dg-final { scan-assembler "call\[^\n\r]_ZGVdN4v_cos" } } +// { dg-final { scan-assembler "call\[^\n\r]_ZGVdN4v_sin" } } + +#ifdef __cplusplus +extern "C" { +#endif +extern double cos (double) __attribute__ ((nothrow, leaf, simd ("notinbranch"))); +extern double sin (double) __attribute__ ((nothrow, leaf, simd ("notinbranch"))); +#ifdef __cplusplus +} +#endif +double p[1024] = { 1.0 }; +double q[1024] = { 1.0 }; + +void +foo (void) +{ + int i; + for (i = 0; i < 1024; i++) + p[i] = cos (q[i]); +} + +void +bar (void) +{ + int i; + for (i = 0; i < 1024; i++) + p[i] = __builtin_sin (q[i]); +} Jakub