diff mbox

_Cilk_spawn and _Cilk_sync for C++

Message ID BF230D13CA30DD48930C31D4099330003A4AD259@FMSMSX101.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Nov. 27, 2013, 11:01 p.m. UTC
Sorry, my patch missed one change. Here is the fixed one.

Thanks,

Balaji V. Iyer.

> -----Original Message-----
> From: Iyer, Balaji V
> Sent: Wednesday, November 27, 2013 6:00 PM
> To: 'Jason Merrill'; gcc-patches@gcc.gnu.org
> Cc: Jeff Law
> Subject: RE: _Cilk_spawn and _Cilk_sync for C++
> 
> 
> 
> > -----Original Message-----
> > From: Jason Merrill [mailto:jason@redhat.com]
> > Sent: Wednesday, November 27, 2013 1:57 PM
> > To: Iyer, Balaji V; gcc-patches@gcc.gnu.org
> > Cc: Jeff Law
> > Subject: Re: _Cilk_spawn and _Cilk_sync for C++
> >
> > On 11/27/2013 01:25 PM, Iyer, Balaji V wrote:
> > >> I think a better approach would be to add a cp_build_cilk_spawn
> > >> that uses stabilize_call to pre-evaluate the arguments of the call.
> > >
> > > I really can't pre-evaluate the calls before I move into the nested
> > > function
> > because all those parts must be in the nested function.
> >
> > OK, then use stabilize_expr to pre-evaluate just the function, to get
> > the effect of your earlier cilk_create_lambda_fn_tmp_var without the
> > undesirable lifetime effects.
> >
> > > Adding another hook seem to be straightforward for me.
> >
> > It's straightforward but undesirable; we want to minimize the number
> > of hooks, and this one is unnecessary.
> >
> 
> Well, if I use copy_tree_body_r for C and C++, in lambda functions, it asserts
> in varasm.c. The main reason I see that, the copy_tree_body_r walks into the
> closure and then maps the variables from the lambda function from the
> spawner to the helper function.
> 
> I moved some functions around and then added a function pointer to  a
> function. Thus, I am able to eliminate the addition to the langhooks and now
> it passes all the tests on x86_64.
> 
> So, is this OK for trunk?
> 
> Here are the ChangeLog entries:
> gcc/c-family/ChangeLog
> 2013-11-27  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * cilk.c (cilk_outline): Replaced a call to copy_tree_body_r with the
>         function pointer passed in.  Made this function non-static.
>         * c-common.h (cilk_outline): New prototype.
>         (c_cilk_install_body_with_frame_cleanup): Added a new parameter.
> 
> gcc/ChangeLog
> 2013-11-27  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * langhooks.h
>         (lang_hooks_for_cilkplus::install_body_with_frame_cleanup): Added
> new
>         parameter.
> 
> gcc/cp/ChangeLog
> 2013-11-27  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * cp-tree.h (cilk_valid_spawn): New prototype.
>         (gimplify_cilk_spawn): Likewise.
>         (cp_cilk_install_body_wframe_cleanup): Likewise.
>         (cilk_create_lambda_fn_tmp_var): Likewise.
>         (create_try_catch_expr): Likewise.
>         * decl.c (finish_function): Insert Cilk function-calls when a
>         _Cilk_spawn is used in a function.
>         * parser.c (cp_parser_postfix_expression): Added RID_CILK_SPAWN and
>         RID_CILK_SYNC cases.
>         * cp-cilkplus.c (set_cilk_except_flag): New function.
>         (set_cilk_except_data): Likewise.
>         (cp_cilk_install_body_wframe_cleanup): Likewise.
>         (is_lambda_function): Likewise.
>         (cp_cilk_copy_tree_body_r): Likewise.
>         * except.c (create_try_catch_expr): Likewise.
>         * parser.h (IN_CILK_SPAWN): New #define.
>         * cp-objcp-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN):
> Likewise.
>         * cp-objcp-common.h
> (LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY):
>         Likewise.
>         (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise.
>         (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
>         * pt.c (tsubst_expr): Added CILK_SPAWN_STMT and CILK_SYNC_STMT
> cases.
>         * semantics.c (potential_constant_expression_1): Likewise.
>         * typeck.c (cp_build_compound_expr): Reject a spawned function in a
>         compound expression.
>         (check_return_expr): Reject a spawned function in a return expression.
> 
> gcc/testsuite/ChangeLog
> 2013-11-27  Balaji V. Iyer  <balaji.v.iyer@intel.com>
> 
>         * g++.dg/cilk-plus/CK/catch_exc.cc: New test case.
>         * g++.dg/cilk-plus/CK/const_spawn.cc: Likewise.
>         * g++.dg/cilk-plus/CK/fib-opr-overload.cc: Likewise.
>         * g++.dg/cilk-plus/CK/fib-tplt.cc: Likewise.
>         * g++.dg/cilk-plus/CK/lambda_spawns.cc: Likewise.
>         * g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc: Likewise.
>         * g++.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords
>         test stored in c-c++-common.  Also, added the Cilk runtime's library
>         to the ld_library_path.
> 
> Thanks,
> 
> Balaji V. Iyer.
> 
> 
> > Jason
diff mbox

Patch

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 664e928..a3365a6 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1379,7 +1379,7 @@  extern vec <tree, va_gc> *fix_sec_implicit_args
 extern tree insert_cilk_frame (tree);
 extern void cilk_init_builtins (void);
 extern int gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *);
-extern void c_cilk_install_body_w_frame_cleanup (tree, tree);
+extern void c_cilk_install_body_w_frame_cleanup (tree, tree, void *);
 extern bool cilk_detect_spawn_and_unwrap (tree *);
 extern bool cilk_set_spawn_marker (location_t, tree);
 extern tree build_cilk_sync (void);
@@ -1387,5 +1387,6 @@  extern tree build_cilk_spawn (location_t, tree);
 extern tree make_cilk_frame (tree);
 extern tree create_cilk_function_exit (tree, bool, bool);
 extern tree cilk_install_body_pedigree_operations (tree);
-
+extern void cilk_outline (tree, tree *, struct wrapper_data *,
+			  tree (*) (tree *, int *, void *));
 #endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
index c85b5f2..e62cbe1 100644
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -477,8 +477,9 @@  wrapper_local_cb (const void *k_v, void **vp, void *data)
 
 /* Alter a tree STMT from OUTER_FN to form the body of INNER_FN.  */
 
-static void
-cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
+void
+cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd,
+	      tree (*copy_body_func) (tree *, int *, void *))
 {
   const tree outer_fn = wd->context;	      
   const bool nested = (wd->type == CILK_BLOCK_FOR);
@@ -513,7 +514,14 @@  cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
   pointer_map_traverse (wd->decl_map, nested ? for_local_cb : wrapper_local_cb,
 			&id);
 
-  walk_tree (stmt_p, copy_tree_body_r, &id, NULL);
+  /* When you are walking through all the trees and copying them, there is no
+     reason to copy the lambda function body that is spawned in C++.
+     For everything else (_Cilk_for body for C/C++), just do the normal copying,
+     i.e. call copy_tree_body_r.  */
+  if (wd->type == CILK_BLOCK_FOR)
+    walk_tree (stmt_p, copy_tree_body_r, (void *) &id, NULL);
+  else
+    walk_tree (stmt_p, copy_body_func, (void *) &id, NULL);
 
   /* See if this function can throw or calls something that should
      not be spawned.  The exception part is only necessary if
@@ -554,10 +562,9 @@  create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
   for (p = wd->parms; p; p = TREE_CHAIN (p))
     DECL_CONTEXT (p) = fndecl;
 
-  cilk_outline (fndecl, &stmt, wd);
-  stmt = fold_build_cleanup_point_expr (void_type_node, stmt);
   gcc_assert (!DECL_SAVED_TREE (fndecl));
-  lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt);
+  lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt, 
+						       (void *) wd);
   gcc_assert (DECL_SAVED_TREE (fndecl));
 
   pop_cfun_to (outer);
@@ -879,7 +886,7 @@  cilk_install_body_pedigree_operations (tree frame_ptr)
    spawn-helper and BODY is the newly created body for FNDECL.  */
 
 void
-c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body)
+c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body, void *wd)
 {
   tree list = alloc_stmt_list ();
   tree frame = make_cilk_frame (fndecl);
@@ -894,6 +901,10 @@  c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body)
   
   tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, frame_ptr); 
   append_to_statement_list (detach_expr, &body_list);
