> -----Original Message-----
> From: Jason Merrill [mailto:[email protected]]
> Sent: Thursday, November 28, 2013 9:11 AM
> To: Iyer, Balaji V; [email protected]
> Cc: Jeff Law
> Subject: Re: _Cilk_spawn and _Cilk_sync for C++
>
> On 11/27/2013 11:05 PM, Iyer, Balaji V wrote:
> > Found the bug. I was not utilizing the stabilize_expr's output correctly.
>
> Unfortunately, I think I was misleading you with talk of stabilize; like you
> said,
> you want to evaluate the whole expression in the spawned function rather
> than in the caller, so that any temporaries (including the lambda closure)
> live
> until the _Cilk_sync. Using stabilize_expr this way (the way I was
> suggesting)
> forces the lambda closure to be evaluated in the caller, and then destroyed
> at the end of the enclosing statement, which is likely to erase any data that
> the spawned function needs to do its work, if anything captured by copy has
> a destructor.
>
> As I said in my last mail, I think the right fix is to make sure that A gets
> remapped properly during copy_body so that its use in the initializer for the
> closure doesn't confuse later passes.
Consider the following test case. I took this from the lambda_spawns.cc line
#203.
global_var = 0;
_Cilk_spawn [=](int *Aa, int size){ foo1_c(A, size); }(B, 2);
foo1 (A, 2);
_Cilk_sync;
if (global_var != 2)
return (++q);
... and here is its gimple output:
{
struct * D.2349;
unsigned long D.2350;
struct * D.2351;
struct * D.2352;
struct * D.2353;
struct * D.2354;
unsigned long D.2355;
struct * D.2356;
struct * D.2357;
struct * D.2358;
struct * D.2359;
struct * D.2360;
struct __lambda0 D.2219;
unsigned int D.2361;
unsigned int D.2362;
void * D.2363;
void * D.2364;
struct * D.2365;
struct * D.2366;
unsigned int D.2367;
try
{
try
{
__cilkrts_enter_frame_fast_1 (&D.2258);
D.2349 = D.2258.worker;
D.2350 = D.2349->pedigree.rank;
D.2258.pedigree.rank = D.2350;
D.2351 = D.2258.worker;
D.2352 = D.2351->pedigree.parent;
D.2258.pedigree.parent = D.2352;
D.2353 = D.2258.call_parent;
D.2354 = D.2258.worker;
D.2355 = D.2354->pedigree.rank;
D.2353->pedigree.rank = D.2355;
D.2356 = D.2258.call_parent;
D.2357 = D.2258.worker;
D.2358 = D.2357->pedigree.parent;
D.2356->pedigree.parent = D.2358;
D.2359 = D.2258.worker;
D.2359->pedigree.rank = 0;
D.2360 = D.2258.worker;
D.2360->pedigree.parent = &D.2258.pedigree;
__cilkrts_detach (&D.2258);
D.2219.__A = CHAIN.6->A;
try
{
main2(int)::<lambda(int*, int)>::operator() (&D.2219, D.2255, 2);
}
finally
{
D.2219 = {CLOBBER};
<===============================
}
}
catch
{
catch (NULL)
{
try
{
D.2361 = D.2258.flags;
D.2362 = D.2361 | 16;
D.2258.flags = D.2362;
D.2363 = __builtin_eh_pointer (0);
D.2258.except_data = D.2363;
D.2364 = __builtin_eh_pointer (0);
__cxa_begin_catch (D.2364);
__cxa_rethrow ();
}
finally
{
__cxa_end_catch ();
}
}
}
finally
as you can tell, it is clobbering the lambda closure at the end of the lambda
calling (in the finally expr, I marked with <========= ) and then it is
catching value of A from main2 as it is supposed to.
What am I misunderstanding?
>
> Jason