This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, Cilk+] CIlk_for enabling in the compiler


Hi!

The patch is another attempt to enable Cilk_for (see eg https://www.cilkplus.org/sites/default/files/open_specifications/Intel_Cilk_plus_lang_spec_1.2.htm) in the GCC compiler.

Bootstrapped and regtested on x86_64.
Is it ok for the trunk?

Thanks,
Igor

Changelogs:

gcc/

2014-08-29  Jakub Jelinek  <jakub@redhat.com>
            Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * cilk-builtins.def (__cilkrts_cilk_for_32): New.
        (__cilkrts_cilk_for_64): Likewise.
        * cilk-common.c (declare_cilk_for_builtin): New function.
        (cilk_init_builtins): Declare __cilkrts_cilk_for_32 and
        __cilkrts_cilk_for_64 bultins.
        * cilk.h (enum cilk_tree_index): Added CILK_TI_F_LOOP_32 and
        CILK_TI_F_LOOP_64.
        (cilk_for_32_fndecl): New define.
        (cilk_for_64_fndecl): Likewise.
        * gimple-pretty-print.c (dump_gimple_omp_for): Correct hadling of
        GF_OMP_FOR_KIND_CILKFOR cases; Added NE_EXPR case.
        * gimple.h (enum gf_mask): Added GF_OMP_FOR_KIND_CILKFOR; adjusted
        GF_OMP_FOR_KIND_MASK, GF_OMP_FOR_SIMD, GF_OMP_FOR_COMBINED,
        GF_OMP_FOR_COMBINED_INTO.
        * gimplify.c (gimplify_scan_omp_clauses): Added
        OMP_CLAUSE__CILK_FOR_COUNT_ case.
        (gimplify_adjust_omp_clauses): Ditto.
        (gimplify_omp_for): Added CILK_FOR case.
        (gimplify_expr): Ditto.
        * omp-low.c: Include cilk.h.
        (extract_omp_for_data): Set appropriate kind for
        GF_OMP_FOR_KIND_CILKFOR; added check for GF_OMP_FOR_KIND_CILKFOR.
        (scan_sharing_clauses): Added OMP_CLAUSE__CILK_FOR_COUNT_ cases.
        (create_omp_child_function_name): Added second argument to handle
        cilk_for case.
        (cilk_for_check_loop_diff_type): New function.
        (expand_cilk_for_call): Likewise.
        (expand_cilk_for): Likewise.
        (create_omp_child_function): Set cilk_for_count; handle the cases when
        it is true; call create_omp_child_function_name with second argument.
        (expand_omp_taskreg): Set is_cilk_for and handle cases when it's true.
        (expand_omp_for): Handle case of GF_OMP_FOR_KIND_CILKFOR.
        * tree-core.h (omp_clause_code): Added OMP_CLAUSE__CILK_FOR_COUNT_.
        * tree-nested.c (convert_nonlocal_omp_clauses): Added
        OMP_CLAUSE__CILK_FOR_COUNT_ case.
        (convert_local_omp_clauses): Ditto.
        * tree-pretty-print.c (dump_omp_clause): Added
        OMP_CLAUSE__CILK_FOR_COUNT_ and OMP_CLAUSE_SCHEDULE_CILKFOR cases.
        (dump_generic_node): Added CILK_FOR case.
        * tree.c (omp_clause_num_ops): New element
        OMP_CLAUSE__CILK_FOR_COUNT_ (1).
        (omp_clause_code_name): New element _Cilk_for_count_.
        (walk_tree_1): Added OMP_CLAUSE__CILK_FOR_COUNT_ case.
        * tree.def: Add tree code for CILK_FOR.

c/

2014-08-29  Jakub Jelinek  <jakub@redhat.com>
            Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * c-parser.c (c_parser_cilk_for): New function.
        (c_parser_cilk_grainsize): Likewise.
        (c_get_temp_regvar): Likewise.
        (c_parser_statement_after_labels): Added RID_CILK_FOR case.
        (c_parser_pragma): Added PRAGMA_CILK_GRAINSIZE case.
        (c_parser_omp_for_loop): Added CILK_FOR and CILK_SIMD checks.
        * c-typeck.c (c_finish_omp_clauses): Added OMP_CLAUSE__CILK_FOR_COUNT_
        case.

cp/

2014-08-29  Jakub Jelinek  <jakub@redhat.com>
            Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * cp-cilkplus.c (cpp_validate_cilk_plus_loop_aux): Loc definition
        simplified.
        * parser.c (cp_parser_cilk_for): New function.
        (cp_parser_cilk_grainsize): Likewise.
        (cp_parser_statement): Added RID_CILK_FOR case.
        (cp_parser_omp_for_cond): Added CILK_FOR check.
        (cp_parser_omp_for_loop_init): Change function argument to accept
        tree_code instead just a bool flag; change the check to use that
        tree_code; check for initialization declaration in case of Cilk_for.
        (cp_parser_omp_for_loop): Added checks for CILK_FOR and RID_CILK_FOR;
        changed call to cp_parser_omp_for_loop_init according new arguments'
        list.
        (cp_parser_pragma): Added PRAGMA_CILK_GRAINSIZE case.
        * pt.c (tsubst_expr): Added CILK_FOR case.
        * semantics.c: Include convert.h.
        (finish_omp_clauses): Properly handle OMP_CLAUSE_SCHEDULE_CILKFOR
        case; added OMP_CLAUSE__CILK_FOR_COUNT_.
        (handle_omp_for_class_iterator): New argument lastp and its usage;
        added NE_EXPR case.
        (finish_omp_for): Changed call to handle_omp_for_class_iterator
        according new arguments' list; in case of Cilk_for save very first
        decl and create empty stmt_list block; use block to build correct
        statement tree.

c-family/

2014-08-29  Jakub Jelinek  <jakub@redhat.com>
            Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * c-cilkplus.c (cilk_for_number_of_iterations): New function.
        * c-common.c (c_common_reswords): Added _Cilk_for.
        * c-common.h (enum rid): Added RID_CILK_FOR.
        (cilk_for_number_of_iterations): Add declaration.
        * c-omp.c (c_finish_omp_for): Added checks for CILK_SIMD and
        CILK_FOR.
        * c-pragma.c (init_pragma): Register "grainsize" pragma.
        * c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_GRAINSIZE.

testsuite/

014-08-29  Jakub Jelinek  <jakub@redhat.com>
            Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * c-c++-common/cilk-plus/CK/cilk-fors.c: New test.
        * c-c++-common/cilk-plus/CK/cilk-for-2.c: New test.
        * c-c++-common/cilk-plus/CK/cilk-for-3.c: New test.
        * c-c++-common/cilk-plus/CK/cilk_for_errors.c: New test.
        * c-c++-common/cilk-plus/CK/cilk_for_grain.c: New test.
        * c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c: New test.
        * c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c: New test.
        * c-c++-common/cilk-plus/CK/nested_cilk_for.c: New test.
        * g++.dg/cilk-plus/CK/cf3.cc: New test.
        * g++.dg/cilk-plus/CK/cilk-for-tplt.cc: New test.
        * g++.dg/cilk-plus/CK/for1.cc: New test.
        * g++.dg/cilk-plus/CK/stl_iter.cc: New test.
        * g++.dg/cilk-plus/CK/stl_rev_iter.cc: New test.
        * g++.dg/cilk-plus/CK/stl_test.cc: New test.



diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
index 1a16f66..131da0b 100644
--- a/gcc/c-family/c-cilkplus.c
+++ b/gcc/c-family/c-cilkplus.c
@@ -91,3 +91,136 @@ c_finish_cilk_clauses (tree clauses)
     }
   return clauses;
}
+
+/* Calculate number of iterations of CILK_FOR.  */
+
+tree
+cilk_for_number_of_iterations (tree cilk_for)
+{
+  tree t, v, n1, n2, step, type, init, cond, incr, itype;
+  enum tree_code cond_code;
+  location_t loc = EXPR_LOCATION (cilk_for);
+
+  init = TREE_VEC_ELT (OMP_FOR_INIT (cilk_for), 0);
+  v = TREE_OPERAND (init, 0);
+  cond = TREE_VEC_ELT (OMP_FOR_COND (cilk_for), 0);
+  incr = TREE_VEC_ELT (OMP_FOR_INCR (cilk_for), 0);
+  type = TREE_TYPE (v);
+
+  gcc_assert (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE
+	      || TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE);
+  n1 = TREE_OPERAND (init, 1);
+  cond_code = TREE_CODE (cond);
+  n2 = TREE_OPERAND (cond, 1);
+  switch (cond_code)
+    {
+    case LT_EXPR:
+    case GT_EXPR:
+    case NE_EXPR:
+      break;
+    case LE_EXPR:
+      if (POINTER_TYPE_P (TREE_TYPE (n2)))
+	n2 = fold_build_pointer_plus_hwi_loc (loc, n2, 1);
+      else
+	n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (n2), n2,
+			      build_int_cst (TREE_TYPE (n2), 1));
+      cond_code = LT_EXPR;
+      break;
+    case GE_EXPR:
+      if (POINTER_TYPE_P (TREE_TYPE (n2)))
+	n2 = fold_build_pointer_plus_hwi_loc (loc, n2, -1);
+      else
+	n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (n2), n2,
+			      build_int_cst (TREE_TYPE (n2), 1));
+      cond_code = GT_EXPR;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  step = NULL_TREE;
+  switch (TREE_CODE (incr))
+    {
+    case PREINCREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      step = build_int_cst (TREE_TYPE (v), 1);
+      break;
+    case PREDECREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+      step = build_int_cst (TREE_TYPE (v), -1);
+      break;
+    case MODIFY_EXPR:
+      t = TREE_OPERAND (incr, 1);
+      gcc_assert (TREE_OPERAND (t, 0) == v);
+      switch (TREE_CODE (t))
+	{
+	case PLUS_EXPR:
+	  step = TREE_OPERAND (t, 1);
+	  break;
+	case POINTER_PLUS_EXPR:
+	  step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
+	  break;
+	case MINUS_EXPR:
+	  step = TREE_OPERAND (t, 1);
+	  step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  itype = type;
+  if (POINTER_TYPE_P (itype))
+    itype = signed_type_for (itype);
+  if (cond_code == NE_EXPR)
+    {
+      /* For NE_EXPR, we need to find out if the iterator increases
+	 or decreases from whether step is positive or negative.  */
+      tree stype = itype;
+      if (TYPE_UNSIGNED (stype))
+	stype = signed_type_for (stype);
+      cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node,
+			      fold_convert_loc (loc, stype, step),
+			      build_int_cst (stype, 0));
+      t = fold_build3_loc (loc, COND_EXPR, itype, cond,
+			   build_int_cst (itype, -1),
+			   build_int_cst (itype, 1));
+    }
+  else
+    t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
+  t = fold_build2_loc (loc, PLUS_EXPR, itype,
+		       fold_convert_loc (loc, itype, step), t);
+  t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
+		       fold_convert_loc (loc, itype, n2));
+  t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
+		       fold_convert_loc (loc, itype, n1));
+  if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
+    t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
+			 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
+			 fold_build1_loc (loc, NEGATE_EXPR, itype,
+					  fold_convert_loc (loc, itype,
+							    step)));
+  else if (TYPE_UNSIGNED (itype) && cond_code == NE_EXPR)
+    {
+      tree t1
+	= fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
+			   fold_convert_loc (loc, itype, step));
+      tree t2
+	= fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
+			   fold_build1_loc (loc, NEGATE_EXPR, itype, t),
+			   fold_build1_loc (loc, NEGATE_EXPR, itype,
+					    fold_convert_loc (loc, itype,
+							      step)));
+      t = fold_build3_loc (loc, COND_EXPR, itype, cond, t1, t2);
+    }
+  else
+    t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
+			 fold_convert_loc (loc, itype, step));
+  cond = fold_build2_loc (loc, cond_code, boolean_type_node, n1, n2);
+  t = fold_build3_loc (loc, COND_EXPR, itype, cond, t,
+		       build_int_cst (itype, 0));
+  return t;
+}
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 58b9763..16cc5f6 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -418,6 +418,7 @@ const struct c_common_resword c_common_reswords[] =
   { "_Complex",		RID_COMPLEX,	0 },
   { "_Cilk_spawn",      RID_CILK_SPAWN, 0 },
   { "_Cilk_sync",       RID_CILK_SYNC,  0 },
