===================================================================
@@ -1148,7 +1148,7 @@
tree);
static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
static tree c_parser_simple_asm_expr (c_parser *);
-static tree c_parser_attributes (c_parser *);
+static tree c_parser_attributes (c_parser *, vec <c_token> *);
static struct c_type_name *c_parser_type_name (c_parser *);
static struct c_expr c_parser_initializer (c_parser *);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
@@ -1502,9 +1502,17 @@
c_parser_peek_token (parser)->value = error_mark_node;
fndef_ok = !nested;
}
+ /* In Cilk Plus SIMD-enabled functions (formerly known as Elemental
+ Functions), attributes are used right above the functoin declaration or
+ the function itself. */
+ tree attrs = NULL_TREE;
+ if (flag_enable_cilkplus
+ && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ attrs = c_parser_attributes (parser, &omp_declare_simd_clauses);
c_parser_declspecs (parser, specs, true, true, start_attr_ok,
true, true, cla_nonabstract_decl);
+ specs->attrs = chainon (attrs, specs->attrs);
if (parser->error)
{
c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1676,7 +1684,7 @@
if (c_parser_next_token_is_keyword (parser, RID_ASM))
asm_name = c_parser_simple_asm_expr (parser);
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- postfix_attrs = c_parser_attributes (parser);
+ postfix_attrs = c_parser_attributes (parser, NULL);
if (c_parser_next_token_is (parser, CPP_EQ))
{
tree d;
@@ -1815,7 +1823,7 @@
}
c_parser_consume_token (parser);
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- all_prefix_attrs = chainon (c_parser_attributes (parser),
+ all_prefix_attrs = chainon (c_parser_attributes (parser, NULL),
prefix_attrs);
else
all_prefix_attrs = prefix_attrs;
@@ -2403,7 +2411,7 @@
case RID_ATTRIBUTE:
if (!attrs_ok)
goto out;
- attrs = c_parser_attributes (parser);
+ attrs = c_parser_attributes (parser, NULL);
declspecs_add_attrs (loc, specs, attrs);
break;
case RID_ALIGNAS:
@@ -2452,7 +2460,7 @@
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
enum_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
- attrs = c_parser_attributes (parser);
+ attrs = c_parser_attributes (parser, NULL);
enum_loc = c_parser_peek_token (parser)->location;
/* Set the location in case we create a decl now. */
c_parser_set_source_position_from_token (c_parser_peek_token (parser));
@@ -2532,7 +2540,7 @@
break;
}
}
- postfix_attrs = c_parser_attributes (parser);
+ postfix_attrs = c_parser_attributes (parser, NULL);
ret.spec = finish_enum (type, nreverse (values),
chainon (attrs, postfix_attrs));
ret.kind = ctsk_tagdef;
@@ -2623,7 +2631,7 @@
}
struct_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
- attrs = c_parser_attributes (parser);
+ attrs = c_parser_attributes (parser, NULL);
/* Set the location in case we create a decl now. */
c_parser_set_source_position_from_token (c_parser_peek_token (parser));
@@ -2735,7 +2743,7 @@
recovered already. Go on with the next field. */
}
}
- postfix_attrs = c_parser_attributes (parser);
+ postfix_attrs = c_parser_attributes (parser, NULL);
ret.spec = finish_struct (struct_loc, type, nreverse (contents),
chainon (attrs, postfix_attrs), struct_info);
ret.kind = ctsk_tagdef;
@@ -2904,7 +2912,7 @@
width = c_parser_expr_no_commas (parser, NULL).value;
}
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- postfix_attrs = c_parser_attributes (parser);
+ postfix_attrs = c_parser_attributes (parser, NULL);
d = grokfield (c_parser_peek_token (parser)->location,
declarator, specs, width, &all_prefix_attrs);
decl_attributes (&d, chainon (postfix_attrs,
@@ -2912,7 +2920,7 @@
DECL_CHAIN (d) = decls;
decls = d;
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- all_prefix_attrs = chainon (c_parser_attributes (parser),
+ all_prefix_attrs = chainon (c_parser_attributes (parser, NULL),
prefix_attrs);
else
all_prefix_attrs = prefix_attrs;
@@ -3226,7 +3234,7 @@
tree attrs;
struct c_declarator *inner;
c_parser_consume_token (parser);
- attrs = c_parser_attributes (parser);
+ attrs = c_parser_attributes (parser, NULL);
if (kind != C_DTR_NORMAL
&& (c_parser_next_token_starts_declspecs (parser)
|| c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
@@ -3382,7 +3390,7 @@
tree attrs;
struct c_arg_info *args;
c_parser_consume_token (parser);
- attrs = c_parser_attributes (parser);
+ attrs = c_parser_attributes (parser, NULL);
args = c_parser_parms_declarator (parser, id_present, attrs);
if (args == NULL)
return NULL;
@@ -3529,7 +3537,7 @@
tree new_attrs;
c_parser_consume_token (parser);
mark_forward_parm_decls ();
- new_attrs = c_parser_attributes (parser);
+ new_attrs = c_parser_attributes (parser, NULL);
return c_parser_parms_list_declarator (parser, new_attrs, expr);
}
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
@@ -3623,7 +3631,7 @@
return NULL;
}
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- postfix_attrs = c_parser_attributes (parser);
+ postfix_attrs = c_parser_attributes (parser, NULL);
return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
declarator);
}
@@ -3760,6 +3768,148 @@
return attr_name;
}
+/* 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, vec <c_token> *token_list)
+{
+ c_token *token = c_parser_peek_token (parser);
+ gcc_assert (simple_cst_equal (token->value,
+ get_identifier ("vectorlength")) == 1);
+ token->value = get_identifier ("simdlen");
+ token_list->safe_push (*token);
+
+ c_parser_consume_token (parser);
+
+ token = c_parser_peek_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return false;
+
+ token_list->safe_push (*token);
+
+ token = c_parser_peek_token (parser);
+ tree value = token->value;
+ if (!value)
+ {
+ error_at (token->location, "expected vectorlength value");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return false;
+ }
+ c_parser_consume_token (parser);
+ 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;
+ }
+ if (!integer_pow2p (value))
+ {
+ error_at (token->location, "vectorlength must be a power of 2");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ return false;
+ }
+ token_list->safe_push (*token);
+
+ token = c_parser_peek_token (parser);
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return false;
+ token_list->safe_push (*token);
+ return true;
+}
+
+/* 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,
+ vec <c_token> *elem_fn_tokens)
+{
+ 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");
+ elem_fn_tokens->safe_push (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_elem_fn_vectorlength (parser, elem_fn_tokens))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ /* No reason to keep any of these tokens if the
+ vectorlength is messed up. */
+ elem_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 ')' */
+ if (!(token->type == CPP_CLOSE_PAREN && paren_scope == 0))
+ elem_fn_tokens->safe_push (*token);
+ c_parser_consume_token (parser);
+ }
+ c_token eol_token;
+ memset (&eol_token, 0, sizeof (eol_token));
+ eol_token.type = CPP_PRAGMA_EOL;
+ elem_fn_tokens->safe_push (eol_token);
+ return;
+}
+
+/* Add 2 CPP_EOF at the end of ELEM_FN_TOKENS vector. */
+
+static void
+c_finish_elem_fn_tokens (vec <c_token> *elem_fn_tokens)
+{
+ /* If the token is a CPP_EOF, then there is no reason to stuff it again
+ with 2 EOF. If it is NULL, then we didn't find any vector keywords. */
+ if (!elem_fn_tokens || *elem_fn_tokens == vNULL
+ || (*elem_fn_tokens)[0].type == CPP_EOF)
+ return;
+ /* Since we are converting an attribute to a pragma, we need to end the
+ attribute with PRAGMA_EOL. OpenMP guys would like to have 2 CPP_EOF
+ at the end, and so we insert that also. */
+ c_token eof_token;
+ memset (&eof_token, 0, sizeof (eof_token));
+ eof_token.type = CPP_PRAGMA_EOL;
+ elem_fn_tokens->safe_push (eof_token);
+ eof_token.type = CPP_EOF;
+ elem_fn_tokens->safe_push (eof_token);
+ elem_fn_tokens->safe_push (eof_token);
+}
+
/* Parse (possibly empty) attributes. This is a GNU extension.
attributes:
@@ -3788,7 +3938,7 @@
allow identifiers declared as types to start the arguments? */
static tree
-c_parser_attributes (c_parser *parser)
+c_parser_attributes (c_parser *parser, vec <c_token> *elem_fn_tokens)
{
tree attrs = NULL_TREE;
while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
@@ -3824,6 +3974,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_elem_fn_expr_list (parser, *v_token, elem_fn_tokens);
+ continue;
+ }
c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
{
@@ -3904,6 +4061,9 @@
}
parser->lex_untranslated_string = false;
}
+
+ if (flag_enable_cilkplus)
+ c_finish_elem_fn_tokens (elem_fn_tokens);
return attrs;
}
@@ -4588,7 +4748,7 @@
c_parser_consume_token (parser);
gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
c_parser_consume_token (parser);
- attrs = c_parser_attributes (parser);
+ attrs = c_parser_attributes (parser, NULL);
tlab = define_label (loc2, name);
if (tlab)
{
@@ -8386,7 +8546,7 @@
}
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- *attributes = c_parser_attributes (parser);
+ *attributes = c_parser_attributes (parser, NULL);
/* If there were no attributes here, just report any earlier error. */
if (*attributes == NULL_TREE || bad)
@@ -8475,7 +8635,7 @@
}
/* New ObjC allows attributes on method parameters. */
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- param_attr = c_parser_attributes (parser);
+ param_attr = c_parser_attributes (parser, NULL);
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected identifier");
@@ -13630,7 +13790,7 @@
tree attr_name, attr = NULL;
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- return c_parser_attributes (parser);
+ return c_parser_attributes (parser, NULL);
if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
return NULL_TREE;
===================================================================
@@ -59,6 +59,12 @@
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/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" " "
+
dg-finish
unset TEST_EXTRA_LIBS
===================================================================
@@ -0,0 +1,49 @@
+/* { 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 vectorlength value" } */
+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 a constant 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 a constant 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 a constant integer" } */
+int func6 (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;
+}
===================================================================
@@ -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;
+}