Hi Aldy & Jakub,
I have made the fixes you have mentioned and have answered your
questions below. Attached is the fixed patch and here are the ChangeLog entries.
Gcc/ChangeLog
2013-12-06 Balaji V. Iyer <[email protected]>
* omp-low.c (expand_simd_clones): Added a new parameter called "type."
(ipa_omp_simd_clone): Added a call to expand_simd_clones when Cilk Plus
is enabled.
(simd_clone_clauses_extract): Replaced the string "cilk simd elemental"
with "cilk simd function."
Gcc/c-family/Changelog
2013-12-06 Balaji V. Iyer <[email protected]>
* c-common.c (c_common_attribute_table): Added "cilk simd function"
attribute.
Gcc/c/ChangeLog
2013-12-06 Balaji V. Iyer <[email protected]>
* 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. Changed return-type
to bool and 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_expr_list): Likewise.
(c_finish_cilk_simd_fn_tokens): Likewise.
(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_expr_list. 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.
Gcc/testsuite/ChangeLog
2013-12-06 Balaji V. Iyer <[email protected]>
* 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.
* gcc.dg/cilk-plus/cilk-plus.exp: Added calls for the above tests.
Jakub, Is it Ok for branch?
Thanks,
Balaji V. Iyer.
> -----Original Message-----
> From: Aldy Hernandez [mailto:[email protected]]
> Sent: Thursday, December 5, 2013 3:20 PM
> To: Iyer, Balaji V
> Cc: 'Jakub Jelinek'; '[email protected]'
> Subject: Re: [PING]: [GOMP4] [PATCH] SIMD-Enabled Functions (formerly
> Elemental functions) for C
>
> On 11/30/13 20:38, Iyer, Balaji V wrote:
> > Hello Aldy,
> > Some of the middle end changes I made in the previous patch was
> not flying for the C++. Here is a fixed patch where the middle-end changes
> will work for both C and C++.
> > With this email, I am attaching the patch for C along with the middle
> end changes. Is this Ok for the branch?
>
> Jakub and company ultimately have to approve your patch, but here are a
> few things.
>
> > +
> > + /* 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 <c_token, va_gc> *elem_fn_tokens;
>
> If the name "elementals" is being phased out, then perhaps you need to
> come up with another name here. Perhaps "cilk_simd_clone_tokens" or
> something that looks similar to the OpenMP variant
> "cilk_declare_simd_tokens" (akin to omp_declare_simd_clauses) in the rest
> of the patch.
>
Fixed. I called it "cilk_simd_fn" instead of "elem_fn"
> Also, "Enabled" should not be capitalized.
>
Fixed.
> > +/* Parses the vectorlength vector attribute for the SIMD Enabled
> functions
> > + in Cilk Plus.
> > + Syntax:
> > + vectorlength (<integer constant expression>) */
> > +
> > +static bool
> > +c_parser_elem_fn_vectorlength (c_parser *parser)
>
> Similarly here. Let's get rid of *elem* nomenclature throughout.
> Perhaps c_parser_cilk_declare_simd_vectorlength and similarly throughout
> the other parsing routines in the patch. This will make it clearer that
> *cilk_declare_simd* is related to OpenMP's declare simd.
>
Fixed.
> > + if (TREE_CODE (value) != INTEGER_CST)
> > + {
> > + error_at (token->location, "vectorlength must be a constant
> > integer");
> > + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
> > + return false;
> > + }
>
> I thought integer constant expressions were allowed here. Shouldn't things
> like "sizeof (int)" be allowed? See what is done in
> c_parser_cilk_clause_vectorlength() which handles constant expressions.
> Also, you will need a corresponding test.
>
Yes it is allowed. Fixed and added a test.
> For that matter... can't we combine the above function with
> c_parser_cilk_clause_vectorlength(). It doesn't make much sense having
> two functions parsing the exact same clause. Perhaps add a flag to it and
> have it work in two modes: one mode to create OMP_CLAUSE_SAFELEN and
> one mode to fill the token vector.
>
OK. Combined both the functions.
> > + if (!c_parser_elem_fn_vectorlength (parser))
> > + {
> > + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
> > NULL);
> > + /* NO reason to keep any of these tokens if the
> > + vectorlength is messed up. */
> > + vec_free (parser->elem_fn_tokens);
> > + return;
>
> It may be cleaner to make the caller free the vector.
Well, the caller doesn't know if an error has occurred. I suppose I could do
something like check for seen_error (), but this sounds a bit more clearer (to
me altleast)
>
> > + /* linear and uniform are the same between SIMD
> > + enabled functions and #pragma omp declare simd. */
>
> Capitalize first word.
>
Fixed.
> > + /* Do not push the last ')' */
> > + if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0))
> > + vec_safe_push (parser->elem_fn_tokens, *token);
>
> You're documenting the obvious. Perhaps a better comment would be to
> explain why you do not push the last ')'.
>
Fixed.
> > +/* Parses the vector attribute of SIMD enabled functions in Cilk Plus.
> > + Syntax:
> > + vector
> > + vector (<vector attributes>). */
> > +
> > +static void
> > +c_parser_elem_fn_expr_list (c_parser *parser, c_token vec_token)
>
> Please document the second argument.
>
Fixed.
>
> > + /* 2 EOF_token is added as a safety-net since the normal C front-end has
> > + two token look-ahead. */
>
> "Two EOF tokens are added..."
>
Fixed.
> > static void
> > -expand_simd_clones (struct cgraph_node *node)
> > +expand_simd_clones (struct cgraph_node *node, const char *type)
>
> Document second argument, but perhaps we don't even need the second
> argument. See below.
>
> > @@ -12337,7 +12336,10 @@
> > {
> > struct cgraph_node *node;
> > FOR_EACH_FUNCTION (node)
> > - expand_simd_clones (node);
> > + expand_simd_clones (node, "omp declare simd"); if
> > + (flag_enable_cilkplus)
> > + FOR_EACH_FUNCTION (node)
> > + expand_simd_clones (node, "cilk plus elemental");
>
> First of all, it's a really bad idea to scan all the functions twice.
> You should have adapted expand_simd_clones() to do the work for both.
>
OK. I included this in the first loop itself so we won't have to scan the
functions twice.
> But even so, I don't think you need to do this at all. Aren't Cilk Plus
> elementals supposed to be tagged as "omp declare simd" as well? In which
> case expand_simd_clones() will DTRT. It should...and then
> simd_clone_clauses_extract() already has the smarts to differentiate
> between the both variants.
>
Yes, the thing is, there is a big do-while loop in the function and that needs
to be replaced if we have to check for SIMD-enabled function and #pragma omp
declare simd. If we pass it as a type, then it just needs to check for the type
string.
> Both OpenMP and Cilk Plus simd clones should have the "omp declare simd"
> attribute, and then Cilk Plus clones should *also* have the "cilk plus
> elemental" attribute.
>
> Speak of which, we should probably rename the "cilk plus elemental"
> attribute throughout to "cilk plus declare simd" as I described earlier, but
> this
> is not your fault. Bonus points if you want to do it as part of this patch
> :).
>
I called it "cilk simd function" (since the name is SIMD-enabled function and
it should have Cilk or Cilk Plus on it somewhere and Cilk simd enabled function
seemed a bit too long)
> > +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-
> plus/EF/*.c]] " -g" " "
> > +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-
> plus/EF/*.c]] " -O1" " "
> > +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-
> plus/EF/*.c]] " -O2 -std=c99" " "
> > +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-
> plus/EF/*.c]] " -O2 -ftree-vectorize" " "
> > +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-
> plus/EF/*.c]] " -O3 -g" " "
> > +
I narrowed this to 5 with the help of Jakub a while back. But now, I have
replaced it with 3, "-O3 -g"," -O3 -g -std=c99"
>
> As I've mentioned before, I am really against running Cilk tests with all
> these
> variants. It's time consuming for all developers and the chances of catching
> an error that is not caught with say... "-O0" are pretty close to 0. Do you
> have
> any particular errors you think will be better checked by trying all these
> variants? The time spent doesn't seem to be worth it. If you have a
> particular test in mind, perhaps you should add that flag to the test itself.
>
OK. Fixes as I mentioned above.
> For that matter, we should probably get rid of all the variant testing in the
> rest of Cilk Plus.
>
I will send this out as a different patch later for all the others.
> Furthermore, rename "EF" to something more readable and less dependent
> on "elementals" which is deprecated. Perhaps "simd-clones" or something
> similar?
>
Renamed "EF" to "SE" (Simd Enabled function)
> Aldy
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c (revision 205717)
+++ gcc/c-family/c-common.c (working copy)
@@ -771,6 +771,8 @@
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 },
{ "bnd_variable_size", 0, 0, true, false, false,
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c (revision 205717)
+++ gcc/c/c-parser.c (working copy)
@@ -208,6 +208,12 @@
/* 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 <c_token, va_gc> *cilk_simd_fn_tokens;
} c_parser;
@@ -1246,6 +1252,7 @@
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 bool c_parser_cilk_clause_vectorlength (c_parser *, tree *, bool);
/* Parse a translation unit (C90 6.7, C99 6.9).
@@ -1647,7 +1654,8 @@
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);
@@ -1734,7 +1742,8 @@
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);
}
@@ -1746,7 +1755,8 @@
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 ());
@@ -1774,7 +1784,8 @@
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)
@@ -1902,7 +1913,8 @@
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,98 @@
return attr_name;
}
+/* Parses the vector attribute of SIMD enabled functions in Cilk Plus.
+ The VEC_TOKEN is the "vector" token that is replaced with "simd" and
+ pushed into the token list.
+ Syntax:
+ vector
+ vector (<vector attributes>). */
+
+static void
+c_parser_cilk_simd_fn_expr_list (c_parser *parser, c_token vec_token)
+{
+ gcc_assert (simple_cst_equal (vec_token.value,
+ get_identifier ("vector")) == 1);
+ int paren_scope = 0;
+ /* Replace the vector keyword with SIMD. */
+ vec_token.value = get_identifier ("simd");
+ 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--;
+ if (token->type == CPP_NAME
+ && TREE_CODE (token->value) == IDENTIFIER_NODE)
+ {
+ tree value = token->value;
+ if (simple_cst_equal (value, get_identifier ("mask")) == 1)
+ token->value = get_identifier ("inbranch");
+ else if (simple_cst_equal (value, get_identifier ("nomask")) == 1)
+ token->value = get_identifier ("notinbranch");
+ else if (simple_cst_equal (value,
+ get_identifier ("vectorlength")) == 1)
+ {
+ if (!c_parser_cilk_clause_vectorlength (parser, NULL, true))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ /* NO reason to keep any of these tokens if the
+ vectorlength is messed up. */
+ vec_free (parser->cilk_simd_fn_tokens);
+ // parser->cilk_simd_fn_tokens->release ();
+ return;
+ }
+ else
+ continue;
+ }
+ /* Linear and uniform are the same between SIMD
+ enabled functions and #pragma omp declare simd. */
+ }
+ /* 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);
+ return;
+}
+
+/* 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, and so if these EOF
+ tokens are already inserted, then don't do them again. */
+ if (last_token.type == CPP_EOF)
+ return;
+
+ /* Two EOF_token is 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 +3933,13 @@
attr_name = c_parser_attribute_any_word (parser);
if (attr_name == NULL)
break;
+ if (flag_enable_cilkplus
+ && simple_cst_equal (attr_name, get_identifier ("vector")) == 1)
+ {
+ c_token *v_token = c_parser_peek_token (parser);
+ c_parser_cilk_simd_fn_expr_list (parser, *v_token);
+ continue;
+ }
c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
{
@@ -3909,6 +4020,9 @@
}
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;
}
@@ -12754,10 +12868,20 @@
c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
vec<c_token> 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 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)
{
@@ -12766,7 +12890,7 @@
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 "
@@ -12780,9 +12904,20 @@
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)
{
@@ -12792,19 +12927,31 @@
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, OMP_DECLARE_SIMD_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);
- c = build_tree_list (get_identifier ("omp declare simd"), c);
+ if (is_cilkplus_cilk_simd_fn)
+ c = build_tree_list (get_identifier ("cilk simd function"), c);
+ else
+ c = build_tree_list (get_identifier ("omp declare simd"), c);
TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
DECL_ATTRIBUTES (fndecl) = c;
}
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);
}
@@ -13400,39 +13547,91 @@
}
/* 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.
+ Syntax:
+ vectorlength ( constant-expression ) */
-static tree
-c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
+static bool
+c_parser_cilk_clause_vectorlength (c_parser *parser, tree *clauses,
+ bool is_simd_fn)
{
- /* The vectorlength clause behaves exactly like OpenMP's safelen
- clause. Represent it in OpenMP terms. */
- check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
+ c_token *token = c_parser_peek_token (parser);
+ if (is_simd_fn)
+ {
+ gcc_assert (simple_cst_equal (token->value,
+ get_identifier ("vectorlength")) == 1);
+ token->value = get_identifier ("simdlen");
+ vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+ c_parser_consume_token (parser);
+ }
+ 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");
+ token = c_parser_peek_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return clauses;
+ return false;
+ if (is_simd_fn)
+ vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+
+ *token = *c_parser_peek_token (parser);
location_t loc = c_parser_peek_token (parser)->location;
tree expr = c_parser_expr_no_commas (parser, NULL).value;
expr = c_fully_fold (expr, false, NULL);
+ bool error_found = false;
- if (!TREE_TYPE (expr)
+ /* if expr is error_mark_node, then the returning function would have
+ flagged the error. No need to flag them twice. */
+ if (expr == error_mark_node)
+ error_found = true;
+ else if (!TREE_TYPE (expr)
|| !TREE_CONSTANT (expr)
|| !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
- error_at (loc, "vectorlength must be an integer constant");
+ {
+ error_at (loc, "vectorlength must be an integer constant");
+ error_found = true;
+ }
else if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
- error_at (loc, "vectorlength must be a power of 2");
+ {
+ error_at (loc, "vectorlength must be a power of 2");
+ error_found = true;
+ }
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)
+ {
+ c_token new_token;
+ /* If we are here then it has be a number. */
+ new_token.type = CPP_NUMBER;
+ new_token.keyword = RID_MAX;
+ new_token.value = expr;
+ vec_safe_push (parser->cilk_simd_fn_tokens, new_token);
+ }
+ else
+ {
+ tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+ OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
+ OMP_CLAUSE_CHAIN (u) = *clauses;
+ *clauses = u;
+ }
}
+ if (error_found && is_simd_fn)
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return false;
+ }
- c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ token = c_parser_peek_token (parser);
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return false;
- return clauses;
+ if (is_simd_fn)
+ vec_safe_push (parser->cilk_simd_fn_tokens, *token);
+ return true;
}
/* Cilk Plus:
@@ -13571,7 +13770,7 @@
switch (c_kind)
{
case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
- clauses = c_parser_cilk_clause_vectorlength (parser, clauses);
+ c_parser_cilk_clause_vectorlength (parser, &clauses, false);
break;
case PRAGMA_CILK_CLAUSE_LINEAR:
clauses = c_parser_cilk_clause_linear (parser, clauses);
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c (revision 205717)
+++ gcc/omp-low.c (working copy)
@@ -11300,7 +11300,7 @@
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
@@ -12238,16 +12238,17 @@
}
/* If the function in NODE is tagged as an elemental SIMD function,
- create the appropriate SIMD clones. */
+ create the appropriate SIMD clones. TYPE string indicates the type of
+ attribute whether we need to look for. To date the choices are
+ Cilk Plus SIMD-enabled function or #pragma OMP declare simd function. */
static void
-expand_simd_clones (struct cgraph_node *node)
+expand_simd_clones (struct cgraph_node *node, const char *type)
{
if (lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
return;
- tree attr = lookup_attribute ("omp declare simd",
- DECL_ATTRIBUTES (node->decl));
+ tree attr = lookup_attribute (type, DECL_ATTRIBUTES (node->decl));
if (!attr || targetm.simd_clone.compute_vecsize_and_simdlen == NULL)
return;
/* Ignore
@@ -12327,7 +12328,7 @@
}
}
}
- while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
+ while ((attr = lookup_attribute (type, TREE_CHAIN (attr))));
}
/* Entry point for IPA simd clone creation pass. */
@@ -12337,7 +12338,11 @@
{
struct cgraph_node *node;
FOR_EACH_FUNCTION (node)
- expand_simd_clones (node);
+ {
+ expand_simd_clones (node, "omp declare simd");
+ if (flag_enable_cilkplus)
+ expand_simd_clones (node, "cilk simd function");
+ }
return 0;
}
Index: gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
===================================================================
--- gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp (revision 205717)
+++ gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp (working copy)
@@ -59,6 +59,10 @@
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
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error.c (revision 0)
@@ -0,0 +1,18 @@
+/* { 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 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);
+}
+
+
+int main (void)
+{
+ return (func (5,6));
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/vlength_errors.c (revision 0)
@@ -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;
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_error2.c (revision 0)
@@ -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));
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test.c (revision 0)
@@ -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;
+}
Index: gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c
===================================================================
--- gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c (revision 0)
+++ gcc/testsuite/c-c++-common/cilk-plus/SE/ef_test2.c (revision 0)
@@ -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;
+}
+