diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 54ea04f..e0d6092 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1137,6 +1137,7 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
   c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
+  c-family/c-cilkplus.o \
   c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o
 
 # Language-independent object files.
@@ -1966,6 +1967,9 @@ c-family/c-lex.o : c-family/c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 c-family/c-omp.o : c-family/c-omp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 	$(TREE_H) $(C_COMMON_H) $(GIMPLE_H) langhooks.h
 
+c-family/c-cilkplus.o : c-family/c-cilkplus.c $(CONFIG_H) $(SYSTEM_H) \
+	coretypes.h $(TREE_H) $(C_COMMON_H) langhooks.h
+
 CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@
 c-family/c-opts.o : c-family/c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
         $(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h langhooks.h \
diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
new file mode 100644
index 0000000..d5f069f
--- /dev/null
+++ b/gcc/c-family/c-cilkplus.c
@@ -0,0 +1,278 @@
+/* This file contains routines to construct and validate Cilk Plus
+   constructs within the C and C++ front ends.
+
+   Copyright (C) 2011-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 "tree.h"
+#include "c-common.h"
+
+/* Helper function for c_check_cilk_loop.
+
+   Validate the increment in a _Cilk_for construct or a <#pragma simd>
+   for loop.
+
+   LOC is the location of the `for' keyword.  DECL is the induction
+   variable.  INCR is the original increment expression.
+
+   Returns the canonicalized increment expression for an OMP_FOR_INCR.
+   If there is a validation error, returns error_mark_node.  */
+
+static tree
+c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
+{
+  if (EXPR_HAS_LOCATION (incr))
+    loc = EXPR_LOCATION (incr);
+
+  if (!incr)
+    {
+      error_at (loc, "missing increment");
+      return error_mark_node;
+    }
+
+  switch (TREE_CODE (incr))
+    {
+    case POSTINCREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+      if (TREE_OPERAND (incr, 0) != decl)
+	break;
+
+      // Bah... canonicalize into whatever OMP_FOR_INCR needs.
+      if (POINTER_TYPE_P (TREE_TYPE (decl))
+	  && TREE_OPERAND (incr, 1))
+	{
+	  tree t = fold_convert_loc (loc,
+				     sizetype, TREE_OPERAND (incr, 1));
+
+	  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
+	      || TREE_CODE (incr) == PREDECREMENT_EXPR)
+	    t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
+	  t = fold_build_pointer_plus (decl, t);
+	  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
+	}
+      return incr;
+
+    case MODIFY_EXPR:
+      {
+	tree rhs;
+
+	if (TREE_OPERAND (incr, 0) != decl)
+	  break;
+
+	rhs = TREE_OPERAND (incr, 1);
+	if (TREE_CODE (rhs) == PLUS_EXPR
+	    && (TREE_OPERAND (rhs, 0) == decl
+		|| TREE_OPERAND (rhs, 1) == decl)
+	    && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
+	  return incr;
+	else if (TREE_CODE (rhs) == MINUS_EXPR
+		 && TREE_OPERAND (rhs, 0) == decl
+		 && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
+	  return incr;
+	// Otherwise fail because only PLUS_EXPR and MINUS_EXPR are
+	// allowed.
+	break;
+      }
+
+    default:
+      break;
+    }
+
+  error_at (loc, "invalid increment expression");
+  return error_mark_node;
+}
+
+/* Validate a _Cilk_for construct (or a #pragma simd for loop, which
+   has the same syntactic restrictions).  Returns TRUE if there were
+   no errors, FALSE otherwise.  LOC is the location of the for.  DECL
+   is the controlling variable.  COND is the condition.  INCR is the
+   increment expression.  BODY is the body of the LOOP.  */
+
+static bool
+c_check_cilk_loop (location_t loc, tree decl, tree cond, tree incr, tree body)
+{
+  if (decl == error_mark_node
+      || cond == error_mark_node 
+      || incr == error_mark_node
+      || body == error_mark_node)
+    return false;
+
+  /* Validate the initialization.  */
+  gcc_assert (decl != NULL);
+  if (TREE_THIS_VOLATILE (decl))
+    {
+      error_at (loc, "induction variable cannot be volatile");
+      return false;
+    }
+  if (DECL_EXTERNAL (decl))
+    {
+      error_at (loc, "induction variable cannot be extern");
+      return false;
+    }
+  if (TREE_STATIC (decl))
+    {
+      error_at (loc, "induction variable cannot be static");
+      return false;
+    }
+  if (DECL_REGISTER (decl))
+    {
+      error_at (loc, "induction variable cannot be declared register");
+      return false;
+    }
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
+      && !POINTER_TYPE_P (TREE_TYPE (decl)))
+    {
+      error_at (loc, "initialization variable must be of integral "
+		"or pointer type");
+      return false;
+    }
+
+  /* Validate the condition.  */
+  if (!cond)
+    {
+      error_at (loc, "missing condition");
+      return false;
+    }
+  bool cond_ok = false;
+  if (TREE_CODE (cond) == NE_EXPR
+      || TREE_CODE (cond) == LT_EXPR
+      || TREE_CODE (cond) == LE_EXPR
+      || TREE_CODE (cond) == GT_EXPR
+      || TREE_CODE (cond) == GE_EXPR)
+    {
+      /* Comparison must either be:
+	   DECL <comparison_operator> EXPR
+	   EXPR <comparison_operator> DECL
+      */
+      if (decl == TREE_OPERAND (cond, 0))
+	cond_ok = true;
+      else if (decl == TREE_OPERAND (cond, 1))
+	{
+	  /* Canonicalize the comparison so the DECL is on the LHS.  */
+	  TREE_SET_CODE (cond,
+			 swap_tree_comparison (TREE_CODE (cond)));
+	  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
+	  TREE_OPERAND (cond, 0) = decl;
+	  cond_ok = true;
+	}
+    }
+  if (!cond_ok)
+    {
+      error_at (loc, "invalid controlling predicate");
+      return false;
+    }
+
+  /* Validate the increment.  */
+  incr = c_check_cilk_loop_incr (loc, decl, incr);
+  if (incr == error_mark_node)
+    return false;
+
+  return true;
+ }
+
+/* Validate and emit code for the FOR loop following a #<pragma simd>
+   construct.
+
+   LOC is the location of the location of the FOR.
+   DECL is the iteration variable.
+   INIT is the initialization expression.
+   COND is the controlling predicate.
+   INCR is the increment expression.
+   BODY is the body of the loop.
+   CLAUSES are the clauses associated with the pragma simd loop.
+
+   Returns the generated statement.  */
+
+tree
+c_finish_cilk_simd_loop (location_t loc,
+			 tree decl,
+			 tree init, tree cond, tree incr,
+			 tree body,
+			 tree clauses)
+{
+  location_t rhs_loc;
+
+  if (!c_check_cilk_loop (loc, decl, cond, incr, body))
+    return NULL;
+
+  /* In the case of "for (int i = 0...)", init will be a decl.  It should
+     have a DECL_INITIAL that we can turn into an assignment.  */
+  if (init == decl)
+    {
+      rhs_loc = DECL_SOURCE_LOCATION (decl);
+
+      init = DECL_INITIAL (decl);
+      if (init == NULL)
+	{
+	  error_at (rhs_loc, "%qE is not initialized", decl);
+	  init = integer_zero_node;
+	  return NULL;
+	}
+
+      init = build_modify_expr (loc, decl, NULL_TREE, NOP_EXPR, rhs_loc,
+				init, NULL_TREE);
+    }
+  gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+  gcc_assert (TREE_OPERAND (init, 0) == decl);
+
+  tree initv = make_tree_vec (1);
+  tree condv = make_tree_vec (1);
+  tree incrv = make_tree_vec (1);
+  TREE_VEC_ELT (initv, 0) = init;
+  TREE_VEC_ELT (condv, 0) = cond;
+  TREE_VEC_ELT (incrv, 0) = incr;
+
+  // FIXME: What should we do about nested loops?  Look at specs.
+
+  /* The OpenMP <#pragma omp simd> construct is exactly the same as
+     the Cilk Plus one, with the exception of the vectorlength()
+     clause in Cilk Plus.  Emitting an OMP_SIMD simlifies
+     everything.  */
+  tree t = make_node (OMP_SIMD);
+  TREE_TYPE (t) = void_type_node;
+  OMP_FOR_INIT (t) = initv;
+  OMP_FOR_COND (t) = condv;
+  OMP_FOR_INCR (t) = incrv;
+  OMP_FOR_BODY (t) = body;
+  OMP_FOR_PRE_BODY (t) = NULL;
+  OMP_FOR_CLAUSES (t) = clauses;
+
+  SET_EXPR_LOCATION (t, loc);
+  return add_stmt (t);
+}
+
+/* Validate and emit code for <#pragma simd> clauses.  */
+
+tree
+c_finish_cilk_clauses (tree clauses)
+{
+  // FIXME: "...no variable shall be the subject of more than one
+  // linear clause".  Verify and check for this.
+
+  // FIXME: Also, do whatever we were doing before in
+  // same_var_in_multiple_lists_p, but rewrite to use OMP_CLAUSEs.
+
+  return clauses;
+}
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index b03ddc1..c05b8d0 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1352,6 +1352,12 @@ init_pragma (void)
 				      omp_pragmas[i].id, true, true);
     }
 
