[gomp4/cilk-in-gomp/cilkplus] C++ parsing for Cilk plus <#pragma simd>

Aldy Hernandez aldyh@redhat.com
Wed Jun 5 19:31:00 GMT 2013


On 05/21/13 10:46, Iyer, Balaji V wrote:
> Hello Aldy et al., Attached, please find a patch on top of gomp4
> branch that implements Cilk's <#pragma simd> for C++. This is done in
> the same fashion as Aldy did in:
> http://gcc.gnu.org/ml/gcc-patches/2013-05/msg00678.html (It creates
> OMP_SIMD trees and let omp-low do the rest).
>
> This patch should be applied on Aldy's branch aldyh/cilk-in-gomp. I
> have also included testsuite code that will catch several errors.

Hi Balaji.

As promised, I have taken over your C++ FE changes and fixed everything 
I pointed out in my review.

I replaced the tests you provided in your patch with my more 
comprehensive ones, after moving mine to the c-c++-common 
infrastructure.  I moved all the C specific tests to 
testsuite/gcc.dg/cilk-plus/ and all the C++ specific tests to 
testsuite/g++.dg/cilk-plus.

I changed some of the C++ FE errors to match the C front-end, and when 
not possible, have adapted the tests to match either the C or the C++ 
error messages.  When the dust settles, I will see if your tests stress 
any cases that mine didn't and incorporate them if necessary.

I cleaned up a lot of stuff, fixed buglets and ICEs that I found while 
running the tests.  However, there are still a handful of failures that 
need to be fixed.

For now I am testing with:

	make check RUNTESTFLAGS="cilk-plus.exp"

which yields the following on x86-64 Linux:

                 === gcc Summary ===

# of expected passes            65

                 === g++ Summary ===

# of expected passes            70
# of unexpected failures        60

The distinct failures are:

     c-c++-common/cilk-plus/PS/body.c
     c-c++-common/cilk-plus/PS/for1.c
     c-c++-common/cilk-plus/PS/for2.c
     c-c++-common/cilk-plus/PS/for3.c

Attached is the patch I am committing to the branch.  I will start 
looking at the remaining failures next, unless you get bored and want to 
look at them as well :).

Thanks again for your patch.
-------------- next part --------------
diff --git a/gcc/ChangeLog.cilkplus b/gcc/ChangeLog.cilkplus
index 5e9fb79..96a02c6 100644
--- a/gcc/ChangeLog.cilkplus
+++ b/gcc/ChangeLog.cilkplus
@@ -1,4 +1,5 @@
 2013-05-13  Aldy Hernandez  <aldyh@redhat.com>
+	    Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* Makefile.in (C_COMMON_OBJS): Depend on c-family/c-cilkplus.o.
 	(c-cilkplus.o): New dependency.
@@ -9,6 +10,8 @@ c-family/
 	* c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_SIMD enum.
 	(enum pragma_cilk_clause): New.
 	* c.opt (fcilkplus): New flag.
+	* c-common.h (c_finish_cilk_simd_loop): Protoize.
+	(c_finish_cilk_clauses): Same.
 
 c/
 	* c-parser.c (c_parser_pragma): Add case for PRAGMA_CILK_SIMD.
@@ -19,8 +22,6 @@ c/
 	(c_parser_cilk_all_clauses): New.
 	(c_parser_cilk_for_statement): New.
 	(c_parser_cilk_simd_construct): New.
-	* c-tree.h (c_finish_cilk_simd_loop): Protoize.
-	(c_finish_cilk_clauses): Same.
 	* c-typeck.c (c_finish_bc_stmt): Add case for _Cilk_for loops.
 
 testsuite/
diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
index 40284fe..84f1645 100644
--- a/gcc/c-family/c-cilkplus.c
+++ b/gcc/c-family/c-cilkplus.c
@@ -104,27 +104,22 @@ c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
   return error_mark_node;
 }
 
-/* Callback for walk_tree.
+/* Callback for walk_tree to validate the body of a pragma simd loop
+   or _cilk_for loop.
 
    This function is passed in as a function pointer to walk_tree.  *TP is
    the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
    recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
    is set to false if an error has occured.  */
 
-static tree
-find_invalid_stmts_in_loops (tree *tp, int *walk_subtrees, void *data)
+tree
+c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
 {
   if (!tp || !*tp)
     return NULL_TREE;
 
   bool *valid = (bool *) data;
 
-  // FIXME: Disallow the following constructs within a SIMD loop:
-  //
-  // _Cilk_spawn
-  // _Cilk_for
-  // try
-
   /* FIXME: Jumps are disallowed into or out of the body of a
      _Cilk_for.  We can't just check for GOTO_EXPR here, since
      GOTO_EXPR's can also be generated by switches and loops.
@@ -205,7 +200,7 @@ static bool
 c_check_cilk_loop_body (tree body)
 {
   bool valid = true;
-  walk_tree (&body, find_invalid_stmts_in_loops, (void *) &valid, NULL);
+  walk_tree (&body, c_validate_cilk_plus_loop, (void *) &valid, NULL);
   return valid;
 }
 
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 78ace77..f0a488e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1046,6 +1046,12 @@ extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
 extern void c_omp_declare_simd_clauses_to_decls (tree, tree);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 
+/* In c-cilkplus.c  */
+extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree,
+				     tree, tree);
+extern tree c_finish_cilk_clauses (tree);
+extern tree c_validate_cilk_plus_loop (tree *, int *, void *);
+
 /* Not in c-omp.c; provided by the front end.  */
 extern bool c_omp_sharing_predetermined (tree);
 extern tree c_omp_remap_decl (tree, bool);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 84471db..93516da 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -647,11 +647,6 @@ extern tree c_build_va_arg (location_t, tree, tree);
 extern tree c_finish_transaction (location_t, tree, int);
 extern bool c_tree_equal (tree, tree);
 
-/* In c-cilkplus.c */
-extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree,
-				     tree, tree);
-extern tree c_finish_cilk_clauses (tree);
-
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index ea4ec3d..fb7ffc5 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9095,9 +9095,9 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
 
     case 2:
       if (is_break) 
-	error ("break statement within _Cilk_for loop");
+	error ("break statement within <#pragma simd> loop body");
       else 
-	error ("continue statement within _Cilk_for loop");
+	error ("continue statement within <#pragma simd> loop loop");
       return NULL_TREE;
 
     default:
diff --git a/gcc/cp/ChangeLog.cilkplus b/gcc/cp/ChangeLog.cilkplus
new file mode 100644
index 0000000..7254b81
--- /dev/null
+++ b/gcc/cp/ChangeLog.cilkplus
@@ -0,0 +1,18 @@
+2013-05-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* cp-tree.h (p_simd_valid_stmts_in_body_p): New prototype.
+	* parser.h (IN_CILK_P_SIMD_FOR): New #define.
+	* Make-lang.in (CXX_AND_OBJCXX_OBJS): Added new obj-file cp-cilkplus.o
+	* cp-cilkplus.c: New file.
+	* parser.c (cp_parser_pragma): Added a PRAGMA_CILK_SIMD case.
+	(cp_parser_cilk_simd_vectorlength): New function.
+	(cp_parser_cilk_simd_linear): Likewise.
+	(cp_parser_cilk_simd_clause_name): Likewise.
+	(cp_parser_cilk_simd_all_clauses): Likewise.
+	(cp_parser_cilk_simd_construct): Likewise.
+	(cp_parser_simd_for_init_statement): Likewise.
+	(cp_parser_cilk_for_expression_iterator): Likewise.
+	(cp_parser_cilk_for_condition): Likewise.
+	(cp_parser_cilk_for): Likewise.
+	(cp_parser_jump_statement): Added a IN_CILK_P_SIMD_FOR case.
+
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index df8ed3e..0e40246 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -80,7 +80,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/cp-cilkplus.o $(CXX_C_OBJS)
 
 # Language-specific object files for C++.
 CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -345,3 +345,5 @@ cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 
 cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
   $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
