From patchwork Mon Jan 20 03:37:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Iyer, Balaji V" X-Patchwork-Id: 312439 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 9769C2C00A4 for ; Mon, 20 Jan 2014 14:37:46 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; q=dns; s=default; b=u1Z+qviz9n/EREG1 ReUi3W0Jts2nY262wAm2ViuQXuWuTq4bcChW0vccKkIzDgsVI0Rpg25F+BvJ1Ks/ Cg+Mc6hJhaKVLIa/4yOPm9Ai73v1uoO/kz8MOjtuaJYPLgPlbxbkjW8ati/bgDvA fNwXk0AcmIJwfKZefC7evDo91A0= 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:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; s=default; bh=/gyJR0eqzrXQEFNYYEjqZQ lwDcA=; b=fOORTuYNdrmSme1T4h1NqVb+r87IzepCRHN9Zy4T+gk22gFMEZD+FI mT4BBM+hQo2G87ecSVjsIJPAImUrYZ7Yi13Q3HdaXaz728nqVB5FTCYckTRgUdxk Zy9ZpF6Z7LjJsOF28GNAv5CrxqIS6/iRVdsFcLaHJCZNHz+46+F4s= Received: (qmail 26645 invoked by alias); 20 Jan 2014 03:37:37 -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 26629 invoked by uid 89); 20 Jan 2014 03:37:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mga03.intel.com Received: from mga03.intel.com (HELO mga03.intel.com) (143.182.124.21) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 20 Jan 2014 03:37:33 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by azsmga101.ch.intel.com with ESMTP; 19 Jan 2014 19:37:31 -0800 X-ExtLoop1: 1 Received: from fmsmsx105.amr.corp.intel.com ([10.19.9.36]) by fmsmga001.fm.intel.com with ESMTP; 19 Jan 2014 19:37:30 -0800 Received: from fmsmsx157.amr.corp.intel.com (10.18.116.73) by FMSMSX105.amr.corp.intel.com (10.19.9.36) with Microsoft SMTP Server (TLS) id 14.3.123.3; Sun, 19 Jan 2014 19:37:30 -0800 Received: from fmsmsx101.amr.corp.intel.com ([169.254.1.227]) by FMSMSX157.amr.corp.intel.com ([10.18.116.73]) with mapi id 14.03.0123.003; Sun, 19 Jan 2014 19:37:29 -0800 From: "Iyer, Balaji V" To: Jakub Jelinek CC: "'Aldy Hernandez (aldyh@redhat.com)'" , "'gcc-patches@gcc.gnu.org'" Subject: RE: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental functions) for C++ Date: Mon, 20 Jan 2014 03:37:29 +0000 Message-ID: References: <20131219072318.GK892@tucnak.redhat.com> <20140117174534.GL892@tucnak.redhat.com> In-Reply-To: <20140117174534.GL892@tucnak.redhat.com> MIME-Version: 1.0 X-IsSubscribed: yes Hi Jakub, I have fixed all the issues you have mentioned below. I am also attaching a fixed patch along with ChangeLog entries. I have also rebased the patch to the trunk revision r206786. Is this Ok to install? Thanks, Balaji V. Iyer. > -----Original Message----- > From: Jakub Jelinek [mailto:jakub@redhat.com] > Sent: Friday, January 17, 2014 12:46 PM > To: Iyer, Balaji V > Cc: 'Aldy Hernandez (aldyh@redhat.com)'; 'gcc-patches@gcc.gnu.org' > Subject: Re: [GOMP4][PATCH] SIMD-enabled functions (formerly Elemental > functions) for C++ > > On Thu, Dec 19, 2013 at 06:12:29PM +0000, Iyer, Balaji V wrote: > > 2013-12-19 Balaji V. Iyer > > > > * parser.c (cp_parser_direct_declarator): When Cilk Plus is enabled > > see if there is an attribute after function decl. If so, then > > parse them now. > > (cp_parser_late_return_type_opt): Handle parsing of Cilk Plus SIMD > > enabled function late parsing. > > (cp_parser_gnu_attribute_list): Parse all the tokens for the vector > > attribute for a SIMD-enabled function. > > (cp_parser_omp_all_clauses): Skip parsing to the end of pragma when > > the function is used by SIMD-enabled function (indicated by NULL > > pragma token). Added 3 new clauses: PRAGMA_CILK_CLAUSE_MASK, > > PRAGMA_CILK_CLAUSE_NOMASK and > PRAGMA_CILK_CLAUSE_VECTORLENGTH > > (cp_parser_cilk_simd_vectorlength): Modified this function to handle > > vectorlength clause in SIMD-enabled function and #pragma SIMD's > > vectorlength clause. Added a new bool parameter to differentiate > > between the two. > > (cp_parser_cilk_simd_fn_vector_attrs): New function. > > (is_cilkplus_vector_p): Likewise. > > (cp_parser_late_parsing_elem_fn_info): Likewise. > > (cp_parser_omp_clause_name): Added a check for "mask," "nomask" > > The comma should have been after " . > Fixed. > > + /* In here, we handle cases where attribute is used after > > + the function declaration. For example: > > + void func (int x) __attribute__((vector(..))); */ > > + if (flag_enable_cilkplus > > + && cp_next_tokens_can_be_attribute_p (parser)) > > As you are just calling cp_parser_gnu_attributes_opt here and not ..._std_..., > I'd say the above should be cp_next_tokens_can_be_gnu_attribute_p > rather than cp_next_tokens_can_be_attribute_p. I think [[...]] attributes at > this position are ignored, so no need to handle them, not sure about > whether we allow e.g. combination of GNU and std attributes or vice versa. > Fixed. > > + { > > + cp_parser_parse_tentatively (parser); > > + tree attr = cp_parser_gnu_attributes_opt (parser); > > + if (cp_lexer_next_token_is_not (parser->lexer, > > + CPP_SEMICOLON) > > + && cp_lexer_next_token_is_not (parser->lexer, > > + CPP_OPEN_BRACE)) > > + cp_parser_abort_tentative_parse (parser); > > + else if (!cp_parser_parse_definitely (parser)) > > + ; > > + else > > + attrs = chainon (attr, attrs); > > + } > > late_return = (cp_parser_late_return_type_opt > > (parser, declarator, > > memfn ? cv_quals : -1)); > > > @@ -17842,6 +17868,10 @@ cp_parser_late_return_type_opt (cp_parser* > parser, cp_declarator *declarator, > > type = cp_parser_trailing_type_id (parser); > > } > > > > + if (cilk_simd_fn_vector_p) > > + declarator->std_attributes > > + = cp_parser_late_parsing_cilk_simd_fn_info (parser, > > + declarator->std_attributes); > > Please make sure declarator is aligned below parser. > Fixed. > > + token->type = CPP_PRAGMA_EOL; > > + parser->lexer->next_token = token; > > + cp_lexer_consume_token (parser->lexer); > > + > > + struct cp_token_cache *cp = > > + cp_token_cache_new (v_token, cp_lexer_peek_token > > + (parser->lexer)); > > The = should already go on the next line. > Fixed. > > +/* Handles the delayed parsing of the Cilk Plus SIMD-enabled function. > > + This function is modelled similar to the late parsing of omp declare > > + simd. */ > > + > > +static tree > > +cp_parser_late_parsing_cilk_simd_fn_info (cp_parser *parser, tree > > +attrs) { > > + struct cp_token_cache *ce; > > + cp_omp_declare_simd_data *info = parser->cilk_simd_fn_info; > > + int ii = 0; > > + > > + if (parser->omp_declare_simd != NULL) > > + { > > + error ("%<#pragma omp declare simd%> cannot be used in the same > function" > > + " marked as a Cilk Plus SIMD-enabled function"); > > + parser->cilk_simd_fn_info = NULL; > > This will leak parser->cilk_simd_fn_info memory. Please XDELETE it first. > Fixed > > + return attrs; > > + } > > + if (!info->error_seen && info->fndecl_seen) > > + { > > + error ("vector attribute not immediately followed by a single function" > > + " declaration or definition"); > > + info->error_seen = true; > > + } > > + if (info->error_seen) > > + return attrs; > > + > > + /* Vector attributes are converted to #pragma omp declare simd values > and > > + so we need them enabled. */ > > + flag_openmp = 1; > > The C FE doesn't do this. I thought all the omp-low.c spots are now guarded > by flag_openmp || flag_enable_cilkplus etc. conditions. Fixed. The above "orring" was omitted in decl.c and pt.c . I have put them in. > > > + c = build_tree_list (get_identifier ("cilk simd function"), > > + cl); > > Please use NULL_TREE instead of cl here and please fix up the C FE as well, > the "cilk simd function" attribute should be just an attribute without value, > serving only as a boolean, if present, decl with "omp declare simd" attribute > is Cilk+, otherwise OpenMP. > > > + TREE_CHAIN (c) = attrs; > > + if (processing_template_decl) > > + ATTR_IS_DEPENDENT (c) = 1; > Fixed. > But, as a boolean attribute it doesn't and shouldn't be ATTR_IS_DEPENDENT, > there is nothing to adjust in it. > > --- a/gcc/cp/pt.c > > +++ b/gcc/cp/pt.c > > @@ -8602,9 +8602,12 @@ apply_late_template_attributes (tree *decl_p, > tree attributes, int attr_flags, > > { > > *p = TREE_CHAIN (t); > > TREE_CHAIN (t) = NULL_TREE; > > - if (flag_openmp > > - && is_attribute_p ("omp declare simd", > > - get_attribute_name (t)) > > + if (((flag_openmp > > + && is_attribute_p ("omp declare simd", > > + get_attribute_name (t))) > > + || (flag_enable_cilkplus > > + && is_attribute_p ("cilk simd function", > > + get_attribute_name (t)))) > > && TREE_VALUE (t)) > > { > > tree clauses = TREE_VALUE (TREE_VALUE (t)); > > And this change is unnecessary after the above suggested change. > Fixed. > Jakub diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 4490210..bbf5287 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -12924,7 +12924,8 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, c = tree_cons (NULL_TREE, c, NULL_TREE); if (is_cilkplus_cilk_simd_fn) { - tree k = build_tree_list (get_identifier ("cilk simd function"), c); + tree k = build_tree_list (get_identifier ("cilk simd function"), + NULL_TREE); TREE_CHAIN (k) = DECL_ATTRIBUTES (fndecl); DECL_ATTRIBUTES (fndecl) = k; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5906653..9918416 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7674,7 +7674,7 @@ grokfndecl (tree ctype, if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl)) TREE_NOTHROW (decl) = 1; - if (flag_openmp) + if (flag_openmp || flag_enable_cilkplus) { /* Adjust "omp declare simd" attributes. */ tree ods = lookup_attribute ("omp declare simd", *attrlist); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c3016bc..971fe8f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -241,6 +241,8 @@ static void cp_parser_cilk_simd (cp_parser *, cp_token *); static bool cp_parser_omp_declare_reduction_exprs (tree, cp_parser *); +static tree cp_parser_cilk_simd_vectorlength + (cp_parser *, tree, bool); /* Manifest constants. */ #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token)) @@ -2115,6 +2117,9 @@ static bool cp_parser_ctor_initializer_opt_and_function_body static tree cp_parser_late_parsing_omp_declare_simd (cp_parser *, tree); +static tree cp_parser_late_parsing_cilk_simd_fn_info + (cp_parser *, tree); + static tree synthesize_implicit_template_parm (cp_parser *); static tree finish_fully_implicit_template @@ -17121,6 +17126,24 @@ cp_parser_direct_declarator (cp_parser* parser, attrs = cp_parser_std_attribute_spec_seq (parser); + /* In here, we handle cases where attribute is used after + the function declaration. For example: + void func (int x) __attribute__((vector(..))); */ + if (flag_enable_cilkplus + && cp_next_tokens_can_be_gnu_attribute_p (parser)) + { + cp_parser_parse_tentatively (parser); + tree attr = cp_parser_gnu_attributes_opt (parser); + if (cp_lexer_next_token_is_not (parser->lexer, + CPP_SEMICOLON) + && cp_lexer_next_token_is_not (parser->lexer, + CPP_OPEN_BRACE)) + cp_parser_abort_tentative_parse (parser); + else if (!cp_parser_parse_definitely (parser)) + ; + else + attrs = chainon (attr, attrs); + } late_return = (cp_parser_late_return_type_opt (parser, declarator, memfn ? cv_quals : -1)); @@ -17829,7 +17852,7 @@ parsing_nsdmi (void) Returns the type indicated by the type-id. In addition to this this parses any queued up omp declare simd - clauses. + clauses and Cilk Plus SIMD-enabled function's vector attributes. QUALS is either a bitmask of cv_qualifiers or -1 for a non-member function. */ @@ -17844,10 +17867,13 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator, && declarator && declarator->kind == cdk_id); + bool cilk_simd_fn_vector_p = (parser->cilk_simd_fn_info + && declarator && declarator->kind == cdk_id); + /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* A late-specified return type is indicated by an initial '->'. */ - if (token->type != CPP_DEREF && !declare_simd_p) + if (token->type != CPP_DEREF && !(declare_simd_p || cilk_simd_fn_vector_p)) return NULL_TREE; tree save_ccp = current_class_ptr; @@ -17866,6 +17892,10 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator, type = cp_parser_trailing_type_id (parser); } + if (cilk_simd_fn_vector_p) + declarator->std_attributes + = cp_parser_late_parsing_cilk_simd_fn_info (parser, + declarator->std_attributes); if (declare_simd_p) declarator->std_attributes = cp_parser_late_parsing_omp_declare_simd (parser, @@ -21399,6 +21429,56 @@ cp_parser_attributes_opt (cp_parser *parser) return cp_parser_std_attribute_spec_seq (parser); } +#define CILK_SIMD_FN_CLAUSE_MASK \ + ((OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_VECTORLENGTH) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_LINEAR) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_UNIFORM) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_MASK) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_CILK_CLAUSE_NOMASK)) + +/* Parses the Cilk Plus SIMD-enabled function's attribute. Syntax: + vector [()] */ + +static void +cp_parser_cilk_simd_fn_vector_attrs (cp_parser *parser, cp_token *v_token) +{ + bool first_p = parser->cilk_simd_fn_info == NULL; + cp_token *token = v_token; + if (first_p) + { + parser->cilk_simd_fn_info = XNEW (cp_omp_declare_simd_data); + parser->cilk_simd_fn_info->error_seen = false; + parser->cilk_simd_fn_info->fndecl_seen = false; + parser->cilk_simd_fn_info->tokens = vNULL; + } + int paren_scope = 0; + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + cp_lexer_consume_token (parser->lexer); + v_token = cp_lexer_peek_token (parser->lexer); + paren_scope++; + } + while (paren_scope > 0) + { + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_OPEN_PAREN) + paren_scope++; + else if (token->type == CPP_CLOSE_PAREN) + paren_scope--; + /* Do not push the last ')' */ + if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0)) + cp_lexer_consume_token (parser->lexer); + } + + token->type = CPP_PRAGMA_EOL; + parser->lexer->next_token = token; + cp_lexer_consume_token (parser->lexer); + + struct cp_token_cache *cp + = cp_token_cache_new (v_token, cp_lexer_peek_token (parser->lexer)); + parser->cilk_simd_fn_info->tokens.safe_push (cp); +} + /* Parse an (optional) series of attributes. attributes: @@ -21457,6 +21537,17 @@ cp_parser_gnu_attributes_opt (cp_parser* parser) return attributes; } +/* Returns true of NAME is an IDENTIFIER_NODE with identiifer "vector," + "__vector" or "__vector__." */ + +static inline bool +is_cilkplus_vector_p (tree name) +{ + if (flag_enable_cilkplus && is_attribute_p ("vector", name)) + return true; + return false; +} + /* Parse a GNU attribute-list. attribute-list: @@ -21495,8 +21586,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser) { tree arguments = NULL_TREE; - /* Consume the token. */ - token = cp_lexer_consume_token (parser->lexer); + /* Consume the token, but save it since we need it for the + SIMD enabled function parsing. */ + cp_token *id_token = cp_lexer_consume_token (parser->lexer); /* Save away the identifier that indicates which attribute this is. */ @@ -21504,7 +21596,7 @@ cp_parser_gnu_attribute_list (cp_parser* parser) /* For keywords, use the canonical spelling, not the parsed identifier. */ ? ridpointers[(int) token->keyword] - : token->u.value; + : id_token->u.value; attribute = build_tree_list (identifier, NULL_TREE); @@ -21516,10 +21608,16 @@ cp_parser_gnu_attribute_list (cp_parser* parser) vec *vec; int attr_flag = (attribute_takes_identifier_p (identifier) ? id_attr : normal_attr); - vec = cp_parser_parenthesized_expression_list - (parser, attr_flag, /*cast_p=*/false, - /*allow_expansion_p=*/false, - /*non_constant_p=*/NULL); + if (is_cilkplus_vector_p (identifier)) + { + cp_parser_cilk_simd_fn_vector_attrs (parser, id_token); + continue; + } + else + vec = cp_parser_parenthesized_expression_list + (parser, attr_flag, /*cast_p=*/false, + /*allow_expansion_p=*/false, + /*non_constant_p=*/NULL); if (vec == NULL) arguments = error_mark_node; else @@ -21530,6 +21628,11 @@ cp_parser_gnu_attribute_list (cp_parser* parser) /* Save the arguments away. */ TREE_VALUE (attribute) = arguments; } + else if (is_cilkplus_vector_p (identifier)) + { + cp_parser_cilk_simd_fn_vector_attrs (parser, id_token); + continue; + } if (arguments != error_mark_node) { @@ -26809,12 +26912,16 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_MAP; else if (!strcmp ("mergeable", p)) result = PRAGMA_OMP_CLAUSE_MERGEABLE; + else if (flag_enable_cilkplus && !strcmp ("mask", p)) + result = PRAGMA_CILK_CLAUSE_MASK; break; case 'n': if (!strcmp ("notinbranch", p)) result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; else if (!strcmp ("nowait", p)) result = PRAGMA_OMP_CLAUSE_NOWAIT; + else if (flag_enable_cilkplus && !strcmp ("nomask", p)) + result = PRAGMA_CILK_CLAUSE_NOMASK; else if (!strcmp ("num_teams", p)) result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; else if (!strcmp ("num_threads", p)) @@ -26860,6 +26967,10 @@ cp_parser_omp_clause_name (cp_parser *parser) else if (!strcmp ("untied", p)) result = PRAGMA_OMP_CLAUSE_UNTIED; break; + case 'v': + if (flag_enable_cilkplus && !strcmp ("vectorlength", p)) + result = PRAGMA_CILK_CLAUSE_VECTORLENGTH; + break; } } @@ -27612,7 +27723,8 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list) linear ( variable-list : expression ) */ static tree -cp_parser_omp_clause_linear (cp_parser *parser, tree list) +cp_parser_omp_clause_linear (cp_parser *parser, tree list, + bool is_cilk_simd_fn) { tree nlist, c, step = integer_one_node; bool colon; @@ -27627,6 +27739,11 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list) { step = cp_parser_expression (parser, false, NULL); + if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL) + { + sorry ("using parameters for % step is not supported yet"); + step = integer_one_node; + } if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -27948,6 +28065,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, tree clauses = NULL; bool first = true; cp_token *token = NULL; + bool cilk_simd_fn = false; while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { @@ -28044,11 +28162,13 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, c_name = "untied"; break; case PRAGMA_OMP_CLAUSE_INBRANCH: + case PRAGMA_CILK_CLAUSE_MASK: clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH, clauses, token->location); c_name = "inbranch"; break; case PRAGMA_OMP_CLAUSE_NOTINBRANCH: + case PRAGMA_CILK_CLAUSE_NOMASK: clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH, clauses, token->location); @@ -28117,7 +28237,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, c_name = "aligned"; break; case PRAGMA_OMP_CLAUSE_LINEAR: - clauses = cp_parser_omp_clause_linear (parser, clauses); + if (((mask >> PRAGMA_CILK_CLAUSE_VECTORLENGTH) & 1) != 0) + cilk_simd_fn = true; + clauses = cp_parser_omp_clause_linear (parser, clauses, cilk_simd_fn); c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: @@ -28153,6 +28275,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, token->location); c_name = "simdlen"; break; + case PRAGMA_CILK_CLAUSE_VECTORLENGTH: + clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, true); + c_name = "simdlen"; + break; default: cp_parser_error (parser, "expected %<#pragma omp%> clause"); goto saw_error; @@ -28169,7 +28295,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, } } saw_error: - cp_parser_skip_to_pragma_eol (parser, pragma_tok); + /* In Cilk Plus SIMD enabled functions there is no pragma_token, so + no reason to skip to the end. */ + if (!(flag_enable_cilkplus && pragma_tok == NULL)) + cp_parser_skip_to_pragma_eol (parser, pragma_tok); if (finish_p) return finish_omp_clauses (clauses); return clauses; @@ -30171,6 +30300,63 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, } } +/* Handles the delayed parsing of the Cilk Plus SIMD-enabled function. + This function is modelled similar to the late parsing of omp declare + simd. */ + +static tree +cp_parser_late_parsing_cilk_simd_fn_info (cp_parser *parser, tree attrs) +{ + struct cp_token_cache *ce; + cp_omp_declare_simd_data *info = parser->cilk_simd_fn_info; + int ii = 0; + + if (parser->omp_declare_simd != NULL) + { + error ("%<#pragma omp declare simd%> cannot be used in the same function" + " marked as a Cilk Plus SIMD-enabled function"); + XDELETE (parser->cilk_simd_fn_info); + parser->cilk_simd_fn_info = NULL; + return attrs; + } + if (!info->error_seen && info->fndecl_seen) + { + error ("vector attribute not immediately followed by a single function" + " declaration or definition"); + info->error_seen = true; + } + if (info->error_seen) + return attrs; + + FOR_EACH_VEC_ELT (info->tokens, ii, ce) + { + tree c, cl; + + cp_parser_push_lexer_for_tokens (parser, ce); + parser->lexer->in_pragma = true; + cl = cp_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK, + "SIMD-enabled functions attribute", + NULL); + cp_parser_pop_lexer (parser); + if (cl) + cl = tree_cons (NULL_TREE, cl, NULL_TREE); + + c = build_tree_list (get_identifier ("cilk simd function"), NULL_TREE); + TREE_CHAIN (c) = attrs; + attrs = c; + + c = build_tree_list (get_identifier ("omp declare simd"), cl); + TREE_CHAIN (c) = attrs; + if (processing_template_decl) + ATTR_IS_DEPENDENT (c) = 1; + attrs = c; + } + info->fndecl_seen = true; + XDELETE (parser->cilk_simd_fn_info); + parser->cilk_simd_fn_info = NULL; + return attrs; +} + /* Finalize #pragma omp declare simd clauses after direct declarator has been parsed, and put that into "omp declare simd" attribute. */ @@ -31351,35 +31537,63 @@ c_parse_file (void) the_parser = NULL; } -/* Parses the Cilk Plus #pragma simd vectorlength clause: +/* Parses the Cilk Plus #pragma simd and SIMD-enabled function attribute's + vectorlength clause: Syntax: vectorlength ( constant-expression ) */ static tree -cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses) +cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses, + bool is_simd_fn) { location_t loc = cp_lexer_peek_token (parser->lexer)->location; tree expr; - /* The vectorlength clause behaves exactly like OpenMP's safelen - clause. Thus, vectorlength is represented as OMP 4.0 - safelen. */ - check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc); - + /* The vectorlength clause in #pragma simd behaves exactly like OpenMP's + safelen clause. Thus, vectorlength is represented as OMP 4.0 + safelen. For SIMD-enabled function it is represented by OMP 4.0 + simdlen. */ + if (!is_simd_fn) + check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", + loc); + else + check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength", + loc); + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return error_mark_node; expr = cp_parser_constant_expression (parser, false, NULL); expr = maybe_constant_value (expr); - - if (TREE_CONSTANT (expr) + + /* If expr == error_mark_node, then don't emit any errors nor + create a clause. if any of the above functions returns + error mark node then they would have emitted an error message. */ + if (expr == error_mark_node) + ; + else if (!TREE_TYPE (expr) + || !TREE_CONSTANT (expr) + || !INTEGRAL_TYPE_P (TREE_TYPE (expr))) + error_at (loc, "vectorlength must be an integer constant"); + else if (TREE_CONSTANT (expr) && exact_log2 (TREE_INT_CST_LOW (expr)) == -1) error_at (loc, "vectorlength must be a power of 2"); - else if (expr != error_mark_node) + else { - tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); - OMP_CLAUSE_SAFELEN_EXPR (c) = expr; - OMP_CLAUSE_CHAIN (c) = clauses; - clauses = c; + tree c; + if (!is_simd_fn) + { + c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (c) = expr; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + else + { + c = build_omp_clause (loc, OMP_CLAUSE_SIMDLEN); + OMP_CLAUSE_SIMDLEN_EXPR (c) = expr; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } } if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) @@ -31542,7 +31756,7 @@ cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token) pragma_omp_clause c_kind; c_kind = cp_parser_cilk_simd_clause_name (parser); if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH) - clauses = cp_parser_cilk_simd_vectorlength (parser, clauses); + clauses = cp_parser_cilk_simd_vectorlength (parser, clauses, false); else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR) clauses = cp_parser_cilk_simd_linear (parser, clauses); else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE) diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 484a8cd..d558c60 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -362,6 +362,13 @@ typedef struct GTY(()) cp_parser { data structure with everything needed for parsing the clauses. */ cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd; + /* When parsing the vector attribute in Cilk Plus SIMD-enabled function, + this is a pointer to data structure with everything needed for parsing + the clauses. The cp_omp_declare_simd_data struct will hold all the + necessary information, so creating another struct for this is not + necessary. */ + cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info; + /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit template parameter. */ bool auto_is_implicit_function_template_parm_p; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2e7cf60..a91df4c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8613,7 +8613,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, { *p = TREE_CHAIN (t); TREE_CHAIN (t) = NULL_TREE; - if (flag_openmp + if ((flag_openmp || flag_enable_cilkplus) && is_attribute_p ("omp declare simd", get_attribute_name (t)) && TREE_VALUE (t)) diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c index ab55fae..195e9f1 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c @@ -1,9 +1,9 @@ /* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-fcilkplus -Wall" } */ -__attribute__((vector (linear (x:y)))) +__attribute__((vector (linear (x:y)))) /* { dg-message "parameter" "" { target c++ } } */ int func2 (int x, int y) -{ /* { dg-message "using parameters for" } */ +{ /* { dg-message "using parameters for" "" { target c } } */ return (x+y); } diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c index 38d610a..1bcf2a2 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c @@ -5,7 +5,8 @@ int z = Q; -__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { dg-error "expected expression" } */ +__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { dg-error "expected expression" "" { target c } } */ + /* { dg-error "expected primary-expression" "" { target c++ } 8 } */ int func2 (int x, int y) { int zq = 5; @@ -19,7 +20,8 @@ int func3 (int x, int y) return x + (y*zq); } -__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { dg-error "vectorlength must be an integer" } */ +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { dg-error "vectorlength must be an integer" "" { target c } } */ + /* { dg-error "constant" "" { target c++ } 23 } */ int func4 (int x, int y) { int zq = 5; @@ -33,7 +35,8 @@ int func5 (int x, int y) return x + (y*zq); } -__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { dg-error "vectorlength must be an integer" } */ +__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { dg-error "vectorlength must be an integer" "" { target c } } */ + /* { dg-error "constant" "" { target c++ } 38 } */ int func6 (int x, int y) { int zq = 5; diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp index 37b8ccb..204a754 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -33,6 +33,9 @@ set TEST_EXTRA_LIBS "-L${library_var}/libcilkrts/.libs" dg-init # Run the tests that are shared with C. g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] "" +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] "-O3" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " " " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] "-g -O2" " " # Run the C++ only tests. g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" dg-finish diff --git a/gcc/testsuite/g++.dg/cilk-plus/ef_test.C b/gcc/testsuite/g++.dg/cilk-plus/ef_test.C new file mode 100644 index 0000000..3e75cbd --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/ef_test.C @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + + +__attribute__((vector (nomask), vector(mask), vector(mask,linear(x:1)))) +int func (int x) +{ + return x+5; +} + + +__attribute__((vector(mask,uniform (y), linear(x:1)))) +__attribute__((vector (nomask, uniform (x), linear(y:1)))) +int func2 (int x, int y) +{ + return x+y; +} + +int func4 (int x, int y) __attribute__((vector, vector (nomask), vector (uniform(y), linear(x:1)))); + + +template +__attribute__((vector, vector(mask,uniform (y), linear(x:1)))) +T func3 (T x, R y) +{ + return x+(T)y; +} + + + +int main (void) +{ + if ((func3 (5, 4) + func2 (5, 4) + func (5) + (int) func3 (5, 4)) != + (5 + 4) + (5 + 4) + (5 + 5) + (int) ((long)5 +(int)4)) + __builtin_abort (); + return 0; +}