+  if (flag_enable_cilk && !flag_preprocess_only)
+    {
+      cpp_register_deferred_pragma (parse_in, NULL, "simd", 
+				    PRAGMA_CILK_SIMD, true, false);
+    }
+
   if (!flag_preprocess_only)
     cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
 				  PRAGMA_GCC_PCH_PREPROCESS, false, false);
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index cd121d4..2ff5a00 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -60,6 +60,9 @@ typedef enum pragma_kind {
   PRAGMA_OMP_THREADPRIVATE,
   PRAGMA_OMP_TEAMS,
 
+  /* Top level clause to handle all Cilk Plus pragma simd clauses.  */
+  PRAGMA_CILK_SIMD,
+
   PRAGMA_GCC_PCH_PREPROCESS,
 
   PRAGMA_FIRST_EXTERNAL
@@ -109,6 +112,19 @@ typedef enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_UNTIED
 } pragma_omp_clause;
 
+/* All Cilk Plus #pragma omp clauses.  */
+typedef enum pragma_cilk_clause {
+  PRAGMA_CILK_CLAUSE_NONE = 0,
+  PRAGMA_CILK_CLAUSE_NOASSERT,
+  PRAGMA_CILK_CLAUSE_ASSERT,
+  PRAGMA_CILK_CLAUSE_VECTORLENGTH,
+  PRAGMA_CILK_CLAUSE_LINEAR,
+  PRAGMA_CILK_CLAUSE_PRIVATE,
+  PRAGMA_CILK_CLAUSE_FIRSTPRIVATE,
+  PRAGMA_CILK_CLAUSE_LASTPRIVATE,
+  PRAGMA_CILK_CLAUSE_REDUCTION
+} pragma_cilk_clause;
+
 extern struct cpp_reader* parse_in;
 
 /* It's safe to always leave visibility pragma enabled as if
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 10ae84d..e502b3f 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -839,6 +839,10 @@ Recognize built-in functions
 fbuiltin-
 C ObjC C++ ObjC++ Joined
 
+fcilkplus
+C ObjC C++ ObjC++ LTO Report Var(flag_enable_cilk) Init(0)
+Enable Cilk
+
 fcanonical-system-headers
 C ObjC C++ ObjC++
 Where shorter, use canonicalized paths to systems headers.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5b06803..41d44a4 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1217,6 +1217,11 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
+/* Cilk Plus supporting routines.  */
+static void c_parser_cilk_for_statement (c_parser *, enum rid, tree);
+static void c_parser_cilk_simd_construct (c_parser *);
+static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -8622,6 +8627,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
       return false;
 
