@@ -237,8 +237,8 @@ static void cp_parser_initial_pragma
static tree cp_literal_operator_id
(const char *);
-static void cp_parser_cilk_simd
- (cp_parser *, cp_token *);
+static tree cp_parser_cilk_simd
+ (cp_parser *, cp_token *, tree);
static bool cp_parser_omp_declare_reduction_exprs
(tree, cp_parser *);
static tree cp_parser_cilk_simd_vectorlength
@@ -9380,6 +9380,18 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
statement = cp_parser_iteration_statement (parser, false);
break;
+ case RID_CILK_FOR:
+ if (!flag_enable_cilkplus)
+ {
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "-fcilkplus must be enabled to use %<_Cilk_for%>");
+ cp_lexer_consume_token (parser->lexer);
+ statement = error_mark_node;
+ }
+ else
+ statement = cp_parser_cilk_simd (parser, NULL, integer_zero_node);
+ break;
+
case RID_BREAK:
case RID_CONTINUE:
case RID_RETURN:
@@ -28865,7 +28877,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
case LE_EXPR:
break;
case NE_EXPR:
- if (code == CILK_SIMD)
+ if (code == CILK_SIMD || code == CILK_FOR)
break;
/* Fall through: OpenMP disallows NE_EXPR. */
default:
@@ -29190,11 +29202,18 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
bool add_private_clause = false;
location_t loc;
- if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+ if (code == CILK_SIMD
+ && !cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
{
cp_parser_error (parser, "for statement expected");
return NULL;
}
+ if (code == CILK_FOR
+ && !cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR))
+ {
+ cp_parser_error (parser, "_Cilk_for statement expected");
+ return NULL;
+ }
loc = cp_lexer_consume_token (parser->lexer)->location;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
@@ -29203,13 +29222,26 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
init = decl = real_decl = NULL;
this_pre_body = push_stmt_list ();
+ if (code == CILK_FOR
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
+ {
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "induction variable cannot be static");
+ cp_lexer_consume_token (parser->lexer);
+ }
add_private_clause
|= cp_parser_omp_for_loop_init (parser,
- /*parsing_openmp=*/code != CILK_SIMD,
+ /*parsing_openmp=*/
+ (code != CILK_SIMD && code != CILK_FOR),
this_pre_body, for_block,
init, decl, real_decl);
- cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+ if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)
+ && code == CILK_FOR)
+ {
+ cp_parser_skip_to_end_of_statement (parser);
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
if (this_pre_body)
{
this_pre_body = pop_stmt_list (this_pre_body);
@@ -29367,17 +29399,30 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
/* Note that we saved the original contents of this flag when we entered
the structured block, and so we don't need to re-save it here. */
- if (code == CILK_SIMD)
+ if (code == CILK_SIMD || code == CILK_FOR)
parser->in_statement = IN_CILK_SIMD_FOR;
else
parser->in_statement = IN_OMP_FOR;
+ tree top_body = NULL_TREE, top_level_body = NULL_TREE;
+ if (code == CILK_FOR)
+ {
+ top_level_body = push_stmt_list ();
+ top_body = begin_omp_parallel ();
+ }
+
/* Note that the grammar doesn't call for a structured block here,
though the loop as a whole is a structured block. */
body = push_stmt_list ();
cp_parser_statement (parser, NULL_TREE, false, NULL);
body = pop_stmt_list (body);
+ if (code == CILK_FOR)
+ {
+ body = add_stmt (body);
+ body = finish_omp_parallel (NULL_TREE, top_body);
+ body = pop_stmt_list (top_level_body);
+ }
if (declv == NULL_TREE)
ret = NULL_TREE;
else
@@ -31312,6 +31357,38 @@ cp_parser_initial_pragma (cp_token *first_token)
cp_lexer_get_preprocessor_token (NULL, first_token);
}
+/* Parses the grainsize pragma for the _Cilk_for statement.
+ Syntax:
+ #pragma cilk grainsize = <VALUE>. */
+
+static void
+cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
+{
+ if (cp_parser_require (parser, CPP_EQ, RT_EQ))
+ {
+ tree exp = cp_parser_binary_expression (parser, false, false,
+ PREC_NOT_OPERATOR, NULL);
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ if (!exp || exp == error_mark_node)
+ {
+ error_at (pragma_tok->location, "invalid grainsize for _Cilk_for");
+ return;
+ }
+ cp_token *n_tok = cp_lexer_peek_token (parser->lexer);
+
+ /* Make sure the next token is _Cilk_for, it is invalid otherwise. */
+ if (n_tok && n_tok->type == CPP_KEYWORD
+ && n_tok->keyword == RID_CILK_FOR)
+ cp_parser_cilk_simd (parser, NULL, exp);
+ else
+ warning_at (cp_lexer_peek_token (parser->lexer)->location, 0,
+ "%<#pragma cilk grainsize%> is not followed by "
+ "%<_Cilk_for%>");
+ return;
+ }
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+
/* Normal parsing of a pragma token. Here we can (and must) use the
regular lexer. */
@@ -31491,9 +31568,30 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
"%<#pragma simd%> must be inside a function");
break;
}
- cp_parser_cilk_simd (parser, pragma_tok);
+ cp_parser_cilk_simd (parser, pragma_tok, NULL_TREE);
return true;
+ case PRAGMA_CILK_GRAINSIZE:
+ if (context == pragma_external)
+ {
+ error_at (pragma_tok->location,
+ "%<#pragma cilk grainsize%> must be inside a function");
+ break;
+ }
+
+ /* Ignore the pragma if Cilk Plus is not enabled. */
+ if (flag_enable_cilkplus)
+ {
+ cp_parser_cilk_grainsize (parser, pragma_tok);
+ return true;
+ }
+ else
+ {
+ error_at (pragma_tok->location, "-fcilkplus must be enabled to use "
+ "%<#pragma cilk grainsize%>");
+ break;
+ }
+
default:
gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
c_invoke_pragma_handler (id);
@@ -31811,31 +31909,64 @@ cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
return c_finish_cilk_clauses (clauses);
}
-/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops. */
+/* Main entry-point for parsing Cilk Plus <#pragma simd> for and _Cilk_for
+ loops. This function returns NULL_TREE whenever it is parsing the
+ #pragma simd's for because the caller does not check the return value.
+ _Cilk_for's caller checks this value and thus return error_mark_node
+ when errors happen and a valid value when things go as expected. */
-static void
-cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
+static tree
+cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token, tree grain)
{
- tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
+ bool is_cilk_for = !pragma_token ? true: false;
+ tree clauses = NULL_TREE;
+
+ if (!is_cilk_for)
+ clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
if (clauses == error_mark_node)
- return;
-
- if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR))
+ return NULL_TREE;
+
+ if (!is_cilk_for
+ && cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR))
{
error_at (cp_lexer_peek_token (parser->lexer)->location,
"for statement expected");
- return;
+ return NULL_TREE;
+ }
+ if (is_cilk_for
+ && cp_lexer_next_token_is_not_keyword (parser->lexer, RID_CILK_FOR))
+ {
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "_Cilk_for statement expected");
+ return error_mark_node;
}
tree sb = begin_omp_structured_block ();
int save = cp_parser_begin_omp_structured_block (parser);
- tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL);
+ enum tree_code code = is_cilk_for ? CILK_FOR : CILK_SIMD;
+ tree ret = cp_parser_omp_for_loop (parser, code, clauses, NULL);
if (ret)
cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret));
+
+ /* For _Cilk_for statements, the grain value is stored in the same
+ location as clauses for OMP for inside a schedule clause. */
+ if (is_cilk_for && ret)
+ {
+ tree l = build_omp_clause (EXPR_LOCATION (grain),
+ OMP_CLAUSE_SCHEDULE);
+ OMP_CLAUSE_SCHEDULE_KIND (l) = OMP_CLAUSE_SCHEDULE_RUNTIME;
+ OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (l) = grain;
+ OMP_CLAUSE_CHAIN (l) = NULL_TREE;
+ OMP_FOR_CLAUSES (ret) = l;
+ }
+
cp_parser_end_omp_structured_block (parser, save);
- add_stmt (finish_omp_structured_block (sb));
- return;
+ tree stmt = finish_omp_structured_block (sb);
+ add_stmt (stmt);
+ if (is_cilk_for)
+ return stmt;
+ return NULL_TREE;
}
/* Create an identifier for a generic parameter type (a synthesized
@@ -13586,6 +13586,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case OMP_FOR:
case OMP_SIMD:
case CILK_SIMD:
+ case CILK_FOR:
case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;
@@ -6036,7 +6036,8 @@ finish_omp_task (tree clauses, tree body)
static bool
handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
tree condv, tree incrv, tree *body,
- tree *pre_body, tree clauses)
+ tree *pre_body, tree clauses,
+ bool is_cilk_for)
{
tree diff, iter_init, iter_incr = NULL, last;
tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -6056,6 +6057,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
case GE_EXPR:
case LT_EXPR:
case LE_EXPR:
+ case NE_EXPR:
if (TREE_OPERAND (cond, 1) == iter)
cond = build2 (swap_tree_comparison (TREE_CODE (cond)),
TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0));
@@ -6199,6 +6201,11 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
break;
decl = create_temporary_var (TREE_TYPE (diff));
+ /* In _Cilk_for we must know the induction variable name since it is
+ read by expand_cilk_for_body in omp-low.c to set the induction
+ variable in the child function correctly. */
+ if (is_cilk_for)
+ DECL_NAME (decl) = make_anon_name ();
pushdecl (decl);
add_decl_expr (decl);
last = create_temporary_var (TREE_TYPE (diff));
@@ -6414,8 +6421,24 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
"iteration variable %qE", decl);
return NULL;
}
- if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
- incrv, &body, &pre_body, clauses))
+
+ /* In _Cilk_for, all the iterator mapping code should be
+ inserted in the OMP_PARALLEL_BODY. */
+ if (code == CILK_FOR)
+ {
+ tree the_body = OMP_PARALLEL_BODY (body);
+ if (TREE_CODE (the_body) == BIND_EXPR)
+ the_body = BIND_EXPR_BODY (the_body);
+ if (handle_omp_for_class_iterator (i, locus, declv, initv,
+ condv, incrv, &the_body,
+ &pre_body, clauses, true))
+ return NULL;
+ else
+ BIND_EXPR_BODY (OMP_PARALLEL_BODY (body)) = the_body;
+ }
+ else if (handle_omp_for_class_iterator (i, locus, declv, initv,
+ condv, incrv, &body,
+ &pre_body, clauses, false))
return NULL;
continue;
}
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#define SIZE 100
+#define CHECK_VALUE 5
+
+template <class T>
+int func (T start, T end)
+{
+ int Array[SIZE];
+ _Cilk_for (T ii = 0; ii < end; ii++)
+ Array[ii] = CHECK_VALUE;
+
+ for (T ii = 0; ii < end; ii++)
+ if (Array[ii] != CHECK_VALUE)
+ __builtin_abort ();
+
+ return 0;
+}
+
+int main (void)
+{
+ return func <int> (0, 100) + func <long> (0, 100);
+}
new file mode 100644
@@ -0,0 +1,52 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#include <vector>
+#include <cstdio>
+#include <iostream>
+#include <algorithm>
+
+using namespace std;
+
+
+int main(void)
+{
+vector <int> array;
+vector <int> array_serial;
+
+#if 1
+for (int ii = -1; ii < 10; ii++)
+{
+ array.push_back(ii);
+ array_serial.push_back (ii);
+}
+#endif
+_Cilk_for (vector<int>::iterator iter = array.begin(); iter != array.end();
+ iter++)
+{
+ if (*iter == 6)
+ *iter = 13;
+}
+for (vector<int>::iterator iter = array_serial.begin();
+ iter != array_serial.end(); iter++)
+{
+ if (*iter == 6)
+ *iter = 13;
+}
+sort (array.begin(), array.end());
+sort (array_serial.begin(), array_serial.end());
+
+vector <int>::iterator iter = array.begin ();
+vector <int>::iterator iter_serial = array_serial.begin ();
+
+while (iter != array.end () && iter_serial != array_serial.end ())
+{
+ if (*iter != *iter_serial)
+ __builtin_abort ();
+ iter++;
+ iter_serial++;
+}
+
+return 0;
+}
new file mode 100644
@@ -0,0 +1,72 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+#include <vector>
+#include <cstdio>
+#include <iostream>
+#include <algorithm>
+
+using namespace std;
+
+
+int main(void)
+{
+vector <int> array,array_serial;
+
+#if 1
+for (int ii = -1; ii < 10; ii++)
+{
+ array.push_back(ii);
+ array_serial.push_back(ii);
+}
+#endif
+_Cilk_for (vector<int>::reverse_iterator iter4 = array.rbegin();
+ iter4 != array.rend(); iter4++)
+{
+ if (*iter4 == 0x8) {
+ *iter4 = 9;
+ }
+}
+
+_Cilk_for (vector<int>::reverse_iterator iter4 = array_serial.rbegin();
+ iter4 != array_serial.rend(); iter4++)
+{
+ if (*iter4 == 0x8) {
+ *iter4 = 9;
+ }
+}
+_Cilk_for (vector<int>::reverse_iterator iter2 = array.rbegin();
+ iter2 != array.rend();
+ iter2 += 1)
+{
+ if ((*iter2 == 0x4) || (*iter2 == 0x7)) {
+ *iter2 = 0x3;
+ }
+}
+for (vector<int>::reverse_iterator iter2 = array_serial.rbegin();
+ iter2 != array_serial.rend();
+ iter2 += 1)
+{
+ if ((*iter2 == 0x4) || (*iter2 == 0x7)) {
+ *iter2 = 0x3;
+ }
+}
+sort (array.begin(), array.end());
+sort (array_serial.begin(), array_serial.end());
+
+vector <int>::iterator iter = array.begin ();
+vector <int>::iterator iter_serial = array_serial.begin ();
+while (iter != array.end () && iter_serial != array_serial.end ())
+{
+ if (*iter != *iter_serial)
+ __builtin_abort ();
+ iter++;
+ iter_serial++;
+}
+
+return 0;
+}
+
+
new file mode 100644
@@ -0,0 +1,50 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+#include <iostream>
+#include <cstdio>
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+#include <list>
+
+using namespace std;
+
+
+int main(int argc, char **argv)
+{
+ vector <int> number_list, number_list_serial;
+ int new_number = 0;
+ int no_elements = 0;
+
+ if (argc != 2)
+ {
+ no_elements = 10000;
+ }
+
+
+ number_list.clear();
+ number_list_serial.clear();
+ for (int ii = 0; ii < no_elements; ii++)
+ {
+ number_list.push_back(new_number);
+ number_list_serial.push_back(new_number);
+ }
+
+ _Cilk_for (int jj = 0; jj < no_elements; jj++)
+ {
+ number_list[jj] = jj + no_elements;
+ }
+ for (int jj = 0; jj < no_elements; jj++)
+ {
+ number_list_serial[jj] = jj + no_elements;
+ }
+
+ for (int jj = 0; jj < no_elements; jj++)
+ if (number_list_serial[jj] != number_list[jj])
+ abort ();
+
+ return 0;
+}