diff mbox

_Cilk_for for C and C++

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

Commit Message

Iyer, Balaji V Nov. 18, 2013, 9:50 p.m. UTC
Hello Everyone,
     Please see my comment below:

> -----Original Message-----
> From: Aldy Hernandez [mailto:aldyh@redhat.com]
> Sent: Friday, November 15, 2013 4:51 PM
> To: Iyer, Balaji V
> Cc: gcc-patches@gcc.gnu.org; Jeff Law; Jason Merrill (jason@redhat.com);
> rth@redhat.com
> Subject: Re: [PATCH] _Cilk_for for C and C++
> 
> 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.

	Attached, please find a refreshed patches (one for C and 1 for C++).  The trunk was "diffed" after Aldy's check in of pragma simd was in. So, now this patch is only dependent on _Cilk_spawn and _Cilk_sync (mostly for execution of tests). They are tested on x86_64 and works successfully.

Here are the fixed Changelog entries (C related changelogs are given first then C++):

C- Related Changes
=====================================================================================
gcc/ChangeLog.
2013-11-18  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-18  Balaji V. Iyer  <balaji.v.iyer@intel.com>

	* c-cilkplus.c (c_check_cilk_loop_incr): New function.
	(c_validate_cilk_plus_loop): Likewise.
	(c_check_cilk_loop): Likewise.
	(c_finish_cilk_for_loops): Likewise.
	(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.
	(c_validate_cilk_loop): Likewise.
	(c_check_cilk_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-18  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-18  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.


=============================================================================================

Here are the C++ related ChangeLogs:

gcc/cp/ChangeLog.
2013-11-18  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-18  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.

Thanks,

Balaji V. Iyer.

diff --git a/gcc/cp/cp-cilk.c b/gcc/cp/cp-cilk.c
old mode 100644
new mode 100755
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 c464719..b40e9a6 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -269,6 +269,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
@@ -1121,6 +1138,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 351158e..ee045b8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5686,6 +5686,10 @@ 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 finish_cilk_for_cond                (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);
@@ -6192,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 29be9a8..0b5621d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -235,6 +235,10 @@ static tree cp_literal_operator_id
 
 static void cp_parser_cilk_simd
   (cp_parser *, cp_token *);
+static tree cp_parser_cilk_for
+  (cp_parser *, tree);
+static void cp_parser_cilk_grainsize
+  (cp_parser *, cp_token *);
 static bool cp_parser_omp_declare_reduction_exprs
   (tree, cp_parser *);
 
@@ -2060,7 +2064,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 +9355,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 +10511,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, NULL_TREE);
+      break;
+
     default:
       cp_parser_error (parser, "expected iteration-statement");
       statement = error_mark_node;
@@ -10624,9 +10641,15 @@ 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_SIMD_FOR:
 	  error_at (token->location, "break statement used with Cilk Plus for loop");
 	  break;
+
+	case IN_CILK_FOR_STMT:
+	  error_at (token->location,
+		    "break statement used in _Cilk_for loop body");
+	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
@@ -10642,6 +10665,7 @@ cp_parser_jump_statement (cp_parser* parser)
 		    "continue statement within %<#pragma simd%> loop body");
 	  /* Fall through.  */
 	case IN_ITERATION_STMT:
+	case IN_CILK_FOR_STMT:
 	case IN_OMP_FOR:
 	  statement = finish_continue_stmt ();
 	  break;
@@ -11188,7 +11212,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
@@ -16439,7 +16463,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;
@@ -16447,7 +16472,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;
@@ -16584,7 +16611,8 @@ cp_parser_init_declarator (cp_parser* parser,
 	      DECL_STRUCT_FUNCTION (decl)->function_start_locus
 		= func_brace_location;
 	    }
-
+	  if (init)
+	    *init = initializer;
 	  return decl;
 	}
     }
@@ -16819,6 +16847,8 @@ cp_parser_init_declarator (cp_parser* parser,
 	finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
     }
 
+  if (init)
+    *init = initializer;
   return decl;
 }
 
@@ -22984,6 +23014,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]
@@ -31253,6 +31284,21 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       cp_parser_cilk_simd (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);
@@ -31569,6 +31615,213 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
   return;
 }
 
