Patchwork PING: Fwd: Re: [patch] implement Cilk Plus simd loops on trunk

login
register
mail settings
Submitter Aldy Hernandez
Date Aug. 27, 2013, 8:03 p.m.
Message ID <521D060E.9030601@redhat.com>
Download mbox | patch
Permalink /patch/270213/
State New
Headers show

Comments

Aldy Hernandez - Aug. 27, 2013, 8:03 p.m.
On 08/26/13 12:22, Richard Henderson wrote:
>> +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;
>> +    }
>
> Either these tests are swapped, or the second one isn't really needed.

Swapped.  Fixed.

>
>
>> +  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;
>
> Handling pointer types and pointer_plus_expr here (p++) ...
>
>> +    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;
>
> ... but not here (p += 1)?

I should make the code more obvious.  What I'm trying to do is generate 
what the gimplifier for OMP_FOR is expecting.  OMP rewrites pointer 
increment/decrement expressions into a corresponding MODIFY_EXPR.

I have abstracted the OMP code and shared it between both type checks, 
and I have also added an assert in the gimplifier just in case some 
future front-end extension generates OMP_FOR_INCR in a wonky way.

>
>
>> +c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
>> +{
>> +  if (!tp || !*tp)
>> +    return NULL_TREE;
>> +
>> +  bool *valid = (bool *) data;
>> +
>> +  switch (TREE_CODE (*tp))
>> +    {
>> +    case CALL_EXPR:
>> +      {
>> +	tree fndecl = CALL_EXPR_FN (*tp);
>> +
>> +	if (TREE_CODE (fndecl) == ADDR_EXPR)
>> +	  fndecl = TREE_OPERAND (fndecl, 0);
>> +	if (TREE_CODE (fndecl) == FUNCTION_DECL)
>> +	  {
>> +	    if (setjmp_call_p (fndecl))
>> +	      {
>> +		error_at (EXPR_LOCATION (*tp),
>> +			  "calls to setjmp are not allowed within loops "
>> +			  "annotated with #pragma simd");
>> +		*valid = false;
>> +		*walk_subtrees = 0;
>> +	      }
>> +	  }
>> +	break;
>
> Why bother checking for setjmp?  While I agree it makes little sense, there are
> plenty of other standard functions which also make no sense to use from within
> #pragma simd.  What's likely to go wrong with a call to setjmp, as opposed to
> getcontext, pthread_create, or even printf?

Sigh...the standard specifically disallows setjmp.

>
>> +  if (DECL_REGISTER (decl))
>> +    {
>> +      error_at (loc, "induction variable cannot be declared register");
>> +      return false;
>> +    }
>
> Why?

The standard :(.

>
> All of the actual gimple changes look good.  You could commit those now if you
> like to reduce the size of the next patch.

Ughh...got lazy on this round.  How about I commit the gimple changes 
for the next round?

How does this look?
Aldy Hernandez - Sept. 9, 2013, 12:54 p.m.
Hi guys!

PING for both C and C++.

Thanks.


-------- Original Message --------
Subject: Re: PING: Fwd: Re: [patch] implement Cilk Plus simd loops on trunk
Date: Tue, 27 Aug 2013 15:03:26 -0500
From: Aldy Hernandez <aldyh@redhat.com>
To: Richard Henderson <rth@redhat.com>
CC: jason merrill <jason@redhat.com>,  gcc-patches <gcc-patches@gcc.gnu.org>

On 08/26/13 12:22, Richard Henderson wrote:
>> +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;
>> +    }
>
> Either these tests are swapped, or the second one isn't really needed.

Swapped.  Fixed.

>
>
>> +  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;
>
> Handling pointer types and pointer_plus_expr here (p++) ...
>
>> +    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;
>
> ... but not here (p += 1)?

I should make the code more obvious.  What I'm trying to do is generate
what the gimplifier for OMP_FOR is expecting.  OMP rewrites pointer
increment/decrement expressions into a corresponding MODIFY_EXPR.

I have abstracted the OMP code and shared it between both type checks,
and I have also added an assert in the gimplifier just in case some
future front-end extension generates OMP_FOR_INCR in a wonky way.

>
>
>> +c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
>> +{
>> +  if (!tp || !*tp)
>> +    return NULL_TREE;
>> +
>> +  bool *valid = (bool *) data;
>> +
>> +  switch (TREE_CODE (*tp))
>> +    {
>> +    case CALL_EXPR:
>> +      {
>> +	tree fndecl = CALL_EXPR_FN (*tp);
>> +
>> +	if (TREE_CODE (fndecl) == ADDR_EXPR)
>> +	  fndecl = TREE_OPERAND (fndecl, 0);
>> +	if (TREE_CODE (fndecl) == FUNCTION_DECL)
>> +	  {
>> +	    if (setjmp_call_p (fndecl))
>> +	      {
>> +		error_at (EXPR_LOCATION (*tp),
>> +			  "calls to setjmp are not allowed within loops "
>> +			  "annotated with #pragma simd");
>> +		*valid = false;
>> +		*walk_subtrees = 0;
>> +	      }
>> +	  }
>> +	break;
>
> Why bother checking for setjmp?  While I agree it makes little sense, there are
> plenty of other standard functions which also make no sense to use from within
> #pragma simd.  What's likely to go wrong with a call to setjmp, as opposed to
> getcontext, pthread_create, or even printf?

Sigh...the standard specifically disallows setjmp.

>
>> +  if (DECL_REGISTER (decl))
>> +    {
>> +      error_at (loc, "induction variable cannot be declared register");
>> +      return false;
>> +    }
>
> Why?

The standard :(.

>
> All of the actual gimple changes look good.  You could commit those now if you
> like to reduce the size of the next patch.

Ughh...got lazy on this round.  How about I commit the gimple changes
for the next round?

How does this look?
Aldy Hernandez - Sept. 30, 2013, 3:18 p.m.
On 09/09/13 07:54, Aldy Hernandez wrote:

PING^3

> Hi guys!
>
> PING for both C and C++.
>
> Thanks.
>
>
> -------- Original Message --------
> Subject: Re: PING: Fwd: Re: [patch] implement Cilk Plus simd loops on trunk
> Date: Tue, 27 Aug 2013 15:03:26 -0500
> From: Aldy Hernandez <aldyh@redhat.com>
> To: Richard Henderson <rth@redhat.com>
> CC: jason merrill <jason@redhat.com>,  gcc-patches
> <gcc-patches@gcc.gnu.org>
>
> On 08/26/13 12:22, Richard Henderson wrote:
>>> +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;
>>> +    }
>>
>> Either these tests are swapped, or the second one isn't really needed.
>
> Swapped.  Fixed.
>
>>
>>
>>> +  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;
>>
>> Handling pointer types and pointer_plus_expr here (p++) ...
>>
>>> +    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;
>>
>> ... but not here (p += 1)?
>
> I should make the code more obvious.  What I'm trying to do is generate
> what the gimplifier for OMP_FOR is expecting.  OMP rewrites pointer
> increment/decrement expressions into a corresponding MODIFY_EXPR.
>
> I have abstracted the OMP code and shared it between both type checks,
> and I have also added an assert in the gimplifier just in case some
> future front-end extension generates OMP_FOR_INCR in a wonky way.
>
>>
>>
>>> +c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
>>> +{
>>> +  if (!tp || !*tp)
>>> +    return NULL_TREE;
>>> +
>>> +  bool *valid = (bool *) data;
>>> +
>>> +  switch (TREE_CODE (*tp))
>>> +    {
>>> +    case CALL_EXPR:
>>> +      {
>>> +    tree fndecl = CALL_EXPR_FN (*tp);
>>> +
>>> +    if (TREE_CODE (fndecl) == ADDR_EXPR)
>>> +      fndecl = TREE_OPERAND (fndecl, 0);
>>> +    if (TREE_CODE (fndecl) == FUNCTION_DECL)
>>> +      {
>>> +        if (setjmp_call_p (fndecl))
>>> +          {
>>> +        error_at (EXPR_LOCATION (*tp),
>>> +              "calls to setjmp are not allowed within loops "
>>> +              "annotated with #pragma simd");
>>> +        *valid = false;
>>> +        *walk_subtrees = 0;
>>> +          }
>>> +      }
>>> +    break;
>>
>> Why bother checking for setjmp?  While I agree it makes little sense,
>> there are
>> plenty of other standard functions which also make no sense to use
>> from within
>> #pragma simd.  What's likely to go wrong with a call to setjmp, as
>> opposed to
>> getcontext, pthread_create, or even printf?
>
> Sigh...the standard specifically disallows setjmp.
>
>>
>>> +  if (DECL_REGISTER (decl))
>>> +    {
>>> +      error_at (loc, "induction variable cannot be declared register");
>>> +      return false;
>>> +    }
>>
>> Why?
>
> The standard :(.
>
>>
>> All of the actual gimple changes look good.  You could commit those
>> now if you
>> like to reduce the size of the next patch.
>
> Ughh...got lazy on this round.  How about I commit the gimple changes
> for the next round?
>
> How does this look?
>
>
>
Jason Merrill - Oct. 2, 2013, 9:53 p.m.
On 08/27/2013 04:03 PM, Aldy Hernandez wrote:
> +  /* First, try to parse as an initialized declaration.  See
> +     cp_parser_condition, from whence the bulk of this is copied.  */

You didn't do this copy, but I'd appreciate it if you could reintegrate 
this with cp_parser_condition.  I notice that there's already been 
significant drift: this copied code doesn't recognize {} initialization.

> +	      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");

Can't the step size be a value-dependent expression like a template 
non-type parameter?

> +  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC)
> +      || cp_lexer_next_token_is_keyword (parser->lexer, RID_REGISTER)
> +      || cp_lexer_next_token_is_keyword (parser->lexer, RID_EXTERN)
> +      || cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE)
> +      || cp_lexer_next_token_is_keyword (parser->lexer, RID_THREAD))
> +    {
> +      error_at (loc, "storage class is not allowed");
> +      cp_lexer_consume_token (parser->lexer);
> +    }

How is this different from any other for-loop?

> +  gcc_assert (for_keyword == RID_FOR);
> +
> +  if (!cp_lexer_next_token_is_keyword (parser->lexer, for_keyword))
> +    {
> +      if (for_keyword == RID_FOR)

A lot of code in this function tests for_keyword after the assert.  A 
comment lower down says

> +      /* Handle _Cilk_for here when implemented.  */
> +      gcc_unreachable ();

So do we need the earlier assert?  At least add a comment to it.

Jason
Aldy Hernandez - Oct. 16, 2013, 5:48 p.m.
On 10/02/13 16:53, Jason Merrill wrote:
> On 08/27/2013 04:03 PM, Aldy Hernandez wrote:

>
>> +          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");
>
> Can't the step size be a value-dependent expression like a template
> non-type parameter?

[Balaji, this is for the linear clause that is either linear(var) or 
linear(var : step)].

Jason, I'm not sure.  The standard says:

	"The conditional-expression in a simd-linear-step shall either
	satisfy the requirements of an integer constant expression, or
	be a reference to a variable with integer type."

I take this to mean, an integral expression or a plain old variable.  Is 
this the case, Balaji?

Jason, are you asking about the validity of something like this:

int *p;

template <int argoop>
void foobar(int a)
{
   int j = 123;
#pragma simd linear(j : argoop)
   for (int i=0; i < a; ++i)
     p[i] = argoop;
}

void funky()
{
   foobar <69> (1000);
}

If this is what you're asking, and the above standardeese allows it, 
then we have a problem, because the code parsing the "j" in the linear 
clause uses cp_parser_id_expression() which gets horrendously confused 
with the colon, expecting a '::'.  For that matter, even doing this 
causes problems:

	int j = 123, k = 456;
	#pragma simd linear (j : k)
	...

Is this what you were asking about?  If so, then perhaps something 
besides cp_parser_id_expression is in order, for the sake of the 
template argument or just a plain variable.

Aldy
Jason Merrill - Oct. 16, 2013, 6:32 p.m.
On 10/16/2013 01:48 PM, Aldy Hernandez wrote:
> On 10/02/13 16:53, Jason Merrill wrote:

>> Can't the step size be a value-dependent expression like a template
>> non-type parameter?

> Jason, I'm not sure.  The standard says:
>
>      "The conditional-expression in a simd-linear-step shall either
>      satisfy the requirements of an integer constant expression, or
>      be a reference to a variable with integer type."
>
> I take this to mean, an integral expression or a plain old variable.  Is
> this the case, Balaji?

Right.  An integral constant expression can be value-dependent.

> If this is what you're asking, and the above standardeese allows it,
> then we have a problem, because the code parsing the "j" in the linear
> clause uses cp_parser_id_expression() which gets horrendously confused
> with the colon, expecting a '::'.

Sounds like you need to turn off parser->colon_corrects_to_scope_p when 
parsing the pragma arguments.

Jason
Iyer, Balaji V - Oct. 16, 2013, 6:34 p.m.
> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Aldy Hernandez
> Sent: Wednesday, October 16, 2013 1:49 PM
> To: Jason Merrill
> Cc: Richard Henderson; gcc-patches; Iyer, Balaji V
> Subject: Re: PING: Fwd: Re: [patch] implement Cilk Plus simd loops on trunk
> 
> On 10/02/13 16:53, Jason Merrill wrote:
> > On 08/27/2013 04:03 PM, Aldy Hernandez wrote:
> 
> >
> >> +          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");
> >
> > Can't the step size be a value-dependent expression like a template
> > non-type parameter?
> 
> [Balaji, this is for the linear clause that is either linear(var) or linear(var : step)].
> 
> Jason, I'm not sure.  The standard says:
> 
> 	"The conditional-expression in a simd-linear-step shall either
> 	satisfy the requirements of an integer constant expression, or
> 	be a reference to a variable with integer type."
> 
> I take this to mean, an integral expression or a plain old variable.  Is this the
> case, Balaji?
> 
Yup.


> Jason, are you asking about the validity of something like this:
> 
> int *p;
> 
> template <int argoop>
> void foobar(int a)
> {
>    int j = 123;
> #pragma simd linear(j : argoop)
>    for (int i=0; i < a; ++i)
>      p[i] = argoop;
> }
> 
> void funky()
> {
>    foobar <69> (1000);
> }
> 
> If this is what you're asking, and the above standardeese allows it, then we have
> a problem, because the code parsing the "j" in the linear clause uses
> cp_parser_id_expression() which gets horrendously confused with the colon,
> expecting a '::'.  For that matter, even doing this causes problems:
> 

In parser structure, there is a variable that called colon_corrects_to_scope_p. Set that to false right before searching for a colon. That should fix this looking for :: issue.

> 	int j = 123, k = 456;
> 	#pragma simd linear (j : k)
> 	...
> 
> Is this what you were asking about?  If so, then perhaps something besides
> cp_parser_id_expression is in order, for the sake of the template argument or
> just a plain variable.
> 

Thanks,

Balaji V. Iyer.


> Aldy

Patch

--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@ 
+2013-08-27  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.
+	* omp-low.c (extract_omp_for_data): Add case for NE_EXPR.
+	(build_outer_var_ref): Check for GF_OMP_FOR_KIND_SIMD bitwise.
+	(check_omp_nesting_restrictions): Same.
+	(lower_rec_input_clauses): Same.
+	(expand_omp_for): Same.
+	(lower_omp_for): Same.
+	(diagnose_sb_0): Adjust for Cilk Plus for loops.
+	(gate_expand_omp): Check for Cilk Plus.
+	(execute_lower_omp): Same.
+	(gate_diagnose_omp_blocks): Same.
+	* tree.h (OMP_LOOP_CHECK): New.
+	Adapt all OMP_FOR_* macros to use OMP_LOOP_CHECK.
+	* tree.def (CILK_SIMD): New entry.
+	* tree-pretty-print.c (dump_generic_node): Add case for CILK_SIMD.
+	* gimple-pretty-print.c (dump_gimple_omp_for): Add case for
+	GF_OMP_FOR_KIND_CILKSIMD.
+	* gimplify.c (gimplify_omp_for): Add case for CILK_SIMD.
+	(gimplify_expr): Same.
+	(is_gimple_stmt): Same.
+
 2013-08-27  Jakub Jelinek  <jakub@redhat.com>
 	    Aldy Hernandez  <aldyh@redhat.com>
 
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,17 @@ 
+2013-08-27  Aldy Hernandez  <aldyh@redhat.com>
+	    Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-cilkplus.c: New.
+	* c-pragma.c (init_pragma): Register "simd" pragma.
+	* 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_omp_for_incr_canonicalize_ptr): Protoize.
+	* c-omp.c (c_omp_for_incr_canonicalize_ptr): New.
+	(c_finish_omp_for): ...use it.
+
 2013-08-26  Gabriel Dos Reis  <gdre@integrable-solutions.net>
 
 	* c-pretty-print.h (c_pretty_printer::unary_expression): Now a
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,16 @@ 
+2013-08-27  Aldy Hernandez  <aldyh@redhat.com>
+	    Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-parser.c (c_parser_pragma): Add case for PRAGMA_CILK_SIMD.
+	(c_parser_cilk_verify_simd): New.
+	(c_parser_cilk_clause_vectorlength): New.
+	(c_parser_cilk_clause_linear): New.
+	(c_parser_cilk_clause_name): New.
+	(c_parser_cilk_all_clauses): New.
+	(c_parser_cilk_for_statement): New.
+	(c_parser_cilk_simd_construct): New.
+	* c-typeck.c (c_finish_bc_stmt): Add case for _Cilk_for loops.
+
 2013-08-26  Joern Rennecke  <joern.rennecke@embecosm.com>
 	    Joseph Myers  <joseph@codesourcery.com>
 
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@ 
+2013-08-27  Aldy Hernandez  <aldyh@redhat.com>
+	    Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* cp-gimplify.c (cp_gimplify_expr): Add case for CILK_SIMD.
+	(cp_genericize_r): Same.
+	* cp-tree.h (p_simd_valid_stmts_in_body_p): New prototype.
+	(finish_cilk_for_cond): Likewise.
+	* 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.
+	* semantics.c (finish_cilk_for_cond): New.
+	* 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.
+	(cp_parser_omp_for_cond): Abstract initialization code...
+	(cp_parser_omp_for_loop_init): ...here.  New function.
+
 2013-08-27  Jakub Jelinek  <jakub@redhat.com>
 	    Aldy Hernandez  <aldyh@redhat.com>
 
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@ 
+2013-08-27  Aldy Hernandez  <aldyh@redhat.com>
+	    Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* gcc.dg/cilk-plus: New directory and associated infrastructure.
+
 2013-08-27  Vidya Praveen  <vidyapraveen@arm.com>
 
 	* gcc.target/aarch64/scalar_shift_1.c: New.
commit c43d908162e33abeaa3a05e5e15880bd7723a9a9
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Fri Jul 5 15:08:07 2013 -0700

    Cilk Plus <#pragma simd> implementation on top of OMP_SIMD.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 387b60f..ef55042 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1154,7 +1154,7 @@  C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.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-semantics.o c-family/c-ada-spec.o tree-mudflap.o \
-  c-family/array-notation-common.o
+  c-family/array-notation-common.o c-family/c-cilkplus.o
 
 # Language-independent object files.
 # We put the insn-*.o files first so that a parallel make will build
@@ -1986,6 +1986,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..17faec1
--- /dev/null
+++ b/gcc/c-family/c-cilkplus.c
@@ -0,0 +1,403 @@ 
+/* 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 (!incr)
+    {
+      error_at (loc, "missing increment");
+      return error_mark_node;
+    }
+
+  if (EXPR_HAS_LOCATION (incr))
+    loc = EXPR_LOCATION (incr);
+
+  switch (TREE_CODE (incr))
+    {
+    case POSTINCREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+      if (TREE_OPERAND (incr, 0) != decl)
+	break;
+
+      return c_omp_for_incr_canonicalize_ptr (loc, decl, 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;
+}
+
+/* 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.  */
+
+tree
+c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
+{
+  if (!tp || !*tp)
+    return NULL_TREE;
+
+  bool *valid = (bool *) data;
+
+  switch (TREE_CODE (*tp))
+    {
+    case CALL_EXPR:
+      {
+	tree fndecl = CALL_EXPR_FN (*tp);
+
+	if (TREE_CODE (fndecl) == ADDR_EXPR)
+	  fndecl = TREE_OPERAND (fndecl, 0);
+	if (TREE_CODE (fndecl) == FUNCTION_DECL)
+	  {
+	    if (setjmp_call_p (fndecl))
+	      {
+		error_at (EXPR_LOCATION (*tp),
+			  "calls to setjmp are not allowed within loops "
+			  "annotated with #pragma simd");
+		*valid = false;
+		*walk_subtrees = 0;
+	      }
+	  }
+	break;
+      }
+
+    case OMP_PARALLEL:
+    case OMP_TASK:
+    case OMP_FOR:
+    case OMP_SIMD:
+    case OMP_SECTIONS:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_MASTER:
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+    case OMP_ATOMIC:
+    case OMP_ATOMIC_READ:
+    case OMP_ATOMIC_CAPTURE_OLD:
+    case OMP_ATOMIC_CAPTURE_NEW:
+      error_at (EXPR_LOCATION (*tp), "OpenMP statements are not allowed "
+		"within loops annotated with #pragma simd");
+      *valid = false;
+      *walk_subtrees = 0;
+      break;
+
+    default:
+      break;
+    }
+  return NULL_TREE;
+}  
+
+/* Validate the body of a _Cilk_for construct or a <#pragma simd> for
+   loop.
+
+   Returns true if there were no errors, false otherwise.  */
+
+static bool
+c_check_cilk_loop_body (tree body)
+{
+  bool valid = true;
+  walk_tree (&body, c_validate_cilk_plus_loop, (void *) &valid, NULL);
+  return valid;
+}
+
+/* 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.
+
+   INCRP is a pointer the increment expression (in case the increment
+   needs to be canonicalized).
+
+   BODY is the body of the LOOP.
+   SCAN_BODY is true if the body must be checked.  */
+
+static bool
+c_check_cilk_loop (location_t loc, tree decl, tree cond, tree *incrp,
+		   tree body, bool scan_body)
+{
+  tree incr = *incrp;
+
+  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, "induction variable must be of integral "
+		"or pointer type (have %qT)", TREE_TYPE (decl));
+      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 and canonicalize the increment.  */
+  incr = c_check_cilk_loop_incr (loc, decl, incr);
+  if (incr == error_mark_node)
+    return false;
+  *incrp = incr;
+
+  if (scan_body && !c_check_cilk_loop_body (body))
+    return false;
+
+  return true;
+}
+
+/* Adjust any clauses to match the requirements for OpenMP.  */
+
+static tree
+adjust_clauses_for_omp (tree clauses)
+{
+  return clauses;
+}
+
+/* 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.
+   SCAN_BODY is true if the body of the loop must be verified.
+
+   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,
+			 bool scan_body)
+{
+  location_t rhs_loc;
+
+  if (!c_check_cilk_loop (loc, decl, cond, &incr, body, scan_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 = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
+      DECL_INITIAL (decl) = NULL;
+    }
+
+  // The C++ parser just gives us the rhs.
+  if (TREE_CODE (init) != MODIFY_EXPR)
+    init = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
+
+  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;
+
+  tree t = make_node (CILK_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) = adjust_clauses_for_omp (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)
+{
+  for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+    {
+      tree prev = clauses;
+
+      /* If a variable appears in a linear clause it cannot appear in
+	 any other OMP clause.  */
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
+	for (tree c2 = clauses; c2; c2 = OMP_CLAUSE_CHAIN (c2))
+	  {
+	    if (c == c2)
+	      continue;
+	    enum omp_clause_code code = OMP_CLAUSE_CODE (c2);
+
+	    switch (code)
+	      {
+	      case OMP_CLAUSE_LINEAR:
+	      case OMP_CLAUSE_PRIVATE:
+	      case OMP_CLAUSE_FIRSTPRIVATE:
+	      case OMP_CLAUSE_LASTPRIVATE:
+	      case OMP_CLAUSE_REDUCTION:
+		break;
+
+	      case OMP_CLAUSE_SAFELEN:
+		goto next;
+
+	      default:
+		gcc_unreachable ();
+	      }
+
+	    if (OMP_CLAUSE_DECL (c) == OMP_CLAUSE_DECL (c2))
+	      {
+		error_at (OMP_CLAUSE_LOCATION (c2),
+			  "variable appears in more than one clause");
+		inform (OMP_CLAUSE_LOCATION (c),
+			"other clause defined here");
+		// Remove problematic clauses.
+		OMP_CLAUSE_CHAIN (prev) = OMP_CLAUSE_CHAIN (c2);
+	      }
+	  next:
+	    prev = c2;
+	  }
+    }
+
+  return clauses;
+}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index cc09dbc..3f17d59 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -521,6 +521,11 @@  struct GTY(()) c_language_function {
 
 #define building_stmt_list_p() (stmt_list_stack && !stmt_list_stack->is_empty())
 
+/* In c-cilkplus.c */
+extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree,
+				     tree, tree, bool);
+extern tree c_finish_cilk_clauses (tree);
+
 /* Language-specific hooks.  */
 
 /* If non-NULL, this function is called after a precompile header file
@@ -1044,6 +1049,7 @@  extern void c_finish_omp_flush (location_t);
 extern void c_finish_omp_taskwait (location_t);
 extern void c_finish_omp_taskyield (location_t);
 extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
+extern tree c_omp_for_incr_canonicalize_ptr (location_t, tree, tree);
 extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 
@@ -1137,6 +1143,12 @@  enum stv_conv {
 extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
 				       tree op0, tree op1, bool);
 
+/* In c-cilkplus.c  */
+extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree,
+				     tree, tree, bool);
+extern tree c_finish_cilk_clauses (tree);
+extern tree c_validate_cilk_plus_loop (tree *, int *, void *);
+
 /* These #defines allow users to access different operands of the
    array notation tree.  */
 
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index f05b60a..47c9969 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -331,6 +331,28 @@  check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
   return error_mark_node;
 }
 
+/* If the OMP_FOR increment expression in INCR is of pointer type,
+   canonicalize it into an expression handled by gimplify_omp_for()
+   and return it.  DECL is the iteration variable.  */
+
+tree
+c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
+{
+  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;
+}
+
 /* Validate and emit code for the OpenMP directive #pragma omp for.
    DECLV is a vector of iteration variables, for each collapsed loop.
    INITV, CONDV and INCRV are vectors containing initialization
@@ -505,18 +527,7 @@  c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
 		break;
 
 	      incr_ok = true;
-	      if (POINTER_TYPE_P (TREE_TYPE (decl))
-		  && TREE_OPERAND (incr, 1))
-		{
-		  tree t = fold_convert_loc (elocus,
-					     sizetype, TREE_OPERAND (incr, 1));
-
-		  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
-		      || TREE_CODE (incr) == PREDECREMENT_EXPR)
-		    t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
-		  t = fold_build_pointer_plus (decl, t);
-		  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
-		}
+	      incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
 	      break;
 
 	    case MODIFY_EXPR:
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 309859f..428ecfa 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1349,6 +1349,12 @@  init_pragma (void)
 				      omp_pragmas[i].id, true, true);
     }
 
+  if (flag_enable_cilkplus && !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 41215db..4c88dc3 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -45,6 +45,9 @@  typedef enum pragma_kind {
   PRAGMA_OMP_TASKYIELD,
   PRAGMA_OMP_THREADPRIVATE,
 
+  /* Top level clause to handle all Cilk Plus pragma simd clauses.  */
+  PRAGMA_CILK_SIMD,
+
   PRAGMA_GCC_PCH_PREPROCESS,
 
   PRAGMA_FIRST_EXTERNAL
@@ -75,6 +78,17 @@  typedef enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_MERGEABLE
 } pragma_omp_clause;
 
+/* All Cilk Plus #pragma omp clauses.  */
+typedef enum pragma_cilk_clause {
+  PRAGMA_CILK_CLAUSE_NONE = 0,
+  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/c-parser.c b/gcc/c/c-parser.c
index b612e29..26c84bc 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1216,6 +1216,10 @@  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);
 static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
@@ -8952,6 +8956,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)
 	{
@@ -10984,7 +10995,392 @@  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_cilkplus)
+    {
+      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:
+   vectorlength ( constant-expression ) */
+
+static tree
+c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
+{
+  /* The vectorlength clause behaves exactly like OpenMP's safelen
+     clause.  Represent it in OpenMP terms.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
+  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 if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
+    error_at (loc, "vectorlength must be a power of 2");
+  else
+    {
+      tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+      OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
+      OMP_CLAUSE_CHAIN (u) = clauses;
+      clauses = u;
+    }
+
+  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  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, "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_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 induction variable 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,
+							    PREC_NONE);
+
+      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;
+
+  if (!fail)
+    {
+      if (for_keyword == RID_FOR)
+	c_finish_cilk_simd_loop (loc, decl, init, cond, incr, body, clauses,
+				 /*scan_body=*/true);
+    }
+
+  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);
+
+  c_parser_cilk_for_statement (parser, RID_FOR, clauses);
+}
+
 /* Parse a transaction attribute (GCC Extension).
 
    transaction-attribute:
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 8b3e3d9..209f361 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9167,6 +9167,13 @@  c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
       error_at (loc, "break statement used with OpenMP for loop");
       return NULL_TREE;
 
+    case 2:
+      if (is_break) 
+	error ("break statement within <#pragma simd> loop body");
+      else 
+	error ("continue statement within <#pragma simd> loop body");
+      return NULL_TREE;
+
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 2c1774f..7bf0634 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -80,6 +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-cilkplus.o \
  cp/cp-gimplify.o cp/cp-array-notation.o cp/lambda.o \
  cp/vtable-class-hierarchy.o $(CXX_C_OBJS)
 
@@ -354,3 +355,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..ef3bbef
--- /dev/null
+++ b/gcc/cp/cp-cilkplus.c
@@ -0,0 +1,81 @@ 
+/* 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;
+
+  // Validate the C common bits.
+  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;
+    }
+  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 876a72a..a00a8fa 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6153,6 +6153,10 @@  extern void vtv_save_class_info                 (tree);
 extern void vtv_recover_class_info              (void);
 extern void vtv_build_vtable_verify_fndecl      (void);
 
+/* In cp-cilkplus.c.  */
+extern bool cpp_validate_cilk_plus_loop		(tree);
+extern tree finish_cilk_for_cond		(tree);
+
 /* In cp/cp-array-notations.c */
 extern tree expand_array_notation_exprs         (tree);
 bool cilkplus_an_triplet_types_ok_p             (location_t, tree, tree, tree,
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 923277b..3726c60 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
@@ -10370,6 +10375,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;
@@ -10387,6 +10396,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 body");
+	  break;
 	default:
 	  gcc_unreachable ();
 	}
