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


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

Re: _Cilk_spawn and _Cilk_sync for C++


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


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