@@ -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 *);
@@ -9364,6 +9364,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:
@@ -28694,7 +28706,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:
@@ -29019,11 +29031,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))
@@ -29032,13 +29051,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);
@@ -29196,17 +29228,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
@@ -31084,6 +31129,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. */
@@ -31263,9 +31340,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);
@@ -31555,31 +31653,63 @@ 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. */
+ if (is_cilk_for && ret)
+ {
+ tree l = build_omp_clause (EXPR_LOCATION (grain),
+ OMP_CLAUSE_SAFELEN);
+ OMP_CLAUSE_SAFELEN_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
@@ -13575,6 +13575,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;
@@ -13582,8 +13583,22 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
tree incrv = NULL_TREE;
int i;
- clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
- args, complain, in_decl);
+ /* We cannot use the tsubst_omp_clauses since it will try to
+ do checking such as whether a certain clause can be used
+ with a certain for-loop. We are just use safelen clause here
+ as a holder to hold the grain value. */
+ if (TREE_CODE (t) == CILK_FOR)
+ {
+ tree l = OMP_FOR_CLAUSES (t);
+ l = RECUR (OMP_CLAUSE_SAFELEN_EXPR (l));
+ clauses = build_omp_clause (EXPR_LOCATION (l),
+ OMP_CLAUSE_SAFELEN);
+ OMP_CLAUSE_SAFELEN_EXPR (clauses) = l;
+ OMP_CLAUSE_CHAIN (clauses) = NULL_TREE;
+ }
+ else
+ clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
+ args, complain, in_decl);
if (OMP_FOR_INIT (t) != NULL_TREE)
{
declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
@@ -5965,7 +5965,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;
@@ -5985,6 +5986,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));
@@ -6128,6 +6130,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));
@@ -6343,8 +6350,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;
}
@@ -7,7 +7,8 @@ int main (void)
{
int q = 0, ii = 0, jj = 0;
- _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" } */
+ _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" "" { target c } } */
+ /* { dg-error "expected" "" { target c++ } 10 } */
q = 5;
_Cilk_for (; ii < 10; ii++) /* { dg-error "expected iteration declaration" } */
@@ -16,24 +17,30 @@ int main (void)
_Cilk_for (int ii = 0; ; ii++) /* { dg-error "missing controlling predicate" } */
q = 2;
- _Cilk_for (int ii = 0; ii < 10, jj < 10; ii++) /* { dg-error "expected ';' before ',' token" } */
+ _Cilk_for (int ii = 0; ii < 10, jj < 10; ii++) /* { dg-error "expected ';' before ',' token" "" { target c } } */
+ /* { dg-error "invalid controlling predicate" "" { target c++ } 20 } */
q = 5;
_Cilk_for (int ii = 0; ii < 10; ) /* { dg-error "missing increment" } */
q = 5;
- _Cilk_for (int ii = 0, jj = 0; ii < 10; ii++) /* { dg-error "expected iteration declaration" } */
+
+ _Cilk_for (int ii = 0, jj = 0; ii < 10; ii++) /* { dg-error "expected" } */
q = 5;
_Cilk_for (volatile int vii = 0; vii < 10; vii++) /* { dg-error "iteration variable cannot be volatile" } */
q = 5;
- _Cilk_for (static int sii = 0; sii < 10; sii++) /* { dg-error "static variable" } */
+
+ _Cilk_for (static int sii = 0; sii < 10; sii++) /* { dg-error "static" } */
+
q = 5;
+
_Cilk_for (float fii = 3.47; fii < 5.23; fii++) /* { dg-error "invalid type for iteration variable" } */
q = 5;
+
_Cilk_for (int ii = 0; 10 > jj; ii++) /* { dg-error "invalid controlling predicate" } */
q = 5;
@@ -43,7 +50,9 @@ int main (void)
_Cilk_for (int ii = 10; ii >= 0; ii--) /* This is OK! */
q = 5;
- _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" } */
+ _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" "" { target c } } */
+ /* { dg-error "expected" "" { target c++ } 53 } */
q = 5;
+
return 0;
}
@@ -29,13 +29,13 @@ int main(int argc, char **argv)
Array1[ii] = 0;
#pragma cilk grainsize = 1
- while (Array1[5] != 0) /* { dg-warning "grainsize pragma is not followed" } */
+ while (Array1[5] != 0) /* { dg-warning "is not followed by" } */
{
/* Blah */
}
#pragma cilk grainsize = 1
- int q = 0; /* { dg-warning "grainsize pragma is not followed" } */
+ int q = 0; /* { dg-warning "is not followed by" } */
_Cilk_for (q = 0; q < 10; q++)
Array1[q] = 5;
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;
+}