+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, 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, tree grain)
+{
+  bool valid = true;
+  tree cond = NULL_TREE;
+  tree incr_expr = NULL_TREE;
+  tree init = NULL_TREE;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  tree scope = begin_for_scope (&init); 
+  tree 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);
+      return error_mark_node;
+    }
+
+  /* Parse initialization.  */ 
+  tree decl = cp_parser_cilk_for_init_statement (parser, &init);
+    
+  if (decl == error_mark_node)
+    valid = false;
+  else if (!decl || (TREE_CODE (decl) != VAR_DECL
+		     && TREE_CODE (decl) != DECL_EXPR))
+    {
+      error_at (loc, "_Cilk_for loop initializer does not declare a variable");
+      valid = false;
+      decl = error_mark_node;
+    }
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+    {
+      error_at (loc, "_Cilk_for loop initializer cannot have multiple variable"
+		" declarations");
+      cp_parser_skip_to_end_of_statement (parser);
+      valid = false;
+    }
+
+  if (!valid)
+    /* Skip to the semicolon ending the init.  */
+    cp_parser_skip_to_end_of_statement (parser);
+  else
+    {
+      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))
+    return error_mark_node;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    {
+      error_at (loc, "missing condition");
+      cond = error_mark_node;
+    }
+  else
+    { 
+      cond = cp_parser_condition (parser);
+      cond = finish_cilk_for_cond (cond); 
+      CILK_FOR_COND (statement) = cond;
+    }
+
+  if (cond == error_mark_node)
+    valid = false;
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+  /* Parse increment.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+    {
+      error_at (loc, "missing increment");
+      incr_expr = error_mark_node;
+    }
+  else
+    incr_expr = cp_parser_expression (parser, false, NULL);
+  if (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);
+      valid = false;
+    }
+  
+  if (!valid)
+    {
+      gcc_assert (sorrycount || errorcount);
+      return error_mark_node;
+    }
+  
+  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;
+  
+  CILK_FOR_GRAIN (statement) = grain;
+  statement = finish_cilk_for_stmt (statement);
+
+  /* Check if the body satisfies all the requirement of _Cilk_for.
+     If invalid, then just return error_mark_node.  */
+  if (statement == error_mark_node
+      || !cpp_validate_cilk_plus_loop (CILK_FOR_BODY (statement)))
+    return error_mark_node;
+  return statement;
+}
+
 /* Create an identifier for a generic parameter type (a synthesized
    template parameter implied by `auto' or a concept identifier). */
 
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index e26e350..8d1ce44 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -302,6 +302,8 @@ typedef struct GTY(()) cp_parser {
 #define IN_IF_STMT             16
 #define IN_CILK_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 1b34434..302163f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13335,6 +13335,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 5d68250..23565ae 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -826,7 +826,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.  */
 
@@ -899,7 +900,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)
@@ -926,7 +927,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
@@ -6663,6 +6667,18 @@ finish_omp_cancellation_point (tree clauses)
   finish_expr_stmt (stmt);
 }
 
+
+/* Perform any canonicalization of the conditional in a Cilk for loop.  */
+tree
+finish_cilk_for_cond (tree cond)
+{
+  if (!processing_template_decl)
+    return cp_truthvalue_conversion (cond);
+  else
+    return cond;
+}
+
+
 /* Begin a __transaction_atomic or __transaction_relaxed statement.
    If PCOMPOUND is non-null, this is for a function-transaction-block, and we
    should create an extra compound stmt.  */
@@ -10615,4 +10631,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())
+	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..b597764
--- /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 "iteration 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)
+    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])
+      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

Jason Merrill Nov. 22, 2013, 4:45 p.m. UTC | #1
On 11/18/2013 04:50 PM, Iyer, Balaji V wrote:
> +  int flags = LOOKUP_PROTECT | LOOKUP_ONLYCONVERTING;

Why not LOOKUP_NORMAL? LOOKUP_ONLYCONVERTING isn't relevant in this context.

> +  tree exp = build_new_op (EXPR_LOCATION (op1), code, flags, op0, op1,
> +			   NULL_TREE, NULL, 0);

Use tf_none instead of 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;

This doesn't make sense to me.  build_x_modify_expr takes codes like 
PLUS_EXPR and then does an assignment afterward; we don't want to 
quietly do += just because there's some error with the evaluation of the 
+ operation.  What is this code trying to do?

> +/* 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.  */

This doesn't explain what VAR2 is.  And it seems like you're also using 
LOW as the increment?

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

Why assign 0 if you're going to immediately assign low afterwards?

> +  /* 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.

Why do you need to resolve them by hand?  It looks like break isn't even 
allowed.

> +     b. C++ doesn't provide a c_finish_loop function like C does.  */