+  { "_Cilk_for",        RID_CILK_FOR,   0 },
   { "_Imaginary",	RID_IMAGINARY, D_CONLY },
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d1cc810..993a97b 100644
--- 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 '@')  */
@@ -1395,4 +1395,5 @@ extern tree create_cilk_function_exit (tree, bool, bool);
extern tree cilk_install_body_pedigree_operations (tree);
extern void cilk_outline (tree, tree *, void *);
extern bool contains_cilk_spawn_stmt (tree);
+extern tree cilk_for_number_of_iterations (tree);
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 6a0e419..d6ca3df 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -396,7 +396,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
   bool fail = false;
   int i;

-  if (code == CILK_SIMD
+  if ((code == CILK_SIMD || code == CILK_FOR)
       && !c_check_cilk_loop (locus, TREE_VEC_ELT (declv, 0)))
     fail = true;

@@ -515,7 +515,10 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
		  || TREE_CODE (cond) == EQ_EXPR)
		{
		  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
-		    cond_ok = false;
+		    {
+		      if (code != CILK_SIMD && code != CILK_FOR)
+			cond_ok = false;
+		    }
		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
					    TYPE_MIN_VALUE (TREE_TYPE (decl)),
					    0))
@@ -526,7 +529,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
					    0))
		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
					 ? LT_EXPR : GE_EXPR);
-		  else if (code != CILK_SIMD)
+		  else if (code != CILK_SIMD && code != CILK_FOR)
		    cond_ok = false;
		}
	    }
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 804f37c..da928b2 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1405,6 +1405,11 @@ init_pragma (void)
   if (!flag_preprocess_only)
     cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
				  false);
+
+  if (flag_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 6f1bf74..b9f09ba 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/c-parser.c b/gcc/c/c-parser.c
index 34f1e47..03c6830 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1264,9 +1264,11 @@ static bool c_parser_objc_diagnose_bad_element_prefix

 /* Cilk Plus supporting routines.  */
static void c_parser_cilk_simd (c_parser *);
+static void c_parser_cilk_for (c_parser *, tree);
static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
+static void c_parser_cilk_grainsize (c_parser *);

 /* Parse a translation unit (C90 6.7, C99 6.9).

@@ -4895,6 +4897,16 @@ c_parser_statement_after_labels (c_parser *parser)
	case RID_FOR:
	  c_parser_for_statement (parser, false);
	  break;
+	case RID_CILK_FOR:
+	  if (!flag_cilkplus)
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"-fcilkplus must be enabled to use %<_Cilk_for%>");
+	      c_parser_skip_to_end_of_block_or_statement (parser);
+	    }
+	  else
+	    c_parser_cilk_for (parser, integer_zero_node);
+	  break;
	case RID_CILK_SYNC:
	  c_parser_consume_token (parser);
	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -9582,6 +9594,23 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_consume_pragma (parser);
       c_parser_cilk_simd (parser);
       return false;
+    case PRAGMA_CILK_GRAINSIZE:
+      if (!flag_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)
@@ -11715,11 +11744,18 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
   condv = make_tree_vec (collapse);
   incrv = make_tree_vec (collapse);

-  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
+  if (code != CILK_FOR
+      && !c_parser_next_token_is_keyword (parser, RID_FOR))
     {
       c_parser_error (parser, "for statement expected");
       return NULL;
     }
+  if (code == CILK_FOR
+      && !c_parser_next_token_is_keyword (parser, RID_CILK_FOR))
+    {
+      c_parser_error (parser, "_Cilk_for statement expected");
+      return NULL;
+    }
   for_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);

@@ -11797,7 +11833,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
	    case LE_EXPR:
	      break;
	    case NE_EXPR:
-	      if (code == CILK_SIMD)
+	      if (code == CILK_SIMD || code == CILK_FOR)
		break;
	      /* FALLTHRU.  */
	    default:
@@ -13890,8 +13926,48 @@ c_parser_cilk_all_clauses (c_parser *parser)
   return c_finish_cilk_clauses (clauses);
}

-/* Main entry point for parsing Cilk Plus <#pragma simd> for
-   loops.  */
+/* 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);
+
+  /* consume the 'grainsize' keyword.  */
+  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 == error_mark_node)
+	{
+	  c_parser_skip_to_pragma_eol (parser);
+	  return;
+	}
+      tree grain = convert_to_integer (long_integer_type_node,
+				       c_fully_fold (g_expr.value, false,
+						     NULL));
+      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)
+	{
+	  if (grain == NULL_TREE || grain == error_mark_node)
+	    grain = integer_zero_node;
+	  c_parser_cilk_for (parser, grain);
+	}
+      else
+	warning (0, "%<#pragma cilk grainsize%> is not followed by "
+		    "%<_Cilk_for%>");
+    }
+  else
+    c_parser_skip_to_pragma_eol (parser);
+}
+
+/* Main entry point for parsing Cilk Plus <#pragma simd> for loops.  */

 static void
c_parser_cilk_simd (c_parser *parser)
@@ -13903,6 +13979,105 @@ c_parser_cilk_simd (c_parser *parser)
   block = c_end_compound_stmt (loc, block, true);
   add_stmt (block);
}
+
+/* Create an artificial decl with TYPE and emit initialization of it with
+   INIT.  */
+
+static tree
+c_get_temp_regvar (tree type, tree init)
+{
+  location_t loc = EXPR_LOCATION (init);
+  tree decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  pushdecl (decl);
+  tree t = build2 (INIT_EXPR, type, decl, init);
+  add_stmt (t);
+  return decl;
+}
+
+/* Main entry point for parsing Cilk Plus _Cilk_for loops.
+  GRAIN is the grain value passed in through pragma or 0.  */
+
+static void
+c_parser_cilk_for (c_parser *parser, tree grain)
+{
+  tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE);
+  OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR;
+  OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain;
+  clauses = c_finish_omp_clauses (clauses);
+
+  tree block = c_begin_compound_stmt (true);
+  tree sb = push_stmt_list ();
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL);
+  sb = pop_stmt_list (sb);
+
+  if (omp_for)
+    {
+      tree omp_par = make_node (OMP_PARALLEL);
+      TREE_TYPE (omp_par) = void_type_node;
+      OMP_PARALLEL_CLAUSES (omp_par) = NULL_TREE;
+      tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+      TREE_SIDE_EFFECTS (bind) = 1;
+      BIND_EXPR_BODY (bind) = sb;
+      OMP_PARALLEL_BODY (omp_par) = bind;
+      if (OMP_FOR_PRE_BODY (omp_for))
+	{
+	  add_stmt (OMP_FOR_PRE_BODY (omp_for));
+	  OMP_FOR_PRE_BODY (omp_for) = NULL_TREE;
+	}
+      tree init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0);
+      tree decl = TREE_OPERAND (init, 0);
+      tree cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), 0);
+      tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0);
+      tree t = TREE_OPERAND (cond, 1), c, clauses = NULL_TREE;
+      if (TREE_CODE (t) != INTEGER_CST)
+	{
+	  TREE_OPERAND (cond, 1) = c_get_temp_regvar (TREE_TYPE (t), t);
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = TREE_OPERAND (cond, 1);
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      if (TREE_CODE (incr) == MODIFY_EXPR)
+	{
+	  t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1);
+	  if (TREE_CODE (t) != INTEGER_CST)
+	    {
+	      TREE_OPERAND (TREE_OPERAND (incr, 1), 1)
+		= c_get_temp_regvar (TREE_TYPE (t), t);
+	      c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	      OMP_CLAUSE_DECL (c) = TREE_OPERAND (TREE_OPERAND (incr, 1), 1);
+	      OMP_CLAUSE_CHAIN (c) = clauses;
+	      clauses = c;
+	    }
+	}
+      t = TREE_OPERAND (init, 1);
+      if (TREE_CODE (t) != INTEGER_CST)
+	{
+	  TREE_OPERAND (init, 1) = c_get_temp_regvar (TREE_TYPE (t), t);
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = TREE_OPERAND (init, 1);
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+      OMP_CLAUSE_DECL (c) = decl;
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      clauses = c;
+      c = build_omp_clause (input_location, OMP_CLAUSE__CILK_FOR_COUNT_);
+      OMP_CLAUSE_OPERAND (c, 0)
+	= cilk_for_number_of_iterations (omp_for);
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c);
+      add_stmt (omp_par);
+    }
+
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+}
+


 /* Parse a transaction attribute (GCC Extension).

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index a7de8f3..da71ab2 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -12229,6 +12229,7 @@ c_finish_omp_clauses (tree clauses)
	case OMP_CLAUSE_SECTIONS:
	case OMP_CLAUSE_TASKGROUP:
	case OMP_CLAUSE_PROC_BIND:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  pc = &OMP_CLAUSE_CHAIN (c);
	  continue;

diff --git a/gcc/cilk-builtins.def b/gcc/cilk-builtins.def
index 9f3240a..bf319d5 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")
diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c
index a6a1aa2..35c47e1 100644
--- a/gcc/cilk-common.c
+++ b/gcc/cilk-common.c
@@ -105,6 +105,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
+declare_cilk_for_builtin (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
@@ -119,7 +140,7 @@ cilk_init_builtins (void)
         uint64_t rank;
         struct __cilkrts_pedigree *parent;
       }  */
-       
+
   tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE);
   tree pedigree_ptr  = build_pointer_type (pedigree_type);
   tree field = add_field ("rank", uint64_type_node, NULL_TREE);
@@ -131,7 +152,7 @@ cilk_init_builtins (void)
   lang_hooks.types.register_builtin_type (pedigree_type,
					  "__cilkrts_pedigree_t");
   cilk_pedigree_type_decl = pedigree_type; 
-  
+
   /* Build the Cilk Stack Frame:
      struct __cilkrts_stack_frame {
        uint32_t flags;
@@ -212,7 +233,7 @@ cilk_init_builtins (void)
   tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE);
   finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE,
			 NULL_TREE);
-  
+
   field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE);
   cilk_trees[CILK_TI_WORKER_TAIL] = field;
   field = add_field ("head", fptr_vol_ptr_vol, field);
@@ -234,16 +255,16 @@ cilk_init_builtins (void)

   tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node);
   tree fptr_fun = build_function_type (void_type_node, fptr_arglist);
-  
+
   /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *);  */
   cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun,
				       BUILT_IN_CILK_ENTER_FRAME, false);

   /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *);  */
   cilk_enter_fast_fndecl = 
-    install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun, 
+    install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun,
		     BUILT_IN_CILK_ENTER_FRAME_FAST, false);
-  
+
   /* void __cilkrts_pop_frame (__cilkrts_stack_frame *);  */
   cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun,
				     BUILT_IN_CILK_POP_FRAME, false);
@@ -261,14 +282,22 @@ cilk_init_builtins (void)
					BUILT_IN_CILK_DETACH, false);

   /* __cilkrts_rethrow (struct stack_frame *);  */
-  cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun, 
+  cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun,
					 BUILT_IN_CILK_RETHROW, false);
   TREE_NOTHROW (cilk_rethrow_fndecl) = 0;

   /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *);  */
