diff mbox

_Cilk_for for C and C++

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

Commit Message

Iyer, Balaji V Nov. 15, 2013, 7:23 p.m. UTC
[Sorry if you received multiple copies, the first one I had forgotten to CC gcc-patches]

Hello Everyone,
	Attached, please find two patches for implementing _Cilk_for for C and C++. I am attaching both of them in the same email because they both share a lot of common routines and the C++ require certain quick fix-ups that C doesn't need and vice-versa. So, if you could see both the patches then these kind of things are easier to see (at least for me it is).

This patch is dependent on the following patches:

#pragma simd work (they both share the same parser routines)

_Cilk_spawn and _Cilk_sync for C++: The Runtime that supports _Cilk_for requires a C++ compiler with _Cilk_spawn and _Cilk_sync support, and the Runtime is required to execute _Cilk_for tests: http://gcc.gnu.org/ml/gcc-patches/2013-10/msg01807.html. The C part is approved but C++ work is still under review. 


One small thing that I have not done that Jakub and several other have asked me before is that, there are no tests in c-c++-common for _Cilk_for. The reason being that the syntax between C and C++ implementations are different. In C++, the induction variable must be defined in the initializer (e.g. it should start wth _Cilk_for (int ii = 0....)). In C, this is not allowed (e.g. it should start as _Cilk_for (ii = 0; ii < 10; ii++)).

Here are the ChangeLog entries:

gcc/ChangeLog.
2013-11-15  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* cilk-builtins.def: Added 2 builtin functions: __cilkrts_cilk_for_64
	and __cilkrts_cilk_for_32.
	* cilk-common.c (cilk_declare_looper): New function.
	(cilk_init_builtins): Added two calls to cilk_declare_looper.
	* cilk.h (enum cilk_tree_index): Added two enums: CILK_TI_F_LOOP_32
	and CILK_TI_F_LOOP_64.
	(enum add_variable_type): Moved here from c-family/cilk.c
	(enum cilk_block_type): Likewise.
	(struct wrapper_data): Likewise.
	(struct cilk_for_desc): New struct.
	(cilk_for_32_fndecl): New #define.
	(cilk_for_64_fndecl): Likewise.
	* tree.h (CILK_FOR_INIT): Likewise.
	(CILK_FOR_COND): Likewise.
	(CILK_FOR_EXPR): Likewise.
	(CILK_FOR_BODY): Likewise.
	(CILK_FOR_SCOPE): Likewise.
	(CILK_FOR_GRAIN): Likewise.
	(CILK_FOR_VAR): Likewise.
	* gimplify.c (gimplify_expr): Added CILK_FOR_STMT case.
	* tree-pretty-print.c (dump_generic_node): Likewise.
	* langhooks-def.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR): New
	#define.
	(LANG_HOOKS_CILKPLUS): Added LANG_HOOKS_CILKPLUS_GIMPLIFY_FOR field.
	* langhooks.h (struct lang_hooks_for_cilkplus): Added a new field
	gimplify_cilk_for.
	* tree.def: Added a new tree CILK_FOR_STMT.

gcc/c-family/ChangeLog.
2013-11-15  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-cilkplus.c (c_check_cilk_loop_incr): Added a check for INDIRECT_REF,
	CLEANUP_POINT_EXPR and TARGET_EXPR.  Added PLUS_EXPR and POINTER_PLUS
	EXPR cases for MODIFY_EXPR case.  Added a CALL_EXPR case.
	(c_validate_cilk_plus_loop): Added "_Cilk_for loops" in the error
	reporting string.
	(c_check_cilk_loop): Added 2 new boolean parameters.  Added handling
	of CALL_EXPR and removed unwanted wrappers from the condition params.
	(c_finish_cilk_for_loops): New function.
	(cp_finish_cilk_for_loops): Likewise.
	* c-common.c (c_common_resword): Added _Cilk_for keyword.
	* c-common.h (enum rid): Added RID_CILK_FOR.
	(cp_finish_cilk_for_loop): New prototype.
	(c_finish_cilk_for_loop): Likewise.
	(cilk_init_fd): Likewise.
	(cilk_extract_free_variables): Likewise.
	(cilk_create_cilk_helper_decl): Likewise.
	(cilk_call_graph_add_fn): Likewise.
	(cilk_outline_body): Likewise.
	(cilk_check_loop_difference_type): Likewise.
	(declare_cilk_for_parms): Likewise.
	(declare_cilk_for_vars): Likewise.
	(cilk_loop_convert): Likewise.
	(cilk_divide_count): Likewise.
	(cilk_calc_forward_div_op): Likewise.
	(cilk_compute_loop_count): Likewise.
	(insert_cilk_for_nested_fn): Likewise.
	(cilk_compute_loop_var): Likewise.
	(cilk_set_inclusive_and_direction): Likewise.
	(cilk_set_iter_difftype): Likewise.
	(cilk_set_incr_info): Likewise.
	(cilk_set_init_info): Likewise.
	(clk_simplify_tree): Likewise.
	(cilk_find_code_from_call): Likewise.
	(cilk_tree_operand_noconv): Likewise.
	(cilk_resolve_continue_stmts): Likewise.
	* c-pragma.c (init_pragma): Added pragma grainsize.
	* c-pragma.h (enum pragma_kind): Added PRAGMA_CILK_GRAINSIZE.
	* cilk.c (enum add_variable_type): Moved to ../cilk.h.
	(enum cilk_block_type): Likewise.
	(struct wrapper_data): Likewise.
	(cilk_call_graph_add_fn): New function.
	(cilk_create_cilk_helper_decl): Likewise.
	(cilk_outline): Renamed to cilk_outline_body.  Also added a parameter
	to hold throw flag for C++.
	(cilk_create_wrapper_body): Renamed create_cilk_helper_decl,
	call_graph_add_fn and cilk_outline to cilk_create_cilk_helper_decl,
	cilk_call_graph_add_fn, and cilk_outline_body, respectively.
	(create_cilk_wrapper): Renamed extact_free_variables to
	cilk_extract_free_variables.
	(extract_free_variables): Likewise.
	(cilk_init_cfd): New function.
	(find_cilk_for_library_fn): Likewise.
	(cilk_compute_incr_direction): Likewise.
	(cilk_check_loop_difference_type): Likewise.
	(cilk_simplify_tree): Likewise.
	(declare_cilk_for_vars): Likewise.
	(declare_cilk_for_parms): Likewise.
	(cilk_loop_convert): Likewise.
	(cilk_divide_count): Likewise.
	(cilk_calc_forward_div_op): Likewise.
	(cilk_compute_loop_count): Likewise.
	(insert_cilk_for_nested_fn): Likewise.
	(cilk_compute_loop_var): Likewise.
	(cilk_tree_operand_noconv): Likewise.
	(cilk_find_code_from_call): Likewise.
	(cilk_set_init_info): Likewise.
	(cilk_set_inclusive_and_direction): Likewise.
	(cilk_set_iter_difftype): Likewise.
	(cilk_set_incr_info): Likewise.

gcc/c/ChangeLog.
2013-11-15  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* Make-lang.in (C_AND_OBJC_OBJS): Added c/c-cilk.o.
	* c-cilk.c: New file.
	* c-objc-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR): New
	#define.
	* c-parser.c (c_parser_cilk_for_statement): New function prototype.
	(c_parser_cilk_grainsize): New function prototype and function.
	(c_parser_statement_after_labels): Added RID_CILK_FOR case.
	(c_parser_pragma): Added PRAGMA_CILK_GRAINSIZE case.
	(c_parser_cilk_for_statement): Renamed a parameter.  Added code to
	accomodate RID_CILK_FOR tree (i.e. to parse _Cilk_for statements).
	* c-tree.h (c_gimplify_cilk_for): New prototype.

gcc/testsuite/ChangeLog.
2013-11-15  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* gcc.dg/cilk-plus/CK/cilk-for.c: New test.
	* gcc.dg/cilk-plus/CK/cilk_for_decr.c: Likewise.
	* gcc.dg/cilk-plus/CK/cilk_for_errors.c: Likewise.
	* gcc.dg/cilk-plus/CK/cilk_for_grain.c: Likewise.
	* gcc.dg/cilk-plus/CK/cilk_for_grain_errors.c: Likewise.
	* gcc.dg/cilk-plus/CK/cilk_for_ptr_iter.c: Likewise.
	* gcc.dg/cilk-plus/CK/cilk_for_warning.c: Likewise.
	* gcc.dg/cilk-plus/cilk-plus.exp: Added support to call _Cilk_for
	testcodes.

gcc/cp/ChangeLog.
2013-11-15  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* cp-cilk.c: Added langhooks.h and tree.h.
	(callable): New function.
	(calc_count_up_count_down): Likewise.
	(compute_loop_var_cp_iter_hdl): Likewise.
	(cp_create_cilk_for_body): Likewise.
	(create_cilk_for_nested_fn): Likewise.
	(gimplify_cilk_for_1): Likewise.
	(cp_extract_cilk_for_fields): Likewise.
	(cp_gimplify_cilk_for): Likewise.
	* cp-gimplify.c (genericize_cilk_for_stmt): Likewise.
	(cp_genericize_r): Added a check for CILK_FOR_STMT.
	* cp-objcp-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR): New
	#define.
	* cp-tree.h (begin_cilk_for_stmt): New prototype.
	(finish_cilk_for_stmt): Likewise.
	(finish_cilk_for_init_stmt): Likewise.
	(cp_gimplify_cilk_for): Likewise.
	* name-lookup.c (begin_scope): Added sk_cilk_for case.
	* name-lookup.h (enum scope_kind): Added sk_cilk_for.
	* parser.c (cp_parser_cilk_grainsize): New function and prototype.
	(cp_parser_init_declarator): Added a new parameter to hold the
	initial value.
	(cp_parser_statement): Added RID_CILK_FOR case.
	(cp_parser_iteration_statement): Likewise.
	(cp_parser_jump_statement): Added IN_CILK_FOR_STMT case (twice).
	(cp_parser_pragma): Added PRAGMA_CILK_GRAINSIZE case.
	(cp_parser_cilk_for_init_statement): New function.
	(cp_parser_cilk_for): Renamed a parameter and added support for
	parsing _Cilk_for loops that are part of Cilk keywords.
	* parser.h (IN_CILK_FOR_STMT): New #define.
	* pt.c (tsubst_expr): Added CILK_FOR_STMT case.
	* semantics.c (begin_for_scope): Added "_Cilk_for statement" in the
	header comment.
	(finish_for_expr): Added support for CILK_FOR_STMT to use this
	function.
	(finish_cilk_for_cond): Added support for processing templates.
	(begin_cilk_for_stmt): New function.
	(finish_cilk_for_init_stmt): Likewise.
	(finish_clk_for_stmt): Likewise.

gcc/testsuite/ChangeLog.
2013-11-15  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* g++.dg/cilk-plus/CK/cilk-for-start-at-5.cc: New test.
	* g++.dg/cilk-plus/CK/cilk-for-tplt.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk-for.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_cont_inside_for.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_cont_with_for.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_cont_with_if.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_cont_with_while.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_genricize_test.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_grainsize.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_p_errors.cc: Likewise.
	* g++.dg/cilk-plus/CK/cilk_for_t_errors.cc: Likewise.
	* g++.dg/cilk-plus/CK/explicit_ctor.cc: Likewise.
	* g++.dg/cilk-plus/CK/label_test.cc: Likewise.
	* g++.dg/cilk-plus/CK/no-opp-overload-error.cc: Likewise.
	* g++.dg/cilk-plus/CK/plus-equal-one.cc: Likewise.
	* g++.dg/cilk-plus/CK/plus-equal-test.cc: Likewise.
	* g++.dg/cilk-plus/CK/stl_iter.cc: Likewise.
	* g++.dg/cilk-plus/CK/stl_test.cc: Likewise.
	* g++.dg/cilk-plus/cilk-plus.exp: Added support to call _Cilk_for
	testcodes.


Thanking You,

Yours Sincerely,

Balaji V. Iyer.

diff --git a/gcc/cp/cp-cilk.c b/gcc/cp/cp-cilk.c
index 0da95e8..bd114c8
--- a/gcc/cp/cp-cilk.c
+++ b/gcc/cp/cp-cilk.c
@@ -23,8 +23,13 @@
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
+#include "tree.h"
 #include "tree-iterator.h"
 #include "cilk.h"
+#include "langhooks.h"
+#include "cgraph.h"
+#include "gimple.h"
+#include "gimplify.h"
 
 /* Sets the EXCEPTION bit (0x10) in the FRAME.flags field.  */
 
@@ -116,3 +121,483 @@ cilk_create_lambda_fn_tmp_var (tree lambda_fn)
   add_local_decl (cfun, return_var);
   return return_var;
 }
