]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Makefile.in (C_COMMON_OBJS): Depend on c-cilkplus.o.
authorAldy Hernandez <aldyh@redhat.com>
Fri, 15 Nov 2013 21:43:59 +0000 (21:43 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Fri, 15 Nov 2013 21:43:59 +0000 (21:43 +0000)
* Makefile.in (C_COMMON_OBJS): Depend on c-cilkplus.o.
* gimple-pretty-print.c (dump_omp_for): Add case for
GF_OMP_FOR_KIND_CILKSIMD.
* gimple.h (enum gf_mask): Restructure entries to add
GF_OMP_FOR_KIND_CILKSIMD.
* gimplify.c (is_gimple_stmt): Add case for CILK_SIMD.
(gimplify_omp_for): Handle CILK_SIMD.
(gimplify_expr): Add ccase for CILK_SIMD.
* omp-low.c (extract_omp_for_data): Handle CILK_SIMD.
(build_outer_var_ref): Same.
(check_omp_nesting_restrictions): Same.
(lower_rec_input_clauses): Same.
(lower_lastprivate_clauses): Same.
(expand_omp_for): Same.
(execute_expand_omp): Check flag_enable_cilkplus.
(execute_lower_omp): Same.
(diagnose_sb_0): Handle CILK_SIMD.
(diagnose_omp_structured_block_errors): Check
flag_enable_cilkplus.
(setjmp_or_longjmp_p): New.
(scan_omp_1_stmt): Error on setjmp/longjmp in a simd construct.
* tree-pretty-print.c (dump_generic_node): Add case for CILK_SIMD.
* tree.def: Add tree code for CILK_SIMD.

testsuite/
* c-c++-common/cilk-plus/PS: New directory.
* g++.dg/cilk-plus/cilk-plus.exp: Run shared tests.
* g++.dg/dg.exp: Run Cilk Plus tests.
* gcc.dg/cilk-plus/cilk-plus.exp: Run shared tests.

c-family/
* c-cilkplus.c: New file.
* c-common.c (readonly_error): Add location argument.
* c-common.h (readonly_error): Same.
(c_finish_cilk_clauses): Protoize.
(c_check_cilk_loop): Same.
c-omp.c (c_finish_omp_for): Handle CILK_SIMD nodes.
Do not fail on error_mark_node.
Abstract increment canonicalization to here...
(c_omp_for_incr_canonicalize_ptr): New.
c-pragma.c (init_pragma): Register "simd" pragma.
c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_SIMD.
(enum pragma_cilk_clause): New.

c/
* c-parser.c (c_parser_cilk_simd): New.
(c_parser_cilk_verify_simd): New.
(c_parser_pragma): Add case for PRAGMA_CILK_SIMD.
(c_parser_omp_for_loop): Add case for NE_EXPR.
Set c_break_label for CILK_SIMD.
(c_parser_cilk_clause_vectorlength): New.
(c_parser_cilk_clause_linear): New.
(c_parser_cilk_clause_name): New.
(c_parser_cilk_all_clauses): New.
* c-typeck.c (build_unary_op): Pass location argument to
readonly_error.
(build_modify_expr): Same.
(build_asm_expr): Same.
(c_finish_bc_stmt): Error on break/continue in loops.

cp/
* Make-lang.in (CXX_AND_OBJCXX_OBJS): Depend on cp/cp-cilkplus.o.
* cp-cilkplus.c: New file.
* cp-tree.h (cpp_validate_cilk_plus_loop): Protoize.
* parser.c (cp_parser_cilk_simd): New.
(cp_debug_parser): Add case for IN_CILK_SIMD_FOR.
(cp_parser_jump_statement): Same.
(cp_parser_omp_for_cond): Add new argument.
Add case for NE_EXPR.
(cp_parser_omp_for_loop): Pass new argument to
cp_parser_omp_for_cond.
Handle CILK_SIMD nodes.
Abstract initilization code to..
(cp_parser_omp_for_loop_init): ...here.
(cp_parser_pragma): Add case for PRAGMA_CILK_SIMD.
(cp_parser_cilk_simd_vectorlength): New.
(cp_parser_cilk_simd_linear): New.
(cp_parser_cilk_simd_clause_name): New.
(cp_parser_cilk_simd_all_clauses): New.
(cp_parser_cilk_simd): New.
* parser.h (IN_CILK_SIMD_FOR): New macro.
* pt.c (tsubst_expr): Add case for CILK_SIMD.
* typeck2.c (cxx_readonly_error): Pass location argument to
readonly_error.

From-SVN: r204863

50 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/c-family/ChangeLog
gcc/c-family/c-cilkplus.c [new file with mode: 0644]
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.c
gcc/c-family/c-pragma.h
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/cp-cilkplus.c [new file with mode: 0644]
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/parser.h
gcc/cp/pt.c
gcc/cp/typeck2.c
gcc/gimple-pretty-print.c
gcc/gimple.h
gcc/gimplify.c
gcc/omp-low.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/cilk-plus/PS/body.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp
gcc/testsuite/g++.dg/cilk-plus/for.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/for2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/for3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/for4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/dg.exp
gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
gcc/testsuite/gcc.dg/cilk-plus/for1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cilk-plus/for2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cilk-plus/jump.c [new file with mode: 0644]
gcc/tree-pretty-print.c
gcc/tree.def

index 6a3e7cc78f04f2f97513190b6fdb0ad770ccb3bf..53be213434c68da976201a4eb172ddab9d0335d8 100644 (file)
@@ -1,3 +1,29 @@
+2013-11-15  Aldy Hernandez  <aldyh@redhat.com>
+
+       * Makefile.in (C_COMMON_OBJS): Depend on c-cilkplus.o.
+       * gimple-pretty-print.c (dump_omp_for): Add case for
+       GF_OMP_FOR_KIND_CILKSIMD.
+       * gimple.h (enum gf_mask): Restructure entries to add
+       GF_OMP_FOR_KIND_CILKSIMD.
+       * gimplify.c (is_gimple_stmt): Add case for CILK_SIMD.
+       (gimplify_omp_for): Handle CILK_SIMD.
+       (gimplify_expr): Add ccase for CILK_SIMD.
+       * omp-low.c (extract_omp_for_data): Handle CILK_SIMD.
+       (build_outer_var_ref): Same.
+       (check_omp_nesting_restrictions): Same.
+       (lower_rec_input_clauses): Same.
+       (lower_lastprivate_clauses): Same.
+       (expand_omp_for): Same.
+       (execute_expand_omp): Check flag_enable_cilkplus.
+       (execute_lower_omp): Same.
+       (diagnose_sb_0): Handle CILK_SIMD.
+       (diagnose_omp_structured_block_errors): Check
+       flag_enable_cilkplus.
+       (setjmp_or_longjmp_p): New.
+       (scan_omp_1_stmt): Error on setjmp/longjmp in a simd construct.
+       * tree-pretty-print.c (dump_generic_node): Add case for CILK_SIMD.
+       * tree.def: Add tree code for CILK_SIMD.
+
 2013-11-15  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * config/rs6000/altivec.md (UNSPEC_VPERM_X, UNSPEC_VPERM_UNS_X):
index 806b6caa8ceb9f75005f3d48fe1a1bdec4fb9f94..77fba80cffc57d9e29cb2cb44f97b010d120d5be 100644 (file)
@@ -1138,6 +1138,7 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
   c-family/c-semantics.o c-family/c-ada-spec.o \
+  c-family/c-cilkplus.o \
   c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o
 
 # Language-independent object files.
index 0c97da83e93fb3ed5235a4d29aaa5eb11ad96708..9f884b6c8451be59e5f091e6ea936b4fa811a569 100644 (file)
@@ -1,3 +1,18 @@
+2013-11-15  Aldy Hernandez  <aldyh@redhat.com>
+
+       * c-cilkplus.c: New file.
+       * c-common.c (readonly_error): Add location argument.
+       * c-common.h (readonly_error): Same.
+       (c_finish_cilk_clauses): Protoize.
+       (c_check_cilk_loop): Same.
+       c-omp.c (c_finish_omp_for): Handle CILK_SIMD nodes.
+       Do not fail on error_mark_node.
+       Abstract increment canonicalization to here...
+       (c_omp_for_incr_canonicalize_ptr): New.
+       c-pragma.c (init_pragma): Register "simd" pragma.
+       c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_SIMD.
+       (enum pragma_cilk_clause): New.
+
 2013-11-15  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * c-pretty-print.c (pp_c_character_constant): Remove unnecessary
diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
new file mode 100644 (file)
index 0000000..6fa979d
--- /dev/null
@@ -0,0 +1,93 @@
+/* This file contains routines to construct and validate Cilk Plus
+   constructs within the C and C++ front ends.
+
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "c-common.h"
+
+/* Validate the body of a _Cilk_for construct or a <#pragma simd> for
+   loop.
+
+   Returns true if there were no errors, false otherwise.  */
+
+bool
+c_check_cilk_loop (location_t loc, tree decl)
+{
+  if (TREE_THIS_VOLATILE (decl))
+    {
+      error_at (loc, "iteration variable cannot be volatile");
+      return false;
+    }
+  return true;
+}
+
+/* Validate and emit code for <#pragma simd> clauses.  */
+
+tree
+c_finish_cilk_clauses (tree clauses)
+{
+  for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+    {
+      tree prev = clauses;
+
+      /* If a variable appears in a linear clause it cannot appear in
+        any other OMP clause.  */
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
+       for (tree c2 = clauses; c2; c2 = OMP_CLAUSE_CHAIN (c2))
+         {
+           if (c == c2)
+             continue;
+           enum omp_clause_code code = OMP_CLAUSE_CODE (c2);
+
+           switch (code)
+             {
+             case OMP_CLAUSE_LINEAR:
+             case OMP_CLAUSE_PRIVATE:
+             case OMP_CLAUSE_FIRSTPRIVATE:
+             case OMP_CLAUSE_LASTPRIVATE:
+             case OMP_CLAUSE_REDUCTION:
+               break;
+
+             case OMP_CLAUSE_SAFELEN:
+               goto next;
+
+             default:
+               gcc_unreachable ();
+             }
+
+           if (OMP_CLAUSE_DECL (c) == OMP_CLAUSE_DECL (c2))
+             {
+               error_at (OMP_CLAUSE_LOCATION (c2),
+                         "variable appears in more than one clause");
+               inform (OMP_CLAUSE_LOCATION (c),
+                       "other clause defined here");
+               // Remove problematic clauses.
+               OMP_CLAUSE_CHAIN (prev) = OMP_CLAUSE_CHAIN (c2);
+             }
+         next:
+           prev = c2;
+         }
+    }
+  return clauses;
+}
index 7955bb1bb155080aaaca044b3262911ec634d614..d7d5cb20a17788530ab29d2db85febc35493b589 100644 (file)
@@ -9816,7 +9816,7 @@ warn_for_omitted_condop (location_t location, tree cond)
    how ARG was being used.  */
 
 void
-readonly_error (tree arg, enum lvalue_use use)
+readonly_error (location_t loc, tree arg, enum lvalue_use use)
 {
   gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
              || use == lv_asm);
@@ -9829,59 +9829,59 @@ readonly_error (tree arg, enum lvalue_use use)
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-        error (READONLY_MSG (G_("assignment of member "
-                               "%qD in read-only object"),
-                            G_("increment of member "
-                               "%qD in read-only object"),
-                            G_("decrement of member "
-                               "%qD in read-only object"),
-                            G_("member %qD in read-only object "
-                               "used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
+        error_at (loc, READONLY_MSG (G_("assignment of member "
+                                       "%qD in read-only object"),
+                                    G_("increment of member "
+                                       "%qD in read-only object"),
+                                    G_("decrement of member "
+                                       "%qD in read-only object"),
+                                    G_("member %qD in read-only object "
+                                       "used as %<asm%> output")),
+                 TREE_OPERAND (arg, 1));
       else
-       error (READONLY_MSG (G_("assignment of read-only member %qD"),
-                            G_("increment of read-only member %qD"),
-                            G_("decrement of read-only member %qD"),
-                            G_("read-only member %qD used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
+       error_at (loc, READONLY_MSG (G_("assignment of read-only member %qD"),
+                                    G_("increment of read-only member %qD"),
+                                    G_("decrement of read-only member %qD"),
+                                    G_("read-only member %qD used as %<asm%> output")),
+                 TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
-                        G_("increment of read-only variable %qD"),
-                        G_("decrement of read-only variable %qD"),
-                        G_("read-only variable %qD used as %<asm%> output")),
-          arg);
+    error_at (loc, READONLY_MSG (G_("assignment of read-only variable %qD"),
+                                G_("increment of read-only variable %qD"),
+                                G_("decrement of read-only variable %qD"),
+                                G_("read-only variable %qD used as %<asm%> output")),
+             arg);
   else if (TREE_CODE (arg) == PARM_DECL)
-    error (READONLY_MSG (G_("assignment of read-only parameter %qD"),
-                        G_("increment of read-only parameter %qD"),
-                        G_("decrement of read-only parameter %qD"),
-                        G_("read-only parameter %qD use as %<asm%> output")),
-          arg);  
+    error_at (loc, READONLY_MSG (G_("assignment of read-only parameter %qD"),
+                                G_("increment of read-only parameter %qD"),
+                                G_("decrement of read-only parameter %qD"),
+                                G_("read-only parameter %qD use as %<asm%> output")),
+             arg);
   else if (TREE_CODE (arg) == RESULT_DECL)
     {
       gcc_assert (c_dialect_cxx ());
-      error (READONLY_MSG (G_("assignment of "
-                             "read-only named return value %qD"),
-                          G_("increment of "
-                             "read-only named return value %qD"),
-                          G_("decrement of "
-                             "read-only named return value %qD"),
-                          G_("read-only named return value %qD "
-                             "used as %<asm%>output")),
-            arg);
+      error_at (loc, READONLY_MSG (G_("assignment of "
+                                     "read-only named return value %qD"),
+                                  G_("increment of "
+                                     "read-only named return value %qD"),
+                                  G_("decrement of "
+                                     "read-only named return value %qD"),
+                                  G_("read-only named return value %qD "
+                                     "used as %<asm%>output")),
+               arg);
     }
   else if (TREE_CODE (arg) == FUNCTION_DECL)
-    error (READONLY_MSG (G_("assignment of function %qD"),
-                        G_("increment of function %qD"),
-                        G_("decrement of function %qD"),
-                        G_("function %qD used as %<asm%> output")),
-          arg);
+    error_at (loc, READONLY_MSG (G_("assignment of function %qD"),
+                                G_("increment of function %qD"),
+                                G_("decrement of function %qD"),
+                                G_("function %qD used as %<asm%> output")),
+             arg);
   else
-    error (READONLY_MSG (G_("assignment of read-only location %qE"),
-                        G_("increment of read-only location %qE"),
-                        G_("decrement of read-only location %qE"),
-                        G_("read-only location %qE used as %<asm%> output")),
-          arg);
+    error_at (loc, READONLY_MSG (G_("assignment of read-only location %qE"),
+                                G_("increment of read-only location %qE"),
+                                G_("decrement of read-only location %qE"),
+                                G_("read-only location %qE used as %<asm%> output")),
+             arg);
 }
 
 /* Print an error message for an invalid lvalue.  USE says
index d9d2c44097aa1f004e43639f6c88924093bcd116..b931fd6d2a8625b671ca366bc767780eff7c0da7 100644 (file)
@@ -970,7 +970,7 @@ enum lvalue_use {
   lv_asm
 };
 
-extern void readonly_error (tree, enum lvalue_use);
+extern void readonly_error (location_t, tree, enum lvalue_use);
 extern void lvalue_error (location_t, enum lvalue_use);
 extern void invalid_indirection_error (location_t, tree, ref_operator);
 
@@ -1289,6 +1289,11 @@ enum stv_conv {
 extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
                                       tree op0, tree op1, bool);
 
+/* In c-cilkplus.c  */
+extern tree c_finish_cilk_clauses (tree);
+extern tree c_validate_cilk_plus_loop (tree *, int *, void *);
+extern bool c_check_cilk_loop (location_t, tree);
+
 /* These #defines allow users to access different operands of the
    array notation tree.  */
 
index b342bd216cbb71be1276f06f227181cf87ef5607..921b40628c364fb153936357f4a35b50e74e8518 100644 (file)
@@ -349,6 +349,28 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
   return error_mark_node;
 }
 
+/* If the OMP_FOR increment expression in INCR is of pointer type,
+   canonicalize it into an expression handled by gimplify_omp_for()
+   and return it.  DECL is the iteration variable.  */
+
+static tree
+c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
+{
+  if (POINTER_TYPE_P (TREE_TYPE (decl))
+      && TREE_OPERAND (incr, 1))
+    {
+      tree t = fold_convert_loc (loc,
+                                sizetype, TREE_OPERAND (incr, 1));
+
+      if (TREE_CODE (incr) == POSTDECREMENT_EXPR
+         || TREE_CODE (incr) == PREDECREMENT_EXPR)
+       t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
+      t = fold_build_pointer_plus (decl, t);
+      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
+    }
+  return incr;
+}
+
 /* Validate and emit code for the OpenMP directive #pragma omp for.
    DECLV is a vector of iteration variables, for each collapsed loop.
    INITV, CONDV and INCRV are vectors containing initialization
@@ -364,6 +386,10 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
   bool fail = false;
   int i;
 
+  if (code == CILK_SIMD
+      && !c_check_cilk_loop (locus, TREE_VEC_ELT (declv, 0)))
+    fail = true;
+
   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
@@ -407,8 +433,11 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
                                    init,
                                    NULL_TREE);
        }
-      gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
-      gcc_assert (TREE_OPERAND (init, 0) == decl);
+      if (init != error_mark_node)
+       {
+         gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+         gcc_assert (TREE_OPERAND (init, 0) == decl);
+       }
 
       if (cond == NULL_TREE)
        {
@@ -487,7 +516,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
+                 else if (code != CILK_SIMD)
                    cond_ok = false;
                }
            }
@@ -523,18 +552,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
                break;
 
              incr_ok = true;
-             if (POINTER_TYPE_P (TREE_TYPE (decl))
-                 && TREE_OPERAND (incr, 1))
-               {
-                 tree t = fold_convert_loc (elocus,
-                                            sizetype, TREE_OPERAND (incr, 1));
-
-                 if (TREE_CODE (incr) == POSTDECREMENT_EXPR
-                     || TREE_CODE (incr) == PREDECREMENT_EXPR)
-                   t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
-                 t = fold_build_pointer_plus (decl, t);
-                 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
-               }
+             incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
              break;
 
            case MODIFY_EXPR:
index c75b0872b446c935e76457ab8fab05a62334a5e2..029ab1e33acebc55be6c550e056c9f65ed5bbbd8 100644 (file)
@@ -1380,6 +1380,10 @@ init_pragma (void)
                                      omp_pragmas_simd[i].id, true, true);
     }
 
+  if (flag_enable_cilkplus && !flag_preprocess_only)
+    cpp_register_deferred_pragma (parse_in, NULL, "simd", PRAGMA_CILK_SIMD,
+                                 true, false);
+
   if (!flag_preprocess_only)
     cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
                                  PRAGMA_GCC_PCH_PREPROCESS, false, false);
index 705bcb472a90a26f05e2b2511e60ff86c33555e6..5379b9e4eb82b178060ff597c8dc11b18018d939 100644 (file)
@@ -52,6 +52,9 @@ typedef enum pragma_kind {
   PRAGMA_OMP_THREADPRIVATE,
   PRAGMA_OMP_TEAMS,
 
+  /* Top level clause to handle all Cilk Plus pragma simd clauses.  */
+  PRAGMA_CILK_SIMD,
+
   PRAGMA_GCC_PCH_PREPROCESS,
   PRAGMA_IVDEP,
 
@@ -103,6 +106,17 @@ typedef enum pragma_omp_clause {
   PRAGMA_OMP_CLAUSE_UNTIED
 } pragma_omp_clause;
 
+/* All Cilk Plus #pragma omp clauses.  */
+typedef enum pragma_cilk_clause {
+  PRAGMA_CILK_CLAUSE_NONE = 0,
+  PRAGMA_CILK_CLAUSE_VECTORLENGTH,
+  PRAGMA_CILK_CLAUSE_LINEAR,
+  PRAGMA_CILK_CLAUSE_PRIVATE,
+  PRAGMA_CILK_CLAUSE_FIRSTPRIVATE,
+  PRAGMA_CILK_CLAUSE_LASTPRIVATE,
+  PRAGMA_CILK_CLAUSE_REDUCTION
+} pragma_cilk_clause;
+
 extern struct cpp_reader* parse_in;
 
 /* It's safe to always leave visibility pragma enabled as if
index 6d390095fdee5bb54875960d40bb926c88489d8d..f1b1a4961853c7e4b8a7176caddd93b30c82962c 100644 (file)
@@ -1,3 +1,20 @@
+2013-11-15  Aldy Hernandez  <aldyh@redhat.com>
+
+       * c-parser.c (c_parser_cilk_simd): New.
+       (c_parser_cilk_verify_simd): New.
+       (c_parser_pragma): Add case for PRAGMA_CILK_SIMD.
+       (c_parser_omp_for_loop): Add case for NE_EXPR.
+       Set c_break_label for CILK_SIMD.
+       (c_parser_cilk_clause_vectorlength): New.
+       (c_parser_cilk_clause_linear): New.
+       (c_parser_cilk_clause_name): New.
+       (c_parser_cilk_all_clauses): New.
+       * c-typeck.c (build_unary_op): Pass location argument to
+       readonly_error.
+       (build_modify_expr): Same.
+       (build_asm_expr): Same.
+       (c_finish_bc_stmt): Error on break/continue in loops.
+
 2013-11-14  Andrew MacLeod  <amacleod@redhat.com>
 
        * c-typeck.c: Include only gimplify.h and gimple.h as needed.
index ffbf3c41f93d4d2125bdebbfc4ea8f0a2169b512..6f034029151f58d6749ae2ab7ee0485ad49ba685 100644 (file)
@@ -1237,6 +1237,9 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
+/* Cilk Plus supporting routines.  */
+static void c_parser_cilk_simd (c_parser *);
+static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
 static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
@@ -9371,6 +9374,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
       return false;
 
+    case PRAGMA_CILK_SIMD:
+      if (!c_parser_cilk_verify_simd (parser, context))
+       return false;
+      c_parser_consume_pragma (parser);
+      c_parser_cilk_simd (parser);
+      return false;
+
     default:
       if (id < PRAGMA_FIRST_EXTERNAL)
        {
@@ -11543,6 +11553,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
            case LT_EXPR:
            case LE_EXPR:
              break;
+           case NE_EXPR:
+             if (code == CILK_SIMD)
+               break;
+             /* FALLTHRU.  */
            default:
              /* Can't be cond = error_mark_node, because we want to preserve
                 the location until c_finish_omp_for.  */
@@ -11616,7 +11630,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
     }
 
   save_break = c_break_label;
-  c_break_label = size_one_node;
+  if (code == CILK_SIMD)
+    c_break_label = build_int_cst (size_type_node, 2);
+  else
+    c_break_label = size_one_node;
   save_cont = c_cont_label;
   c_cont_label = NULL_TREE;
   body = push_stmt_list ();
@@ -13311,7 +13328,252 @@ c_parser_omp_threadprivate (c_parser *parser)
 
   c_parser_skip_to_pragma_eol (parser);
 }
+\f
+/* Cilk Plus <#pragma simd> parsing routines.  */
+
+/* Helper function for c_parser_pragma.  Perform some sanity checking
+   for <#pragma simd> constructs.  Returns FALSE if there was a
+   problem.  */
+
+static bool
+c_parser_cilk_verify_simd (c_parser *parser,
+                                 enum pragma_context context)
+{
+  if (!flag_enable_cilkplus)
+    {
+      warning (0, "pragma simd ignored because -fcilkplus is not enabled");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  if (context == pragma_external)
+    {
+      c_parser_error (parser,"pragma simd must be inside a function");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+    }
+  return true;
+}
+
+/* Cilk Plus:
+   vectorlength ( constant-expression ) */
+
+static tree
+c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses)
+{
+  /* The vectorlength clause behaves exactly like OpenMP's safelen
+     clause.  Represent it in OpenMP terms.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength");
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree expr = c_parser_expr_no_commas (parser, NULL).value;
+  expr = c_fully_fold (expr, false, NULL);
+
+  if (!TREE_TYPE (expr)
+      || !TREE_CONSTANT (expr)
+      || !INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+    error_at (loc, "vectorlength must be an integer constant");
+  else if (exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
+    error_at (loc, "vectorlength must be a power of 2");
+  else
+    {
+      tree u = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+      OMP_CLAUSE_SAFELEN_EXPR (u) = expr;
+      OMP_CLAUSE_CHAIN (u) = clauses;
+      clauses = u;
+    }
+
+  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  return clauses;
+}
+
+/* Cilk Plus:
+   linear ( simd-linear-variable-list )
+
+   simd-linear-variable-list:
+     simd-linear-variable
+     simd-linear-variable-list , simd-linear-variable
+
+   simd-linear-variable:
+     id-expression
+     id-expression : simd-linear-step
+
+   simd-linear-step:
+   conditional-expression */
+
+static tree
+c_parser_cilk_clause_linear (c_parser *parser, tree clauses)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return clauses;
+
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  if (c_parser_next_token_is_not (parser, CPP_NAME)
+      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+    c_parser_error (parser, "expected identifier");
+
+  while (c_parser_next_token_is (parser, CPP_NAME)
+        && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+    {
+      tree var = lookup_name (c_parser_peek_token (parser)->value);
+
+      if (var == NULL)
+       {
+         undeclared_variable (c_parser_peek_token (parser)->location,
+                              c_parser_peek_token (parser)->value);
+       c_parser_consume_token (parser);
+       }
+      else if (var == error_mark_node)
+       c_parser_consume_token (parser);
+      else
+       {
+         tree step = integer_one_node;
+
+         /* Parse the linear step if present.  */
+         if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+           {
+             c_parser_consume_token (parser);
+             c_parser_consume_token (parser);
+
+             tree expr = c_parser_expr_no_commas (parser, NULL).value;
+             expr = c_fully_fold (expr, false, NULL);
+
+             if (TREE_TYPE (expr)
+                 && INTEGRAL_TYPE_P (TREE_TYPE (expr))
+                 && (TREE_CONSTANT (expr)
+                     || DECL_P (expr)))
+               step = expr;
+             else
+               c_parser_error (parser,
+                               "step size must be an integer constant "
+                               "expression or an integer variable");
+           }
+         else
+           c_parser_consume_token (parser);
+
+         /* Use OMP_CLAUSE_LINEAR, which has the same semantics.  */
+         tree u = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+         OMP_CLAUSE_DECL (u) = var;
+         OMP_CLAUSE_LINEAR_STEP (u) = step;
+         OMP_CLAUSE_CHAIN (u) = clauses;
+         clauses = u;
+       }
+
+      if (c_parser_next_token_is_not (parser, CPP_COMMA))
+       break;
+
+      c_parser_consume_token (parser);
+    }
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  return clauses;
+}
+
+/* Returns the name of the next clause.  If the clause is not
+   recognized SIMD_OMP_CLAUSE_NONE is returned and the next token is
+   not consumed.  Otherwise, the appropriate pragma_simd_clause is
+   returned and the token is consumed.  */
+
+static pragma_cilk_clause
+c_parser_cilk_clause_name (c_parser *parser)
+{
+  pragma_cilk_clause result;
+  c_token *token = c_parser_peek_token (parser);
+
+  if (!token->value || token->type != CPP_NAME)
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  const char *p = IDENTIFIER_POINTER (token->value);
+
+  if (!strcmp (p, "vectorlength"))
+    result = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (p, "linear"))
+    result = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (p, "private"))
+    result = PRAGMA_CILK_CLAUSE_PRIVATE;
+  else if (!strcmp (p, "firstprivate"))
+    result = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
+  else if (!strcmp (p, "lastprivate"))
+    result = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
+  else if (!strcmp (p, "reduction"))
+    result = PRAGMA_CILK_CLAUSE_REDUCTION;
+  else
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  c_parser_consume_token (parser);
+  return result;
+}
+
+/* Parse all #<pragma simd> clauses.  Return the list of clauses
+   found.  */
+
+static tree
+c_parser_cilk_all_clauses (c_parser *parser)
+{
+  tree clauses = NULL;
+
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      pragma_cilk_clause c_kind;
+
+      c_kind = c_parser_cilk_clause_name (parser);
+
+      switch (c_kind)
+       {
+       case PRAGMA_CILK_CLAUSE_VECTORLENGTH:
+         clauses = c_parser_cilk_clause_vectorlength (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_LINEAR:
+         clauses = c_parser_cilk_clause_linear (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_PRIVATE:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_private (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_FIRSTPRIVATE:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_firstprivate (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_LASTPRIVATE:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+         break;
+       case PRAGMA_CILK_CLAUSE_REDUCTION:
+         /* Use the OpenMP counterpart.  */
+         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         break;
+       default:
+         c_parser_error (parser, "expected %<#pragma simd%> clause");
+         goto saw_error;
+       }
+    }
+
+ saw_error:
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_cilk_clauses (clauses);
+}
+
+/* Main entry point for parsing Cilk Plus <#pragma simd> for
+   loops.  */
 
+static void
+c_parser_cilk_simd (c_parser *parser ATTRIBUTE_UNUSED)
+{
+  char p_name[100];
+  strcpy (p_name, "#pragma omp");
+  tree clauses = c_parser_cilk_all_clauses (parser);
+  tree block = c_begin_compound_stmt (true);
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL);
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+}
+\f
 /* Parse a transaction attribute (GCC Extension).
 
    transaction-attribute:
index a9c9e6eb02aaf3103bb1a21c6f631bb13a5c2b73..a823f1439f3e77bf7c954724be6fa9a8b02769b8 100644 (file)
@@ -4055,7 +4055,7 @@ build_unary_op (location_t location,
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
-           readonly_error (arg,
+           readonly_error (location, arg,
                            ((code == PREINCREMENT_EXPR
                              || code == POSTINCREMENT_EXPR)
                             ? lv_increment : lv_decrement));
@@ -5266,7 +5266,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
     {
-      readonly_error (lhs, lv_assign);
+      readonly_error (location, lhs, lv_assign);
       return error_mark_node;
     }
   else if (TREE_READONLY (lhs))
@@ -8949,7 +8949,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
              || ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE
                   || TREE_CODE (TREE_TYPE (output)) == UNION_TYPE)
                  && C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
-       readonly_error (output, lv_asm);
+       readonly_error (loc, output, lv_asm);
 
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       oconstraints[i] = constraint;
@@ -9576,6 +9576,13 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
       error_at (loc, "break statement used with OpenMP for loop");
       return NULL_TREE;
 
+    case 2:
+      if (is_break) 
+       error ("break statement within %<#pragma simd%> loop body");
+      else 
+       error ("continue statement within %<#pragma simd%> loop body");
+      return NULL_TREE;
+
     default:
       gcc_unreachable ();
     }
index b252637421f7d05763295fb169ac63c73f65e566..2a16220dda212cf25df57206f83368a30d1b6a3f 100644 (file)
@@ -1,3 +1,29 @@
+2013-11-15  Aldy Hernandez  <aldyh@redhat.com>
+
+       * Make-lang.in (CXX_AND_OBJCXX_OBJS): Depend on cp/cp-cilkplus.o.
+       * cp-cilkplus.c: New file.
+       * cp-tree.h (cpp_validate_cilk_plus_loop): Protoize.
+       * parser.c (cp_parser_cilk_simd): New.
+       (cp_debug_parser): Add case for IN_CILK_SIMD_FOR.
+       (cp_parser_jump_statement): Same.
+       (cp_parser_omp_for_cond): Add new argument.
+       Add case for NE_EXPR.
+       (cp_parser_omp_for_loop): Pass new argument to
+       cp_parser_omp_for_cond.
+       Handle CILK_SIMD nodes.
+       Abstract initilization code to..
+       (cp_parser_omp_for_loop_init): ...here.
+       (cp_parser_pragma): Add case for PRAGMA_CILK_SIMD.
+       (cp_parser_cilk_simd_vectorlength): New.
+       (cp_parser_cilk_simd_linear): New.
+       (cp_parser_cilk_simd_clause_name): New.
+       (cp_parser_cilk_simd_all_clauses): New.
+       (cp_parser_cilk_simd): New.
+       * parser.h (IN_CILK_SIMD_FOR): New macro.
+       * pt.c (tsubst_expr): Add case for CILK_SIMD.
+       * typeck2.c (cxx_readonly_error): Pass location argument to
+       readonly_error.
+
 2013-11-14  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/57887
index 9bcea20bd022335cb8585ca6e5063ba9a03202ec..424f2e6cdc509260ee86427eeffb51728c3fa65e 100644 (file)
@@ -76,6 +76,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
+ cp/cp-cilkplus.o \
  cp/cp-gimplify.o cp/cp-array-notation.o cp/lambda.o \
  cp/vtable-class-hierarchy.o $(CXX_C_OBJS)
 
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
new file mode 100644 (file)
index 0000000..5c1090a
--- /dev/null
@@ -0,0 +1,77 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains routines to handle Cilk Plus specific
+   routines for the C++ Compiler.
+   Copyright (C) 2013  Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cp-tree.h"
+#include "diagnostic-core.h"
+
+
+/* Callback for cp_walk_tree to validate the body of a pragma simd loop
+   or _cilk_for loop.
+
+   This function is passed in as a function pointer to walk_tree.  *TP is
+   the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
+   recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
+   is set to false if an error has occured.  */
+
+static tree
+cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data)
+{
+  bool *valid = (bool *) data;
+  location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
+    UNKNOWN_LOCATION;
+
+  if (!tp || !*tp)
+    return NULL_TREE;
+
+  if (TREE_CODE (*tp) == THROW_EXPR)
+    {
+      error_at (loc, "throw expressions are not allowed inside loops "
+               "marked with pragma simd");
+      *walk_subtrees = 0;
+      *valid = false;
+    }
+  else if (TREE_CODE (*tp) == TRY_BLOCK)
+    {
+      error_at (loc, "try statements are not allowed inside loops marked "
+               "with #pragma simd");
+      *valid = false;
+      *walk_subtrees = 0;
+    }
+  return NULL_TREE;
+}  
+
+
+/* Walks through all the subtrees of BODY using walk_tree to make sure
+   invalid statements/expressions are not found inside BODY.  Returns
+   false if any invalid statements are found.  */
+
+bool
+cpp_validate_cilk_plus_loop (tree body)
+{
+  bool valid = true;
+  cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux,
+               (void *) &valid, NULL);
+  return valid;
+}
index e30922ab43aed5ffa03b5cd4e5156b6bb8a6f033..4e26bd501b44a64e4a302a15833c7a483c74454f 100644 (file)
@@ -6177,6 +6177,9 @@ extern void vtv_save_class_info                 (tree);
 extern void vtv_recover_class_info              (void);
 extern void vtv_build_vtable_verify_fndecl      (void);
 
+/* In cp-cilkplus.c.  */
+extern bool cpp_validate_cilk_plus_loop                (tree);
+
 /* In cp/cp-array-notations.c */
 extern tree expand_array_notation_exprs         (tree);
 bool cilkplus_an_triplet_types_ok_p             (location_t, tree, tree, tree,
index ab3325794d1ba7099ed3877beba7229d378b96ec..27f10543b822e5cb0733df9008e10c8786e6d5bc 100644 (file)
@@ -233,6 +233,8 @@ static void cp_parser_initial_pragma
 static tree cp_literal_operator_id
   (const char *);
 
+static void cp_parser_cilk_simd
+  (cp_parser *, cp_token *);
 static bool cp_parser_omp_declare_reduction_exprs
   (tree, cp_parser *);
 
@@ -531,6 +533,8 @@ cp_debug_parser (FILE *file, cp_parser *parser)
                              parser->in_statement & IN_SWITCH_STMT);
   cp_debug_print_flag (file, "Parsing a structured OpenMP block",
                              parser->in_statement & IN_OMP_BLOCK);
+  cp_debug_print_flag (file, "Parsing a Cilk Plus for loop",
+                             parser->in_statement & IN_CILK_SIMD_FOR);
   cp_debug_print_flag (file, "Parsing a an OpenMP loop",
                              parser->in_statement & IN_OMP_FOR);
   cp_debug_print_flag (file, "Parsing an if statement",
@@ -10558,6 +10562,9 @@ cp_parser_jump_statement (cp_parser* parser)
        case IN_OMP_FOR:
          error_at (token->location, "break statement used with OpenMP for loop");
          break;
+       case IN_CILK_SIMD_FOR:
+         error_at (token->location, "break statement used with Cilk Plus for loop");
+         break;
        }
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
@@ -10568,6 +10575,10 @@ cp_parser_jump_statement (cp_parser* parser)
        case 0:
          error_at (token->location, "continue statement not within a loop");
          break;
+       case IN_CILK_SIMD_FOR:
+         error_at (token->location,
+                   "continue statement within %<#pragma simd%> loop body");
+         /* Fall through.  */
        case IN_ITERATION_STMT:
        case IN_OMP_FOR:
          statement = finish_continue_stmt ();
@@ -28591,7 +28602,7 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
 /* Helper function, to parse omp for increment expression.  */
 
 static tree
-cp_parser_omp_for_cond (cp_parser *parser, tree decl)
+cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
 {
   tree cond = cp_parser_binary_expression (parser, false, true,
                                           PREC_NOT_OPERATOR, NULL);
@@ -28609,6 +28620,10 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
     case LT_EXPR:
     case LE_EXPR:
       break;
+    case NE_EXPR:
+      if (code == CILK_SIMD)
+       break;
+      /* Fall through: OpenMP disallows NE_EXPR.  */
     default:
       return error_mark_node;
     }
@@ -28718,6 +28733,186 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
   return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
 }
 
+/* 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,
+                            tree &this_pre_body,
+                            vec<tree, va_gc> *for_block,
+                            tree &init,
+                            tree &decl,
+                            tree &real_decl)
+{
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    return false;
+
+  bool add_private_clause = false;
+
+  /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+
+     init-expr:
+     var = lb
+     integer-type var = lb
+     random-access-iterator-type var = lb
+     pointer-type var = lb
+  */
+  cp_decl_specifier_seq type_specifiers;
+
+  /* First, try to parse as an initialized declaration.  See
+     cp_parser_condition, from whence the bulk of this is copied.  */
+
+  cp_parser_parse_tentatively (parser);
+  cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+                               /*is_trailing_return=*/false,
+                               &type_specifiers);
+  if (cp_parser_parse_definitely (parser))
+    {
+      /* If parsing a type specifier seq succeeded, then this
+        MUST be a initialized declaration.  */
+      tree asm_specification, attributes;
+      cp_declarator *declarator;
+
+      declarator = cp_parser_declarator (parser,
+                                        CP_PARSER_DECLARATOR_NAMED,
+                                        /*ctor_dtor_or_conv_p=*/NULL,
+                                        /*parenthesized_p=*/NULL,
+                                        /*member_p=*/false);
+      attributes = cp_parser_attributes_opt (parser);
+      asm_specification = cp_parser_asm_specification_opt (parser);
+
+      if (declarator == cp_error_declarator) 
+       cp_parser_skip_to_end_of_statement (parser);
+
+      else 
+       {
+         tree pushed_scope, auto_node;
+
+         decl = start_decl (declarator, &type_specifiers,
+                            SD_INITIALIZED, attributes,
+                            /*prefix_attributes=*/NULL_TREE,
+                            &pushed_scope);
+
+         auto_node = type_uses_auto (TREE_TYPE (decl));
+         if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+           {
+             if (cp_lexer_next_token_is (parser->lexer, 
+                                         CPP_OPEN_PAREN))
+               {
+                 if (parsing_openmp)
+                   error ("parenthesized initialization is not allowed in "
+                          "OpenMP %<for%> loop");
+                 else
+                   error ("parenthesized initialization is "
+                          "not allowed in for-loop");
+               }
+             else
+               /* Trigger an error.  */
+               cp_parser_require (parser, CPP_EQ, RT_EQ);
+
+             init = error_mark_node;
+             cp_parser_skip_to_end_of_statement (parser);
+           }
+         else if (CLASS_TYPE_P (TREE_TYPE (decl))
+                  || type_dependent_expression_p (decl)
+                  || auto_node)
+           {
+             bool is_direct_init, is_non_constant_init;
+
+             init = cp_parser_initializer (parser,
+                                           &is_direct_init,
+                                           &is_non_constant_init);
+
+             if (auto_node)
+               {
+                 TREE_TYPE (decl)
+                   = do_auto_deduction (TREE_TYPE (decl), init,
+                                        auto_node);
+
+                 if (!CLASS_TYPE_P (TREE_TYPE (decl))
+                     && !type_dependent_expression_p (decl))
+                   goto non_class;
+               }
+                     
+             cp_finish_decl (decl, init, !is_non_constant_init,
+                             asm_specification,
+                             LOOKUP_ONLYCONVERTING);
+             if (CLASS_TYPE_P (TREE_TYPE (decl)))
+               {
+                 vec_safe_push (for_block, this_pre_body);
+                 init = NULL_TREE;
+               }
+             else
+               init = pop_stmt_list (this_pre_body);
+             this_pre_body = NULL_TREE;
+           }
+         else
+           {
+             /* Consume '='.  */
+             cp_lexer_consume_token (parser->lexer);
+             init = cp_parser_assignment_expression (parser, false, NULL);
+
+           non_class:
+             if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+               init = error_mark_node;
+             else
+               cp_finish_decl (decl, NULL_TREE,
+                               /*init_const_expr_p=*/false,
+                               asm_specification,
+                               LOOKUP_ONLYCONVERTING);
+           }
+
+         if (pushed_scope)
+           pop_scope (pushed_scope);
+       }
+    }
+  else 
+    {
+      cp_id_kind idk;
+      /* If parsing a type specifier sequence failed, then
+        this MUST be a simple expression.  */
+      cp_parser_parse_tentatively (parser);
+      decl = cp_parser_primary_expression (parser, false, false,
+                                          false, &idk);
+      if (!cp_parser_error_occurred (parser)
+         && decl
+         && DECL_P (decl)
+         && CLASS_TYPE_P (TREE_TYPE (decl)))
+       {
+         tree rhs;
+
+         cp_parser_parse_definitely (parser);
+         cp_parser_require (parser, CPP_EQ, RT_EQ);
+         rhs = cp_parser_assignment_expression (parser, false, NULL);
+         finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
+                                                decl, NOP_EXPR,
+                                                rhs,
+                                                tf_warning_or_error));
+         add_private_clause = true;
+       }
+      else
+       {
+         decl = NULL;
+         cp_parser_abort_tentative_parse (parser);
+         init = cp_parser_expression (parser, false, NULL);
+         if (init)
+           {
+             if (TREE_CODE (init) == MODIFY_EXPR
+                 || TREE_CODE (init) == MODOP_EXPR)
+               real_decl = TREE_OPERAND (init, 0);
+           }
+       }
+    }
+  return add_private_clause;
+}
+
 /* Parse the restricted form of the for statement allowed by OpenMP.  */
 
 static tree