@@ -27528,6 +27541,191 @@  cp_parser_omp_for_incr (cp_parser *parser, tree decl)
   return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
 }
 
+/* Parse the initialization statement of the restricted form of the
+   for statement allowed by OpenMP and Cilk Plus.
+
+   If parsing for OpenMP, PARSING_OPENMP is true.
+
+   A statement list with possible statements to be prepended to the
+   for loop is returned in *THIS_PRE_BODYP.
+
+   Upon return, *INITP will contain the initialization expression,
+   *DECLP will contain the variable declared in the for-init, if any.
+   *REAL_DECL_P will contain the induction variable.  */
+
+static bool
+cp_parser_omp_for_loop_init (cp_parser *parser,
+			     bool parsing_openmp,
+			     tree *this_pre_bodyp,
+			     vec<tree, va_gc> *for_block,
+			     tree *initp,
+			     tree *declp,
+			     tree *real_declp)
+{
+  *initp = *declp = *real_declp = NULL;
+  *this_pre_bodyp = push_stmt_list ();
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    return false;
+
+  /* See 2.5.1 (in OpenMP 3.0, similar wording is in the 2.5 standard too):
+
+     init-expr:
+     var = lb
+     integer-type var = lb
+     random-access-iterator-type var = lb
+     pointer-type var = lb
+  */
+  bool add_private_clause = false;
+  cp_decl_specifier_seq type_specifiers;
+
+  /* First, try to parse as an initialized declaration.  See
+     cp_parser_condition, from whence the bulk of this is copied.  */
+
+  cp_parser_parse_tentatively (parser);
+  cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+				/*is_trailing_return=*/false,
+				&type_specifiers);
+  if (cp_parser_parse_definitely (parser))
+    {
+      /* If parsing a type specifier seq succeeded, then this
+	 MUST be a initialized declaration.  */
+      tree asm_specification, attributes;
+      cp_declarator *declarator;
+
+      declarator = cp_parser_declarator (parser,
+					 CP_PARSER_DECLARATOR_NAMED,
+					 /*ctor_dtor_or_conv_p=*/NULL,
+					 /*parenthesized_p=*/NULL,
+					 /*member_p=*/false);
+      attributes = cp_parser_attributes_opt (parser);
+      asm_specification = cp_parser_asm_specification_opt (parser);
+
+      if (declarator == cp_error_declarator) 
+	cp_parser_skip_to_end_of_statement (parser);
+
+      else 
+	{
+	  tree pushed_scope, auto_node;
+
+	  *declp = start_decl (declarator, &type_specifiers,
+			       SD_INITIALIZED, attributes,
+			       /*prefix_attributes=*/NULL_TREE,
+			       &pushed_scope);
+
+	  auto_node = type_uses_auto (TREE_TYPE (*declp));
+	  if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+	    {
+	      if (cp_lexer_next_token_is (parser->lexer, 
+					  CPP_OPEN_PAREN))
+		{
+		  if (parsing_openmp)
+		    error ("parenthesized initialization is not allowed in "
+			   "OpenMP %<for%> loop");
+		  else
+		    error ("parenthesized initialization is "
+			   "not allowed in for-loop");
+		}
+	      else
+		/* Trigger an error.  */
+		cp_parser_require (parser, CPP_EQ, RT_EQ);
+
+	      *initp = error_mark_node;
+	      cp_parser_skip_to_end_of_statement (parser);
+	    }
+	  else if (CLASS_TYPE_P (TREE_TYPE (*declp))
+		   || type_dependent_expression_p (*declp)
+		   || auto_node)
+	    {
+	      bool is_direct_init, is_non_constant_init;
+
+	      *initp = cp_parser_initializer (parser,
+					      &is_direct_init,
+					      &is_non_constant_init);
+
+	      if (auto_node)
+		{
+		  TREE_TYPE (*declp)
+		    = do_auto_deduction (TREE_TYPE (*declp), *initp,
+					 auto_node);
+
+		  if (!CLASS_TYPE_P (TREE_TYPE (*declp))
+		      && !type_dependent_expression_p (*declp))
+		    goto non_class;
+		}
+
+	      cp_finish_decl (*declp, *initp, !is_non_constant_init,
+			      asm_specification,
+			      LOOKUP_ONLYCONVERTING);
+	      if (CLASS_TYPE_P (TREE_TYPE (*declp)))
+		{
+		  if (for_block)
+		    vec_safe_push (for_block, *this_pre_bodyp);
+		  *initp = NULL_TREE;
+		}
+	      else
+		*initp = pop_stmt_list (*this_pre_bodyp);
+	      *this_pre_bodyp = NULL_TREE;
+	    }
+	  else
+	    {
+	      /* Consume '='.  */
+	      cp_lexer_consume_token (parser->lexer);
+	      *initp = cp_parser_assignment_expression (parser, false, NULL);
+
+	    non_class:
+	      if (TREE_CODE (TREE_TYPE (*declp)) == REFERENCE_TYPE)
+		*initp = error_mark_node;
+	      else
+		cp_finish_decl (*declp, NULL_TREE,
+				/*init_const_expr_p=*/false,
+				asm_specification,
+				LOOKUP_ONLYCONVERTING);
+	    }
+
+	  if (pushed_scope)
+	    pop_scope (pushed_scope);
+	}
+    }
+  else 
+    {
+      cp_id_kind idk;
+      /* If parsing a type specifier sequence failed, then
+	 this MUST be a simple expression.  */
+      cp_parser_parse_tentatively (parser);
+      *declp = cp_parser_primary_expression (parser, false, false,
+					     false, &idk);
+      if (!cp_parser_error_occurred (parser)
+	  && *declp
+	  && DECL_P (*declp)
+	  && CLASS_TYPE_P (TREE_TYPE (*declp)))
+	{
+	  tree rhs;
+
+	  cp_parser_parse_definitely (parser);
+	  cp_parser_require (parser, CPP_EQ, RT_EQ);
+	  rhs = cp_parser_assignment_expression (parser, false, NULL);
+	  finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
+						 *declp, NOP_EXPR,
+						 rhs,
+						 tf_warning_or_error));
+	  add_private_clause = true;
+	}
+      else
+	{
+	  *declp = NULL;
+	  cp_parser_abort_tentative_parse (parser);
+	  *initp = cp_parser_expression (parser, false, NULL);
+	  if (*initp)
+	    {
+	      if (TREE_CODE (*initp) == MODIFY_EXPR
+		  || TREE_CODE (*initp) == MODOP_EXPR)
+		*real_declp = TREE_OPERAND (*initp, 0);
+	    }
+	}
+    }
+  return add_private_clause;
+}
+
 /* Parse the restricted form of the for statement allowed by OpenMP.  */
 
 static tree