+
+/* Returns an overloaded function that does operation based on CODE using
+   OP0 and OP1.  If CRY is set to true, then the function complains when
+   it is unable to find an overloaded operator.  */
+
+static tree
+callable (location_t loc, enum tree_code code, tree op0, tree op1, bool cry)
+{
+  vec<tree, va_gc> *op1_vec = make_tree_vector_single (op1);
+  if (code == INIT_EXPR)
+    return build_special_member_call (NULL_TREE, complete_ctor_identifier,
+				      &op1_vec,
+				      TYPE_MAIN_VARIANT (TREE_TYPE (op1)), 0,
+				      cry);
+    
+  if (code == PSEUDO_DTOR_EXPR)
+    return build_special_member_call (NULL_TREE, complete_dtor_identifier,
+				      &op1_vec,
+				      TYPE_MAIN_VARIANT (TREE_TYPE (op1)), 0,
+				      cry);
+
+  int flags = LOOKUP_PROTECT | LOOKUP_ONLYCONVERTING;
+  tree exp = build_new_op (EXPR_LOCATION (op1), code, flags, op0, op1,
+			   NULL_TREE, NULL, 0);
+  if (exp == error_mark_node)
+    exp = build_x_modify_expr (EXPR_LOCATION (op1), op0, code, op1, tf_none);
+  if (exp && exp != error_mark_node)
+    return exp;
+
+  const char *op = operator_name_info[(int) code].name;
+  const char *explain = cry ? "" : "accessible, unambiguous";
+  if (op1) 
+    error_at (loc, "No%s operator%s(%T,%T) for _Cilk_for loop", explain, op, 
+	      TREE_TYPE (op0), TREE_TYPE (op1)); 
+  else 
+    error_at (loc, "No%s operator%s(%T,%T) for _Cilk_for loop", explain, op, 
+	      TREE_TYPE (op0), TREE_TYPE (op0));
+  return NULL_TREE;
+}
+
+/* Calculates the COUNT_UP and/or COUNT_DOWN values for a _Cilk_for loop using
+   its characteristics stored in *CFD.  */
+
+static void
+calc_count_up_count_down (struct cilk_for_desc *cfd, tree *count_up,
+			  tree *count_down)
+{
+  /* Reasoning for high and low variables can be found in
+     cilk_compute_loop_count in c-family/cilk.c.  */
+  tree high = cfd->end_var ? cfd->end_var : cfd->end_expr;
+  tree low = cfd->lower_bound ? cfd->lower_bound : cfd->var;
+
+  /* When these are invalid, we flag them in cilk_compute_loop_var.  This
+     condition is a bit rare.  */
+  if (high == error_mark_node || low == error_mark_node)
+    return;
+  
+  /* Only call this function if we are using an iterator.  */
+  gcc_assert (cfd->iterator);
+  
+  if (TREE_CODE (high) == TARGET_EXPR)
+    high = TARGET_EXPR_INITIAL (high);
+  if (TREE_CODE (low) == TARGET_EXPR)
+    low = TARGET_EXPR_INITIAL (low);
+  
+  if (TREE_CODE (low) == TREE_LIST)
+    low = TREE_VALUE (low);
+  high = cilk_tree_operand_noconv (high);
+  if (cfd->direction >= 0)
+    {
+      *count_up = build_x_binary_op (cfd->loc, MINUS_EXPR, high,
+				     TREE_CODE (high), low, TREE_CODE (low),
+				     NULL, tf_warning_or_error);
+      /* We should have already failed if this operator is not callable.  */
+      gcc_assert (*count_up != error_mark_node);
+    }
+  else
+    {
+      *count_down = build_x_binary_op (cfd->loc, MINUS_EXPR, low,
+				       TREE_CODE (low), high, TREE_CODE (high),
+				       NULL, tf_warning_or_error);
+      /* ...same reasoning as count up for the assert below.  */
+      gcc_assert (*count_down != error_mark_node);
+    }
+}
+
+/* Handler for iterator to compute the loop variable.  ADD_OP indicates
+   whether we need a '+' or '-' operation. LOW indicates the starting point
+   and LOOP_VAR is the induction variable.  Returns an expression (or a
+   STATEMENT_LIST of expressions).  If it is unable to find the appropriate
+   iteration, then it returns an error mark node and its parent will set
+   the loop as invalid.  */
+
+static tree
+compute_loop_var_cp_iter_hdl (location_t loc, enum tree_code add_op,
+			      tree low, tree loop_var, tree var2)
+{
+  tree exp = build_new_op (loc, add_op, 0, low, loop_var, NULL_TREE, 0,
+			   tf_none);
+  if (exp == error_mark_node)
+    {
+      /* If we are here then operator+ or operator- could not be found.
+	 So, the other option is to use +=.  This requires storing values
+	 in the variable and then adding them one by one.  */
+      tree new_var = var2;
+      exp = alloc_stmt_list ();
+      tree new_stmt = build_x_modify_expr (loc, new_var, INIT_EXPR,
+					   build_zero_cst (TREE_TYPE (new_var)),
+					   tf_warning_or_error);
+      if (new_stmt == error_mark_node)
+	return error_mark_node;
+      append_to_statement_list (new_stmt, &exp);
+      new_stmt = build_x_modify_expr (loc, new_var, NOP_EXPR, low,
+				      tf_warning_or_error);
+      if (new_stmt == error_mark_node)
+	return error_mark_node;
+      append_to_statement_list (new_stmt, &exp);
+      new_stmt = build_x_modify_expr (loc, new_var, add_op, loop_var,
+				      tf_warning_or_error);
+      if (new_stmt == error_mark_node)
+	return error_mark_node;
+      append_to_statement_list (new_stmt, &exp);
+      return exp;
+    }
+  exp = cp_build_modify_expr (var2, INIT_EXPR, exp, tf_warning_or_error);
+  return exp;
+}
+
+/* Returns the body of the nested function for a _Cilk_for using the loop's
+   characteristic information from CFD.  The returned tree will be a
+   STATEMENT LIST.  */
+
+static tree
+cp_create_cilk_for_body (struct cilk_for_desc *cfd)
+{
+  push_function_context ();
+  declare_cilk_for_parms (cfd);
+  cfd->wd.fntype = build_function_type (void_type_node, cfd->wd.argtypes);
+
+  tree fndecl = cilk_create_cilk_helper_decl (&cfd->wd);
+  fndecl = build_lang_decl (FUNCTION_DECL, DECL_NAME (fndecl), cfd->wd.fntype);
+  if (cfd->nested_ok)
+    DECL_CONTEXT (fndecl) = current_function_decl;
+  else
+    DECL_CONTEXT (fndecl) = DECL_CONTEXT (current_function_decl);
+
+  tree outer = current_function_decl;
+  SET_DECL_LANGUAGE (fndecl, lang_c);
+  start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
+
+  declare_cilk_for_vars (cfd, fndecl);
+  
+  tree lower_bound = cfd->lower_bound;
+  struct gimplify_ctx gctx;
+
+  tree body = begin_compound_stmt (BCS_FN_BODY);
+  push_gimplify_context (&gctx);
+
+  gimple_add_tmp_var (cfd->var2);
+
+  /* Get the lower bound into a variable unless it is a constant or a
+     non-copyable value.  If non-copyable value, then reference value from
+     the outer frame.  */
+  if (!lower_bound)
+    {
+      lower_bound = cfd->var;
+      tree hack = build_decl (cfd->loc, VAR_DECL, NULL_TREE,
+			      TREE_TYPE (lower_bound));
+      DECL_CONTEXT (hack) = DECL_CONTEXT (lower_bound);
+      *pointer_map_insert (cfd->wd.decl_map, hack) = lower_bound;
+      lower_bound = hack;
+    }
+  tree cast_max_expr, count_type, pre, loop_var;
+  if (INTEGRAL_TYPE_P (cfd->var_type))
+    {
+      loop_var = create_tmp_var (cfd->var_type, NULL);
+      count_type = cfd->var_type;
+      tree cvt_expr = cp_fold_convert (cfd->var_type, cfd->min_parm);
+      pre = build_x_modify_expr (cfd->loc, loop_var, NOP_EXPR, cvt_expr,
+				 tf_warning_or_error);
+      cast_max_expr = cp_fold_convert (count_type, cfd->max_parm);
+    }
+  else
+    {
+      loop_var = create_tmp_var (TREE_TYPE (cfd->min_parm), NULL);
+      count_type = cfd->count_type;
+      pre = fold_build2 (INIT_EXPR, void_type_node, loop_var, cfd->min_parm);
+      cast_max_expr = cfd->max_parm;
+    }
+
+  tree loop_body = alloc_stmt_list ();
+  
+  /* Concat. the control variable initialization with the loop body.
+     Do not call gimplify_and_add to append to list because we need
+     to wrap the entire list in a cleanup point expr to delay destruction
+     of the control variable to the end of the loop if it is an iterator.  */
+  tree loop_end_comp = cilk_compute_loop_var (cfd, loop_var, lower_bound,
+					      compute_loop_var_cp_iter_hdl);
+  if (loop_end_comp == error_mark_node)
+    {
+      cfd->invalid = true;
+      return error_mark_node;
+    }
+  append_to_statement_list (loop_end_comp, &loop_body);
+  tree cleanup = cxx_maybe_build_cleanup (cfd->var2, tf_none);
+  if (cleanup)
+    {
+      append_to_statement_list (cfd->body, &loop_body);
+      append_to_statement_list (cleanup, &loop_body);
+    }
+  else
+    append_to_statement_list (cfd->body, &loop_body);
+
+  loop_body = fold_build_cleanup_point_expr (void_type_node, loop_body);
+  DECL_SEEN_IN_BIND_EXPR_P (cfd->var2) = 1;
+
+  cfd->wd.context = outer;
+  bool throws = flag_exceptions ? cp_function_chain->can_throw : false;
+  cilk_outline_body (fndecl, &loop_body, &cfd->wd, &throws);
+  cp_function_chain->can_throw = throws;
+  
+  /* We have to manually create this loop for two reasons:
+     a. We need to have access to continue and start label since we need
+        to resolve continue and breaks by hand.
+     b. C++ doesn't provide a c_finish_loop function like C does.  */
+  tree c_for_loop = push_stmt_list ();
+  tree slab = build_decl (cfd->loc, LABEL_DECL, NULL_TREE, void_type_node);
+  DECL_ARTIFICIAL (slab) = 0;
+  DECL_IGNORED_P (slab) = 1;
+  DECL_CONTEXT (slab) = fndecl;
+  tree top_label = build1 (LABEL_EXPR, void_type_node, slab);
+
+  tree cont_lab = build_decl (cfd->loc, LABEL_DECL, NULL_TREE, void_type_node);
+  DECL_ARTIFICIAL (cont_lab) = 0;
+  DECL_IGNORED_P (cont_lab) = 1;
+  DECL_CONTEXT (cont_lab) = fndecl;
+
+  tree continue_label = build1 (LABEL_EXPR, void_type_node, cont_lab);
+  tree loop_cond = fold_build2 (LT_EXPR, boolean_type_node, loop_var,
+				cast_max_expr);
+  tree cond_expr = build3 (COND_EXPR, void_type_node, loop_cond,
+			   build1 (GOTO_EXPR, void_type_node, slab),
+			   build_empty_stmt (cfd->loc));
+  tree mod_expr = fold_build2 (MODIFY_EXPR, void_type_node, loop_var,
+				build2 (PLUS_EXPR, count_type, loop_var,
+					build_one_cst (count_type)));
+  add_stmt (pre);
+  add_stmt (top_label);
+  add_stmt (loop_body);
+  add_stmt (continue_label);
+  add_stmt (mod_expr);
+  add_stmt (cond_expr);
+  pop_stmt_list (c_for_loop);
+
+  /* Resolve all the continues in the _Cilk_for body here.  */
+  walk_tree (&c_for_loop, cilk_resolve_continue_stmts, (void *) cont_lab, NULL);
+  add_stmt (c_for_loop);
+
+  DECL_INITIAL (fndecl) = make_node (BLOCK);
+  TREE_USED (DECL_INITIAL (fndecl)) = 1;
+  BLOCK_VARS (DECL_INITIAL (fndecl)) = loop_var;
+  TREE_CHAIN (loop_var) = cfd->var2;
+
+  body = build3 (BIND_EXPR, void_type_node, loop_var, body,
+		 DECL_INITIAL (fndecl));
+  DECL_CONTEXT (cfd->var2) = fndecl;
+  pop_gimplify_context (0);
+
+  finish_function_body (body);
+  
+  /* A nested function canot be expanded or deferred until its parent is done.
+     So, don't call expand_or_defer_fn here.  A non-nested function must be
+     done here.  */
+  if (!cfd->nested_ok)
+    expand_or_defer_fn (fndecl);
+  
+  pop_function_context ();
+  return fndecl;
+}
+
+/* Creates a nested function for the _Cilk_for statement using its information
+   in CFD.  PRE_P is the preceeding gimple trees function.  */
+
+static tree
+create_cilk_for_nested_fn (struct cilk_for_desc *cfd, gimple_seq *pre_p)
+{
+  tree var = cfd->var;
+  DECL_CONTEXT (var) = current_function_decl;
+
+  if (POINTER_TYPE_P (TREE_TYPE (var)))
+    cilk_extract_free_variables (cfd->lower_bound, &cfd->wd, ADD_WRITE);
+  else
+    cilk_extract_free_variables (cfd->lower_bound, &cfd->wd, ADD_READ);
+
+  tree incr = cfd->incr;
+
+  /* If the loop increment is not an integer constant and is not a DECL,
+     copy it to a temporary.  if it is modified during the loop the behavior
+     is undefined.  Races could be avoided by copying it to a temporary
+     variable.  */
+  if (TREE_CODE (incr) != INTEGER_CST && !DECL_P (incr))
+    {
+      incr = get_formal_tmp_var (incr, pre_p);
+      cfd->incr = incr;
+    }
+
+  if (DECL_P (incr) && !TREE_STATIC (incr) && !DECL_EXTERNAL (incr))
+    *pointer_map_insert (cfd->wd.decl_map, incr) = incr;
+
+  /* Map the loop variable to integer_minus_one_node if we won't really be
+     passing it into hte loop body.  Otherwise map to integer_zero_node.  */
+  *pointer_map_insert (cfd->wd.decl_map, var) =
+    (void *) (cfd->lower_bound ? integer_minus_one_node : integer_zero_node);
+  cilk_extract_free_variables (cfd->body, &cfd->wd, ADD_READ);
+
+  tree fn = cp_create_cilk_for_body (cfd);
+
+  /* One of the reasons why FN is error_mark_node is because the function
+     couldn't find the appropriate overloaded operation.  */
+  if (fn == error_mark_node)
+    return error_mark_node;
+
+  DECL_UNINLINABLE (fn) = 1;
+  DECL_STATIC_CHAIN (fn) = 1;
+
+  current_function_decl = fn;
+  /* Genericize the _Cilk_for body, mainly split up the _Cilk_for body and
+     the for-loop we inserted.  */
+  cp_genericize (fn);
+  return fn;
+}
+
+/* Helper function to gimplify a CILK_FOR_STMT.  CFD holds all the values
+   extracted a CILK_FOR_STMT and *PRE_P is the preceeding sequence.  */
+
+static void
+gimplify_cilk_for_1 (struct cilk_for_desc cfd, gimple_seq *pre_p)
+{
+  bool order_variable = false;
+  tree parent_function = current_function_decl;
+  
+  if (TREE_SIDE_EFFECTS (cfd.end_expr))
+    {
+      enum tree_code ecode = TREE_CODE (cfd.end_expr);
+      if (ecode == INIT_EXPR || ecode == MODIFY_EXPR)
+	cfd.end_var = TREE_OPERAND (cfd.end_expr, 0);
+      else if (ecode == TARGET_EXPR)
+	{
+	  cfd.end_var = TARGET_EXPR_INITIAL (cfd.end_expr);
+	  if (TREE_CODE (cfd.end_var) == AGGR_INIT_EXPR)
+	    cfd.end_var = TARGET_EXPR_SLOT (cfd.end_expr);
+	  else
+	    cfd.end_var = get_formal_tmp_var (cfd.end_var, pre_p);
+	}
+      else if (ecode == CALL_EXPR)
+	cfd.end_var = cfd.end_expr;
+      else
+	{
+	  tree ii_tree = cfd.end_expr;
+	  while (TREE_CODE_CLASS (TREE_CODE (ii_tree)) == tcc_unary)
+	    ii_tree = TREE_OPERAND (ii_tree, 0);
+	  if (TREE_CODE (ii_tree) == ADDR_EXPR)
+	    ii_tree = TREE_OPERAND (ii_tree, 0);
+	  ecode = TREE_CODE (ii_tree);
+	  tree tmp_var = cilk_tree_operand_noconv (cfd.end_expr);
+	  cfd.end_var = get_formal_tmp_var (tmp_var, pre_p);
+	  order_variable = true;
+	}
+    }
+  tree cond = cfd.cond;
+  tree op1 = TREE_OPERAND (cond, 1);
+  tree op0 = TREE_OPERAND (cond, 0);
+  enum tree_code cond_code = TREE_CODE (cond);
+
+  /* In this case below, we have an overloaded boolean comparison operation.  */
+  if (cond_code == CALL_EXPR)
+    {
+      cond_code = cilk_find_code_from_call (CALL_EXPR_FN (cond));
+      op1 = cilk_tree_operand_noconv (CALL_EXPR_ARG (cond, 1));
+      op0 = cilk_tree_operand_noconv (CALL_EXPR_ARG (cond, 0));
+      if (TREE_CODE (op0) == ADDR_EXPR || TREE_CODE (op0) == INDIRECT_REF)
+	op0 = TREE_OPERAND (op0, 0);
+    }
+  if (order_variable && op1 == cfd.end_expr)
+    op1 = cfd.end_var;
+  else if (order_variable && op0 == cfd.end_expr)
+    op0 = cfd.end_var;
+  
+  cond = callable (cfd.loc, cond_code, op0, op1, false);
+  gcc_assert (cond != NULL_TREE);
+
+  if (TREE_CODE (TREE_TYPE (cond)) != BOOLEAN_TYPE)
+    cond = perform_implicit_conversion (boolean_type_node, cond,
+					tf_warning_or_error);
+  enum tree_code div_op = NOP_EXPR;
+  tree forward = NULL_TREE, count_up = NULL_TREE, count_down = NULL_TREE;
+  cilk_calc_forward_div_op (&cfd, &div_op, &forward);
+  if (cfd.iterator)
+    calc_count_up_count_down (&cfd, &count_up, &count_down);
+  
+  tree count = cilk_compute_loop_count (&cfd, div_op, forward, count_up,
+					count_down);
+  tree fn = create_cilk_for_nested_fn (&cfd, pre_p);
+  if (fn == error_mark_node)
+    return;
+  cfd.cond = cond;
+  
+  current_function_decl = parent_function;
+  gimple_seq inner_seq = insert_cilk_for_nested_fn (&cfd, count, fn);
+  gimple_seq_add_seq (pre_p, inner_seq);
+}
+
+/* Extract all the relevant information from CFOR, a CILK_FOR_STMT tree
+   and store them in CFD structure.  */
+
+static void
+cp_extract_cilk_for_fields (struct cilk_for_desc *cfd, tree cfor)
+{
+  cfd->var = CILK_FOR_VAR (cfor);
+  cfd->cond = CILK_FOR_COND (cfor);
+  cfd->lower_bound = CILK_FOR_INIT (cfor);
+  cfd->incr = CILK_FOR_EXPR (cfor);
+  cfd->loc = EXPR_LOCATION (cfor);
+  cfd->body = CILK_FOR_BODY (cfor);
+  cfd->grain = CILK_FOR_GRAIN (cfor);
+  cfd->invalid = false;
+
+  /* This function shouldn't be setting these two variables.  */
+  cfd->ctx_arg = NULL_TREE;
+  cfd->count = NULL_TREE;
+  
+  cilk_set_init_info (cfd);
+  cilk_set_inclusive_and_direction (cfd);
+  cilk_set_iter_difftype (cfd);
+
+  if (cfd->iterator)
+    {
+      tree exp = NULL_TREE;
+      tree hack = build_decl (cfd->loc, VAR_DECL, NULL_TREE,
+			      TREE_TYPE (cfd->var));
+      if (cfd->direction >= 0)
+	exp = callable (cfd->loc, MINUS_EXPR, hack, cfd->var,true);
+      else
+	exp = callable (cfd->loc, MINUS_EXPR, cfd->var, hack, true);
+      if (!exp) 
+	{ 
+	  cfd->invalid = true;
+	  return;
+	}
+      cfd->difference_type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+    }
+  cfd->count_type = cilk_check_loop_difference_type (cfd->difference_type);
+  cilk_set_incr_info (cfd, true);
+}
+
+/* Entry function to gimplify a CILK_FOR_STMT, *FOR_P.  *PRE_P and *POST_P are
+    preceeding and proceeding gimple sequences of *FOR_P, respectively.  */
+
+int
+cp_gimplify_cilk_for (tree *for_p, gimple_seq *pre_p,
+		      gimple_seq *post_p ATTRIBUTE_UNUSED)
+{
+  struct cilk_for_desc cfd;
+
+  cfun->is_cilk_function = 1;
+  cilk_init_cfd (&cfd);
+
+  cp_extract_cilk_for_fields (&cfd, *for_p);
+  if (cfd.invalid)
+    {
+      *for_p = build_empty_stmt (cfd.loc);
+      return GS_ERROR;
+    }
+  cfd.nested_ok = !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl);
+  gimplify_cilk_for_1 (cfd, pre_p);
+  *for_p = NULL_TREE;
+
+  return GS_ALL_DONE;
+}
+
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index e8ccf1a..ed630bf 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -268,6 +268,23 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
   *stmt_p = stmt_list;
 }
 
+/* Genericize a CILK_FOR_STMT node *STMT_P.  */
+
+static void
+genericize_cilk_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
+{
+  tree stmt = *stmt_p;
+  cp_walk_tree (&CILK_FOR_COND (stmt), cp_genericize_r, data, NULL);
+  cp_walk_tree (&CILK_FOR_INIT (stmt), cp_genericize_r, data, NULL);
+  cp_walk_tree (&CILK_FOR_GRAIN (stmt), cp_genericize_r, data, NULL);
+  cp_walk_tree (&CILK_FOR_VAR (stmt), cp_genericize_r, data, NULL);
+  cp_walk_tree (&CILK_FOR_EXPR (stmt), cp_genericize_r, data, NULL);
+
+  /* _Cilk_for body will be resolved after it is inserted into a nested
+     function.  */
+  *walk_subtrees = 0;
+} 
+
 /* Genericize a FOR_STMT node *STMT_P.  */
 
 static void
@@ -1120,6 +1137,8 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
     gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
   else if (TREE_CODE (stmt) == FOR_STMT)
     genericize_for_stmt (stmt_p, walk_subtrees, data);
+  else if (TREE_CODE (stmt) == CILK_FOR_STMT)
+    genericize_cilk_for_stmt (stmt_p, walk_subtrees, data);
   else if (TREE_CODE (stmt) == WHILE_STMT)
     genericize_while_stmt (stmt_p, walk_subtrees, data);
   else if (TREE_CODE (stmt) == DO_STMT)
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 77a66c3..baf3ee3 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -164,4 +164,7 @@ extern void cp_common_init_ts (void);
 #undef  LANG_HOOKS_CILKPLUS_FRAME_CLEANUP
 #define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP cp_cilk_install_body_wframe_cleanup
 
+#undef  LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR
+#define LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR cp_gimplify_cilk_for
+
 #endif /* GCC_CP_OBJCP_COMMON */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9a950f0..c0c0291 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5686,6 +5686,9 @@ extern void finish_for_init_stmt		(tree);
 extern void finish_for_cond			(tree, tree, bool);
 extern void finish_for_expr			(tree, tree);
 extern void finish_for_stmt			(tree);
+extern tree begin_cilk_for_stmt                 (tree, tree);
+extern void finish_cilk_for_init_stmt           (tree);
+extern tree finish_cilk_for_stmt                (tree);
 extern tree begin_range_for_stmt		(tree, tree);
 extern void finish_range_for_decl		(tree, tree, tree);
 extern void finish_range_for_stmt		(tree);
@@ -6193,6 +6196,8 @@ extern int gimplify_cilk_spawn                  (tree *, gimple_seq *,
 /* In cp/cp-cilk.c */
 extern void cp_cilk_install_body_wframe_cleanup (tree, tree);
 extern tree cilk_create_lambda_fn_tmp_var       (tree);
+extern int cp_gimplify_cilk_for                 (tree *, gimple_seq *,
+						 gimple_seq *);
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index ced596e..ae03c56 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1542,6 +1542,7 @@ begin_scope (scope_kind kind, tree entity)
     case sk_try:
     case sk_catch:
     case sk_for:
+    case sk_cilk_for:
     case sk_cond:
     case sk_class:
     case sk_scoped_enum:
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 57641a1..66d1876 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -107,6 +107,8 @@ typedef enum scope_kind {
   sk_catch,	     /* A catch-block.  */
   sk_for,	     /* The scope of the variable declared in a
 			for-init-statement.  */
+  sk_cilk_for,       /* The scope of the variable declared in _Cilk_for init
+			statement.  */
   sk_cond,	     /* The scope of the variable declared in the condition
 			of an if or switch statement.  */
   sk_function_parms, /* The scope containing function parameters.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3a22e90..25e2796 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -237,6 +237,8 @@ static void cp_parser_cilk_simd_construct
   (cp_parser *, cp_token *);
 static tree cp_parser_cilk_for
   (cp_parser *, enum rid, tree);
+static void cp_parser_cilk_grainsize
+  (cp_parser *, cp_token *);
 static bool cp_parser_omp_declare_reduction_exprs
   (tree, cp_parser *);
 
@@ -2060,7 +2062,8 @@ static tree cp_parser_decltype
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *);
+  (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
+   bool, bool, int, bool *, tree *, tree *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
 static cp_declarator *cp_parser_direct_declarator
@@ -9350,6 +9353,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
 	case RID_WHILE:
 	case RID_DO:
+	case RID_CILK_FOR:
 	case RID_FOR:
 	  statement = cp_parser_iteration_statement (parser, false);
 	  break;
@@ -10505,6 +10509,17 @@ cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
       }
       break;
 
+    case RID_CILK_FOR:
+      if (!flag_enable_cilkplus)
+	{ 
+	  error_at (token->location, 
+		    "-fcilkplus must be enabled t use %<_Cilk_for%>");
+	  statement = error_mark_node;
+	}
+      else
+	statement = cp_parser_cilk_for (parser, RID_CILK_FOR, NULL_TREE);
+      break;
+
     default:
       cp_parser_error (parser, "expected iteration-statement");
       statement = error_mark_node;
@@ -10624,6 +10639,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_FOR_STMT:
+	  error_at (token->location,
+		    "break statement used in _Cilk_for loop body");
+	  break;
 	case IN_CILK_P_SIMD_FOR:
 	  error_at (token->location,
 		    "break statement within <#pragma simd> loop body");
@@ -10639,6 +10658,7 @@ cp_parser_jump_statement (cp_parser* parser)
 	  error_at (token->location, "continue statement not within a loop");
 	  break;
 	case IN_ITERATION_STMT:
+	case IN_CILK_FOR_STMT:
 	case IN_OMP_FOR:
 	  statement = finish_continue_stmt ();
 	  break;
@@ -11189,7 +11209,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 					/*member_p=*/false,
 					declares_class_or_enum,
 					&function_definition_p,
-					maybe_range_for_decl);
+					maybe_range_for_decl, NULL);
       /* If an error occurred while parsing tentatively, exit quickly.
 	 (That usually happens when in the body of a function; each
 	 statement is treated as a declaration-statement until proven
@@ -16440,7 +16460,8 @@ cp_parser_init_declarator (cp_parser* parser,
 			   bool member_p,
 			   int declares_class_or_enum,
 			   bool* function_definition_p,
-			   tree* maybe_range_for_decl)
+			   tree* maybe_range_for_decl,
+			   tree* init)
 {
   cp_token *token = NULL, *asm_spec_start_token = NULL,
            *attributes_start_token = NULL;
@@ -16448,7 +16469,9 @@ cp_parser_init_declarator (cp_parser* parser,
   tree prefix_attributes;
   tree attributes = NULL;
   tree asm_specification;
-  tree initializer;
+  /* Initialize initalizer to remove a "using potentially unset variable"
+     warning/error.  */
+  tree initializer = NULL_TREE;
   tree decl = NULL_TREE;
   tree scope;
   int is_initialized;
@@ -16585,7 +16608,8 @@ cp_parser_init_declarator (cp_parser* parser,
 	      DECL_STRUCT_FUNCTION (decl)->function_start_locus
 		= func_brace_location;
 	    }

+	  if (init)
+	    *init = initializer;
 	  return decl;
 	}
     }
@@ -16820,6 +16844,8 @@ cp_parser_init_declarator (cp_parser* parser,
 	finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
     }
 
+  if (init)
+    *init = initializer;
   return decl;
 }
 
@@ -22985,6 +23011,7 @@ cp_parser_single_declaration (cp_parser* parser,
 				        member_p,
 				        declares_class_or_enum,
 				        &function_definition_p,
+					NULL,
 					NULL);
 
     /* 7.1.1-1 [dcl.stc]
@@ -31243,6 +31270,21 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       cp_parser_cilk_simd_construct (parser, pragma_tok);
       return true;
 
+    case PRAGMA_CILK_GRAINSIZE:
+      if (context == pragma_external)
+	{
+	  error_at (pragma_tok->location,
+		    "%<#pragma cilk grainsize%> may only be be used inside a "
+		    "function");
+	  break;
+	}
+
+      /* Ignore the pragma if Cilk Plus is not enabled.  */
+      if (flag_enable_cilkplus)
+	{
+	  cp_parser_cilk_grainsize (parser, pragma_tok);
+	  return true;
+	}
     default:
       gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
       c_invoke_pragma_handler (id);
@@ -31608,28 +31650,135 @@ cp_parser_simd_for_init_statement (cp_parser *parser, tree *init,
   return decl;
 }
 
+static tree
+cp_parser_cilk_for_init_statement (cp_parser *parser, tree *init)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  location_t loc = token->location;
+  tree decl_init = NULL_TREE;
+  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);
+    }
+
+  if (token->type == CPP_NAME)
+    {
+      tree type = cp_parser_lookup_name_simple (parser, token->u.value, loc);
+      if (TREE_CODE (type) == VAR_DECL || TREE_CODE (type) == PARM_DECL)
+	{
+	  error_at (loc, "_Cilk_for loop initializer must declare variable");
+	  cp_parser_skip_to_end_of_statement (parser);
+	  return error_mark_node;
+	}
+    }
+  int flags = 0;
+  cp_decl_specifier_seq specs;
+  cp_parser_decl_specifier_seq (parser, CP_PARSER_FLAGS_NONE, &specs, &flags);
+  tree decl = cp_parser_init_declarator (parser, &specs, NULL, false, false,
+					 flags, NULL, NULL, &decl_init);
+  /* Sometimes if the initial is constant, it won't save in DECL_INITIAL,
+     and thus we need to get the initial value.  Now, if it saved the
+     DECL_INITIAL value, then just use it since it will have all the
+     necessary type casting.  */
+  if (DECL_INITIAL (decl))
+      decl_init = DECL_INITIAL (decl);
+
+  
+  if (processing_template_decl)
+    add_stmt (decl_init);
+  else
+    *init = decl_init;
+  parser->scope = NULL_TREE;
+  parser->qualifying_scope = NULL_TREE;
+  parser->object_scope = NULL_TREE;
+
+  if (decl == error_mark_node || DECL_INITIAL (decl) == error_mark_node
+      || TREE_TYPE (decl) == error_mark_node)
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      gcc_assert (errorcount || sorrycount);
+      return error_mark_node;
+    }
+  return decl;
+}
+
+static void
+cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
+{
+  if (cp_parser_require (parser, CPP_EQ, RT_EQ))
+    {
+      tree exp = cp_parser_binary_expression (parser, false, false,
+					      PREC_NOT_OPERATOR, NULL);
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      if (!exp || exp == error_mark_node)
+	{
+	  error_at (pragma_tok->location, "invalid grainsize for _Cilk_for");
+	  return;
+	}
+      cp_token *n_tok = cp_lexer_peek_token (parser->lexer);
+
+      /* Make sure the next token is _Cilk_for, it is invalid otherwise.  */
+      if (n_tok && n_tok->type == CPP_KEYWORD && n_tok->keyword == RID_CILK_FOR)
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  tree cfor = cp_parser_cilk_for (parser, RID_CILK_FOR, exp);
+	  if (cfor && STATEMENT_CODE_P (TREE_CODE (cfor)))
+	    SET_EXPR_LOCATION (cfor, n_tok->location);
+	}
+      else
+	warning (0, "%<#pragma cilk grainsize%> is not followed by "
+		 "%<_Cilk_for%>");
+      return;
+    }
+  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+	      
+
 /* 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)
+cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword,
+		    tree clauses_or_grain)
 {
   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;
-  
-  if (!cp_lexer_next_token_is_keyword (parser->lexer, for_keyword))
+  tree clauses = (for_keyword == RID_FOR) ? clauses_or_grain : NULL_TREE;
+  tree grain = (for_keyword == RID_CILK_FOR) ? clauses_or_grain: NULL_TREE;
+  tree statement = NULL_TREE;
+
+  /* If the RID_KEYWORD is RID_CILK_FOR, then it would already be consumed
+     by the parser.  So, this check will fail.  */
+  if (for_keyword == RID_FOR)
     {
-      if (for_keyword == RID_FOR)
-	cp_parser_error (parser, "for statement expected");
+      if (!cp_lexer_next_token_is_keyword (parser->lexer, for_keyword))
+	{
+	  cp_parser_error (parser, "for statement expected");
+	  return error_mark_node;
+	}
       else
-	cp_parser_error (parser, "_Cilk_for statement expected");
-      return error_mark_node;
+	cp_lexer_consume_token (parser->lexer);
     }