+cp/cp-cilkplus.o: cp/cp-cilkplus.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+    $(CXX_TREE_H) $(DIAGNOSTIC_CORE_H)
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
new file mode 100644
index 0000000..f387e2f
--- /dev/null
+++ b/gcc/cp/cp-cilkplus.c
@@ -0,0 +1,83 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains routines to handle Cilk Plus specific
+   routines for the C++ Compiler.
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+		  Aldy Hernandez <aldyh@redhat.com>.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cp-tree.h"
+#include "diagnostic-core.h"
+
+
+/* Callback for cp_walk_tree to validate the body of a pragma simd loop
+   or _cilk_for loop.
+
+   This function is passed in as a function pointer to walk_tree.  *TP is
+   the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
+   recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
+   is set to false if an error has occured.  */
+
+static tree
+cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data)
+{
+  bool *valid = (bool *) data;
+  location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
+    UNKNOWN_LOCATION;
+
+  if (!tp || !*tp)
+    return NULL_TREE;
+
+  // Call generic C version.
+  (void) c_validate_cilk_plus_loop (tp, walk_subtrees, data);
+  
+  if (TREE_CODE (*tp) == THROW_EXPR)
+    {
+      error_at (loc, "throw expressions are not allowed inside loops "
+		"marked with pragma simd");
+      *walk_subtrees = 0;
+      *valid = false;
+    }
+  else if (TREE_CODE (*tp) == TRY_BLOCK)
+    {
+      error_at (loc, "try statements are not allowed inside loops marked "
+		"with #pragma simd");
+      *valid = false;
+      *walk_subtrees = 0;
+    }
+    /* FIXME: Add a check for TREE_CODE (*tp) == CILK_FOR_STMT and
+       flag them as invalid when cilk keywords are adopted.  */
+  return NULL_TREE;
+}  
+
+
+/* Walks through all the subtrees of BODY using walk_tree to make sure
+   invalid statements/expressions are not found inside BODY.  Returns
+   false if any invalid statements are found.  */
+
+bool
+cpp_validate_cilk_plus_loop (tree body)
+{
+  bool valid = true;
+  cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux,
+		(void *) &valid, NULL);
+  return valid;
+}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7046713..97e4e3c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6144,6 +6144,9 @@ extern bool cxx_omp_privatize_by_reference	(const_tree);
 extern void suggest_alternatives_for            (location_t, tree);
 extern tree strip_using_decl                    (tree);
 
+/* in cp-cilkplus.c */
+extern bool cpp_validate_cilk_plus_loop		(tree);
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a30f52a..b4c6ba3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -231,6 +231,11 @@ static void cp_parser_initial_pragma
 static tree cp_literal_operator_id
   (const char *);
 
+static void cp_parser_cilk_simd_construct
+  (cp_parser *, cp_token *);
+static tree cp_parser_cilk_for
+  (cp_parser *, enum rid, tree);
+
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
 #define CP_SAVED_TOKEN_STACK 5
@@ -10297,6 +10302,10 @@ cp_parser_jump_statement (cp_parser* parser)
 	case IN_OMP_FOR:
 	  error_at (token->location, "break statement used with OpenMP for loop");
 	  break;
+	case IN_CILK_P_SIMD_FOR:
+	  error_at (token->location,
+		    "break statement within <#pragma simd> loop body");
+	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
@@ -10314,6 +10323,10 @@ cp_parser_jump_statement (cp_parser* parser)
 	case IN_OMP_BLOCK:
 	  error_at (token->location, "invalid exit from OpenMP structured block");
 	  break;
+	case IN_CILK_P_SIMD_FOR:
+	  error_at (token->location,
+		    "continue statement within <#pragma simd> loop loop");
+	  break;
 	default:
 	  gcc_unreachable ();
 	}
@@ -29851,6 +29864,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 		"%<#pragma omp sections%> construct");
       break;
 
+    case PRAGMA_CILK_SIMD:
+      if (context == pragma_external)
+	goto bad_stmt;
+      cp_parser_cilk_simd_construct (parser, pragma_tok);
+      return true;
+
     default:
       gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
       c_invoke_pragma_handler (id);