@@ -27569,160 +27767,11 @@  cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
 
       if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
 	return NULL;
-
-      init = decl = real_decl = NULL;
-      this_pre_body = push_stmt_list ();
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-	{
-	  /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
-
-	     init-expr:
-	               var = lb
-		       integer-type var = lb
-		       random-access-iterator-type var = lb
-		       pointer-type var = lb
-	  */
-	  cp_decl_specifier_seq type_specifiers;
-
-	  /* First, try to parse as an initialized declaration.  See
-	     cp_parser_condition, from whence the bulk of this is copied.  */
-
-	  cp_parser_parse_tentatively (parser);
-	  cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
-					/*is_trailing_return=*/false,
-					&type_specifiers);
-	  if (cp_parser_parse_definitely (parser))
-	    {
-	      /* If parsing a type specifier seq succeeded, then this
-		 MUST be a initialized declaration.  */
-	      tree asm_specification, attributes;
-	      cp_declarator *declarator;
-
-	      declarator = cp_parser_declarator (parser,
-						 CP_PARSER_DECLARATOR_NAMED,
-						 /*ctor_dtor_or_conv_p=*/NULL,
-						 /*parenthesized_p=*/NULL,
-						 /*member_p=*/false);
-	      attributes = cp_parser_attributes_opt (parser);
-	      asm_specification = cp_parser_asm_specification_opt (parser);
-
-	      if (declarator == cp_error_declarator) 
-		cp_parser_skip_to_end_of_statement (parser);
-
-	      else 
-		{
-		  tree pushed_scope, auto_node;
-
-		  decl = start_decl (declarator, &type_specifiers,
-				     SD_INITIALIZED, attributes,
-				     /*prefix_attributes=*/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 ("parenthesized initialization is not allowed in "
-			       "OpenMP %<for%> loop");
-		      else
-			/* Trigger an error.  */
-			cp_parser_require (parser, CPP_EQ, RT_EQ);
-
-		      init = error_mark_node;
-		      cp_parser_skip_to_end_of_statement (parser);
-		    }
-		  else if (CLASS_TYPE_P (TREE_TYPE (decl))
-			   || type_dependent_expression_p (decl)
-			   || auto_node)
-		    {
-		      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_specification,
-				      LOOKUP_ONLYCONVERTING);
-		      if (CLASS_TYPE_P (TREE_TYPE (decl)))
-			{
-			  vec_safe_push (for_block, this_pre_body);
-			  init = NULL_TREE;
-			}
-		      else
-			init = pop_stmt_list (this_pre_body);
-		      this_pre_body = NULL_TREE;
-		    }
-		  else
-		    {
-		      /* Consume '='.  */
-		      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,
-					/*init_const_expr_p=*/false,
-					asm_specification,
-					LOOKUP_ONLYCONVERTING);
-		    }
-
-		  if (pushed_scope)
-		    pop_scope (pushed_scope);
-		}
-	    }
-	  else 
-	    {
-	      cp_id_kind idk;
-	      /* If parsing a type specifier sequence failed, then
-		 this MUST be a simple expression.  */
-	      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;
-
-		  cp_parser_parse_definitely (parser);
-		  cp_parser_require (parser, CPP_EQ, RT_EQ);
-		  rhs = cp_parser_assignment_expression (parser, false, NULL);
-		  finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
-							 decl, NOP_EXPR,
-							 rhs,
-							 tf_warning_or_error));
-		  add_private_clause = true;
-		}
-	      else
-		{
-		  decl = NULL;
-		  cp_parser_abort_tentative_parse (parser);
-		  init = cp_parser_expression (parser, false, NULL);
-		  if (init)
-		    {
-		      if (TREE_CODE (init) == MODIFY_EXPR
-			  || TREE_CODE (init) == MODOP_EXPR)
-			real_decl = TREE_OPERAND (init, 0);
-		    }
-		}
-	    }
-	}
+      add_private_clause |=
+	cp_parser_omp_for_loop_init (parser,
+				     /*parsing_openmp=*/true,
+				     &this_pre_body, for_block,
+				     &init, &decl, &real_decl);
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       if (this_pre_body)
 	{
@@ -28743,6 +28792,16 @@  cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 		"%<#pragma omp sections%> construct");
       break;
 