-  cp_lexer_consume_token (parser->lexer);
-
+  if (for_keyword == RID_CILK_FOR)
+    {
+      tree scope = begin_for_scope (&init);
+      statement = begin_cilk_for_stmt (scope, init);
+    }
+      
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     {
       cp_parser_skip_to_end_of_statement (parser);
@@ -31639,7 +31788,9 @@ cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
   /* Parse initialization.  */
   if (for_keyword == RID_FOR)
     decl = cp_parser_simd_for_init_statement (parser, &init, &pre_body);
-
+  else
+    decl = cp_parser_cilk_for_init_statement (parser, &init);
+    
   if (decl == error_mark_node)
     valid = false;
   else if (!decl || (TREE_CODE (decl) != VAR_DECL
@@ -31663,6 +31814,12 @@ cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
       /* Skip to the semicolon ending the init.  */
       cp_parser_skip_to_end_of_statement (parser);
     }
+  else if (for_keyword == RID_CILK_FOR)
+    {
+      CILK_FOR_INIT (statement) = init;
+      CILK_FOR_VAR (statement) = decl;
+      finish_cilk_for_init_stmt (statement);
+    }
 
   /* Parse condition.  */
   if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
@@ -31673,9 +31830,11 @@ cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
       cond = error_mark_node;
     }
   else
-    {
+    { 
       cond = cp_parser_condition (parser);
       cond = finish_cilk_for_cond (cond);
+      if (for_keyword == RID_CILK_FOR)
+	CILK_FOR_COND (statement) = cond;
     }
 
   if (cond == error_mark_node)
@@ -31690,13 +31849,11 @@ cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
     }
   else
     incr_expr = cp_parser_expression (parser, false, NULL);
-  
-  if (incr_expr == error_mark_node)
+  if (TREE_CODE (incr_expr) == ERROR_MARK)
     {
       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);
@@ -31708,7 +31865,7 @@ cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
       gcc_assert (sorrycount || errorcount);
       return error_mark_node;
     }
-
+  
   if (for_keyword == RID_FOR)
     {
       parser->in_statement = IN_CILK_P_SIMD_FOR;
@@ -31728,9 +31885,20 @@ cp_parser_cilk_for (cp_parser *parser, enum rid for_keyword, tree clauses)
     }
   else
     {
-      /* Handle _Cilk_for here when implemented.  */
-      gcc_unreachable ();
-      return NULL_TREE;
+      finish_for_expr (incr_expr, statement);
+      CILK_FOR_EXPR (statement) = incr_expr;
+      int saved_in_statement = parser->in_statement;
+      parser->in_statement = IN_CILK_FOR_STMT;
+      cp_parser_already_scoped_statement (parser);
+      parser->in_statement = saved_in_statement;
+      /* Check if the body satisfies all the requirement of _Cilk_for.
+	 If invalid, then just return error_mark_node.  */
+      CILK_FOR_GRAIN (statement) = grain;
+      statement = finish_cilk_for_stmt (statement);
+      if (statement == error_mark_node
+	  || !cpp_validate_cilk_plus_loop (CILK_FOR_BODY (statement)))
+	return error_mark_node;
+      return statement;
     }
 }
 
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 093ca41..a0ad750 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -301,7 +301,9 @@ typedef struct GTY(()) cp_parser {
 #define IN_OMP_FOR		8
 #define IN_IF_STMT             16
 #define IN_CILK_P_SIMD_FOR     32 
 #define IN_CILK_SPAWN          64 
+#define IN_CILK_FOR_STMT       128
+  
   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 3357966..e7262ad 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13328,6 +13328,45 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       finish_for_stmt (stmt);
       break;
 
+    case CILK_FOR_STMT:
+      {
+	stmt = begin_cilk_for_stmt (NULL_TREE, NULL_TREE);
+	CILK_FOR_INIT (stmt) = RECUR (CILK_FOR_INIT (t));
+	finish_cilk_for_init_stmt (stmt);
+	tmp = RECUR (CILK_FOR_VAR (t));
+	CILK_FOR_VAR (stmt) = tmp;
+	CILK_FOR_GRAIN (stmt) = CILK_FOR_GRAIN (t);
+
+	tmp = CILK_FOR_COND (t);
+	if (COMPARISON_CLASS_P (tmp))
+	  {
+	    tree op0 = RECUR (TREE_OPERAND (tmp, 0));
+	    tree op1 = RECUR (TREE_OPERAND (tmp, 1));
+	    tmp = build2 (TREE_CODE (tmp), boolean_type_node, op0, op1);
+	  }
+	CILK_FOR_COND (stmt) = tmp;
+
+	tmp = CILK_FOR_EXPR (t);
+	if (TREE_CODE (tmp) == MODIFY_EXPR)
+	  {
+	    tree lhs = TREE_OPERAND (tmp, 0);
+	    tree rhs = TREE_OPERAND (tmp, 1);
+	    lhs = RECUR (lhs);
+	    rhs = build2 (TREE_CODE (rhs), TREE_TYPE (lhs),
+			  RECUR (TREE_OPERAND (rhs, 0)),
+			  RECUR (TREE_OPERAND (rhs, 1)));
+	    tmp = build2 (MODIFY_EXPR, void_type_node, lhs, rhs);
+	  }
+	else
+	  tmp = build2 (TREE_CODE (tmp), void_type_node,
+			RECUR (TREE_OPERAND (tmp, 0)),
+			RECUR (TREE_OPERAND (tmp, 1)));
+	finish_for_expr (tmp, stmt);
+	RECUR (CILK_FOR_BODY (t));
+	stmt = finish_cilk_for_stmt (stmt);
+	CILK_FOR_GRAIN (stmt) = RECUR (CILK_FOR_GRAIN (t));	
+	break;
+      }
     case RANGE_FOR_STMT:
       {
         tree decl, expr;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c03cdc5..03e72a1 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -825,7 +825,8 @@ finish_return_stmt (tree expr)
   return r;
 }
 
-/* Begin the scope of a for-statement or a range-for-statement.
+/* Begin the scope of a for-statement _Cilk_for statement 
+   or a range-for-statement.
    Both the returned trees are to be used in a call to
    begin_for_stmt or begin_range_for_stmt.  */
 
@@ -898,7 +899,7 @@ finish_for_cond (tree cond, tree for_stmt, bool ivdep)
 }
 
 /* Finish the increment-EXPRESSION in a for-statement, which may be
-   given by FOR_STMT.  */
+   given by FOR_STMT or CILK_FOR_STMT.  */
 
 void
 finish_for_expr (tree expr, tree for_stmt)
@@ -925,7 +926,10 @@ finish_for_expr (tree expr, tree for_stmt)
   expr = maybe_cleanup_point_expr_void (expr);
   if (check_for_bare_parameter_packs (expr))
     expr = error_mark_node;