Why is that important?

>    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.  */

How is this different from a normal for-init-statement?  Nothing seems 
to use it.

Jason
Jeff Law Nov. 27, 2013, 10:06 p.m. UTC | #2
On 11/18/13 14:50, Iyer, Balaji V wrote:
>
> 	Attached, please find a refreshed patches (one for C and 1 for C++).  The trunk was "diffed" after Aldy's check in of pragma simd was in. So, now this patch is only dependent on _Cilk_spawn and _Cilk_sync (mostly for execution of tests). They are tested on x86_64 and works successfully.
>
> Here are the fixed Changelog entries (C related changelogs are given first then C++):
I'm just getting started on the C stuff.  This likely will be a partial 
review.

First, it looks like you've got a ton of unrelated cleanup work going on 
in c-family/cilk.c.  Function/parameter renaming and the like.  If this 
stuff is important, can it go forward independently?  It's certainly 
hard to find Cilk_for stuff in there with all the unrelated changes 
going on.  Some of the stuff seems to have moved into cilk.h which is 
probably good too, but probably should be separated from the Cilk_for 
support patch as well.


The semantics of cilk_check_loop_difference_type seem a bit odd.  Can 
you explain a bit more how those semantics were choosen?   And given the 
implementation, isn't it impossible for it to return NULL_TREE, meaning 
that check in c_extract_cilk_for_fields is pointless?

Isn't cilk_simplify_tree just used in the validation code?  Can it be 
moved into that file and privatized?  It probably needs a better name 
too.  I have to also admit, it looks pretty bogus to just start 
stripping things like that.  Oh yea, declaring and using tree_ssa_... is 
not OK there, thus it's not ok to use STRIP_USELESS_TYPE_CONVERSION.

In general, could you do a pass over those functions with external 
linkage and if they're only used in one file, move them to that file and 
privatize them?

So Cilk_for has a type?  That's the impression I get by looking at 
cilk_loop_convert.  In reality, I think it's just poorly named.  I've 
got to believe there's something, somewhere that will do equivalent 
conversions for you :-)

There's a mismatch between direction tracking between 
cilk_calc_forward_div_op and cilk_compute_incr_direction.  THe former 
handles -1, the latter never returns it.  I'd probably prefer to see the 
direction information represented as an ENUM anyway.
.
Presumably you're using nested functions to encapsulate the body for the 
Cilk_for loop?  Does the nested function have access to the parent's 
context?

If the verification routines have to stay, then isn't there a lot of 
commonality between (for example) cilk_set_incr_info and 
c_check_cilk_loop_incr?  Anything worth refactoring there?  Probably not 
I guess

I must have missed something -- when can we get a CONTINUE_STMT outside 
a loop body?  See cilk_resolve_continue_stmts.


In c-common.h, you added several prototypes for things in c-cilkplus.c. 
  We're trying to avoid doing that, instead favoring putting them into 
c-cilkplus.h and including that where needed.

Similarly in c-tree.h



Is there any significant sharable code between parsing a normal C for 
statement a a Cilk_for that we could factor out?  What about the 
validation code?  Can any of that be shared with OpenMP?  What about the 
gimplification?

Are the syntatical differences so significant that we can't share any of 
that code?

Any particular reason why the runtime uses different names for the 32bit 
and 64bit Clik_for support?  ISTM you wouldn't ever be binding the 32bit 
and 64bit runtimes into a single application, so you could have just 
called it __cilkrts_cilk_for and be done with it.  I guess it's too late 
to change that now.  Or does the 32/64 split refer to the # bits 
necessary to hold the iteration counter?

vertical whitespace removed after the cilk_arrow function, causing it to 
end up immediately adjacent to the comment for the next function.  I 
suspect this was unintentional.


You define CILK_FOR_STMT and new gimplification routines to handle it. 
Is there any way you can funnel all this through the OpenMP 4 support?

It looks like you've got unrelated cleanups going on in c-family/cilk.c. 
  Function renaming and such.  Is that strictly related to Cilk_for 
support?  Much of it looks independent of Cilk_for support.  Seems to me 
like that should break out and go forward independently.

I'm going to have to look at this some more, but I wanted to give you as 
much feedback as I could before I disappear for the holidays.


jeff
diff mbox

Patch

diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
index 6fa979d..010d39d 100644
--- a/gcc/c-family/c-cilkplus.c
+++ b/gcc/c-family/c-cilkplus.c
@@ -26,8 +26,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "c-common.h"
 