-  cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", 
+  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 = declare_cilk_for_builtin ("__cilkrts_cilk_for_32",
+						 unsigned_intSI_type_node,
+						 BUILT_IN_CILK_FOR_32);
+  /* __cilkrts_cilk_for_64 (...);  */
+  cilk_for_64_fndecl = declare_cilk_for_builtin ("__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 ae96f53..1fee929 100644
--- a/gcc/cilk.h
+++ b/gcc/cilk.h
@@ -40,6 +40,9 @@ 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.  */
@@ -77,6 +80,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]
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
index daa9b8e..565dd40 100644
--- a/gcc/cp/cp-cilkplus.c
+++ b/gcc/cp/cp-cilkplus.c
@@ -42,12 +42,11 @@ static tree
cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data)
{
   bool *valid = (bool *) data;
-  location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
-    UNKNOWN_LOCATION;

   if (!tp || !*tp)
     return NULL_TREE;

+  location_t loc = EXPR_LOCATION (*tp);
   if (TREE_CODE (*tp) == THROW_EXPR)
     {
       error_at (loc, "throw expressions are not allowed inside loops "
@@ -142,4 +141,3 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
   append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor),
			    &list);
}
-
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ad99cab..05fa86a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -239,6 +239,8 @@ 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 bool cp_parser_omp_declare_reduction_exprs
   (tree, cp_parser *);
static tree cp_parser_cilk_simd_vectorlength 
@@ -9532,6 +9534,18 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
	  statement = cp_parser_iteration_statement (parser, false);
	  break;

+	case RID_CILK_FOR:
+	  if (!flag_cilkplus)
+	    {
+	      error_at (cp_lexer_peek_token (parser->lexer)->location,
+			"-fcilkplus must be enabled to use %<_Cilk_for%>");
+	      cp_lexer_consume_token (parser->lexer);
+	      statement = error_mark_node;
+	    }
+	  else
+	    statement = cp_parser_cilk_for (parser, integer_zero_node);
+	  break;
+
	case RID_BREAK:
	case RID_CONTINUE:
	case RID_RETURN:
@@ -29222,7 +29236,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
     case LE_EXPR:
       break;
     case NE_EXPR:
-      if (code == CILK_SIMD)
+      if (code == CILK_SIMD || code == CILK_FOR)
	break;
       /* Fall through: OpenMP disallows NE_EXPR.  */
     default:
@@ -29337,15 +29351,12 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
/* Parse the initialization statement of either an OpenMP for loop or
    a Cilk Plus for loop.

-   PARSING_OPENMP is true if parsing OpenMP, or false if parsing Cilk
-   Plus.
-
    Return true if the resulting construct should have an
    OMP_CLAUSE_PRIVATE added to it.  */

 static bool
cp_parser_omp_for_loop_init (cp_parser *parser,
-			     bool parsing_openmp,
+			     enum tree_code code,
			     tree &this_pre_body,
			     vec<tree, va_gc> *for_block,
			     tree &init,
@@ -29408,7 +29419,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
	      if (cp_lexer_next_token_is (parser->lexer, 
 					  CPP_OPEN_PAREN))
		{
-		  if (parsing_openmp)
+		  if (code != CILK_SIMD && code != CILK_FOR)
		    error ("parenthesized initialization is not allowed in "
			   "OpenMP %<for%> loop");
		  else
@@ -29480,6 +29491,9 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
       cp_id_kind idk;
       /* If parsing a type specifier sequence failed, then
	 this MUST be a simple expression.  */
+      if (code == CILK_FOR)
+	error ("%<_Cilk_for%> allows expression instead of declaration only "
+	       "in C, not in C++");
       cp_parser_parse_tentatively (parser);
       decl = cp_parser_primary_expression (parser, false, false,
					   false, &idk);
@@ -29548,11 +29562,18 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
       bool add_private_clause = false;
       location_t loc;

-      if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+      if (code != CILK_FOR
+	  && !cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
	{
	  cp_parser_error (parser, "for statement expected");
	  return NULL;
	}
+      if (code == CILK_FOR
+	  && !cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR))
+	{
+	  cp_parser_error (parser, "_Cilk_for statement expected");
+	  return NULL;
+	}
       loc = cp_lexer_consume_token (parser->lexer)->location;

       if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
@@ -29562,8 +29583,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
       this_pre_body = push_stmt_list ();

       add_private_clause
-	|= cp_parser_omp_for_loop_init (parser,
-					/*parsing_openmp=*/code != CILK_SIMD,
+	|= cp_parser_omp_for_loop_init (parser, code,
					this_pre_body, for_block,
					init, decl, real_decl);

@@ -29733,7 +29753,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,

   /* Note that we saved the original contents of this flag when we entered
      the structured block, and so we don't need to re-save it here.  */
-  if (code == CILK_SIMD)
+  if (code == CILK_SIMD || code == CILK_FOR)
     parser->in_statement = IN_CILK_SIMD_FOR;
   else
     parser->in_statement = IN_OMP_FOR;
@@ -31692,6 +31712,36 @@ cp_parser_initial_pragma (cp_token *first_token)
   cp_lexer_get_preprocessor_token (NULL, first_token);
}

+/* Parses the grainsize pragma for the _Cilk_for statement.
+   Syntax:
+   #pragma cilk grainsize = <VALUE>.  */
+
+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;
+	}
+
+      /* Make sure the next token is _Cilk_for, it is invalid otherwise.  */
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR))
+	cp_parser_cilk_for (parser, exp);
+      else
+	warning_at (cp_lexer_peek_token (parser->lexer)->location, 0,
+		    "%<#pragma cilk grainsize%> is not followed by "
+		    "%<_Cilk_for%>");
+      return;
+    }
+  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+
/* Normal parsing of a pragma token.  Here we can (and must) use the
    regular lexer.  */

@@ -31874,6 +31924,27 @@ 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%> must be inside a function");
+	  break;
+	}
+
+      /* Ignore the pragma if Cilk Plus is not enabled.  */
+      if (flag_cilkplus)
+	{
+	  cp_parser_cilk_grainsize (parser, pragma_tok);
+	  return true;
+	}
+      else
+	{
+	  error_at (pragma_tok->location, "-fcilkplus must be enabled to use "
+		    "%<#pragma cilk grainsize%>");
+	  break;
+	}
+
     default:
       gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
       c_invoke_pragma_handler (id);
@@ -31960,10 +32031,10 @@ cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses,

   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return error_mark_node;
-  
+
   expr = cp_parser_constant_expression (parser, false, NULL);
   expr = maybe_constant_value (expr);
-  
+
   /* If expr == error_mark_node, then don't emit any errors nor
      create a clause.  if any of the above functions returns
      error mark node then they would have emitted an error message.  */
@@ -32197,7 +32268,7 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)

   if (clauses == error_mark_node)
     return;
-  
+
   if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR))
     {
       error_at (cp_lexer_peek_token (parser->lexer)->location,
@@ -32212,7 +32283,35 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
     cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret));
   cp_parser_end_omp_structured_block (parser, save);
   add_stmt (finish_omp_structured_block (sb));
