From: Jakub Jelinek Date: Sat, 12 Oct 2019 08:27:36 +0000 (+0200) Subject: c-common.h (c_omp_mark_declare_variant, [...]): Declare. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=20de9568b49e663be848a35ce0bb08f63f14b5b2;p=gcc.git c-common.h (c_omp_mark_declare_variant, [...]): Declare. c-family/ * c-common.h (c_omp_mark_declare_variant, c_omp_context_selector_matches): Declare. * c-omp.c: Include attribs.h, gimplify.h, cgraph.h, symbol-summary.h and hsa-common.h. (c_omp_get_context_selector): Support second argument NULL. (c_omp_mark_declare_variant, c_omp_context_selector_matches): New functions. * c-attribs.c (c_common_attribute_table): Remove "omp declare variant" attribute, add "omp declare variant base" and "omp declare variant variant" attributes. c/ * c-parser.c (c_parser_omp_context_selector): Improve error recovery. For simd properties, put them directly into TREE_VALUE. (c_finish_omp_declare_variant): Call c_omp_mark_declare_variant. If c_omp_context_selector_matches is 0, don't add attribute, otherwise add "omp declare variant base" attribute rather than "omp declare variant". cp/ * parser.c (cp_parser_omp_context_selector): Improve error recovery. For simd properties, put them directly into TREE_VALUE. (cp_finish_omp_declare_variant): Add "omp declare variant base" attribute rather than "omp declare variant". testsuite/ * c-c++-common/gomp/declare-variant-2.c: Adjust for error recovery improvements. Add new tests. * c-c++-common/gomp/declare-variant-4.c: New test. * c-c++-common/gomp/declare-variant-5.c: New test. * c-c++-common/gomp/declare-variant-6.c: New test. * c-c++-common/gomp/declare-variant-7.c: New test. From-SVN: r276914 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index fea97bb434f..2b63689bc7a 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,16 @@ +2019-10-12 Jakub Jelinek + + * c-common.h (c_omp_mark_declare_variant, + c_omp_context_selector_matches): Declare. + * c-omp.c: Include attribs.h, gimplify.h, cgraph.h, symbol-summary.h + and hsa-common.h. + (c_omp_get_context_selector): Support second argument NULL. + (c_omp_mark_declare_variant, c_omp_context_selector_matches): New + functions. + * c-attribs.c (c_common_attribute_table): Remove "omp declare variant" + attribute, add "omp declare variant base" and + "omp declare variant variant" attributes. + 2019-10-11 Joseph Myers * c.opt (Wc11-c2x-compat): Add CPP(cpp_warn_c11_c2x_compat) diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 917d483bcbf..ea273f89a8e 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -444,7 +444,9 @@ const struct attribute_spec c_common_attribute_table[] = handle_returns_nonnull_attribute, NULL }, { "omp declare simd", 0, -1, true, false, false, false, handle_omp_declare_simd_attribute, NULL }, - { "omp declare variant", 0, -1, true, false, false, false, + { "omp declare variant base", 0, -1, true, false, false, false, + handle_omp_declare_variant_attribute, NULL }, + { "omp declare variant variant", 0, -1, true, false, false, false, handle_omp_declare_variant_attribute, NULL }, { "simd", 0, 1, true, false, false, false, handle_simd_attribute, NULL }, @@ -3068,7 +3070,7 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *) return NULL_TREE; } -/* Handle an "omp declare variant" attribute; arguments as in +/* Handle an "omp declare variant {base,variant}" attribute; arguments as in struct attribute_spec.handler. */ static tree diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index eabe689120f..db7f26eec53 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1191,6 +1191,8 @@ extern bool c_omp_predefined_variable (tree); extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); extern tree c_omp_check_context_selector (location_t, tree); extern tree c_omp_get_context_selector (tree, const char *, const char *); +extern void c_omp_mark_declare_variant (location_t, tree, tree); +extern int c_omp_context_selector_matches (tree); /* Return next tree in the chain for chain_next walking of tree nodes. */ static inline tree diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 542625604ad..339818817e2 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -32,6 +32,11 @@ along with GCC; see the file COPYING3. If not see #include "omp-general.h" #include "gomp-constants.h" #include "memmodel.h" +#include "attribs.h" +#include "gimplify.h" +#include "cgraph.h" +#include "symbol-summary.h" +#include "hsa-common.h" /* Complete a #pragma oacc wait construct. LOC is the location of @@ -2236,17 +2241,335 @@ c_omp_check_context_selector (location_t loc, tree ctx) } /* From context selector CTX, return trait-selector with name SEL in - trait-selector-set with name SET if any, or NULL_TREE if not found. */ + trait-selector-set with name SET if any, or NULL_TREE if not found. + If SEL is NULL, return the list of trait-selectors in SET. */ tree c_omp_get_context_selector (tree ctx, const char *set, const char *sel) { tree setid = get_identifier (set); - tree selid = get_identifier (sel); + tree selid = sel ? get_identifier (sel) : NULL_TREE; for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1)) if (TREE_PURPOSE (t1) == setid) - for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2)) - if (TREE_PURPOSE (t2) == selid) - return t2; + { + if (sel == NULL) + return TREE_VALUE (t1); + for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2)) + if (TREE_PURPOSE (t2) == selid) + return t2; + } return NULL_TREE; } + +/* Register VARIANT as variant of some base function marked with + #pragma omp declare variant. CONSTRUCT is corresponding construct + selector set. */ + +void +c_omp_mark_declare_variant (location_t loc, tree variant, tree construct) +{ + tree attr = lookup_attribute ("omp declare variant variant", + DECL_ATTRIBUTES (variant)); + if (attr == NULL_TREE) + { + attr = tree_cons (get_identifier ("omp declare variant variant"), + unshare_expr (construct), + DECL_ATTRIBUTES (variant)); + DECL_ATTRIBUTES (variant) = attr; + return; + } + tree t1 = TREE_VALUE (attr); + tree t2 = construct; + tree simd = get_identifier ("simd"); + while (t1 && t2) + { + if (TREE_PURPOSE (t1) != TREE_PURPOSE (t2)) + break; + if (TREE_PURPOSE (t1) == simd) + { + if ((TREE_VALUE (t1) == NULL_TREE) + != (TREE_VALUE (t2) == NULL_TREE)) + break; + if (TREE_VALUE (t1)) + { + struct declare_variant_simd_data { + bool inbranch, notinbranch; + tree simdlen; + auto_vec data_sharing; + auto_vec aligned; + declare_variant_simd_data () + : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {} + } data[2]; + unsigned int i; + for (i = 0; i < 2; i++) + for (tree c = TREE_VALUE (i ? t2 : t1); + c; c = OMP_CLAUSE_CHAIN (c)) + { + vec *v; + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_INBRANCH: + data[i].inbranch = true; + continue; + case OMP_CLAUSE_NOTINBRANCH: + data[i].notinbranch = true; + continue; + case OMP_CLAUSE_SIMDLEN: + data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c); + continue; + case OMP_CLAUSE_UNIFORM: + case OMP_CLAUSE_LINEAR: + v = &data[i].data_sharing; + break; + case OMP_CLAUSE_ALIGNED: + v = &data[i].aligned; + break; + default: + gcc_unreachable (); + } + unsigned HOST_WIDE_INT argno + = tree_to_uhwi (OMP_CLAUSE_DECL (c)); + if (argno >= v->length ()) + v->safe_grow_cleared (argno + 1); + (*v)[argno] = c; + } + if (data[0].inbranch != data[1].inbranch + || data[0].notinbranch != data[1].notinbranch + || !simple_cst_equal (data[0].simdlen, + data[1].simdlen) + || (data[0].data_sharing.length () + != data[1].data_sharing.length ()) + || (data[0].aligned.length () + != data[1].aligned.length ())) + break; + tree c1, c2; + FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1) + { + c2 = data[1].data_sharing[i]; + if ((c1 == NULL_TREE) != (c2 == NULL_TREE)) + break; + if (c1 == NULL_TREE) + continue; + if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2)) + break; + if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR) + continue; + if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1) + != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2)) + break; + if (OMP_CLAUSE_LINEAR_KIND (c1) + != OMP_CLAUSE_LINEAR_KIND (c2)) + break; + if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1), + OMP_CLAUSE_LINEAR_STEP (c2))) + break; + } + if (i < data[0].data_sharing.length ()) + break; + FOR_EACH_VEC_ELT (data[0].aligned, i, c1) + { + c2 = data[1].aligned[i]; + if ((c1 == NULL_TREE) != (c2 == NULL_TREE)) + break; + if (c1 == NULL_TREE) + continue; + if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1), + OMP_CLAUSE_ALIGNED_ALIGNMENT (c2))) + break; + } + if (i < data[0].aligned.length ()) + break; + } + } + t1 = TREE_CHAIN (t1); + t2 = TREE_CHAIN (t2); + } + if (t1 || t2) + error_at (loc, "%qD used as a variant with incompatible % " + "selector sets", variant); +} + +/* Return 1 if context selector matches the current OpenMP context, 0 + if it does not and -1 if it is unknown and need to be determined later. + Some properties can be checked right away during parsing (this routine), + others need to wait until the whole TU is parsed, others need to wait until + IPA, others until vectorization. */ + +int +c_omp_context_selector_matches (tree ctx) +{ + int ret = 1; + for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1)) + { + char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0]; + if (set == 'c') + { + /* For now, ignore the construct set. While something can be + determined already during parsing, we don't know until end of TU + whether additional constructs aren't added through declare variant + unless "omp declare variant variant" attribute exists already + (so in most of the cases), and we'd need to maintain set of + surrounding OpenMP constructs, which is better handled during + gimplification. */ + ret = -1; + continue; + } + for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2)) + { + const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2)); + switch (*sel) + { + case 'v': + if (set == 'i' && !strcmp (sel, "vendor")) + for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3)) + { + const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3)); + if (!strcmp (prop, " score") || !strcmp (prop, "gnu")) + continue; + return 0; + } + break; + case 'e': + if (set == 'i' && !strcmp (sel, "extension")) + /* We don't support any extensions right now. */ + return 0; + break; + case 'a': + if (set == 'i' && !strcmp (sel, "atomic_default_mem_order")) + { + enum omp_memory_order omo + = ((enum omp_memory_order) + (omp_requires_mask + & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER)); + if (omo == OMP_MEMORY_ORDER_UNSPECIFIED) + { + /* We don't know yet, until end of TU. */ + ret = -1; + break; + } + tree t3 = TREE_VALUE (t2); + const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3)); + if (!strcmp (prop, " score")) + { + t3 = TREE_CHAIN (t3); + prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3)); + } + if (!strcmp (prop, "relaxed") + && omo != OMP_MEMORY_ORDER_RELAXED) + return 0; + else if (!strcmp (prop, "seq_cst") + && omo != OMP_MEMORY_ORDER_SEQ_CST) + return 0; + else if (!strcmp (prop, "acq_rel") + && omo != OMP_MEMORY_ORDER_ACQ_REL) + return 0; + } + if (set == 'd' && !strcmp (sel, "arch")) + /* For now, need a target hook. */ + ret = -1; + break; + case 'u': + if (set == 'i' && !strcmp (sel, "unified_address")) + { + if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0) + ret = -1; + break; + } + if (set == 'i' && !strcmp (sel, "unified_shared_memory")) + { + if ((omp_requires_mask + & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0) + ret = -1; + break; + } + break; + case 'd': + if (set == 'i' && !strcmp (sel, "dynamic_allocators")) + { + if ((omp_requires_mask + & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0) + ret = -1; + break; + } + break; + case 'r': + if (set == 'i' && !strcmp (sel, "reverse_offload")) + { + if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0) + ret = -1; + break; + } + break; + case 'k': + if (set == 'd' && !strcmp (sel, "kind")) + for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3)) + { + const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3)); + if (!strcmp (prop, "any")) + continue; + if (!strcmp (prop, "fpga")) + return 0; /* Right now GCC doesn't support any fpgas. */ + if (!strcmp (prop, "host")) + { + if (ENABLE_OFFLOADING || hsa_gen_requested_p ()) + ret = -1; + continue; + } + if (!strcmp (prop, "nohost")) + { + if (ENABLE_OFFLOADING || hsa_gen_requested_p ()) + ret = -1; + else + return 0; + continue; + } + if (!strcmp (prop, "cpu") || !strcmp (prop, "gpu")) + { + bool maybe_gpu = false; + if (hsa_gen_requested_p ()) + maybe_gpu = true; + else if (ENABLE_OFFLOADING) + for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); + c; ) + { + if (!strncmp (c, "nvptx", strlen ("nvptx")) + || !strncmp (c, "amdgcn", strlen ("amdgcn"))) + { + maybe_gpu = true; + break; + } + else if ((c = strchr (c, ','))) + c++; + } + if (!maybe_gpu) + { + if (prop[0] == 'g') + return 0; + } + else + ret = -1; + continue; + } + /* Any other kind doesn't match. */ + return 0; + } + break; + case 'i': + if (set == 'd' && !strcmp (sel, "isa")) + /* For now, need a target hook. */ + ret = -1; + break; + case 'c': + if (set == 'u' && !strcmp (sel, "condition")) + for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3)) + if (TREE_PURPOSE (t3) == NULL_TREE + && integer_zerop (TREE_VALUE (t3))) + return 0; + break; + default: + break; + } + } + } + return ret; +} diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 894f5e752e3..5fb386c4b9e 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2019-10-12 Jakub Jelinek + + * c-parser.c (c_parser_omp_context_selector): Improve error recovery. + For simd properties, put them directly into TREE_VALUE. + (c_finish_omp_declare_variant): Call c_omp_mark_declare_variant. + If c_omp_context_selector_matches is 0, don't add attribute, otherwise + add "omp declare variant base" attribute rather than + "omp declare variant". + 2019-10-11 Joseph Myers * c-decl.c (declspecs_add_type): Use pedwarn_c11 for DFP types. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 2daaee80d85..9d0b2b671f8 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -19219,6 +19219,8 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms) else properties = tree_cons (NULL_TREE, t, properties); } + else + return error_mark_node; if (c_parser_next_token_is (parser, CPP_COMMA)) c_parser_consume_token (parser); @@ -19263,6 +19265,8 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms) else properties = tree_cons (NULL_TREE, t, properties); } + else + return error_mark_node; break; case CTX_PROPERTY_SIMD: if (parms == NULL_TREE) @@ -19280,7 +19284,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms) == error_mark_node ? NULL_TREE : parms, c); - properties = tree_cons (NULL_TREE, c, properties); + properties = c; break; default: gcc_unreachable (); @@ -19389,7 +19393,7 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms) } /* Finalize #pragma omp declare variant after FNDECL has been parsed, and put - that into "omp declare variant" attribute. */ + that into "omp declare variant base" attribute. */ static void c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) @@ -19473,10 +19477,16 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) if (variant != error_mark_node) { C_DECL_USED (variant) = 1; - tree attr = tree_cons (get_identifier ("omp declare variant"), - build_tree_list (variant, ctx), - DECL_ATTRIBUTES (fndecl)); - DECL_ATTRIBUTES (fndecl) = attr; + tree construct = c_omp_get_context_selector (ctx, "construct", NULL); + c_omp_mark_declare_variant (match_loc, variant, construct); + if (c_omp_context_selector_matches (ctx)) + { + tree attr + = tree_cons (get_identifier ("omp declare variant base"), + build_tree_list (variant, ctx), + DECL_ATTRIBUTES (fndecl)); + DECL_ATTRIBUTES (fndecl) = attr; + } } } @@ -19486,7 +19496,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) /* Finalize #pragma omp declare simd or #pragma omp declare variant clauses after FNDECL has been parsed, and put that into "omp declare simd" - or "omp declare variant" attribute. */ + or "omp declare variant base" attribute. */ static void c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 02a330d772e..dcae4909d5e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-10-12 Jakub Jelinek + + * parser.c (cp_parser_omp_context_selector): Improve error recovery. + For simd properties, put them directly into TREE_VALUE. + (cp_finish_omp_declare_variant): Add "omp declare variant base" + attribute rather than "omp declare variant". + 2019-10-11 Marek Polacek PR c++/92049 - extra error with -fchecking=2. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3ee8da7db94..9bf690a0efb 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40488,6 +40488,8 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p) else properties = tree_cons (NULL_TREE, t, properties); } + else + return error_mark_node; if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); @@ -40532,6 +40534,8 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p) else properties = tree_cons (NULL_TREE, t, properties); } + else + return error_mark_node; break; case CTX_PROPERTY_SIMD: if (!has_parms_p) @@ -40541,11 +40545,10 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p) "%"); return error_mark_node; } - tree c; - c = cp_parser_omp_all_clauses (parser, + properties + = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, "simd", NULL, true, true); - properties = tree_cons (NULL_TREE, c, properties); break; default: gcc_unreachable (); @@ -40662,7 +40665,7 @@ cp_parser_omp_context_selector_specification (cp_parser *parser, } /* Finalize #pragma omp declare variant after a fndecl has been parsed, and put - that into "omp declare variant" attribute. */ + that into "omp declare variant base" attribute. */ static tree cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, @@ -40717,7 +40720,7 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, ctx = c_omp_check_context_selector (match_loc, ctx); if (ctx != error_mark_node && variant != error_mark_node) { - attrs = tree_cons (get_identifier ("omp declare variant"), + attrs = tree_cons (get_identifier ("omp declare variant base"), build_tree_list (variant, ctx), attrs); if (processing_template_decl) ATTR_IS_DEPENDENT (attrs) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9b31f353642..14b5da645ec 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2019-10-12 Jakub Jelinek + + * c-c++-common/gomp/declare-variant-2.c: Adjust for error recovery + improvements. Add new tests. + * c-c++-common/gomp/declare-variant-4.c: New test. + * c-c++-common/gomp/declare-variant-5.c: New test. + * c-c++-common/gomp/declare-variant-6.c: New test. + * c-c++-common/gomp/declare-variant-7.c: New test. + 2019-10-11 Joseph Myers * gcc.dg/dfp/c11-constants-1.c, gcc.dg/dfp/c11-constants-2.c, diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c index bc12398911c..f058f57e687 100644 --- a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c @@ -1,3 +1,4 @@ +void f0 (void); void f1 (void); #pragma omp declare variant /* { dg-error "expected '\\(' before end of line" } */ void f2 (void); @@ -34,7 +35,7 @@ void f17 (void); #pragma omp declare variant (f1) match(user={condition}) /* { dg-error "expected '\\(' before '\\\}' token" } */ void f18 (void); #pragma omp declare variant (f1) match(user={condition(}) /* { dg-error "expected \[^\n\r]*expression before '\\\}' token" } */ -void f19 (void); /* { dg-error "expected '\\)' before '\\\}' token" "" { target c++ } .-1 } */ +void f19 (void); #pragma omp declare variant (f1) match(user={condition()}) /* { dg-error "expected \[^\n\r]*expression before '\\)' token" } */ void f20 (void); #pragma omp declare variant (f1) match(user={condition(f1)}) /* { dg-error "property must be constant integer expression" "" { target { c || c++11 } } } */ @@ -50,7 +51,7 @@ void f25 (void); /* { dg-error "expected '\\\}' before end of line" "" { ta /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-2 } */ #pragma omp declare variant (f1) match(construct={parallel(1)}) /* { dg-error "selector 'parallel' does not accept any properties" } */ void f26 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */ -#pragma omp declare variant (f1) match(construct={simd(12)}) /* { dg-error "expected \[^\n\r]* clause before" } */ +#pragma omp declare variant (f0) match(construct={simd(12)}) /* { dg-error "expected \[^\n\r]* clause before" } */ void f27 (void); /* { dg-error "'\\)' before numeric constant" "" { target c++ } .-1 } */ #pragma omp declare variant (f1) match(construct={parallel},construct={for}) /* { dg-error "selector set 'construct' specified more than once" } */ void f28 (void); @@ -120,3 +121,31 @@ void f58 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { ta void f59 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */ #pragma omp declare variant (f1) match(construct={parallel},foobar={bar}) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'foobar'" } */ void f60 (void); +#pragma omp declare variant (f1) match(construct={parallel,parallel}) /* { dg-error "selector 'parallel' specified more than once in set 'construct'" } */ +void f61 (void); +#pragma omp declare variant (f1) match(construct={target,parallel,for,simd,parallel}) /* { dg-error "selector 'parallel' specified more than once in set 'construct'" } */ +void f62 (void); +#pragma omp declare variant (f1) match(construct={target,teams,teams}) /* { dg-error "selector 'teams' specified more than once in set 'construct'" } */ +void f63 (void); +#pragma omp declare variant (f1) match(construct={single}) /* { dg-error "selector 'single' not allowed for context selector set 'construct'" } */ +void f64 (void); +#pragma omp declare variant (f1) match(construct={taskgroup}) /* { dg-error "selector 'taskgroup' not allowed for context selector set 'construct'" } */ +void f65 (void); +#pragma omp declare variant (f1) match(construct={do}) /* { dg-error "selector 'do' not allowed for context selector set 'construct'" } */ +void f66 (void); +#pragma omp declare variant (f1) match(construct={threadprivate}) /* { dg-error "selector 'threadprivate' not allowed for context selector set 'construct'" } */ +void f67 (void); +#pragma omp declare variant (f1) match(construct={critical}) /* { dg-error "selector 'critical' not allowed for context selector set 'construct'" } */ +void f68 (void); +#pragma omp declare variant (f1) match(construct={task}) /* { dg-error "selector 'task' not allowed for context selector set 'construct'" } */ +void f69 (void); +#pragma omp declare variant (f1) match(construct={taskloop}) /* { dg-error "selector 'taskloop' not allowed for context selector set 'construct'" } */ +void f70 (void); +#pragma omp declare variant (f1) match(construct={sections}) /* { dg-error "selector 'sections' not allowed for context selector set 'construct'" } */ +void f71 (void); +#pragma omp declare variant (f1) match(construct={section}) /* { dg-error "selector 'section' not allowed for context selector set 'construct'" } */ +void f72 (void); +#pragma omp declare variant (f1) match(construct={workshare}) /* { dg-error "selector 'workshare' not allowed for context selector set 'construct'" } */ +void f73 (void); +#pragma omp declare variant (f1) match(construct={requires}) /* { dg-error "selector 'requires' not allowed for context selector set 'construct'" } */ +void f74 (void); diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-4.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-4.c new file mode 100644 index 00000000000..add373006ad --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-4.c @@ -0,0 +1,22 @@ +double f1 (int, long, float); +double f2 (int, long, float); +double f3 (int, long, float); +double f4 (int, long, float); +double f5 (int, long, float); + +#pragma omp declare variant (f1) match (user={condition(1)}) +#pragma omp declare variant (f2) match (user={condition(score(1):1)}) +#pragma omp declare variant (f3) match (user={condition(score(3):1)}) +#pragma omp declare variant (f4) match (user={condition(score(2):1)}) +#pragma omp declare variant (f5) match (implementation={vendor(gnu)}) +double +f6 (int x, long y, float z) +{ + return z + x + y; +} + +double +test (int x) +{ + return f6 (x, x, 3.5f); +} diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c new file mode 100644 index 00000000000..6ebf09457c0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-additional-options "-mavx2" } */ + +typedef float __v4sf __attribute__((vector_size (16))); +typedef int __v4si __attribute__((vector_size (16))); +typedef float __v8sf __attribute__((vector_size (32))); +typedef int __v8si __attribute__((vector_size (32))); +__v4si f1 (__v4sf, __v4sf, float *); +__v8si f2 (__v8sf, __v8sf, float *); +__v4si f3 (__v4si, int, __v4si); + +#pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))}) +#pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)}) +int f4 (float x, float y, float *z); + +#pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) +int f5 (int x, int y); + +void +test (int *x, float *y, float *z, float *w) +{ + #pragma omp parallel + #pragma omp for simd aligned (w:4 * sizeof (float)) + for (int i = 0; i < 1024; i++) + x[i] = f4 (y[i], z[i], w); + #pragma omp parallel for simd aligned (w:4 * sizeof (float)) simdlen(4) + for (int i = 1024; i < 2048; i++) + x[i] = f4 (y[i], z[i], w); + #pragma omp simd aligned (w:4 * sizeof (float)) + for (int i = 2048; i < 4096; i++) + x[i] = f4 (y[i], z[i], w); + #pragma omp simd + for (int i = 4096; i < 8192; i++) + if (x[i] > 10) + x[i] = f5 (x[i], i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-6.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-6.c new file mode 100644 index 00000000000..67c5a00bd8a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-6.c @@ -0,0 +1,35 @@ +double f1 (int, long, float); +double f2 (int, long, float); +#pragma omp declare variant (f1) match (user={condition(0)},construct={parallel}) +double f3 (int, long, float); +#pragma omp declare variant (f1) match (construct={parallel},user={condition(score(1):1)}) +double f4 (int, long, float); +double f5 (int, long, float); +#pragma omp declare variant (f5) match (user={condition(0)}) +double f6 (int, long, float); +#pragma omp declare variant (f5) match (construct={parallel},user={condition(score(1):1)}) /* { dg-error "'f5' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +double f7 (int, long, float); +double f8 (int, long, float); +#pragma omp declare variant (f8) match (user={condition(0)},construct={for}) +double f9 (int, long, float); +#pragma omp declare variant (f8) match (user={condition(1)}) /* { dg-error "'f8' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +double f10 (int, long, float); +double f11 (int, long, float); +#pragma omp declare variant (f11) match (construct={target,teams,parallel,for}) +double f12 (int, long, float); +#pragma omp declare variant (f11) match (user={condition(score(1):1)},construct={target,teams,parallel,for}) +double f13 (int, long, float); +#pragma omp declare variant (f11) match (implementation={vendor(gnu)},construct={target,teams,parallel}) /* { dg-error "'f11' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +double f14 (int, long, float); +#pragma omp declare variant (f11) match (device={kind(any)},construct={teams,parallel}) /* { dg-error "'f11' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +double f15 (int, long, float); +double f16 (int, long, float); +#pragma omp declare variant (f16) match (construct={teams,parallel}) +double f17 (int, long, float); +#pragma omp declare variant (f16) match(construct={teams,parallel,for}) /* { dg-error "'f16' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +double f18 (int, long, float); +double f19 (int, long, float); +#pragma omp declare variant (f19) match (construct={parallel}) +double f20 (int, long, float); +#pragma omp declare variant (f19) match (construct={for},implementation={vendor(gnu,llvm)}) /* { dg-error "'f19' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +double f21 (int, long, float); diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c new file mode 100644 index 00000000000..f818cd5ec7b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-additional-options "-mavx2" } */ + +typedef float __v4sf __attribute__((vector_size (16))); +typedef int __v4si __attribute__((vector_size (16))); +typedef float __v8sf __attribute__((vector_size (32))); +typedef int __v8si __attribute__((vector_size (32))); +__v4si f1 (__v4sf, __v4sf, float *); +__v8si f2 (__v8sf, __v8sf, float *); +__v4si f3 (__v4si, int, __v4si); + +#pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))}) +int f4 (float x, float y, float *z); +#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),simdlen(8*2-12),aligned(w:4*sizeof (float)),notinbranch)}) +int f5 (float u, float v, float *w); +#pragma omp declare variant (f1) match (construct={parallel,for,simd(linear(w),notinbranch,simdlen(4),aligned(w:4*sizeof (float)))}) /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +int f6 (float u, float v, float *w); +#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w:2*sizeof (float)))}) /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +int f7 (float u, float v, float *w); +#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w))}) /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +int f8 (float u, float v, float *w); +#pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)}) +int f9 (float x, float y, float *z); +#pragma omp declare variant (f2) match (construct={for,simd(notinbranch,simdlen(2+2+4),uniform (q))}) +int f10 (float x, float y, float *q); +#pragma omp declare variant (f2) match (construct={for,simd(linear(z:2),simdlen(8),notinbranch)}) /* { dg-error "'f2' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +int f11 (float x, float y, float *z); +#pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) +int f12 (int x, int y); +#pragma omp declare variant (f3) match (construct={simd(inbranch,simdlen(5-1),linear(q:4-3))}) +int f13 (int x, int q); +#pragma omp declare variant (f3) match (construct={simd(inbranch,simdlen(4),linear(q:2))}) /* { dg-error "'f3' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */ +int f14 (int x, int q);