-/* Validate the body of a _Cilk_for construct or a <#pragma simd> for
-   loop.
+/* Validate the body of a <#pragma simd> for loop.
 
    Returns true if there were no errors, false otherwise.  */
 
@@ -91,3 +90,401 @@  c_finish_cilk_clauses (tree clauses)
     }
   return clauses;
 }
+
+/* Helper function for c_check_cilk_for_loop.
+
+   Validate the increment in a _Cilk_for construct or a <#pragma simd>
+   for loop.
+
+   LOC is the location of the `for' keyword.  DECL is the induction
+   variable.  INCR is the original increment expression.
+
+   Returns the canonicalized increment expression for an OMP_FOR_INCR.
+   If there is a validation error, returns error_mark_node.  */
+
+static tree
+c_check_cilk_loop_incr (location_t loc, tree decl, tree incr)
+{
+  tree orig_incr = incr;
+  if (!incr)
+    {
+      error_at (loc, "missing increment");
+      return error_mark_node;
+    }
+
+  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:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+      if (TREE_OPERAND (incr, 0) != decl)
+	break;
+
+      return incr;
+
+    case MODIFY_EXPR:
+      {
+	tree rhs;
+
+	if (TREE_OPERAND (incr, 0) != decl)
+	  break;
+
+	rhs = TREE_OPERAND (incr, 1);
+	if ((TREE_CODE (rhs) == PLUS_EXPR
+	     || TREE_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 incr;
+	else if (TREE_CODE (rhs) == MINUS_EXPR
+		 && TREE_OPERAND (rhs, 0) == decl
+		 && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
+	  return incr;
+	// Otherwise fail because only PLUS_EXPR and MINUS_EXPR are
+	// allowed.
+	break;
+      }
+
+      /* 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 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;
+    }
+
+  error_at (loc, "invalid increment expression");
+  return error_mark_node;
+}
+
+/* Callback for walk_tree to validate the body of a pragma simd loop
+   or _cilk_for loop.
+
+   This function is passed in as a function pointer to walk_tree.  *TP is
+   the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
+   recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
+   is set to false if an error has occured.  */
+
+tree
+c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
+{
+  if (!tp || !*tp)
+    return NULL_TREE;
+
+  bool *valid = (bool *) data;
+
+  switch (TREE_CODE (*tp))
+    {
+    case CALL_EXPR:
+      {
+	tree fndecl = CALL_EXPR_FN (*tp);
+
+	if (TREE_CODE (fndecl) == ADDR_EXPR)
+	  fndecl = TREE_OPERAND (fndecl, 0);
+	if (TREE_CODE (fndecl) == FUNCTION_DECL)
+	  {
+	    if (setjmp_call_p (fndecl))
+	      {
+		error_at (EXPR_LOCATION (*tp),
+			  "calls to setjmp are not allowed within loops "
+			  "annotated with #pragma simd or _Cilk_for loops");
+		*valid = false;
+		*walk_subtrees = 0;
+	      }
+	  }
+	break;
+      }
+
+    case OMP_PARALLEL:
+    case OMP_TASK:
+    case OMP_FOR:
+    case OMP_SIMD:
+    case OMP_SECTIONS:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_MASTER:
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+    case OMP_ATOMIC:
+    case OMP_ATOMIC_READ:
+    case OMP_ATOMIC_CAPTURE_OLD:
+    case OMP_ATOMIC_CAPTURE_NEW:
+      error_at (EXPR_LOCATION (*tp), "OpenMP statements are not allowed "
+		"within loops annotated with #pragma simd");
+      *valid = false;
+      *walk_subtrees = 0;
+      break;
+
+    default:
+      break;
+    }
+  return NULL_TREE;
+}  
+
+/* Validate the body of a _Cilk_for construct or a <#pragma simd> for
+   loop.
+
+   Returns true if there were no errors, false otherwise.  */
+
+static bool
+c_check_cilk_loop_body (tree body)
+{
+  bool valid = true;
+  walk_tree (&body, c_validate_cilk_plus_loop, (void *) &valid, NULL);
+  return valid;
+}
+
+/* Validate a _Cilk_for construct (or a #pragma simd for loop, which
+   has the same syntactic restrictions).
+
+   Returns TRUE if there were no errors, FALSE otherwise.
+
+   LOC is the location of the for.
+   DECL is the controlling variable.
+   COND is the condition.
+
+   INCRP is a pointer the increment expression (in case the increment
+   needs to be canonicalized).
+
+   BODY is the body of the LOOP.
+   SCAN_BODY is true if the body must be checked.  */
+
+static bool
+c_check_cilk_for_loop (location_t loc, tree decl, tree cond, tree *incrp, 
+		       tree body, bool scan_body, bool is_cpp, 
+		       bool proc_templates_p)
+{
+  tree incr = *incrp;
+
+  if (TREE_THIS_VOLATILE (decl))
+    {
+      error_at (loc, "iteration variable cannot be volatile");
+      return false;
+    }
+  if (TREE_STATIC (decl))
+    {
+      error_at (loc, "induction variable cannot be static");
+      return false;
+    }
+  if (DECL_REGISTER (decl))
+    {
+      error_at (loc, "induction variable cannot be declared register");
+      return false;
+    }
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
+      && !POINTER_TYPE_P (TREE_TYPE (decl)))
+    {
+      /* 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.  */
+  if (!cond)
+    {
+      error_at (loc, "missing condition");
+      return false;
+    }
+  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
+      || TREE_CODE (cond) == GE_EXPR)
+    {
+      /* Comparison must either be:
+	   DECL <comparison_operator> EXPR
+	   EXPR <comparison_operator> DECL
+      */
+      if (decl == cilk_simplify_tree (TREE_OPERAND (cond, 0)))
+	cond_ok = true;
+      else if (decl == cilk_simplify_tree (TREE_OPERAND (cond, 1)))
+	{
+	  /* Canonicalize the comparison so the DECL is on the LHS.  */
+	  TREE_SET_CODE (cond,
+			 swap_tree_comparison (TREE_CODE (cond)));
+	  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
+	  TREE_OPERAND (cond, 0) = decl;
+	  cond_ok = true;
+	}
+    }
+
+  /* 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");
+      return false;
+    }
+
+  /* Validate and canonicalize the increment.  */
+  incr = c_check_cilk_loop_incr (loc, decl, incr);
+  if (incr == error_mark_node)
+    return false;
+  *incrp = incr;
+
+  if (scan_body && !c_check_cilk_loop_body (body))
+    return false;
+
+  return true;
+}
+
+/* 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_for_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_for_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;
+}
+
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d7d5cb2..e500b20 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -416,6 +416,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
old mode 100644
new mode 100755
index b931fd6..507f62d
--- 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 '@')  */
@@ -524,6 +524,14 @@  struct GTY(()) c_language_function {
 
 #define building_stmt_list_p() (stmt_list_stack && !stmt_list_stack->is_empty())
 
+/* In c-cilkplus.c */
+extern void cp_finish_cilk_for_loop (tree *, bool);
+extern tree c_validate_cilk_plus_loop (tree *, int *, void *);
+extern bool c_check_cilk_loop (location_t, tree);
+extern tree c_finish_cilk_for_loop (location_t, tree, tree, tree, tree, tree,
+				    tree, bool, bool);
+
 /* Language-specific hooks.  */
 
 /* If non-NULL, this function is called after a precompile header file
@@ -1292,7 +1300,6 @@  extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
 /* In c-cilkplus.c  */
 extern tree c_finish_cilk_clauses (tree);
 extern tree c_validate_cilk_plus_loop (tree *, int *, void *);
-extern bool c_check_cilk_loop (location_t, tree);
 
 /* These #defines allow users to access different operands of the
    array notation tree.  */
@@ -1377,5 +1384,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 029ab1e..7f5f3df 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1390,6 +1390,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
old mode 100644
new mode 100755
index 165348f..a313816
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -35,47 +35,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
@@ -156,8 +115,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);
@@ -283,8 +242,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)
@@ -452,6 +411,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;
@@ -472,15 +433,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;
 
@@ -496,7 +460,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;
@@ -515,8 +479,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
@@ -538,7 +504,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))
     {
@@ -551,7 +517,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);
@@ -560,7 +526,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;
 }
 
