[omp4/cilkplus] jumps in/out-of #pragma simd for
diff mbox

Message ID 51C4998B.2070808@redhat.com
State New
Headers show

Commit Message

Aldy Hernandez June 21, 2013, 6:20 p.m. UTC
>>   	case NE_EXPR:
>> -	  if (!flag_enable_cilk)
>> +	  /* NE_EXPR is only allowed for Cilk Plus loops.  */
>> +	  if (flag_enable_cilk
>
> Very weird name of a flag.  Should have been flag_cilk or flag_cilkplus
> IMHO.

I know.  It was already there from Balaji's first iteration with array 
notation.  I've asked him to submit a patch.  If he can't, I'll post a 
separate patch to trunk next week.

I've fixed everything else Richard and you pointed out, with the 
exception of:

>>     if (copyin_by_ref || lastprivate_firstprivate)
>>       {
>> -      /* Don't add any barrier for #pragma omp simd.  */
>> +      /* Don't add any barrier for #pragma omp simd or #pragma simd.  */
>>         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))
>>   	gimplify_and_add (build_omp_barrier (), ilist);
>
> This one will clash with a change I'm working on right now (we don't
> want a barrier for distribute either, so this is now
> || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR

Did you mean "|| gimple_omp_for_kind (ctx->stmt) != 
GF_OMP_FOR_KIND_SIMD)" here basically leaving things as they are, or did 
you actually mean change the original "!=" to "=="?  I'm confused.

Otherwise, how does this look?

BTW, yes, I still need to massage the C++ FE appropriately.

Patch
diff mbox

diff --git a/gcc/ChangeLog.cilkplus b/gcc/ChangeLog.cilkplus
index 6a48ada..352d724 100644
--- a/gcc/ChangeLog.cilkplus
+++ b/gcc/ChangeLog.cilkplus
@@ -1,9 +1,25 @@ 
-2013-05-13  Aldy Hernandez  <aldyh@redhat.com>
+2013-06-20  Aldy Hernandez  <aldyh@redhat.com>
 	    Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* Makefile.in (C_COMMON_OBJS): Depend on c-family/c-cilkplus.o.
 	(c-cilkplus.o): New dependency.
 	* omp-low.c (extract_omp_for_data): Add case for NE_EXPR.
+	(build_outer_var_ref): Check for GF_OMP_FOR_KIND_SIMD bitwise.
+	(check_omp_nesting_restrictions): Same.
+	(lower_rec_input_clauses): Same.
+	(expand_omp_for): Same.
+	(lower_omp_for): Same.
+	(diagnose_sb_0): Adjust for Cilk Plus for loops.
+	(gate_expand_omp): Check for Cilk Plus.
+	(execute_lower_omp): Same.
+	(gate_diagnose_omp_blocks): Same.
+	* tree.def (CILK_SIMD): New entry.
+	* tree-pretty-print.c (dump_generic_node): Add case for CILK_SIMD.
+	* gimple-pretty-print.c (dump_gimple_omp_for): Add case for
+	GF_OMP_FOR_KIND_CILKSIMD.
+	* gimplify.c (gimplify_omp_for): Add case for CILK_SIMD.
+	(gimplify_expr): Same.
+	(is_gimple_stmt): Same.
 
 c-family/
 	* c-cilkplus.c: New.
diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c
index 12097e0..861bcbc 100644
--- a/gcc/c-family/c-cilkplus.c
+++ b/gcc/c-family/c-cilkplus.c
@@ -120,24 +120,8 @@  c_validate_cilk_plus_loop (tree *tp, int *walk_subtrees, void *data)
 
   bool *valid = (bool *) data;
 