@@ -28763,157 +28958,13 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
 
       init = decl = real_decl = NULL;
       this_pre_body = push_stmt_list ();
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-       {
-         /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
-
-            init-expr:
-                      var = lb
-                      integer-type var = lb
-                      random-access-iterator-type var = lb
-                      pointer-type var = lb
-         */
-         cp_decl_specifier_seq type_specifiers;
-
-         /* First, try to parse as an initialized declaration.  See
-            cp_parser_condition, from whence the bulk of this is copied.  */
 
-         cp_parser_parse_tentatively (parser);
-         cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
-                                       /*is_trailing_return=*/false,
-                                       &type_specifiers);
-         if (cp_parser_parse_definitely (parser))
-           {
-             /* If parsing a type specifier seq succeeded, then this
-                MUST be a initialized declaration.  */
-             tree asm_specification, attributes;
-             cp_declarator *declarator;
+      add_private_clause
+       |= cp_parser_omp_for_loop_init (parser,
+                                       /*parsing_openmp=*/code != CILK_SIMD,
+                                       this_pre_body, for_block,
+                                       init, decl, real_decl);
 
-             declarator = cp_parser_declarator (parser,
-                                                CP_PARSER_DECLARATOR_NAMED,
-                                                /*ctor_dtor_or_conv_p=*/NULL,
-                                                /*parenthesized_p=*/NULL,
-                                                /*member_p=*/false);
-             attributes = cp_parser_attributes_opt (parser);
-             asm_specification = cp_parser_asm_specification_opt (parser);
-
-             if (declarator == cp_error_declarator) 
-               cp_parser_skip_to_end_of_statement (parser);
-
-             else 
-               {
-                 tree pushed_scope, auto_node;
-
-                 decl = start_decl (declarator, &type_specifiers,
-                                    SD_INITIALIZED, attributes,
-                                    /*prefix_attributes=*/NULL_TREE,
-                                    &pushed_scope);
-
-                 auto_node = type_uses_auto (TREE_TYPE (decl));
-                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
-                   {
-                     if (cp_lexer_next_token_is (parser->lexer, 
-                                                 CPP_OPEN_PAREN))
-                       error ("parenthesized initialization is not allowed in "
-                              "OpenMP %<for%> loop");
-                     else
-                       /* Trigger an error.  */
-                       cp_parser_require (parser, CPP_EQ, RT_EQ);
-
-                     init = error_mark_node;
-                     cp_parser_skip_to_end_of_statement (parser);
-                   }
-                 else if (CLASS_TYPE_P (TREE_TYPE (decl))
-                          || type_dependent_expression_p (decl)
-                          || auto_node)
-                   {
-                     bool is_direct_init, is_non_constant_init;
-
-                     init = cp_parser_initializer (parser,
-                                                   &is_direct_init,
-                                                   &is_non_constant_init);
-
-                     if (auto_node)
-                       {
-                         TREE_TYPE (decl)
-                           = do_auto_deduction (TREE_TYPE (decl), init,
-                                                auto_node);
-
-                         if (!CLASS_TYPE_P (TREE_TYPE (decl))
-                             && !type_dependent_expression_p (decl))
-                           goto non_class;
-                       }
-                     
-                     cp_finish_decl (decl, init, !is_non_constant_init,
-                                     asm_specification,
-                                     LOOKUP_ONLYCONVERTING);
-                     if (CLASS_TYPE_P (TREE_TYPE (decl)))
-                       {
-                         vec_safe_push (for_block, this_pre_body);
-                         init = NULL_TREE;
-                       }
-                     else
-                       init = pop_stmt_list (this_pre_body);
-                     this_pre_body = NULL_TREE;
-                   }
-                 else
-                   {
-                     /* Consume '='.  */
-                     cp_lexer_consume_token (parser->lexer);
-                     init = cp_parser_assignment_expression (parser, false, NULL);
-
-                   non_class:
-                     if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
-                       init = error_mark_node;
-                     else
-                       cp_finish_decl (decl, NULL_TREE,
-                                       /*init_const_expr_p=*/false,
-                                       asm_specification,
-                                       LOOKUP_ONLYCONVERTING);
-                   }
-
-                 if (pushed_scope)
-                   pop_scope (pushed_scope);
-               }
-           }
-         else 
-           {
-             cp_id_kind idk;
-             /* If parsing a type specifier sequence failed, then
-                this MUST be a simple expression.  */
-             cp_parser_parse_tentatively (parser);
-             decl = cp_parser_primary_expression (parser, false, false,
-                                                  false, &idk);
-             if (!cp_parser_error_occurred (parser)
-                 && decl
-                 && DECL_P (decl)
-                 && CLASS_TYPE_P (TREE_TYPE (decl)))
-               {
-                 tree rhs;
-
-                 cp_parser_parse_definitely (parser);
-                 cp_parser_require (parser, CPP_EQ, RT_EQ);
-                 rhs = cp_parser_assignment_expression (parser, false, NULL);
-                 finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
-                                                        decl, NOP_EXPR,
-                                                        rhs,
-                                                        tf_warning_or_error));
-                 add_private_clause = true;
-               }
-             else
-               {
-                 decl = NULL;
-                 cp_parser_abort_tentative_parse (parser);
-                 init = cp_parser_expression (parser, false, NULL);
-                 if (init)
-                   {
-                     if (TREE_CODE (init) == MODIFY_EXPR
-                         || TREE_CODE (init) == MODOP_EXPR)
-                       real_decl = TREE_OPERAND (init, 0);
-                   }
-               }
-           }
-       }
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       if (this_pre_body)
        {
@@ -29002,7 +29053,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
 
       cond = NULL;
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-       cond = cp_parser_omp_for_cond (parser, decl);
+       cond = cp_parser_omp_for_cond (parser, decl, code);
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
       incr = NULL;
@@ -29072,7 +29123,10 @@ 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.  */
-  parser->in_statement = IN_OMP_FOR;
+  if (code == CILK_SIMD)
+    parser->in_statement = IN_CILK_SIMD_FOR;
+  else
+    parser->in_statement = IN_OMP_FOR;
 
   /* Note that the grammar doesn't call for a structured block here,
      though the loop as a whole is a structured block.  */
@@ -31127,6 +31181,16 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
        return true;
       }
 
