Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/copyable_task.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ function build_callable(sig::Type{<:Tuple})
return fresh_copy(mc_cache[key])
else
ir = Base.code_ircode_by_type(sig)[1][1]
# Check whether this is a varargs call.
isva = which(sig).isva
bb, refs, types = derive_copyable_task_ir(BBCode(ir))
unoptimised_ir = IRCode(bb)
optimised_ir = optimise_ir!(unoptimised_ir)
mc_ret_type = callable_ret_type(sig, types)
mc = misty_closure(mc_ret_type, optimised_ir, refs...; do_compile=true)
mc = misty_closure(mc_ret_type, optimised_ir, refs...; isva=isva, do_compile=true)
mc_cache[key] = mc
return mc, refs[end]
end
Expand Down Expand Up @@ -315,7 +317,7 @@ end
"""
set_taped_globals!(t::TapedTask, new_taped_globals)::Nothing

Set the `taped_globals` of `t` to `new_taped_globals`. Any calls to
Set the `taped_globals` of `t` to `new_taped_globals`. Any calls to
[`get_taped_globals`](@ref) in future calls to `consume(t)` (either directly, or implicitly
via iteration) will see this new value.
"""
Expand Down Expand Up @@ -573,7 +575,7 @@ function derive_copyable_task_ir(ir::BBCode)::Tuple{BBCode,Tuple,Vector{Any}}
# We enforced above the condition that the final statement in a basic block must not
# produce. This ensures that the final split does not produce. While not strictly
# necessary, this simplifies the implementation (see below).
#
#
# As a result of the above, a basic block will be associated to exactly one split if it
# does not contain any statements which may produce.
#
Expand All @@ -595,7 +597,7 @@ function derive_copyable_task_ir(ir::BBCode)::Tuple{BBCode,Tuple,Vector{Any}}
# Owing to splitting blocks up, we will need to re-label some `GotoNode`s and
# `GotoIfNot`s. To understand this, consider the following block, whose original `ID`
# we assume to be `ID(old_id)`.
# ID(new_id) - %1 = φ(ID(3) => ...)
# ID(new_id) - %1 = φ(ID(3) => ...)
# ID(new_id) - %3 = call_which_must_not_produce(...)
# ID(new_id) - %4 = produce(%3)
# ID(old_id) - GotoNode(ID(5))
Expand Down
66 changes: 66 additions & 0 deletions src/test_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,38 @@ function test_cases()
[true, 1],
none,
),
Testcase(
"nested with args (static)",
nothing,
(static_nested_outer_args,),
nothing,
[:a, :b, false],
none,
),
Testcase(
"nested with args (static + used)",
nothing,
(static_nested_outer_use_produced_args,),
nothing,
[:a, :b, 1],
none,
),
Testcase(
"nested with args (dynamic)",
nothing,
(dynamic_nested_outer_args, Ref{Any}(nested_inner_args)),
nothing,
[:a, :b, false],
none,
),
Testcase(
"nested with args (dynamic + used)",
nothing,
(dynamic_nested_outer_use_produced_args, Ref{Any}(nested_inner_args)),
nothing,
[:a, :b, 1],
none,
),
Testcase(
"callable struct", nothing, (CallableStruct(5), 4), nothing, [5, 4, 9], allocs
),
Expand Down Expand Up @@ -334,6 +366,40 @@ function dynamic_nested_outer_use_produced(f::Ref{Any})
return nothing
end

@noinline function nested_inner_args(xs...)
for x in xs
produce(x)
end
return 1
end

Libtask.might_produce(::Type{<:Tuple{typeof(nested_inner_args),Any}}) = true
Libtask.might_produce(::Type{<:Tuple{typeof(nested_inner_args),Any,Vararg}}) = true

function static_nested_outer_args()
nested_inner_args(:a, :b)
produce(false)
return nothing
end

function static_nested_outer_use_produced_args()
y = nested_inner_args(:a, :b)
produce(y)
return nothing
end

function dynamic_nested_outer_args(f::Ref{Any})
f[](:a, :b)
produce(false)
return nothing
end

function dynamic_nested_outer_use_produced_args(f::Ref{Any})
y = f[](:a, :b)
produce(y)
return nothing
end

struct CallableStruct{T}
x::T
end
Expand Down
Loading