@@ -29916,4 +29935,659 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
+
+/* Parses the Cilk Plus #pragma simd vectorlength clause:
+   Syntax:
+   vectorlength ( constant-expression )  */
+
+static tree
+cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  tree expr;
+  /* The vectorlength clause behaves exactly like OpenMP's safelen
+     clause.  Thus, vectorlength is represented as OMP 4.0
+     safelen.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc);
+  
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return error_mark_node;
+  
+  expr = cp_parser_constant_expression (parser, false, NULL);
+  expr = maybe_constant_value (expr);
+
+  if (TREE_CONSTANT (expr)
+	   && exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
+    error_at (loc, "vectorlength must be a power of 2");
+  else if (expr != error_mark_node)
+    {
+      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      clauses = c;
+    }
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    return error_mark_node;
+  return clauses;
+}
+
+/* Handles the Cilk Plus #pragma simd linear clause.
+   Syntax:
+   linear ( simd-linear-variable-list )
+
+   simd-linear-variable-list:
+     simd-linear-variable
+     simd-linear-variable-list , simd-linear-variable
+
+   simd-linear-variable:
+     id-expression
+     id-expression : simd-linear-step
+
+   simd-linear-step:
+   conditional-expression */
+
+static tree
+cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return clauses;
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+    {
+      cp_parser_error (parser, "expected identifier");
+      cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+      return error_mark_node;
+    }
+
+  while (1)
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+	{
+	  cp_parser_error (parser, "expected variable-name");
+	  clauses = error_mark_node;
+	  break;
+	}
+
+      tree var_name = cp_parser_id_expression (parser, false, true, NULL,
+					       false, false);
+      tree decl = cp_parser_lookup_name_simple (parser, var_name,
+						token->location);
+      if (decl == error_mark_node)
+	{
+	  cp_parser_name_lookup_error (parser, var_name, decl, NLE_NULL,
+				       token->location);
+	  clauses = error_mark_node;
+	}
+      else
+	{
+	  tree e = NULL_TREE;
+	  tree step_size = integer_one_node;
+
+	  /* If present, parse the linear step.  Otherwise, assume the default
+	     value of 1.  */
+	  if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+	    {
+	      cp_lexer_consume_token (parser->lexer);
+
+	      e = cp_parser_constant_expression (parser, false, NULL);
+	      e = maybe_constant_value (e);
+
+	      if (e == error_mark_node)
+		{
+		  /* If an error has occurred,  then the whole pragma is
+		     considered ill-formed.  Thus, no reason to keep
+		     parsing.  */
+		  clauses = error_mark_node;
+		  break;
+		}
+	      else if (!TREE_TYPE (e) || !TREE_CONSTANT (e)
+		       || !INTEGRAL_TYPE_P (TREE_TYPE (e)))
+		cp_parser_error (parser,
+				 "step size must be an integer constant");
+	      else
+		step_size = e;
+	    }
+
+	  /* Use the OMP_CLAUSE_LINEAR,  which has the same semantics.  */
+	  tree l = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+	  OMP_CLAUSE_DECL (l) = decl;
+	  OMP_CLAUSE_LINEAR_STEP (l) = step_size;
+	  OMP_CLAUSE_CHAIN (l) = clauses;
+	  clauses = l;
+	}
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+	break;
+      else
+	{
+	  error_at (cp_lexer_peek_token (parser->lexer)->location,
+		    "expected %<,%> or %<)%> after %qE", decl);
+	  clauses = error_mark_node;
+	  break;
+	}
+    }
+  cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+  return clauses;
+}
+
+/* Returns the name of the next clause.  If the clause is not
+   recognized, then PRAGMA_CILK_CLAUSE_NONE is returned and the next
+   token is not consumed.  Otherwise, the appropriate enum from the
+   pragma_simd_clause is returned and the token is consumed.  */
+
+static pragma_cilk_clause
+cp_parser_cilk_simd_clause_name (cp_parser *parser)
+{
+  pragma_cilk_clause clause_type;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->keyword == RID_PRIVATE)
+    clause_type = PRAGMA_CILK_CLAUSE_PRIVATE;
+  else if (!token->u.value || token->type != CPP_NAME)
+    return PRAGMA_CILK_CLAUSE_NONE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "vectorlength"))
+    clause_type = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "linear"))
+    clause_type = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "firstprivate"))
+    clause_type = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "lastprivate"))
+    clause_type = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "reduction"))
+    clause_type = PRAGMA_CILK_CLAUSE_REDUCTION;
+  else
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  cp_lexer_consume_token (parser->lexer);
+  return clause_type;
+}
+
+/* Parses all the #pragma simd clauses.  Returns a list of clauses found.  */
+
+static tree
+cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
+{
+  tree clauses = NULL_TREE;
+
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
+	 && clauses != error_mark_node)
+    {
+      pragma_cilk_clause c_kind;
+      c_kind = cp_parser_cilk_simd_clause_name (parser);
+      if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH)
+	clauses = cp_parser_cilk_simd_vectorlength (parser, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
+	clauses = cp_parser_cilk_simd_linear (parser, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
+	/* Use the OpenMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_FIRSTPRIVATE)
+	/* Use the OpenMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
+					  clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_LASTPRIVATE)
+	/* Use the OMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
+					  clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_REDUCTION)
+	/* Use the OMP 4.0 equivalent function.  */
+	clauses = cp_parser_omp_clause_reduction (parser, clauses);
+      else
+	{
+	  clauses = error_mark_node;
+	  cp_parser_error (parser, "expected %<#pragma simd%> clause");
+	  break;
+	}
+    }
+
+  cp_parser_skip_to_pragma_eol (parser, pragma_token);
+
+  if (clauses == error_mark_node)
+    return error_mark_node;
+  else
+    return c_finish_cilk_clauses (clauses);
+}
+
+/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops.  */
+
+static void
+cp_parser_cilk_simd_construct (cp_parser *parser, cp_token *pragma_token)
+{
+  tree 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))
+    {
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+		"expected for-statement after %<#pragma simd%> clauses");
+      return;
+    }
+
+  /* #pragma simd is built on top of OpenMP 4.0's OMP_SIMD trees.  */
+  if (!flag_openmp)
+    flag_openmp = true;
+
+  tree sb = begin_omp_structured_block ();
+  int save = cp_parser_begin_omp_structured_block (parser);
+  cp_parser_cilk_for (parser, RID_FOR, clauses);
+  cp_parser_end_omp_structured_block (parser, save);
+  add_stmt (finish_omp_structured_block (sb));
+  return;
+}
+
+/* Parses the initializer of a for/_Cilk_for statement.  The initial
+   value is stored in *INIT, and the inital value's declaration is
+   stored as DECL_EXPR in *PRE_BODY.  */
+
+static tree
+cp_parser_simd_for_init_statement (cp_parser *parser, tree *init,
+				   tree *pre_body)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  tree decl = NULL_TREE;
+  cp_decl_specifier_seq type_specifiers;
+  tree this_pre_body = push_stmt_list ();
+  if (token->type == CPP_SEMICOLON)
+    {
+      error_at (loc, "for-loop initializer must declare variable");
+      return error_mark_node;
+    }
+  cp_parser_parse_tentatively (parser);
+  cp_parser_type_specifier_seq (parser, true, false, &type_specifiers);
+  if (cp_parser_parse_definitely (parser))
+    {
+      cp_declarator *cp_decl;
+      tree asm_spec, attr;
+      cp_decl = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+				      NULL, NULL, false);
+      attr = cp_parser_attributes_opt (parser);
+      asm_spec = cp_parser_asm_specification_opt (parser);
+      if (cp_decl == cp_error_declarator)
+	cp_parser_skip_to_end_of_statement (parser);
+      else
+	{
+	  tree pushed_scope, auto_node;
+	  decl = start_decl (cp_decl, &type_specifiers, SD_INITIALIZED, attr,
+			     NULL_TREE, &pushed_scope);
+	  auto_node = type_uses_auto (TREE_TYPE (decl));
+	  if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+	    {
+	      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+		error_at (loc, "parenthesized initialization is "
+			  "not allowed in for-loop");
+	      else
+		{	  
+		  if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+		    decl = error_mark_node;
+		}
+
+	      *init = error_mark_node;
+	      cp_parser_skip_to_end_of_statement (parser);
+	    }
+	  else if (CLASS_TYPE_P (TREE_TYPE (decl)) || auto_node
+		   || type_dependent_expression_p (decl))
+	    {
+	      bool is_direct_init, is_non_constant_init;
+	      *init = cp_parser_initializer (parser, &is_direct_init,
+					    &is_non_constant_init);
+	      if (auto_node)
+		{
+		  TREE_TYPE (decl)
+		    = do_auto_deduction (TREE_TYPE (decl), *init, auto_node);
+		  if (!CLASS_TYPE_P (TREE_TYPE (decl))
+		      && !type_dependent_expression_p (decl))
+		    goto non_class;
+		}
+	      cp_finish_decl (decl, *init, !is_non_constant_init, asm_spec,
+			      LOOKUP_ONLYCONVERTING);
+	      if (CLASS_TYPE_P (TREE_TYPE (decl)))
+		*init = NULL_TREE;
+	      else
+		*init = pop_stmt_list (this_pre_body);
+	      this_pre_body = NULL_TREE;
+	    }
+	  else
+	    {
+	      /* Consume the '='.  */
+	      cp_lexer_consume_token (parser->lexer);
+	      *init = cp_parser_assignment_expression (parser, false, NULL);
+	    non_class:
+	      if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+		*init = error_mark_node;
+	      else
+		cp_finish_decl (decl, NULL_TREE, false, asm_spec,
+				LOOKUP_ONLYCONVERTING);
+	      if (decl != error_mark_node)
+		DECL_INITIAL (decl) = (*init || *init != error_mark_node) ?
+		  *init : NULL_TREE;
+	    }
+	  if (pushed_scope)
+	    pop_scope (pushed_scope);
+	}
+    }
+  else
+    {
+      cp_id_kind idk;
+      cp_parser_parse_tentatively (parser);
+      decl = cp_parser_primary_expression (parser, false, false,
+					   false, &idk);
+      if (!cp_parser_error_occurred (parser) && decl && DECL_P (decl)
+	  && CLASS_TYPE_P (TREE_TYPE (decl)))
+	{
+	  tree rhs, new_expr;
+	  cp_parser_parse_definitely (parser);
+	  cp_parser_require (parser, CPP_EQ, RT_EQ);
+	  rhs = cp_parser_assignment_expression (parser, false, NULL);
+	  new_expr = build_x_modify_expr (EXPR_LOCATION (rhs), decl,
+					  NOP_EXPR, rhs,
+					  tf_warning_or_error);
+	  finish_expr_stmt (new_expr);
+	}
+      else
+	{
+	  decl = NULL_TREE;
+	  cp_parser_abort_tentative_parse (parser);
+	  *init = cp_parser_expression (parser, false, NULL);
+	}
+    }
+  
+  if (this_pre_body)
+    this_pre_body = pop_stmt_list (this_pre_body);
+
+  *pre_body = this_pre_body;
+  return decl;
+}
+  
+
+/* Parses the increment expresion for a cilk_for or for statement with
+   #pragma simd.  */
+
+static tree
+cp_parser_cilk_for_expression_iterator (cp_parser *parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  tree name = NULL_TREE, expr = NULL_TREE;
+  enum tree_code t_code = NOP_EXPR;
+
+  if (token->type == CPP_SEMICOLON)
+    {
+      error_at (token->location, "missing loop expression");
+      return error_mark_node;
+    }
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
+      t_code = token->type == CPP_PLUS_PLUS ? PREINCREMENT_EXPR
+	: PREDECREMENT_EXPR;
+    }
+
+  if (token->type != CPP_NAME)
+    {
+      error_at (token->location, "invalid loop expression");
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  name = cp_parser_lookup_name (parser, token->u.value, none_type, false, false,
+				false, NULL, token->location);
+  if (name == error_mark_node)
+    return error_mark_node;
+
+  /* If name is not a declaration, then the loop is not valid.  */
+  if (!DECL_P (name))
+    {
+      error_at (token->location, "invalid loop increment expression");
+      return error_mark_node;
+    }
+  cp_lexer_consume_token (parser->lexer);
+  token = cp_lexer_peek_token (parser->lexer);
+
+  if (t_code != NOP_EXPR)
+    {
+      if (token->type != CPP_CLOSE_PAREN)
+	{
+	  error_at (token->location, "invalid loop expression");
+	  return error_mark_node;
+	}
+      return build2 (t_code, void_type_node, name, NULL_TREE);
+    }
+
+  if (token->type == CPP_CLOSE_PAREN)
+    {
+      error_at (token->location,
+		"loop expression must modify control variable");
+      return error_mark_node;
+    }
+
+  cp_lexer_consume_token (parser->lexer);
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    return build2 (token->type == CPP_PLUS_PLUS ? POSTINCREMENT_EXPR
+		   : POSTDECREMENT_EXPR, void_type_node, name, NULL_TREE);
+  else if (token->type == CPP_EQ)
+    {
+      sorry ("loop with = operator");
+      return error_mark_node;
+    }
+  else if (token->type == CPP_PLUS_EQ || token->type == CPP_MINUS_EQ)
+    t_code = token->type == CPP_PLUS_EQ  ? PLUS_EXPR : MINUS_EXPR;
+  else if (token->type == CPP_MOD_EQ || token->type == CPP_XOR_EQ
+	   || token->type == CPP_DIV_EQ || token->type == CPP_AND_EQ
+	   || token->type == CPP_OR_EQ || token->type == CPP_AND_EQ
+	   || token->type == CPP_LSHIFT_EQ || token->type == CPP_RSHIFT_EQ)
+    {
+      error_at (token->location, "invalid loop increment operation");
+      return error_mark_node;
+    }
+  else
+    {
+      error_at (token->location, "invalid loop expression");
+      return error_mark_node;
+    }
+  expr = cp_parser_binary_expression (parser, false, false, PREC_NOT_OPERATOR,
+				      NULL);
+  if (expr == error_mark_node)
+    return expr;
+
+  return build2 (MODIFY_EXPR, void_type_node, name,
+		 build2 (t_code, TREE_TYPE (name), name, expr));
+}
+
+/* Parses the condition for a for-loop with pragma simd or _Cilk_for
+   loop.  */
+
+static tree
+cp_parser_cilk_for_condition (cp_parser *parser)
+{
+  tree lhs, rhs;
+  enum tree_code code = ERROR_MARK;
+
+  lhs = cp_parser_binary_expression (parser, false, false,
+				     PREC_SHIFT_EXPRESSION, NULL);
+  switch (cp_lexer_peek_token (parser->lexer)->type)
+    {
+    case CPP_NOT_EQ:
+      code = NE_EXPR;
+      break;    
+    case CPP_LESS:
+      code = LT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      code = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      code = GE_EXPR;
+      break;
+    case CPP_GREATER:
+      code = GT_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+		"equality test not permitted in the Cilk_for loop");
+      break;
+    default:
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+		"missing comparison operator in the loop condition");
+    }
+  cp_lexer_consume_token (parser->lexer);
+
+  rhs = cp_parser_binary_expression (parser, false, false,
+				     PREC_SHIFT_EXPRESSION, NULL);
+  parser->scope = NULL_TREE;
+  parser->qualifying_scope = NULL_TREE;
+  parser->object_scope = NULL_TREE;
+
+  if (code == ERROR_MARK || lhs == error_mark_node || rhs == error_mark_node)
+    return error_mark_node;
+
+  return build2 (code, boolean_type_node, lhs, rhs);
+}
+   
+/* Top-level function to parse _Cilk_for and for statements.  */
+
+static tree
+cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
+{
+  bool valid = true;
+  tree cond = NULL_TREE;
+  tree incr_expr = NULL_TREE;
+  tree init = NULL_TREE, pre_body = NULL_TREE, decl;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  
+  /* FIXME: Allow CILK_FOR into this function.  That is, use this
+     function to parse _Cilk_for statments also.  To do this
+     correctly, add another param.  called "grain" to hold the
+     grainsize.  */
+
+  gcc_assert (for_keyword == RID_FOR);
+
+  if (!cp_lexer_next_token_is_keyword (parser->lexer, for_keyword))
+    {
+      if (for_keyword == RID_FOR)
+	cp_parser_error (parser, "for statement expected");
+      else
+	cp_parser_error (parser, "_Cilk_for statement expected");
+      return error_mark_node;
+    }
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  if (for_keyword == RID_FOR)
+    decl = cp_parser_simd_for_init_statement (parser, &init, &pre_body);
+
+  if (decl == error_mark_node)
+    valid = false;
+  else if (!decl || (TREE_CODE (decl) != VAR_DECL
+		     && TREE_CODE (decl) != DECL_EXPR))
+    {
+      error_at (loc, "%s-loop initializer does not declare a variable",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      valid = false;
+      decl = error_mark_node;
+    }
+  else if (!processing_template_decl
+	   && !DECL_NONTRIVIALLY_INITIALIZED_P (decl)
+	   && !DECL_INITIAL (decl)
+	   && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+    {
+      error_at (loc, "control variable for the %s-loop needs to "
+		"be initialized",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      valid = false;
+    }
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+    {
+      error_at (loc, "%s-loop initializer cannot have multiple variable "
+		"declarations", for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      cp_parser_skip_to_end_of_statement (parser);
+      valid = false;
+    }
+
+  if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
+    return error_mark_node;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    {
+      error_at (loc, "%s-loop requires a condition",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      cond = error_mark_node;
+    }
+  else
+    cond = cp_parser_cilk_for_condition (parser);
+
+  if (cond == error_mark_node)
+    valid = false;
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  
+  if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+    {
+      error_at (loc, "%s-loop requires an increment expression",
+		for_keyword == RID_FOR ? "for" : "_Cilk_for");
+      incr_expr = error_mark_node;
+    }
+  else
+    incr_expr = cp_parser_cilk_for_expression_iterator (parser);
+  
+  if (incr_expr == error_mark_node)
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, false);
+      valid = false;
+    }
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      valid = false;
+    }
+  
+  if (!valid)
+    {
+      gcc_assert (sorrycount || errorcount);
+      return error_mark_node;
+    }
+
+  if (for_keyword == RID_FOR)
+    {
+      tree initv, incrv, condv, declv, omp_simd_node, body = NULL_TREE;
+
+      parser->in_statement = IN_CILK_P_SIMD_FOR;
+      body = push_stmt_list ();
+      cp_parser_statement (parser, NULL_TREE, false, NULL);
+      body = pop_stmt_list (body);
+
+      /* Check if the body satisfies all the requirement of a #pragma
+	 simd for body.  If it is invalid, then do not make the OpenMP
+	 nodes, just return an error mark node.  */
+      if (!cpp_validate_cilk_plus_loop (body))
+	return error_mark_node;
+      
+      /* Now pass all the information into finish_omp_for.  */
+      initv = make_tree_vec (1);
+      condv = make_tree_vec (1);
+      incrv = make_tree_vec (1);
+      declv = make_tree_vec (1);
+      TREE_VEC_ELT (initv, 0) = init;
+      TREE_VEC_ELT (condv, 0) = cond;
+      TREE_VEC_ELT (incrv, 0) = incr_expr;
+      TREE_VEC_ELT (declv, 0) = decl;
+      omp_simd_node = finish_omp_for (loc, OMP_SIMD, declv, initv, condv,
+				      incrv, body, pre_body, clauses);
+      return omp_simd_node;
+    }
+  else
+    /* Fix this when _Cilk_for is added into the mix.  */
+    return NULL_TREE;
+}
+
 #include "gt-cp-parser.h"
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 6d9f1fb..48ec8dd 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -292,6 +292,7 @@ typedef struct GTY(()) cp_parser {
 #define IN_OMP_BLOCK		4
 #define IN_OMP_FOR		8
 #define IN_IF_STMT             16
+#define IN_CILK_P_SIMD_FOR     32
   unsigned char in_statement;
 
   /* TRUE if we are presently parsing the body of a switch statement.
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
new file mode 100644
index 0000000..5ecefd5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -fopenmp" } */
+
+int *a, *b, c;
+void *jmpbuf[10];
+
+void foo()
+{
+  int j;
+
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+      if (c == 5)
+	return;	 /* { dg-error "return statments are not allowed" } */
+      if (c == 6)
+	__builtin_setjmp (jmpbuf); /* { dg-error "calls to setjmp are not allowed" } */
+      a[i] = b[i];
+    }
+
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+      if (c==5)
+	break; /* { dg-error "break statement within" } */
+    }
+
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+#pragma omp for /* { dg-error "OpenMP statements are not allowed" } */
+      for (j=0; j < 1000; ++j)
+	a[i] = b[i];
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c
new file mode 100644
index 0000000..6d84791
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c
@@ -0,0 +1,76 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Werror -Wunknown-pragmas -fcilkplus" } */
+
+volatile int *a, *b;
+
+void foo()
+{
+  int i, j, k;
+
+#pragma simd assert /* { dg-error "expected '#pragma simd' clause" } */
+  for (i=0; i < 100; ++i)
+    a[i] = b[i];
+
+#pragma simd vectorlength /* { dg-error "expected '\\('" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength /* { dg-error "expected '\\('" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength(sizeof (a) == sizeof (float) ? 4 : 8)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength(4,8) /* { dg-error "expected '\\)'" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength(i) /* { dg-error "\(vectorlength must be an integer\|in a constant\)" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(35) /* { dg-error "expected identifier" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(blah) /* { dg-error "'blah' \(undeclared\|has not been\)" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(j, 36, k) /* { dg-error "expected" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i, j)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i : 4)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i : 2, j : 4, k)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(j : sizeof (a) == sizeof (float) ? 4 : 8)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+  // And now everyone in unison!
+#pragma simd linear(j : 4) vectorlength(4)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(blah2, 36)
+  /* { dg-error "'blah2' \(undeclared\|has not been\)" "undeclared" { target *-*-* } 71 } */
+  /* { dg-error "expected" "expected" { target *-*-* } 71 } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c
new file mode 100644
index 0000000..71589c2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-original -fcilkplus" } */
+
+volatile int *a, *b;
+
+void foo()
+{
+  int j, k;
+
+#pragma simd linear(j : 4, k) vectorlength(4)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+}
+
+/* { dg-final { scan-tree-dump-times "linear\\(j:4\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "linear\\(k:1\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "safelen\\(4\\)" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c
new file mode 100644
index 0000000..579b718
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#define N 1000
+
+int A[N], B[N], C[N];
+int main (void)
+{
+#pragma simd private (B) linear(B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd private (B, C) linear(B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd private (B) linear(C:2, B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd reduction (+:B) linear(B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd reduction (+:B) linear(B) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c
new file mode 100644
index 0000000..04773d1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c
@@ -0,0 +1,139 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+int *a, *b, *c;
+int something;
+
+void foo()
+{
+  int i, j;
+
+  // Declaration and initialization is allowed.
+#pragma simd
+  for (int i=0; i < 1000; i++)
+    a[i] = b[j];
+
+  // Empty initialization is not allowed.
+#pragma simd
+  for (; i < 5; ++i)		// { dg-error "expected iteration decl" }
+    a[i] = i;
+
+  // Empty condition is not allowed.
+#pragma simd
+  for (int i=0; ; ++i)		/* { dg-error "missing condition" } */
+    a[i] = i;
+
+  // Empty increment is not allowed.
+#pragma simd
+  for (int i=0; i < 1234; )		/* { dg-error "missing increment" } */
+    a[i] = i*2;
+
+#pragma simd
+  i = 5; /* { dg-error "for statement expected" } */
+
+  // Initialization variables must be either integral or pointer types.
+  struct S {
+    int i;
+  };
+#pragma simd
+  for (struct S ss = { 0 }; ss.i <= 1000; ++ss.i) /* { dg-error "initialization variable must be of integral or pointer type" } */
+    a[ss.i] = b[ss.i];
+
+  #pragma simd
+  for (float f=0.0; f < 15.0; ++f) /* { dg-error "must be of integral" } */
+    a[(int)f] = (int) f;
+
+  // Pointers are OK.
+  #pragma simd
+  for (int *i=c; i < &c[100]; ++i)
+    *a = '5';
+
+  // Condition of '==' is not allowed.
+#pragma simd
+  for (int i=j; i == 5; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];
+
+  // The LHS or RHS of the condition must be the initialization variable.
+#pragma simd
+  for (int i=0; i+j < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];  
+
+  // Likewise.
+#pragma simd
+  for (int i=0; 1234 < i + j; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];  
+
+  // Likewise, this is ok.
+#pragma simd
+  for (int i=0; 1234 + j < i; ++i)
+    a[i] = b[i];
+
+  // According to the CilkPlus forum, casts are not allowed, even if
+  // they are no-ops.
+#pragma simd
+  for (int i=0; (char)i < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=255; i != something; --i)
+    a[i] = b[i];
+
+  // This condition gets folded into "i != 0" by
+  // c_parser_cilk_for_statement().  This is allowed as per the "!="
+  // allowance above.
+#pragma simd
+  for (int i=100; i; --i)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=100; i != 5; i += something)
+    a[i] = b[i];
+
+  // Increment must be on the induction variable.
+#pragma simd
+  for (int i=0; i < 100; j++) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+  // Likewise.
+#pragma simd
+  for (int i=0; i < 100; j = i + 1) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+  // Likewise.
+#pragma simd
+  for (int i=0; i < 100; i = j + 1) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i = i + 5)
+    a[i] = b[i];
+
+  // Only PLUS and MINUS increments are allowed.
+#pragma simd
+  for (int i=0; i < 100; i *= 5) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i -= j)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i = i + j)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i = j + i)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; ++i, ++j) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int *point=0; point < b; ++point)
+    *point = 555;
+
+#pragma simd
+  for (int *point=0; point > b; --point)
+    *point = 555;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
new file mode 100644
index 0000000..dc0a41e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
@@ -0,0 +1,66 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+// Test storage classes in the initialization of a <#pragma simd> for
+// loop.
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+  for (static int foo=5; foo < 10; ++foo)
+    a[foo] = b[foo];
+  /* { dg-error "declaration of static variable" "storage class1" { target *-*-* } 12 } */
+  /* { dg-error "induction variable cannot be static" "storage class2" { target *-*-* } 12 } */
+
+  static int bar;
+#pragma simd
+  for (bar=0; bar < 1000; ++bar) /* { dg-error "induction variable cannot be static" } */
+    a[bar] = bar;
+
+#pragma simd
+  for (extern int var=0; var < 1000; ++var)
+    a[var] = var;
+  /* { dg-error "has both 'extern' and initializer" "extern" { target *-*-* } 23 } */
+  /* { dg-error "declaration of static variable" "" { target *-*-* } 23 } */
+  /* { dg-error "induction variable cannot be static" "" { target *-*-* } 23 } */
+
+  extern int extvar;
+#pragma simd
+  for (extvar = 0; extvar < 1000; ++extvar) /* { dg-error "induction variable cannot be extern" } */
+    b[extvar] = a[extvar];
+
+  // This seems like it should be ok.
+  // Must check with standards people.
+#pragma simd
+  for (auto int autoi = 0; autoi < 1000; ++autoi)
+    b[autoi] = a[autoi] * 2;
+  // Similarly here.
+  auto int autoj;
+#pragma simd
+  for (auto int autoj = 0; autoj < 1000; ++autoj)
+    b[autoj] = a[autoj] * 2;
+
+  register int regi;
+#pragma simd
+  for (regi = 0; regi < 1000; ++regi) /* { dg-error "induction variable cannot be declared register" } */
+    b[regi] = a[regi] * 2;
+
+#pragma simd
+  for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "induction variable cannot be declared register" } */
+    b[regj] = a[regj] * 2;
+
+  volatile int vi;
+#pragma simd
+  for (vi=0; vi<1000; ++vi) /* { dg-error "induction variable cannot be volatile" } */
+    a[vi] = b[vi];
+
+#pragma simd
+  for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable cannot be volatile" } */
+    a[vj] = b[vj];
+
+#pragma simd
+  for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only var" } */
+    a[ci] = b[ci];
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c
new file mode 100644
index 0000000..8660627
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#pragma simd		/* { dg-error "must be inside a function" } */
+
+void foo()
+{
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c
new file mode 100644
index 0000000..2c59de9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-gimple -fcilkplus" } */
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd vectorlength(8)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "safelen\\(8\\)" 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c
new file mode 100644
index 0000000..9aa4a68
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+volatile int *a, *b, N;
+typedef int tint;
+struct someclass {
+  int a;
+  char b;
+  int *p;
+};
+
+void foo()
+{
+#pragma simd vectorlength(4) vectorlength(8) /* { dg-error "too many 'vectorlength' clauses" } */
+  for (int i=0; i < N; ++i)
+    a[i] = b[i];
+
+#pragma simd vectorlength(3) /* { dg-error "must be a power of 2" } */
+  for (int i=0; i < N; ++i)
+    a[i] = b[i];
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
new file mode 100644
index 0000000..ab38903
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -0,0 +1,30 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+# Load support procs.
+load_lib g++-dg.exp
+
+dg-init
+
+# Run the tests that are shared with C.
+g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] ""
+
+# Run the C++ only tests.
+g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
+
+dg-finish
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for.C b/gcc/testsuite/g++.dg/cilk-plus/for.C
new file mode 100644
index 0000000..2295d21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/for.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-ftree-vectorize -fcilkplus" } */
+
+int *a, *b;
+
+void foo()
+{
+  int i;
+#pragma simd
+  for (i=0; i < 10000; ++i) /* { dg-error "initializer does not declare a var" } */
+    a[i] = b[i];
+}
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
index 7201359..a3e9c1f 100644
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -48,6 +48,7 @@ set tests [prune $tests $srcdir/$subdir/tree-prof/*]
 set tests [prune $tests $srcdir/$subdir/torture/*]
 set tests [prune $tests $srcdir/$subdir/graphite/*]
 set tests [prune $tests $srcdir/$subdir/tm/*]
+set tests [prune $tests $srcdir/$subdir/cilk-plus/*]
 set tests [prune $tests $srcdir/$subdir/guality/*]
 set tests [prune $tests $srcdir/$subdir/simulate-thread/*]
 set tests [prune $tests $srcdir/$subdir/asan/*]
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/auto.c b/gcc/testsuite/gcc.dg/cilk-plus/auto.c
new file mode 100644
index 0000000..253acee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/auto.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+int *a, *b;
+
+void foo()
+{
+  // This seems like it should be ok.
+  // Must check with standards people.
+#pragma simd
+  for (auto int autoi = 0; autoi < 1000; ++autoi)
+    b[autoi] = a[autoi] * 2;
+  // Similarly here.
+  auto int autoj;
+#pragma simd
+  for (auto int autoj = 0; autoj < 1000; ++autoj)
+    b[autoj] = a[autoj] * 2;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
new file mode 100644
index 0000000..623c3b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
@@ -0,0 +1,55 @@
+#   Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+
+# Run the tests that are shared with C++.
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] " -ftree-vectorize -fcilkplus -std=c99" " "
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O0 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O1 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O2 -ftree-vectorize -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O3 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O0 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O1 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O3 -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus" " "
+
+# Run the C-only tests.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
+	"-ftree-vectorize -fcilkplus -std=c99" " "
+
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/body.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/body.c
deleted file mode 100644
index 50b3ab1..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/body.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -fcilkplus -fopenmp" } */
-
-int *a, *b, c;
-void *jmpbuf[10];
-
-void foo()
-{
-  int i, j;
-
-#pragma simd
-  for (i=0; i < 1000; ++i)
-    {
-      if (c == 5)
-	return;	 /* { dg-error "return statments are not allowed" } */
-      if (c == 6)
-	__builtin_setjmp (jmpbuf); /* { dg-error "calls to setjmp are not allowed" } */
-      a[i] = b[i];
-    }
-
-#pragma simd
-  for (i=0; i < 1000; ++i)
-    {
-      if (c==5)
-	break; /* { dg-error "break statement within" } */
-    }
-
-#pragma simd
-  for (i=0; i < 1000; ++i)
-    {
-#pragma omp for /* { dg-error "OpenMP statements are not allowed" } */
-      for (j=0; j < 1000; ++j)
-	a[i] = b[i];
-    }
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp
deleted file mode 100644
index 154bb8c..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp
+++ /dev/null
@@ -1,23 +0,0 @@
-#   Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <http://www.gnu.org/licenses/>.
-
-load_lib gcc-dg.exp
-
-set OPTS "-fcilkplus -c -ftree-vectorize"
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " $OPTS" " "
-dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c
deleted file mode 100644
index d0a2f79..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -std=c99 -fcilkplus -Werror -Wunknown-pragmas" } */
-
-volatile int *a, *b;
-
-void foo()
-{
-  int i, j, k;
-
-#pragma simd assert /* { dg-error "expected '#pragma simd' clause" } */
-  for (i=0; i < 100; ++i)
-    a[i] = b[i];
-
-#pragma simd vectorlength /* { dg-error "expected '\\('" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd vectorlength /* { dg-error "expected '\\('" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd vectorlength(sizeof (a) == sizeof (float) ? 4 : 8)
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd vectorlength(4,8) /* { dg-error "expected '\\)'" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd vectorlength(i) /* { dg-error "vectorlength must be an integer" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(35) /* { dg-error "expected identifier" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(blah) /* { dg-error "'blah' undeclared" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(j, 36, k) /* { dg-error "expected '\\)'" } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(i, j)
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(i)
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(i : 4)
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(i : 2, j : 4, k)
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(j : sizeof (a) == sizeof (float) ? 4 : 8)
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-  // And now everyone in unison!
-#pragma simd linear(j : 4) vectorlength(4)
-  for (i=0; i < 1000; ++i)
-    a[i] = b[j];
-
-#pragma simd linear(blah2, 36)
-  /* { dg-error "'blah2' undeclared" "undeclared" { target *-*-* } 71 } */
-  /* { dg-error "expected '\\)'" "expected" { target *-*-* } 71 } */
-  for (int i=0; i < 1000; ++i)
-    a[i] = b[j];
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c
deleted file mode 100644
index ca99ca8..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -std=c99 -fcilkplus -fdump-tree-original" } */
-
-volatile int *a, *b;
-
-void foo()
-{
-  int i, j, k;
-
-#pragma simd linear(j : 4, k) vectorlength(4)
-  for (i=0; i < 1000; ++i)
-    a[i] = b[j];
-}
-
-/* { dg-final { scan-tree-dump-times "linear\\(j:4\\)" 1 "original" } } */
-/* { dg-final { scan-tree-dump-times "linear\\(k:1\\)" 1 "original" } } */
-/* { dg-final { scan-tree-dump-times "safelen\\(4\\)" 1 "original" } } */
-/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses3.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses3.c
deleted file mode 100644
index 5536884..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses3.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -std=c99 -fcilkplus" } */
-
-#define N 1000
-
-int A[N], B[N], C[N];
-int main (void)
-{
-  int ii = 0;
-
-#pragma simd private (B) linear(B:1) /* { dg-error "more than one clause" } */
-  for (ii = 0; ii < N; ii++)
-    {
-      A[ii] = B[ii] + C[ii];
-    }
-
-#pragma simd private (B, C) linear(B:1) /* { dg-error "more than one clause" } */
-  for (ii = 0; ii < N; ii++)
-    {
-      A[ii] = B[ii] + C[ii];
-    }
-
-#pragma simd private (B) linear(C:2, B:1) /* { dg-error "more than one clause" } */
-  for (ii = 0; ii < N; ii++)
-    {
-      A[ii] = B[ii] + C[ii];
-    }
-
-#pragma simd reduction (+:B) linear(B:1) /* { dg-error "more than one clause" } */
-  for (ii = 0; ii < N; ii++)
-    {
-      A[ii] = B[ii] + C[ii];
-    }
-
-#pragma simd reduction (+:B) linear(B) /* { dg-error "more than one clause" } */
-  for (ii = 0; ii < N; ii++)
-    {
-      A[ii] = B[ii] + C[ii];
-    }
-  return 0;
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c
deleted file mode 100644
index f8cc558..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -std=c99 -fcilkplus" } */
-
-int *a, *b, *c;
-int something;
-
-void foo()
-{
-  int i, j;
-
-  // The initialization shall declare or initialize a *SINGLE* variable.
-#pragma simd
-  for (i=0, j=5; i < 1000; i++) // { dg-error "expected ';' before ','" }
-    a[i] = b[j];
-
-  // Declaration and initialization is allowed.
-#pragma simd
-  for (int i=0; i < 1000; i++)
-    a[i] = b[j];
-
-  // Empty initialization is not allowed.
-#pragma simd
-  for (; i < 5; ++i)		// { dg-error "expected iteration decl" }
-    a[i] = i;
-
-  // Empty condition is not allowed.
-#pragma simd
-  for (i=0; ; ++i)		/* { dg-error "missing condition" } */
-    a[i] = i;
-
-  // Empty increment is not allowed.
-#pragma simd
-  for (i=0; i < 1234; )		/* { dg-error "missing increment" } */
-    a[i] = i*2;
-
-#pragma simd
-  i = 5; /* { dg-error "for statement expected" } */
-
-  // Initialization variables must be either integral or pointer types.
-  struct S {
-    int i;
-  };
-#pragma simd
-  for (struct S ss = { 0 }; ss.i <= 1000; ++ss.i) /* { dg-error "initialization variable must be of integral or pointer type" } */
-    a[ss.i] = b[ss.i];
-
-  #pragma simd
-  for (float f=0.0; f < 15.0; ++f) /* { dg-error "must be of integral" } */
-    a[(int)f] = (int) f;
-
-  // Pointers are OK.
-  #pragma simd
-  for (int *i=c; i < &c[100]; ++i)
-    *a = '5';
-
-  // Condition of '==' is not allowed.
-#pragma simd
-  for (i=j; i == 5; ++i) /* { dg-error "invalid controlling predicate" } */
-    a[i] = b[i];
-
-  // The LHS or RHS of the condition must be the initialization variable.
-#pragma simd
-  for (i=0; i+j < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
-    a[i] = b[i];  
-
-  // Likewise.
-#pragma simd
-  for (i=0; 1234 < i + j; ++i) /* { dg-error "invalid controlling predicate" } */
-    a[i] = b[i];  
-
-  // Likewise, this is ok.
-#pragma simd
-  for (i=0; 1234 + j < i; ++i)
-    a[i] = b[i];
-
-  // According to the CilkPlus forum, casts are not allowed, even if
-  // they are no-ops.
-#pragma simd
-  for (i=0; (char)i < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
-    a[i] = b[i];
-
-#pragma simd
-  for (i=255; i != something; --i)
-    a[i] = b[i];
-
-  // This condition gets folded into "i != 0" by
-  // c_parser_cilk_for_statement().  This is allowed as per the "!="
-  // allowance above.
-#pragma simd
-  for (i=100; i; --i)
-    a[i] = b[i];
-
-#pragma simd
-  for (i=100; i != 5; i += something)
-    a[i] = b[i];
-
-  // Increment must be on the induction variable.
-#pragma simd
-  for (i=0; i < 100; j++) /* { dg-error "invalid increment expression" } */
-    a[i] = b[i];
-
-  // Likewise.
-#pragma simd
-  for (i=0; i < 100; j = i + 1) /* { dg-error "invalid increment expression" } */
-    a[i] = b[i];
-
-  // Likewise.
-#pragma simd
-  for (i=0; i < 100; i = j + 1) /* { dg-error "invalid increment expression" } */
-    a[i] = b[i];
-
-#pragma simd
-  for (i=0; i < 100; i = i + 5)
-    a[i] = b[i];
-
-  // Only PLUS and MINUS increments are allowed.
-#pragma simd
-  for (i=0; i < 100; i *= 5) /* { dg-error "invalid increment expression" } */
-    a[i] = b[i];
-
-#pragma simd
-  for (i=0; i < 100; i -= j)
-    a[i] = b[i];
-
-#pragma simd
-  for (i=0; i < 100; i = i + j)
-    a[i] = b[i];
-
-#pragma simd
-  for (i=0; i < 100; i = j + i)
-    a[i] = b[i];
-
-#pragma simd
-  for (i=0; i < 100; ++i, ++j) /* { dg-error "invalid increment expression" } */
-    a[i] = b[i];
-
-#pragma simd
-  for (int *point=0; point < b; ++point)
-    *point = 555;
-
-#pragma simd
-  for (int *point=0; point > b; --point)
-    *point = 555;
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c
deleted file mode 100644
index 2d09ae8..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -std=c99 -fcilkplus" } */
-
-// Test storage classes in the initialization of a <#pragma simd> for
-// loop.
-
-int *a, *b;
-
-void foo()
-{
-#pragma simd
-  for (static int foo=5; foo < 10; ++foo)
-    a[foo] = b[foo];
-  /* { dg-error "declaration of static variable" "storage class1" { target *-*-* } 12 } */
-  /* { dg-error "induction variable cannot be static" "storage class2" { target *-*-* } 12 } */
-
-  static int bar;
-#pragma simd
-  for (bar=0; bar < 1000; ++bar) /* { dg-error "induction variable cannot be static" } */
-    a[bar] = bar;
-
-#pragma simd
-  for (extern int var=0; var < 1000; ++var)
-    a[var] = var;
-  /* { dg-error "has both 'extern' and initializer" "extern" { target *-*-* } 23 } */
-  /* { dg-error "declaration of static variable" "" { target *-*-* } 23 } */
-  /* { dg-error "induction variable cannot be static" "" { target *-*-* } 23 } */
-
-  extern int extvar;
-#pragma simd
-  for (extvar = 0; extvar < 1000; ++extvar) /* { dg-error "induction variable cannot be extern" } */
-    b[extvar] = a[extvar];
-
-  // This seems like it should be ok.
-  // Must check with standards people.
-#pragma simd
-  for (auto int autoi = 0; autoi < 1000; ++autoi)
-    b[autoi] = a[autoi] * 2;
-  // Similarly here.
-  auto int autoj;
-#pragma simd
-  for (auto int autoj = 0; autoj < 1000; ++autoj)
-    b[autoj] = a[autoj] * 2;
-
-  register int regi;
-#pragma simd
-  for (regi = 0; regi < 1000; ++regi) /* { dg-error "induction variable cannot be declared register" } */
-    b[regi] = a[regi] * 2;
-
-#pragma simd
-  for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "induction variable cannot be declared register" } */
-    b[regj] = a[regj] * 2;
-
-  volatile int vi;
-#pragma simd
-  for (vi=0; vi<1000; ++vi) /* { dg-error "induction variable cannot be volatile" } */
-    a[vi] = b[vi];
-
-#pragma simd
-  for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable cannot be volatile" } */
-    a[vj] = b[vj];
-
-#pragma simd
-  for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only var" } */
-    a[ci] = b[ci];
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for3.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for3.c
deleted file mode 100644
index 8660627..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for3.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -fcilkplus" } */
-
-#pragma simd		/* { dg-error "must be inside a function" } */
-
-void foo()
-{
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/safelen.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/safelen.c
deleted file mode 100644
index 430aa41..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/safelen.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -fcilkplus -fdump-tree-gimple" } */
-
-int *a, *b;
-
-void foo()
-{
-  int i;
-#pragma simd vectorlength(8)
-  for (i=0; i < 1000; ++i)
-    a[i] = b[i];
-}
-
-/* { dg-final { scan-tree-dump-times "safelen\\(8\\)" 1 "gimple" } } */
-/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/vectorlength.c b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/vectorlength.c
deleted file mode 100644
index 4bff17d..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/vectorlength.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -fcilkplus" } */
-
-volatile int *a, *b, N;
-typedef int tint;
-struct someclass {
-  int a;
-  char b;
-  int *p;
-};
-
-void foo()
-{
-  int i;
-#pragma simd vectorlength(4) vectorlength(8) /* { dg-error "too many 'vectorlength' clauses" } */
-  for (i=0; i < N; ++i)
-    a[i] = b[i];
-
-#pragma simd vectorlength(3) /* { dg-error "must be a power of 2" } */
-  for (i=0; i < N; ++i)
-    a[i] = b[i];
-}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/for1.c b/gcc/testsuite/gcc.dg/cilk-plus/for1.c
new file mode 100644
index 0000000..4fb5342
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/for1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+int *a, *b, *c;
+
+void foo()
+{
+  int i, j;
+  // The initialization shall declare or initialize a *SINGLE* variable.
+#pragma simd
+  for (i=0, j=5; i < 1000; i++) // { dg-error "expected ';' before ','" }
+    a[i] = b[j];
+}


More information about the Gcc-patches mailing list