From patchwork Sat Oct 12 08:31:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1175680 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-510830-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="acyxAxI0"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46qyjg6Qcbz9sCJ for ; Sat, 12 Oct 2019 19:32:05 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; q=dns; s=default; b=Q+33I4TbykruAmtpAheUIa4M8H+ELU/OrCCDqQ7BID6 Jjb6ANslNqs6IrITpLRv71+37XCkBjA9fSf2enybJixDR3QuAkIzrPAL3xAeAgsM s8knuXng9GyPHQbYeu9IhEdESthJFTNlT1ohvvnM8PAQNn6VrgdYfcLkjEziOJEE = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; s=default; bh=i7SReyP/RdJA+uKW6gGHJASS5pg=; b=acyxAxI0nm+JlSU/H LhW1YeIqrpj75iVZp8zHsCWdPPFGvHaUY9hUwvPzkimqvy31SAymKormZYsn1RS7 oDk6e2pSQodZmkxQaMVnIfDF21W8NfB1zSnl30JPrOFLpfHJGVcLzqIc6lbX/3Nj ikGQUrfmVmpIXm6N2FlMjXrEkU= Received: (qmail 129413 invoked by alias); 12 Oct 2019 08:31:56 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 129405 invoked by uid 89); 12 Oct 2019 08:31:56 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=1203, 43, sk:enable_ X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 12 Oct 2019 08:31:52 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F3121A2666F for ; Sat, 12 Oct 2019 08:31:50 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-90.ams2.redhat.com [10.36.116.90]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4F13660923 for ; Sat, 12 Oct 2019 08:31:50 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id x9C8Vm0N022690 for ; Sat, 12 Oct 2019 10:31:48 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id x9C8Vl95022689 for gcc-patches@gcc.gnu.org; Sat, 12 Oct 2019 10:31:47 +0200 Date: Sat, 12 Oct 2019 10:31:47 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [committed] Further work on declare variant Message-ID: <20191012083147.GZ15914@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.11.3 (2019-02-01) X-IsSubscribed: yes Hi! The following patch adds diagnostics if the same function serves as variant for multiple base functions and there is a mismatch in the construct selector set. Additionally, it adds a start of a function that says if a context selector matches the OpenMP context, doesn't or we don't know yet. In the last case we need to defer the decision until later. The C++ part for this isn't done, because I need to figure out the right way to perform the lookup (using dummy arguments (and dummy instance for methods) based on the function argument types and method context)). Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2019-10-12 Jakub Jelinek 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. Jakub --- gcc/c-family/c-common.h.jj 2019-10-11 20:48:23.823186584 +0200 +++ gcc/c-family/c-common.h 2019-10-11 20:48:36.795991404 +0200 @@ -1191,6 +1191,8 @@ extern bool c_omp_predefined_variable (t 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 --- gcc/c-family/c-omp.c.jj 2019-10-11 20:48:23.812186749 +0200 +++ gcc/c-family/c-omp.c 2019-10-11 21:07:33.083904116 +0200 @@ -32,6 +32,11 @@ along with GCC; see the file COPYING3. #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 } /* 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; +} --- gcc/c-family/c-attribs.c.jj 2019-10-11 20:48:23.842186298 +0200 +++ gcc/c-family/c-attribs.c 2019-10-11 20:48:36.797991374 +0200 @@ -444,7 +444,9 @@ const struct attribute_spec c_common_att 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 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 --- gcc/c/c-parser.c.jj 2019-10-11 20:48:23.637189382 +0200 +++ gcc/c/c-parser.c 2019-10-11 20:48:36.801991314 +0200 @@ -19219,6 +19219,8 @@ c_parser_omp_context_selector (c_parser 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 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 == 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_specificat } /* 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 * 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 * /* 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, --- gcc/cp/parser.c.jj 2019-10-11 20:48:23.607189833 +0200 +++ gcc/cp/parser.c 2019-10-11 20:48:36.806991239 +0200 @@ -40488,6 +40488,8 @@ cp_parser_omp_context_selector (cp_parse 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_parse 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_parse "%"); 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_specifica } /* 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 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; --- gcc/testsuite/c-c++-common/gomp/declare-variant-2.c.jj 2019-10-11 20:48:23.730187983 +0200 +++ gcc/testsuite/c-c++-common/gomp/declare-variant-2.c 2019-10-11 20:48:36.806991239 +0200 @@ -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 "exp /* { 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 "exp 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); --- gcc/testsuite/c-c++-common/gomp/declare-variant-4.c.jj 2019-10-11 20:48:36.806991239 +0200 +++ gcc/testsuite/c-c++-common/gomp/declare-variant-4.c 2019-10-11 20:48:36.806991239 +0200 @@ -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); +} --- gcc/testsuite/c-c++-common/gomp/declare-variant-5.c.jj 2019-10-11 20:48:36.806991239 +0200 +++ gcc/testsuite/c-c++-common/gomp/declare-variant-5.c 2019-10-11 20:48:36.806991239 +0200 @@ -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); +} --- gcc/testsuite/c-c++-common/gomp/declare-variant-6.c.jj 2019-10-11 20:48:36.806991239 +0200 +++ gcc/testsuite/c-c++-common/gomp/declare-variant-6.c 2019-10-11 20:48:36.806991239 +0200 @@ -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); --- gcc/testsuite/c-c++-common/gomp/declare-variant-7.c.jj 2019-10-11 20:48:36.806991239 +0200 +++ gcc/testsuite/c-c++-common/gomp/declare-variant-7.c 2019-10-11 20:48:36.806991239 +0200 @@ -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);