-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Copy constructor within spawn not outlined #91
Comments
Thanks for pointing out this issue. I was in the midst of crafting a long response about why Cilk evaluates all function arguments before the spawn and why your example contains a subtlety — compiler optimizations at Right now is a particularly busy time for me, but I'll try to get back to you soon. |
Thanks for the quick response, I appreciate any time you can devote to this. Some more thoughts: The key question is whether Here's my mental model of what should happen:
From the IR, it looks like all the detached children will share a single copy of I've verified that the behavior for this example is the same at |
(Finally getting back to this question after a major deadline on my end, and before my next major deadline in a week.) I agree with your mental model of what should happen in this case. I'm working through a fix, but it might take a while to implement and test. |
Here's an interesting wrinkle: If I give struct object {
long _value;
noinline object(long value) : _value(value) {
*marker = 0xC;
}
noinline object(const object& other) {
*marker = 0xCC;
}
noinline ~object() {
*marker = 0xD;
}
};
// ...
// The rest is unchanged ; Function Attrs: noinline nounwind uwtable
define internal fastcc void @_Z6parentl_invoke.cont.cilk(i64 %x.cilk, i64 %i.015.cilk, %struct.object* align 8 %obj.cilk) unnamed_addr #2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
for.body.cilk:
%__cilkrts_sf = alloca %struct.__cilkrts_stack_frame, align 8
call fastcc void @__cilkrts_enter_frame_fast_1(%struct.__cilkrts_stack_frame* nonnull %__cilkrts_sf)
call fastcc void @__cilkrts_detach(%struct.__cilkrts_stack_frame* nonnull %__cilkrts_sf)
%agg.tmp.cilk = alloca %struct.object, align 8
%0 = bitcast %struct.object* %agg.tmp.cilk to i8*
call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0)
%call.cilk = call i64 @add(long, long)(i64 %x.cilk, i64 %i.015.cilk)
%add.cilk = add nsw i64 %i.015.cilk, %x.cilk
call void @object::object(object const&)(%struct.object* nonnull %agg.tmp.cilk, %struct.object* nonnull dereferenceable(8) %obj.cilk)
call void @child(long, long, object)(i64 %add.cilk, i64 %call.cilk, %struct.object* nonnull %agg.tmp.cilk)
call void @object::~object()(%struct.object* nonnull %agg.tmp.cilk) #7
call fastcc void @__cilk_parent_epilogue(%struct.__cilkrts_stack_frame* nonnull %__cilkrts_sf)
ret void
} |
When a cilk_spawn expression is outlined into a function, all sub-expressions are moved into the outlined function. For example, in
cilk_spawn foo(x + y)
, the values ofx
andy
are passed as arguments to the outlined function, which adds them together before callingfoo
. Nested function calls are also handled in this way.Now consider the case where one of the arguments to the spawned function is an object, passed by value. An implicit call to the object's copy-constructor occurs here. I would have expected to see the call to the copy-constructor occur within the outlined function, but in Tapir it happens before the call to the outlined function. Is this intentional? Why the inconsistent behavior?
Example:
Compiled with
-g0 -fcilkplus -std=c++14 -O1 -emit-llvm -mllvm -debug-abi-calls
. Here's the demangled IR for the outlined function. Notice the evaluation ofx + i
and the call toadd
have been outlined as expected, but the copy constructor is not here.Here's the call to the copy constructor at the call site:
The text was updated successfully, but these errors were encountered: