===================================================================
@@ -0,0 +1,38 @@
+/* { 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 <class T, class R>
+__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<long, int> (5, 4)) !=
+ (5 + 4) + (5 + 4) + (5 + 5) + (int) ((long)5 +(int)4))
+ __builtin_abort ();
+ return 0;
+}
+
===================================================================
@@ -60,6 +60,12 @@
dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+
+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=c++11" " "
+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
===================================================================
@@ -2111,6 +2111,9 @@
static tree cp_parser_late_parsing_omp_declare_simd
(cp_parser *, tree);
+static tree cp_parser_late_parsing_elem_fn_info
+ (cp_parser *, tree);
+
static tree synthesize_implicit_template_parm
(cp_parser *);
static tree finish_fully_implicit_template
@@ -17031,6 +17034,14 @@
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_lexer_next_token_is_keyword (parser->lexer,
+ RID_ATTRIBUTE))
+ attrs = chainon (cp_parser_gnu_attributes_opt (parser),
+ attrs);
late_return = (cp_parser_late_return_type_opt
(parser, declarator,
memfn ? cv_quals : -1));
@@ -17739,7 +17750,7 @@
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. */
@@ -17754,10 +17765,14 @@
&& declarator
&& declarator->kind == cdk_id);
+ bool elem_fn_vector_p = (parser->elem_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 || elem_fn_vector_p))
return NULL_TREE;
tree save_ccp = current_class_ptr;
@@ -17776,6 +17791,10 @@
type = cp_parser_trailing_type_id (parser);
}
+ if (elem_fn_vector_p)
+ declarator->std_attributes
+ = cp_parser_late_parsing_elem_fn_info (parser,
+ declarator->std_attributes);
if (declare_simd_p)
declarator->std_attributes
= cp_parser_late_parsing_omp_declare_simd (parser,
@@ -21306,6 +21325,121 @@
return cp_parser_std_attribute_spec_seq (parser);
}
+/* Parses the vectorlength clause in Cilk Plus SIMD-enabled function
+ (formerly called elemental functions). Syntax:
+ vectorlength ( <constant integer> ) */
+
+static void
+cp_parser_elem_fn_vectorlength (cp_parser *parser,
+ cp_omp_declare_simd_data *info)
+{
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ {
+ info->error_seen = true;
+ return;
+ }
+
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ location_t loc = token->location;
+ if (!token->u.value)
+ {
+ error_at (loc, "expected vectorlength value");
+ info->error_seen = true;
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ return;
+ }
+ if (TREE_CODE (token->u.value) != INTEGER_CST)
+ {
+ error_at (loc, "vectorlength must be a constant integer");
+ info->error_seen = true;
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ return;
+ }
+ if (!integer_pow2p (token->u.value))
+ {
+ error_at (loc, "vectorlength must be a power of 2");
+ info->error_seen = true;
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ return;
+ }
+ /* Consume the vectorlength value. */
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ info->error_seen = true;
+}
+
+cp_omp_declare_simd_data info;
+
+/* Parses the Cilk Plus SIMD-enabled function's attribute. Syntax:
+ vector [(<clauses>)] */
+
+static void
+cp_parser_elem_fn_expr_list (cp_parser *parser, cp_token *v_token)
+{
+ bool first_p = parser->elem_fn_info == NULL;
+ cp_token *token = v_token;
+ if (first_p)
+ {
+ info.error_seen = false;
+ info.fndecl_seen = false;
+ info.tokens = vNULL;
+ parser->elem_fn_info = &info;
+ }
+ 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--;
+ else if (token->type == CPP_NAME
+ && TREE_CODE (token->u.value) == IDENTIFIER_NODE)
+ {
+ tree val = token->u.value;
+ if (simple_cst_equal (val, get_identifier ("mask")) == 1)
+ token->u.value = get_identifier ("inbranch");
+ else if (simple_cst_equal (val, get_identifier ("nomask")) == 1)
+ token->u.value = get_identifier ("notinbranch");
+ else if (simple_cst_equal (val,
+ get_identifier ("vectorlength")) == 1)
+ {
+ token->u.value = get_identifier ("simdlen");
+ parser->lexer->next_token->u.value = token->u.value;
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_elem_fn_vectorlength (parser, &info);
+ /* The above function should parse till the end of
+ vectorlength's last parenthesis. */
+ continue;
+ }
+ /* linear and uniform are the same between SIMD-enabled functions
+ and #pragma omp declare simd. */
+
+ /* We sometimes modify the next token, so reset the next token. */
+ parser->lexer->next_token->u.value = token->u.value;
+ }
+
+ /* 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->elem_fn_info->tokens.safe_push (cp);
+}
+
/* Parse an (optional) series of attributes.
attributes:
@@ -21402,8 +21536,9 @@
{
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. */
@@ -21411,7 +21546,7 @@
/* 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);
@@ -21423,10 +21558,17 @@
vec<tree, va_gc> *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 (simple_cst_equal (identifier,
+ get_identifier ("vector")) == 1)
+ {
+ cp_parser_elem_fn_expr_list (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
@@ -21437,6 +21579,12 @@
/* Save the arguments away. */
TREE_VALUE (attribute) = arguments;
}
+ else if (simple_cst_equal (identifier,
+ get_identifier ("vector")) == 1)
+ {
+ cp_parser_elem_fn_expr_list (parser, id_token);
+ continue;
+ }
if (arguments != error_mark_node)
{
@@ -28076,7 +28224,10 @@
}
}
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;
@@ -30074,6 +30225,59 @@
}
}
+/* 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_elem_fn_info (cp_parser *parser, tree attrs)
+{
+ struct cp_token_cache *ce;
+ cp_omp_declare_simd_data *info = parser->elem_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 SIMD-enabled function");
+ parser->elem_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;
+
+ /* Vector attributes are converted to #pragma omp declare simd values and
+ so we need them enabled. */
+ flag_openmp = 1;
+
+ 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, OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "#pragma omp declare simd", NULL);
+ cp_parser_pop_lexer (parser);
+ if (cl)
+ cl = tree_cons (NULL_TREE, cl, NULL_TREE);
+ 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;
+ parser->elem_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. */
===================================================================
@@ -361,6 +361,13 @@
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)) elem_fn_info;
+
/* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
template parameter. */
bool auto_is_implicit_function_template_parm_p;