+    case PRAGMA_CILK_SIMD:
+      if (context == pragma_external)
+       {
+         error_at (pragma_tok->location,
+                   "%<#pragma simd%> must be inside a function");
+         break;
+       }
+      cp_parser_cilk_simd (parser, pragma_tok);
+      return true;
+
     default:
       gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
       c_invoke_pragma_handler (id);
@@ -31192,6 +31256,257 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
+/* Parses the Cilk Plus #pragma simd vectorlength clause:
+   Syntax:
+   vectorlength ( constant-expression )  */
+
+static tree
+cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  tree expr;
+  /* The vectorlength clause behaves exactly like OpenMP's safelen
+     clause.  Thus, vectorlength is represented as OMP 4.0
+     safelen.  */
+  check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength", loc);
+  
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return error_mark_node;
+  
+  expr = cp_parser_constant_expression (parser, false, NULL);
+  expr = maybe_constant_value (expr);
+
+  if (TREE_CONSTANT (expr)
+          && exact_log2 (TREE_INT_CST_LOW (expr)) == -1)
+    error_at (loc, "vectorlength must be a power of 2");
+  else if (expr != error_mark_node)
+    {
+      tree c = build_omp_clause (loc, OMP_CLAUSE_SAFELEN);
+      OMP_CLAUSE_SAFELEN_EXPR (c) = expr;
+      OMP_CLAUSE_CHAIN (c) = clauses;
+      clauses = c;
+    }
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    return error_mark_node;
+  return clauses;
+}
+
+/* Handles the Cilk Plus #pragma simd linear clause.
+   Syntax:
+   linear ( simd-linear-variable-list )
+
+   simd-linear-variable-list:
+     simd-linear-variable
+     simd-linear-variable-list , simd-linear-variable
+
+   simd-linear-variable:
+     id-expression
+     id-expression : simd-linear-step
+
+   simd-linear-step:
+   conditional-expression */
+
+static tree
+cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return clauses;
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+    {
+      cp_parser_error (parser, "expected identifier");
+      cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+      return error_mark_node;
+    }
+
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+  parser->colon_corrects_to_scope_p = false;
+  while (1)
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+       {
+         cp_parser_error (parser, "expected variable-name");
+         clauses = error_mark_node;
+         break;
+       }
+
+      tree var_name = cp_parser_id_expression (parser, false, true, NULL,
+                                              false, false);
+      tree decl = cp_parser_lookup_name_simple (parser, var_name,
+                                               token->location);
+      if (decl == error_mark_node)
+       {
+         cp_parser_name_lookup_error (parser, var_name, decl, NLE_NULL,
+                                      token->location);
+         clauses = error_mark_node;
+       }
+      else
+       {
+         tree e = NULL_TREE;
+         tree step_size = integer_one_node;
+
+         /* If present, parse the linear step.  Otherwise, assume the default
+            value of 1.  */
+         if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
+           {
+             cp_lexer_consume_token (parser->lexer);
+
+             e = cp_parser_assignment_expression (parser, false, NULL);
+             e = maybe_constant_value (e);
+
+             if (e == error_mark_node)
+               {
+                 /* If an error has occurred,  then the whole pragma is
+                    considered ill-formed.  Thus, no reason to keep
+                    parsing.  */
+                 clauses = error_mark_node;
+                 break;
+               }
+             else if (type_dependent_expression_p (e)
+                      || value_dependent_expression_p (e)
+                      || (TREE_TYPE (e)
+                          && INTEGRAL_TYPE_P (TREE_TYPE (e))
+                          && (TREE_CONSTANT (e)
+                              || DECL_P (e))))
+               step_size = e;
+             else
+               cp_parser_error (parser,
+                                "step size must be an integer constant "
+                                "expression or an integer variable");
+           }
+
+         /* Use the OMP_CLAUSE_LINEAR,  which has the same semantics.  */
+         tree l = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+         OMP_CLAUSE_DECL (l) = decl;
+         OMP_CLAUSE_LINEAR_STEP (l) = step_size;
+         OMP_CLAUSE_CHAIN (l) = clauses;
+         clauses = l;
+       }
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+       break;
+      else
+       {
+         error_at (cp_lexer_peek_token (parser->lexer)->location,
+                   "expected %<,%> or %<)%> after %qE", decl);
+         clauses = error_mark_node;
+         break;
+       }
+    }
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+  cp_parser_skip_to_closing_parenthesis (parser, false, false, true);
+  return clauses;
+}
+
+/* Returns the name of the next clause.  If the clause is not
+   recognized, then PRAGMA_CILK_CLAUSE_NONE is returned and the next
+   token is not consumed.  Otherwise, the appropriate enum from the
+   pragma_simd_clause is returned and the token is consumed.  */
+
+static pragma_cilk_clause
+cp_parser_cilk_simd_clause_name (cp_parser *parser)
+{
+  pragma_cilk_clause clause_type;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->keyword == RID_PRIVATE)
+    clause_type = PRAGMA_CILK_CLAUSE_PRIVATE;
+  else if (!token->u.value || token->type != CPP_NAME)
+    return PRAGMA_CILK_CLAUSE_NONE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "vectorlength"))
+    clause_type = PRAGMA_CILK_CLAUSE_VECTORLENGTH;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "linear"))
+    clause_type = PRAGMA_CILK_CLAUSE_LINEAR;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "firstprivate"))
+    clause_type = PRAGMA_CILK_CLAUSE_FIRSTPRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "lastprivate"))
+    clause_type = PRAGMA_CILK_CLAUSE_LASTPRIVATE;
+  else if (!strcmp (IDENTIFIER_POINTER (token->u.value), "reduction"))
+    clause_type = PRAGMA_CILK_CLAUSE_REDUCTION;
+  else
+    return PRAGMA_CILK_CLAUSE_NONE;
+
+  cp_lexer_consume_token (parser->lexer);
+  return clause_type;
+}
+
+/* Parses all the #pragma simd clauses.  Returns a list of clauses found.  */
+
+static tree
+cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
+{
+  tree clauses = NULL_TREE;
+
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
+        && clauses != error_mark_node)
+    {
+      pragma_cilk_clause c_kind;
+      c_kind = cp_parser_cilk_simd_clause_name (parser);
+      if (c_kind == PRAGMA_CILK_CLAUSE_VECTORLENGTH)
+       clauses = cp_parser_cilk_simd_vectorlength (parser, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_LINEAR)
+       clauses = cp_parser_cilk_simd_linear (parser, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_PRIVATE)
+       /* Use the OpenMP 4.0 equivalent function.  */
+       clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_FIRSTPRIVATE)
+       /* Use the OpenMP 4.0 equivalent function.  */
+       clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
+                                         clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_LASTPRIVATE)
+       /* Use the OMP 4.0 equivalent function.  */
+       clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
+                                         clauses);
+      else if (c_kind == PRAGMA_CILK_CLAUSE_REDUCTION)
+       /* Use the OMP 4.0 equivalent function.  */
+       clauses = cp_parser_omp_clause_reduction (parser, clauses);
+      else
+       {
+         clauses = error_mark_node;
+         cp_parser_error (parser, "expected %<#pragma simd%> clause");
+         break;
+       }
+    }
+
+  cp_parser_skip_to_pragma_eol (parser, pragma_token);
+
+  if (clauses == error_mark_node)
+    return error_mark_node;
+  else
+    return c_finish_cilk_clauses (clauses);
+}
+
+/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops.  */
+
+static void
+cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
+{
+  tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
+
+  if (clauses == error_mark_node)
+    return;
+  
+  if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR))
+    {
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+               "for statement expected");
+      return;
+    }
+
+  tree sb = begin_omp_structured_block ();
+  int save = cp_parser_begin_omp_structured_block (parser);
+  tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL);
+  if (ret)
+    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;
+}
+
 /* Create an identifier for a generic parameter type (a synthesized
    template parameter implied by `auto' or a concept identifier). */
 