-  return;
+}
+
+/* Main entry-point for parsing Cilk Plus _Cilk_for
+   loops.  The return value is error_mark_node
+   when errors happen and CILK_FOR tree on success.  */
+
+static tree
+cp_parser_cilk_for (cp_parser *parser, tree grain)
+{
+  if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_CILK_FOR))
+    gcc_unreachable ();
+
+  tree sb = begin_omp_structured_block ();
+  int save = cp_parser_begin_omp_structured_block (parser);
+
+  tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE);
+  OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR;
+  OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain;
+  clauses = finish_omp_clauses (clauses);
+
+  tree ret = cp_parser_omp_for_loop (parser, CILK_FOR, clauses, NULL);
+  if (ret)
+    cpp_validate_cilk_plus_loop (ret);
+  else
+    ret = error_mark_node;
+
+  cp_parser_end_omp_structured_block (parser, save);
+  add_stmt (finish_omp_structured_block (sb));
+  return ret;
}

 /* Create an identifier for a generic parameter type (a synthesized
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index eac837f..5ea5a58 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14012,6 +14012,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
     case OMP_FOR:
     case OMP_SIMD:
     case CILK_SIMD:
+    case CILK_FOR:
     case OMP_DISTRIBUTE:
       {
	tree clauses, body, pre_body;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 168bde8..01748da 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  If not see
#include "bitmap.h"
#include "omp-low.h"
#include "builtins.h"
+#include "convert.h"

 static bool verify_constant (tree, bool, bool *, bool *);
#define VERIFY_CONSTANT(X)						\
@@ -5424,6 +5425,8 @@ finish_omp_clauses (tree clauses)
	  else if (t == error_mark_node)
	    remove = true;
	  else if (!type_dependent_expression_p (t)
+		   && (OMP_CLAUSE_SCHEDULE_KIND (c)
+		       != OMP_CLAUSE_SCHEDULE_CILKFOR)
		   && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
	    {
	      error ("schedule chunk size expression must be integral");
@@ -5433,7 +5436,19 @@ finish_omp_clauses (tree clauses)
	    {
	      t = mark_rvalue_use (t);
	      if (!processing_template_decl)
-		t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+		{
+		  if (OMP_CLAUSE_SCHEDULE_KIND (c)
+		      == OMP_CLAUSE_SCHEDULE_CILKFOR)
+		    {
+		      t = convert_to_integer (long_integer_type_node, t);
+		      if (t == error_mark_node)
+			{
+			  remove = true;
+			  break;
+			}
+		    }
+		  t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+		}
	      OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
	    }
	  break;
@@ -5734,6 +5749,7 @@ finish_omp_clauses (tree clauses)
	case OMP_CLAUSE_SECTIONS:
	case OMP_CLAUSE_TASKGROUP:
	case OMP_CLAUSE_PROC_BIND:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  break;

 	case OMP_CLAUSE_INBRANCH:
@@ -6053,7 +6069,7 @@ finish_omp_task (tree clauses, tree body)
static bool
handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
			       tree condv, tree incrv, tree *body,
-			       tree *pre_body, tree clauses)
+			       tree *pre_body, tree clauses, tree *lastp)
{
   tree diff, iter_init, iter_incr = NULL, last;
   tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -6073,6 +6089,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
     case GE_EXPR:
     case LT_EXPR:
     case LE_EXPR:
+    case NE_EXPR:
       if (TREE_OPERAND (cond, 1) == iter)
	cond = build2 (swap_tree_comparison (TREE_CODE (cond)),
		       TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0));
@@ -6285,6 +6302,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
   TREE_VEC_ELT (initv, i) = init;
   TREE_VEC_ELT (condv, i) = cond;
   TREE_VEC_ELT (incrv, i) = incr;
+  *lastp = last;

   return false;
}
@@ -6301,7 +6319,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
		tree condv, tree incrv, tree body, tree pre_body, tree clauses)
{
   tree omp_for = NULL, orig_incr = NULL;
-  tree decl, init, cond, incr;
+  tree decl = NULL, init, cond, incr, orig_decl = NULL_TREE, block = NULL_TREE;
+  tree last = NULL_TREE;
   location_t elocus;
   int i;

@@ -6431,8 +6450,11 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
				"iteration variable %qE", decl);
	      return NULL;
	    }
+	  if (code == CILK_FOR && i == 0)
+	    orig_decl = decl;
	  if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
-					     incrv, &body, &pre_body, clauses))
+					     incrv, &body, &pre_body,
+					     clauses, &last))
	    return NULL;
	  continue;
	}
@@ -6485,11 +6507,18 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
   if (IS_EMPTY_STMT (pre_body))
     pre_body = NULL;

+  if (code == CILK_FOR && !processing_template_decl)
+    block = push_stmt_list ();
+
   omp_for = c_finish_omp_for (locus, code, declv, initv, condv, incrv,
			      body, pre_body);

   if (omp_for == NULL)
-    return NULL;
+    {
+      if (block)
+	pop_stmt_list (block);
+      return NULL;
+    }

   for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++)
     {
@@ -6523,8 +6552,117 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
       if (orig_incr)
	TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i) = TREE_VEC_ELT (orig_incr, i);
     }
-  if (omp_for != NULL)
-    OMP_FOR_CLAUSES (omp_for) = clauses;
+  OMP_FOR_CLAUSES (omp_for) = clauses;
+
+  if (block)
+    {
+      tree omp_par = make_node (OMP_PARALLEL);
+      TREE_TYPE (omp_par) = void_type_node;
+      OMP_PARALLEL_CLAUSES (omp_par) = NULL_TREE;
+      tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+      TREE_SIDE_EFFECTS (bind) = 1;
+      BIND_EXPR_BODY (bind) = pop_stmt_list (block);
+      OMP_PARALLEL_BODY (omp_par) = bind;
+      if (OMP_FOR_PRE_BODY (omp_for))
+	{
+	  add_stmt (OMP_FOR_PRE_BODY (omp_for));
+	  OMP_FOR_PRE_BODY (omp_for) = NULL_TREE;
+	}
+      init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0);
+      decl = TREE_OPERAND (init, 0);
+      cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), 0);
+      incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0);
+      tree t = TREE_OPERAND (cond, 1), c, clauses, *pc;
+      clauses = OMP_FOR_CLAUSES (omp_for);
+      OMP_FOR_CLAUSES (omp_for) = NULL_TREE;
+      for (pc = &clauses; *pc; )
+	if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_SCHEDULE)
+	  {
+	    gcc_assert (OMP_FOR_CLAUSES (omp_for) == NULL_TREE);
+	    OMP_FOR_CLAUSES (omp_for) = *pc;
+	    *pc = OMP_CLAUSE_CHAIN (*pc);
+	    OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (omp_for)) = NULL_TREE;
+	  }
+	else
+	  {
+	    gcc_assert (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_FIRSTPRIVATE);
+	    pc = &OMP_CLAUSE_CHAIN (*pc);
+	  }
+      if (TREE_CODE (t) != INTEGER_CST)
+	{
+	  TREE_OPERAND (cond, 1) = get_temp_regvar (TREE_TYPE (t), t);
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = TREE_OPERAND (cond, 1);
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      if (TREE_CODE (incr) == MODIFY_EXPR)
+	{
+	  t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1);
+	  if (TREE_CODE (t) != INTEGER_CST)
+	    {
+	      TREE_OPERAND (TREE_OPERAND (incr, 1), 1)
+		= get_temp_regvar (TREE_TYPE (t), t);
+	      c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	      OMP_CLAUSE_DECL (c) = TREE_OPERAND (TREE_OPERAND (incr, 1), 1);
+	      OMP_CLAUSE_CHAIN (c) = clauses;
+	      clauses = c;
+	    }
+	}
+      t = TREE_OPERAND (init, 1);
+      if (TREE_CODE (t) != INTEGER_CST)
+	{
+	  TREE_OPERAND (init, 1) = get_temp_regvar (TREE_TYPE (t), t);
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = TREE_OPERAND (init, 1);
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      if (orig_decl && orig_decl != decl)
+	{
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = orig_decl;
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      if (last)
+	{
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = last;
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+      OMP_CLAUSE_DECL (c) = decl;
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      clauses = c;
+      c = build_omp_clause (input_location, OMP_CLAUSE__CILK_FOR_COUNT_);
+      OMP_CLAUSE_OPERAND (c, 0)
+	= cilk_for_number_of_iterations (omp_for);
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      OMP_PARALLEL_CLAUSES (omp_par) = finish_omp_clauses (c);
+      add_stmt (omp_par);
+      return omp_par;
+    }
+  else if (code == CILK_FOR && processing_template_decl)
+    {
+      tree c, clauses = OMP_FOR_CLAUSES (omp_for);
+      if (orig_decl && orig_decl != decl)
+	{
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = orig_decl;
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      if (last)
+	{
+	  c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (c) = last;
+	  OMP_CLAUSE_CHAIN (c) = clauses;
+	  clauses = c;
+	}
+      OMP_FOR_CLAUSES (omp_for) = clauses;
+    }
   return omp_for;
}

diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 283aca2..60b56b0 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1135,6 +1135,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
	case GF_OMP_FOR_KIND_DISTRIBUTE:
	  kind = " distribute";
	  break;
+	case GF_OMP_FOR_KIND_CILKFOR:
+	  kind = " _Cilk_for";
+	  break;
	default:
	  gcc_unreachable ();
	}
@@ -1169,16 +1172,24 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
	case GF_OMP_FOR_KIND_DISTRIBUTE:
	  pp_string (buffer, "#pragma omp distribute");
	  break;
+	case GF_OMP_FOR_KIND_CILKFOR:
+	  break;
	default:
	  gcc_unreachable ();
	}
-      dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags);
+      if (gimple_omp_for_kind (gs) != GF_OMP_FOR_KIND_CILKFOR)
+	dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags);
       for (i = 0; i < gimple_omp_for_collapse (gs); i++)
	{
	  if (i)
	    spc += 2;
-	  newline_and_indent (buffer, spc);
-	  pp_string (buffer, "for (");
+	  if (gimple_omp_for_kind (gs) == GF_OMP_FOR_KIND_CILKFOR)
+	    pp_string (buffer, "_Cilk_for (");
+	  else
+	    {
+	      newline_and_indent (buffer, spc);
+	      pp_string (buffer, "for (");
+	    }
	  dump_generic_node (buffer, gimple_omp_for_index (gs, i), spc,
			     flags, false);
	  pp_string (buffer, " = ");
@@ -1203,6 +1214,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
	    case GE_EXPR:
	      pp_greater_equal (buffer);
	      break;
+	    case NE_EXPR:
+	      pp_string (buffer, "!=");
+	      break;
	    default:
	      gcc_unreachable ();
	    }
@@ -1221,6 +1235,8 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)

       if (!gimple_seq_empty_p (gimple_omp_body (gs)))
	{
+	  if (gimple_omp_for_kind (gs) == GF_OMP_FOR_KIND_CILKFOR)
+	    dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags);
	  newline_and_indent (buffer, spc + 2);
	  pp_left_brace (buffer);
	  pp_newline (buffer);
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 51814ba..ec41585 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -92,15 +92,16 @@ enum gf_mask {
     GF_CALL_INTERNAL		= 1 << 6,
     GF_CALL_CTRL_ALTERING       = 1 << 7,
     GF_OMP_PARALLEL_COMBINED	= 1 << 0,
-    GF_OMP_FOR_KIND_MASK	= (1 << 2) - 1,
+    GF_OMP_FOR_KIND_MASK	= 7 << 0,
     GF_OMP_FOR_KIND_FOR		= 0,
     GF_OMP_FOR_KIND_DISTRIBUTE	= 1,
+    GF_OMP_FOR_KIND_CILKFOR     = 2,
     /* Flag for SIMD variants of OMP_FOR kinds.  */
-    GF_OMP_FOR_SIMD		= 1 << 1,
+    GF_OMP_FOR_SIMD		= 1 << 2,
     GF_OMP_FOR_KIND_SIMD	= GF_OMP_FOR_SIMD | 0,
     GF_OMP_FOR_KIND_CILKSIMD	= GF_OMP_FOR_SIMD | 1,
-    GF_OMP_FOR_COMBINED		= 1 << 2,
-    GF_OMP_FOR_COMBINED_INTO	= 1 << 3,
+    GF_OMP_FOR_COMBINED		= 1 << 3,
+    GF_OMP_FOR_COMBINED_INTO	= 1 << 4,
     GF_OMP_TARGET_KIND_MASK	= (1 << 2) - 1,
     GF_OMP_TARGET_KIND_REGION	= 0,
     GF_OMP_TARGET_KIND_DATA	= 1,
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 658c5d2..0ebc24c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6208,6 +6208,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
	case OMP_CLAUSE_THREAD_LIMIT:
	case OMP_CLAUSE_DIST_SCHEDULE:
	case OMP_CLAUSE_DEVICE:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
			     is_gimple_val, fb_rvalue) == GS_ERROR)
	    remove = true;
@@ -6584,6 +6585,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, tree *list_p)
	case OMP_CLAUSE_PROC_BIND:
	case OMP_CLAUSE_SAFELEN:
	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  break;

 	default:
@@ -7056,6 +7058,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
     case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
     case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
     case CILK_SIMD: kind = GF_OMP_FOR_KIND_CILKSIMD; break;
+    case CILK_FOR: kind = GF_OMP_FOR_KIND_CILKFOR; break;
     case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
     default:
       gcc_unreachable ();
@@ -8128,6 +8131,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
	case OMP_FOR:
	case OMP_SIMD:
	case CILK_SIMD:
+	case CILK_FOR:
	case OMP_DISTRIBUTE:
	  ret = gimplify_omp_for (expr_p, pre_p);
	  break;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 9d1cd2c..22a8fca 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3.  If not see
#include "ipa-prop.h"
#include "tree-nested.h"
#include "tree-eh.h"
+#include "cilk.h"

 
 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
@@ -313,6 +314,8 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
   fd->have_ordered = false;
   fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
   fd->chunk_size = NULL_TREE;
+  if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
+    fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
   collapse_iter = NULL;
   collapse_count = NULL;

@@ -392,7 +395,9 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
	  break;
	case NE_EXPR:
	  gcc_assert (gimple_omp_for_kind (for_stmt)
-		      == GF_OMP_FOR_KIND_CILKSIMD);
+		      == GF_OMP_FOR_KIND_CILKSIMD
+		      || (gimple_omp_for_kind (for_stmt)
+			  == GF_OMP_FOR_KIND_CILKFOR));
	  break;
	case LE_EXPR:
	  if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
@@ -1604,6 +1609,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
	case OMP_CLAUSE_SCHEDULE:
	case OMP_CLAUSE_DIST_SCHEDULE:
	case OMP_CLAUSE_DEPEND:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  if (ctx->outer)
	    scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
	  break;
@@ -1812,6 +1818,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
	case OMP_CLAUSE__LOOPTEMP_:
	case OMP_CLAUSE_TO:
	case OMP_CLAUSE_FROM:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  break;

 	default:
@@ -1835,13 +1842,39 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
	scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
}

-/* Create a new name for omp child function.  Returns an identifier.  */
+/* Create a new name for omp child function.  Returns an identifier.  If
+   IS_CILK_FOR is true then the suffix for the child function is
+   "_cilk_for_fn."  */

 static tree