+ 
+  cilk_outline (fndecl, &body, (struct wrapper_data *) wd, copy_tree_body_r);
+  body = fold_build_cleanup_point_expr (void_type_node, body);
+
   append_to_statement_list (body, &body_list);
   append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
 				       	body_list, dtor), &list);
diff --git a/gcc/cp/cp-cilk.c b/gcc/cp/cp-cilk.c
new file mode 100755
index 0000000..57e8ad5
--- /dev/null
+++ b/gcc/cp/cp-cilk.c
@@ -0,0 +1,28 @@ 
+/* Functions to handle Cilk keywords support in C++.
+   Copyright (C) 2011-2013  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+   Intel Corporation.
+
+   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 "tree-iterator.h"
+#include "cilk.h"
+
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
index 5c1090a..ae2d0f2 100644
--- a/gcc/cp/cp-cilkplus.c
+++ b/gcc/cp/cp-cilkplus.c
@@ -25,7 +25,10 @@ 
 #include "coretypes.h"
 #include "cp-tree.h"
 #include "diagnostic-core.h"
-
+#include "tree-iterator.h"
+#include "tree-inline.h"  /* for copy_tree_body_r.  */
+#include "ggc.h"
+#include "cilk.h"
 
 /* Callback for cp_walk_tree to validate the body of a pragma simd loop
    or _cilk_for loop.
@@ -75,3 +78,108 @@  cpp_validate_cilk_plus_loop (tree body)
 		(void *) &valid, NULL);
   return valid;
 }
+
+/* Sets the EXCEPTION bit (0x10) in the FRAME.flags field.  */
+
+static tree
+set_cilk_except_flag (tree frame)
+{
+  tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, 0);
+
+  flags = build2 (MODIFY_EXPR, void_type_node, flags,
+		  build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
+			  build_int_cst (TREE_TYPE (flags),
+					 CILK_FRAME_EXCEPTING)));
+  return flags;
+}
+
+/* Sets the frame.EXCEPT_DATA field to the head of the exception pointer.  */
+
+static tree
+set_cilk_except_data (tree frame)
+{
+  tree except_data = cilk_dot (frame, CILK_TI_FRAME_EXCEPTION, 0);
+  tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
+  tree ret_expr;
+  uresume_fn  = build_call_expr (uresume_fn, 1,
+				 build_int_cst (integer_type_node, 0));
+  ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn);
+  return ret_expr;
+}
+
+/* Returns true if the FUNCTION_DECL in call_exp, A CALL_EXPR tree is a
+   lambda function.  */
+
+static bool
+is_lambda_fn_p (tree call_exp)
+{
+  tree call_fn = CALL_EXPR_FN (call_exp);
+  if (TREE_CODE (call_fn) == ADDR_EXPR)
+    call_fn = TREE_OPERAND (call_fn, 0);
+  if (call_fn && LAMBDA_FUNCTION_P (call_fn))
+    return true;
+  return false;
+}
+
+/* Helper function for walk_tree.  This function will call copy_tree_body_r
+   for all the sub_trees except the first parameter of a lambda function.  */
+
+static tree
+cp_cilk_copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
+{
+  if (TREE_CODE (*tp) == CALL_EXPR)
+    {
+      int nargs = call_expr_nargs (*tp);
+      int start = 0;
+      if (cxx_dialect >= cxx0x && is_lambda_fn_p (*tp))
+	start = 1;
+      for (int ii = start; ii < nargs; ii++)
+	walk_tree (&CALL_EXPR_ARG ((*tp), ii), copy_tree_body_r, data, NULL);
+      /* No need to visit *TP's subtrees since we have done the necessary
+	 ones above.  */
+      *walk_subtrees = 0;
+    }
+  else
+    walk_tree (tp, copy_tree_body_r, data, NULL);
+  return NULL_TREE;
+}
+
+/* Installs BODY into function FNDECL with appropriate exception handling
+   code.  WD holds information of wrapper function used to pass into the
+   outlining function, cilk_outline.  */
+
+void
+cp_cilk_install_body_wframe_cleanup (tree fndecl, tree orig_body, void *wd)
+{
+  tree frame = make_cilk_frame (fndecl);
+  tree dtor = create_cilk_function_exit (frame, false, false);
+  add_local_decl (cfun, frame);
+
+  cfun->language = ggc_alloc_cleared_language_function ();
+  
+  location_t loc = EXPR_LOCATION (orig_body);
+  tree list = alloc_stmt_list ();
+  DECL_SAVED_TREE (fndecl) = list;
+  tree fptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), frame);
+  tree body = cilk_install_body_pedigree_operations (fptr);
+  gcc_assert (TREE_CODE (body) == STATEMENT_LIST);
+  tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, fptr);
+  append_to_statement_list (detach_expr, &body);
+
+  cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd, 
+		cp_cilk_copy_tree_body_r);
+  orig_body = fold_build_cleanup_point_expr (void_type_node, orig_body);
+  append_to_statement_list (orig_body, &body);
+  if (flag_exceptions)
+    {
+      tree except_flag = set_cilk_except_flag (frame);
+      tree except_data = set_cilk_except_data (frame);
+      tree catch_list = alloc_stmt_list ();
+      append_to_statement_list (except_flag, &catch_list);
+      append_to_statement_list (except_data, &catch_list);
+      body = create_try_catch_expr (body, catch_list);
+    }
+  append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor),
+			    &list);
+}
+
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index ee22423..77a66c3 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -154,4 +154,14 @@  extern void cp_common_init_ts (void);
 #undef LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS
 #define LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS cp_protect_cleanup_actions
 