+    case PRAGMA_CILK_SIMD:
+      if (!c_parser_cilk_verify_simd (parser, context))
+	return false;
+      c_parser_consume_pragma (parser);
+      c_parser_cilk_simd_construct (parser);
+      return false;
+
     default:
       if (id < PRAGMA_FIRST_EXTERNAL)
 	{
@@ -10664,7 +10676,457 @@ c_parser_omp_threadprivate (c_parser *parser)
 
   c_parser_skip_to_pragma_eol (parser);
 }
+
+/* Cilk Plus <#pragma simd> parsing routines.  */
+
+/* Helper function for c_parser_pragma.  Perform some sanity checking
+   for <#pragma simd> constructs.  Returns FALSE if there was a
+   problem.  */
+
+static bool
+c_parser_cilk_verify_simd (c_parser *parser,
+				  enum pragma_context context)
+{
+  if (!flag_enable_cilk)
+    {
+      warning (0, "pragma simd ignored because -fcilkplus is not enabled");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  if (!flag_tree_vectorize)
+    {
+      warning (0, "pragma simd is useless without -ftree-vectorize");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  if (context == pragma_external)
+    {
+      c_parser_error (parser,"pragma simd must be inside a function");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  return true;
+}
+
+/* Cilk Plus:
+   assert */
+
+static tree
+c_parser_cilk_clause_assert (c_parser *parser, tree clauses)
+{
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_CILK_ASSERT, "assert");
+
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree c = build_omp_clause (loc, OMP_CLAUSE_CILK_ASSERT);
+  OMP_CLAUSE_CHAIN (c) = clauses;
+  return c;
+}
+
+/* Cilk Plus:
+   noassert */
+
+static tree
+c_parser_cilk_clause_noassert (c_parser *parser ATTRIBUTE_UNUSED,
+			       tree clauses)
+{
+  /* Only check that we don't already have an assert clause.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_CILK_ASSERT, "assert");
+
+  return clauses;
+}
+
+/* Cilk Plus:
+   vectorlength (constant-expression-list )
+
+   constant-expression-list:
+     constant-expression
+     constant-expression-list , constant-expression */
+
+static tree
+c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
+{
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_CILK_VECTORLENGTH,
+			     "vectorlength");
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
+  while (true)
+    {
+      tree expr = c_parser_expr_no_commas (parser, NULL).value;
+      expr = c_fully_fold (expr, false, NULL);
+
+      if (!TREE_TYPE (expr)
+	  || !TREE_CONSTANT (expr)
+	  || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+	error_at (loc, "vectorlength must be an integer constant");
+      else
+	{
+	  tree u = build_omp_clause (loc, OMP_CLAUSE_CILK_VECTORLENGTH);
+	  OMP_CLAUSE_CILK_VECTORLENGTH_EXPR (u) = expr;
+	  OMP_CLAUSE_CHAIN (u) = clauses;
+	  clauses = u;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	{
+	  c_parser_consume_token (parser);
+	  return clauses;
+	}
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+    }
+
+  return clauses;
+}
+
+/* Cilk Plus:
+   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
+c_parser_cilk_clause_linear (c_parser *parser, tree clauses)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
 
+  if (c_parser_next_token_is_not (parser, CPP_NAME)
+      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+    c_parser_error (parser, "expected identifier");
+
+  while (c_parser_next_token_is (parser, CPP_NAME)
+	 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+    {
+      tree var = lookup_name (c_parser_peek_token (parser)->value);
+
+      if (var == NULL)
+	{
+	  undeclared_variable (c_parser_peek_token (parser)->location,
+			       c_parser_peek_token (parser)->value);
+	c_parser_consume_token (parser);
+	}
+      else if (var == error_mark_node)
+	c_parser_consume_token (parser);
+      else
+	{
+	  tree step = integer_one_node;
+
+	  /* Parse the linear step if present.  */
+	  if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	    {
+	      c_parser_consume_token (parser);
+	      c_parser_consume_token (parser);
+
+	      tree expr = c_parser_expr_no_commas (parser, NULL).value;
+	      expr = c_fully_fold (expr, false, NULL);
+
+	      if (!TREE_TYPE (expr)
+		  || !TREE_CONSTANT (expr)
+		  || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+		c_parser_error (parser,
+				"step size must be an integer constant");
+	      else
+		step = expr;
+	    }
+	  else
+	    c_parser_consume_token (parser);
+
+	  /* Use OMP_CLAUSE_LINEAR, which has the same semantics.  */
+	  tree u = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+	  OMP_CLAUSE_DECL (u) = var;
+	  OMP_CLAUSE_LINEAR_STEP (u) = step;
+	  OMP_CLAUSE_CHAIN (u) = clauses;
+	  clauses = u;
+	}
+
+      if (c_parser_next_token_is_not (parser, CPP_COMMA))
+	break;
+
+      c_parser_consume_token (parser);
+    }
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  return clauses;
+}
+
+/* Returns the name of the next clause.  If the clause is not
+   recognized SIMD_OMP_CLAUSE_NONE is returned and the next token is
+   not consumed.  Otherwise, the appropriate pragma_simd_clause is
+   returned and the token is consumed.  */
+
+static pragma_cilk_clause
+c_parser_cilk_clause_name (c_parser *parser)
+{
+  pragma_cilk_clause result;
+  c_token *token = c_parser_peek_token (parser);
+
+  if (!token->value || token->type != CPP_NAME)
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  const char *p = IDENTIFIER_POINTER (token->value);
+
+  if (!strcmp (p, "noassert"))
+    result = PRAGMA_CILK_CLAUSE_NOASSERT;
+  else if (!strcmp (p, "assert"))
+    result = PRAGMA_CILK_CLAUSE_ASSERT;
+  else if (!strcmp (p, "vectorlength"))
+    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (p, "linear"))
+    result = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (p, "private"))
+    result = PRAGMA_CILK_CLAUSE_PRIVATE;
+  else if (!strcmp (p, "firstprivate"))
+    result = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
+  else if (!strcmp (p, "lastprivate"))
+    result = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
+  else if (!strcmp (p, "reduction"))
+    result = PRAGMA_CILK_CLAUSE_REDUCTION;
+  else
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  c_parser_consume_token (parser);
+  return result;
+}
+
+/* Parse all #<pragma simd> clauses.  Return the list of clauses
+   found.  */
+
+static tree
+c_parser_cilk_all_clauses (c_parser *parser)
+{
+  tree clauses = NULL;
+
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      pragma_cilk_clause c_kind;
+
+      c_kind = c_parser_cilk_clause_name (parser);
+
+      switch (c_kind)
+	{
+	case PRAGMA_CILK_CLAUSE_NOASSERT:
+	  clauses = c_parser_cilk_clause_noassert (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_ASSERT:
+	  clauses = c_parser_cilk_clause_assert (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
+	  clauses = c_parser_cilk_clause_vectorlength (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_LINEAR:
+	  clauses = c_parser_cilk_clause_linear (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_PRIVATE:
+	  /* Use the OpenMP counterpart.  */
+	  clauses = c_parser_omp_clause_private (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_FIRSTPRIVATE:
+	  /* Use the OpenMP counterpart.  */
+	  clauses = c_parser_omp_clause_firstprivate (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_LASTPRIVATE:
+	  /* Use the OpenMP counterpart.  */
+	  clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+	  break;
+	case PRAGMA_CILK_CLAUSE_REDUCTION:
+	  /* Use the OpenMP counterpart.  */
+	  clauses = c_parser_omp_clause_reduction (parser, clauses);
+	  break;
+	default:
+	  c_parser_error (parser, "expected %<#pragma simd%> clause");
+	  goto saw_error;
+	}
+    }
+
+ saw_error:
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_cilk_clauses (clauses);
+}
+
+/* Parse the restriction form of the for statement allowed by
+   Cilk Plus.  This function parses both the _CILK_FOR construct as
+   well as the for loop following a <#pragma simd> construct, both of
+   which have the same syntactic restrictions.
+
+   FOR_KEYWORD can be either RID_CILK_FOR or RID_FOR, for parsing
+   _cilk_for or the <#pragma simd> for loop construct respectively.
+
+   (NOTE: For now, only RID_FOR is handled).
+
+   For a <#pragma simd>, CLAUSES are the clauses that should have been
+   previously parsed.  If there are none, or if we are parsing a
+   _Cilk_for instead, this will be NULL.  */
+   
+static void
+c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
+			     tree clauses)
+{
+  tree init, decl,  cond, stmt;
+  tree block, incr, save_break, save_cont, body;
+  location_t loc;
+  bool fail = false;
+
+  gcc_assert (/*for_keyword == RID_CILK_FOR || */for_keyword == RID_FOR);
+
+  if (!c_parser_next_token_is_keyword (parser, for_keyword))
+    {
+      if (for_keyword == RID_FOR)
+	c_parser_error (parser, "for statement expected");
+      else
+	c_parser_error (parser, "_Cilk_for statement expected");
+      return;
+    }
+
+  loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+
+  block = c_begin_compound_stmt (true);
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      add_stmt (c_end_compound_stmt (loc, block, true));
+      return;
+    }
+
+  /* Parse the initialization declaration.  */
+  if (c_parser_next_tokens_start_declaration (parser))
+    {
+      c_parser_declaration_or_fndef (parser, true, false, false,
+				     false, false, NULL);
+      decl = check_for_loop_decls (loc, flag_isoc99);
+      if (decl == NULL)
+	goto error_init;
+      if (DECL_INITIAL (decl) == error_mark_node)
+	decl = error_mark_node;
+      init = decl;
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME)
+	   && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+    {
+      struct c_expr decl_exp;
+      struct c_expr init_exp;
+      location_t init_loc;
+
+      decl_exp = c_parser_postfix_expression (parser);
+      decl = decl_exp.value;
+
+      c_parser_require (parser, CPP_EQ, "expected %<=%>");
+
+      init_loc = c_parser_peek_token (parser)->location;
+      init_exp = c_parser_expr_no_commas (parser, NULL);
+      init_exp = default_function_array_read_conversion (init_loc,
+							 init_exp);
+      init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+				NOP_EXPR, init_loc, init_exp.value,
+				init_exp.original_type);
+      init = c_process_expr_stmt (init_loc, init);
+
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+    }
+  else
+    {
+    error_init:
+      c_parser_error (parser,
+		      "expected iteration declaration or initialization");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				 "expected %<)%>");
+      return;
+    }
+
+  /* Parse the loop condition.  */
+  cond = NULL_TREE;
+  if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
+    {
+      location_t cond_loc = c_parser_peek_token (parser)->location;
+      struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
+							    NULL);
+
+      cond = cond_expr.value;
+      cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+      cond = c_fully_fold (cond, false, NULL);
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+  /* Parse the increment expression.  */
+  incr = NULL_TREE;
+  if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      location_t incr_loc = c_parser_peek_token (parser)->location;
+      incr = c_process_expr_stmt (incr_loc,
+				  c_parser_expression (parser).value);
+    }
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  if (decl == NULL || decl == error_mark_node || init == error_mark_node)
+    fail = true;
+
+  save_break = c_break_label;
+  /* Magic number to inform c_finish_bc_stmt() that we are within a
+     Cilk for construct.  */
+  c_break_label = build_int_cst (size_type_node, 2);
+
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+
+  // FIXME: Disallow the following constructs within a SIMD loop:
+  //
+  // RETURN
+  // GOTO
+  // _Cilk_spawn
+  // _Cilk_for
+  // OpenMP directive or construct
+  // Calls to setjmp()
+
+  if (!fail)
+    {
+      /*
+      // FIXME: Uncomment when RID_CILK_FOR is implemented.
+      if (for_keyword == RID_CILK_FOR)
+	c_finish_cilk_loop (loc, decl, cond, incr, body, grain);
+      else
+      */
+	c_finish_cilk_simd_loop (loc, decl, init, cond, incr, body, clauses);
+    }
+
+  stmt = c_end_compound_stmt (loc, block, true);
+  add_stmt (stmt);
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+}
+
+/* Main entry point for parsing Cilk Plus <#pragma simd> for
+   loops.  */
+
+static void
+c_parser_cilk_simd_construct (c_parser *parser)
+{
+  tree clauses = c_parser_cilk_all_clauses (parser);
+
+  /* For <#pragma simd> we will be generating OMP_SIMD's and let the
+     OpenMP mechanism handle everything.  */
+  if (!flag_openmp)
+    flag_openmp = true;
+
+  c_parser_cilk_for_statement (parser, RID_FOR, clauses);
+}
+
 /* Parse a transaction attribute (GCC Extension).
 
    transaction-attribute:
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c4210a5..0fd9cc6 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -642,6 +642,11 @@ 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/gimplify.c b/gcc/gimplify.c
index f6b6717..013fe43 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6337,6 +6337,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 	case OMP_CLAUSE_MERGEABLE:
 	case OMP_CLAUSE_PROC_BIND:
 	case OMP_CLAUSE_SAFELEN:
+	case OMP_CLAUSE_CILK_ASSERT:
+	case OMP_CLAUSE_CILK_VECTORLENGTH:
 	  break;
 
 	case OMP_CLAUSE_ALIGNED:
@@ -6528,6 +6530,8 @@ gimplify_adjust_omp_clauses (tree *list_p)
 	case OMP_CLAUSE_MERGEABLE:
 	case OMP_CLAUSE_PROC_BIND:
 	case OMP_CLAUSE_SAFELEN:
+	case OMP_CLAUSE_CILK_ASSERT:
+	case OMP_CLAUSE_CILK_VECTORLENGTH:
 	  break;
 
 	default:
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 58117d9..b38ed9b 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1491,6 +1491,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
 	case OMP_CLAUSE_PROC_BIND:
 	case OMP_CLAUSE_SAFELEN:
 	case OMP_CLAUSE_ALIGNED:
+	case OMP_CLAUSE_CILK_ASSERT:
+	case OMP_CLAUSE_CILK_VECTORLENGTH:
 	  break;
 
 	default:
@@ -1547,6 +1549,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
 	case OMP_CLAUSE_PROC_BIND:
 	case OMP_CLAUSE_SAFELEN:
 	case OMP_CLAUSE_ALIGNED:
+	case OMP_CLAUSE_CILK_ASSERT:
+	case OMP_CLAUSE_CILK_VECTORLENGTH:
 	  break;
 
 	default:
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
new file mode 100644
index 0000000..154bb8c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/cilk-simd-compile.exp
@@ -0,0 +1,23 @@
+#   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
new file mode 100644
index 0000000..ae01db3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses1.c
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=c99 -fcilkplus" } */
+
+volatile int *a, *b;
+
+void foo()
+{
+  int i, j, k;
+
+#pragma simd assert aoeu /* { dg-error "expected '#pragma simd' clause" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd noassert aoeu /* { dg-error "expected '#pragma simd' clause" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd assert noassert /* { dg-error "too many 'assert' clauses" } */
+  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 /* { 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)
+  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(blah2, 36)
+  /* { dg-error "'blah2' undeclared" "undeclared" { target *-*-* } 50 } */
+  /* { dg-error "expected '\\)'" "expected" { target *-*-* } 50 } */
+  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 assert linear(j : 4) vectorlength(4)
+  for (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
new file mode 100644
index 0000000..6be6085
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/clauses2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=c99 -fcilkplus -fdump-tree-original" } */
+
+volatile int *a, *b;
+
+void foo()
+{
+  int i, j, k;
+
+#pragma simd assert 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 "cilk_vectorlength\\(4\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "cilk_assert" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
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
new file mode 100644
index 0000000..38700e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for1.c
@@ -0,0 +1,135 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=c99 -fcilkplus" } */
+
+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];
+
+  // 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];
+
+  // ?? This condition gets folded into "i != 0" by
+  // c_parser_cilk_for_statement().  Does this count as a "!=", or is
+  // this disallowed?  Assume it is allowed.
+#pragma simd
+  for (i=100; i; --i)
+    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
new file mode 100644
index 0000000..2d09ae8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/for2.c
@@ -0,0 +1,66 @@
+/* { 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
new file mode 100644
index 0000000..8660627
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-simd/compile/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/tree-pretty-print.c b/gcc/tree-pretty-print.c
index f3de68c..8d1f06e9 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -586,6 +586,17 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
       pp_string (buffer, "taskgroup");
       break;
 
+    case OMP_CLAUSE_CILK_ASSERT:
+      pp_string (buffer, "cilk_assert");
+      break;
+
+    case OMP_CLAUSE_CILK_VECTORLENGTH:
+      pp_string (buffer, "cilk_vectorlength(");
+      dump_generic_node (buffer, OMP_CLAUSE_CILK_VECTORLENGTH_EXPR (clause),
+			 spc, flags, false);
+      pp_character (buffer, ')');
+      break;
+
     default:
       /* Should never happen.  */
       dump_generic_node (buffer, clause, spc, flags, false);
diff --git a/gcc/tree.c b/gcc/tree.c
index 36fadff..2bc6131 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -264,6 +264,8 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_PARALLEL  */
   0, /* OMP_CLAUSE_SECTIONS  */
   0  /* OMP_CLAUSE_TASKGROUP  */
+  , 0, /* OMP_CLAUSE_CILK_ASSERT  */
+  1, /* OMP_CLAUSE_CILK_VECTORLENGTH  */
 };
 
 const char * const omp_clause_code_name[] =
@@ -305,6 +307,8 @@ const char * const omp_clause_code_name[] =
   "parallel",
   "sections",
   "taskgroup"
+  , "cilk_assert",
+  "cilk_vectorlength",
 };
 
 