-create_omp_child_function_name (bool task_copy)
+create_omp_child_function_name (bool task_copy, bool is_cilk_for)
{
-  return (clone_function_name (current_function_decl,
-			       task_copy ? "_omp_cpyfn" : "_omp_fn"));
+  if (is_cilk_for)
+    return clone_function_name (current_function_decl, "_cilk_for_fn");
+  return clone_function_name (current_function_decl,
+			      task_copy ? "_omp_cpyfn" : "_omp_fn");
+}
+
+/* Returns the type of the induction variable for the child function for
+   _Cilk_for and the types for _high and _low variables based on TYPE.  */
+
+static tree
+cilk_for_check_loop_diff_type (tree type)
+{
+  if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
+    {
+      if (TYPE_UNSIGNED (type))
+	return uint32_type_node;
+      else
+	return integer_type_node;
+    }
+  else
+    {
+      if (TYPE_UNSIGNED (type))
+	return uint64_type_node;
+      else
+	return long_long_integer_type_node;
+    }
}

 /* Build a decl for the omp child function.  It'll not contain a body
@@ -1852,15 +1885,28 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
{
   tree decl, type, name, t;

-  name = create_omp_child_function_name (task_copy);
+  tree cilk_for_count
+    = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
+      ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
+			 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
+  tree cilk_var_type = NULL_TREE;
+
+  name = create_omp_child_function_name (task_copy,
+					 cilk_for_count != NULL_TREE);
   if (task_copy)
     type = build_function_type_list (void_type_node, ptr_type_node,
				     ptr_type_node, NULL_TREE);
+  else if (cilk_for_count)
+    {
+      type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
+      cilk_var_type = cilk_for_check_loop_diff_type (type);
+      type = build_function_type_list (void_type_node, ptr_type_node,
+				       cilk_var_type, cilk_var_type, NULL_TREE);
+    }
   else
     type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);

-  decl = build_decl (gimple_location (ctx->stmt),
-		     FUNCTION_DECL, name, type);
+  decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);

   if (!task_copy)
     ctx->cb.dst_fn = decl;
@@ -1904,13 +1950,42 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
   DECL_CONTEXT (t) = decl;
   DECL_RESULT (decl) = t;

-  t = build_decl (DECL_SOURCE_LOCATION (decl),
-		  PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
+  /* _Cilk_for's child function requires two extra parameters called
+     __low and __high that are set the by Cilk runtime when it calls this
+     function.  */
+  if (cilk_for_count)
+    {
+      t = build_decl (DECL_SOURCE_LOCATION (decl),
+		      PARM_DECL, get_identifier ("__high"), cilk_var_type);
+      DECL_ARTIFICIAL (t) = 1;
+      DECL_NAMELESS (t) = 1;
+      DECL_ARG_TYPE (t) = ptr_type_node;
+      DECL_CONTEXT (t) = current_function_decl;
+      TREE_USED (t) = 1;
+      DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
+      DECL_ARGUMENTS (decl) = t;
+
+      t = build_decl (DECL_SOURCE_LOCATION (decl),
+		      PARM_DECL, get_identifier ("__low"), cilk_var_type);
+      DECL_ARTIFICIAL (t) = 1;
+      DECL_NAMELESS (t) = 1;
+      DECL_ARG_TYPE (t) = ptr_type_node;
+      DECL_CONTEXT (t) = current_function_decl;
+      TREE_USED (t) = 1;
+      DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
+      DECL_ARGUMENTS (decl) = t;
+    }
+
+  tree data_name = get_identifier (".omp_data_i");
+  t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
+		  ptr_type_node);
   DECL_ARTIFICIAL (t) = 1;
   DECL_NAMELESS (t) = 1;
   DECL_ARG_TYPE (t) = ptr_type_node;
   DECL_CONTEXT (t) = current_function_decl;
   TREE_USED (t) = 1;
+  if (cilk_for_count)
+    DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
   DECL_ARGUMENTS (decl) = t;
   if (!task_copy)
     ctx->receiver_decl = t;
@@ -4382,6 +4457,44 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
			    false, GSI_CONTINUE_LINKING);
}

+/* Insert a function call whose name is FUNC_NAME with the information from
+   ENTRY_STMT into the basic_block BB.  */
+
+static void
+expand_cilk_for_call (basic_block bb, gimple entry_stmt,
+		      vec <tree, va_gc> *ws_args)
+{
+  tree t, t1, t2;
+  gimple_stmt_iterator gsi;
+  vec <tree, va_gc> *args;
+
+  gcc_assert (vec_safe_length (ws_args) == 2);
+  tree func_name = (*ws_args)[0];
+  tree grain = (*ws_args)[1];
+
+  tree clauses = gimple_omp_parallel_clauses (entry_stmt);
+  tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
+  gcc_assert (count != NULL_TREE);
+  count = OMP_CLAUSE_OPERAND (count, 0);
+
+  gsi = gsi_last_bb (bb);
+  t = gimple_omp_parallel_data_arg (entry_stmt);
+  if (t == NULL)
+    t1 = null_pointer_node;
+  else
+    t1 = build_fold_addr_expr (t);
+  t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
+
+  vec_alloc (args, 4);
+  args->quick_push (t2);
+  args->quick_push (t1);
+  args->quick_push (count);
+  args->quick_push (grain);
+  t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
+
+  force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
+			    GSI_CONTINUE_LINKING);
+}

 /* Build the function call to GOMP_task to actually
    generate the task operation.  BB is the block where to insert the code.  */
@@ -4717,7 +4830,18 @@ expand_omp_taskreg (struct omp_region *region)
   entry_bb = region->entry;
   exit_bb = region->exit;

-  if (is_combined_parallel (region))
+  bool is_cilk_for
+    = (flag_cilkplus
+       && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
+       && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
+			   OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
+
+  if (is_cilk_for)
+    /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
+       and the inner statement contains the name of the built-in function
+       and grain.  */
+    ws_args = region->inner->ws_args;
+  else if (is_combined_parallel (region))
     ws_args = region->ws_args;
   else
     ws_args = NULL;
@@ -4929,7 +5053,9 @@ expand_omp_taskreg (struct omp_region *region)
     }

   /* Emit a library call to launch the children threads.  */
-  if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
+  if (is_cilk_for)
+    expand_cilk_for_call (new_bb, entry_stmt, ws_args);
+  else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
     expand_parallel_call (region, new_bb, entry_stmt, ws_args);
   else
     expand_task_call (new_bb, entry_stmt);
@@ -6621,6 +6747,191 @@ expand_omp_for_static_chunk (struct omp_region *region,
     }
}

