Skip to content

Commit c291735

Browse files
committed
Try out set_valid_worlds! instead of manual optimisation
1 parent c5dd2bc commit c291735

File tree

2 files changed

+35
-63
lines changed

2 files changed

+35
-63
lines changed

src/copyable_task.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ function build_callable(sig::Type{<:Tuple})
7979
TapedTask from that function."""
8080
throw(ArgumentError(msg))
8181
end
82-
key = CacheKey(Base.get_world_counter(), sig)
82+
world_age = Base.get_world_counter()
83+
key = CacheKey(world_age, sig)
8384
if haskey(mc_cache, key)
8485
return fresh_copy(mc_cache[key])
8586
else
@@ -88,11 +89,12 @@ function build_callable(sig::Type{<:Tuple})
8889
isva = which(sig).isva
8990
bb, refs, types = derive_copyable_task_ir(BBCode(ir))
9091
unoptimised_ir = IRCode(bb)
92+
@static if VERSION > v"1.12-"
93+
unoptimised_ir = set_valid_world!(unoptimised_ir, world_age)
94+
end
9195
optimised_ir = optimise_ir!(unoptimised_ir)
9296
mc_ret_type = callable_ret_type(sig, types)
93-
mc = optimized_misty_closure(
94-
mc_ret_type, optimised_ir, refs...; isva=isva, do_compile=true
95-
)
97+
mc = misty_closure(mc_ret_type, optimised_ir, refs...; isva=isva, do_compile=true)
9698
mc_cache[key] = mc
9799
return mc, refs[end]
98100
end

src/utils.jl

Lines changed: 29 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -220,55 +220,6 @@ function opaque_closure(
220220
)::Core.OpaqueClosure{sig,ret_type}
221221
end
222222

223-
function optimized_opaque_closure(rtype, ir::IRCode, env...; kwargs...)
224-
oc = opaque_closure(rtype, ir, env...; kwargs...)
225-
world = UInt(oc.world)
226-
set_world_bounds_for_optimization!(oc)
227-
optimized_oc = optimize_opaque_closure(oc, rtype, env...; kwargs...)
228-
return optimized_oc
229-
end
230-
231-
function optimize_opaque_closure(oc::Core.OpaqueClosure, rtype, env...; kwargs...)
232-
method = oc.source
233-
ci = method.specializations.cache
234-
world = UInt(oc.world)
235-
ir = reinfer_and_inline(ci, world)
236-
ir === nothing && return oc # nothing to optimize
237-
return opaque_closure(rtype, ir, env...; kwargs...)
238-
end
239-
240-
# Allows optimization to make assumptions about binding access,
241-
# enabling inlining and other optimizations.
242-
function set_world_bounds_for_optimization!(oc::Core.OpaqueClosure)
243-
ci = oc.source.specializations.cache
244-
ci.inferred === nothing && return nothing
245-
ci.inferred.min_world = oc.world
246-
return ci.inferred.max_world = oc.world
247-
end
248-
249-
function reinfer_and_inline(ci::Core.CodeInstance, world::UInt)
250-
interp = CC.NativeInterpreter(world)
251-
mi = get_mi(ci)
252-
argtypes = collect(Any, mi.specTypes.parameters)
253-
irsv = CC.IRInterpretationState(interp, ci, mi, argtypes, world)
254-
irsv === nothing && return nothing
255-
for stmt in irsv.ir.stmts
256-
inst = stmt[:inst]
257-
if Meta.isexpr(inst, :loopinfo) ||
258-
Meta.isexpr(inst, :pop_exception) ||
259-
isa(inst, CC.GotoIfNot) ||
260-
isa(inst, CC.GotoNode) ||
261-
Meta.isexpr(inst, :copyast)
262-
continue
263-
end
264-
stmt[:flag] |= CC.IR_FLAG_REFINED
265-
end
266-
CC.ir_abstract_constant_propagation(interp, irsv)
267-
state = CC.InliningState(interp)
268-
ir = CC.ssa_inlining_pass!(irsv.ir, state, CC.propagate_inbounds(irsv))
269-
return ir
270-
end
271-
272223
"""
273224
misty_closure(
274225
ret_type::Type,
@@ -291,14 +242,33 @@ function misty_closure(
291242
return MistyClosure(opaque_closure(ret_type, ir, env...; isva, do_compile), Ref(ir))
292243
end
293244

294-
function optimized_misty_closure(
295-
ret_type::Type,
296-
ir::IRCode,
297-
@nospecialize env...;
298-
isva::Bool=false,
299-
do_compile::Bool=true,
300-
)
301-
return MistyClosure(
302-
optimized_opaque_closure(ret_type, ir, env...; isva, do_compile), Ref(ir)
303-
)
245+
@static if VERSION > v"1.12-"
246+
"""
247+
set_valid_world!(ir::IRCode, world::UInt)::IRCode
248+
249+
(1.12+ only)
250+
Create a shallow copy of the given IR code, with its `valid_worlds` field updated
251+
to a single valid world. This allows the compiler to perform more inlining.
252+
253+
In particular, if the IR comes from say a function `f` which makes a call to another
254+
function `g` which only got defined after `f`, then at the min_world when `f` was
255+
defined, `g` was not available yet. If we restrict the IR to a world where `g` is
256+
available then `g` can be inlined.
257+
258+
Will error if `world` is not in the existing `valid_worlds` of `ir`.
259+
"""
260+
function set_valid_world!(ir::IRCode, world::UInt)
261+
if world ir.valid_worlds
262+
error("World $world is not valid for this IRCode: $(ir.valid_worlds).")
263+
end
264+
return CC.IRCode(
265+
ir.stmts,
266+
ir.cfg,
267+
ir.debuginfo,
268+
ir.argtypes,
269+
ir.meta,
270+
ir.sptypes,
271+
CC.WorldRange(world, world),
272+
)
273+
end
304274
end

0 commit comments

Comments
 (0)