-  FOR_EXPR (for_stmt) = expr;
+  if (TREE_CODE (for_stmt) == CILK_FOR_STMT)
+    CILK_FOR_EXPR (for_stmt) = expr;
+  else
+    FOR_EXPR (for_stmt) = expr;
 }
 
 /* Finish the body of a for-statement, which may be given by
@@ -6666,7 +6670,10 @@ finish_omp_cancellation_point (tree clauses)
 tree
 finish_cilk_for_cond (tree cond)
 {
-  return cp_truthvalue_conversion (cond);
+  if (!processing_template_decl)
+    return cp_truthvalue_conversion (cond);
+  else
+    return cond;
 }
 
 /* Begin a __transaction_atomic or __transaction_relaxed statement.
@@ -10621,4 +10628,51 @@ capture_decltype (tree decl)
   return type;
 }
 
+/* Begin a _Cilk_for-statement.  Returns a new FOR_STMT.  
+   SCOPE and INIT should be the return of begin_for_scope, 
+   or both NULL_TREE  */
+
+tree
+begin_cilk_for_stmt (tree scope, tree init)
+{
+  tree cilk_for_stmt = build_stmt (input_location, CILK_FOR_STMT, NULL_TREE,
+				   NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
+				   NULL_TREE, NULL_TREE);
+  if (scope == NULL_TREE)
+    {
+      if (!init)
+	scope = begin_for_scope (&init);
+    }
+  CILK_FOR_INIT (cilk_for_stmt) = init;
+  CILK_FOR_SCOPE (cilk_for_stmt) = scope;
+  return cilk_for_stmt;
+}
+
+/* Finish the for-init-statement of a for-statement, which may be given 
+   by C_FOR_STMT.  */
+
+void
+finish_cilk_for_init_stmt (tree c_for_stmt)
+{
+  if (processing_template_decl)
+    CILK_FOR_INIT (c_for_stmt) = pop_stmt_list (CILK_FOR_INIT (c_for_stmt));
+  CILK_FOR_BODY (c_for_stmt) = do_pushlevel (sk_block);
+}
+
+/* Finish the body of a for-statement, which may be given by FOR_STMT.  
+   Returns a CILK_FOR_STMT that is type checked.  */
+
+tree
+finish_cilk_for_stmt (tree cilk_for_stmt)
+{
+  CILK_FOR_BODY (cilk_for_stmt) = do_poplevel (CILK_FOR_BODY (cilk_for_stmt));
+  tree *scope_ptr = &CILK_FOR_SCOPE (cilk_for_stmt);
+  tree scope = *scope_ptr;
+  *scope_ptr = NULL;
+  add_stmt (do_poplevel (scope));
+  cp_finish_cilk_for_loop (&cilk_for_stmt, processing_template_decl);
+  add_stmt (cilk_for_stmt);
+  return cilk_for_stmt;
+}
+
 #include "gt-cp-semantics.h"
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-start-at-5.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-start-at-5.cc
new file mode 100644
index 0000000..dec650c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-start-at-5.cc
@@ -0,0 +1,42 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+
+
+int j[10];
+
+int main(void)
+{
+  int error = 0;
+  int j_serial[10];
+  for (int ii = 0; ii < 10; ii++)
+    {
+      j[ii] = 10;
+      j_serial[ii] = 10;
+    }
+  _Cilk_for (int ii = 5; ii < 10; ii++)
+    {
+      j[ii]=ii;
+    }
+
+  for (int ii = 5; ii < 10; ii++)
+    {
+      j_serial[ii] = ii;
+    }
+
+  for (int ii = 0; ii < 10; ii++)
+    {
+      if (j[ii] != j_serial[ii]) 
+	error = 1;    
+    }
+
+  if (error)
+    __builtin_abort ();
+  else
+    return 0;
+
+  return j[9];
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-tplt.cc
new file mode 100644
index 0000000..8221371
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-tplt.cc
@@ -0,0 +1,25 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#define SIZE 100
+#define CHECK_VALUE 5
+
+template <class T>
+int func (T start, T end)
+{
+  int Array[SIZE];
+  _Cilk_for (T ii = 0; ii < end; ii++)
+    Array[ii] = CHECK_VALUE;
+  
+  for (T ii = 0; ii < end; ii++)
+    if (Array[ii] != CHECK_VALUE)
+      __builtin_abort ();
+
+  return 0;
+}
+
+int main (void)
+{
+  return func <int> (0, 100) + func <long> (0, 100);
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for.cc
new file mode 100644
index 0000000..30ea29d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for.cc
@@ -0,0 +1,34 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+int main(int argc, char **argv)
+{
+  char Array1[26], Array2[26];
+  char Array1_Serial[26], Array2_Serial[26];
+
+  for (int ii = 0; ii < 26; ii++)  
+    { 
+      Array1[ii] = 'A'+ii;
+      Array1_Serial[ii] = 'A'+ii;
+    }
+  for (int ii = 0; ii < 26; ii++)
+    {
+      Array2[ii] = 'a'+ii;
+      Array2_Serial[ii] = 'a'+ii;
+    }
+
+  _Cilk_for (int ii = 0 ; ii < 26; ii++) 
+    Array1[ii] = Array2[ii];
+
+  for (int ii = 0; ii < 26; ii++)
+    Array1_Serial[ii] = Array2_Serial[ii];
+
+  for (int ii = 0; ii < 26; ii++)  {
+    if (Array1_Serial[ii] != Array1[ii])  { 
+	__builtin_abort ();
+    }
+  }
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_inside_for.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_inside_for.cc
new file mode 100644
index 0000000..3759a36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_inside_for.cc
@@ -0,0 +1,22 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+int q[10], seq[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      _Cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  for (int jj = 0; jj < 10; jj++)  
+	    {
+	      if (seq[jj] == 5)
+		continue;
+	      else
+		seq[jj] = 2;
+	    }
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_for.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_for.cc
new file mode 100644
index 0000000..38c4d51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_for.cc
@@ -0,0 +1,19 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+int q[10], seq2[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      _Cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  for (int jj = 0; jj < 10; jj++) 
+	    seq2[jj] = 5;
+	  continue;
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_if.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_if.cc
new file mode 100644
index 0000000..e68c700
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_if.cc
@@ -0,0 +1,18 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+int q[10], seq2[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      _Cilk_for(int ii = max - 1; ii >= start; ii--) 
+	{ 
+	  if (q[ii] != 0) 
+	    continue;
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_while.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_while.cc
new file mode 100644
index 0000000..17fd064
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_cont_with_while.cc
@@ -0,0 +1,23 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+int q[10], seq2[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      _Cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  int jj = 0;
+	  while (jj < 10)
+	    {
+	      seq2[jj] = 1;
+	      jj++;
+	    }
+	  continue;
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_genricize_test.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_genricize_test.cc
new file mode 100644
index 0000000..f0ad2a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_genricize_test.cc
@@ -0,0 +1,42 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <vector>
+#include <list>
+#if HAVE_IO 
+#include <stdio.h>
+#endif
+#define NUMBER 500
+#include <stdlib.h>
+typedef std::pair<int, int> my_type_t;
+
+long
+valid_pairs(std::vector< my_type_t > my_list) 
+{
+  _Cilk_for (int ii = 0; ii < my_list.size(); ii++) 
+    {
+#if HAVE_IO
+    fprintf(stderr, "my_list index: %d, size: %zu.\n", ii, my_list.size());
+#endif
+      if (ii < 0 || ii >= my_list.size())
+	__builtin_abort (); 
+    }
+  return 0;
+}
+
+int main(int argc, char **argv) 
+{
+  std::vector<my_type_t> my_list;
+
+  for (int ii = 0; ii < NUMBER; ii++) 
+    my_list.push_back(my_type_t(ii, ii));
+  long res = valid_pairs(my_list);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_grainsize.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_grainsize.cc
new file mode 100644
index 0000000..7d54828
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_grainsize.cc
@@ -0,0 +1,77 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+int x = 5;
+int q = 25;
+int z = 2;
+
+int square (int b)
+{
+  return (b*b);
+}
+
+template<class T>
+int templated_func (T a, T b, T c)
+{
+  T Array[10];
+#pragma cilk grainsize = a
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = a;
+
+  for (int ii = 0; ii < 10; ii++)
+    if (Array[ii] != a)
+      __builtin_abort ();
+
+#pragma cilk grainsize = square ((int) (b/c))
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = b;
+
+  for (int ii = 0; ii < 10; ii++)
+    if (Array[ii] != b)
+      __builtin_abort ();
+
+#pragma cilk grainsize = 2
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = c;
+
+  for (int ii = 0; ii < 10; ii++)
+    if (Array[ii] != c)
+      __builtin_abort ();
+
+  return 0;
+}
+
+ 
+
+int main (void)
+{
+  int Array[10];
+#pragma cilk grainsize = 5
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = 5;
+
+  for (int ii = 0; ii < 10; ii++)
+    if (Array[ii] != 5)
+      __builtin_abort ();
+
+
+#pragma cilk grainsize = x
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = 10;
+
+  for (int ii = 0; ii < 10; ii++)
+    if (Array[ii] != 10)
+      __builtin_abort ();
+
+#pragma cilk grainsize = square (z)
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = 15;
+
+  for (int ii = 0; ii < 10; ii++)
+    if (Array[ii] != 15)
+      __builtin_abort ();
+
+  int r = 5, s=10, t =15;
+  return templated_func (r, s, t);
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_p_errors.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_p_errors.cc
new file mode 100644
index 0000000..4c69712
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_p_errors.cc
@@ -0,0 +1,52 @@
+/* { dg-options "-fcilkplus -Wunknown-pragmas" } */
+
+int main (void)
+{
+  int a, iii = 0;
+  _Cilk_for (; iii < 10; iii++) /* { dg-error "expected induction variable" } */
+    a = 5;
+
+  _Cilk_for (iii = 0; iii < 10; iii++) /* { dg-error " must declare variable" } */
+    a = 5;
+
+  _Cilk_for (int qq = 0, jj = 0; qq < 10; qq++) /* { dg-error " initializer cannot have multiple variable declarations" } */
+    a = 5;
+
+  _Cilk_for (int ii = 0, int jj = 0; ii < 10; ii++) /* { dg-error " initializer cannot have multiple variable declarations" } */
+    a = 5;
+
+  _Cilk_for (int rr = 0; ; rr++) /* { dg-error "missing condition" } */
+    a = 5;
+
+  _Cilk_for (int ii = 0; ii = 5; ii++) /* { dg-error "invalid controlling predicate" } */
+    a = 5;
+
+  _Cilk_for (int ii = 0; ii == 5; ii++) /* { dg-error "invalid controlling predicate" } */
+    a = 5;
+
+  _Cilk_for (int ii = 0; ii < 10;) /* { dg-error "missing increment" } */
+    a = 5;
+
+  _Cilk_for (int ii = 0; ii < 10; ii ) /* { dg-error "invalid increment expression" } */
+    a = 5;
+
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    {
+      a = 5;
+      if (ii == 5)
+	break; /* { dg-error "break statement used in _Cilk_for loop body" } */
+    }
+
+#pragma cilk grainsize 5 /* { dg-error "expected '=' before numeric constant" } */
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    a = 5;
+
+#pragma Silk grainsize = 5 /* { dg-warning "ignoring #pragma Silk grainsize" } */
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    a = 5;
+#pragma cilk grainsiz = 5 /* { dg-warning "ignoring #pragma cilk grainsiz" } */
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    a = 5;
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_t_errors.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_t_errors.cc
new file mode 100644
index 0000000..3d1914a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk_for_t_errors.cc
@@ -0,0 +1,30 @@
+/* { dg-options "-fcilkplus" } */
+
+#include <setjmp.h>
+int main (void)
+{
+  int a, iii = 0;
+
+  _Cilk_for (volatile int ii = 0; ii < 10; ii++) /* { dg-error "induction variable cannot be volatile" } */
+    a = 5;
+
+  _Cilk_for (static int ii = 0; ii < 10; ii++) /* { dg-error "storage class is not allowed" } */
+    a = 5;
+  _Cilk_for (register int ii = 0; ii < 10; ii++) /* { dg-error "storage class is not allowed" } */
+    a = 5;
+
+  _Cilk_for (extern int ii = 0; ii < 10; ii++) /* { dg-error "storage class is not allowed" } */
+    a = 5;
+
+  _Cilk_for (float ii = 0.0; ii < 10.0; ii += 0.5) /* { dg-error "induction variable must be of integral record or pointer type" } */
+    a = 5;
+
+  jmp_buf env;
+  _Cilk_for (int ii = 0; ii < 10; ii++) 
+    {
+      a = 5;
+      setjmp (env); /* { dg-error "calls to setjmp are not allowed within" } */
+    }
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/explicit_ctor.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/explicit_ctor.cc
new file mode 100644
index 0000000..89f6403
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/explicit_ctor.cc
@@ -0,0 +1,27 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+
+struct BruceBoxleitner {
+    int m;
+    BruceBoxleitner (int n = 0) : m(n) { }
+    BruceBoxleitner operator--() { --m; return *this; }
+};
+
+int operator- (BruceBoxleitner a, BruceBoxleitner b) { return a.m - b.m; }
+
+struct BruceLee {
+    int m;
+    explicit BruceLee (int n) : m(n) { }
+};
+
+bool operator> (BruceBoxleitner a, BruceLee b) { return a.m > b.m; }
+int operator- (BruceBoxleitner a, BruceLee b) { return a.m - b.m; }
+
+int main () {
+    _Cilk_for (BruceBoxleitner i = 10; i > BruceLee(0); --i)
+      ;
+    return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/label_test.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/label_test.cc
new file mode 100644
index 0000000..495e9b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/label_test.cc
@@ -0,0 +1,26 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+int main(void)
+{
+  int jj = 0;
+  int total = 0;
+
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    {
+      if ((ii % 2) == 0)
+	goto hello_label;
+      else
+	goto world_label;
+
+hello_label:
+     total++;
+world_label:
+     total++;
+    }
+  if (total != 15)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/no-opp-overload-error.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/no-opp-overload-error.cc
new file mode 100644
index 0000000..582ef60
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/no-opp-overload-error.cc
@@ -0,0 +1,88 @@
+/* { dg-options "-fcilkplus" } */
+
+
+#define NUMBER_OF_ELEMENTS 10
+
+#include <cstdlib>
+
+class my_class {
+private:
+  int value;
+public:
+
+  my_class ();
+  my_class (const my_class &val);
+  my_class (my_class &val);
+  my_class (int val);
+  ~my_class ();
+  int getValue();
+  my_class &operator= (my_class &new_value);
+  my_class &operator= (int x);
+  my_class &operator+= (int val)
+  {
+    value += val;
+    return *this;
+  }
+  bool operator< (const my_class &val)
+  {
+    return (value < val.value);
+  }
+};
+
+
+my_class::my_class ()
+{
+  value = 0;
+}
+
+my_class::my_class(int val)
+{
+  value = val;
+}
+
+my_class::my_class (my_class &val)
+{
+  value = val.value;
+}
+
+my_class::my_class (const my_class &val)
+{
+  value = val.value;
+}
+
+my_class::~my_class ()
+{
+  value = -1;
+}
+
+int my_class::getValue ()
+{
+  return value;
+}
+
+my_class & my_class::operator= (my_class &new_value)
+{
+  value = new_value.value;
+  return *this;
+}
+
+my_class &my_class::operator= (int x)
+{
+  value = x;
+  return *this;
+}
+
+int main (void)
+{
+  int n, *array_parallel;
+  my_class length (NUMBER_OF_ELEMENTS);
+    n = NUMBER_OF_ELEMENTS;
+  
+  array_parallel = new int[NUMBER_OF_ELEMENTS];
+  _Cilk_for (my_class ii (0); ii < length; ii += 1) { /* { dg-error " No operator-" } */
+      int x = ii.getValue();
+    array_parallel [x] = x * 2;
+  }
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/plus-equal-one.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/plus-equal-one.cc
new file mode 100644
index 0000000..1326308
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/plus-equal-one.cc
@@ -0,0 +1,59 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+#if HAVE_IO
+#include <cstdio>
+#endif
+#define TEST 1
+
+
+#define ITER 300
+
+int n_errors;
+#if TEST
+void test (int *array, int n, int val) {
+#if HAVE_IO
+    for (int i = 0; i < n; i++)
+      std::printf("array[%3d] = %2d\n", i, array[i]);
+#endif
+    for (int i = 0; i < n; ++i) {
+        if (array[i] != val) {
+           __builtin_abort (); 
+        }
+    }
+}
+#endif
+ 
+
+int main () {
+    int array[ITER];
+  
+    for (int ii = 0; ii < ITER; ii++)
+      array[ii] = 9;
+    _Cilk_for (int *j = (array); j < array + ITER; j += 1)  {
+       *j = 6; 
+    }
+#if TEST
+    test(array, ITER, 6);
+#endif
+
+    _Cilk_for (int *i = array; i < array + ITER; i += 1) {
+        *i = 1;
+    }
+
+#if TEST
+    test(array, ITER, 1);
+#endif
+
+    _Cilk_for (int *k = array+ITER-1; k >= array; k -= 1) {
+        *k = 8;
+    }
+#if TEST
+    test(array, ITER, 8);
+#endif
+  
+    return 0;
+
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/plus-equal-test.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/plus-equal-test.cc
new file mode 100644
index 0000000..0ca588d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/plus-equal-test.cc
@@ -0,0 +1,111 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+#define NUMBER_OF_ELEMENTS 10
+
+#include <cstdlib>
+
+#if HAVE_IO
+#include <cstdio>
+#endif
+
+class my_class {
+private:
+  int value;
+public:
+
+  my_class ();
+  my_class (const my_class &val);
+  my_class (my_class &val);
+  my_class (int val);
+  ~my_class ();
+  int getValue();
+  my_class &operator= (my_class &new_value);
+  my_class &operator+= (int val)
+  {
+    value += val;
+    return *this;
+  }
+  bool operator< (const my_class &val)
+  {
+    return (value < val.value);
+  }
+};
+
+
+my_class::my_class ()
+{
+  value = 0;
+}
+
+my_class::my_class(int val)
+{
+  value = val;
+}
+
+my_class::my_class (my_class &val)
+{
+  value = val.value;
+}
+
+my_class::my_class (const my_class &val)
+{
+  value = val.value;
+}
+
+my_class::~my_class ()
+{
+  value = -1;
+}
+
+int my_class::getValue ()
+{
+  return value;
+}
+
+my_class & my_class::operator= (my_class &new_value)
+{
+  value = new_value.value;
+  return *this;
+}
+
+int operator- (my_class x, my_class y)
+{
+  int val_x = x.getValue ();
+  int val_y = y.getValue ();
+  return (val_x - val_y);
+}
+
+
+int main (void)
+{
+  int n, *array_parallel, *array_serial;
+  my_class length (NUMBER_OF_ELEMENTS);
+    n = NUMBER_OF_ELEMENTS;
+  
+  array_parallel = new int[NUMBER_OF_ELEMENTS];
+  array_serial = new int[NUMBER_OF_ELEMENTS];
+
+  _Cilk_for (my_class ii (0); ii < length; ii += 1) {
+#if HAVE_IO
+    std::printf("ii.getValue() = %d\n", ii.getValue ());
+#endif
+    array_parallel [ii.getValue ()] = ii.getValue() * 2;
+  }
+
+  for (my_class ii (0); ii < length; ii += 1)
+    array_serial [ii.getValue ()] = ii.getValue () * 2;
+  
+  for (int ii = 0; ii < NUMBER_OF_ELEMENTS; ii++)
+    if (array_serial[ii] != array_parallel[ii]) {
+#if HAVE_IO
+      std::printf("array_serial[%3d] = %6d\tarray_parallel[%3d] = %6d\n", ii,
+		  array_serial[ii], ii, array_parallel[ii]);
+#endif
+      __builtin_abort ();
+    }
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.cc
new file mode 100644
index 0000000..e4f2ee5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.cc
@@ -0,0 +1,58 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+
+
+#include <vector>
+#include <cstdio>
+#include <iostream>
+#include <algorithm>
+
+using namespace std;
+
+int main(void)
+{
+vector <int> array;
+vector <int> array_serial;
+
+#if 1
+for (int ii = -1; ii < 10; ii++)
+{   
+  array.push_back(ii);
+  array_serial.push_back (ii);
+}
+#endif
+#if 1
+_Cilk_for (vector<int>::iterator iter = array.begin(); iter != array.end(); 
+	   iter++)
+{
+   if (*iter  == 6) 
+     *iter = 13;
+}
+#endif
+for (vector<int>::iterator iter2 = array_serial.begin(); 
+     iter2 != array_serial.end(); iter2++)
+{
+   if (*iter2  == 6) 
+     *iter2 = 13;
+}
+sort (array.begin(), array.end());
+sort (array_serial.begin(), array_serial.end());
+
+vector <int>::iterator iter3 = array.begin ();
+vector <int>::iterator iter_serial = array_serial.begin ();
+
+while (iter3 != array.end () && iter_serial != array_serial.end ())
+{
+  if (*iter3 != *iter_serial)
+    __builtin_abort ();
+  iter3++;
+  iter_serial++;
+}
+
+return 0;
+}   
+
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/stl_test.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_test.cc
new file mode 100644
index 0000000..3e350a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_test.cc
@@ -0,0 +1,50 @@
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+#include <iostream>
+#include <cstdio>
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+#include <list>
+
+using namespace std;
+
+
+int main(int argc, char **argv)
+{
+  vector <int> number_list, number_list_serial;
+  int new_number = 0;
+  int no_elements = 0;
+  
+  if (argc != 2)
+  {
+    no_elements = 10000;
+  }
+
+
+  number_list.clear();
+  number_list_serial.clear();
+  for (int ii = 0; ii < no_elements; ii++)
+  {
+    number_list.push_back(new_number);
+    number_list_serial.push_back(new_number);
+  }
+
+  _Cilk_for (int jj = 0; jj < no_elements; jj++)
+  {
+    number_list[jj] = jj + no_elements;
+  }
+  for (int jj = 0; jj < no_elements; jj++)
+  {
+    number_list_serial[jj] = jj + no_elements;
+  }
+
+  for (int jj = 0; jj < no_elements; jj++)
+    if (number_list_serial[jj] != number_list[jj])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
index 27412e8..ff5ea33 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
@@ -64,12 +64,10 @@ dg-finish
 
 dg-init
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O0 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O1 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O2 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O3 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O0 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O1 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O3 -fcilkplus" " "
@@ -77,7 +75,6 @@ dg-finish
 
 dg-init
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O0 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus" " "

Comments

Aldy Hernandez Nov. 15, 2013, 9:50 p.m. UTC | #1
On 11/15/13 12:23, Iyer, Balaji V wrote:

> This patch is dependent on the following patches:
>
> #pragma simd work (they both share the same parser routines)

I have just committed this to trunk, so it shouldn't be a blocker.

Also, in the past 2 days the #pragma simd parsing has been merged with 
the OpenMP parsing routines, so please adjust your patch accordingly.

Thanks.
Aldy
Aldy Hernandez Nov. 20, 2013, 1:54 a.m. UTC | #2
> One small thing that I have not done that Jakub and several other
> have asked me before is that, there are no tests in c-c++-common for
> _Cilk_for. The reason being that the syntax between C and C++
> implementations are different. In C++, the induction variable must be
> defined in the initializer (e.g. it should start wth _Cilk_for (int
> ii = 0....)). In C, this is not allowed (e.g. it should start as
> _Cilk_for (ii = 0; ii < 10; ii++)).

For pragma simd what I did was put the tests in c-c++-common and pass 
"-std=c99" to the C tests.  That should allow declaration at initialization.

Can you do this?

Aldy
Jason Merrill Nov. 27, 2013, 5:48 p.m. UTC | #3
On 11/15/2013 02:23 PM, Iyer, Balaji V wrote:
> One small thing that I have not done that Jakub and several other have asked me before is that, there are no tests in c-c++-common for _Cilk_for. The reason being that the syntax between C and C++ implementations are different. In C++, the induction variable must be defined in the initializer (e.g. it should start wth _Cilk_for (int ii = 0....)). In C, this is not allowed (e.g. it should start as _Cilk_for (ii = 0; ii < 10; ii++)).

That can be handled with #ifdef __cplusplus.

Jason
Jakub Jelinek Nov. 27, 2013, 5:54 p.m. UTC | #4
On Wed, Nov 27, 2013 at 12:48:11PM -0500, Jason Merrill wrote:
> On 11/15/2013 02:23 PM, Iyer, Balaji V wrote:
> >One small thing that I have not done that Jakub and several other have asked me before is that, there are no tests in c-c++-common for _Cilk_for. The reason being that the syntax between C and C++ implementations are different. In C++, the induction variable must be defined in the initializer (e.g. it should start wth _Cilk_for (int ii = 0....)). In C, this is not allowed (e.g. it should start as _Cilk_for (ii = 0; ii < 10; ii++)).
> 
> That can be handled with #ifdef __cplusplus.

It isn't allowed even in C99?  For OpenMP,
int a[30];

void
foo ()
{
  #pragma omp for
  for (int i = 0; i < 30; i++)
    a[i] = i;
}
is valid for C99.  So, perhaps you just want
/* { dg-additional-options "-std=c99" { target c } } */
in the c-c++-common tests?

	Jakub
Aldy Hernandez Nov. 27, 2013, 5:58 p.m. UTC | #5
On 11/27/13 10:54, Jakub Jelinek wrote:
> On Wed, Nov 27, 2013 at 12:48:11PM -0500, Jason Merrill wrote:
>> On 11/15/2013 02:23 PM, Iyer, Balaji V wrote:
>>> One small thing that I have not done that Jakub and several other have asked me before is that, there are no tests in c-c++-common for _Cilk_for. The reason being that the syntax between C and C++ implementations are different. In C++, the induction variable must be defined in the initializer (e.g. it should start wth _Cilk_for (int ii = 0....)). In C, this is not allowed (e.g. it should start as _Cilk_for (ii = 0; ii < 10; ii++)).
>>
>> That can be handled with #ifdef __cplusplus.
>
> It isn't allowed even in C99?  For OpenMP,
> int a[30];
>
> void
> foo ()
> {
>    #pragma omp for
>    for (int i = 0; i < 30; i++)
>      a[i] = i;
> }
> is valid for C99.  So, perhaps you just want
> /* { dg-additional-options "-std=c99" { target c } } */
> in the c-c++-common tests?
>
> 	Jakub
>

Yup, that's what I did for the Cilk Plus pragma simd tests.
diff mbox

Patch

diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
index cfaa10e..2c4233b 100644
--- a/gcc/c-family/c-cilkplus.c
+++ b/gcc/c-family/c-cilkplus.c
@@ -41,6 +41,7 @@  along with GCC; see the file COPYING3.  If not see
 static tree
 c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
 {
+  tree orig_incr = incr;
   if (!incr)
     {
       error_at (loc, "missing increment");
@@ -50,6 +51,16 @@  c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
   if (EXPR_HAS_LOCATION (incr))
     loc = EXPR_LOCATION (incr);
 
+  /* We hit this if-statement if we have an overloaded operand like
+     this: *my_class::operator+= (&ii, 1).  For example, see the testscase
+     plus-equal-test.cc.  */
+  if (TREE_CODE (incr) == INDIRECT_REF
+      || TREE_CODE (incr) == CLEANUP_POINT_EXPR)
+    incr = TREE_OPERAND (incr, 0);
+
+  if (TREE_CODE (incr) == TARGET_EXPR)
+    incr = TARGET_EXPR_INITIAL (incr);
+
   switch (TREE_CODE (incr))
     {
     case POSTINCREMENT_EXPR:
@@ -69,10 +80,12 @@  c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
 	  break;
 
 	rhs = TREE_OPERAND (incr, 1);
-	if (TREE_CODE (rhs) == PLUS_EXPR
+	if ((TREE_CODE (rhs) == PLUS_EXPR
+	     || TREE_CODE (rhs) == POINTER_PLUS_EXPR)
 	    && (TREE_OPERAND (rhs, 0) == decl
 		|| TREE_OPERAND (rhs, 1) == decl)
-	    && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
+	    && (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
+		|| POINTER_TYPE_P (TREE_TYPE (rhs))))
 	  return incr;
 	else if (TREE_CODE (rhs) == MINUS_EXPR
 		 && TREE_OPERAND (rhs, 0) == decl
@@ -83,6 +96,49 @@  c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
 	break;
       }
 
+      /* We encounter CALL_EXPR in C++ when we have a case like this:
+	 operator+= (&ii, 1);  */
+    case CALL_EXPR:
+      {
+	enum tree_code code = cilk_find_code_from_call (CALL_EXPR_FN (incr));
+	if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
+	    || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+	  {
+	    tree val = CALL_EXPR_ARG (incr, 0);
+	    if (TREE_CODE (val) == ADDR_EXPR
+		|| TREE_CODE (val) == INDIRECT_REF)
+	      val = TREE_OPERAND (val, 0);
+	    if (val != decl)
+	      break;
+	    return c_omp_for_incr_canonicalize_ptr (loc, decl, incr);
+	  }
+	for (int ii = 0; ii < call_expr_nargs (incr); ii++)
+	  {
+	    tree val = CALL_EXPR_ARG (incr, ii);
+	    if (TREE_CODE (val) == ADDR_EXPR)
+	      val = TREE_OPERAND (val, 0);
+	    if (val == decl)
+	      continue;
+	    else
+	      {
+		tree rhs = val;
+		if (TREE_CODE (rhs) == INTEGER_CST)
+		  return orig_incr;
+		if ((TREE_CODE (rhs) == PLUS_EXPR
+		     || TREE_CODE (rhs) == POINTER_PLUS_EXPR)
+		    && (TREE_OPERAND (rhs, 0) == decl
+			|| TREE_OPERAND (rhs, 1) == decl)
+		    && (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
+			|| POINTER_TYPE_P (TREE_TYPE (rhs))))
+		  return orig_incr;
+		else if (TREE_CODE (rhs) == MINUS_EXPR
+			 && TREE_OPERAND (rhs, 0) == decl
+			 && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
+		  return orig_incr;
+	      }
+	  }
+      }
+
     default:
       break;
     }
@@ -121,7 +177,7 @@  c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
 	      {
 		error_at (EXPR_LOCATION (*tp),
 			  "calls to setjmp are not allowed within loops "
-			  "annotated with #pragma simd");
+			  "annotated with #pragma simd or _Cilk_for loops");
 		*valid = false;
 		*walk_subtrees = 0;
 	      }
@@ -185,7 +241,8 @@  c_check_cilk_loop_body (tree body)
 
 static bool
 c_check_cilk_loop (location_t loc, tree decl, tree cond, tree *incrp,
-		   tree body, bool scan_body)
+		   tree body, bool scan_body, bool is_cpp,
+		   bool proc_templates_p)
 {
   tree incr = *incrp;
 
@@ -220,9 +277,22 @@  c_check_cilk_loop (location_t loc, tree decl, tree cond, tree *incrp,
   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;
+      /* In C++ iterators are allowed.  */
+      if (!is_cpp)
+	{
+	  error_at (loc, "induction variable must be of integral "
+		    "or pointer type (have %qT)", TREE_TYPE (decl));
+	  return false;
+	}
+      /* If we are processing templates then these checks are done
+	 in pt.c.  */
+      else if (!proc_templates_p
+	       && TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE)
+	{
+	  error_at (loc, "induction variable must be of integral "
+		    "record or pointer type (have %qT)", TREE_TYPE (decl)); 
+	  return false;
+	}
     }
 
   /* Validate the condition.  */
@@ -233,6 +303,7 @@  c_check_cilk_loop (location_t loc, tree decl, tree cond, tree *incrp,
     }
   bool cond_ok = false;
   if (TREE_CODE (cond) == NE_EXPR
+      || TREE_CODE (cond) == CALL_EXPR
       || TREE_CODE (cond) == LT_EXPR
       || TREE_CODE (cond) == LE_EXPR
       || TREE_CODE (cond) == GT_EXPR
@@ -242,9 +313,9 @@  c_check_cilk_loop (location_t loc, tree decl, tree cond, tree *incrp,
 	   DECL <comparison_operator> EXPR
 	   EXPR <comparison_operator> DECL
       */
-      if (decl == TREE_OPERAND (cond, 0))
+      if (decl == cilk_simplify_tree (TREE_OPERAND (cond, 0)))
 	cond_ok = true;
-      else if (decl == TREE_OPERAND (cond, 1))
+      else if (decl == cilk_simplify_tree (TREE_OPERAND (cond, 1)))
 	{
 	  /* Canonicalize the comparison so the DECL is on the LHS.  */
 	  TREE_SET_CODE (cond,
@@ -254,6 +325,29 @@  c_check_cilk_loop (location_t loc, tree decl, tree cond, tree *incrp,
 	  cond_ok = true;
 	}
     }
+
+  /* In C++ you can have cases like this: x < 5
+     where '<' is overloaded and so it is translated like this:
+     operator< (x, 5), and this is acceptable.  */
+  cond = cilk_simplify_tree (cond);
+  if (!cond_ok && is_cpp && TREE_CODE (cond) == CALL_EXPR)
+    {
+      if (call_expr_nargs (cond) < 2)
+	cond_ok = false;
+      for (int ii = 0; ii < call_expr_nargs (cond); ii++)
+	{
+	  tree val = cilk_simplify_tree (CALL_EXPR_ARG (cond, ii));
+	  if (TREE_CODE (val) == ADDR_EXPR)
+	    val = TREE_OPERAND (val, 0);
+	  else if (TREE_CODE (val) == TARGET_EXPR)
+	    val = TARGET_EXPR_INITIAL (val);
+	  if (decl == val)
+	    {
+	      cond_ok = true;
+	      break;
+	    }
+	}
+    }	
   if (!cond_ok)
     {
       error_at (loc, "invalid controlling predicate");
@@ -305,7 +399,8 @@  c_finish_cilk_simd_loop (location_t loc,
 {
   location_t rhs_loc;
 
-  if (!c_check_cilk_loop (loc, decl, cond, &incr, body, scan_body))
+  if (!c_check_cilk_loop (loc, decl, cond, &incr, body, scan_body, false,
+			  false))
     return NULL;
 
   /* In the case of "for (int i = 0...)", init will be a decl.  It should
@@ -352,6 +447,76 @@  c_finish_cilk_simd_loop (location_t loc,
   return add_stmt (t);
 }
 
+/* Validate and emit code for the _Cilk_for loop
+
+   LOC is the location of the location of the _Cilk_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.
+   SCAN_BODY is true if the body of the loop must be verified.
+
+   Returns the generated statement.  */
+
+tree
+c_finish_cilk_for_loop (location_t loc, tree decl, tree init, tree cond,
+			tree incr, tree body, tree grain, bool is_cpp,
+			bool proc_templates_p)
+{
+  if (!c_check_cilk_loop (loc, decl, cond, &incr, body, true,
+			  is_cpp, proc_templates_p))
+    return NULL;
+
+  /* In the case for "_Cilk_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)
+    {
+      location_t rhs_loc = DECL_SOURCE_LOCATION (decl);
+      init = DECL_INITIAL (decl);
+      if (!init)
+	{
+	  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;
+    }
+
+  tree t = make_node (CILK_FOR_STMT);
+  TREE_TYPE (t) = void_type_node;
+
+  init = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
+  CILK_FOR_INIT (t) = init;
+  CILK_FOR_COND (t) = cond;
+  CILK_FOR_EXPR (t) = incr;
+  CILK_FOR_BODY (t) = body;
+  CILK_FOR_SCOPE (t) = NULL_TREE;
+  CILK_FOR_VAR (t) = decl;
+  CILK_FOR_GRAIN (t) = grain;
+
+  SET_EXPR_LOCATION (t, loc);
+  return add_stmt (t);
+}  
+
+/* Similar to c_finish_cilk_for_loop, but don't actually create the
+   CILK_FOR_STMT tree ad return it.  *CILK_FOR_STMT is the CILK_FOR_STMT 
+   tree and proc_templates_p is set if we are processing templates.  */
+
+void
+cp_finish_cilk_for_loop (tree *cilk_for_stmt, bool proc_templates_p)
+{
+  tree cfor = *cilk_for_stmt;
+  tree incr = CILK_FOR_EXPR (cfor);
+  if (!c_check_cilk_loop (EXPR_LOCATION (cfor),	CILK_FOR_VAR (cfor),
+			  CILK_FOR_COND (cfor), &incr, CILK_FOR_BODY (cfor), 
+			  true, true, proc_templates_p))
+    *cilk_for_stmt = error_mark_node;
+  else
+    CILK_FOR_EXPR (*cilk_for_stmt) = incr;
+}
+
 /* Validate and emit code for <#pragma simd> clauses.  */
 
 tree
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 1f5e4ed..4d90633 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -415,6 +415,7 @@  const struct c_common_resword c_common_reswords[] =
   { "_Complex",		RID_COMPLEX,	0 },
   { "_Cilk_spawn",      RID_CILK_SPAWN, 0 },
   { "_Cilk_sync",       RID_CILK_SYNC,  0 },
+  { "_Cilk_for",        RID_CILK_FOR,   0 },
   { "_Imaginary",	RID_IMAGINARY, D_CONLY },
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 2599c97..bb4ab79
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -149,7 +149,7 @@  enum rid
   RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
 
   /* Cilk Plus keywords.  */
-  RID_CILK_SPAWN, RID_CILK_SYNC,
+  RID_CILK_SPAWN, RID_CILK_SYNC, RID_CILK_FOR,
   
   /* Objective-C ("AT" reserved words - they are only keywords when
      they follow '@')  */
@@ -527,7 +527,10 @@  struct GTY(()) c_language_function {
 /* In c-cilkplus.c */
 extern tree c_finish_cilk_simd_loop (location_t, tree, tree, tree, tree,
 				     tree, tree, tree, bool);
+extern void cp_finish_cilk_for_loop (tree *, bool);
 extern tree c_finish_cilk_clauses (tree);
+extern tree c_finish_cilk_for_loop (location_t, tree, tree, tree, tree, tree,
+				    tree, bool, bool);
 
 /* Language-specific hooks.  */
 
@@ -1296,8 +1299,6 @@  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 *);
 
@@ -1384,5 +1385,31 @@  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_init_cfd (struct cilk_for_desc *);
+extern void cilk_extract_free_variables (tree, struct wrapper_data *, int);
+extern tree cilk_create_cilk_helper_decl (struct wrapper_data *);
+extern void cilk_call_graph_add_fn (tree);
+extern void cilk_outline_body (tree, tree *, struct wrapper_data *, bool *);
+extern tree cilk_check_loop_difference_type (tree);
+extern void declare_cilk_for_parms (struct cilk_for_desc *);
+extern void declare_cilk_for_vars (struct cilk_for_desc *, tree);
+extern tree cilk_loop_convert (tree, tree);
+extern tree cilk_divide_count (tree, enum tree_code, tree, bool, tree);
+extern void cilk_calc_forward_div_op (struct cilk_for_desc *, enum tree_code *,
+				      tree *);
+extern tree cilk_compute_loop_count (struct cilk_for_desc *, enum tree_code,
+				     tree, tree, tree);
+extern gimple_seq insert_cilk_for_nested_fn (struct cilk_for_desc *, tree,
+					     tree);
+extern tree cilk_compute_loop_var (struct cilk_for_desc *, tree, tree,
+				   tree (*)(location_t, enum tree_code, tree,
+					    tree, tree));
+extern void cilk_set_inclusive_and_direction (struct cilk_for_desc *);
+extern void cilk_set_iter_difftype (struct cilk_for_desc *);
+extern void cilk_set_incr_info (struct cilk_for_desc *, bool);
+extern void cilk_set_init_info (struct cilk_for_desc *);
+extern tree cilk_simplify_tree (tree);
+extern enum tree_code cilk_find_code_from_call (tree);
+extern tree cilk_tree_operand_noconv (tree);
+extern tree cilk_resolve_continue_stmts (tree *, int *, void *);
 #endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 179c620..351977e 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1392,6 +1392,11 @@  init_pragma (void)
 
   cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
 				false);
+
+  if (flag_enable_cilkplus && !flag_preprocess_only)
+    cpp_register_deferred_pragma (parse_in, "cilk", "grainsize",
+				  PRAGMA_CILK_GRAINSIZE, true, false);
+
 #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
   c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
 #else
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 5379b9e..ca8b190 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -55,6 +55,9 @@  typedef enum pragma_kind {
   /* Top level clause to handle all Cilk Plus pragma simd clauses.  */
   PRAGMA_CILK_SIMD,
 
+  /* This pragma handles setting of grainsize for a _Cilk_for.  */
+  PRAGMA_CILK_GRAINSIZE,
+  
   PRAGMA_GCC_PCH_PREPROCESS,
   PRAGMA_IVDEP,
 
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
index f6d7dce..38362f9
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -34,47 +34,6 @@  along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "cilk.h"
 
-enum add_variable_type {
-    /* Reference to previously-defined variable.  */
-    ADD_READ,
-    /* Definition of a new variable in inner-scope.  */
-    ADD_BIND,
-    /* Write to possibly previously-defined variable.  */
-    ADD_WRITE
-};
-
-enum cilk_block_type {
-    /* Indicates a _Cilk_spawn block.  30 was an arbitary number picked for 
-       ease of debugging.  */
-    CILK_BLOCK_SPAWN = 30,
-    /* Indicates _Cilk_for statement block.  */
-    CILK_BLOCK_FOR
-};
-
-struct wrapper_data
-{
-  /* Kind of function to be created.  */
-  enum cilk_block_type type;
-  /* Signature of helper function.  */
-  tree fntype;
-  /* Containing function.  */
-  tree context;
-  /* Disposition of all variables in the inner statement.  */
-  struct pointer_map_t *decl_map;
-  /* True if this function needs a static chain.  */
-  bool nested;
-  /* Arguments to be passed to wrapper function, currently a list.  */
-  tree arglist;
-  /* Argument types, a list.  */
-  tree argtypes;
-  /* Incoming parameters.  */
-  tree parms;
-  /* Outer BLOCK object.  */
-  tree block;
-};
-
-static void extract_free_variables (tree, struct wrapper_data *,
-				    enum add_variable_type);
 static HOST_WIDE_INT cilk_wrapper_count;
 
 /* Marks the CALL_EXPR or FUNCTION_DECL, FCALL, as a spawned function call
@@ -155,8 +114,8 @@  pop_cfun_to (tree outer)
 /* This function does whatever is necessary to make the compiler emit a newly 
    generated function, FNDECL.  */
 
-static void
-call_graph_add_fn (tree fndecl)
+void
+cilk_call_graph_add_fn (tree fndecl)
 {
   const tree outer = current_function_decl;
   struct function *f = DECL_STRUCT_FUNCTION (fndecl);
@@ -282,8 +241,8 @@  cilk_detect_spawn_and_unwrap (tree *exp0)
 /* This function will build and return a FUNCTION_DECL using information 
    from *WD.  */
 
-static tree
-create_cilk_helper_decl (struct wrapper_data *wd)
+tree
+cilk_create_cilk_helper_decl (struct wrapper_data *wd)
 {
   char name[20];
   if (wd->type == CILK_BLOCK_FOR)
@@ -451,6 +410,8 @@  for_local_cb (const void *k_v, void **vp, void *p)
   tree k = *(tree *) &k_v;
   tree v = (tree) *vp;
 
+  if (k == v)
+    return true;
   if (v == error_mark_node)
     *vp = copy_decl_no_change (k, (copy_body_data *) p);
   return true;
@@ -471,15 +432,18 @@  wrapper_local_cb (const void *k_v, void **vp, void *data)
   return true;
 }
 
-/* Alter a tree STMT from OUTER_FN to form the body of INNER_FN.  */
+/* Alter a tree STMT from OUTER_FN to form the body of INNER_FN.  THR is set
+   to true if the original function has exception enabled (only applicable for
+   C++ Cilk_for nested function).  This value is evaluated and then
+   passed back into cp_function_tree->can_throw.  */
 
-static void
-cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
+void
+cilk_outline_body (tree inner_fn, tree *stmt_p, struct wrapper_data *wd,
+		   bool *thr)
 {
   const tree outer_fn = wd->context;	      
   const bool nested = (wd->type == CILK_BLOCK_FOR);
   copy_body_data id;
-  bool throws;
 
   DECL_STATIC_CHAIN (outer_fn) = 1;
 
@@ -495,7 +459,7 @@  cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
   id.retvar = 0; 
   id.decl_map = wd->decl_map;
   id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk;
-  id.block = DECL_INITIAL (inner_fn);
+  id.block = 0; 
   id.transform_lang_insert_block = NULL;
 
   id.transform_new_cfg = true;
@@ -514,8 +478,10 @@  cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
   /* See if this function can throw or calls something that should
      not be spawned.  The exception part is only necessary if
      flag_exceptions && !flag_non_call_exceptions.  */
-  throws = false ;
+  bool throws = thr ? *thr : false;
   (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws);
+  if (thr)
+    *thr = throws;
 }
 
 /* Generate the body of a wrapper function that assigns the
@@ -537,7 +503,7 @@  create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
   /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS 
      (modified) to the wrapped function.  Return the wrapper and modified ARGS 
      to the caller to generate a function call.  */
-  fndecl = create_cilk_helper_decl (wd);
+  fndecl = cilk_create_cilk_helper_decl (wd);
   push_struct_function (fndecl);
   if (wd->nested && (wd->type == CILK_BLOCK_FOR))
     {
@@ -550,7 +516,7 @@  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);
+  cilk_outline_body (fndecl, &stmt, wd, NULL);
   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);
@@ -559,7 +525,7 @@  create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
   pop_cfun_to (outer);
 
   /* Recognize the new function.  */
-  call_graph_add_fn (fndecl);
+  cilk_call_graph_add_fn (fndecl);
   return fndecl;
 }
 
@@ -701,14 +667,14 @@  create_cilk_wrapper (tree exp, tree *args_out)
      by spawn and the variable must remain in the outer function.  */
   if (TREE_CODE (exp) == INIT_EXPR)
     {
-      extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
-      extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
+      cilk_extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
+      cilk_extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
       /* TREE_TYPE should be void.  Be defensive.  */
       if (TREE_TYPE (exp) != void_type_node)
-	extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
+	cilk_extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
     }
   else
-    extract_free_variables (exp, &wd, ADD_READ);
+    cilk_extract_free_variables (exp, &wd, ADD_READ);
   pointer_map_traverse (wd.decl_map, declare_one_free_variable, &wd);
   wd.block = TREE_BLOCK (exp);
   if (!wd.block)
@@ -995,14 +961,14 @@  add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how)
 
 /* Find the variables referenced in an expression T.  This does not avoid 
    duplicates because a variable may be read in one context and written in 
-   another.  HOW describes the context in which the reference is seen.  If 
+   another.  HOW_T describes the context in which the reference is seen.  If 
    NESTED is true a nested function is being generated and variables in the 
    original context should not be remapped.  */
 
-static void
-extract_free_variables (tree t, struct wrapper_data *wd,
-			enum add_variable_type how)
+void
+cilk_extract_free_variables (tree t, struct wrapper_data *wd, int how_t)
 {  
+  enum add_variable_type how = (enum add_variable_type) how_t;
   if (t == NULL_TREE)
     return;
 
@@ -1010,7 +976,7 @@  extract_free_variables (tree t, struct wrapper_data *wd,
   bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
 
   if (is_expr)
-    extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+    cilk_extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
 
   switch (code)
     {
@@ -1030,7 +996,7 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 
     case SSA_NAME:
       /* Currently we don't see SSA_NAME.  */
-      extract_free_variables (SSA_NAME_VAR (t), wd, how);
+      cilk_extract_free_variables (SSA_NAME_VAR (t), wd, how);
       return;
 
     case LABEL_DECL:
@@ -1052,12 +1018,12 @@  extract_free_variables (tree t, struct wrapper_data *wd,
     case NON_LVALUE_EXPR:
     case CONVERT_EXPR:
     case NOP_EXPR:
-      extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
       return;
 
     case INIT_EXPR:
-      extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
-      extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
+      cilk_extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
       return;
 
     case MODIFY_EXPR:
@@ -1066,8 +1032,8 @@  extract_free_variables (tree t, struct wrapper_data *wd,
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
       /* These write their result.  */
-      extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
-      extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
+      cilk_extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
       return;
 
     case ADDR_EXPR:
@@ -1078,9 +1044,9 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 	 be addressable, and marking it modified will cause a spurious
 	 warning about writing the control variable.  */
       if (wd->type != CILK_BLOCK_SPAWN)
-	extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+	cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
       else 
-	extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
+	cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
       return;
 
     case ARRAY_REF:
@@ -1092,17 +1058,17 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 	 is being accessed here.  As for ADDR_EXPR, don't do this
 	 in a nested loop, unless the access is to a fixed index.  */
       if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1)))
-	extract_free_variables (TREE_OPERAND (t, 0), wd, how);
+	cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, how);
       else
-	extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
-      extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
-      extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
+	cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
       return;
 
     case TREE_LIST:
-      extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
-      extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
-      extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
       return;
 
     case TREE_VEC:
@@ -1110,7 +1076,7 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 	int len = TREE_VEC_LENGTH (t);
 	int i;
 	for (i = 0; i < len; i++)
-	  extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
+	  cilk_extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
 	return;
       }
 
@@ -1118,13 +1084,13 @@  extract_free_variables (tree t, struct wrapper_data *wd,
       {
 	unsigned ii = 0;
 	for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++)
-	  extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ); 
+	  cilk_extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ); 
 	break;
       }
 
     case COMPLEX_CST:
-      extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
-      extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
       return;
 
     case BIND_EXPR:
@@ -1135,11 +1101,11 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 	    add_variable (wd, decl, ADD_BIND);
 	    /* A self-referential initialization is no problem because
 	       we already entered the variable into the map as local.  */
-	    extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
-	    extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
-	    extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
+	    cilk_extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
+	    cilk_extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
+	    cilk_extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
 	  }
-	extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
+	cilk_extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
 	return;
       }
 
@@ -1147,17 +1113,17 @@  extract_free_variables (tree t, struct wrapper_data *wd,
       {
 	tree_stmt_iterator i;
 	for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
-	  extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
+	  cilk_extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
 	return;
       }
 
     case TARGET_EXPR:
       {
-	extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
-	extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
-	extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
+	cilk_extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
+	cilk_extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+	cilk_extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
 	if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1))
-	  extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
+	  cilk_extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
 	return;
       }
 
@@ -1171,32 +1137,32 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 
     case DECL_EXPR:
       if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL)
-	extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
+	cilk_extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
       return;
 
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
-      extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
-      extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
       return;
 
     case POINTER_TYPE:
-      extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
       break;
 
     case ARRAY_TYPE:
-      extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
-      extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
+      cilk_extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
       return;
 
     case RECORD_TYPE:
-      extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
+      cilk_extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
       return;
     
     case METHOD_TYPE:
-      extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
-      extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
+      cilk_extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
+      cilk_extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
       return;
 
     case AGGR_INIT_EXPR:
@@ -1209,8 +1175,8 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 	    len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
 
 	    for (ii = 0; ii < len; ii++)
-	      extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
-	    extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+	      cilk_extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
+	    cilk_extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
 	  }
 	break;
       }
@@ -1226,7 +1192,7 @@  extract_free_variables (tree t, struct wrapper_data *wd,
 	  /* Go through the subtrees.  We need to do this in forward order so
 	     that the scope of a FOR_EXPR is handled properly.  */
 	  for (i = 0; i < len; ++i)
-	    extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
+	    cilk_extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
 	}
     }
 }
@@ -1303,3 +1269,872 @@  build_cilk_sync (void)
   TREE_SIDE_EFFECTS (sync) = 1;
   return sync;
 }
+
+/* Zeros out all the fields in CFD.  */
+
+void
+cilk_init_cfd (struct cilk_for_desc *cfd)
+{
+  memset (cfd, 0, sizeof *cfd);
+  init_wd (&cfd->wd, CILK_BLOCK_FOR);
+}
+
+/* Returns a CALL_EXPR based on the TYPE_PRECISON of COUNT_TYPE.  */
+
+static tree
+find_cilk_for_library_fn (tree count_type)
+{
+  if (TYPE_PRECISION (count_type) == 32)
+    return cilk_for_32_fndecl;
+  else if (TYPE_PRECISION (count_type) == 64)
+    return cilk_for_64_fndecl;
+  else
+    gcc_unreachable ();
+}
+
+/* This function finds the direction INCR, the increment expression, of the
+   loop: Return 0 if the sign of INCR_DIRECTION is unknown,
+   +1 if the value is exactly +1,
+   +2 if the value is known to be positive, and
+   -2 if the value is known to be negative.  */
+
+static int
+cilk_compute_incr_direction (tree incr)
+{
+  if (TREE_CODE (incr) != INTEGER_CST)
+    return tree_expr_nonnegative_p (incr) ? 2 : 0;
+  else if (integer_onep (incr))
+    return 1;
+  else
+    return 2 * tree_int_cst_sgn (incr);
+}
+
+/* Return the count type based on TYPE of a Cilk for loop, or unsigned long if
+   there is no acceptable type.  */
+
+tree
+cilk_check_loop_difference_type (tree type)
+{
+  if ((TYPE_PRECISION (type) > TYPE_PRECISION (long_unsigned_type_node))
+      || (TYPE_MAIN_VARIANT (type) == long_long_integer_type_node)
+      || (TYPE_MAIN_VARIANT (type) == long_long_unsigned_type_node))
+    return long_long_unsigned_type_node;
+
+  return long_unsigned_type_node;
+}
+
+/* Removes unwanted wrappers from a tree, T.  */
+
+tree
+cilk_simplify_tree (tree t)
+{
+  extern tree tree_ssa_strip_useless_type_conversions (tree);
+
+  if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
+    t = TREE_OPERAND (t, 0);
+  if (TREE_CODE (t) == NOP_EXPR)
+    t = TREE_OPERAND (t, 0);
+  if ((TREE_CODE (t) == CONVERT_EXPR) && (VOID_TYPE_P (TREE_TYPE (t)) != 0))
+    t = TREE_OPERAND (t, 0);
+
+  STRIP_USELESS_TYPE_CONVERSION (t);
+
+  return t;
+}
+
+/* Set up the variable mapping for the FNDECL and install parameters after
+   declaring the function and scanning the loop body's variable use.
+   Information about the _Cilk_for statement is stored in *CFD.  */
+
+void
+declare_cilk_for_vars (struct cilk_for_desc *cfd, tree fndecl)
+{
+  tree var2 = build_decl (cfd->loc, VAR_DECL, DECL_NAME (cfd->var),
+                     cfd->var_type);
+  DECL_CONTEXT (var2) = fndecl;
+  cfd->var2 = var2;
+
+  void **mapped = pointer_map_contains (cfd->wd.decl_map, cfd->var);
+  /* The loop control variable must be mapped.  */
+  gcc_assert (mapped);
+  const_tree t = (const_tree) *mapped;
+
+  /* The loop control variable may appear as mapped to itself
+     or mapped to integer_one_node depending on its type and
+     how it was modified.  */
+  if ((TREE_CODE (t) != INTEGER_CST) || (t == integer_one_node))
+    {
+      tree save_function = current_function_decl;
+      current_function_decl = DECL_CONTEXT (cfd->var);
+      warning (0, "loop body modifies control variable %qD", cfd->var);
+      current_function_decl = save_function;
+    }
+  *mapped = (void *) var2;
+
+  tree p = cfd->wd.parms;
+  DECL_ARGUMENTS (fndecl) = p;
+  do
+    {
+      DECL_CONTEXT (p) = fndecl;
+      p = TREE_CHAIN (p);
+    }
+  while (p);
+}
+
+/* Set up the signature and parameters of the _Cilk_for body function
+   before declaring the function using information stored in CFD.  */
+
+void
+declare_cilk_for_parms (struct cilk_for_desc *cfd)
+{
+  tree count_type = cfd->count_type;
+  tree ro_count = build_qualified_type (count_type, TYPE_QUAL_CONST);
+  tree ctx = build_decl (cfd->loc, PARM_DECL, NULL_TREE, ptr_type_node);
+  tree t1 = get_identifier ("__low");
+  tree min_parm = build_decl (cfd->loc, PARM_DECL, t1, ro_count);
+  tree t2 = get_identifier ("__high");
+  tree max_parm = build_decl (cfd->loc, PARM_DECL, t2, ro_count);
+
+  DECL_ARG_TYPE (max_parm) = count_type;
+  DECL_ARTIFICIAL (max_parm) = 1;
+  TREE_READONLY (max_parm) = 1;
+
+  DECL_ARG_TYPE (min_parm) = count_type;
+  DECL_ARTIFICIAL (min_parm) = 1;
+  TREE_READONLY (min_parm) = 1;
+
+  DECL_ARG_TYPE (ctx) = ptr_type_node;
+  DECL_ARTIFICIAL (ctx) = 1;
+  TREE_READONLY (ctx) = 1;
+
+  TREE_CHAIN (min_parm) = max_parm;
+  TREE_CHAIN (ctx) = min_parm;
+
+  tree types = tree_cons (NULL_TREE, TREE_TYPE (max_parm), void_list_node);
+  types = tree_cons (NULL_TREE, TREE_TYPE (min_parm), types);
+  types = tree_cons (NULL_TREE, TREE_TYPE (ctx), types);
+
+  cfd->min_parm = min_parm;
+  cfd->max_parm = max_parm;
+  cfd->wd.argtypes = types;
+  cfd->wd.arglist = NULL_TREE;
+  cfd->wd.parms = ctx;
+}
+
+/* Convert a loop, EXP, to the way required by _Cilk_for and sets it type as
+   indicated by TYPE.  */
+
+tree
+cilk_loop_convert (tree type, tree exp)
+{
+  enum tree_code code;
+  int inprec, outprec;
+  if (type == TREE_TYPE (exp))
+    return exp;
+  inprec = TYPE_PRECISION (TREE_TYPE (exp));
+  outprec = TYPE_PRECISION (type);
+  if (outprec > inprec && !TYPE_UNSIGNED (TREE_TYPE (exp)))
+    code = CONVERT_EXPR;
+  else
+    code = NOP_EXPR;
+  return fold_build1 (code, type, exp);
+}
+
+/* Returns the number of times a loop is divided.  */
+
+tree
+cilk_divide_count (tree count, enum tree_code op, tree incr, bool negate,
+		   tree type)
+{
+  tree dtype;
+
+  if (!count)
+    return NULL_TREE;
+
+  tree ctype = TREE_TYPE (count);
+  tree itype = TREE_TYPE (incr);
+
+  if (op == NOP_EXPR && !negate)
+    return cilk_loop_convert (type, count);
+  /* Return -(unsigned) count instead of (unsigned)-count in case the negate
+     overflows.  */
+  if (op == NOP_EXPR && negate)
+    return fold_build1 (NEGATE_EXPR, type, cilk_loop_convert (type, count));
+
+  /* We are dividing two positive values or else the user has invoked
+     undefined behavior.  That means we can divide in a common narrow
+     type and widen after.  This does not work if we must negate signed
+     INCR to get a positive value because we could be negating INT_MIN.  */
+
+  if (ctype != itype || (negate && !TYPE_UNSIGNED (itype)))
+    {
+      incr = cilk_loop_convert (type, incr);
+      count = cilk_loop_convert (type, count);
+      dtype = type;
+    }
+  else
+    dtype = ctype;
+
+  if (negate)
+    incr = fold_build1 (NEGATE_EXPR, TREE_TYPE (incr), incr);
+
+  count = fold_build2 (op, dtype, count, incr);
+  if (dtype != type)
+    count = cilk_loop_convert (type, count);
+
+  return count;
+}
+
+/* Sets *DIV_OP to the appropriate operation to divide the loop and
+   the *FORWARD tree with condition expression based on DIRECTION, INCR_SIGN
+   and EXACTLY_ONE.  */
+
+void
+cilk_calc_forward_div_op (struct cilk_for_desc *cfd, enum tree_code *div_op,
+			  tree *forward)
+{
+  switch (cfd->direction)
+    {
+    case -2:
+      *forward = boolean_false_node;
+      *div_op = CEIL_DIV_EXPR;
+      break;
+    case -1:
+      *forward = boolean_false_node;
+      *div_op = EXACT_DIV_EXPR;
+      break;
+    case 0:
+      *forward = build2 (cfd->incr_sign > 0 ? GE_EXPR : LT_EXPR,
+			 boolean_type_node, cfd->incr, integer_zero_node);
+      /* Loops with indeterminate direction use != and are always exact.  */
+      *div_op = EXACT_DIV_EXPR;
+      break;
+    case 1:
+      *forward = boolean_true_node;
+      *div_op = EXACT_DIV_EXPR;
+      break;
+    case 2:
+      *forward = boolean_true_node;
+      *div_op = CEIL_DIV_EXPR;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (cfd->exactly_one)
+    *div_op = NOP_EXPR;
+}
+
+/* Returns the loop-count based on the _Cilk_for loop's characteristics given
+   in *CFD.  DIV_OP indicates whether we have exact division or a CEILING
+   operation need to be performed.  COUNT_UP and COUNT_DOWN are not
+   NULL_TREE if the increment and decrement operation are done using an
+   iterator.  */
+
+tree
+cilk_compute_loop_count (struct cilk_for_desc *cfd, enum tree_code div_op,
+			 tree forward, tree count_up, tree count_down)
+{
+  /* if initial value is not given, the use the variable since it holds the
+     lower value.  */
+  tree low = cfd->lower_bound ? cfd->lower_bound : cfd->var;
+
+  /* Same logic as low for high variable.  */
+  tree high = cfd->end_var ? cfd->end_var : cfd->end_expr;
+
+  if (low == error_mark_node || high == error_mark_node)
+    {
+      gcc_assert (errorcount || sorrycount);
+      return error_mark_node;
+    }
+
+  /* If either count_up or count_down are not NULL, then it is an indication
+     that we have an interator for loop computation, so we check if
+     cfd->iterator is set to true.  */
+  if (count_up != NULL_TREE || count_down != NULL_TREE)
+    gcc_assert (cfd->iterator);
+  else
+    {
+      tree low_type = TREE_TYPE (low);
+      tree high_type = TREE_TYPE (high);
+      tree sub_type = NULL_TREE;
+
+      if (TREE_CODE (TREE_TYPE (cfd->var)) == POINTER_TYPE)
+	sub_type = ptrdiff_type_node;
+      else
+	{
+	  /* We need to compute HIGH - LOW or LOW - HIGH without overflow.  */
+	  sub_type = common_type (low_type, high_type);
+
+	  /* If subtracting two signed vars. without widening then convert them
+	     to unsigned.  */
+	  if (!TYPE_UNSIGNED (sub_type)
+	      && (TYPE_PRECISION (sub_type) == TYPE_PRECISION (low_type)
+		  || TYPE_PRECISION (sub_type) == TYPE_PRECISION (high_type)))
+	    sub_type = unsigned_type_for (sub_type);
+	}
+      if (low_type != sub_type)
+	low = convert (sub_type, low);
+      if (high_type != sub_type)
+	high = convert (sub_type, high);
+
+      if (cfd->direction <= 0)
+	count_down = fold_build2 (MINUS_EXPR, sub_type, low, high);
+      if (cfd->direction >= 0)
+	count_up = fold_build2 (MINUS_EXPR, sub_type, high, low);
+    }
+
+  /* if the loop is not exact add one before dividing.  Otherwise add 1 after
+     dividing.  Assumed that it can't overflow (meaning that loop range cannot
+     exceed the range of the loop variable or difference type).  */
+  if (cfd->inclusive && div_op == CEIL_DIV_EXPR)
+    {
+      if (count_up)
+	count_up = fold_build2 (PLUS_EXPR, TREE_TYPE (count_up), count_up,
+				build_one_cst (TREE_TYPE (count_up)));
+      if (count_down)
+	count_down = fold_build2 (PLUS_EXPR, TREE_TYPE (count_down), count_down,
+				  build_one_cst (TREE_TYPE (count_down)));
+    }
+
+  /* Serial semantics: INCR is converted to the common type of VAR and INCR then
+     the result is converted to the type of VAR.  */
+  tree incr = cfd->incr;
+  if (!cfd->iterator && TREE_CODE (TREE_TYPE (cfd->var)) != POINTER_TYPE)
+    incr = cilk_loop_convert (common_type (TREE_TYPE (cfd->var),
+					   TREE_TYPE (incr)), incr);
+
+  /* Now separately divide each count by +/- INCR yielding a value with type
+     TYPE.  */
+  count_up = cilk_divide_count (count_up, div_op, incr, cfd->incr_sign < 0,
+				cfd->count_type);
+  count_down = cilk_divide_count (count_down, div_op, incr, cfd->incr_sign > 0,
+				  cfd->count_type);
+  /* Merge forward and backward counts.  */
+  tree count = NULL_TREE;
+  if (!count_up)
+    count = count_down;
+  else if (!count_down)
+    count = count_up;
+  else
+    count = fold_build3 (COND_EXPR, cfd->count_type, forward, count_up,
+			 count_down);
+
+  /* Add one, maybe.  */
+  if (cfd->inclusive && div_op != CEIL_DIV_EXPR)
+    count = fold_build2 (PLUS_EXPR, cfd->count_type, count,
+			 build_one_cst (cfd->count_type));
+
+  return count;
+}
+
+/* Returns a GIMPLE_SEQ that contains a call to the Cilk library function and
+   the necessary temporary variables.  COUNT and FN are parameters to the
+   library function indicating the loop-count and nested function,
+   respectively.  */
+
+gimple_seq
+insert_cilk_for_nested_fn (struct cilk_for_desc *cfd, tree count, tree fn)
+{
+  /* INNER_SEQ contains evaluation of variables holding loop increment and
+     count.  These are evaluated inside the loop guard.  */
+  gimple_seq inner_seq = 0;
+  if (!TREE_CONSTANT (count))
+    {
+      count = fold_build_cleanup_point_expr (TREE_TYPE (count), count);
+      count = get_formal_tmp_var (count, &inner_seq);
+    }
+
+  if (TREE_SIDE_EFFECTS (cfd->incr))
+    cfd->incr = get_formal_tmp_var (cfd->incr, &inner_seq);
+
+  tree libfun = find_cilk_for_library_fn (cfd->count_type);
+  tree ctx = cfd->ctx_arg;
+  if (ctx)
+    {
+      if (TREE_TYPE (ctx) != ptr_type_node)
+	ctx = fold_build1 (NOP_EXPR, ptr_type_node, ctx);
+      if (!DECL_P (ctx))
+	ctx = get_formal_tmp_var (ctx, &inner_seq);
+    }
+  else
+    {
+      ctx = fold_build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+      ctx = get_formal_tmp_var (ctx, &inner_seq);
+    }
+  fn = fold_build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+  TREE_CONSTANT (fn) = 1;
+  fn = get_formal_tmp_var (fn, &inner_seq);
+
+  tree grain = cfd->grain;
+  tree tmv_count_type = TYPE_MAIN_VARIANT (cfd->count_type);
+  if (!grain)
+    grain = get_formal_tmp_var (build_zero_cst (cfd->count_type), &inner_seq);
+  else if (TYPE_MAIN_VARIANT (TREE_TYPE (grain)) != tmv_count_type)
+    grain = convert (cfd->count_type, grain);
+
+  tree libfun_call = build_call_expr (libfun, 4, fn, ctx, count, grain);
+  gimplify_and_add (libfun_call, &inner_seq);
+  return inner_seq;
+}
+
+/* The loop function looks like
+   
+   body (void *, unsigned long max, unsigned long min)
+   const T start = [outer_context] var;
+   T var';
+   for (unsigned long i = min; i < max; i++) {
+     var' = start + (T) i * (T) incr;
+     body (var');
+   }
+
+   COMPUTE_LOOP_VAR returns an expression for
+   var' = start + i * incr;
+   or
+   var' = start - i * decr;
+   with suitable type conversions.
+
+   If direction is known we know the sign of INCR (or else it's
+   undefined behavior) and we can work with positive unsigned
+   numbers until the last addition or subtraction.
+
+   If direction is not known then the increment and loop variable
+   are signed but the product of the loop count and increment may
+   not be representable as a signed value.
+
+   We can't do the last addition or subtraction in C without
+   a conditional operation because the conversion of unsigned
+   to signed is undefined for "negative" values of the unsigned
+   number.  For now we just pretend this isn't a problem.  We
+   may fail on targets with signed overflow.
+
+   For iterator loops we require that the difference type have
+   enough range and simply pass the value to operator+ or operator-
+   based on the static direction of the loop.  Iterator loop case is
+   handled by the function passed in a function pointer, *ITER_HANDLER.
+
+   LOOP_VAR has type COUNT_TYPE.  */
+
+tree
+cilk_compute_loop_var (struct cilk_for_desc *cfd, tree loop_var,
+		       tree lower_bound,
+		       tree (*iter_handler) (location_t, enum tree_code,
+					     tree, tree, tree))
+{
+  tree count_type = NULL_TREE;
+  if (INTEGRAL_TYPE_P (TREE_TYPE (loop_var)))
+    count_type = TREE_TYPE (loop_var);
+  else
+    count_type = cfd->count_type;
+  
+   /* Compute an expression to be added or subtracted.
+
+     We want to add or subtract LOOP_VAR * INCR.  INCR may be negative.
+     If the static direction is indeterminate we don't know that at
+     compile time.  The code to convert to unsigned and multiply does
+     the right thing in the end.  For iterator loops we don't need to
+     go to that trouble, but scalar loops can have range that can not
+     be represented in the signed loop variable.  */
+  tree scaled = NULL_TREE, incr = NULL_TREE;
+  if (integer_onep (cfd->incr))
+    scaled = loop_var;
+  else
+    {
+      incr = cilk_loop_convert (count_type, cfd->incr);
+      scaled = fold_build2 (MULT_EXPR, count_type, loop_var, incr);
+    }
+
+  enum tree_code add_op = cfd->incr_sign >= 0 ? PLUS_EXPR : MINUS_EXPR;
+  if (cfd->iterator)
+    {
+      /* Convert LOOP_VAR to T3 (difference_type) so that
+         operator+(T1, T3) is preferred over operator+(T1, count_type)
+         operator+ constructs the object if it returns by value.
+         Use operator- if the user wrote -=.  */
+      if (count_type != cfd->difference_type)
+	loop_var = convert (cfd->difference_type, scaled);
+      tree low = lower_bound ? lower_bound : cfd->var;
+      if (TREE_CODE (low) == TREE_LIST)
+	low = TREE_VALUE (low);
+      tree exp = iter_handler (cfd->loc, add_op, low, loop_var, cfd->var2);
+      return exp;
+    }
+   /* The scaled count may not be representable in the type of the
+     loop variable, e.g. if the loop range is INT_MIN+1 to INT_MAX-1
+     the range does not fit in a signed int.  The sum of the lower
+     bound and the count is representable.  Do the addition or
+     subtraction in the wider type, then narrow. */
+  tree cvt_val = cilk_loop_convert (count_type, lower_bound);
+  tree adjusted = fold_build2 (add_op, count_type, cvt_val, scaled);
+  tree exp = fold_build2 (MODIFY_EXPR, void_type_node, cfd->var2,
+			  cilk_loop_convert (cfd->var_type, adjusted));
+  return exp;
+}
+
+/* Remove NOP_EXPR, ADDR_EXPR and INDIRECT_REF wrappers from EXP and
+   return.  */
+
+tree
+cilk_tree_operand_noconv (tree exp)
+{
+  tree op = exp;
+  while (TREE_CODE (op) == NOP_EXPR
+	 || TREE_CODE (op) == ADDR_EXPR
+	 || TREE_CODE (op) == INDIRECT_REF)
+    op = TREE_OPERAND (op, 0);
+  return op;
+}
+
+/* Return the TREE_CODE for an overloaded function call, FN_CALL.  */
+
+enum tree_code
+cilk_find_code_from_call (tree fn_call)
+{
+  /* Unwrap the ADDR_EXPR layer.  */
+  tree call = TREE_OPERAND (fn_call, 0);
+  call = DECL_NAME (call);
+  const char *name = IDENTIFIER_POINTER (call);
+  char op_name[2];
+  op_name[1] = name[strlen (name) - 1];
+  if (name [strlen (name) - 2] != 'r')
+    op_name[0] = name [strlen (name) - 2];
+  else
+    op_name[0] = ' ';
+
+  if (op_name[1] == '<')
+    return LT_EXPR;
+  else if (op_name[1] == '>')
+    return GT_EXPR;
+  else if (op_name[1] == '=')
+    {
+      if (op_name[0] == '<')
+	return LE_EXPR;
+      else if (op_name[0] == '>')
+	return GE_EXPR;
+      else if (op_name[0] == '!')
+	return NE_EXPR;
+      else if (op_name[0] == '=')
+	return EQ_EXPR;
+      else if (op_name[0] == '+')
+	return PLUS_EXPR;
+      else if (op_name[0] == '-')
+	return MINUS_EXPR;
+      else
+	gcc_unreachable ();
+    }
+  else if (op_name[1] == '+' && op_name[0] == '+')
+    /* This could be post or pre increment expression, but for our case
+       it really does not matter.  */
+    return POSTINCREMENT_EXPR;
+  else if (op_name[1] == '-' && op_name[0] == '-')
+    /* Same reasoning as above for decrement expression.  */
+    return POSTDECREMENT_EXPR;
+  else
+    gcc_unreachable ();
+  return NOP_EXPR;
+}
+
+/* Extracts the initial value of the initalizer for a CILK_FOR_STMT.  This
+   information is stored in CFD->LOWER_BOUND.  */
+
+void
+cilk_set_init_info (struct cilk_for_desc *cfd)
+{
+  if (!cfd->lower_bound)
+    return;
+  else if (TREE_CODE (cfd->lower_bound) == MODIFY_EXPR
+	   || TREE_CODE (cfd->lower_bound) == INIT_EXPR)
+    {
+      tree op0 = TREE_OPERAND (cfd->lower_bound, 0);
+      tree op1 = TREE_OPERAND (cfd->lower_bound, 1);
+
+      gcc_assert (op0 == cfd->var);
+      cfd->lower_bound = op1;
+    }
+}
+
+/* Sets the CFD->INCLUSIVE, CFD->END_EXPR and CFD->DIRECTION based on the
+   characteristics of the Cilk for statement. */
+
+void
+cilk_set_inclusive_and_direction (struct cilk_for_desc *cfd)
+{
+  tree cond = cfd->cond;
+  enum tree_code cond_code = TREE_CODE (cond);
+  if (cond_code == CALL_EXPR)
+    cond_code = cilk_find_code_from_call (CALL_EXPR_FN (cond));
+  
+  switch (cond_code)
+    {
+    case NE_EXPR:
+      cfd->inclusive = false;
+      cfd->direction = 0;
+      break;
+    case GE_EXPR:
+      cfd->inclusive = true;
+      cfd->direction = -2;
+      break;
+    case GT_EXPR:
+      cfd->inclusive = false;
+      cfd->direction = -2;
+      break;
+    case LE_EXPR:
+      cfd->inclusive = true;
+      cfd->direction = 2;
+      break;
+    case LT_EXPR:
+      cfd->inclusive = false;
+      cfd->direction = 2;
+      break;
+    default:
+      /* == is not allowed.  */
+      gcc_unreachable ();
+    }
+  tree limit = NULL_TREE;
+  tree arg0, arg1;
+  
+  if (TREE_CODE (cond) == CALL_EXPR)
+    {
+      arg0 = CALL_EXPR_ARG (cond, 0);
+      arg1 = CALL_EXPR_ARG (cond, 1);
+    }
+  else
+    {
+      arg0 = TREE_OPERAND (cond, 0);
+      arg1 = TREE_OPERAND (cond, 1);
+    }
+
+  if (cilk_tree_operand_noconv (arg0) == cfd->var)
+    limit = arg1;
+  else
+    {
+      /* If we are here, then we have a case like this: 10 > ii;  */
+      limit = arg0;
+      cfd->direction = -cfd->direction;
+    }	
+     
+  cfd->end_expr = limit;
+}
+
+/* Sets CFD->ITERATOR and CFD->DIFFERENCE_TYPE based on the characteristics of
+   the _Cilk_for statement.  */
+
+void
+cilk_set_iter_difftype (struct cilk_for_desc *cfd)
+{
+  tree var_type = TREE_TYPE (cfd->var);
+  gcc_assert (var_type);
+  
+  switch (TREE_CODE (var_type))
+    {
+    case POINTER_TYPE:
+      cfd->iterator = false;
+      cfd->difference_type = ptrdiff_type_node;
+      break;
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case INTEGER_TYPE:
+      cfd->iterator = false;
+      cfd->difference_type = lang_hooks.types.type_promotes_to (var_type);
+      break;
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      cfd->iterator = true;
+      cfd->difference_type = NULL; /* This will be set later for C++.  */
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Populate CFD with characteristics of the increment expression.  If
+   HANDLE_PTR_MULT is set, then increment is multiplied by the size of
+   pointer.  This is necessary for C++ but not for C.  */
+
+void
+cilk_set_incr_info (struct cilk_for_desc *cfd, bool handle_ptr_mult)
+{
+  int negate_incr = 0, incr_direction = 0;
+
+  cfd->incr = cilk_simplify_tree (cfd->incr);
+  enum tree_code inc_op = TREE_CODE (cfd->incr);
+  bool is_incr = false;
+  tree op0, op1;
+  tree incr;
+  if (inc_op == ADDR_EXPR || inc_op == CALL_EXPR || inc_op == INDIRECT_REF)
+      /* This indicates that the increment operation is overloaded.  */
+    incr = cilk_tree_operand_noconv (cfd->incr);
+  else if (inc_op == TARGET_EXPR)
+    incr = TARGET_EXPR_INITIAL (cfd->incr);
+  else
+    incr = cfd->incr;
+      
+  if (TREE_CODE (incr) == CALL_EXPR)
+    {
+      inc_op = cilk_find_code_from_call (CALL_EXPR_FN (incr));
+      if (inc_op == PLUS_EXPR || inc_op == MINUS_EXPR)
+	{
+	  op1 = CALL_EXPR_ARG (incr, 1);
+	  op0 = cilk_tree_operand_noconv (CALL_EXPR_ARG (incr, 0));
+	  inc_op = (inc_op == PLUS_EXPR ? PREINCREMENT_EXPR
+		    : PREDECREMENT_EXPR);
+	}
+      else if (inc_op == POSTINCREMENT_EXPR || inc_op == POSTDECREMENT_EXPR
+	       || inc_op == PREDECREMENT_EXPR || inc_op == PREINCREMENT_EXPR)
+	op1 = integer_one_node;
+      else
+	op1 = CALL_EXPR_ARG (incr, 0);
+    }
+  else
+    op1 = TREE_OPERAND (cfd->incr, 1);
+  
+  is_incr = (inc_op == PREINCREMENT_EXPR || inc_op == POSTINCREMENT_EXPR);
+  switch (inc_op)
+    {
+    case POSTDECREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      negate_incr = is_incr ? false : true;
+      incr_direction = is_incr ? -1 : 1;
+      cfd->incr = op1;
+      if (!cfd->incr)
+	{
+	  tree var_type = TREE_TYPE (cfd->var);
+	  if (TREE_CODE (var_type) == POINTER_TYPE)
+	    cfd->incr = size_in_bytes (TREE_TYPE (var_type));
+	  else
+	    cfd->incr = integer_one_node;
+	}
+      cfd->exactly_one = integer_onep (cfd->incr);
+      break;
+    case MODIFY_EXPR:
+      {
+	/* In here the expressions will have the form var <MODIFY_OP> incr or
+	   op = op <OPERATION> incr.  */
+	cfd->incr = (TREE_CODE (cfd->incr) != MODIFY_EXPR ? op1
+		     : TREE_OPERAND (cfd->incr, 1));
+	enum tree_code increment_code = TREE_CODE (cfd->incr);
+	if (increment_code == PLUS_EXPR || increment_code == POINTER_PLUS_EXPR)
+	  {
+	    op0 = TREE_OPERAND (cfd->incr, 0);
+	    op1 = TREE_OPERAND (cfd->incr, 1);
+
+	    if (op0 == cfd->var || DECL_NAME (op0) == DECL_NAME (cfd->var))
+	      cfd->incr = op1;
+	    else if (op1 == cfd->var || DECL_NAME (op1) == DECL_NAME (cfd->var))
+	      cfd->incr = op0;
+	    else
+	      gcc_unreachable ();
+
+	    negate_incr = false;
+	    incr_direction = cilk_compute_incr_direction (cfd->incr);
+	  
+	    /* Adding a negative number treated as unsigned is like adding a
+	       large positive number.  */
+	    if (TYPE_UNSIGNED (cfd->difference_type) && incr_direction < 0)
+	      incr_direction = 2;
+	    cfd->exactly_one = (incr_direction == 1);
+
+	    /* Don't need to do this in POINTER_PLUS_EXPR since it already
+	       does this for you.  */
+	    if (handle_ptr_mult && increment_code != POINTER_PLUS_EXPR)
+	      {
+		tree var_type = TREE_TYPE (cfd->var);
+		if (TREE_CODE (var_type) == POINTER_TYPE)
+		  {
+		    tree size = size_in_bytes (TREE_TYPE (var_type));
+		    if (!integer_onep (size))
+		      {
+			cfd->exactly_one = 0;
+			/* For example, in the following _Cilk_for statement:
+			   _Cilk_for (int *p = a, p < b; p += (char)c)
+			   We need to do the match in a type wider than c.
+			   "build_binary_op" will do the default conversions
+			   which should be enough if SIZE is size_t.  */
+			cfd->incr = build_binary_op (cfd->loc, MULT_EXPR,
+						     cfd->incr, size, 0);
+		      }
+		  }
+	      }
+	  }
+	else if (TREE_CODE (cfd->incr) == MINUS_EXPR)
+	  {
+	    op1 = TREE_OPERAND (cfd->incr, 1);
+	    op0 = TREE_OPERAND (cfd->incr, 0);
+
+	    gcc_assert (op0 == cfd->var
+			|| DECL_NAME (op0) == DECL_NAME (cfd->var));
+	    cfd->incr = op1;
+	    negate_incr = true;
+	    incr_direction = -cilk_compute_incr_direction (cfd->incr);
+
+	    /* Subtracting a negative number is treated as adding a
+	       positive.  */
+	    if (TYPE_UNSIGNED (cfd->difference_type) && incr_direction > 0)
+	      incr_direction = -2;
+	    cfd->exactly_one = (incr_direction == -1);
+
+	    /* In C++ we need to handle the pointer arithmetic manually, but
+	       in C it seem to automatically figure this out.  */
+	    if (handle_ptr_mult)
+	      {
+		tree var_type  = TREE_TYPE (cfd->var);
+		if (TREE_CODE (var_type) == POINTER_TYPE)
+		  {
+		    tree size = size_in_bytes (TREE_TYPE (var_type));
+		    if (!integer_onep (size))
+		      {
+			cfd->exactly_one = 0;
+			/* For example, in the following _Cilk_for statement:
+			   _Cilk_for (int *p = a, p < b; p += (char)c)
+			   We need to do the match in a type wider than c.
+			   "build_binary_op" will do the default conversions
+			   which should be enough if SIZE is size_t.  */
+			cfd->incr = build_binary_op (cfd->loc, MULT_EXPR,
+						     cfd->incr, size, 0);
+		      }
+		  }
+	      }
+	  }
+	else
+	  {
+	    location_t incr_loc = EXPR_LOCATION (cfd->incr);
+	    error_at (incr_loc, "invalid loop increment operation");
+	    cfd->invalid = true;
+	    return;
+	  }
+      }
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  cfd->var_type = TREE_TYPE (cfd->var);
+  cfd->incr_sign = negate_incr ? -1 : 1;
+}
+
+/* Helper function for walk_tree. Fixes up all the continues inside a
+   _Cilk_for body.  */
+
+tree
+cilk_resolve_continue_stmts (tree *tp, int *walk_subtrees, void *data)
+{
+  tree goto_label = NULL_TREE, goto_stmt = NULL_TREE;
+  if (!tp || !*tp)
+    return NULL_TREE;
+
+  if (TREE_CODE (*tp) == CONTINUE_STMT)
+    {
+      goto_label = (tree) data;
+      goto_stmt = build1 (GOTO_EXPR, void_type_node, goto_label);
+      *tp = goto_stmt;
+      *walk_subtrees = 0;
+    }
+  else if (TREE_CODE (*tp) == FOR_STMT || TREE_CODE (*tp) == WHILE_STMT
+           || TREE_CODE (*tp) == DO_STMT || TREE_CODE (*tp) == CILK_FOR_STMT)
+      /* Inside these statements, the continue goes to a different place not
+         end of cilk_for. You do not want to go into these trees because we
+         will resolve those later.  */
+    *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index d79fc4f..baa8af2 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -51,7 +51,7 @@  CFLAGS-c/gccspec.o += $(DRIVER_DEFINES)
 # Language-specific object files for C and Objective C.
 C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
   c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
-  c/c-array-notation.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+  c/c-array-notation.o c/c-cilk.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
 
 # Language-specific object files for C.
 C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
diff --git a/gcc/c/c-cilk.c b/gcc/c/c-cilk.c
new file mode 100644
index 0000000..982b0de
--- /dev/null
+++ b/gcc/c/c-cilk.c
@@ -0,0 +1,359 @@ 
+/* This file is part of the Intel (R) Cilk (TM) Plus support
+   This file contains the functions required to handle _Cilk_for
+   for the C language.
+   Copyright (C) 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 "tree.h"
+#include "c-tree.h"
+#include "langhooks.h"
+#include "gimple.h"
+#include "tree-iterator.h"
+#include "tree-inline.h"
+#include "c-family/c-common.h"
+#include "toplev.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "cilk.h"
+#include "gimplify.h"
+
+/* Get a block for the CILK_FOR_STMT, CFOR.  */
+
+static tree
+block_cilk_for_loop (tree cfor)
+{
+  tree block = tree_block (cfor);
+  if (block)
+    return block;
+  return DECL_INITIAL (current_function_decl);
+}
+
+/* Create or discover the variable to be used in the loop termination
+   condition.  Return true if the cfd->end_var should be used in the
+   guard test around the runtime call.  Otherwise the guard test uses
+   the complex expression, which in C++ may initialize the variable.
+
+   For example, if END_EXPR is
+
+   (target_expr limit (call constructor ...))
+
+   the variable limit is not initialized until the target_expr is
+   evaluated.  */
+
+static bool
+cilk_for_end (struct cilk_for_desc *cfd, gimple_seq *pre_p)
+{
+  tree end = cfd->end_expr;
+  if (TREE_SIDE_EFFECTS (end))
+    {
+      enum tree_code ecode = TREE_CODE (end);
+      if (ecode == INIT_EXPR || ecode == MODIFY_EXPR || ecode == TARGET_EXPR)
+        {
+          cfd->end_var = TREE_OPERAND (end, 0);
+          return false;
+        }
+      else
+        {
+          /* Copy the result of evaluating the expression into a variable.
+             The compiler will probably crash if there's anything
+             complicated in it -- a complicated value needs to go through
+             the other branch of this IF using an explicit temporary.  */
+          cfd->end_var = get_formal_tmp_var (end, pre_p);
+          return true;
+        }
+    }
+  cfd->end_var = end;
+  return false;
+}
+
+/* Handler for iterator to compute the loop variable.  LOW indicates the
+   starting point and LOOP_VAR is the induction variable, and VAR2 is the
+   original induction variable in the Cilk_for.  Returns an expression
+   (or a STATEMENT_LIST of expressions).  */
+
+static tree
+compute_loop_var_c_iter_hdl (location_t loc, enum tree_code add_op, tree low,
+			     tree loop_var, tree var2)
+{
+  tree exp = fold_build2 (add_op, TREE_TYPE (loop_var), low, loop_var);
+  gcc_assert (exp != error_mark_node);
+
+  exp = build_modify_expr (loc, var2, TREE_TYPE (var2), INIT_EXPR, loc, exp,
+			   TREE_TYPE (exp));
+  gcc_assert (exp != error_mark_node);
+  return exp;
+}
+
+
+/* Creates a body of the _Cilk_for wrapper function with the information
+   in *CFD.  */
+
+static tree
+create_cilk_for_body (struct cilk_for_desc *cfd)
+{
+  declare_cilk_for_parms (cfd);
+  cfd->wd.fntype = build_function_type (void_type_node, cfd->wd.argtypes);
+  tree fndecl = cilk_create_cilk_helper_decl (&cfd->wd);
+
+  tree outer = current_function_decl;
+  push_struct_function (fndecl);
+  current_function_decl = fndecl;
+
+  declare_cilk_for_vars (cfd, fndecl);
+
+  tree body = push_stmt_list ();
+  tree mod_expr = NULL_TREE, loop_var = NULL_TREE;
+  tree lower_bound = cfd->lower_bound;
+  if (!lower_bound)
+    {
+      lower_bound = cfd->var;
+      tree hack = build_decl (EXPR_LOCATION (cfd->var), VAR_DECL, NULL_TREE,
+			      TREE_TYPE (lower_bound));
+      DECL_CONTEXT (hack) = DECL_CONTEXT (lower_bound);
+      DECL_NAME (hack) = DECL_NAME (lower_bound);
+      *pointer_map_insert (cfd->wd.decl_map, hack) = lower_bound;
+      lower_bound = hack;
+    }
+  if (INTEGRAL_TYPE_P (cfd->var_type))
+    {
+      tree new_min_parm = fold_build1 (CONVERT_EXPR, cfd->var_type,
+				       cfd->min_parm);
+      loop_var = create_tmp_var (cfd->var_type, NULL);
+      location_t loc = EXPR_LOCATION (cfd->var);
+      mod_expr = build_modify_expr (loc, loop_var, cfd->var_type, NOP_EXPR,
+				    loc, new_min_parm, cfd->var_type);
+    }
+  else
+    {
+      loop_var = create_tmp_var (TREE_TYPE (cfd->min_parm), NULL);
+      mod_expr = fold_build2 (INIT_EXPR, void_type_node, loop_var,
+			      cfd->min_parm);
+    }
+  add_stmt (mod_expr);
+  tree loop_body = NULL_TREE;
+  tree new_max_parm = NULL_TREE;
+
+  if (!INTEGRAL_TYPE_P (cfd->var_type))
+    new_max_parm = cfd->max_parm;
+  else
+    new_max_parm = fold_build1 (CONVERT_EXPR, cfd->var_type, cfd->max_parm);
+
+  tree end_comp = cilk_compute_loop_var (cfd, loop_var, lower_bound,
+					 compute_loop_var_c_iter_hdl);
+  append_to_statement_list (end_comp, &loop_body);
+  append_to_statement_list (cfd->body, &loop_body);
+  loop_body = fold_build_cleanup_point_expr (void_type_node, loop_body);
+  DECL_SEEN_IN_BIND_EXPR_P (cfd->var2) = 1;
+
+  cilk_outline_body (fndecl, &loop_body, &cfd->wd, NULL);
+  
+  tree loop = push_stmt_list ();
+  /* Now create a loop with c_finish_loop.  */
+  tree incr = fold_build2 (PLUS_EXPR, TREE_TYPE (loop_var), loop_var,
+			   build_one_cst (TREE_TYPE (loop_var)));
+  incr = fold_build2 (MODIFY_EXPR, void_type_node, loop_var, incr);
+  tree cond = fold_build2 (LT_EXPR, boolean_type_node, loop_var, new_max_parm);
+  c_finish_loop (EXPR_LOCATION (cfd->var), cond, incr, loop_body, NULL_TREE,
+		 NULL_TREE, false);
+  loop = pop_stmt_list (loop);
+  add_stmt (loop);
+  body = pop_stmt_list (body);
+
+  tree block = DECL_INITIAL (fndecl);
+  BLOCK_VARS (block) = loop_var;
+  body = build3 (BIND_EXPR, void_type_node, loop_var, body, block);
+  TREE_CHAIN (loop_var) = cfd->var2;
+  if (cilk_detect_spawn_and_unwrap (&body))
+    lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, body);
+  else
+    DECL_SAVED_TREE (fndecl) = body;
+
+  pop_cfun ();
+  current_function_decl = outer;
+  return fndecl;
+}
+
+/* Creates a wrapper function for the body of a _Cilk_for statement with the
+   information stored in *CFD.  */
+
+static tree
+create_cilk_for_wrapper (struct cilk_for_desc *cfd)
+{
+  tree old_cfd = current_function_decl;
+  tree incr = cfd->incr;
+  tree var = cfd->var;
+
+  if (POINTER_TYPE_P (TREE_TYPE (var)))
+    cilk_extract_free_variables (cfd->lower_bound, &cfd->wd, ADD_WRITE);
+  else
+    cilk_extract_free_variables (cfd->lower_bound, &cfd->wd, ADD_READ);
+
+  cilk_extract_free_variables (incr, &cfd->wd, ADD_READ);
+
+  /* Map the loop variable to integer_minus_one_node if we won't really
+     be passing it to the loop body and integer_zero_node otherwise.
+
+     If the map ends up integer_one_node then somebody wrote to the loop
+     variable and that's a user error.
+     The correct map will be installed in declare_for_loop_variables. */
+  *pointer_map_insert (cfd->wd.decl_map, var) =
+    (void *) (cfd->lower_bound ? integer_minus_one_node : integer_zero_node);
+  
+  /* Note that variables are not extracted from the loop condition
+     and increment.  They are evaluated, to the extent they are
+     evaluated, in the context containing the for loop.  */
+  cilk_extract_free_variables (cfd->body, &cfd->wd, ADD_READ);
+
+  tree fn = create_cilk_for_body (cfd);
+  DECL_UNINLINABLE (fn) = 1;
+  current_function_decl = old_cfd;
+  set_cfun (DECL_STRUCT_FUNCTION (current_function_decl));
+  cfun->is_cilk_function = 1;
+
+  /* Add the new function to the cgraph list.  */
+  cilk_call_graph_add_fn (fn);
+  return fn;
+}
+
+/* Helper function for gimplify_cilk_for.  *CFD contains all the relevant
+   information extracted from a _Cilk_for statement passed into the parent
+   function gimplify_cilk_for.  */
+   
+void
+gimplify_cilk_for_1 (struct cilk_for_desc *cfd, gimple_seq *pre_p)
+{ 
+  /* We don't have to evaluate INCR only once, but we do have
+     to evaluate it no more times than in the serial loop.
+     The naive method evaluates INCR exactly that many times
+     except if the static loop direction is indeterminate.
+
+     Storing the increment in a variable is thus mandatory
+     if cfd.direction == 0.  It is an optimization otherwise
+     and there seems no harm and some benefit in doing it.
+
+     The evaluation is on the inner statement list.  The
+     increment can not be referenced prior to the loop test.  */
+  if (TREE_SIDE_EFFECTS (cfd->incr))
+    sorry ("_Cilk_for increment with side effects");
+
+  tree cond = cfd->cond;
+  tree op0 = TREE_OPERAND (cond, 0);
+  tree op1 = TREE_OPERAND (cond, 1);
+  if (!cilk_for_end (cfd, pre_p) && cfd->end_var != cfd->end_expr)
+    {
+      if (op1 == cfd->end_expr)
+	op1 = cfd->end_var;
+      else
+	op0 = cfd->end_var;
+    }
+  cond = fold_build2 (TREE_CODE (cond), boolean_type_node, op0, op1);
+
+  tree forward = NULL_TREE;
+  
+  /* This is set to NOP_EXPR to have an initial value since we are passing in
+     an address to the function below.  */
+  enum tree_code div_op = NOP_EXPR;
+
+  cilk_calc_forward_div_op (cfd, &div_op, &forward);
+
+  tree count = cilk_compute_loop_count (cfd, div_op, forward, NULL_TREE,
+					NULL_TREE);
+  tree fn = create_cilk_for_wrapper (cfd);
+
+  /* Set condition correctly, so that the function below can use it.  */
+  cfd->cond = cond;
+  gimple_seq inner_seq = insert_cilk_for_nested_fn (cfd, count, fn);
+  gimple_seq_add_seq (pre_p, inner_seq);
+}
+
+/* Extracts all the relevant information from CFOR, a CILK_FOR_STMT tree and
+   stores them in CFD structure.  */
+
+static void
+c_extract_cilk_for_fields (struct cilk_for_desc *cfd, tree cfor)
+{
+  cfd->var = CILK_FOR_VAR (cfor);
+  cfd->cond = CILK_FOR_COND (cfor);
+  cfd->lower_bound = CILK_FOR_INIT (cfor);
+  cfd->incr = CILK_FOR_EXPR (cfor);
+  cfd->loc = EXPR_LOCATION (cfor);
+  cfd->body = CILK_FOR_BODY (cfor);
+  cfd->grain = CILK_FOR_GRAIN (cfor);
+  cfd->invalid = false;
+
+  /* This function shouldn't be setting these two variables.  */
+  cfd->ctx_arg = NULL_TREE;
+  cfd->count = NULL_TREE;
+
+  if (TREE_CODE (cfd->lower_bound) == MODIFY_EXPR
+      || TREE_CODE (cfd->lower_bound) == INIT_EXPR)
+    {
+      tree op0 = TREE_OPERAND (cfd->lower_bound, 0); 
+      tree op1 = TREE_OPERAND (cfd->lower_bound, 1);
+
+      gcc_assert (op0 == cfd->var);
+      cfd->lower_bound = op1;
+    }
+
+  cilk_set_inclusive_and_direction (cfd);  
+  cilk_set_iter_difftype (cfd);
+  
+  /* Difference type cannot be NULL_TREE here for C.  */
+  cfd->count_type = cilk_check_loop_difference_type (cfd->difference_type);
+  if (cfd->count_type == NULL_TREE)
+    {
+      cfd->invalid = true;
+      return;
+    }
+
+  cilk_set_incr_info (cfd, false);
+}  
+
+/* Main entry-point function to gimplify a cilk_for statement.  *EXPR_P should
+   be a CILK_FOR_STMT tree.  */
+
+int
+c_gimplify_cilk_for (tree *expr_p, gimple_seq *pre_p,
+		     gimple_seq *post_p ATTRIBUTE_UNUSED)
+{
+  struct cilk_for_desc cfd;
+  tree cfor_expr = *expr_p;
+  
+  cfun->is_cilk_function = 1;
+  cilk_init_cfd (&cfd);
+  cfd.wd.block = block_cilk_for_loop (cfor_expr);
+  
+  c_extract_cilk_for_fields (&cfd, cfor_expr);
+  
+  *expr_p = NULL_TREE;
+  if (cfd.invalid)
+    return GS_ERROR;
+
+  tree var = CILK_FOR_VAR (cfor_expr);
+  tree init = CILK_FOR_INIT (cfor_expr);
+  tree init_expr = fold_build2 (MODIFY_EXPR, void_type_node, var, init);
+  
+  gimplify_and_add (init_expr, pre_p);
+  gimplify_cilk_for_1 (&cfd, pre_p);
+  return GS_ALL_DONE;
+}
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index 6ae7b3e..ca7fa4a 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -114,4 +114,7 @@  along with GCC; see the file COPYING3.  If not see
 #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_GIMPLIFY_CILK_FOR
+#define LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR c_gimplify_cilk_for
 #endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index bae9708..fc82fcc 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1165,6 +1165,8 @@  static void c_parser_switch_statement (c_parser *);
 static void c_parser_while_statement (c_parser *, bool);
 static void c_parser_do_statement (c_parser *, bool);
 static void c_parser_for_statement (c_parser *, bool);
+static void c_parser_cilk_for_statement (c_parser *, enum rid, tree);
+static void c_parser_cilk_grainsize (c_parser *parser);
 static tree c_parser_asm_statement (c_parser *);
 static tree c_parser_asm_operands (c_parser *);
 static tree c_parser_asm_goto_operands (c_parser *);
@@ -4772,6 +4774,12 @@  c_parser_statement_after_labels (c_parser *parser)
 	case RID_FOR:
 	  c_parser_for_statement (parser, false);
 	  break;
+	case RID_CILK_FOR:
+	  if (!flag_enable_cilkplus)
+	    error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_for%>");
+	  else
+	    c_parser_cilk_for_statement (parser, RID_CILK_FOR, NULL_TREE);
+	  break;
 	case RID_CILK_SYNC:
 	  c_parser_consume_token (parser);
 	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -9382,6 +9390,24 @@  c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_cilk_simd_construct (parser);
       return false;
 
+    case PRAGMA_CILK_GRAINSIZE:
+      if (!flag_enable_cilkplus)
+	{
+	  warning (0, "%<#pragma grainsize%> ignored because -fcilkplus is not"
+		   " enabled");
+	  c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+	  return false;
+	}
+      if (context == pragma_external)
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "%<#pragma grainsize%> must be inside a function");
+	  c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+	  return false;
+	}
+      c_parser_cilk_grainsize (parser);
+      return false;
+
     default:
       if (id < PRAGMA_FIRST_EXTERNAL)
 	{
@@ -13566,22 +13592,24 @@  c_parser_cilk_all_clauses (c_parser *parser)
    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).
-
+   CLAUSES_OR_GRAIN is used to pass Clauses or Grain for <#pragma simd> and
+   _Cilk_for, respectively.
+   
    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.  */
+   previously parsed.  For _Cilk_for, this will be the GRAIN that user passes
+   in through a pragma.  If none is passed in, then this field is NULL.  */
    
 static void
 c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
-			     tree clauses)
+			     tree clauses_or_grain)
 {
   tree init, decl,  cond, stmt;
   tree block, incr, save_break, save_cont, body;
-  location_t loc;
   bool fail = false;
+  tree clauses = (for_keyword == RID_FOR) ? clauses_or_grain : NULL_TREE;
+  tree grain =  (for_keyword == RID_CILK_FOR) ? clauses_or_grain : NULL_TREE;
 
-  gcc_assert (/*for_keyword == RID_CILK_FOR || */for_keyword == RID_FOR);
+  gcc_assert (for_keyword == RID_CILK_FOR || for_keyword == RID_FOR);
 
   if (!c_parser_next_token_is_keyword (parser, for_keyword))
     {
@@ -13592,8 +13620,8 @@  c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
       return;
     }
 
-  loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
+  location_t loc = c_parser_peek_token (parser)->location;
 
   block = c_begin_compound_stmt (true);
 
@@ -13606,8 +13634,14 @@  c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
   /* Parse the initialization declaration.  */
   if (c_parser_next_tokens_start_declaration (parser))
     {
+      vec<c_token> none_clauses = vNULL;
+      c_token eof_token;
+      memset (&eof_token, 0, sizeof (eof_token));
+      eof_token.type = CPP_EOF;
+      none_clauses.safe_push (eof_token);
+      none_clauses.safe_push (eof_token);
       c_parser_declaration_or_fndef (parser, true, false, false,
-				     false, false, NULL, vNULL);
+				     false, false, NULL, none_clauses);
       decl = check_for_loop_decls (loc, flag_isoc99);
       if (decl == NULL)
 	goto error_init;
@@ -13653,8 +13687,7 @@  c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
   if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
     {
       location_t cond_loc = c_parser_peek_token (parser)->location;
-      struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
-							    NULL);
+      struct c_expr cond_expr = c_parser_binary_expression (parser, NULL, NULL);
 
       cond = cond_expr.value;
       cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
@@ -13691,6 +13724,9 @@  c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
       if (for_keyword == RID_FOR)
 	c_finish_cilk_simd_loop (loc, decl, init, cond, incr, body, NULL,
 				 clauses, /*scan_body=*/true);
+      else
+	c_finish_cilk_for_loop (loc, decl, init, cond, incr, body, grain,
+				false, false);
     }
 
   stmt = c_end_compound_stmt (loc, block, true);
@@ -13699,6 +13735,48 @@  c_parser_cilk_for_statement (c_parser *parser, enum rid for_keyword,
   c_cont_label = save_cont;
 }
 
+/* This function helps parse the grainsize pragma available in the Cilkplus 
+   port. Here is the correct syntax of this pragma: 
+	    #pragma cilk grainsize = <EXP> 
+ */
+
+static void
+c_parser_cilk_grainsize (c_parser *parser)
+{
+  extern tree convert_to_integer (tree, tree);
+  
+  c_parser_consume_pragma (parser);
+
+  if (c_parser_require (parser, CPP_EQ, "expected %<=%>") != 0)
+    {
+      struct c_expr g_expr = c_parser_binary_expression (parser, NULL, NULL);
+      if (g_expr.value && TREE_CODE (g_expr.value) == C_MAYBE_CONST_EXPR)
+	{
+	  error_at (input_location, "cannot convert grain to long integer.\n");
+	  c_parser_skip_to_pragma_eol (parser);
+	}   
+      else if (g_expr.value && g_expr.value != error_mark_node)
+	{
+	  c_parser_skip_to_pragma_eol (parser);
+	  c_token *token = c_parser_peek_token (parser);
+	  if (token && token->type == CPP_KEYWORD
+	      && token->keyword == RID_CILK_FOR)
+	    {
+	      tree grain = convert_to_integer (long_integer_type_node,
+					       g_expr.value);
+	      if (grain && grain != error_mark_node) 
+		c_parser_cilk_for_statement (parser, RID_CILK_FOR, grain);
+	    }
+	  else
+	    warning (0, "grainsize pragma is not followed by %<_Cilk_for%>");
+	}
+      else
+	c_parser_skip_to_pragma_eol (parser);
+    }
+  else
+    c_parser_skip_to_pragma_eol (parser);
+}
+
 /* Main entry point for parsing Cilk Plus <#pragma simd> for
    loops.  */
 
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c4dfc3b..55f2a7a 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -684,4 +684,7 @@  extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
 extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
 extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
 
+/* In c-cilk.c */
+extern int c_gimplify_cilk_for (tree *, gimple_seq *, gimple_seq *);
+
 #endif /* ! GCC_C_TREE_H */
diff --git a/gcc/cilk-builtins.def b/gcc/cilk-builtins.def
index 8634194..a279a93 100644
--- a/gcc/cilk-builtins.def
+++ b/gcc/cilk-builtins.def
@@ -31,3 +31,5 @@  DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNC, "__cilkrts_sync")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_LEAVE_FRAME, "__cilkrts_leave_frame")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_POP_FRAME, "__cilkrts_pop_frame")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SAVE_FP, "__cilkrts_save_fp_ctrl_state")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_FOR_32, "__cilkrts_cilk_for_32")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_FOR_64, "__cilkrts_cilk_for_64")
\ No newline at end of file
diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c
index 216c7d4..92b757b 100644
--- a/gcc/cilk-common.c
+++ b/gcc/cilk-common.c
@@ -69,7 +69,6 @@  cilk_arrow (tree frame_ptr, int field_number, bool volatil)
 		   field_number, volatil);
 }
 
-
 /* This function will add FIELD of type TYPE to a defined built-in 
    structure.  *NAME is the name of the field to be added.  */
 
@@ -104,6 +103,27 @@  install_builtin (const char *name, tree fntype, enum built_in_function code,
   return fndecl;
 }
 
+/* Returns a FUNCTION_DECL of type TYPE whose name is *NAME.  */
+
+static tree
+cilk_declare_looper (const char *name, tree type, enum built_in_function code)
+{
+  tree cb, ft, fn;
+
+  cb = build_function_type_list (void_type_node,
+                                 ptr_type_node, type, type,
+                                 NULL_TREE);
+  cb = build_pointer_type (cb);
+  ft = build_function_type_list (void_type_node,
+                                 cb, ptr_type_node, type,
+                                 integer_type_node, NULL_TREE);
+  fn = install_builtin (name, ft, code, false);
+  TREE_NOTHROW (fn) = 0;
+
+  return fn;
+}
+
+
 /* Creates and initializes all the built-in Cilk keywords functions and three
    structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker.
    Detailed information about __cilkrts_stack_frame and
@@ -267,6 +287,17 @@  cilk_init_builtins (void)
   cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", 
 					 fptr_fun, BUILT_IN_CILK_SAVE_FP,
 					 false);
+
+  /* __cilkrts_cilk_for_32 (...);  */
+  cilk_for_32_fndecl = cilk_declare_looper ("__cilkrts_cilk_for_32",
+					    unsigned_intSI_type_node,
+				       	    BUILT_IN_CILK_FOR_32);
+
+
+  /* __cilkrts_cilk_for_64 (...);  */
+  cilk_for_64_fndecl = cilk_declare_looper ("__cilkrts_cilk_for_64",
+					    unsigned_intDI_type_node,
+					    BUILT_IN_CILK_FOR_64);
 }
 
 /* Get the appropriate frame arguments for CALL that is of type CALL_EXPR.  */
diff --git a/gcc/cilk.h b/gcc/cilk.h
index 99b4d78..acdfb9c 100644
--- a/gcc/cilk.h
+++ b/gcc/cilk.h
@@ -40,6 +40,8 @@  enum cilk_tree_index  {
   CILK_TI_F_POP,                      /* __cilkrts_pop_frame (...).  */
   CILK_TI_F_RETHROW,                  /* __cilkrts_rethrow (...).  */
   CILK_TI_F_SAVE_FP,                  /* __cilkrts_save_fp_ctrl_state (...).  */
+  CILK_TI_F_LOOP_32,                  /* __cilkrts_cilk_for_32 (...).  */
+  CILK_TI_F_LOOP_64,                  /* __cilkrts_cilk_for_64 (...).  */
   /* __cilkrts_stack_frame struct fields.  */
   CILK_TI_FRAME_FLAGS,                /* stack_frame->flags.  */
   CILK_TI_FRAME_PARENT,               /* stack_frame->parent.  */
@@ -65,6 +67,140 @@  enum cilk_tree_index  {
   CILK_TI_MAX
 };
 
+enum add_variable_type {
+    /* Reference to previously-defined variable.  */
+    ADD_READ,
+    /* Definition of a new variable in inner-scope.  */
+    ADD_BIND,
+    /* Write to possibly previously-defined variable.  */
+    ADD_WRITE
+};
+
+enum cilk_block_type {
+    /* Indicates a _Cilk_spawn block.  30 was an arbitary number picked for 
+       ease of debugging.  */
+    CILK_BLOCK_SPAWN = 30,
+    /* Indicates _Cilk_for statement block.  */
+    CILK_BLOCK_FOR
+};
+
+struct wrapper_data
+{
+  /* Kind of function to be created.  */
+  enum cilk_block_type type;
+  /* Signature of helper function.  */
+  tree fntype;
+  /* Containing function.  */
+  tree context;
+  /* Disposition of all variables in the inner statement.  */
+  struct pointer_map_t *decl_map;
+  /* True if this function needs a static chain.  */
+  bool nested;
+  /* Arguments to be passed to wrapper function, currently a list.  */
+  tree arglist;
+  /* Argument types, a list.  */
+  tree argtypes;
+  /* Incoming parameters.  */
+  tree parms;
+  /* Outer BLOCK object.  */
+  tree block;
+};
+
+/* This structure holds all the important information necessary for decomposing
+   a cilk_for statement.  */
+
+struct cilk_for_desc
+{
+  /* Location of the _Cilk_for statement.  */
+  location_t loc;
+
+  /* Information about the wrapper/nested function for _Cilk_for.  */ 
+  struct wrapper_data wd;
+
+  /* Does the loop body trigger undefined behavior at runtime?  */
+  bool invalid;
+
+  /* Indicates if the parent function is a nested function (C++ only).  */
+  bool nested_ok;
+
+  /* Is the loop control variable a RECORD_TYPE?  */
+  bool iterator;
+
+  /* Does the loop range include its upper bound?  */
+  bool inclusive;
+
+  /* Does the loop control variable, after converting pointer to
+     machine address and taking into account sizeof pointed to
+     type, increment or decrement by (plus or minus) one?  */
+  bool exactly_one;
+
+  /* Is the increment stored in this structure to be added (+1)
+     or subtracted (-1)? */
+  signed char incr_sign;
+
+  /* Direction is +/-1 if the increment is known to be exactly one
+     in the user-visible units, +/-2 if the sign is known but the
+     value is not known to be one, and zero if the sign is not known
+     at compile time.  */
+  signed char direction;
+
+  /* Loop upper bound.  END_EXPR is the tree for the loop bound.
+     END_VAR is either END_EXPR or a VAR_DECL holding the stabilized
+     value, if computation of the value has side effects.  */
+  tree end_expr, end_var;
+
+  /* The originally-declared loop control variable.  */
+  tree var;
+
+  /* Lower bound of the loop if it is constant enough.
+     With a constant lower bound the loop body may not
+     need to use the static chain to compute the iterator
+     value.  */
+  tree lower_bound;
+
+  /* Several types:
+
+     The declared type of the loop control variable,
+     T1 in the cilk_for spec.
+
+     The type of the loop count and argument to loop body, currently
+     always unsigned long.  (If pointers are wider, we will need a
+     pointer-sized type.)
+
+     The static type of end, T2 in the cilk_for spec.
+
+     The difference type T3 of T1-T1, which is the same as T1 for
+     integral types.  The difference type may not be wider than the
+     count type.  For integers subtraction is done in count_type
+     in case difference_type can't hold the range.
+
+     If integral, the type of the increment is known to be no wider
+     than var_type otherwise the truncation in
+     VAR = (shorter)((longer)VAR + INCR)
+     would have been rejected.  */
+  tree var_type, count_type, difference_type;
+  tree incr;
+  tree cond;
+  /* The originally-declared body of the loop.  */
+  tree body;
+
+  /* Grainsize set by the user.  */
+  tree grain;
+
+  /* Context argument to generated function, if not (fdesc fn 1).  */
+  tree ctx_arg;
+
+  /* The number of loop iterations, in case the generated function
+     needs to know.  */
+  tree count;
+
+  /* Variables of the generated function.  */
+  tree ctx_parm, min_parm, max_parm;
+
+  /* Copy of the induction variable, but at different function context.  */
+  tree var2;
+};
+
 extern GTY (()) tree cilk_trees[CILK_TI_MAX];
 
 #define cilk_worker_fndecl            cilk_trees[CILK_TI_F_WORKER]
@@ -77,6 +213,8 @@  extern GTY (()) tree cilk_trees[CILK_TI_MAX];
 #define cilk_rethrow_fndecl           cilk_trees[CILK_TI_F_RETHROW]
 #define cilk_pop_fndecl               cilk_trees[CILK_TI_F_POP]
 #define cilk_save_fp_fndecl           cilk_trees[CILK_TI_F_SAVE_FP]
+#define cilk_for_32_fndecl            cilk_trees[CILK_TI_F_LOOP_32]
+#define cilk_for_64_fndecl            cilk_trees[CILK_TI_F_LOOP_64]
 
 #define cilk_worker_type_fndecl       cilk_trees[CILK_TI_WORKER_TYPE]
 #define cilk_frame_type_decl          cilk_trees[CILK_TI_FRAME_TYPE]
@@ -90,6 +228,7 @@  extern tree cilk_dot (tree, int, bool);
 extern void cilk_init_builtins (void);
 extern void gimplify_cilk_sync (tree *, gimple_seq *);
 extern tree cilk_call_setjmp (tree);
+
 /* Returns true if Cilk Plus is enabled and if F->cilk_frame_decl is not
    NULL_TREE.  */
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 951d9f6..dbb05b2 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -7256,6 +7256,11 @@  gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	    }
 	  break;
 
+	case CILK_FOR_STMT:
+	  ret = (enum gimplify_status)
+	    lang_hooks.cilkplus.gimplify_cilk_for (expr_p, pre_p, post_p);
+	  break;
+
 	case CILK_SPAWN_STMT:
 	  gcc_assert 
 	    (fn_contains_cilk_spawn_p (cfun) 
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 411cf74..e9c46b2 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -219,11 +219,13 @@  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
 #define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN lhd_gimplify_expr
+#define LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR lhd_gimplify_expr
 
 #define LANG_HOOKS_CILKPLUS {			\
   LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP,	\
   LANG_HOOKS_CILKPLUS_FRAME_CLEANUP,		\
-  LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN            \
+  LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN,           \
+  LANG_HOOKS_CILKPLUS_GIMPLIFY_CILK_FOR         \
 }
 
 #define LANG_HOOKS_DECLS { \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 9539e7d..fe8e440 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -154,6 +154,11 @@  struct lang_hooks_for_cilkplus
      status, but as mentioned in a previous comment, we can't see that type 
      here, so just return an int.  */
   int (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *);
+
+  /* Function to gimplify a _Cilk_for statement.  Returns enum gimplify
+     status, but as mentioned in a previous comment, we can't see that type 
+     here, so just return an int.  */
+  int (*gimplify_cilk_for) (tree *, gimple_seq *, gimple_seq *);
 };
 
 /* Language hooks related to decls and the symbol table.  */
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk-for.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk-for.c
new file mode 100644
index 0000000..caab055
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk-for.c
@@ -0,0 +1,34 @@ 
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+int main(int argc, char **argv)
+{
+  char Array1[26], Array2[26];
+  char Array1_Serial[26], Array2_Serial[26];
+  
+  int ii = 0, error = 0;
+  for (ii = 0; ii < 26; ii++)  
+    { 
+      Array1[ii] = 'A'+ii;
+      Array1_Serial[ii] = 'A'+ii;
+    }
+  for (ii = 0; ii < 26; ii++)
+    {
+      Array2[ii] = 'a'+ii;
+      Array2_Serial[ii] = 'a'+ii;
+    }
+  ii = 0;
+  _Cilk_for (ii = 0 ; ii < 26; ii++) 
+    Array1[ii] = Array2[ii];
+
+  for (ii = 0; ii < 26; ii++)
+    Array1_Serial[ii] = Array2_Serial[ii];
+
+  for (ii = 0; ii < 26; ii++)  {
+    if (Array1_Serial[ii] != Array1[ii])  { 
+	error = 1; 
+    }
+  }
+  return error;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_decr.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_decr.c
new file mode 100644
index 0000000..e45b557
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_decr.c
@@ -0,0 +1,44 @@ 
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -w" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#define ARRAY_SIZE 1000
+
+int a[ARRAY_SIZE];
+
+int main(void)
+{
+  int i= 0;
+
+  for (i = 0; i < ARRAY_SIZE; i++)
+    a[i] = 0;
+  
+  _Cilk_for (i = (ARRAY_SIZE-1); i >= 0; i--) 
+    a[i] = i;
+
+  for (i = 0; i < ARRAY_SIZE; i++)
+    if (a[i] != i)
+      return 1;
+
+  for (i = 0; i < ARRAY_SIZE; i++)
+    a[i] = 0;
+  
+  _Cilk_for (i = (ARRAY_SIZE-1); i >= 0; i -= 1) 
+    a[i] = i;
+
+  for (i = 0; i < ARRAY_SIZE; i++)
+    if (a[i] != i)
+      return 1;
+
+  for (i = 0; i < ARRAY_SIZE; i++)
+    a[i] = 0;
+  
+  _Cilk_for (i = (ARRAY_SIZE-1); i >= 0; --i) 
+    a[i] = i;
+
+  for (i = 0; i < ARRAY_SIZE; i++)
+    if (a[i] != i)
+      return 1;
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_errors.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_errors.c
new file mode 100644
index 0000000..022513f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_errors.c
@@ -0,0 +1,64 @@ 
+struct foo
+{
+  int x,y,z;
+  char q;
+};
+
+int main (void)
+{
+  int q = 0, ii = 0, jj = 0;
+  volatile int vii = 0;
+  static int sii = 0;
+  register int rii = 0;
+  extern int eii;
+  struct foo something, nothing;
+  float fii = 0;
+  _Cilk_for (ii; ii < 10; ii++) /* { dg-error " expected induction variable initialization" } */
+    q = 5;
+
+  _Cilk_for (; ii < 10; ii++) /* { dg-error "expected induction variable initialization" } */
+    q = 2;
+
+  _Cilk_for (ii = 0; ; ii++) /* { dg-error "missing condition" } */
+    q = 2;
+
+  _Cilk_for (ii = 0; ii < 10, jj < 10; ii++)  /* { dg-error "expected ';' before ',' token" } */
+    q = 5;
+
+  _Cilk_for (ii = 0; ii < 10; ) /* { dg-error "missing increment" } */
+    q = 5;
+
+  _Cilk_for (ii = 0, jj = 0; ii < 10; ii++) /* { dg-error "expected ';' before ',' token" } */
+    q = 5;
+
+  _Cilk_for (vii = 0; vii < 10; vii++) /* { dg-error "induction variable cannot be volatile" } */
+    q = 5;
+
+  _Cilk_for (sii = 0; sii < 10; sii++) /* { dg-error "induction variable cannot be static" } */
+    q = 5;
+
+  _Cilk_for (rii = 0; rii < 10; rii++) /* { dg-error "induction variable cannot be declared register" } */
+    q = 5;
+
+  _Cilk_for (eii = 0; eii < 10; eii++)  /* { dg-error "induction variable cannot be extern" } */
+    q = 5;
+
+  _Cilk_for (something = nothing; ii < 10; ii++) /* { dg-error "induction variable must be of integral or" } */
+    q = 5;
+
+  _Cilk_for (fii = 3.47; fii < 5.23; ii++) /* { dg-error "induction variable must be of integral or pointer type" } */
+    q = 5;
+
+  _Cilk_for (ii = 0; 10 > jj; ii++) /* { dg-error "invalid controlling predicate" } */
+    q = 5;
+
+  _Cilk_for (ii = 0; ii < 10; ii >> 1) /* { dg-error "invalid increment expression" } */
+    q = 5;
+
+  _Cilk_for (ii = 10; ii >= 0; ii--) /* This is OK!  */
+    q = 5;
+
+  _Cilk_for (ii; ii < 10; ii++) /* { dg-error "expected induction variable initialization" } */
+    q = 5;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_grain.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_grain.c
new file mode 100644
index 0000000..4c86bf6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_grain.c
@@ -0,0 +1,34 @@ 
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -w" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+int grain_value = 2;
+int main (void)
+{
+  int Array1[200], Array1_Serial[200];
+  int ii = 0; 
+
+  for (ii = 0; ii < 200; ii++)
+    {
+      Array1_Serial[ii] = 2;
+      Array1[ii] = 1;
+    }
+
+#pragma cilk grainsize = 2
+  _Cilk_for (ii = 0; ii < 200; ii++)
+    Array1[ii] = 2;
+
+  for (ii = 0; ii < 200; ii++)
+    if (Array1[ii] != Array1_Serial[ii])
+      return (ii+1);
+
+#pragma cilk grainsize = grain_value
+  _Cilk_for (ii = 0; ii < 200; ii++) 
+    Array1[ii] = 2;
+
+  for (ii = 0; ii < 200; ii++)
+    if (Array1[ii] != Array1_Serial[ii])
+      return (ii+1);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_grain_errors.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_grain_errors.c
new file mode 100644
index 0000000..36d75df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_grain_errors.c
@@ -0,0 +1,31 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Wall -fcilkplus" } */
+char Array1[26];
+
+#pragma cilk grainsize = 2 /* { dg-error "must be inside a function" } */
+
+int main(int argc, char **argv)
+{
+  int ii = 0;
+
+/* This is OK.  */
+#pragma cilk grainsize = 2
+  _Cilk_for (ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+#pragma cilk grainsize 2 /* { dg-error "expected '=' before numeric constant" } */
+  _Cilk_for (ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+#pragma cilk grainsiz = 2 /* { dg-warning "ignoring #pragma cilk grainsiz" } */
+  _Cilk_for (ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+
+/* This is OK, it will do a type conversion to long int.  */
+#pragma cilk grainsize = 0.5 
+  _Cilk_for (ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_ptr_iter.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_ptr_iter.c
new file mode 100644
index 0000000..8eec6be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_ptr_iter.c
@@ -0,0 +1,28 @@ 
+/* { dg-do run  { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -w" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+/* <feature> loop control variable must have integer, pointer or class type
+   </feature>
+*/
+
+#define ARRAY_SIZE 10000
+int a[ARRAY_SIZE];
+
+int main(void)
+{ 
+  int *aa = 0;
+  int ii = 0;
+
+  for (ii =0; ii < ARRAY_SIZE; ii++)
+    a[ii] = 5;
+
+  _Cilk_for(aa = a; aa < a + ARRAY_SIZE; aa++) 
+    *aa = 0;
+
+  for (ii = 0; ii < ARRAY_SIZE; ii++) 
+    if (a[ii] != 0) 
+      return 1;
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_warning.c b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_warning.c
new file mode 100644
index 0000000..f39eb7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_warning.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+int main (void)
+{
+  int ii = 0, q = 2;
+  _Cilk_for (ii = 0; ii < 10; ii++) /* { dg-warning "loop body modifies control variable" } */
+    ii += q;
+  
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
index 7407e8e..edab8eb 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
@@ -60,5 +60,12 @@  if { [check_effective_target_lto] } {
     dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus $ALWAYS_CFLAGS" " "
 }
 
-
+dg-runtest [lsort [glob -nocomplain $srcdir/gcc.dg/cilk-plus/CK/*.c]] " -g -fcilkplus $ALWAYS_CFLAGS " " "
+dg-runtest [lsort [glob -nocomplain $srcdir/gcc.dg/cilk-plus/CK/*.c]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/gcc.dg/cilk-plus/CK/*.c]] " -O2 -std=c99 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/gcc.dg/cilk-plus/CK/*.c]] " -O2 -ftree-vectorize -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/gcc.dg/cilk-plus/CK/*.c]] " -O3 -g -fcilkplus $ALWAYS_CFLAGS" " "
+if { [check_effective_target_lto] } {
+dg-runtest [lsort [glob -nocomplain $srcdir/gcc.dg/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus $ALWAYS_CFLAGS" " "
+}
 dg-finish
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 7fe849d..de2a24b 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2661,6 +2661,29 @@  dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_string (buffer, "_Cilk_sync");
       break;
 
+    case CILK_FOR_STMT:
+      if (CILK_FOR_GRAIN (node))
+	{
+	  pp_string (buffer, "#pragma cilk grainsize = ");
+	  dump_generic_node (buffer, CILK_FOR_GRAIN (node), spc, flags, false); 
+	  newline_and_indent (buffer, spc);
+	}
+      pp_string (buffer, "_Cilk_for (");
+      dump_generic_node (buffer, CILK_FOR_INIT (node), spc, flags, false);
+      pp_string (buffer, "; ");
+      dump_generic_node (buffer, CILK_FOR_COND (node), spc, flags, false);
+      pp_string (buffer, "; ");
+      dump_generic_node (buffer, CILK_FOR_EXPR (node), spc, flags, false);
+      pp_string (buffer, ")");
+      newline_and_indent (buffer, spc + 2);
+      pp_left_brace (buffer);
+      newline_and_indent (buffer, spc + 4);
+      dump_generic_node (buffer, CILK_FOR_BODY (node), spc + 4, flags, false);
+      newline_and_indent (buffer, spc + 2);
+      pp_right_brace (buffer);
+      is_expr = false;
+      break;
+
     default:
       NIY;
     }
diff --git a/gcc/tree.def b/gcc/tree.def
index 8eecba7..9c0bfe2 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1285,6 +1285,16 @@  DEFTREECODE (CILK_SPAWN_STMT, "cilk_spawn_stmt", tcc_statement, 1)
 /* Cilk Sync statement: Does not have any operands.  */
 DEFTREECODE (CILK_SYNC_STMT, "cilk_sync_stmt", tcc_statement, 0)
 
+/* Cilk for statement
+   Operand 0 is the initializer.
+   Operand 1 is the loop terminating condition.
+   Operand 2 is the increment/decrement expression.
+   Operand 3 is the loop-body.
+   Operand 4 is the scope.
+   Operand 5 is the induction variable.
+   Operand 6 is the grain that is passed in through a pragma.  */
+DEFTREECODE (CILK_FOR_STMT, "cilk_for_stmt", tcc_statement, 7)
+
 /*
 Local variables:
 mode:c
diff --git a/gcc/tree.h b/gcc/tree.h
index e58b3a5..000a448 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -804,6 +804,15 @@  extern void omp_clause_range_check_failed (const_tree, const char *, int,
 /* Cilk keywords accessors.  */
 #define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0)
 
+/* CILK_FOR_STMT accessors.  */
+#define CILK_FOR_INIT(NODE)     TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 0)
+#define CILK_FOR_COND(NODE)     TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 1)
+#define CILK_FOR_EXPR(NODE)     TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 2)
+#define CILK_FOR_BODY(NODE)     TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 3)
+#define CILK_FOR_SCOPE(NODE)    TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 4)
+#define CILK_FOR_VAR(NODE)      TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 5)
+#define CILK_FOR_GRAIN(NODE)    TREE_OPERAND (CILK_FOR_STMT_CHECK (NODE), 6)
+
 /* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is
    passed by invisible reference (and the TREE_TYPE is a pointer to the true
    type).  */