index 1024024d42dc915435ba571afdbd562c3f3c6015..edd4e6e8b98c85a5d7fc40b5e98242e7b0fcc234 100644 (file)
@@ -300,6 +300,7 @@ typedef struct GTY(()) cp_parser {
 #define IN_OMP_BLOCK           4
 #define IN_OMP_FOR             8
 #define IN_IF_STMT             16
+#define IN_CILK_SIMD_FOR       32
   unsigned char in_statement;
 
   /* TRUE if we are presently parsing the body of a switch statement.
index e714e790eadfcda808efb6c9bc583e865bed86ec..3bc8ccb0ee32da54f05b55eed74a3e9aaab01dd2 100644 (file)
@@ -13566,6 +13566,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 
     case OMP_FOR:
     case OMP_SIMD:
+    case CILK_SIMD:
     case OMP_DISTRIBUTE:
       {
        tree clauses, body, pre_body;
index 9da8e3de8444f8533470c0c2f6f63ffacad8326c..5c4fdfa0162ed12d086d9c29cee93f64b27e06dc 100644 (file)
@@ -125,7 +125,7 @@ cxx_readonly_error (tree arg, enum lvalue_use errstring)
                              "read-only reference %qD"),
                           TREE_OPERAND (arg, 0));
   else
-    readonly_error (arg, errstring);
+    readonly_error (input_location, arg, errstring);
 }
 
 \f
index 26d59d14b359d67915a83b39d0feadd0d719aeae..b20d11ae3d48e99ae036abb35b2dca0689a95bc2 100644 (file)
@@ -1118,6 +1118,8 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
        case GF_OMP_FOR_KIND_SIMD:
          kind = " simd";
          break;
+       case GF_OMP_FOR_KIND_CILKSIMD:
+         kind = " cilksimd";
        case GF_OMP_FOR_KIND_DISTRIBUTE:
          kind = " distribute";
          break;
@@ -1149,6 +1151,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
        case GF_OMP_FOR_KIND_SIMD:
          pp_string (buffer, "#pragma omp simd");
          break;
+       case GF_OMP_FOR_KIND_CILKSIMD:
+         pp_string (buffer, "#pragma simd");
+         break;
        case GF_OMP_FOR_KIND_DISTRIBUTE:
          pp_string (buffer, "#pragma omp distribute");
          break;
index 6a0c39b7fce089044edc7e12eafd1694e995bfda..c7cb9f75d18c83f5949d67ef3bba0ac081baada8 100644 (file)
@@ -102,12 +102,13 @@ enum gf_mask {
     GF_CALL_ALLOCA_FOR_VAR     = 1 << 5,
     GF_CALL_INTERNAL           = 1 << 6,
     GF_OMP_PARALLEL_COMBINED   = 1 << 0,
-    GF_OMP_FOR_KIND_MASK       = 3 << 0,
+    GF_OMP_FOR_KIND_MASK       = 7,
     GF_OMP_FOR_KIND_FOR                = 0 << 0,
-    GF_OMP_FOR_KIND_SIMD       = 1 << 0,
-    GF_OMP_FOR_KIND_DISTRIBUTE = 2 << 0,
-    GF_OMP_FOR_COMBINED                = 1 << 2,
-    GF_OMP_FOR_COMBINED_INTO   = 1 << 3,
+    GF_OMP_FOR_KIND_SIMD       = 2 << 0,
+    GF_OMP_FOR_KIND_CILKSIMD   = 3 << 0,
+    GF_OMP_FOR_KIND_DISTRIBUTE = 1 << 2,
+    GF_OMP_FOR_COMBINED                = 1 << 3,
+    GF_OMP_FOR_COMBINED_INTO   = 1 << 4,
     GF_OMP_TARGET_KIND_MASK    = 3 << 0,
     GF_OMP_TARGET_KIND_REGION  = 0 << 0,
     GF_OMP_TARGET_KIND_DATA    = 1 << 0,
index 4e6f44898bacd4eef8a29cf01ad56f0a620404df..bb50e250213f71031d4c0711198cdf2faca8ca4d 100644 (file)
@@ -4189,6 +4189,7 @@ is_gimple_stmt (tree t)
     case OMP_PARALLEL:
     case OMP_FOR:
     case OMP_SIMD:
+    case CILK_SIMD:
     case OMP_DISTRIBUTE:
     case OMP_SECTIONS:
     case OMP_SECTION:
@@ -6406,7 +6407,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 
   orig_for_stmt = for_stmt = *expr_p;
 
-  simd = TREE_CODE (for_stmt) == OMP_SIMD;
+  simd = TREE_CODE (for_stmt) == OMP_SIMD
+    || TREE_CODE (for_stmt) == CILK_SIMD;
   gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
                             simd ? ORT_SIMD : ORT_WORKSHARE);
 
@@ -6543,15 +6545,22 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
        {
        case PREINCREMENT_EXPR:
        case POSTINCREMENT_EXPR:
-         if (orig_for_stmt != for_stmt)
+         {
+           tree decl = TREE_OPERAND (t, 0);
+           // c_omp_for_incr_canonicalize_ptr() should have been
+           // called to massage things appropriately.
+           gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+
+           if (orig_for_stmt != for_stmt)
+             break;
+           t = build_int_cst (TREE_TYPE (decl), 1);
+           if (c)
+             OMP_CLAUSE_LINEAR_STEP (c) = t;
+           t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
+           t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
+           TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
            break;
-         t = build_int_cst (TREE_TYPE (decl), 1);
-         if (c)
-           OMP_CLAUSE_LINEAR_STEP (c) = t;
-         t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
-         t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
-         TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
-         break;
+         }
 
        case PREDECREMENT_EXPR:
        case POSTDECREMENT_EXPR:
@@ -6661,6 +6670,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 OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
     default:
       gcc_unreachable ();
@@ -7730,6 +7740,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
        case OMP_FOR:
        case OMP_SIMD:
+       case CILK_SIMD:
        case OMP_DISTRIBUTE:
          ret = gimplify_omp_for (expr_p, pre_p);
          break;
index 5be9ff8ec406227f3f43516b65e7d41ae398b132..e2fc53c4b83aa6cfe4cfe87fff9e62471d106482 100644 (file)
@@ -285,7 +285,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
   int i;
   struct omp_for_data_loop dummy_loop;
   location_t loc = gimple_location (for_stmt);
-  bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
+  bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
   bool distribute = gimple_omp_for_kind (for_stmt)
                    == GF_OMP_FOR_KIND_DISTRIBUTE;
 
@@ -377,6 +377,10 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
        case LT_EXPR:
        case GT_EXPR:
          break;
+       case NE_EXPR:
+         gcc_assert (gimple_omp_for_kind (for_stmt)
+                     == GF_OMP_FOR_KIND_CILKSIMD);
+         break;
        case LE_EXPR:
          if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
            loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
@@ -1003,7 +1007,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
       x = build_receiver_ref (var, by_ref, ctx);
     }
   else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-          && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+          && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     {
       /* #pragma omp simd isn't a worksharing construct, and can reference even
         private vars in its linear etc. clauses.  */
@@ -2230,7 +2234,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
   if (ctx != NULL)
     {
       if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-         && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+         && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
        {
          error_at (gimple_location (stmt),
                    "OpenMP constructs may not be nested inside simd region");
@@ -2253,7 +2257,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
   switch (gimple_code (stmt))
     {
     case GIMPLE_OMP_FOR:
-      if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
+      if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
        return true;
       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
        {
@@ -2536,6 +2540,23 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
+/* Return true if FNDECL is a setjmp or a longjmp.  */
+
+static bool
+setjmp_or_longjmp_p (const_tree fndecl)
+{
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+      && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
+         || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
+    return true;
+
+  tree declname = DECL_NAME (fndecl);
+  if (!declname)
+    return false;
+  const char *name = IDENTIFIER_POINTER (declname);
+  return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
+}
+
 
 /* Helper function for scan_omp.
 
@@ -2559,22 +2580,33 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   else if (is_gimple_call (stmt))
     {
       tree fndecl = gimple_call_fndecl (stmt);
-      if (fndecl
-         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
-       switch (DECL_FUNCTION_CODE (fndecl))
-         {
-         case BUILT_IN_GOMP_BARRIER:
-         case BUILT_IN_GOMP_CANCEL:
-         case BUILT_IN_GOMP_CANCELLATION_POINT:
-         case BUILT_IN_GOMP_TASKYIELD:
-         case BUILT_IN_GOMP_TASKWAIT:
-         case BUILT_IN_GOMP_TASKGROUP_START:
-         case BUILT_IN_GOMP_TASKGROUP_END:
-           remove = !check_omp_nesting_restrictions (stmt, ctx);
-           break;
-         default:
-           break;
-         }
+      if (fndecl)
+       {
+         if (setjmp_or_longjmp_p (fndecl)
+             && ctx
+             && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+             && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+           {
+             remove = true;
+             error_at (gimple_location (stmt),
+                       "setjmp/longjmp inside simd construct");
+           }
+         else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+           switch (DECL_FUNCTION_CODE (fndecl))
+             {
+             case BUILT_IN_GOMP_BARRIER:
+             case BUILT_IN_GOMP_CANCEL:
+             case BUILT_IN_GOMP_CANCELLATION_POINT:
+             case BUILT_IN_GOMP_TASKYIELD:
+             case BUILT_IN_GOMP_TASKWAIT:
+             case BUILT_IN_GOMP_TASKGROUP_START:
+             case BUILT_IN_GOMP_TASKGROUP_END:
+               remove = !check_omp_nesting_restrictions (stmt, ctx);
+               break;
+             default:
+               break;
+             }
+       }
     }
   if (remove)
     {
@@ -2967,7 +2999,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
   bool reduction_omp_orig_ref = false;
   int pass;
   bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-                 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
+                 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
   int max_vf = 0;
   tree lane = NULL_TREE, idx = NULL_TREE;
   tree ivar = NULL_TREE, lvar = NULL_TREE;
@@ -3587,7 +3619,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       /* Don't add any barrier for #pragma omp simd or
         #pragma omp distribute.  */
       if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
-         || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
+         || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
        gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
     }
 
@@ -3666,7 +3698,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
     }
 
   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-      && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+      && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     {
       simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
       if (simduid)
@@ -3761,7 +3793,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
 
   /* SIMD reductions are handled in lower_rec_input_clauses.  */
   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
-      && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
+      && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
     return;
 
   /* First see if there is exactly one reduction clause.  Use OMP_ATOMIC
@@ -6794,7 +6826,7 @@ expand_omp_for (struct omp_region *region, gimple inner_stmt)
        original loops from being detected.  Fix that up.  */
     loops_state_set (LOOPS_NEED_FIXUP);
 
-  if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
+  if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
     expand_omp_simd (region, &fd);
   else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
           && !fd.have_ordered)
@@ -8236,7 +8268,8 @@ execute_expand_omp (void)
 static bool
 gate_expand_omp (void)
 {
-  return ((flag_openmp != 0 || flag_openmp_simd != 0) && !seen_error ());
+  return ((flag_openmp != 0 || flag_openmp_simd != 0
+          || flag_enable_cilkplus != 0) && !seen_error ());
 }
 
 namespace {
@@ -10057,7 +10090,7 @@ execute_lower_omp (void)
 
   /* This pass always runs, to provide PROP_gimple_lomp.
      But there is nothing to do unless -fopenmp is given.  */
-  if (flag_openmp == 0 && flag_openmp_simd == 0)
+  if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
     return 0;
 
   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
@@ -10177,12 +10210,33 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
     error ("invalid entry to OpenMP structured block");
 #endif
 
+  bool cilkplus_block = false;
+  if (flag_enable_cilkplus)
+    {
+      if ((branch_ctx
+          && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
+          && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
+         || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
+             && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
+       cilkplus_block = true;
+    }
+
   /* If it's obvious we have an invalid entry, be specific about the error.  */
   if (branch_ctx == NULL)
-    error ("invalid entry to OpenMP structured block");
+    {
+      if (cilkplus_block)
+       error ("invalid entry to Cilk Plus structured block");
+      else
+       error ("invalid entry to OpenMP structured block");
+    }
   else
-    /* Otherwise, be vague and lazy, but efficient.  */
-    error ("invalid branch to/from an OpenMP structured block");
+    {
+      /* Otherwise, be vague and lazy, but efficient.  */
+      if (cilkplus_block)
+       error ("invalid branch to/from a Cilk Plus structured block");
+      else
+       error ("invalid branch to/from an OpenMP structured block");
+    }
 
   gsi_replace (gsi_p, gimple_build_nop (), false);
   return true;
@@ -10486,7 +10540,7 @@ diagnose_omp_structured_block_errors (void)
 static bool
 gate_diagnose_omp_blocks (void)
 {
-  return flag_openmp != 0;
+  return flag_openmp || flag_enable_cilkplus;
 }
 
 namespace {
index 21334a4d294ff79d46d399d81a45329de078c66d..23928d4ceeeba3ca97ea96ba0b3db419028fd79f 100644 (file)
@@ -1,3 +1,10 @@
+2013-11-15  Aldy Hernandez  <aldyh@redhat.com>
+
+       * c-c++-common/cilk-plus/PS: New directory.
+       * g++.dg/cilk-plus/cilk-plus.exp: Run shared tests.
+       * g++.dg/dg.exp: Run Cilk Plus tests.
+       * gcc.dg/cilk-plus/cilk-plus.exp: Run shared tests.
+
 2013-11-15  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * gcc.dg/vmx/3b-15.c: Revise for little endian.
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
new file mode 100644 (file)
index 0000000..9b10041
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -fopenmp" } */
+
+int *a, *b, c;
+void *jmpbuf[10];
+
+void foo()
+{
+  int j;
+
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+      if (c == 6)
+       __builtin_setjmp (jmpbuf); /* { dg-error "setjmp" } */
+      a[i] = b[i];
+    }
+
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+      if (c==5)
+       break; /* { dg-error "break statement " } */
+    }
+
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+#pragma omp for /* { dg-error "OpenMP constructs may not" } */
+      for (j=0; j < 1000; ++j)
+       a[i] = b[i];
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses1.c
new file mode 100644 (file)
index 0000000..27d117e
--- /dev/null
@@ -0,0 +1,80 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Werror -Wunknown-pragmas -fcilkplus" } */
+
+volatile int *a, *b;
+
+void foo()
+{
+  int i, j, k;
+
+#pragma simd assert /* { dg-error "expected '#pragma simd' clause" } */
+  for (i=0; i < 100; ++i)
+    a[i] = b[i];
+
+#pragma simd vectorlength /* { dg-error "expected '\\('" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength /* { dg-error "expected '\\('" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength(sizeof (a) == sizeof (float) ? 4 : 8)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength(4,8) /* { dg-error "expected '\\)'" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd vectorlength(i) /* { dg-error "\(vectorlength must be an integer\|in a constant\)" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(35) /* { dg-error "expected identifier" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(blah) /* { dg-error "'blah' \(undeclared\|has not been\)" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(j, 36, k) /* { dg-error "expected" } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i, j)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i : 4)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(i : 2, j : 4, k)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(j : sizeof (a) == sizeof (float) ? 4 : 8)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+  // And now everyone in unison!
+#pragma simd linear(j : 4) vectorlength(4)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(blah2, 36)
+  /* { dg-error "'blah2' \(undeclared\|has not been\)" "undeclared" { target *-*-* } 71 } */
+  /* { dg-error "expected" "expected" { target *-*-* } 71 } */
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+
+#pragma simd linear(j : k)
+  for (int i=0; i < 1234; ++i)
+    a[i] = b[j];
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses2.c
new file mode 100644 (file)
index 0000000..71589c2
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-original -fcilkplus" } */
+
+volatile int *a, *b;
+
+void foo()
+{
+  int j, k;
+
+#pragma simd linear(j : 4, k) vectorlength(4)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[j];
+}
+
+/* { dg-final { scan-tree-dump-times "linear\\(j:4\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "linear\\(k:1\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "safelen\\(4\\)" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/clauses3.c
new file mode 100644 (file)
index 0000000..579b718
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#define N 1000
+
+int A[N], B[N], C[N];
+int main (void)
+{
+#pragma simd private (B) linear(B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd private (B, C) linear(B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd private (B) linear(C:2, B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd reduction (+:B) linear(B:1) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+
+#pragma simd reduction (+:B) linear(B) /* { dg-error "more than one clause" } */
+  for (int ii = 0; ii < N; ii++)
+    {
+      A[ii] = B[ii] + C[ii];
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for1.c
new file mode 100644 (file)
index 0000000..3b67895
--- /dev/null
@@ -0,0 +1,132 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+int *a, *b, *c;
+int something;
+
+void foo()
+{
+  int i, j;
+
+  // Declaration and initialization is allowed.
+#pragma simd
+  for (int i=0; i < 1000; i++)
+    a[i] = b[j];
+
+  // Empty initialization is not allowed.
+#pragma simd
+  for (; i < 5; ++i)           // { dg-error "expected iteration" }
+    a[i] = i;
+
+  // Empty condition is not allowed.
+#pragma simd
+  for (int i=0; ; ++i)         /* { dg-error "missing controlling" } */
+    a[i] = i;
+
+  // Empty increment is not allowed.
+#pragma simd
+  for (int i=0; i < 1234; )            /* { dg-error "missing increment" } */
+    a[i] = i*2;
+
+#pragma simd
+  i = 5; /* { dg-error "for statement expected" } */
+
+  // Initialization variables must be either integral or pointer types.
+  struct S {
+    int i;
+  };
+#pragma simd
+  for (struct S ss = { 0 }; ss.i <= 1000; ++ss.i) /* { dg-error "invalid controlling\|invalid type for iteration\|invalid increment" } */
+    a[ss.i] = b[ss.i];
+
+  #pragma simd
+  for (float f=0.0; f < 15.0; ++f) /* { dg-error "invalid type" } */
+    a[(int)f] = (int) f;
+
+  // Pointers are OK.
+  #pragma simd
+  for (int *i=c; i < &c[100]; ++i)
+    *a = '5';
+
+  // Condition of '==' is not allowed.
+#pragma simd
+  for (int i=j; i == 5; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];
+
+  // The LHS or RHS of the condition must be the initialization variable.
+#pragma simd
+  for (int i=0; i+j < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];  
+
+  // Likewise.
+#pragma simd
+  for (int i=0; 1234 < i + j; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];  
+
+  // Likewise, this is ok.
+#pragma simd
+  for (int i=0; 1234 + j < i; ++i)
+    a[i] = b[i];
+
+  // According to the CilkPlus forum, casts are not allowed, even if
+  // they are no-ops.
+#pragma simd
+  for (int i=0; (char)i < 1234; ++i) /* { dg-error "invalid controlling predicate" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=255; i != something; --i)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=100; i != 5; i += something)
+    a[i] = b[i];
+
+  // Increment must be on the induction variable.
+#pragma simd
+  for (int i=0; i < 100; j++) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+  // Likewise.
+#pragma simd
+  for (int i=0; i < 100; j = i + 1) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+  // Likewise.
+#pragma simd
+  for (int i=0; i < 100; i = j + 1) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i = i + 5)
+    a[i] = b[i];
+
+  // Only PLUS and MINUS increments are allowed.
+#pragma simd
+  for (int i=0; i < 100; i *= 5) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i -= j)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i = i + j)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; i = j + i)
+    a[i] = b[i];
+
+#pragma simd
+  for (int i=0; i < 100; ++i, ++j) /* { dg-error "invalid increment expression" } */
+    a[i] = b[i];
+
+#pragma simd
+  for (int *point=0; point < b; ++point)
+    *point = 555;
+
+#pragma simd
+  for (int *point=0; point > b; --point)
+    *point = 555;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
new file mode 100644 (file)
index 0000000..8660627
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#pragma simd           /* { dg-error "must be inside a function" } */
+
+void foo()
+{
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/for3.c
new file mode 100644 (file)
index 0000000..2da8235
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+int *a, *c;
+
+void foo()
+{
+  int i, j;
+
+  // Pointers are OK.
+  #pragma simd
+  for (int *i=c; i < c; ++i)
+    *a = '5';
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-1.c
new file mode 100644 (file)
index 0000000..d8cec84
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+/* FIXME: This test has been xfailed until reductions are fixed.  */
+
+int argc = 1;
+
+/* This is a simple vectorization test.  It tests if reduction works
+   and if it can vectorize the loop in func correctly. */
+#define N 1000
+
+int func (int *p, int *q) {
+    int x = 0;
+#pragma simd reduction (+:x)
+    for (int ii = 0; ii < N; ii++) { 
+       x += (q[ii] + p[ii]);
+    }
+    return x; 
+
+}
+
+int main ()
+{
+  int ii = 0, x;
+  int Array[N], Array2[N];
+
+  for (ii = 0; ii < N; ii++)
+    {
+      Array[ii] = 5 + argc;
+      Array2[ii] = argc;
+    }
+  x = func (Array, Array2);
+
+  if (x != N * 7)
+    return 1;
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-2.c
new file mode 100644 (file)
index 0000000..f5554f6
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+/* FIXME: This test has been xfailed until reductions are fixed.  */
+
+#include <stdio.h>
+
+#define ARRAY_SIZE  (256)
+int a[ARRAY_SIZE];
+
+__attribute__((noinline))
+int addit (int *arr, int N)
+{
+  int s=0;
+#pragma simd reduction (+:s)
+  for (int i = 0; i < N; i++)
+    s += arr[i];
+  return s;
+}
+
+int main () {
+  int i, s = 0, r = 0;
+  for (i = 0; i < ARRAY_SIZE; i++)
+    {
+      a[i] = i;
+    }
+
+  s = addit (a, ARRAY_SIZE);
+
+  for (i = 0; i < ARRAY_SIZE; i++) 
+    r += i;
+
+  if (s == r)
+    return 0;
+  return 1;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/reduction-3.c
new file mode 100644 (file)
index 0000000..26822d6
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+/* FIXME: This test has been xfailed until reductions are fixed.  */
+
+#define N 256
+#if HAVE_IO
+#include <stdio.h>
+#endif
+#include <malloc.h>
+
+int
+reduction_simd (int *a)
+{
+  int s = 0;
+
+#pragma simd reduction (+:s)
+  for (int i = 0; i < N; i++)
+    {
+      s += a[i];
+    }
+
+  return s;
+}
+
+int
+main ()
+{
+  int *a = (int *) malloc (N * sizeof (int));
+  int i, s = (N - 1) * N / 2;
+
+  for (i = 0; i < N; i++)
+    {
+      a[i] = i;
+    }
+#if HAVE_IO
+  printf ("%d, %d\n", s, reduction_simd (a));
+#endif
+  if (s == reduction_simd (a))
+    return 0;
+  else
+    return 1;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/run-1.c
new file mode 100644 (file)
index 0000000..c8fe1c7
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus -O3" } */
+
+#include <stdlib.h>
+
+#define N 4
+
+float f1[] =  { 2.0, 3.0,  4.0,  5.0 };
+float f2[] =  { 1.0, 6.0, -1.0, -2.0 };
+float res[] = { 3.0, 9.0,  3.0,  3.0 };
+
+__attribute__((noinline))
+void verify (float *sum)
+{
+  for (int i=0; i < N; ++i)
+    if (sum[i] != res[i])
+      abort ();
+}
+
+int main()
+{
+  float sum[N];
+#pragma simd
+  for (int i=0; i < N; ++i)
+    sum[i] = f1[i] + f2[i];
+  verify (sum);
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/safelen.c
new file mode 100644 (file)
index 0000000..2c59de9
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-gimple -fcilkplus" } */
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd vectorlength(8)
+  for (int i=0; i < 1000; ++i)
+    a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "safelen\\(8\\)" 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/vectorlength.c
new file mode 100644 (file)
index 0000000..9aa4a68
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+volatile int *a, *b, N;
+typedef int tint;
+struct someclass {
+  int a;
+  char b;
+  int *p;
+};
+
+void foo()
+{
+#pragma simd vectorlength(4) vectorlength(8) /* { dg-error "too many 'vectorlength' clauses" } */
+  for (int i=0; i < N; ++i)
+    a[i] = b[i];
+
+#pragma simd vectorlength(3) /* { dg-error "must be a power of 2" } */
+  for (int i=0; i < N; ++i)
+    a[i] = b[i];
+}
index 7e0fda57b27ffedeeaf55ca2177f54ef47df5d70..fa9246cc70491c61e640a64a9dc9543f8d895b52 100644 (file)
 
 # Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
 
-
 load_lib g++-dg.exp
 
 if { ![check_effective_target_cilkplus] } {
     return;
 }
 
+dg-init
+# Run the tests that are shared with C.
+g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] ""
+# Run the C++ only tests.
+g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
+dg-finish
+
 dg-init
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " "
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for.C b/gcc/testsuite/g++.dg/cilk-plus/for.C
new file mode 100644 (file)
index 0000000..6e16cfc
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+// Test storage classes in the initialization of a <#pragma simd> for
+// loop.
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+  for (static int tt=5; tt < 10; ++tt) /* { dg-error "before 'static'\|not declared\|expected" } */
+    a[tt] = b[tt];
+
+#pragma simd
+  for (extern int var=0; var < 1000; ++var) /* { dg-error "before 'extern'\|not declared\|expected" } */
+    a[var] = var;
+
+#pragma simd
+  for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "before 'register'\|not declared\|expected" } */
+    b[regj] = a[regj] * 2;
+
+#pragma simd
+  for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "iteration variable cannot be volatile" } */
+    a[vj] = b[vj];
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for2.C b/gcc/testsuite/g++.dg/cilk-plus/for2.C
new file mode 100644 (file)
index 0000000..345e542
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int *p;
+extern int stuff();
+
+template <int value>
+void foobar(int a)
+{
+#pragma simd
+  for (int i=0; i < a; ++i)
+    p[i] = value;
+}
+
+template <int value>
+void foobar2(int a)
+{
+  int j = 123;
+#pragma simd linear(j : value)
+  for (int i=0; i < a; ++i)
+    {
+      p[i] = value;
+      j += stuff();
+    }
+}
+
+void funky()
+{
+  foobar <69> (1000);
+  foobar2 <123> (2000);
+}
+
+void foobar3(int a)
+{
+  int j = 123;
+#pragma simd linear(j : a + a) /* { dg-error "step size must be an integer" } */
+  for (int i=0; i < a; ++i)
+    {
+    p[i] = 1234;
+    extern int bar();
+    j += bar();
+    }
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for3.C b/gcc/testsuite/g++.dg/cilk-plus/for3.C
new file mode 100644 (file)
index 0000000..28dbdee
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+// Test storage classes in the initialization of a <#pragma simd> for
+// loop.
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+  for (int tt=5; tt < 10; ++tt)
+    {
+      a[tt] = b[tt];
+      if (tt == 8)
+       throw 1; /* { dg-error "throw expressions are not allowed" } */
+    }
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for4.C b/gcc/testsuite/g++.dg/cilk-plus/for4.C
new file mode 100644 (file)
index 0000000..5b86b9f
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int *p;
+extern int stuff();
+
+template <int value>
+void foobar(int a)
+{
+  int j = 123;
+#pragma simd linear(j : value + 1)
+  for (int i=0; i < a; ++i)
+    {
+      p[i] = value;
+      j += stuff();
+    }
+}
+
+void funky()
+{
+  foobar <69> (1000);
+}
index 0528538cee7c0c5194351629375660279d7391af..d107dfe7894d8a6249a8c775a0c3f74185917324 100644 (file)
@@ -49,6 +49,7 @@ set tests [prune $tests $srcdir/$subdir/tree-prof/*]
 set tests [prune $tests $srcdir/$subdir/torture/*]
 set tests [prune $tests $srcdir/$subdir/graphite/*]
 set tests [prune $tests $srcdir/$subdir/tm/*]
+set tests [prune $tests $srcdir/$subdir/cilk-plus/*]
 set tests [prune $tests $srcdir/$subdir/guality/*]
 set tests [prune $tests $srcdir/$subdir/simulate-thread/*]
 set tests [prune $tests $srcdir/$subdir/asan/*]
index 7dc2c6e43a996447f45c18777e70dbfd1ab815dc..7407e8e86ac1b3a345506a35fea8cf31754bc5d2 100644 (file)
@@ -33,6 +33,13 @@ set ALWAYS_CFLAGS ""
 lappend ALWAYS_CFLAGS "-L${library_var}/libcilkrts/.libs"
 
 dg-init
+
+# Run the tests that are shared with C++.
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] " -ftree-vectorize -fcilkplus -std=c99" " "
+# Run the C-only tests.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
+       "-ftree-vectorize -fcilkplus -std=c99" " "
+
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O1 -fcilkplus" " "
 dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -fcilkplus" " "
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/for1.c b/gcc/testsuite/gcc.dg/cilk-plus/for1.c
new file mode 100644 (file)
index 0000000..4fb5342
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+int *a, *b, *c;
+
+void foo()
+{
+  int i, j;
+  // The initialization shall declare or initialize a *SINGLE* variable.
+#pragma simd
+  for (i=0, j=5; i < 1000; i++) // { dg-error "expected ';' before ','" }
+    a[i] = b[j];
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/for2.c b/gcc/testsuite/gcc.dg/cilk-plus/for2.c
new file mode 100644 (file)
index 0000000..285f35a
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+  for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only var\|invalid controlling\|invalid increment\|assignment of read" } */
+    a[ci] = b[ci];
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/jump.c b/gcc/testsuite/gcc.dg/cilk-plus/jump.c
new file mode 100644 (file)
index 0000000..9ec3293
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int *a, *b, c;
+
+void foo()
+{
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+      a[i] = b[i];
+      if (c == 5)
+       return;  /* { dg-error "invalid branch to.from a Cilk" } */
+    }
+}
+
+void bar()
+{
+#pragma simd
+  for (int i=0; i < 1000; ++i)
+    {
+    lab:
+      a[i] = b[i];
+    }
+  if (c == 6)
+    goto lab; /* { dg-error "invalid entry to Cilk Plus" } */
+}
index 7cd578cf99629c2b9afd65f3e32c94237b1792a9..7fe849d914f1c870dec383dc1cc5b174dc4abb0b 100644 (file)
@@ -2380,6 +2380,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_string (buffer, "#pragma omp simd");
       goto dump_omp_loop;
 
+    case CILK_SIMD:
+      pp_string (buffer, "#pragma simd");
+      goto dump_omp_loop;
+
     case OMP_DISTRIBUTE:
       pp_string (buffer, "#pragma omp distribute");
       goto dump_omp_loop;
index 6763e78835fa6413773ada26a65508b7b3e9324e..8eecba7a7ad3548bc0067b943893e3e451c9e51c 100644 (file)
@@ -1042,6 +1042,10 @@ DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
    Operands like for OMP_FOR.  */
 DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
 
+/* Cilk Plus - #pragma simd [clause1 ... clauseN]
+   Operands like for OMP_FOR.  */
+DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6)
+
 /* OpenMP - #pragma omp distribute [clause1 ... clauseN]
    Operands like for OMP_FOR.  */
 DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)