+#undef  LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN
+#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn
+
+#undef  LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP
+#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP  \
+    cilk_detect_spawn_and_unwrap
+
+#undef  LANG_HOOKS_CILKPLUS_FRAME_CLEANUP
+#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP cp_cilk_install_body_wframe_cleanup
+
 #endif /* GCC_CP_OBJCP_COMMON */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1fc4b59..109110b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5356,6 +5356,7 @@  extern tree begin_eh_spec_block			(void);
 extern void finish_eh_spec_block		(tree, tree);
 extern tree build_eh_type_type			(tree);
 extern tree cp_protect_cleanup_actions		(void);
+extern tree create_try_catch_expr               (tree, tree);
 
 /* in expr.c */
 extern tree cplus_expand_constant		(tree);
@@ -6180,11 +6181,17 @@  extern void vtv_build_vtable_verify_fndecl      (void);
 
 /* In cp-cilkplus.c.  */
 extern bool cpp_validate_cilk_plus_loop		(tree);
+extern void cp_cilk_install_body_wframe_cleanup (tree, tree, void *);
 
 /* 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,
 						 tree);
+/* In c-family/cilk.c */
+extern bool cilk_valid_spawn                    (tree);
+extern int gimplify_cilk_spawn                  (tree *, gimple_seq *,
+						 gimple_seq *);
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9508131..5e3c301 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -59,6 +59,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "splay-tree.h"
 #include "plugin.h"
 #include "cgraph.h"
+#include "cilk.h"
 
 /* Possible cases of bad specifiers type used by bad_specifiers. */
 enum bad_spec_place {
@@ -13883,6 +13884,9 @@  finish_function (int flags)
   /* If we're saving up tree structure, tie off the function now.  */
   DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
 
+  if (fn_contains_cilk_spawn_p (cfun) && !processing_template_decl)
+    cfun->cilk_frame_decl = insert_cilk_frame (fndecl);
+
   finish_fname_decls ();
 
   /* If this function can't throw any exceptions, remember that.  */
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index d7d009b..8ecac62 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -1342,4 +1342,22 @@  build_noexcept_spec (tree expr, int complain)
     }
 }
 
