[list copied]
On 06/20/13 11:20, Jakub Jelinek wrote:
On Wed, Jun 19, 2013 at 05:08:38PM -0500, Aldy Hernandez wrote:
On 06/19/13 16:43, Jakub Jelinek wrote:
On Wed, Jun 19, 2013 at 04:39:52PM -0500, Aldy Hernandez wrote:
Jumps are disallowed into or out of the body of the for loop
associated with a #pragma simd.
I guess my preference would be CILK_SIMD tree (handled the same
as OMP_SIMD during genericization/instantiation), and let
gimplification turn that into (note CILKSIMD added, and everything
reordered):
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 #pragma simd
This way, when testing for whether it is any kind of simd
we can use gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD
instead of the current gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD
test, and the equality can be tested where we expect differences
(say, in the diagnostics - provide different wording), or in nesting
restrictions/combined constructs etc.
I have done as suggested, and cleaned things up along the way.
I believe this is the last remaining TODO on my Cilk Plus pragma simd
list. Everything else is dependent on OMP4.
Is this what you had in mind?
If you'd like, I can submit the OMP changes separately so we can put
them on the OMP4 branch. However, my plan is to start pushing the OMP4
supporting bits (from gomp-4_0-branch) and the Cilk Plus #pragma simd
support (from aldyh/cilk-in-gomp) next week, so perhaps everything will
fall into place shortly. As you wish...
Aldy
commit 0d0061a495d9adec95d67eafa0baac2b77396392
Author: Aldy Hernandez <al...@redhat.com>
Date: Thu Jun 20 19:26:12 2013 -0500
Implement a new CILK_SIMD tree code and gimplify it into GIMPLE_OMP_FOR with
an appropriate annotation.
diff --git a/gcc/ChangeLog.cilkplus b/gcc/ChangeLog.cilkplus
index 6a48ada..4ca0c67 100644
--- a/gcc/ChangeLog.cilkplus
+++ b/gcc/ChangeLog.cilkplus
@@ -1,9 +1,23 @@
-2013-05-13 Aldy Hernandez <al...@redhat.com>
+2013-06-20 Aldy Hernandez <al...@redhat.com>
Balaji V. Iyer <balaji.v.i...@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.
+ * 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.
+ (find_combined_omp_for): 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..3d2f385 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:
@@ -6838,6 +6839,8 @@ find_combined_omp_for (tree *tp, int *walk_subtrees, void
*)
*walk_subtrees = 1;
/* FALLTHRU */
case OMP_SIMD:
+ case CILK_SIMD:
+ /* ?? Hmmm, is this the right way to handle CILK_SIMD? */
if (OMP_FOR_INIT (*tp) != NULL_TREE)
return *tp;
break;
@@ -6868,9 +6871,11 @@ 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
+ (TREE_CODE (for_stmt) == OMP_SIMD
+ || TREE_CODE (for_stmt) == CILK_SIMD)
? ORT_SIMD : ORT_WORKSHARE);
/* Handle OMP_FOR_INIT. */
@@ -7108,6 +7113,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 ();
@@ -8110,6 +8116,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p,
gimple_seq *post_p,
ret = GS_ALL_DONE;
break;
+ case CILK_SIMD:
+ /* For <#pragma simd> we will be generating GIMPLE_OMP_FOR
+ with GF_OMP_FOR_KIND_CILKSIMD and let the OpenMP
+ mechanism handle everything. */
+ if (!flag_openmp)
+ flag_openmp = true;
+ /* FALLTHRU */
+
case OMP_FOR:
case OMP_SIMD:
case OMP_DISTRIBUTE:
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 0065443..3b88906 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,11 +317,12 @@ extract_omp_for_data (gimple for_stmt, struct
omp_for_data *fd,
case GT_EXPR:
break;
case NE_EXPR:
- if (!flag_enable_cilk)
+ /* NE_EXPR is only allowed for Cilk Plus loops. */
+ if (flag_enable_cilk
+ && gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD)
+ break;
+ else
gcc_unreachable ();
- /* NE_EXPR is technically not allowed in OpenMP, but it is
- allowed in Cilk Plus, which generates OMP_SIMD constructs. */
- break;
case LE_EXPR:
if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
@@ -945,7 +946,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 +1892,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 +1923,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 +2764,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 +5512,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
@@ -7203,7 +7204,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 +7221,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),
@@ -7888,12 +7889,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;
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)