+    case PRAGMA_CILK_SIMD:
+      if (context == pragma_external)
+	{
+	  error_at (pragma_tok->location,
+		    "%<#pragma simd%> must be inside a function");
+	  break;
+	}
+      cp_parser_cilk_simd_construct (parser, pragma_tok);
+      return true;
+
     default:
       gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
       c_invoke_pragma_handler (id);
@@ -28808,4 +28867,414 @@  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,
+		"for statement expected");
+      return;
+    }
+
+  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;
+
+  if (token->type == CPP_SEMICOLON)
+    {
+      error_at (loc, "expected induction variable");
+      return error_mark_node;
+    }
+
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC)
+      || cp_lexer_next_token_is_keyword (parser->lexer, RID_REGISTER)
+      || cp_lexer_next_token_is_keyword (parser->lexer, RID_EXTERN)
+      || cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE)
+      || cp_lexer_next_token_is_keyword (parser->lexer, RID_THREAD))
+    {
+      error_at (loc, "storage class is not allowed");
+      cp_lexer_consume_token (parser->lexer);
+    }
+
+  tree this_pre_body, decl, real_decl;
+  (void) cp_parser_omp_for_loop_init (parser,
+				      /*parsing_openmp=*/false,
+				      &this_pre_body,
+				      /*for_block=*/NULL,
+				      init, &decl, &real_decl);
+  if (this_pre_body)
+    this_pre_body = pop_stmt_list (this_pre_body);
+
+  *pre_body = this_pre_body;
+  return decl;
+}
+
+/* Top-level function to parse _Cilk_for and the for statement
+   following <#pragma simd>.  */
+
+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;
+  
+  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;
+    }
+
+  /* Parse initialization.  */
+  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;
+    }
+  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 (!valid)
+    {
+      /* Skip to the semicolon ending the init.  */
+      cp_parser_skip_to_end_of_statement (parser);
+    }
+
+  /* Parse condition.  */
+  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, "missing condition");
+      cond = error_mark_node;
+    }
+  else
+    {
+      cond = cp_parser_condition (parser);
+      cond = finish_cilk_for_cond (cond);
+    }
+
+  if (cond == error_mark_node)
+    valid = false;
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+  /* Parse increment.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+    {
+      error_at (loc, "missing increment");
+      incr_expr = error_mark_node;
+    }
+  else
+    incr_expr = cp_parser_expression (parser, false, NULL);
+  
+  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)
+    {
+      parser->in_statement = IN_CILK_P_SIMD_FOR;
+      tree 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;
+
+      return c_finish_cilk_simd_loop (loc, decl, init, cond, incr_expr,
+				      body, clauses,
+				      /*scan_body=*/false);
+    }
+  else
+    {
+      /* Handle _Cilk_for here when implemented.  */
+      gcc_unreachable ();
+      return NULL_TREE;
+    }
+}
+
 #include "gt-cp-parser.h"
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 3d8bb74..4fbc655 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/cp/semantics.c b/gcc/cp/semantics.c
index ee3503c..9d91d99 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5145,6 +5145,13 @@  finish_omp_taskyield (void)
   finish_expr_stmt (stmt);
 }
 