+/* A subroutine of expand_omp_for.  Generate code for _Cilk_for loop.
+   Given parameters:
+   for (V = N1; V cond N2; V += STEP) BODY;
+
+   where COND is "<" or ">" or "!=", we generate pseudocode
+
+   for (ind_var = low; ind_var < high; ind_var++)
+     {
+       V = n1 + (ind_var * STEP)
+
+       <BODY>
+     }
+
+   In the above pseudocode, low and high are function parameters of the
+   child function.  In the function below, we are inserting a temp.
+   variable that will be making a call to two OMP functions that will not be
+   found in the body of _Cilk_for (since OMP_FOR cannot be mixed
+   with _Cilk_for).  These functions are replaced with low and high
+   by the function that handles taskreg.  */
+
+
+static void
+expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
+{
+  bool broken_loop = region->cont == NULL;
+  basic_block entry_bb = region->entry;
+  basic_block cont_bb = region->cont;
+
+  gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
+  gcc_assert (broken_loop
+	      || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
+  basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
+  basic_block l1_bb, l2_bb;
+
+  if (!broken_loop)
+    {
+      gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
+      gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
+      l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
+      l2_bb = BRANCH_EDGE (entry_bb)->dest;
+    }
+  else
+    {
+      BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
+      l1_bb = split_edge (BRANCH_EDGE (entry_bb));
+      l2_bb = single_succ (l1_bb);
+    }
+  basic_block exit_bb = region->exit;
+  basic_block l2_dom_bb = NULL;
+
+  gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
+
+  /* Below statements until the "tree high_val = ..." are pseudo statements
+     used to pass information to be used by expand_omp_taskreg.
+     low_val and high_val will be replaced by the __low and __high
+     parameter from the child function.
+
+     The call_exprs part is a place-holder, it is mainly used
+     to distinctly identify to the top-level part that this is
+     where we should put low and high (reasoning given in header
+     comment).  */
+
+  tree child_fndecl
+    = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry));
+  tree t, low_val = NULL_TREE, high_val = NULL_TREE;
+  for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
+    {
+      if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
+	high_val = t;
+      else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
+	low_val = t;
+    }
+  gcc_assert (low_val && high_val);
+
+  tree type = TREE_TYPE (low_val);
+  tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
+  gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
+
+  /* Not needed in SSA form right now.  */
+  gcc_assert (!gimple_in_ssa_p (cfun));
+  if (l2_dom_bb == NULL)
+    l2_dom_bb = l1_bb;
+
+  tree n1 = low_val;
+  tree n2 = high_val;
+
+  gimple stmt = gimple_build_assign (ind_var, n1);
+
+  /* Replace the GIMPLE_OMP_FOR statement.  */
+  gsi_replace (&gsi, stmt, true);
+
+  if (!broken_loop)
+    {
+      /* Code to control the increment goes in the CONT_BB.  */
+      gsi = gsi_last_bb (cont_bb);
+      stmt = gsi_stmt (gsi);
+      gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
+      stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
+					   build_one_cst (type));
+
+      /* Replace GIMPLE_OMP_CONTINUE.  */
+      gsi_replace (&gsi, stmt, true);
+    }
+
+  /* Emit the condition in L1_BB.  */
+  gsi = gsi_after_labels (l1_bb);
+  t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
+		   fold_convert (TREE_TYPE (fd->loop.step), ind_var),
+		   fd->loop.step);
+  if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
+    t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
+		     fd->loop.n1, fold_convert (sizetype, t));
+  else
+    t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
+		     fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
+  t = fold_convert (TREE_TYPE (fd->loop.v), t);
+  expand_omp_build_assign (&gsi, fd->loop.v, t);
+
+  /* The condition is always '<' since the runtime will fill in the low
+     and high values.  */
+  stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
+  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+
+  /* Remove GIMPLE_OMP_RETURN.  */
+  gsi = gsi_last_bb (exit_bb);
+  gsi_remove (&gsi, true);
+
+  /* Connect the new blocks.  */
+  remove_edge (FALLTHRU_EDGE (entry_bb));
+
+  edge e, ne;
+  if (!broken_loop)
+    {
+      remove_edge (BRANCH_EDGE (entry_bb));
+      make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
+
+      e = BRANCH_EDGE (l1_bb);
+      ne = FALLTHRU_EDGE (l1_bb);
+      e->flags = EDGE_TRUE_VALUE;
+    }
+  else
+    {
+      single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+
+      ne = single_succ_edge (l1_bb);
+      e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
+
+    }
+  ne->flags = EDGE_FALSE_VALUE;
+  e->probability = REG_BR_PROB_BASE * 7 / 8;
+  ne->probability = REG_BR_PROB_BASE / 8;
+
+  set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
+  set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
+  set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
+
+  if (!broken_loop)
+    {
+      struct loop *loop = alloc_loop ();
+      loop->header = l1_bb;
+      loop->latch = cont_bb;
+      add_loop (loop, l1_bb->loop_father);
+      loop->safelen = INT_MAX;
+    }
+
+  /* Pick the correct library function based on the precision of the
+     induction variable type.  */
+  tree lib_fun = NULL_TREE;
+  if (TYPE_PRECISION (type) == 32)
+    lib_fun = cilk_for_32_fndecl;
+  else if (TYPE_PRECISION (type) == 64)
+    lib_fun = cilk_for_64_fndecl;
+  else
+    gcc_unreachable ();
+
+  gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
+
+  /* WS_ARGS contains the library function flavor to call:
+     __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
+     user-defined grain value.  If the user does not define one, then zero
+     is passed in by the parser.  */
+  vec_alloc (region->ws_args, 2);
+  region->ws_args->quick_push (lib_fun);
+  region->ws_args->quick_push (fd->chunk_size);
+}

 /* A subroutine of expand_omp_for.  Generate code for a simd non-worksharing
    loop.  Given parameters:
@@ -6964,6 +7275,8 @@ expand_omp_for (struct omp_region *region, gimple inner_stmt)

   if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
     expand_omp_simd (region, &fd);
+  else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
+    expand_cilk_for (region, &fd);
   else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
	   && !fd.have_ordered)
     {
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-2.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-2.c
new file mode 100644
index 0000000..fd30667
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-2.c
@@ -0,0 +1,393 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+int msk;
+
+#define BODY \
+  do {									\
+    int j = (i >= 30U) ? 30 : i;					\
+    if (__atomic_fetch_or (&msk, 1 << j, __ATOMIC_RELAXED) & (1 << j))	\
+      __builtin_abort ();						\
+  } while (0)
+#define TEST(x) if (msk != (x)) __builtin_abort (); msk = 0
+
+__attribute__((noinline, noclone)) void
+test (int seven, int three, int two, int minustwo, int ten,
+      int zero, int eleven, int six, int one, int threealt,
+      unsigned long int sevenUL, unsigned long int threeUL,
+      unsigned long int twoUL, unsigned long int minustwoUL,
+      unsigned long int tenUL, unsigned long int zeroUL,
+      unsigned long int elevenUL, unsigned long int sixUL,
+      unsigned long int oneUL, unsigned long int threealtUL)
+{
+  _Cilk_for (int i = seven; i < three; ++i)
+    __builtin_abort ();
+  _Cilk_for (int i = seven; i <= three; ++i)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i != threealt; ++i)
+    __builtin_abort ();
+  _Cilk_for (int i = seven; i < three; i += two)
+    __builtin_abort ();
+  _Cilk_for (int i = seven; i <= three; i += two)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i != threealt; i += two)
+    __builtin_abort ();
+  _Cilk_for (int i = seven; i < three; i -= minustwo)
+    __builtin_abort ();
+  _Cilk_for (int i = seven; i <= three; i -= minustwo)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i != threealt; i -= minustwo)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i > seven; --i)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i >= seven; i--)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i != threealt; i--)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i > seven; i -= two)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i >= seven; i -= two)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i != threealt; i -= two)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i > seven; i += minustwo)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i >= seven; i += minustwo)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i != threealt; i += minustwo)
+    __builtin_abort ();
+  _Cilk_for (int i = three; i < seven; ++i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (int i = three; i <= seven; i++)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (int i = three; i != seven; i++)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (int i = zero; i < ten; i += two)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = zero; i <= ten; i += two)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (int i = zero; i != ten; i += two)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = zero; i < ten; i -= minustwo)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = zero; i <= ten; i -= minustwo)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (int i = zero; i != ten; i -= minustwo)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = six; i > two; --i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (int i = seven; i >= three; i--)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (int i = seven; i != three; i--)
+    BODY;
+  TEST (0xf0);
+  _Cilk_for (int i = eleven; i > one; i += minustwo)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = eleven; i >= two; i += minustwo)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = eleven; i != one; i += minustwo)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = eleven; i > one; i -= two)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = eleven; i >= two; i -= two)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = eleven; i != one; i -= two)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = sevenUL; i < threeUL; ++i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = sevenUL; i <= threeUL; ++i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i != threealtUL; ++i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = sevenUL; i < threeUL; i += twoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = sevenUL; i <= threeUL; i += twoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i += twoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = sevenUL; i < threeUL; i -= minustwoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = sevenUL; i <= threeUL; i -= minustwoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i -= minustwoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i > sevenUL; --i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i >= sevenUL; i--)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i--)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i > sevenUL; i -= twoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i >= sevenUL; i -= twoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i -= twoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i > sevenUL; i += minustwoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i >= sevenUL; i += minustwoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i += minustwoUL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = threeUL; i < sevenUL; ++i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (unsigned long int i = threeUL; i <= sevenUL; i++)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (unsigned long int i = threeUL; i != sevenUL; i++)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (unsigned long int i = zeroUL; i < tenUL; i += twoUL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = zeroUL; i <= tenUL; i += twoUL)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (unsigned long int i = zeroUL; i != tenUL; i += twoUL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = zeroUL; i < tenUL; i -= minustwoUL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = zeroUL; i <= tenUL; i -= minustwoUL)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (unsigned long int i = zeroUL; i != tenUL; i -= minustwoUL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = sixUL; i > twoUL; --i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (unsigned long int i = sevenUL; i >= threeUL; i--)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (unsigned long int i = sevenUL; i != threeUL; i--)
+    BODY;
+  TEST (0xf0);
+  _Cilk_for (unsigned long int i = elevenUL; i > oneUL; i += minustwoUL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = elevenUL; i >= twoUL; i += minustwoUL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = elevenUL; i != oneUL; i += minustwoUL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = elevenUL; i > oneUL; i -= twoUL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = elevenUL; i >= twoUL; i -= twoUL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = elevenUL; i != oneUL; i -= twoUL)
+    BODY;
+  TEST (0xaa8);
+}
+
+int
+main ()
+{
+  _Cilk_for (int i = 7; i < 3; ++i)
+    __builtin_abort ();
+  _Cilk_for (int i = 7; i <= 3; ++i)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i != 3; ++i)
+    __builtin_abort ();
+  _Cilk_for (int i = 7; i < 3; i += 2)
+    __builtin_abort ();
+  _Cilk_for (int i = 7; i <= 3; i += 2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i != 3; i += 2)
+    __builtin_abort ();
+  _Cilk_for (int i = 7; i < 3; i -= -2)
+    __builtin_abort ();
+  _Cilk_for (int i = 7; i <= 3; i -= -2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i != 3; i -= -2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i > 7; --i)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i >= 7; i--)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i != 3; i--)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i > 7; i -= 2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i >= 7; i -= 2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i != 3; i -= 2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i > 7; i += -2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i >= 7; i += -2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i != 3; i += -2)
+    __builtin_abort ();
+  _Cilk_for (int i = 3; i < 7; ++i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (int i = 3; i <= 7; i++)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (int i = 3; i != 7; i++)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (int i = 0; i < 10; i += 2)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = 0; i <= 10; i += 2)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (int i = 0; i != 10; i += 2)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = 0; i < 10; i -= -2)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = 0; i <= 10; i -= -2)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (int i = 0; i != 10; i -= -2)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (int i = 6; i > 2; --i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (int i = 7; i >= 3; i--)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (int i = 7; i != 3; i--)
+    BODY;
+  TEST (0xf0);
+  _Cilk_for (int i = 11; i > 1; i += -2)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = 11; i >= 2; i += -2)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = 11; i != 1; i += -2)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = 11; i > 1; i -= 2)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = 11; i >= 2; i -= 2)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (int i = 11; i != 1; i -= 2)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = 7UL; i < 3UL; ++i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 7UL; i <= 3UL; ++i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i != 3UL; ++i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 7UL; i < 3UL; i += 2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 7UL; i <= 3UL; i += 2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i != 3UL; i += 2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 7UL; i < 3UL; i -= -2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 7UL; i <= 3UL; i -= -2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i != 3UL; i -= -2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i > 7UL; --i)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i >= 7UL; i--)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i != 3UL; i--)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i > 7UL; i -= 2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i >= 7UL; i -= 2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i != 3UL; i -= 2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i > 7UL; i += -2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i >= 7UL; i += -2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i != 3UL; i += -2UL)
+    __builtin_abort ();
+  _Cilk_for (unsigned long int i = 3UL; i < 7UL; ++i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (unsigned long int i = 3UL; i <= 7UL; i++)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (unsigned long int i = 3UL; i != 7UL; i++)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (unsigned long int i = 0UL; i < 10UL; i += 2UL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = 0UL; i <= 10UL; i += 2UL)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (unsigned long int i = 0UL; i != 10UL; i += 2UL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = 0UL; i < 10UL; i -= -2UL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = 0UL; i <= 10UL; i -= -2UL)
+    BODY;
+  TEST (0x555);
+  _Cilk_for (unsigned long int i = 0UL; i != 10UL; i -= -2UL)
+    BODY;
+  TEST (0x155);
+  _Cilk_for (unsigned long int i = 6UL; i > 2UL; --i)
+    BODY;
+  TEST (0x78);
+  _Cilk_for (unsigned long int i = 7UL; i >= 3UL; i--)
+    BODY;
+  TEST (0xf8);
+  _Cilk_for (unsigned long int i = 7UL; i != 3UL; i--)
+    BODY;
+  TEST (0xf0);
+  _Cilk_for (unsigned long int i = 11UL; i > 1UL; i += -2UL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = 11UL; i >= 2UL; i += -2UL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = 11UL; i != 1UL; i += -2UL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = 11UL; i > 1UL; i -= 2UL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = 11UL; i >= 2UL; i -= 2UL)
+    BODY;
+  TEST (0xaa8);
+  _Cilk_for (unsigned long int i = 11UL; i != 1UL; i -= 2UL)
+    BODY;
+  TEST (0xaa8);
+  test (7, 3, 2, -2, 10, 0, 11, 6, 1, 3,
+	7UL, 3UL, 2UL, -2UL, 10UL, 0UL, 11UL, 6UL, 1UL, 3UL);
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-3.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-3.c
new file mode 100644
index 0000000..04c1635
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+void bar (int *, int *, int *, int *);
+void baz (char **, char **, char **, int *);
+
+void
+foo ()
+{
+  int a, b, c;
+  char *d, *e;
+  bar (0, &a, &b, &c);
+  _Cilk_for (int i = a; i < b; i += c)
+    bar (&i, &a, &b, &c);
+  baz (0, &d, &e, &c);
+  _Cilk_for (char *p = d; p != e; p += c)
+    baz (&p, &d, &e, &c);
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-fors.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-fors.c
new file mode 100644
index 0000000..0a8f046
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-fors.c
@@ -0,0 +1,87 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+static void check (int *Array, int start, int end, int incr, int value)
+{
+  int ii = 0;
+  for (ii = start;  ii < end; ii = ii + incr)
+    if (Array[ii] != value)
+      __builtin_abort ();
+#if HAVE_IO
+  printf ("Passed\n");
+#endif
+}
+
+static void check_reverse (int *Array, int start, int end, int incr, int value)
+{
+  int ii = 0;
+  for (ii = start; ii >= end; ii = ii - incr)
+    if (Array[ii] != value)
+      __builtin_abort ();
+#if HAVE_IO
+  printf ("Passed\n");
+#endif
+}
+
+
+int main (void)
+{
+  int Array[10];
+  int x = 9, y = 0, z = 3;
+
+
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array[ii] = 1133;
+  check (Array, 0, 10, 1, 1133);
+
+  _Cilk_for (int ii = 0; ii < 10; ++ii)
+    Array[ii] = 3311;
+  check (Array, 0, 10, 1, 3311);
+
+  _Cilk_for (int ii = 9; ii > -1; ii--)
+    Array[ii] = 4433;
+  check_reverse (Array, 9, 0, 1, 4433);
+
+  _Cilk_for (int ii = 9; ii > -1; --ii)
+    Array[ii] = 9988;
+  check_reverse (Array, 9, 0, 1, 9988);
+
+  _Cilk_for (int ii = 0; ii < 10; ++ii)
+    Array[ii] = 3311;
+  check (Array, 0, 10, 1, 3311);
+
+  _Cilk_for (int ii = 0; ii < 10; ii += 2)
+    Array[ii] = 1328;
+  check (Array, 0, 10, 2, 1328);
+
+  _Cilk_for (int ii = 9; ii >= 0; ii -= 2)
+    Array[ii] = 1738;
+  check_reverse (Array, 9, 0, 2, 1738);
+
+
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    {
+      if (ii % 2)
+	Array[ii] = 1343;
+      else
+	Array[ii] = 3413;
+    }
+
+  check (Array, 1, 10, 2, 1343);
+  check (Array, 0, 10, 2, 3413);
+
+  _Cilk_for (short cc = 0; cc < 10; cc++)
+    Array[cc] = 1343;
+  check (Array, 0, 10,  1,1343);
+
+  _Cilk_for (short cc = 9; cc >= 0; cc--)
+    Array[cc] = 1348;
+  check_reverse (Array, 9, 0, 1, 1348);
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_errors.c
new file mode 100644
index 0000000..60a9e7d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_errors.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+
+int main (void)
+{
+  int q = 0, ii = 0, jj = 0;
+
+  _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" "" { target c } } */
+    /* { dg-error "expected" "" { target c++ } 10 } */
+    q = 5;
+
+  _Cilk_for (; ii < 10; ii++) /* { dg-error "expected iteration declaration" } */
+    q = 2;
+
+  _Cilk_for (int ii = 0; ; ii++) /* { dg-error "missing controlling predicate" } */
+    q = 2;
+
+  _Cilk_for (int ii = 0; ii < 10, jj < 10; ii++)  /* { dg-error "expected ';' before ',' token" "" { target c } } */
+    /* { dg-error "invalid controlling predicate" "" { target c++ }  20 } */
+    q = 5;
+
+  _Cilk_for (int ii = 0; ii < 10; ) /* { dg-error "missing increment" } */
+    q = 5;
+
+  _Cilk_for (int ii = 0, jj = 0; ii < 10; ii++) /* { dg-error "expected|invalid" } */
+    q = 5;
+
+  _Cilk_for (volatile int vii = 0; vii < 10; vii++) /* { dg-error "iteration variable cannot be volatile" } */
+    q = 5;
+
+  _Cilk_for (static int sii = 0; sii < 10; sii++) /* { dg-error "static|expected|declared|expression" } */
+    q = 5;
+
+  _Cilk_for (float fii = 3.47; fii < 5.23; fii++) /* { dg-error "invalid type for iteration variable" } */
+    q = 5;
+
+  _Cilk_for (int ii = 0; 10 > jj; ii++) /* { dg-error "invalid controlling predicate" } */
+    q = 5;
+
+  _Cilk_for (int ii = 0; ii < 10; ii >> 1) /* { dg-error "invalid increment expression" } */
+    q = 5;
+
+  _Cilk_for (int ii = 10; ii >= 0; ii--) /* This is OK!  */
+    q = 5;
+
+  _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" "" { target c } } */
+    /* { dg-error "expected" "" { target c++ } 48 } */
+    q = 5;
+
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain.c
new file mode 100644
index 0000000..ec02613
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain.c
@@ -0,0 +1,35 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+
+int grain_value = 2;
+int main (void)
+{
+  int Array1[200], Array1_Serial[200];
+
+  for (int ii = 0; ii < 200; ii++)
+    {
+      Array1_Serial[ii] = 2;
+      Array1[ii] = 1;
+    }
+
+#pragma cilk grainsize = 2
+  _Cilk_for (int ii = 0; ii < 200; ii++)
+    Array1[ii] = 2;
+
+  for (int ii = 0; ii < 200; ii++)
+    if (Array1[ii] != Array1_Serial[ii])
+      return (ii+1);
+
+#pragma cilk grainsize = grain_value
+  _Cilk_for (int ii = 0; ii < 200; ii++)
+    Array1[ii] = 2;
+
+  for (int ii = 0; ii < 200; ii++)
+    if (Array1[ii] != Array1_Serial[ii])
+      return (ii+1);
+
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c
new file mode 100644
index 0000000..214c6be
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wunknown-pragmas" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+
+char Array1[26];
+
+#pragma cilk grainsize = 2 /* { dg-error "must be inside a function" } */
+
+int main(int argc, char **argv)
+{
+/* This is OK.  */
+#pragma cilk grainsize = 2
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+#pragma cilk grainsize 2 /* { dg-error "expected '=' before numeric constant" } */
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+#pragma cilk grainsiz = 2 /* { dg-warning "ignoring #pragma cilk grainsiz" } */
+  _Cilk_for (int 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 (int ii = 0; ii < 10; ii++)
+    Array1[ii] = 0;
+
+#pragma cilk grainsize = 1
+  while (Array1[5] != 0) /* { dg-warning "is not followed by" } */
+    {
+    /* Blah */
+    }
+
+#pragma cilk grainsize = 1
+  int q = 0; /* { dg-warning "is not followed by" } */
+  _Cilk_for (q = 0; q < 10; q++) /* { dg-error "allows expression instead of declaration" "" { target c++ } } */
+    Array1[q] = 5;
+
+  while (Array1[5] != 0)
+    {
+    /* Blah */
+    }
+
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c
new file mode 100644
index 0000000..f4a1f4c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c
@@ -0,0 +1,35 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+/* { dg-additional-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 ii = 0;
+
+  for (ii =0; ii < ARRAY_SIZE; ii++)
+    a[ii] = 5;
+  _Cilk_for(int *aa = a; aa < a + ARRAY_SIZE; aa++)
+    *aa = 0;
+  for (ii = 0; ii < ARRAY_SIZE; ii++)
+    if (a[ii] != 0)
+      __builtin_abort ();
+
+  _Cilk_for (int *aa = a; aa < a + ARRAY_SIZE; aa = aa + 2)
+    *aa = 4;
+
+  for (ii = 0; ii < ARRAY_SIZE; ii = ii + 2)
+    if (a[ii] != 4)
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/nested_cilk_for.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/nested_cilk_for.c
new file mode 100644
index 0000000..3daaca9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/nested_cilk_for.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+int main (void)
+{
+  int Array[10][10];
+
+
+  for (int ii = 0; ii < 10; ii++)
+    for (int jj = 0; jj < 10; jj++)
+	{
+	  Array[ii][jj] = 0;
+	}
+
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    _Cilk_for (int jj = 0; jj < 5; jj++)
+      Array[ii][jj] = 5;
+
+  for (int ii = 0; ii < 10; ii++)
+    for (int jj = 0; jj < 5; jj++)
+      if (Array[ii][jj] != 5)
+#if HAVE_IO
+	printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]);
+#else
+	__builtin_abort ();
+#endif
+
+
+  /* One goes up and one goes down.  */
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    _Cilk_for (int jj = 9; jj >= 0; jj--)
+      Array[ii][jj] = 7;
+
+  for (int ii = 0; ii < 10; ii++)
+    for (int jj = 9; jj >= 0; jj--)
+      if (Array[ii][jj] != 7)
+#if HAVE_IO
+	printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]);
+#else
+	__builtin_abort ();
+#endif
+
+  /* different step sizes.  */
+  _Cilk_for (int ii = 0; ii < 10; ii++)
+    _Cilk_for (int jj = 0; jj < 10; jj += 2)
+      Array[ii][jj] = 9;
+
+  for (int ii = 0; ii < 10; ii++)
+    for (int jj = 0; jj < 10; jj += 2)
+      if (Array[ii][jj] != 9)
+#if HAVE_IO
+	printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]);
+#else
+	__builtin_abort ();
+#endif
+
+  /* different step sizes.  */
+  _Cilk_for (int ii = 0; ii < 10; ii += 2)
+    _Cilk_for (int jj = 5; jj < 9; jj++)
+      Array[ii][jj] = 11;
+
+  for (int ii = 0; ii < 10; ii += 2)
+    for (int jj = 5; jj < 9; jj++)
+      if (Array[ii][jj] != 11)
+#if HAVE_IO
+	printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]);
+#else
+	__builtin_abort ();
+#endif
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cf3.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cf3.cc
new file mode 100644
index 0000000..8d88c5f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cf3.cc
@@ -0,0 +1,96 @@
+/* { dg-options "-fcilkplus" } */
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
+template <typename T>
+class I
+{
+public:
+  typedef ptrdiff_t difference_type;
+  I ();
+  ~I ();
+  I (T *);
+  I (const I &);
+  T &operator * ();
+  T *operator -> ();
+  T &operator [] (const difference_type &) const;
+  I &operator = (const I &);
+  I &operator ++ ();
+  I operator ++ (int);
+  I &operator -- ();
+  I operator -- (int);
+  I &operator += (const difference_type &);
+  I &operator -= (const difference_type &);
+  I operator + (const difference_type &) const;
+  I operator - (const difference_type &) const;
+  template <typename S> friend bool operator == (I<S> &, I<S> &);
+  template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator < (I<S> &, I<S> &);
+  template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator <= (I<S> &, I<S> &);
+  template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator > (I<S> &, I<S> &);
+  template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator >= (I<S> &, I<S> &);
+  template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+  template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+  T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+  J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+  const I<T> &begin ();
+  const I<T> &end ();
+private:
+  I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+template <typename T>
+void baz (I<T> &i);
+
+void
+foo (J<int> j)
+{
+  _Cilk_for (I<int> i = j.begin (); i < j.end (); i += 2)
+    baz (i);
+}
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..ff9a324
--- /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/for1.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/for1.cc
new file mode 100644
index 0000000..d2243ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/for1.cc
@@ -0,0 +1,376 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <cstdio>
+#endif
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+class I
+{
+public:
+  typedef ptrdiff_t difference_type;
+  I ();
+  ~I ();
+  I (T *);
+  I (const I &);
+  T &operator * ();
+  T *operator -> ();
+  T &operator [] (const difference_type &) const;
+  I &operator = (const I &);
+  I &operator ++ ();
+  I operator ++ (int);
+  I &operator -- ();
+  I operator -- (int);
+  I &operator += (const difference_type &);
+  I &operator -= (const difference_type &);
+  I operator + (const difference_type &) const;
+  I operator - (const difference_type &) const;
+  template <typename S> friend bool operator == (I<S> &, I<S> &);
+  template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator < (I<S> &, I<S> &);
+  template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator <= (I<S> &, I<S> &);
+  template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator > (I<S> &, I<S> &);
+  template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator >= (I<S> &, I<S> &);
+  template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+  template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+  T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+  J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+  const I<T> &begin ();
+  const I<T> &end ();
+private:
+  I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+  if (*i < 0 || *i >= 2000)
+    {
+#if HAVE_IO
+      printf ("*i(%d) is < 0 or >= 2000\n", *i);
+      fflush (stdout);
+#endif
+     __builtin_abort ();
+    }
+  else
+    results[*i]++;
+}
+
+void
+f1 (const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I<int> i = x; i <= y; i += 6)
+    {
+      baz (i);
+    }
+
+#if HAVE_IO
+  printf("===== Starting F1 =========\n");
+  for (I<int> i = x; i <= y; i+= 6) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I<int> i = x; i < y - 1; i += 2)
+    baz (i);
+
+#if HAVE_IO
+  printf("===== Starting F2 =========\n");
+  for (int ii = 0; ii < 1998; ii += 2) {
+    printf("Result[%4d] = %2d\n", ii, results[ii]);
+    fflush (stdout);
+  }
+#endif
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I<int> i = x; i <= y; i += 1)
+    baz (i);
+#if HAVE_IO
+  printf("===== Starting F3 =========\n");
+  for (int ii = 20; ii < 1987; ii += 1) {
+    printf("Result[%4d] = %2d\n", ii, results[ii]);
+    fflush (stdout);
+  }
+
+#endif
+}
+
+template <typename T>
+void
+f4 (const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I<int> i = x + (2000 - 64); i > y + 10; --i)
+    baz (i);
+#if HAVE_IO
+  printf("===== Starting F3 =========\n");
+  for (I<int> i = x + (2000 - 64); i > y + 10; --i) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+}
+void
+f5 (const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I<int> i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+#if HAVE_IO
+  for (I<int> i = x + 2000 - 64; i > y + 10; i -= 10) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I<int> i = x + 2000 - 64; i > y + 10; i -= 10)
+    {
+      I<int> j = i + N;
+      baz (j);
+    }
+#if HAVE_IO
+  for (I<int> i = x + 2000 - 64; i > y + 10; i = i - 12 + 2)
+    {
+      I<int> j = i + N;
+      printf("Result[%4d] = %2d\n", *j, results[*j]);
+      fflush (stdout);
+    }
+#endif
+}
+template <int N>
+void
+f7 (I<int> ii, const I<int> &x, const I<int> &y)
+{
+  _Cilk_for (I <int> i = x - 10; i <= y + 10; i += N)
+    baz (i);
+#if HAVE_IO
+  for (I<int> i = x - 10; i <= y + 10; i += N)
+    {
+      printf("Result[%4d] = %2d\n", *i, results[*i]);
+      fflush (stdout);
+    }
+#endif
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  _Cilk_for (I<int> i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+#if HAVE_IO
+  for (I<int> i = j.begin (); i <= j.end () + N; i += 2) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+  _Cilk_for (I<T> i = x; i <= y; i += N)
+    baz (i);
+#if HAVE_IO
+  for (I<T> i = x; i <= y;  i  = i + N)
+    {
+      printf("Result[%4d] = %2d\n", *i, results[*i]);
+      fflush (stdout);
+    }
+#endif
+}
+
+template <typename T, int N>
+void
+f10 (const I<T> &x, const I<T> &y)
+{
+  _Cilk_for (I<T> i = x; i > y; i += N)
+    baz (i);
+#if HAVE_IO
+  for (I<T> i = x; i > y;  i  = i + N) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+    _Cilk_for (T i = x; i <= y; i += 3)
+      baz (i);
+
+#if HAVE_IO
+  for (T i = x; i <= y;  i  += 3) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+      T j = y + 3;
+      baz (j);
+
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  _Cilk_for (T i = x; i > y; --i)
+    baz (i);
+#if HAVE_IO
+  for (T i = x; i > y;  --i) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+}
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+    _Cilk_for (T i = x; i <= y + N; i += N)
+      baz (i);
+#if HAVE_IO
+  for (T i = x; i < y+N;  i += N) {
+    printf("Result[%4d] = %2d\n", *i, results[*i]);
+    fflush (stdout);
+  }
+#endif
+  }
+};
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1) {				\
+	  __builtin_abort ();				\
+	}						\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      abort ()
+
+int
+main ()
+{
+  int a[2000];
+  long b[2000];
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  f1 (&a[10], &a[1990]);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (&a[0], &a[1999]);
+  check (i < 1998 && (i & 1) == 0);
+  f3<int> (&a[20], &a[1837]);
+  check (i >= 20 && i <= 1837);
+  f4<int> (&a[0], &a[30]);
+  check (i > 40 && i <= 2000 - 64);
+
+  f5 (&a[0], &a[100]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (&a[10], &a[110]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+
+  f7<6> (I<int> (), &a[12], &a[1800]);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+
+  f8<121> (J<int> (&a[14], &a[1803]));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (&a[33], &a[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (&a[1939], &a[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<int> > (&a[16], &a[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<int> > (&a[1761], &a[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<int> > (&a[1], &a[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  f9<long, 7> (&b[33], &b[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (&b[1939], &b[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<long> > (&b[16], &b[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<long> > (&b[1761], &b[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<long> > (&b[1], &b[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  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..d68ee7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.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 <vector>
+#include <cstdio>
+#include <iostream>
+#include <algorithm>
+
+using namespace std;
+
+
+int main(void)
+{
+vector <int> array;
+vector <int> array_serial;
+
+for (int ii = -1; ii < 10; ii++)
+{
+  array.push_back(ii);
+  array_serial.push_back (ii);
+}
+_Cilk_for (vector<int>::iterator iter = array.begin(); iter != array.end();
+	  iter++)
+{
+   if (*iter == 6)
+     *iter = 13;
+}
+for (vector<int>::iterator iter = array_serial.begin();
+     iter != array_serial.end(); iter++)
+{
+   if (*iter == 6)
+     *iter = 13;
+}
+sort (array.begin(), array.end());
+sort (array_serial.begin(), array_serial.end());
+
+vector <int>::iterator iter = array.begin ();
+vector <int>::iterator iter_serial = array_serial.begin ();
+
+while (iter != array.end () && iter_serial != array_serial.end ())
+{
+  if (*iter != *iter_serial)
+    __builtin_abort ();
+  iter++;
+  iter_serial++;
+}
+
+return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/stl_rev_iter.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_rev_iter.cc
new file mode 100644
index 0000000..6eee0d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_rev_iter.cc
@@ -0,0 +1,68 @@
+/* { 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,array_serial;
+
+for (int ii = -1; ii < 10; ii++)
+{
+  array.push_back(ii);
+  array_serial.push_back(ii);
+}
+_Cilk_for (vector<int>::reverse_iterator iter4 = array.rbegin();
+	   iter4 != array.rend(); iter4++)
+{
+  if (*iter4 == 0x8) {
+    *iter4 = 9;
+  }
+}
+
+_Cilk_for (vector<int>::reverse_iterator iter4 = array_serial.rbegin();
+	   iter4 != array_serial.rend(); iter4++)
+{
+  if (*iter4 == 0x8) {
+    *iter4 = 9;
+  }
+}
+_Cilk_for (vector<int>::reverse_iterator iter2 = array.rbegin();
+	   iter2 != array.rend();
+	  iter2 += 1)
+{
+   if ((*iter2 == 0x4) || (*iter2 == 0x7)) {
+    *iter2 = 0x3;
+   }
+}
+for (vector<int>::reverse_iterator iter2 = array_serial.rbegin();
+     iter2 != array_serial.rend();
+	  iter2 += 1)
+{
+   if ((*iter2 == 0x4) || (*iter2 == 0x7)) {
+    *iter2 = 0x3;
+   }
+}
+sort (array.begin(), array.end());
+sort (array_serial.begin(), array_serial.end());
+
+vector <int>::iterator iter = array.begin ();
+vector <int>::iterator iter_serial = array_serial.begin ();
+while (iter != array.end () && iter_serial != array_serial.end ())
+{
+  if (*iter != *iter_serial)
+    __builtin_abort ();
+  iter++;
+  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..84518f3
--- /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 = 10;
+  }
+
+
+  number_list.clear();
+  number_list_serial.clear();
+  for (int ii = 0; ii < no_elements; ii++)
+  {
+    number_list.push_back(new_number);
+    number_list_serial.push_back(new_number);
+  }
+
+  _Cilk_for (int jj = 0; jj < no_elements; jj++)
+  {
+    number_list[jj] = jj + no_elements;
+  }
+  for (int jj = 0; jj < no_elements; jj++)
+  {
+    number_list_serial[jj] = jj + no_elements;
+  }
+
+  for (int jj = 0; jj < no_elements; jj++)
+    if (number_list_serial[jj] != number_list[jj])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 9e9ca8c..0761f95 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -334,7 +334,11 @@ enum omp_clause_code {
   OMP_CLAUSE_TASKGROUP,

   /* Internally used only clause, holding SIMD uid.  */
-  OMP_CLAUSE__SIMDUID_
+  OMP_CLAUSE__SIMDUID_,
+
+  /* Internally used only clause, holding _Cilk_for # of iterations
+     on OMP_PARALLEL.  */
+  OMP_CLAUSE__CILK_FOR_COUNT_
};

 #undef DEFTREESTRUCT
@@ -351,6 +355,7 @@ enum omp_clause_schedule_kind {
   OMP_CLAUSE_SCHEDULE_GUIDED,
   OMP_CLAUSE_SCHEDULE_AUTO,
   OMP_CLAUSE_SCHEDULE_RUNTIME,
+  OMP_CLAUSE_SCHEDULE_CILKFOR,
   OMP_CLAUSE_SCHEDULE_LAST
};

diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 6ca594d..a378a02 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1115,6 +1115,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
	case OMP_CLAUSE_NUM_TEAMS:
	case OMP_CLAUSE_THREAD_LIMIT:
	case OMP_CLAUSE_SAFELEN:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  wi->val_only = true;
	  wi->is_lhs = false;
	  convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
@@ -1744,6 +1745,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
	case OMP_CLAUSE_NUM_TEAMS:
	case OMP_CLAUSE_THREAD_LIMIT:
	case OMP_CLAUSE_SAFELEN:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  wi->val_only = true;
	  wi->is_lhs = false;
	  convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index aee0331..ce0c655 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -361,6 +361,13 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
       pp_right_paren (buffer);
       break;

+    case OMP_CLAUSE__CILK_FOR_COUNT_:
+      pp_string (buffer, "_Cilk_for_count_(");
+      dump_generic_node (buffer, OMP_CLAUSE_OPERAND (clause, 0),
+			 spc, flags, false);
+      pp_right_paren (buffer);
+      break;
+
     case OMP_CLAUSE_NOWAIT:
       pp_string (buffer, "nowait");
       break;
@@ -411,6 +418,9 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
	case OMP_CLAUSE_SCHEDULE_AUTO:
	  pp_string (buffer, "auto");
	  break;
+	case OMP_CLAUSE_SCHEDULE_CILKFOR:
+	  pp_string (buffer, "cilk-for grain");
+	  break;
	default:
	  gcc_unreachable ();
	}
@@ -2421,6 +2431,12 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_string (buffer, "#pragma simd");
       goto dump_omp_loop;

+    case CILK_FOR:
+      /* This label points one line after dumping the clauses.
+	 For _Cilk_for the clauses are dumped after the _Cilk_for (...)
+	 parameters are printed out.  */
+      goto dump_omp_loop_cilk_for;
+
     case OMP_DISTRIBUTE:
       pp_string (buffer, "#pragma omp distribute");
       goto dump_omp_loop;
@@ -2449,18 +2465,22 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
     dump_omp_loop:
       dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags);

+    dump_omp_loop_cilk_for:
       if (!(flags & TDF_SLIM))
	{
	  int i;

 	  if (OMP_FOR_PRE_BODY (node))
	    {
-	      newline_and_indent (buffer, spc + 2);
+	      if (TREE_CODE (node) == CILK_FOR)
+		pp_string (buffer, "  ");
+	      else
+		newline_and_indent (buffer, spc + 2);
	      pp_left_brace (buffer);
	      spc += 4;
	      newline_and_indent (buffer, spc);
	      dump_generic_node (buffer, OMP_FOR_PRE_BODY (node),
-		  spc, flags, false);
+				 spc, flags, false);
	    }
	  if (OMP_FOR_INIT (node))
	    {
@@ -2468,8 +2488,12 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
	      for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++)
		{
		  spc += 2;
-		  newline_and_indent (buffer, spc);
-		  pp_string (buffer, "for (");
+		  if (TREE_CODE (node) != CILK_FOR || OMP_FOR_PRE_BODY (node))
+		    newline_and_indent (buffer, spc);
+		  if (TREE_CODE (node) == CILK_FOR)
+		    pp_string (buffer, "_Cilk_for (");
+		  else
+		    pp_string (buffer, "for (");
		  dump_generic_node (buffer,
				     TREE_VEC_ELT (OMP_FOR_INIT (node), i),
				     spc, flags, false);
@@ -2483,6 +2507,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
				     spc, flags, false);
		  pp_right_paren (buffer);
		}
+	      if (TREE_CODE (node) == CILK_FOR)
+		dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags);
	    }
	  if (OMP_FOR_BODY (node))
	    {
diff --git a/gcc/tree.c b/gcc/tree.c
index 33922a0..d1d67ef 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -281,6 +281,7 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_SECTIONS  */
   0, /* OMP_CLAUSE_TASKGROUP  */
   1, /* OMP_CLAUSE__SIMDUID_  */
+  1, /* OMP_CLAUSE__CILK_FOR_COUNT_  */
};

 const char * const omp_clause_code_name[] =
@@ -324,7 +325,8 @@ const char * const omp_clause_code_name[] =
   "parallel",
   "sections",
   "taskgroup",
-  "_simduid_"
+  "_simduid_",
+  "_Cilk_for_count_"
};

 
@@ -11041,6 +11043,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
	case OMP_CLAUSE_SIMDLEN:
	case OMP_CLAUSE__LOOPTEMP_:
	case OMP_CLAUSE__SIMDUID_:
+	case OMP_CLAUSE__CILK_FOR_COUNT_:
	  WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
	  /* FALLTHRU */

diff --git a/gcc/tree.def b/gcc/tree.def
index 84ffe93..bd39e4b 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1064,6 +1064,10 @@ DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
    Operands like for OMP_FOR.  */
DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6)

+/* Cilk Plus - _Cilk_for (..)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (CILK_FOR, "cilk_for", tcc_statement, 6)
+
/* OpenMP - #pragma omp distribute [clause1 ... clauseN]
    Operands like for OMP_FOR.  */
DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]