-  /* FIXME: Jumps are disallowed into or out of the body of a
-     _Cilk_for.  We can't just check for GOTO_EXPR here, since
-     GOTO_EXPR's can also be generated by switches and loops.
-
-     We should check for this case after we have built the CFG,
-     possibly at OMP expansion (ompexp).  However, since by then we
-     have expanded the _Cilk_for into an OMP_FOR, we should probably
-     set a tree bit in OMP_FOR differentiating it from the Cilk SIMD
-     construct and handle it appropriately.  */
-
   switch (TREE_CODE (*tp))
     {
-    case RETURN_EXPR:
-      error_at (EXPR_LOCATION (*tp), "return statments are not allowed "
-		"within loops annotated with #pragma simd");
-      *valid = false;
-      *walk_subtrees = 0;
-      break;
     case CALL_EXPR:
       {
 	tree fndecl = CALL_EXPR_FN (*tp);
@@ -358,23 +342,11 @@  c_finish_cilk_simd_loop (location_t loc,
   TREE_VEC_ELT (condv, 0) = cond;
   TREE_VEC_ELT (incrv, 0) = incr;
 
-  /* The OpenMP <#pragma omp simd> construct is exactly the same as
-     the Cilk Plus one, with the exception of the vectorlength()
-     clause in Cilk Plus.  Emitting an OMP_SIMD simlifies
-     everything.  */
-  tree t = make_node (OMP_SIMD);
+  tree t = make_node (CILK_SIMD);
   TREE_TYPE (t) = void_type_node;
   OMP_FOR_INIT (t) = initv;
-
-  /* ?? The spec says "The increment and limit expressions may be
-     evaluated fewer times than in the serialization.  If different
-     evaluations of the same expression yield different values, the
-     behavior of the program is undefined."  Perhaps the RHS of the
-     condition and increment could be wrapped in a SAVE_EXPR to
-     evaluate only once.  */
   OMP_FOR_COND (t) = condv;
   OMP_FOR_INCR (t) = incrv;
-
   OMP_FOR_BODY (t) = body;
   OMP_FOR_PRE_BODY (t) = NULL;
   OMP_FOR_CLAUSES (t) = adjust_clauses_for_omp (clauses);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 3793bd9..c20d91c 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12123,11 +12123,6 @@  c_parser_cilk_simd_construct (c_parser *parser)
 {
   tree clauses = c_parser_cilk_all_clauses (parser);
 
-  /* For <#pragma simd> we will be generating OMP_SIMD's and let the
-     OpenMP mechanism handle everything.  */
-  if (!flag_openmp)
-    flag_openmp = true;
-
   c_parser_cilk_for_statement (parser, RID_FOR, clauses);
 }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bced6c3..a4ef585 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30420,10 +30420,6 @@  cp_parser_cilk_simd_construct (cp_parser *parser, cp_token *pragma_token)
       return;
     }
 
-  /* #pragma simd is built on top of OpenMP 4.0's OMP_SIMD trees.  */
-  if (!flag_openmp)
-    flag_openmp = true;
-
   tree sb = begin_omp_structured_block ();
   int save = cp_parser_begin_omp_structured_block (parser);
   cp_parser_cilk_for (parser, RID_FOR, clauses);
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index ba7993a..8c92b5b 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1110,6 +1110,9 @@  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";
+	  break;
 	case GF_OMP_FOR_KIND_DISTRIBUTE:
 	  kind = " distribute";
 	  break;
@@ -1141,6 +1144,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;
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 08dacc5..6987df5 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -111,9 +111,10 @@  enum gf_mask {
     GF_CALL_INTERNAL		= 1 << 6,
     GF_OMP_PARALLEL_COMBINED	= 1 << 0,
     GF_OMP_FOR_KIND_MASK	= 3 << 0,
-    GF_OMP_FOR_KIND_FOR		= 0 << 0,
-    GF_OMP_FOR_KIND_SIMD	= 1 << 0,
-    GF_OMP_FOR_KIND_DISTRIBUTE	= 2 << 0,
+    GF_OMP_FOR_KIND_FOR		= 0 << 0, /* #pragma omp for */
+    GF_OMP_FOR_KIND_DISTRIBUTE	= 1 << 0, /* #pragma omp distribute */
+    GF_OMP_FOR_KIND_SIMD	= 2 << 0, /* #pragma omp simd */
+    GF_OMP_FOR_KIND_CILKSIMD	= 3 << 0, /* (Cilk Plus) #pragma simd */
     GF_OMP_FOR_COMBINED		= 4 << 0,
     GF_OMP_TARGET_KIND_MASK	= 3 << 0,
     GF_OMP_TARGET_KIND_REGION	= 0 << 0,
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 78ba9da..b4cddb0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4716,6 +4716,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:
@@ -6868,10 +6869,10 @@  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,
-			     TREE_CODE (for_stmt) == OMP_SIMD
-			     ? ORT_SIMD : ORT_WORKSHARE);
+			     simd ? ORT_SIMD : ORT_WORKSHARE);
 
   /* Handle OMP_FOR_INIT.  */
   for_pre_body = NULL;
@@ -7108,6 +7109,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 ();
@@ -8112,6 +8114,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;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 0065443..45831cf 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -223,7 +223,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 non_ws = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
+  bool non_ws = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
   bool distribute = gimple_omp_for_kind (for_stmt)
 		    == GF_OMP_FOR_KIND_DISTRIBUTE;
 
@@ -317,10 +317,8 @@  extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
 	case GT_EXPR:
 	  break;
 	case NE_EXPR:
-	  if (!flag_enable_cilk)
-	    gcc_unreachable ();
-	  /* NE_EXPR is technically not allowed in OpenMP, but it is
-	     allowed in Cilk Plus, which generates OMP_SIMD constructs.  */
+	  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)))
@@ -945,7 +943,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.  */
@@ -1891,7 +1889,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");
@@ -1922,7 +1920,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)
 	{
@@ -2763,9 +2761,9 @@  lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
      happens after firstprivate copying in all threads.  */
   if (copyin_by_ref || lastprivate_firstprivate)
     {
-      /* Don't add any barrier for #pragma omp simd.  */
+      /* Don't add any barrier for #pragma omp simd or #pragma simd.  */
       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))
 	gimplify_and_add (build_omp_barrier (), ilist);
     }
 }
