On Mon, Aug 07, 2017 at 05:27:42PM +0200, Jakub Jelinek wrote: > > This should really be a separate function. Perhaps "merge_one_attribute"? > > If it is outlined without the first 7 lines, i.e. just the body of if (b), > then it could be duplicate_one_attribute (tree *, tree, const char *); > called like if (b) duplicate_one_attribute (&DECL_ATTRIBUTES (b), s, "omp > declare simd"); > If it is duplicated as whole, it should be called > duplicate_one_attr_to_builtin or something similar. > In any case, it could be in tree.c or attribs.c. > > The primary question is if we want this behavior, or if we should go the > libstdc++ patch routine (and for Jonathan the question is if he knows > why __builtin_XXXf has been used there rather than the ::XXXf).
Here is updated patch that commonizes big part of that into duplicate_one_attribute. Bootstrapped/regtested on x86_64-linux and i686-linux. The question stands, do we want to go this way or using some libstdc++ solution? 2017-09-01 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): New function. * attribs.h (duplicate_one_attribute): New declaration. * 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-09-01 09:25:37.000000000 +0200 +++ gcc/attribs.c 2017-09-01 09:54:28.581146071 +0200 @@ -1116,9 +1116,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)); @@ -1310,6 +1310,31 @@ 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) +{ + 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)); + } +} + #if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Specialization of merge_decl_attributes for various Windows targets. --- gcc/attribs.h.jj 2017-09-01 09:25:37.000000000 +0200 +++ gcc/attribs.h 2017-09-01 09:54:57.366809765 +0200 @@ -77,6 +77,11 @@ 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 *); + /* 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-09-01 09:25:40.707410605 +0200 +++ gcc/c/c-decl.c 2017-09-01 09:49:57.419314085 +0200 @@ -2569,6 +2569,17 @@ merge_decls (tree newdecl, tree olddecl, set_builtin_decl_declared_p (fncode, true); break; } + + tree s = lookup_attribute ("omp declare simd", + DECL_ATTRIBUTES (newdecl)); + if (s) + { + tree b + = builtin_decl_explicit (DECL_FUNCTION_CODE (newdecl)); + if (b) + duplicate_one_attribute (&DECL_ATTRIBUTES (b), s, + "omp declare simd"); + } } } else --- gcc/cp/decl.c.jj 2017-09-01 09:26:24.748892739 +0200 +++ gcc/cp/decl.c 2017-09-01 09:55:52.940160495 +0200 @@ -2470,6 +2470,16 @@ next_arg:; break; } } + + tree s = lookup_attribute ("omp declare simd", + DECL_ATTRIBUTES (newdecl)); + if (s) + { + tree b = builtin_decl_explicit (DECL_FUNCTION_CODE (newdecl)); + if (b) + duplicate_one_attribute (&DECL_ATTRIBUTES (b), s, + "omp declare simd"); + } } if (new_defines_function) /* If defining a function declared with other language --- gcc/testsuite/gcc.target/i386/pr81706.c.jj 2017-09-01 09:40:46.345761553 +0200 +++ gcc/testsuite/gcc.target/i386/pr81706.c 2017-09-01 09:40:46.345761553 +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-09-01 09:40:46.345761553 +0200 +++ gcc/testsuite/g++.dg/ext/pr81706.C 2017-09-01 09:40:46.345761553 +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