@@ -220,55 +220,6 @@ function opaque_closure(
220220 ):: Core.OpaqueClosure{sig,ret_type}
221221end
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))
292243end
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
304274end
0 commit comments