@@ -10809,6 +10813,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
 	case OMP_CLAUSE_DIST_SCHEDULE:
 	case OMP_CLAUSE_SAFELEN:
 	case OMP_CLAUSE_SIMDLEN:
+	case OMP_CLAUSE_CILK_VECTORLENGTH:
 	  WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
 	  /* FALLTHRU */
 
@@ -10853,6 +10858,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
 	    WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
 	  }
 
+	case OMP_CLAUSE_CILK_ASSERT:
+	  break;
+
 	default:
 	  gcc_unreachable ();
 	}
diff --git a/gcc/tree.h b/gcc/tree.h
index b4bd6c4..75fbebf 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -446,7 +446,13 @@ enum omp_clause_code
   OMP_CLAUSE_SECTIONS,
 
   /* OpenMP clause: taskgroup.  */
-  OMP_CLAUSE_TASKGROUP
+  OMP_CLAUSE_TASKGROUP,
+
+  /* Cilk Plus clause: assert.  */
+  OMP_CLAUSE_CILK_ASSERT,
+
+  /* Cilk Plus clause: vectorlength (constant-expression-list).  */
+  OMP_CLAUSE_CILK_VECTORLENGTH
 };
 
 /* The definition of tree nodes fills the next several pages.  */
@@ -1857,6 +1863,13 @@ extern void protected_set_expr_location (tree, location_t);
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE),	\
 					      OMP_CLAUSE_PRIVATE,	\
 					      OMP_CLAUSE_MAP), 0)
+
+/* In an OMP_SIMD_CLAUSE_CILK_VECTORLENGTH, one vectorlength
+   expression.  */
+#define OMP_CLAUSE_CILK_VECTORLENGTH_EXPR(NODE) \
+  OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK \
+		      (NODE, OMP_CLAUSE_CILK_VECTORLENGTH), 0)
+
 #define OMP_CLAUSE_HAS_LOCATION(NODE) \
   (LOCATION_LOCUS ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus)		\
   != UNKNOWN_LOCATION)