@@ -5511,7 +5509,7 @@  expand_omp_for (struct omp_region *region)
        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
@@ -6628,7 +6626,7 @@  execute_expand_omp (void)
 static bool
 gate_expand_omp (void)
 {
-  return (flag_openmp != 0 && !seen_error ());
+  return ((flag_openmp || flag_enable_cilk) && !seen_error ());
 }
 
 struct gimple_opt_pass pass_expand_omp =
@@ -7203,7 +7201,7 @@  lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   /* Once lowered, extract the bounds and clauses.  */
   extract_omp_for_data (stmt, &fd, NULL);
 
-  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))
     lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
 
   gimple_seq_add_stmt (&body, stmt);
@@ -7220,7 +7218,7 @@  lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   /* Region exit marker goes at the end of the loop body.  */
   gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
-  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)
     {
       dlist = NULL;
       lower_lastprivate_clauses (gimple_omp_for_clauses (fd.for_stmt),
@@ -7785,7 +7783,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)
+  if (!flag_openmp && !flag_enable_cilk)
     return 0;
 
   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
@@ -7888,12 +7886,33 @@  diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
     error ("invalid entry to OpenMP structured block");
 #endif
 
+  bool cilkplus_block = false;
+  if (flag_enable_cilk)
+    {
+      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;
@@ -8076,7 +8095,7 @@  diagnose_omp_structured_block_errors (void)
 static bool
 gate_diagnose_omp_blocks (void)
 {
-  return flag_openmp != 0;
+  return flag_openmp || flag_enable_cilk;
 }
 
 struct gimple_opt_pass pass_diagnose_omp_blocks =
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
index fe8b630..e8e2066 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
@@ -11,8 +11,6 @@  void foo()
 #pragma simd
   for (int i=0; i < 1000; ++i)
     {
-      if (c == 5)
-	return;	 /* { dg-error "\(return statments are not allowed\|invalid exit\)" } */
       if (c == 6)
 	__builtin_setjmp (jmpbuf); /* { dg-error "calls to setjmp are not allowed" } */
       a[i] = b[i];
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/jump.c b/gcc/testsuite/gcc.dg/cilk-plus/jump.c
new file mode 100644
index 0000000..9ec3293
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/jump.c
@@ -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" } */
+}
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 9c3d15e..9c29a5b 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2364,6 +2364,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;
diff --git a/gcc/tree.def b/gcc/tree.def
index a23d5bf..75b4d8a 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1034,6 +1034,13 @@  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.
+
+   NOTE: This must go between OMP_FOR and OMP_DISTRIBUTE, so
+   OMP_LOOP_CHECK works as expected.  */
+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)