From 41958c2823a16a91e548b6d24178ae18bc203918 Mon Sep 17 00:00:00 2001 From: "Balaji V. Iyer" Date: Wed, 18 Dec 2013 19:00:21 +0000 Subject: [PATCH] Added support for Cilk Plus SIMD-enabled function for C. +++ gcc/ChangeLog +2013-12-18 Balaji V. Iyer + + * omp-low.c (simd_clone_clauses_extract): Replaced the string + "cilk simd elemental" with "cilk simd function." + * config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen): + Removed a carriage-return from a warning string. + +++ gcc/c-family/ChangeLog +2013-12-18 Balaji V. Iyer + + * c-common.c (c_common_attribute_table): Added "cilk simd function" + attribute. + * c-pragma.h (enum pragma_cilk_clause): Remove. + (enum pragma_omp_clause): Added the following fields: + PRAGMA_CILK_CLAUSE_NOMASK, PRAGMA_CILK_CLAUSE_MASK, + PRAGMA_CILK_CLAUSE_VECTORLENGTH, PRAGMA_CILK_CLAUSE_NONE, + PRAGMA_CILK_CLAUSE_LINEAR, PRAGMA_CILK_CLAUSE_PRIVATE, + PRAGMA_CILK_CLAUSE_FIRSTPRIVATE, PRAGMA_CILK_CLAUSE_LASTPRIVATE, + PRAGMA_CILK_CLAUSE_UNIFORM. + + +++ gcc/c/ChangeLog +2013-12-18 Balaji V. Iyer + + * c-parser.c (struct c_parser::cilk_simd_fn_tokens): Added new field. + (c_parser_declaration_or_fndef): Added a check if cilk_simd_fn_tokens + field in parser is not empty. If not-empty, call the function + c_parser_finish_omp_declare_simd. + (c_parser_cilk_clause_vectorlength): Modified function to be shared + between SIMD-enabled functions and #pragma simd. Added new parameter. + (c_parser_cilk_all_clauses): Modified the usage of the function + c_parser_cilk_clause_vectorlength as mentioned above. + (c_parser_cilk_simd_fn_vector_attrs): New function. + (c_finish_cilk_simd_fn_tokens): Likewise. + (is_cilkplus_vector_p): Likewise. + (c_parser_omp_clause_name): Added checking for "vectorlength," + "nomask," and "mask" strings in clause name. + (c_parser_omp_all_clauses): Added 3 new case statements: + PRAGMA_CILK_CLAUSE_VECTORLENGTH, PRAGMA_CILK_CLAUSE_MASK and + PRAGMA_CILK_CLAUSE_NOMASK. + (c_parser_attributes): Added a cilk_simd_fn_tokens parameter. Added a + check for vector attribute and if so call the function + c_parser_cilk_simd_fn_vector_attrs. Also, when Cilk plus is enabled, + called the function c_finish_cilk_simd_fn_tokens. + (c_finish_omp_declare_simd): Added a check if cilk_simd_fn_tokens in + parser field is non-empty. If so, parse them as you would parse + the omp declare simd pragma. + (c_parser_omp_clause_linear): Added a new bool parm. is_cilk_simd_fn. + Added a check when step is a parameter and flag it as error. + (CILK_SIMD_FN_CLAUSE_MASK): New #define. + (c_parser_cilk_clause_name): Changed pragma_cilk_clause to + pragma_omp_clause. + +++ gcc/testsuite/ChangeLog +2013-12-18 Balaji V. Iyer + + * c-c++-common/cilk-plus/SE/ef_test.c: New test. + * c-c++-common/cilk-plus/SE/ef_test2.c: Likewise. + * c-c++-common/cilk-plus/SE/vlength_errors.c: Likewise. + * c-c++-common/cilk-plus/SE/ef_error.c: Likewise. + * c-c++-common/cilk-plus/SE/ef_error2.c: Likewise. + * c-c++-common/cilk-plus/SE/ef_error3.c: Likewise. + * gcc.dg/cilk-plus/cilk-plus.exp: Added calls for the above tests. + From-SVN: r206095 --- gcc/ChangeLog | 7 + gcc/c-family/ChangeLog | 13 ++ gcc/c-family/c-common.c | 2 + gcc/c-family/c-pragma.h | 25 +- gcc/c/ChangeLog | 31 +++ gcc/c/c-parser.c | 257 ++++++++++++++++++--- gcc/config/i386/i386.c | 2 +- gcc/cp/parser.c | 6 +- gcc/omp-low.c | 2 +- gcc/testsuite/ChangeLog | 10 + gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c | 32 +++ .../c-c++-common/cilk-plus/SE/ef_error2.c | 14 ++ .../c-c++-common/cilk-plus/SE/ef_error3.c | 13 ++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c | 78 +++++++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c | 16 ++ .../c-c++-common/cilk-plus/SE/vlength_errors.c | 56 +++++ gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp | 4 + 17 files changed, 517 insertions(+), 51 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c create mode 100644 gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c create mode 100644 gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c create mode 100644 gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c create mode 100644 gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c create mode 100644 gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b83157f..7f77d8a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2013-12-18 Balaji V. Iyer + + * omp-low.c (simd_clone_clauses_extract): Replaced the string + "cilk simd elemental" with "cilk simd function." + * config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen): + Removed a carriage-return from a warning string. + 2013-12-18 Aldy Hernandez * passes.c (execute_function_dump): Set graph_dump_initialized diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 462b4b1..ffd8eff 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,16 @@ +2013-12-18 Balaji V. Iyer + + * c-common.c (c_common_attribute_table): Added "cilk simd function" + attribute. + * c-pragma.h (enum pragma_cilk_clause): Remove. + (enum pragma_omp_clause): Added the following fields: + PRAGMA_CILK_CLAUSE_NOMASK, PRAGMA_CILK_CLAUSE_MASK, + PRAGMA_CILK_CLAUSE_VECTORLENGTH, PRAGMA_CILK_CLAUSE_NONE, + PRAGMA_CILK_CLAUSE_LINEAR, PRAGMA_CILK_CLAUSE_PRIVATE, + PRAGMA_CILK_CLAUSE_FIRSTPRIVATE, PRAGMA_CILK_CLAUSE_LASTPRIVATE, + PRAGMA_CILK_CLAUSE_UNIFORM. + + 2013-12-11 Balaji V. Iyer * cilk.c (cilk_outline): Made this function non-static. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index cfaeaf0..229f8fa 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -762,6 +762,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_returns_nonnull_attribute, false }, { "omp declare simd", 0, -1, true, false, false, handle_omp_declare_simd_attribute, false }, + { "cilk simd function", 0, -1, true, false, false, + handle_omp_declare_simd_attribute, false }, { "omp declare target", 0, 0, true, false, false, handle_omp_declare_target_attribute, false }, { NULL, 0, 0, false, false, false, NULL, false } diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 5379b9e..683b3f8 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -103,19 +103,20 @@ typedef enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_THREAD_LIMIT, PRAGMA_OMP_CLAUSE_TO, PRAGMA_OMP_CLAUSE_UNIFORM, - PRAGMA_OMP_CLAUSE_UNTIED -} pragma_omp_clause; - -/* All Cilk Plus #pragma omp clauses. */ -typedef enum pragma_cilk_clause { - PRAGMA_CILK_CLAUSE_NONE = 0, + PRAGMA_OMP_CLAUSE_UNTIED, + + /* Clauses for Cilk Plus SIMD-enabled function. */ + PRAGMA_CILK_CLAUSE_NOMASK, + PRAGMA_CILK_CLAUSE_MASK, PRAGMA_CILK_CLAUSE_VECTORLENGTH, - PRAGMA_CILK_CLAUSE_LINEAR, - PRAGMA_CILK_CLAUSE_PRIVATE, - PRAGMA_CILK_CLAUSE_FIRSTPRIVATE, - PRAGMA_CILK_CLAUSE_LASTPRIVATE, - PRAGMA_CILK_CLAUSE_REDUCTION -} pragma_cilk_clause; + PRAGMA_CILK_CLAUSE_NONE = PRAGMA_OMP_CLAUSE_NONE, + PRAGMA_CILK_CLAUSE_LINEAR = PRAGMA_OMP_CLAUSE_LINEAR, + PRAGMA_CILK_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE, + PRAGMA_CILK_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, + PRAGMA_CILK_CLAUSE_LASTPRIVATE = PRAGMA_OMP_CLAUSE_LASTPRIVATE, + PRAGMA_CILK_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION, + PRAGMA_CILK_CLAUSE_UNIFORM = PRAGMA_OMP_CLAUSE_UNIFORM +} pragma_omp_clause; extern struct cpp_reader* parse_in; diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 9db78c6..58631ee 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,34 @@ +2013-12-18 Balaji V. Iyer + + * c-parser.c (struct c_parser::cilk_simd_fn_tokens): Added new field. + (c_parser_declaration_or_fndef): Added a check if cilk_simd_fn_tokens + field in parser is not empty. If not-empty, call the function + c_parser_finish_omp_declare_simd. + (c_parser_cilk_clause_vectorlength): Modified function to be shared + between SIMD-enabled functions and #pragma simd. Added new parameter. + (c_parser_cilk_all_clauses): Modified the usage of the function + c_parser_cilk_clause_vectorlength as mentioned above. + (c_parser_cilk_simd_fn_vector_attrs): New function. + (c_finish_cilk_simd_fn_tokens): Likewise. + (is_cilkplus_vector_p): Likewise. + (c_parser_omp_clause_name): Added checking for "vectorlength," + "nomask," and "mask" strings in clause name. + (c_parser_omp_all_clauses): Added 3 new case statements: + PRAGMA_CILK_CLAUSE_VECTORLENGTH, PRAGMA_CILK_CLAUSE_MASK and + PRAGMA_CILK_CLAUSE_NOMASK. + (c_parser_attributes): Added a cilk_simd_fn_tokens parameter. Added a + check for vector attribute and if so call the function + c_parser_cilk_simd_fn_vector_attrs. Also, when Cilk plus is enabled, + called the function c_finish_cilk_simd_fn_tokens. + (c_finish_omp_declare_simd): Added a check if cilk_simd_fn_tokens in + parser field is non-empty. If so, parse them as you would parse + the omp declare simd pragma. + (c_parser_omp_clause_linear): Added a new bool parm. is_cilk_simd_fn. + Added a check when step is a parameter and flag it as error. + (CILK_SIMD_FN_CLAUSE_MASK): New #define. + (c_parser_cilk_clause_name): Changed pragma_cilk_clause to + pragma_omp_clause. + 2013-12-17 Thomas Schwinge * c-parser.c (c_parser_omp_parallel): Fix description. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 28f53c1..5dd953d 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -208,6 +208,12 @@ typedef struct GTY(()) c_parser { /* True if we are in a context where the Objective-C "Property attribute" keywords are valid. */ BOOL_BITFIELD objc_property_attr_context : 1; + + /* Cilk Plus specific parser/lexer information. */ + + /* Buffer to hold all the tokens from parsing the vector attribute for the + SIMD-enabled functions (formerly known as elemental functions). */ + vec *cilk_simd_fn_tokens; } c_parser; @@ -1245,6 +1251,7 @@ static bool c_parser_objc_diagnose_bad_element_prefix static void c_parser_cilk_simd (c_parser *); static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context); static tree c_parser_array_notation (location_t, c_parser *, tree, tree); +static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool); /* Parse a translation unit (C90 6.7, C99 6.9). @@ -1646,7 +1653,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, C_DTR_NORMAL, &dummy); if (declarator == NULL) { - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE, omp_declare_simd_clauses); c_parser_skip_to_end_of_block_or_statement (parser); @@ -1733,7 +1741,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); } @@ -1745,7 +1754,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); start_init (d, asm_name, global_bindings_p ()); @@ -1773,7 +1783,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, tree d = start_decl (declarator, specs, false, chainon (postfix_attrs, all_prefix_attrs)); - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) { tree parms = NULL_TREE; if (d && TREE_CODE (d) == FUNCTION_DECL) @@ -1901,7 +1912,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_parser_declaration_or_fndef (parser, false, false, false, true, false, NULL, vNULL); store_parm_decls (); - if (omp_declare_simd_clauses.exists ()) + if (omp_declare_simd_clauses.exists () + || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, omp_declare_simd_clauses); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus @@ -3765,6 +3777,87 @@ c_parser_attribute_any_word (c_parser *parser) return attr_name; } +/* 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; +} + +#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 vector attribute of SIMD enabled functions in Cilk Plus. + VEC_TOKEN is the "vector" token that is replaced with "simd" and + pushed into the token list. + Syntax: + vector + vector (). */ + +static void +c_parser_cilk_simd_fn_vector_attrs (c_parser *parser, c_token vec_token) +{ + gcc_assert (is_cilkplus_vector_p (vec_token.value)); + + int paren_scope = 0; + vec_safe_push (parser->cilk_simd_fn_tokens, vec_token); + /* Consume the "vector" token. */ + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + paren_scope++; + } + while (paren_scope > 0) + { + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_OPEN_PAREN) + paren_scope++; + else if (token->type == CPP_CLOSE_PAREN) + paren_scope--; + /* Do not push the last ')' since we are not pushing the '('. */ + if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0)) + vec_safe_push (parser->cilk_simd_fn_tokens, *token); + c_parser_consume_token (parser); + } + + /* Since we are converting an attribute to a pragma, we need to end the + attribute with PRAGMA_EOL. */ + c_token eol_token; + memset (&eol_token, 0, sizeof (eol_token)); + eol_token.type = CPP_PRAGMA_EOL; + vec_safe_push (parser->cilk_simd_fn_tokens, eol_token); +} + +/* Add 2 CPP_EOF at the end of PARSER->ELEM_FN_TOKENS vector. */ + +static void +c_finish_cilk_simd_fn_tokens (c_parser *parser) +{ + c_token last_token = parser->cilk_simd_fn_tokens->last (); + + /* c_parser_attributes is called in several places, so if these EOF + tokens are already inserted, then don't do them again. */ + if (last_token.type == CPP_EOF) + return; + + /* Two CPP_EOF token are added as a safety net since the normal C + front-end has two token look-ahead. */ + c_token eof_token; + eof_token.type = CPP_EOF; + vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); + vec_safe_push (parser->cilk_simd_fn_tokens, eof_token); +} + /* Parse (possibly empty) attributes. This is a GNU extension. attributes: @@ -3829,6 +3922,12 @@ c_parser_attributes (c_parser *parser) attr_name = c_parser_attribute_any_word (parser); if (attr_name == NULL) break; + if (is_cilkplus_vector_p (attr_name)) + { + c_token *v_token = c_parser_peek_token (parser); + c_parser_cilk_simd_fn_vector_attrs (parser, *v_token); + continue; + } c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) { @@ -3909,6 +4008,9 @@ c_parser_attributes (c_parser *parser) } parser->lex_untranslated_string = false; } + + if (flag_enable_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + c_finish_cilk_simd_fn_tokens (parser); return attrs; } @@ -9524,6 +9626,8 @@ c_parser_omp_clause_name (c_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)) @@ -9534,6 +9638,8 @@ c_parser_omp_clause_name (c_parser *parser) result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; else if (!strcmp ("num_threads", p)) result = PRAGMA_OMP_CLAUSE_NUM_THREADS; + else if (flag_enable_cilkplus && !strcmp ("nomask", p)) + result = PRAGMA_CILK_CLAUSE_NOMASK; break; case 'o': if (!strcmp ("ordered", p)) @@ -9577,6 +9683,10 @@ c_parser_omp_clause_name (c_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; } } @@ -10393,7 +10503,7 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) linear ( variable-list : expression ) */ static tree -c_parser_omp_clause_linear (c_parser *parser, tree list) +c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c, step; @@ -10410,6 +10520,11 @@ c_parser_omp_clause_linear (c_parser *parser, tree list) step = c_parser_expression (parser).value; mark_exp_read (step); step = c_fully_fold (step, 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 (!INTEGRAL_TYPE_P (TREE_TYPE (step))) { error_at (clause_loc, "% clause step expression must " @@ -10768,7 +10883,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, const char *where, bool finish_p = true) { tree clauses = NULL; - bool first = true; + bool first = true, cilk_simd_fn = false; while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { @@ -10854,11 +10969,13 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, c_name = "untied"; break; case PRAGMA_OMP_CLAUSE_INBRANCH: + case PRAGMA_CILK_CLAUSE_MASK: clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH, clauses); c_name = "inbranch"; break; case PRAGMA_OMP_CLAUSE_NOTINBRANCH: + case PRAGMA_CILK_CLAUSE_NOMASK: clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH, clauses); c_name = "notinbranch"; @@ -10924,8 +11041,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_aligned (parser, clauses); c_name = "aligned"; break; - case PRAGMA_OMP_CLAUSE_LINEAR: - clauses = c_parser_omp_clause_linear (parser, clauses); + case PRAGMA_OMP_CLAUSE_LINEAR: + if (((mask >> PRAGMA_CILK_CLAUSE_VECTORLENGTH) & 1) != 0) + cilk_simd_fn = true; + clauses = c_parser_omp_clause_linear (parser, clauses, cilk_simd_fn); c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: @@ -10952,6 +11071,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_safelen (parser, clauses); c_name = "safelen"; break; + case PRAGMA_CILK_CLAUSE_VECTORLENGTH: + clauses = c_parser_cilk_clause_vectorlength (parser, clauses, true); + c_name = "simdlen"; + break; case PRAGMA_OMP_CLAUSE_SIMDLEN: clauses = c_parser_omp_clause_simdlen (parser, clauses); c_name = "simdlen"; @@ -12727,10 +12850,19 @@ static void c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, vec clauses) { + if (flag_enable_cilkplus + && clauses.exists () && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + { + error ("%<#pragma omp declare simd%> cannot be used in the same " + "function marked as a Cilk Plus SIMD-enabled function"); + vec_free (parser->cilk_simd_fn_tokens); + return; + } + /* Normally first token is CPP_NAME "simd". CPP_EOF there indicates error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd has already processed the tokens. */ - if (clauses[0].type == CPP_EOF) + if (clauses.exists () && clauses[0].type == CPP_EOF) return; if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL) { @@ -12739,7 +12871,7 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, clauses[0].type = CPP_EOF; return; } - if (clauses[0].type != CPP_NAME) + if (clauses.exists () && clauses[0].type != CPP_NAME) { error_at (DECL_SOURCE_LOCATION (fndecl), "%<#pragma omp declare simd%> not immediately followed by " @@ -12753,23 +12885,49 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, unsigned int tokens_avail = parser->tokens_avail; gcc_assert (parser->tokens == &parser->tokens_buf[0]); - parser->tokens = clauses.address (); - parser->tokens_avail = clauses.length (); - + bool is_cilkplus_cilk_simd_fn = false; + + if (flag_enable_cilkplus && !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + { + parser->tokens = parser->cilk_simd_fn_tokens->address (); + parser->tokens_avail = vec_safe_length (parser->cilk_simd_fn_tokens); + is_cilkplus_cilk_simd_fn = true; + } + else + { + parser->tokens = clauses.address (); + parser->tokens_avail = clauses.length (); + } + /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */ while (parser->tokens_avail > 3) { c_token *token = c_parser_peek_token (parser); - gcc_assert (token->type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); + if (!is_cilkplus_cilk_simd_fn) + gcc_assert (token->type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); + else + gcc_assert (token->type == CPP_NAME + && is_cilkplus_vector_p (token->value)); c_parser_consume_token (parser); parser->in_pragma = true; - tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, - "#pragma omp declare simd"); + tree c = NULL_TREE; + if (is_cilkplus_cilk_simd_fn) + c = c_parser_omp_all_clauses (parser, CILK_SIMD_FN_CLAUSE_MASK, + "SIMD-enabled functions attribute"); + else + c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, + "#pragma omp declare simd"); c = c_omp_declare_simd_clauses_to_numbers (parms, c); if (c != NULL_TREE) 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_CHAIN (k) = DECL_ATTRIBUTES (fndecl); + DECL_ATTRIBUTES (fndecl) = k; + } c = build_tree_list (get_identifier ("omp declare simd"), c); TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); DECL_ATTRIBUTES (fndecl) = c; @@ -12777,7 +12935,11 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, parser->tokens = &parser->tokens_buf[0]; parser->tokens_avail = tokens_avail; - clauses[0].type = CPP_PRAGMA; + if (clauses.exists ()) + clauses[0].type = CPP_PRAGMA; + + if (!vec_safe_is_empty (parser->cilk_simd_fn_tokens)) + vec_free (parser->cilk_simd_fn_tokens); } @@ -13370,14 +13532,26 @@ c_parser_cilk_verify_simd (c_parser *parser, } /* Cilk Plus: - vectorlength ( constant-expression ) */ + This function is shared by SIMD-enabled functions and #pragma simd. + If IS_SIMD_FN is true then it is parsing a SIMD-enabled function and + CLAUSES is unused. The main purpose of this function is to parse a + vectorlength attribute or clause and check for parse errors. + When IS_SIMD_FN is true then the function is merely caching the tokens + in PARSER->CILK_SIMD_FN_TOKENS. If errors are found then the token + cache is cleared since there is no reason to continue. + Syntax: + vectorlength ( constant-expression ) */ static tree -c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses) +c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, + bool is_simd_fn) { + if (is_simd_fn) + check_no_duplicate_clause (clauses, OMP_CLAUSE_SIMDLEN, "vectorlength"); + else /* The vectorlength clause behaves exactly like OpenMP's safelen clause. Represent it in OpenMP terms. */ - check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); + check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return clauses; @@ -13386,18 +13560,33 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses) tree expr = c_parser_expr_no_commas (parser, NULL).value; expr = c_fully_fold (expr, false, NULL); - if (!TREE_TYPE (expr) - || !TREE_CONSTANT (expr) - || !INTEGRAL_TYPE_P (TREE_TYPE (expr))) - error_at (loc, "vectorlength must be an integer constant"); + /* If expr is an error_mark_node then the above function would have + emitted an error. No reason to do it twice. */ + 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 (exact_log2 (TREE_INT_CST_LOW (expr)) == -1) error_at (loc, "vectorlength must be a power of 2"); else { - tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); - OMP_CLAUSE_SAFELEN_EXPR (u) = expr; - OMP_CLAUSE_CHAIN (u) = clauses; - clauses = u; + if (is_simd_fn) + { + tree u = build_omp_clause (loc, OMP_CLAUSE_SIMDLEN); + OMP_CLAUSE_SIMDLEN_EXPR (u) = expr; + OMP_CLAUSE_CHAIN (u) = clauses; + clauses = u; + } + else + { + tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (u) = expr; + OMP_CLAUSE_CHAIN (u) = clauses; + clauses = u; + } } c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -13494,10 +13683,10 @@ c_parser_cilk_clause_linear (c_parser *parser, tree clauses) not consumed. Otherwise, the appropriate pragma_simd_clause is returned and the token is consumed. */ -static pragma_cilk_clause +static pragma_omp_clause c_parser_cilk_clause_name (c_parser *parser) { - pragma_cilk_clause result; + pragma_omp_clause result; c_token *token = c_parser_peek_token (parser); if (!token->value || token->type != CPP_NAME) @@ -13534,14 +13723,14 @@ c_parser_cilk_all_clauses (c_parser *parser) while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - pragma_cilk_clause c_kind; + pragma_omp_clause c_kind; c_kind = c_parser_cilk_clause_name (parser); switch (c_kind) { case PRAGMA_CILK_CLAUSE_VECTORLENGTH: - clauses = c_parser_cilk_clause_vectorlength (parser, clauses); + clauses = c_parser_cilk_clause_vectorlength (parser, clauses, false); break; case PRAGMA_CILK_CLAUSE_LINEAR: clauses = c_parser_cilk_clause_linear (parser, clauses); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ecf5e0b..0be671d 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -43860,7 +43860,7 @@ ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node, || (clonei->simdlen & (clonei->simdlen - 1)) != 0)) { warning_at (DECL_SOURCE_LOCATION (node->decl), 0, - "unsupported simdlen %d\n", clonei->simdlen); + "unsupported simdlen %d", clonei->simdlen); return 0; } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9f8ad39..2a2cbf0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -31478,10 +31478,10 @@ cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses) token is not consumed. Otherwise, the appropriate enum from the pragma_simd_clause is returned and the token is consumed. */ -static pragma_cilk_clause +static pragma_omp_clause cp_parser_cilk_simd_clause_name (cp_parser *parser) { - pragma_cilk_clause clause_type; + pragma_omp_clause clause_type; cp_token *token = cp_lexer_peek_token (parser->lexer); if (token->keyword == RID_PRIVATE) @@ -31515,7 +31515,7 @@ cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token) while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL) && clauses != error_mark_node) { - pragma_cilk_clause c_kind; + 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); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 2398a96..aacee38 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -10688,7 +10688,7 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, declare simd". */ bool cilk_clone = (flag_enable_cilkplus - && lookup_attribute ("cilk plus elemental", + && lookup_attribute ("cilk simd function", DECL_ATTRIBUTES (node->decl))); /* Allocate one more than needed just in case this is an in-branch diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 20a1bc5..f4e055f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2013-12-18 Balaji V. Iyer + + * c-c++-common/cilk-plus/SE/ef_test.c: New test. + * c-c++-common/cilk-plus/SE/ef_test2.c: Likewise. + * c-c++-common/cilk-plus/SE/vlength_errors.c: Likewise. + * c-c++-common/cilk-plus/SE/ef_error.c: Likewise. + * c-c++-common/cilk-plus/SE/ef_error2.c: Likewise. + * c-c++-common/cilk-plus/SE/ef_error3.c: Likewise. + * gcc.dg/cilk-plus/cilk-plus.exp: Added calls for the above tests. + 2013-12-18 Jakub Jelinek PR target/59539 diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c new file mode 100644 index 0000000..6a4b4a4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -fopenmp" } */ + +#pragma omp declare simd linear(y:1) simdlen(4) +__attribute__((vector (linear (y:1), vectorlength(4)))) +int func (int x, int y) { /* { dg-error "cannot be used in the same function marked as a Cilk Plus SIMD-enabled" } */ + return (x+y); +} +__attribute__((vector (linear (y:1), private (x)))) /* { dg-error "is not valid for" } */ +int func2 (int x, int y) { + return (x+y); +} + +__attribute__((vector (linear (y:1), simdlen (4)))) /* { dg-error "is not valid for" } */ +int func2_1 (int x, int y) { + return (x+y); +} + +__attribute__((vector (linear (y:1), inbranch))) /* { dg-error "is not valid for" } */ +int func2_3 (int x, int y) { + return (x+y); +} + +__attribute__((vector (notinbranch, vectorlength (4)))) /* { dg-error "is not valid for" } */ +int func2_2 (int x, int y) { + return (x+y); +} + +int main (void) +{ + return (func (5,6)); +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c new file mode 100644 index 0000000..518d640 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus -Wall" } */ + +__attribute__((vector (vectorlength(32)))) +//#pragma omp simd simdlen (32) +int func2 (int x, int y) /* { dg-warning "unsupported simdlen" } */ +{ + return (x+y); +} + +int main (void) +{ + return (func2 (5,6)); +} 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 new file mode 100644 index 0000000..ab55fae --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error3.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus -Wall" } */ + +__attribute__((vector (linear (x:y)))) +int func2 (int x, int y) +{ /* { dg-message "using parameters for" } */ + return (x+y); +} + +int main (void) +{ + return (func2 (5,6)); +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c new file mode 100644 index 0000000..e606acac --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c @@ -0,0 +1,78 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -Wunknown-pragmas" } */ + +/* Tests the clauses in several combinations put in different locations. */ +/* This is mostly a parser test. */ +#define Q 4 + +int z = Q; + + __attribute__ ((vector (uniform(x), linear (y:1), vectorlength (4) ))) +int func (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + __attribute__ ((__vector__ (uniform(x), vectorlength (2), linear (y:1) ))) +int func2 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(y), linear (x), vectorlength (4) ))) +int func3 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), mask))) +int func4 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), nomask))) +int func5 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), mask, linear (y:1)))) +int func6 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform (x), mask, linear (y:1)), vector)) +int func7 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform (x), mask, linear (y:1)), vector (uniform (y), mask))) +int func8 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector, vector (uniform (y), mask))) +int func9 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +int main (int argc, char *argv[]) +{ + int ii = 0, q = 5; + for (ii = 0; ii < 10; ii++) + q += func (argc, ii); + return q; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c new file mode 100644 index 0000000..7ec0578 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ +void func (int x, int y) __attribute__((vector(linear(x:1), uniform (y)), + vector)); + +int q; +int main (void) +{ + int ii = 0; + q = 5; + for (ii = 0; ii < 100; ii++) + func (ii, q); + + return 0; +} + 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 new file mode 100644 index 0000000..38d610a --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -Wunknown-pragmas" } */ + +#define Q 4 + +int z = Q; + +__attribute__ ((vector (uniform(x), vectorlength (), linear (y:1) ))) /* { dg-error "expected expression" } */ +int func2 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (4.5) ))) /* { dg-error "vectorlength must be an integer" } */ +int func3 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (z) ))) /* { dg-error "vectorlength must be an integer" } */ +int func4 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (Q) ))) /* This is OK! */ +int func5 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), vectorlength (z), linear (y:1)))) /* { dg-error "vectorlength must be an integer" } */ +int func6 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +__attribute__ ((vector (uniform(x), linear (y:1), vectorlength (sizeof (int)) ))) /* This is OK too! */ +int func7 (int x, int y) +{ + int zq = 5; + return x + (y*zq); +} + +int main (void) +{ + int ii = 0, q = 5; + for (ii = 0; ii < 10; ii++) + q += func2 (z, ii); + return q; +} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp index 39abbba..51c715d 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp @@ -60,6 +60,10 @@ if { [check_effective_target_lto] } { dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus" " " } +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -g" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -std=c99" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -O3 -g" " " + dg-finish unset TEST_EXTRA_LIBS -- 2.7.4