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: "Iyer, Balaji V" <balaji dot v dot iyer at intel dot com>
- To: Jason Merrill <jason at redhat 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: Thu, 28 Nov 2013 17:01:22 +0000
- Subject: RE: _Cilk_spawn and _Cilk_sync for C++
- Authentication-results: sourceware.org; auth=none
> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Thursday, November 28, 2013 9:11 AM
> To: Iyer, Balaji V; gcc-patches@gcc.gnu.org
> 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.
Ok. I think I cut and pasted the wrong part. I am very sorry about it.
Here is the original code:
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);
Here is the gimple output with _Cilk_spawn and _Cilk_sync *DISABLED*
try
{
A[0] = 5;
A[1] = 3;
B[0] = 5;
B[1] = 3;
main_size = argc + 1;
q = 0;
global_var = 0;
D.2219.__A = A;
try
{
main2(int)::<lambda(int*, int)>::operator() (&D.2219, &B, 2);
}
finally
{
D.2219 = {CLOBBER};
}
foo1 (&A, 2);
global_var.4 = global_var;
if (global_var.4 != 2) goto <D.2255>; else goto <D.2256>;
<D.2255>:
q = q + 1;
D.2257 = q;
return D.2257;
<D.2256>:
D.2257 = q;
return D.2257;
}
finally
{
A = {CLOBBER};
B = {CLOBBER};
}
Here is the gimple output with _Cilk_spawn and _Cilk_synd enabled
try
{
try
{
__cilkrts_enter_frame_fast_1 (&D.2258);
D.2351 = D.2258.worker;
D.2352 = D.2351->pedigree.rank;
D.2258.pedigree.rank = D.2352;
D.2353 = D.2258.worker;
D.2354 = D.2353->pedigree.parent;
D.2258.pedigree.parent = D.2354;
D.2355 = D.2258.call_parent;
D.2356 = D.2258.worker;
D.2357 = D.2356->pedigree.rank;
D.2355->pedigree.rank = D.2357;
D.2358 = D.2258.call_parent;
D.2359 = D.2258.worker;
D.2360 = D.2359->pedigree.parent;
D.2358->pedigree.parent = D.2360;
D.2361 = D.2258.worker;
D.2361->pedigree.rank = 0;
D.2362 = D.2258.worker;
D.2362->pedigree.parent = &D.2258.pedigree;
__cilkrts_detach (&D.2258);
B.5 = &CHAIN.7->B;
D.2219.__A = CHAIN.7->A;
try
{
main2(int)::<lambda(int*, int)>::operator() (&D.2219, B.5, 2);
}
finally
{
D.2219 = {CLOBBER}; <================ CLOBBERING LINE
}
}
catch
{
catch (NULL)
{
try
{
D.2364 = D.2258.flags;
D.2365 = D.2364 | 16;
D.2258.flags = D.2365;
D.2366 = __builtin_eh_pointer (0);
D.2258.except_data = D.2366;
D.2367 = __builtin_eh_pointer (0);
__cxa_begin_catch (D.2367);
__cxa_rethrow ();
}
finally
{
__cxa_end_catch ();
}
}
}
}
finally
{
D.2368 = D.2258.worker;
D.2369 = D.2258.call_parent;
D.2368->current_stack_frame = D.2369;
__cilkrts_pop_frame (&D.2258);
D.2370 = D.2258.flags;
if (D.2370 != 16777216) goto <D.2371>; else goto <D.2372>;
<D.2371>:
__cilkrts_leave_frame (&D.2258);
goto <D.2373>;
<D.2372>:
<D.2373>:
}
}
In this line (<=====) it is clobbering the lambda closure.
Sorry again about the mistake.
By the way, I have only cut and pasted the part from the top-level try expression to just show the relevant part. If you want, I can show you the rest.
>
> Jason