+/* Returns a TRY_CATCH_EXPR that will put TRY_LIST and CATCH_LIST in the
+   TRY and CATCH locations.  CATCH_LIST must be a STATEMENT_LIST */
+
+tree
+create_try_catch_expr (tree try_expr, tree catch_list)
+{
+  location_t loc = EXPR_LOCATION (try_expr);
+  gcc_assert (TREE_CODE (catch_list) == STATEMENT_LIST);
+  append_to_statement_list (do_begin_catch (), &catch_list);
+  append_to_statement_list (build_throw (NULL_TREE), &catch_list);
+  tree catch_tf_expr = build_stmt (loc, TRY_FINALLY_EXPR, catch_list, 
+				   do_end_catch (NULL_TREE));
+  catch_list = build2 (CATCH_EXPR, void_type_node, NULL_TREE,
+		       catch_tf_expr);
+  tree try_catch_expr = build_stmt (loc, TRY_CATCH_EXPR, try_expr, catch_list);
+  return try_catch_expr;
+}
+
 #include "gt-cp-except.h"
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d7092cc..2069e4c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5627,6 +5627,7 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
   cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
   bool is_member_access = false;
+  int saved_in_statement = -1;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -5771,6 +5772,70 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
       }
       break;
 
+    case RID_CILK_SPAWN:
+      {
+	cp_lexer_consume_token (parser->lexer);
+	token = cp_lexer_peek_token (parser->lexer);
+	if (token->type == CPP_SEMICOLON)
+	  {
+	    error_at (token->location, "%<_Cilk_spawn%> must be followed by an "
+		      "expression");
+	    postfix_expression = error_mark_node;
+	    break;
+	  }
+	else if (!current_function_decl)
+	  {
+	    error_at (token->location, "%<_Cilk_spawn%> may only be used "
+		      "inside a function");
+	    postfix_expression = error_mark_node;
+	    break;
+	  }
+	else
+	  {
+	    /* Break or continue statements within this primary expression
+	       is not allowed.  */
+	    saved_in_statement = parser->in_statement;
+	    parser->in_statement = IN_CILK_SPAWN;
+	  }
+	/* We set this here so that finish_call_expr can set lambda to a var.
+	   if it is not done so.  */
+	cfun->calls_cilk_spawn = 1;
+	postfix_expression = cp_parser_postfix_expression (parser, false, false,
+							   false, false, &idk);
+	if (saved_in_statement & IN_CILK_SPAWN)
+	  {
+	    error_at (token->location, "consecutive %<_Cilk_spawn%> keywords "
+		      "are not permitted");
+	    postfix_expression = error_mark_node;
+	    cfun->calls_cilk_spawn = 0; 
+	  }
+	else
+	  {
+	    postfix_expression = build_cilk_spawn (token->location, 
+						   postfix_expression);
+	    if (postfix_expression != error_mark_node) 
+	      SET_EXPR_LOCATION (postfix_expression, input_location);
+	    parser->in_statement = parser->in_statement & ~IN_CILK_SPAWN;
+	  }
+	break;
+      }
+      
+    case RID_CILK_SYNC:
+      if (flag_enable_cilkplus)
+	{ 
+	  tree sync_expr = build_cilk_sync ();
+	  SET_EXPR_LOCATION (sync_expr, 
+			     cp_lexer_peek_token (parser->lexer)->location);
+	  finish_expr_stmt (sync_expr);
+	}
+      else
+	error_at (input_location, "_Cilk_sync cannot be used without enabling "
+		  "Cilk Plus");
+      cp_lexer_consume_token (parser->lexer);
+      if (parser->in_statement & IN_CILK_SPAWN)
+	parser->in_statement = parser->in_statement & ~IN_CILK_SPAWN;
+      break;
+
     case RID_BUILTIN_SHUFFLE:
       {
 	vec<tree, va_gc> *vec;
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index edd4e6e..e26e350 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -301,6 +301,7 @@  typedef struct GTY(()) cp_parser {
 #define IN_OMP_FOR		8
 #define IN_IF_STMT             16
 #define IN_CILK_SIMD_FOR       32
+#define IN_CILK_SPAWN          64
   unsigned char in_statement;
 
   /* TRUE if we are presently parsing the body of a switch statement.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b58c755..8672129 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13762,6 +13762,13 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       error ("use %<...%> to expand argument pack");
       RETURN (error_mark_node);
 
+    case CILK_SPAWN_STMT:
+      cfun->calls_cilk_spawn = 1;
+      RETURN (build_cilk_spawn (EXPR_LOCATION (t), RECUR (CILK_SPAWN_FN (t))));
+
+    case CILK_SYNC_STMT:
+      RETURN (build_cilk_sync ());
+
     case COMPOUND_EXPR:
       tmp = RECUR (TREE_OPERAND (t, 0));
       if (tmp == NULL_TREE)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d871c4d..4f637fb 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -10417,6 +10417,8 @@  potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
       return true;
 
+    case CILK_SYNC_STMT:
+    case CILK_SPAWN_STMT:
     case ARRAY_NOTATION_REF:
       return false;
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a4da037..fd8eac1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6164,6 +6164,17 @@  cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
   if (lhs == error_mark_node || rhs == error_mark_node)
     return error_mark_node;
 
+  if (flag_enable_cilkplus
+      && (TREE_CODE (lhs) == CILK_SPAWN_STMT
+	  || TREE_CODE (rhs) == CILK_SPAWN_STMT))
+    {
+      location_t loc = (EXPR_HAS_LOCATION (lhs) ? EXPR_LOCATION (lhs)
+			: EXPR_LOCATION (rhs));
+      error_at (loc,
+		"spawned function call cannot be part of a comma expression");
+      return error_mark_node;
+    }
+
   if (TREE_CODE (rhs) == TARGET_EXPR)
     {
       /* If the rhs is a TARGET_EXPR, then build the compound
@@ -8288,6 +8299,13 @@  check_return_expr (tree retval, bool *no_warning)
 
   *no_warning = false;
 
+  if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT)
+    {
+      error_at (EXPR_LOCATION (retval), "use of %<_Cilk_spawn%> in a return "
+		"statement is not allowed");
+      return NULL_TREE;
+    }
+
   /* A `volatile' function is one that isn't supposed to return, ever.
      (This is a G++ extension, used to get better code for functions
      that call the `volatile' function.)  */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 411cf74..e3c34d9 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -214,7 +214,7 @@  extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
 #define LANG_HOOKS_OMP_FINISH_CLAUSE hook_void_tree
 
-extern void lhd_install_body_with_frame_cleanup (tree, tree);
+extern void lhd_install_body_with_frame_cleanup (tree, tree, void *);
 extern bool lhd_cilk_detect_spawn (tree *);
 #define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP lhd_cilk_detect_spawn
 #define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 7fe349d..ef6d82d 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -681,7 +681,7 @@  lhd_end_section (void)
    frame cleanup function for _Cilk_spawn.  */
 
 void
-lhd_install_body_with_frame_cleanup (tree, tree)
+lhd_install_body_with_frame_cleanup (tree, tree, void *)
 {
 }
 
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 9539e7d..80bfa66 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -148,7 +148,7 @@  struct lang_hooks_for_cilkplus
 
   /* Function to add the clean up functions after spawn.  The reason why it is
      language dependent is because in C++, it must handle exceptions.  */
-  void (*install_body_with_frame_cleanup) (tree, tree);
+  void (*install_body_with_frame_cleanup) (tree, tree, void *);
 
   /* Function to gimplify a spawned function call.  Returns enum gimplify
      status, but as mentioned in a previous comment, we can't see that type 
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/catch_exc.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/catch_exc.cc
new file mode 100644
index 0000000..0633d19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/catch_exc.cc
@@ -0,0 +1,67 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */
+
+#include <assert.h>
+#include <unistd.h>
+#if HAVE_IO
+#include <cstdio>
+#include <cilk/cilk_api.h>
+#endif
+#include <cstdlib>
+
+
+void func(int volatile* steal_me) 
+{
+  while (! (*steal_me)) 
+    {
+      usleep(2000);
+    }
+#if HAVE_IO
+  printf("Foo executing on %d\n", __cilkrts_get_worker_number());
+#endif
+  throw 5;
+}
+
+void my_test() 
+{
+  volatile int steal_me = 0;
+
+  try 
+    {
+      _Cilk_spawn func(&steal_me);
+#if HAVE_IO
+      printf("Continuation executing on %d\n",
+	     __cilkrts_get_worker_number());
+#endif
+      steal_me = 1;
+      _Cilk_sync;
+      goto bad;
+    }
+
+  catch (int x) 
+    {
+#if HAVE_IO
+      printf("We caught x = %d\n", x);
+#endif
+      assert(x == 5);
+    }
+  if (0) 
+    {
+    bad:
+#if HAVE_IO
+      printf("We should not be here!\n");
+#endif
+      __builtin_abort ();
+    }
+}
+
+
+int main() 
+{
+  my_test();
+#if HAVE_IO
+  printf("PASSED\n");
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/const_spawn.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/const_spawn.cc
new file mode 100644
index 0000000..1ea473f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/const_spawn.cc
@@ -0,0 +1,78 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */
+
+class Rectangle
+{
+  int area_val, h, w;
+  public:
+    Rectangle (int, int);
+    Rectangle (int, int, int);
+    ~Rectangle ();
+    int area ();
+};
+Rectangle::~Rectangle ()
+{
+  h = 0;
+  w = 0;
+  area_val = 0;
+}
+Rectangle::Rectangle (int height, int width)
+{
+  h = height;
+  w = width;
+  area_val = 0;
+}
+
+Rectangle::Rectangle (int height, int width, int area_orig)
+{
+  h = height;
+  w = width;
+  area_val = area_orig;
+}
+
+int Rectangle::area()
+{
+  return (area_val += (h*w));
+}
+
+/* Spawning constructor.  */
+int main1 (void)
+{
+  Rectangle r = _Cilk_spawn Rectangle (4, 3);
+  return r.area();
+}
+ 
+/* Spawning constructor 2.  */
+int main2 (void)
+{
+  Rectangle r (_Cilk_spawn Rectangle (4, 3));
+  return r.area();
+}
+
+/* Spawning copy constructor.  */
+int main3 (void)
+{
+  Rectangle r = _Cilk_spawn Rectangle (4, 3, 2);
+  return r.area ();
+}
+
+/* Spawning copy constructor 2.  */
+int main4 (void)
+{
+  Rectangle r ( _Cilk_spawn Rectangle (4, 3, 2));
+  return r.area();
+}
+
+int main (void)
+{
+  if (main1 () != 12)
+    __builtin_abort ();
+  if (main2 () != 12)
+    __builtin_abort ();
+  if (main3 () != 14)
+    __builtin_abort ();
+  if (main4() != 14)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/fib-opr-overload.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-opr-overload.cc
new file mode 100644
index 0000000..6af4a36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-opr-overload.cc
@@ -0,0 +1,94 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */
+
+#if HAVE_IO
+#include <iostream>
+#endif
+
+class Some_Struct
+{
+  int calculated_value;
+  short some_unused_value;
+public:
+  Some_Struct () {
+      this->calculated_value = 0;
+  }
+  Some_Struct (int value) {
+      this->calculated_value = value;
+  }
+  Some_Struct operator=(Some_Struct f) {
+      this->calculated_value = f.calculated_value;
+      return *this;
+  }
+  bool operator!=(Some_Struct f) {
+      return (this->calculated_value != f.calculated_value);
+  }
+  Some_Struct operator+(Some_Struct &f) {
+    Some_Struct z;
+    z.calculated_value = this->calculated_value + f.calculated_value;
+      return z;
+  }
+  Some_Struct operator-(int x) {
+    Some_Struct z;
+    z.calculated_value = this->calculated_value - x;
+    return z;
+  }
+  bool operator<(int x) {
+      return (this->calculated_value < x);
+  }
+  int get_calculated_value () {
+      return this->calculated_value;
+  }
+};
+
+
+template <class T>
+T fibonacci_serial (T f)
+{
+  if (f < 2)
+    return f;
+  T a = fibonacci_serial (f-1);
+  T b = fibonacci_serial (f-2);
+  return (a+b);
+}
+
+template <class T>
+T fibonacci (T f)
+{
+  if (f < 2)
+    return f;
+  T a = _Cilk_spawn fibonacci (f-1);
+  T b = fibonacci (f-2);
+  _Cilk_sync; 
+  return (a+b);
+}
+
+int main (void)
+{
+  Some_Struct f (40), f_serial(40);
+  f = fibonacci (f);
+  f_serial = fibonacci_serial (f_serial);
+  
+  if (f != f_serial)
+    __builtin_abort ();
+  
+  int t = 40, t_serial = 40;
+  t = fibonacci (t);
+  t_serial = fibonacci_serial (t_serial);
+  if (t != t_serial)
+    __builtin_abort ();
+
+  short s = 20, s_serial = 20;
+  s = fibonacci (s);
+  s_serial = fibonacci_serial (s_serial);
+  if (s != s_serial)
+    __builtin_abort ();
+
+#if HAVE_IO
+  std::cout << "Fib_Parallel (40) = " << f.get_calculated_value() << std::endl;
+  std::cout << "Fib_Serial   (40) = " << f_serial.get_calculated_value() 
+    << std::endl;
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/fib-tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-tplt.cc
new file mode 100644
index 0000000..dbc2da8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-tplt.cc
@@ -0,0 +1,53 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-*-* } } } */
+
+struct fib_struct
+{
+  int x;
+  int *y;
+  int z[3];
+  struct fib_struct *ptr_next;
+  struct fib_struct operator+(struct fib_struct &other) {
+    struct fib_struct z ;
+     z.x = (*this).x + (other.x);
+    return z; 
+  }
+  struct fib_struct operator-(int other) {
+    struct fib_struct z ;
+    z.x = this->x - other;
+    return z;
+  }
+  bool operator<(int number) {
+   return (this->x < number);
+  }
+    
+};
+
+template <typename T>
+T fib (T z) {
+    if (z < 2) return z;
+    T a = _Cilk_spawn fib<T>(z - 1);
+    T b = fib<T>(z - 2);
+    T c = a + b;
+    return (a+b);
+}
+
+
+int sfib(int x)
+{
+  if (x < 2) return x;
+  int a = sfib(x-1);
+  int b = sfib(x-2);
+  return (a+b);
+}
+
+int main () {
+     int z = 30;
+     int parallel_fib = fib<int>(z);
+     int serial_fib = sfib(z);
+    if (serial_fib != parallel_fib) 
+      __builtin_abort ();
+    
+    return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns.cc
new file mode 100644
index 0000000..7448d1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns.cc
@@ -0,0 +1,236 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */
+/* { dg-options "-std=c++11 -fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */
+#define FIRST_NUMBER 5
+#define SECOND_NUMBER 3
+#define HAVE_IO 0
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+
+int global_var;
+
+void foo1(int *array, int size)
+{
+#if HAVE_IO
+  for (int ii = 0; ii < size; ii++) 
+    printf("%2d\t", array[ii]);
+  printf("\n");
+  fflush (stdout);
+#else
+  if (size != 2)
+    __builtin_abort ();
+  if (array[0] != FIRST_NUMBER)
+    __builtin_abort ();
+  if (array[1] != SECOND_NUMBER)
+    __builtin_abort ();
+#endif
+  global_var++;
+}
+void foo1_c(const int *array, int size)
+{
+#if HAVE_IO
+  for (int ii = 0; ii < size; ii++) 
+    printf("%2d\t", array[ii]);
+  printf("\n");
+  fflush (stdout);
+#else
+  if (size != 2)
+    __builtin_abort ();
+  if (array[0] != FIRST_NUMBER)
+    __builtin_abort ();
+  if (array[1] != SECOND_NUMBER)
+    __builtin_abort ();
+#endif
+  global_var++;
+}
+
+
+int main2 (int argc) {
+  int A[2] = {FIRST_NUMBER, SECOND_NUMBER};
+  int B[2] = {FIRST_NUMBER, SECOND_NUMBER};
+  int main_size = argc+1; /* We know argc is 1, and so 1+1 = 2.  */
+  int q = 0;
+
+  global_var = 0;
+  auto func0 = [=](){ foo1_c(A, 2); };
+  _Cilk_spawn func0();
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func1 = [=](int *Aa){ foo1(Aa, 2); };
+  _Cilk_spawn func1 (A);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func2 = [=](int *Aa, int size){ foo1(Aa, size); };
+  _Cilk_spawn func2 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func3 = [=](int *Aa, int size){ int new_size = (size % 2 + 2); 
+				       foo1(Aa, size); };
+  _Cilk_spawn func3 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func4 = [](int *Aa){ foo1(Aa, 2); };
+  _Cilk_spawn func4 (A);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func5 = [](int *Aa, int size){ foo1(Aa, size); };
+  _Cilk_spawn func5 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func6 = [&](int *Aa){ foo1(Aa, 2); };
+  _Cilk_spawn func6 (A);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func7 = [&](int *Aa, int size){ foo1(Aa, size); };
+  _Cilk_spawn func7 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func8 = [&](){ foo1(A, 2); };
+  _Cilk_spawn func8 ();
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  /* We ignore the first param here and pass in A from the outer fn.  */
+  auto func9 = [&](int *Aa, int size){ foo1(A, size); };
+  _Cilk_spawn func9 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func10 = [=](){ foo1_c(A, main_size); };
+  _Cilk_spawn func10 ();
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  auto func11 = [&](){ foo1(A, main_size); };
+  _Cilk_spawn func11 ();
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  /* We ignore the first & second param here and pass in A from the 
+     outer fn.  */
+  auto func12 = [&](int *Aa, int size){ foo1(A, main_size); };
+  _Cilk_spawn func12 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [&](int *Aa){ foo1(Aa, 2); }(A);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [&](int *Aa, int size){ foo1(Aa, size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [=](int *Aa){ foo1(Aa, 2); }(A);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [=](int *Aa, int size){ foo1(Aa, size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  /* We ignore the first param here.  */
+  _Cilk_spawn [=](int *Aa, int size){ foo1_c(A, size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  /* We ignore the first and second param here.  */
+  _Cilk_spawn [=](int *Aa, int size){ foo1_c(A, size); }(B, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [&](){ foo1(A, 2); }();
+  [&](){ foo1(A, 2); }();
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [=](){ foo1_c (A, main_size); }();
+  foo1 (A, 2);
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  global_var = 0;
+  _Cilk_spawn [&](){ foo1(A, main_size); }();
+  [&](){ foo1(A, 2); }();
+  _Cilk_sync;
+  if (global_var != 2)
+    return (++q);
+
+  return q;
+}
+
+int main (void)
+{
+  return main2 (1);
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc
new file mode 100644
index 0000000..2667f5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc
@@ -0,0 +1,173 @@ 
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */
+/* { dg-options "-std=c++11 -fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */
+
+#define FIRST_NUMBER 5
+#define SECOND_NUMBER 3
+#define HAVE_IO 0
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+
+template <class T>
+void foo1(T *array, int size)
+{
+#if HAVE_IO
+  for (int ii = 0; ii < size; ii++) 
+    printf("%2d\t", (int)array[ii]);
+  printf("\n");
+  fflush (stdout);
+#else
+  if (size != 2)
+    __builtin_abort ();
+  if (array[0] != FIRST_NUMBER)
+    __builtin_abort ();
+  if (array[1] != SECOND_NUMBER)
+    __builtin_abort ();
+#endif
+}
+template <class T>
+void foo1_c(const T *array, int size)
+{
+#if HAVE_IO
+  for (int ii = 0; ii < size; ii++) 
+    printf("%2d\t", (int)array[ii]);
+  printf("\n");
+  fflush (stdout);
+#else
+  if (size != 2)
+    __builtin_abort ();
+  if (array[0] != FIRST_NUMBER)
+    __builtin_abort ();
+  if (array[1] != SECOND_NUMBER)
+    __builtin_abort ();
+#endif
+}
+template <class T>
+int main2 (int argc, char **argv) {
+  T A[2] = {FIRST_NUMBER, SECOND_NUMBER};
+  int main_size = argc+1; /* We know argc is 1, and so 1+1 = 2.  */
+  auto func0 = [=](){ foo1_c(A, 2); };
+  _Cilk_spawn func0();
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func1 = [=](T *Aa){ foo1(Aa, 2); };
+  _Cilk_spawn func1 (A);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func2 = [=](T *Aa, int size){ foo1(Aa, size); };
+  _Cilk_spawn func2 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func3 = [=](T *Aa, int size){ int new_size = (size % 2 + 2); 
+				       foo1(Aa, size); };
+  _Cilk_spawn func3 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func4 = [](T *Aa){ foo1(Aa, 2); };
+  _Cilk_spawn func4 (A);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func5 = [](T *Aa, int size){ foo1(Aa, size); };
+  _Cilk_spawn func5 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func6 = [&](T *Aa){ foo1(Aa, 2); };
+  _Cilk_spawn func6 (A);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func7 = [&](T *Aa, int size){ foo1(Aa, size); };
+  _Cilk_spawn func7 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func8 = [&](){ foo1(A, 2); };
+  _Cilk_spawn func8 ();
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  /* We ignore the first param here and pass in A from the outer fn.  */
+  auto func9 = [&](T *Aa, int size){ foo1(A, size); };
+  _Cilk_spawn func9 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func10 = [=](){ foo1_c(A, main_size); };
+  _Cilk_spawn func10 ();
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  auto func11 = [&](){ foo1(A, main_size); };
+  _Cilk_spawn func11 ();
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  /* We ignore the first & second param here and pass in A from the 
+     outer fn.  */
+  auto func12 = [&](T *Aa, int size){ foo1(A, main_size); };
+  _Cilk_spawn func12 (A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  _Cilk_spawn [&](T *Aa){ foo1(Aa, 2); }(A);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  _Cilk_spawn [&](T *Aa, int size){ foo1(Aa, size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  _Cilk_spawn [=](T *Aa){ foo1(Aa, 2); }(A);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  _Cilk_spawn [=](T *Aa, int size){ foo1(Aa, size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  /* We ignore the first param here.  */
+  _Cilk_spawn [=](T *Aa, int size){ foo1_c(A, size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  /* We ignore the first and second param here.  */
+  _Cilk_spawn [=](T *Aa, int size){ foo1_c(A, main_size); }(A, 2);
+  foo1 (A, 2);
+  _Cilk_sync;
+
+  _Cilk_spawn [&](){ foo1(A, 2); }();
+  [&](){ foo1(A, 2); }();
+  _Cilk_sync;
+
+  _Cilk_spawn [=](){ foo1_c(A, main_size); }();
+  foo1 (A, 2);
+  _Cilk_sync;
+	
+  _Cilk_spawn [&](){ foo1(A, main_size); }();
+  [&](){ foo1(A, 2); }();
+  _Cilk_sync;
+
+  return 0;
+}
+
+int main (void)
+{
+  int argc = 1;
+  char **argv = NULL;
+  int x = 1, y = 1, z = 1, q = 1, p = 1;
+  x = main2<char>(argc,argv);
+  y = main2<short>(argc,argv);
+  z = main2<int>(argc,argv);
+  p = main2<long>(argc,argv);
+  q = main2<long long>(argc,argv);
+  return (x+y+z+p+q);
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
index a66ec44..a4328d0 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -22,6 +22,14 @@  if { ![check_effective_target_cilkplus] } {
     return;
 }
 
+verbose "$tool $libdir" 1
+set library_var "[get_multilibs]"
+# Pointing the ld_library_path to the Cilk Runtime library binaries.
+set ld_library_path "$[get_multilibs]/libcilkrts/.libs"
+
+set ALWAYS_CFLAGS ""
+lappend ALWAYS_CFLAGS "-L${library_var}/libcilkrts/.libs"
+
 dg-init
 # Run the tests that are shared with C.
 g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] ""
@@ -62,4 +70,23 @@  dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " "
 dg-finish
 
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O2 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O3 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O2 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O3 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-finish
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O3 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-finish
 unset TEST_EXTRA_LIBS
diff --git a/gcc/varasm.c b/gcc/varasm.c
old mode 100644
new mode 100755
diff --git a/libcilkrts/Makefile.am b/libcilkrts/Makefile.am
index 56bc9eb..d252087 100644
--- a/libcilkrts/Makefile.am
+++ b/libcilkrts/Makefile.am
@@ -38,7 +38,7 @@  ACLOCAL_AMFLAGS = -I .. -I ../config
 
 # Compiler and linker flags.
 GENERAL_FLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/runtime -I$(top_srcdir)/runtime/config/$(config_dir) -DIN_CILK_RUNTIME=1
-GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for
+# GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for
 
 # Enable Intel Cilk Plus extension
 GENERAL_FLAGS += -fcilkplus
diff --git a/libcilkrts/Makefile.in b/libcilkrts/Makefile.in
index 5066bef..94902e1 100644
--- a/libcilkrts/Makefile.in
+++ b/libcilkrts/Makefile.in
@@ -342,12 +342,12 @@  AUTOMAKE_OPTIONS = foreign
 ACLOCAL_AMFLAGS = -I .. -I ../config
 
 # Compiler and linker flags.
+# GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for
 
 # Enable Intel Cilk Plus extension
 GENERAL_FLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/runtime \
 	-I$(top_srcdir)/runtime/config/$(config_dir) \
-	-DIN_CILK_RUNTIME=1 -D_Cilk_spawn="" -D_Cilk_sync="" \
-	-D_Cilk_for=for -fcilkplus
+	-DIN_CILK_RUNTIME=1 -fcilkplus
 AM_CFLAGS = $(GENERAL_FLAGS) -std=c99
 AM_CPPFLAGS = $(GENERAL_FLAGS)
 AM_LDFLAGS = -lpthread 
diff --git a/libcilkrts/configure.ac b/libcilkrts/configure.ac
index 30fac99..2a095de 100644
--- a/libcilkrts/configure.ac
+++ b/libcilkrts/configure.ac
@@ -31,8 +31,8 @@ 
 #  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #  POSSIBILITY OF SUCH DAMAGE.
 
-AC_INIT([Cilk Runtime Library], [2.0], [cilk@intel.com])
 AC_PREREQ([2.64])
+AC_INIT([Cilk Runtime Library], [2.0], [cilk@intel.com])
 
 # Needed to define ${target}.  Needs to be very early to avoid annoying
 # warning about calling AC_ARG_PROGRAM before AC_CANONICAL_SYSTEM
diff --git a/libcilkrts/runtime/symbol_test.c b/libcilkrts/runtime/symbol_test.c
index 1113ecd..8291d36 100644
--- a/libcilkrts/runtime/symbol_test.c
+++ b/libcilkrts/runtime/symbol_test.c
@@ -41,6 +41,7 @@ 
  * will cause a linker error.
  */
 
+#define _Cilk_for for
 extern void* __cilkrts_global_state;
 void *volatile p;