This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: _Cilk_spawn and _Cilk_sync for C++
- From: Jason Merrill <jason at redhat dot com>
- To: "Iyer, Balaji V" <balaji dot v dot iyer at intel dot com>, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: Jeff Law <law at redhat dot com>
- Date: Fri, 22 Nov 2013 10:51:29 -0500
- Subject: Re: _Cilk_spawn and _Cilk_sync for C++
- Authentication-results: sourceware.org; auth=none
- References: <BF230D13CA30DD48930C31D4099330003A4A696B at FMSMSX101 dot amr dot corp dot intel dot com> <528E57DE dot 90900 at redhat dot com> <BF230D13CA30DD48930C31D4099330003A4AA318 at FMSMSX101 dot amr dot corp dot intel dot com>
On 11/21/2013 05:40 PM, Iyer, Balaji V wrote:
+/* Returns a TRY_CATCH_EXPR that will encapsulate BODY, EXCEPT_DATA and
+ EXCEPT_FLAG. */
+
+tree
+create_cilk_try_catch (tree except_flag, tree except_data, tree body)
+{
+ tree catch_list = alloc_stmt_list ();
+ append_to_statement_list (except_flag, &catch_list);
+ append_to_statement_list (except_data, &catch_list);
+ append_to_statement_list (do_begin_catch (), &catch_list);
+ append_to_statement_list (build_throw (NULL_TREE), &catch_list);
+ tree catch_tf_expr = build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
+ catch_list, do_end_catch (NULL_TREE));
+ catch_list = build2 (CATCH_EXPR, void_type_node, NULL_TREE,
+ catch_tf_expr);
+ tree try_catch_expr = build_stmt (EXPR_LOCATION (body), TRY_CATCH_EXPR,
+ body, catch_list);
+ return try_catch_expr;
+}
I had in mind something less cilk-specific: a function that takes two
tree operands, one for the body and one for the throwing path.
Basically, make catch_list a parameter and move the first two appends
back into the calling function.
The reason is that, when you have something like this:
_Cilk_spawn [=] { <body> } ();
I need to capture the function call (which in this case is the whole function) and throw it into a nested function. The nested function implementation is shared with C. If the function is stored in a variable then I can just send that out to the nested function. I have added another constraint to make sure the function is a spawning function, this way we can reduce more cases were they are stored to a variable. The reason why I added this check in finish_call_expr is that it seemed to be most straight-forward for me and only place where I could do with least disruption (code-changes).
It looks like you're transforming any
[...] {...} (...);
into
auto lambda = [...]{...};
lambda(...);
which has significantly different semantics, particularly in terms of
the lifetime of the lambda object. In some of the Cilk online
documentation, I see:
When spawning named lambda functions, be careful that the lifespan of the lambda extends at least until the next sync, or else the destructor for the lambda will race with the spawned call. For example:
double i = g();
if (some condition) {
// named lambda with value capture of i
auto f = [=i]() { double d = sin(i); f(d); };
cilk_spawn f();
} // Ouch! destructor for f is in parallel with spawned call.
This would seem to apply even more to unnamed lambda functions, since
normally they would be destroyed at the end of the full-expression,
which must always be before the sync. Does the Intel compiler
implicitly extend the lifetime of a lambda called by cilk spawn? In any
case, we really don't want to do this for all calls to unnamed lambdas
just because we turned on cilk mode.
Jason