@@ -702,14 +668,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)
@@ -996,14 +962,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;
 
@@ -1011,7 +977,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)
     {
@@ -1031,7 +997,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:
@@ -1053,12 +1019,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:
@@ -1067,8 +1033,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:
@@ -1079,9 +1045,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:
@@ -1093,17 +1059,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:
@@ -1111,7 +1077,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;
       }
 
@@ -1119,13 +1085,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:
@@ -1136,11 +1102,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;
       }
 
@@ -1148,17 +1114,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;
       }
 
@@ -1172,32 +1138,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:
@@ -1210,8 +1176,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;
       }
@@ -1227,7 +1193,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);
 	}
     }
 }
@@ -1304,3 +1270,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 100755
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 6f03402..b7fb11a 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 *, 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 *);
@@ -4771,6 +4773,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, NULL_TREE);
+	  break;
 	case RID_CILK_SYNC:
 	  c_parser_consume_token (parser);
 	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -9381,6 +9389,24 @@  c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_cilk_simd (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)
 	{
@@ -13558,6 +13584,174 @@  c_parser_cilk_all_clauses (c_parser *parser)
   return c_finish_cilk_clauses (clauses);
 }
 
+/* Parses a _Cilk_for statement. 
+
+   GRAIN is used to pass the Grain value from <#pragma cilk grainsize>.  If
+   this field is NULL then runtime will find an appropriate grain size
+   (highly recommended!).  */
+  
+static void
+c_parser_cilk_for_statement (c_parser *parser, tree grain)
+{
+  tree init, decl, stmt;
+  tree  body;
+  bool fail = false;
+
+  if (!c_parser_next_token_is_keyword (parser, RID_CILK_FOR))
+    { 
+      c_parser_error (parser, "_Cilk_for statement expected");
+      return;
+    }
+
+  c_parser_consume_token (parser);
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  tree block = c_begin_compound_stmt (true);
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      add_stmt (c_end_compound_stmt (loc, block, true));
+      return;
+    }
+
+  /* Parse the initialization declaration.  */
+  if (c_parser_next_tokens_start_declaration (parser))
+    {
+      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, none_clauses);
+      decl = check_for_loop_decls (loc, flag_isoc99);
+      if (decl == NULL)
+	goto error_init;
+      if (DECL_INITIAL (decl) == error_mark_node)
+	decl = error_mark_node;
+      init = decl;
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME)
+	   && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+    {
+      struct c_expr decl_exp;
+      struct c_expr init_exp;
+      location_t init_loc;
+
+      decl_exp = c_parser_postfix_expression (parser);
+      decl = decl_exp.value;
+
+      c_parser_require (parser, CPP_EQ, "expected %<=%>");
+
+      init_loc = c_parser_peek_token (parser)->location;
+      init_exp = c_parser_expr_no_commas (parser, NULL);
+      init_exp = default_function_array_read_conversion (init_loc,
+							 init_exp);
+      init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+				NOP_EXPR, init_loc, init_exp.value,
+				init_exp.original_type);
+      init = c_process_expr_stmt (init_loc, init);
+
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+    }
+  else
+    {
+    error_init:
+      c_parser_error (parser, "expected induction variable initialization");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      return;
+    }
+
+  /* Parse the loop condition.  */
+  tree cond = NULL_TREE;
+  if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
+    {
+      location_t cond_loc = c_parser_peek_token (parser)->location;
+      struct c_expr cond_expr = c_parser_binary_expression (parser, NULL, NULL);
+
+      cond = cond_expr.value;
+      cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+      cond = c_fully_fold (cond, false, NULL);
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+  /* Parse the increment expression.  */
+  tree incr = NULL_TREE;
+  if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      location_t incr_loc = c_parser_peek_token (parser)->location;
+      incr = c_process_expr_stmt (incr_loc,
+				  c_parser_expression (parser).value);
+    }
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  if (decl == NULL || decl == error_mark_node || init == error_mark_node)
+    fail = true;
+
+  tree save_break = c_break_label;
+  /* Magic number to inform c_finish_bc_stmt() that we are within a
+     Cilk for construct.  */
+  c_break_label = build_int_cst (size_type_node, 2);
+
+  tree save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+
+  if (!fail) 
+    c_finish_cilk_for_loop (loc, decl, init, cond, incr, body, grain, false, 
+			    false);
+
+  stmt = c_end_compound_stmt (loc, block, true);
+  add_stmt (stmt);
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+}
+
+/* This function helps parse the grainsize pragma for a _Cilk_for statement. 
+   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, 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 8e070a3..c5308f4 100644
--- a/gcc/cilk-common.c
+++ b/gcc/cilk-common.c
@@ -70,7 +70,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.  */
 
@@ -105,6 +104,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
@@ -268,6 +288,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 bb50e25..f8b2b9b 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -7246,6 +7246,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..c6d6656
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/CK/cilk_for_errors.c
@@ -0,0 +1,61 @@ 
+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 "iteration 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 (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).  */