+/* Perform any canonicalization of the conditional in a Cilk for loop.  */
+tree
+finish_cilk_for_cond (tree cond)
+{
+  return cp_truthvalue_conversion (cond);
+}
+
 /* Begin a __transaction_atomic or __transaction_relaxed statement.
    If PCOMPOUND is non-null, this is for a function-transaction-block, and we
    should create an extra compound stmt.  */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 3ab558c..67be47b 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1097,6 +1097,9 @@  dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
 	case GF_OMP_FOR_KIND_SIMD:
 	  kind = " simd";
 	  break;
+	case GF_OMP_FOR_KIND_CILKSIMD:
+	  kind = " cilksimd";
+	  break;
 	default:
 	  gcc_unreachable ();
 	}
@@ -1125,6 +1128,9 @@  dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
 	case GF_OMP_FOR_KIND_SIMD:
 	  pp_string (buffer, "#pragma omp simd");
 	  break;
+	case GF_OMP_FOR_KIND_CILKSIMD:
+	  pp_string (buffer, "#pragma simd");
+	  break;
 	default:
 	  gcc_unreachable ();
 	}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 9f29561..6eab2ad 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -112,7 +112,8 @@  enum gf_mask {
     GF_OMP_PARALLEL_COMBINED	= 1 << 0,
     GF_OMP_FOR_KIND_MASK	= 3 << 0,
     GF_OMP_FOR_KIND_FOR		= 0 << 0,
-    GF_OMP_FOR_KIND_SIMD	= 1 << 0,
+    GF_OMP_FOR_KIND_SIMD	= 2 << 0,
+    GF_OMP_FOR_KIND_CILKSIMD	= 3 << 0,
 
     /* True on an GIMPLE_OMP_RETURN statement if the return does not require
        a thread synchronization via some sort of barrier.  The exact barrier
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 3b3adb3..7273d35 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4710,6 +4710,7 @@  is_gimple_stmt (tree t)
     case OMP_PARALLEL:
     case OMP_FOR:
     case OMP_SIMD:
+    case CILK_SIMD:
     case OMP_SECTIONS:
     case OMP_SECTION:
     case OMP_SINGLE:
@@ -6583,7 +6584,8 @@  gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 
   for_stmt = *expr_p;
 
-  simd = TREE_CODE (for_stmt) == OMP_SIMD; 
+  simd = TREE_CODE (for_stmt) == OMP_SIMD
+    || TREE_CODE (for_stmt) == CILK_SIMD;
   gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
 			     simd ? ORT_SIMD : ORT_WORKSHARE);
 
@@ -6623,7 +6625,8 @@  gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
   for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
     {
       t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
-      gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
+      gcc_assert (TREE_CODE (t) == MODIFY_EXPR
+		  || TREE_CODE (t) == INIT_EXPR);
       decl = TREE_OPERAND (t, 0);
       gcc_assert (DECL_P (decl));
       gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
@@ -6708,13 +6711,21 @@  gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 	{
 	case PREINCREMENT_EXPR:
 	case POSTINCREMENT_EXPR:
-	  t = build_int_cst (TREE_TYPE (decl), 1);
-	  if (c)
-	    OMP_CLAUSE_LINEAR_STEP (c) = t;
-	  t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
-	  t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
-	  TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
-	  break;
+	  {
+	    tree decl = TREE_OPERAND (t, 0);
+
+	    // The c_omp_for_incr_canonicalize_ptr() should have been
+	    // called to massage things appropriately.
+	    gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+
+	    t = build_int_cst (TREE_TYPE (decl), 1);
+	    if (c)
+	      OMP_CLAUSE_LINEAR_STEP (c) = t;
+	    t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
+	    t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
+	    TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
+	    break;
+	  }
 
 	case PREDECREMENT_EXPR:
 	case POSTDECREMENT_EXPR:
@@ -6809,6 +6820,7 @@  gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
     {
     case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
     case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
+    case CILK_SIMD: kind = GF_OMP_FOR_KIND_CILKSIMD; break;
     default:
       gcc_unreachable ();
     }
@@ -7751,6 +7763,7 @@  gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
 	case OMP_FOR:
 	case OMP_SIMD:
+	case CILK_SIMD:
 	  ret = gimplify_omp_for (expr_p, pre_p);
 	  break;
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index d24270f..2250451 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -223,7 +223,7 @@  extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
   int i;
   struct omp_for_data_loop dummy_loop;
   location_t loc = gimple_location (for_stmt);
-  bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
+  bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
 
   fd->for_stmt = for_stmt;
   fd->pre = NULL;
@@ -309,6 +309,10 @@  extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
 	case LT_EXPR:
 	case GT_EXPR:
 	  break;
+	case NE_EXPR:
+	  gcc_assert (gimple_omp_for_kind (for_stmt)
+		      == GF_OMP_FOR_KIND_CILKSIMD);
+	  break;
 	case LE_EXPR:
 	  if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
 	    loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
@@ -933,7 +937,7 @@  build_outer_var_ref (tree var, omp_context *ctx)
       x = build_receiver_ref (var, by_ref, ctx);
     }
   else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-	   && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+	   && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     {
       /* #pragma omp simd isn't a worksharing construct, and can reference even
 	 private vars in its linear etc. clauses.  */
@@ -1864,7 +1868,7 @@  check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
   if (ctx != NULL)
     {
       if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-	  && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+	  && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
 	{
 	  error_at (gimple_location (stmt),
 		    "OpenMP constructs may not be nested inside simd region");
@@ -1874,7 +1878,7 @@  check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
   switch (gimple_code (stmt))
     {
     case GIMPLE_OMP_FOR:
-      if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
+      if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
 	return true;
       /* FALLTHRU */
     case GIMPLE_OMP_SECTIONS:
@@ -2378,7 +2382,7 @@  lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
   bool lastprivate_firstprivate = false;
   int pass;
   bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-		  && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
+		  && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
   int max_vf = 0;
   tree lane = NULL_TREE, idx = NULL_TREE;
   tree ivar = NULL_TREE, lvar = NULL_TREE;
@@ -2835,7 +2839,7 @@  lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       /* Don't add any barrier for #pragma omp simd or
 	 #pragma omp distribute.  */
       if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
-	  || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
+	  || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
 	gimplify_and_add (build_omp_barrier (), ilist);
     }
 
@@ -2914,7 +2918,7 @@  lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
     }
 
   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-      && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+      && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     {
       simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
       if (simduid)
@@ -3009,7 +3013,7 @@  lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
 
   /* SIMD reductions are handled in lower_rec_input_clauses.  */
   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-      && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+      && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     return;
 
   /* First see if there is exactly one reduction clause.  Use OMP_ATOMIC
@@ -5726,7 +5730,7 @@  expand_omp_for (struct omp_region *region)
        original loops from being detected.  Fix that up.  */
     loops_state_set (LOOPS_NEED_FIXUP);
 
-  if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
+  if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
     expand_omp_simd (region, &fd);
   else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
       && !fd.have_ordered
@@ -6831,7 +6835,7 @@  execute_expand_omp (void)
 static bool
 gate_expand_omp (void)
 {
-  return (flag_openmp != 0 && !seen_error ());
+  return ((flag_openmp || flag_enable_cilkplus) && !seen_error ());
 }
 
 namespace {
@@ -8000,7 +8004,7 @@  execute_lower_omp (void)
 
   /* This pass always runs, to provide PROP_gimple_lomp.
      But there is nothing to do unless -fopenmp is given.  */
-  if (flag_openmp == 0)
+  if (!flag_openmp && !flag_enable_cilkplus)
     return 0;
 
   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
@@ -8120,12 +8124,33 @@  diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
     error ("invalid entry to OpenMP structured block");
 #endif
 
+  bool cilkplus_block = false;
+  if (flag_enable_cilkplus)
+    {
+      if ((branch_ctx
+	   && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
+	   && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
+	  || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
+	      && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
+	cilkplus_block = true;
+    }
+
   /* If it's obvious we have an invalid entry, be specific about the error.  */
   if (branch_ctx == NULL)
-    error ("invalid entry to OpenMP structured block");
+    {
+      if (cilkplus_block)
+	error ("invalid entry to Cilk Plus structured block");
+      else
+	error ("invalid entry to OpenMP structured block");
+    }
   else
-    /* Otherwise, be vague and lazy, but efficient.  */
-    error ("invalid branch to/from an OpenMP structured block");
+    {
+      /* Otherwise, be vague and lazy, but efficient.  */
+      if (cilkplus_block)
+	error ("invalid branch to/from a Cilk Plus structured block");
+      else
+	error ("invalid branch to/from an OpenMP structured block");
+    }
 
   gsi_replace (gsi_p, gimple_build_nop (), false);
   return true;
@@ -8308,7 +8333,7 @@  diagnose_omp_structured_block_errors (void)
 static bool
 gate_diagnose_omp_blocks (void)
 {
-  return flag_openmp != 0;
+  return flag_openmp || flag_enable_cilkplus;
 }
 
 namespace {
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..e8e2066
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
@@ -0,0 +1,33 @@ 
+/* { 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 == 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..e9e140d
--- /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 induction variable" }
+    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 "induction 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/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/for4.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for4.c
new file mode 100644
index 0000000..2da8235
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for4.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+int *a, *c;
+
+void foo()
+{
+  int i, j;
+
+  // Pointers are OK.
+  #pragma simd
+  for (int *i=c; i < c; ++i)
+    *a = '5';
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for5.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for5.c
new file mode 100644
index 0000000..7075a44
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/for5.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+  for (int i=100; i; --i)
+    a[i] = b[i];
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c
new file mode 100644
index 0000000..81a1abb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c
@@ -0,0 +1,38 @@ 
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+/* FIXME: This test has been xfailed until reductions are fixed.  */
+
+int argc = 1;
+
+/* This is a simple vectorization test.  It tests if reduction works
+   and if it can vectorize the loop in func correctly. */
+#define N 1000
+
+int func (int *p, int *q) {
+    int x = 0;
+#pragma simd reduction (+:x)
+    for (int ii = 0; ii < N; ii++) { 
+	x += (q[ii] + p[ii]);
+    }
+    return x; 
+
+}
+
+int main ()
+{
+  int ii = 0, x;
+  int Array[N], Array2[N];
+
+  for (ii = 0; ii < N; ii++)
+    {
+      Array[ii] = 5 + argc;
+      Array2[ii] = argc;
+    }
+  x = func (Array, Array2);
+
+  if (x != N * 7)
+    return 1;
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c
new file mode 100644
index 0000000..912d5f5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c
@@ -0,0 +1,38 @@ 
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+/* FIXME: This test has been xfailed until reductions are fixed.  */
+
+#include <stdio.h>
+
+#define ARRAY_SIZE  (256)
+int a[ARRAY_SIZE];
+
+__attribute__((noinline))
+int addit (int *arr, int N)
+{
+  int s=0;
+#pragma simd reduction (+:s)
+  for (int i = 0; i < N; i++)
+    s += arr[i];
+  return s;
+}
+
+int main () {
+  int i, s = 0, r = 0;
+  for (i = 0; i < ARRAY_SIZE; i++)
+    {
+      a[i] = i;
+    }
+
+  s = addit (a, ARRAY_SIZE);
+
+  for (i = 0; i < ARRAY_SIZE; i++) 
+    r += i;
+
+  if (s == r)
+    return 0;
+  else
+    return 1;
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c
new file mode 100644
index 0000000..3508c02
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c
@@ -0,0 +1,43 @@ 
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+/* FIXME: This test has been xfailed until reductions are fixed.  */
+
+#define N 256
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <malloc.h>
+
+int
+reduction_simd (int *a)
+{
+  int s = 0;
+
+#pragma simd reduction (+:s)
+  for (int i = 0; i < N; i++)
+    {
+      s += a[i];
+    }
+
+  return s;
+}
+
+int
+main ()
+{
+  int *a = (int *) malloc (N * sizeof (int));
+  int i, s = (N - 1) * N / 2;
+
+  for (i = 0; i < N; i++)
+    {
+      a[i] = i;
+    }
+#if HAVE_IO
+  printf ("%d, %d\n", s, reduction_simd (a));
+#endif
+  if (s == reduction_simd (a))
+    return 0;
+  else
+    return 1;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c
new file mode 100644
index 0000000..c8fe1c7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c
@@ -0,0 +1,28 @@ 
+/* { dg-do run } */
+/* { dg-options "-fcilkplus -O3" } */
+
+#include <stdlib.h>
+
+#define N 4
+
+float f1[] =  { 2.0, 3.0,  4.0,  5.0 };
+float f2[] =  { 1.0, 6.0, -1.0, -2.0 };
+float res[] = { 3.0, 9.0,  3.0,  3.0 };
+
+__attribute__((noinline))
+void verify (float *sum)
+{
+  for (int i=0; i < N; ++i)
+    if (sum[i] != res[i])
+      abort ();
+}
+
+int main()
+{
+  float sum[N];
+#pragma simd
+  for (int i=0; i < N; ++i)
+    sum[i] = f1[i] + f2[i];
+  verify (sum);
+  return 0;
+}
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
index 7e0fda5..fa9246c 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -16,7 +16,6 @@ 
 
 # Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
 
-
 load_lib g++-dg.exp
 
 if { ![check_effective_target_cilkplus] } {
@@ -24,6 +23,13 @@  if { ![check_effective_target_cilkplus] } {
 }
 
 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
+
+dg-init
 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" " "
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/cilk-plus/for2.C b/gcc/testsuite/g++.dg/cilk-plus/for2.C
new file mode 100644
index 0000000..d30e057
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/for2.C
@@ -0,0 +1,26 @@ 
+/* { 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 tt=5; tt < 10; ++tt) /* { dg-error "storage class is not allowed" } */
+    a[tt] = b[tt];
+
+#pragma simd
+  for (extern int var=0; var < 1000; ++var) /* { dg-error "storage class is not allowed" } */
+    a[var] = var;
+
+#pragma simd
+  for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "storage class is not allowed" } */
+    b[regj] = a[regj] * 2;
+
+#pragma simd
+  for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable cannot be volatile" } */
+    a[vj] = b[vj];
+}
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
index 710218e..e9d0428 100644
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -49,6 +49,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
index 2533feb..4eb43d6 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
@@ -24,6 +24,13 @@  if { ![check_effective_target_cilkplus] } {
 }
 
 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" " "
+# Run the C-only tests.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.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" " "
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];
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/for2.c b/gcc/testsuite/gcc.dg/cilk-plus/for2.c
new file mode 100644
index 0000000..dc0a41e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/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/gcc.dg/cilk-plus/jump.c b/gcc/testsuite/gcc.dg/cilk-plus/jump.c
new file mode 100644
index 0000000..9ec3293
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/jump.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int *a, *b, c;
+
+void foo()
+{
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+      a[i] = b[i];
+      if (c == 5)
+	return;	 /* { dg-error "invalid branch to.from a Cilk" } */
+    }
+}
+
+void bar()
+{
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+    lab:
+      a[i] = b[i];
+    }
+  if (c == 6)
+    goto lab; /* { dg-error "invalid entry to Cilk Plus" } */
+}
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 69e4006..ab914ef 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2212,6 +2212,10 @@  dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_string (buffer, "#pragma omp simd");
       goto dump_omp_loop;
 
+    case CILK_SIMD:
+      pp_string (buffer, "#pragma simd");
+      goto dump_omp_loop;
+
     dump_omp_loop:
       dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags);
 
diff --git a/gcc/tree.def b/gcc/tree.def
index f825aad..552c704 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1034,6 +1034,10 @@  DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
    Operands like for OMP_FOR.  */
 DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
 
+/* Cilk Plus - #pragma simd [clause1 ... clauseN]
+   Operands like for OMP_FOR.  */
+DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6)
+
 /* OpenMP - #pragma omp sections [clause1 ... clauseN]
    Operand 0: OMP_SECTIONS_BODY: Sections body.
    Operand 1: OMP_SECTIONS_CLAUSES: List of clauses.  */
diff --git a/gcc/tree.h b/gcc/tree.h
index eb017e5..624a3e7 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1795,12 +1795,13 @@  extern void protected_set_expr_location (tree, location_t);
 #define OMP_TASKREG_BODY(NODE)    TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 0)
 #define OMP_TASKREG_CLAUSES(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 1)
 
-#define OMP_FOR_BODY(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 0)
-#define OMP_FOR_CLAUSES(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 1)
-#define OMP_FOR_INIT(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 2)
-#define OMP_FOR_COND(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 3)
-#define OMP_FOR_INCR(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 4)
-#define OMP_FOR_PRE_BODY(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 5)
+#define OMP_LOOP_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_FOR, CILK_SIMD)
+#define OMP_FOR_BODY(NODE)	   TREE_OPERAND (OMP_LOOP_CHECK (NODE), 0)
+#define OMP_FOR_CLAUSES(NODE)	   TREE_OPERAND (OMP_LOOP_CHECK (NODE), 1)
+#define OMP_FOR_INIT(NODE)	   TREE_OPERAND (OMP_LOOP_CHECK (NODE), 2)
+#define OMP_FOR_COND(NODE)	   TREE_OPERAND (OMP_LOOP_CHECK (NODE), 3)
+#define OMP_FOR_INCR(NODE)	   TREE_OPERAND (OMP_LOOP_CHECK (NODE), 4)
+#define OMP_FOR_PRE_BODY(NODE)	   TREE_OPERAND (OMP_LOOP_CHECK (NODE), 5)
 
 #define OMP_SECTIONS_BODY(NODE)    TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
 #define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)