@@ -217,21 +217,29 @@ function _typeinf(interp::AbstractInterpreter, frame::InferenceState)
217
217
# with no active ip's, frame is done
218
218
frames = frame. callers_in_cycle
219
219
isempty (frames) && push! (frames, frame)
220
+ valid_worlds = WorldRange ()
220
221
for caller in frames
221
222
@assert ! (caller. dont_work_on_me)
222
223
caller. dont_work_on_me = true
224
+ # might might not fully intersect these earlier, so do that now
225
+ valid_worlds = intersect (caller. valid_worlds, valid_worlds)
223
226
end
224
227
for caller in frames
228
+ caller. valid_worlds = valid_worlds
225
229
finish (caller, interp)
230
+ # finalize and record the linfo result
231
+ caller. inferred = true
226
232
end
227
233
# collect results for the new expanded frame
228
- results = Tuple{InferenceResult, Bool}[ ( frames[i]. result,
229
- frames[i]. cached || frames[i]. parent != = nothing ) for i in 1 : length (frames) ]
230
- # empty!(frames)
231
- valid_worlds = frame. valid_worlds
234
+ results = Tuple{InferenceResult, Vector{Any}, Bool}[
235
+ ( frames[i]. result,
236
+ frames[i]. stmt_edges[1 ],
237
+ frames[i]. cached || frames[i]. parent != = nothing )
238
+ for i in 1 : length (frames) ]
239
+ empty! (frames)
232
240
cached = frame. cached
233
241
if cached || frame. parent != = nothing
234
- for (caller, doopt) in results
242
+ for (caller, _, doopt) in results
235
243
opt = caller. src
236
244
if opt isa OptimizationState
237
245
run_optimizer = doopt && may_optimize (interp)
@@ -253,31 +261,24 @@ function _typeinf(interp::AbstractInterpreter, frame::InferenceState)
253
261
caller. src = nothing
254
262
end
255
263
end
256
- # As a hack the et reuses frame_edges[1] to push any optimization
257
- # edges into, so we don't need to handle them specially here
258
- valid_worlds = intersect (valid_worlds, opt. inlining. et. valid_worlds[])
264
+ caller. valid_worlds = opt. inlining. et. valid_worlds[]
259
265
end
260
266
end
261
267
end
262
- if last (valid_worlds) == get_world_counter ()
263
- valid_worlds = WorldRange (first (valid_worlds), typemax (UInt))
264
- end
265
- for caller in frames
268
+ for (caller, edges, doopt) in results
269
+ valid_worlds = caller. valid_worlds
270
+ if last (valid_worlds) == get_world_counter ()
271
+ valid_worlds = WorldRange (first (valid_worlds), typemax (UInt))
272
+ end
266
273
caller. valid_worlds = valid_worlds
267
- caller. src. min_world = first (valid_worlds)
268
- caller. src. max_world = last (valid_worlds)
269
274
if cached
270
- cache_result! (interp, caller. result, valid_worlds )
275
+ cache_result! (interp, caller)
271
276
end
272
- if last (valid_worlds) == typemax (UInt)
277
+ if doopt && last (valid_worlds) == typemax (UInt)
273
278
# if we aren't cached, we don't need this edge
274
279
# but our caller might, so let's just make it anyways
275
- for caller in frames
276
- store_backedges (caller)
277
- end
280
+ store_backedges (caller, edges)
278
281
end
279
- # finalize and record the linfo result
280
- caller. inferred = true
281
282
end
282
283
return true
283
284
end
@@ -343,14 +344,16 @@ function maybe_compress_codeinfo(interp::AbstractInterpreter, linfo::MethodInsta
343
344
end
344
345
345
346
function transform_result_for_cache (interp:: AbstractInterpreter , linfo:: MethodInstance ,
346
- @nospecialize (inferred_result))
347
+ valid_worlds :: WorldRange , @nospecialize (inferred_result))
347
348
local const_flags:: Int32
348
349
# If we decided not to optimize, drop the OptimizationState now.
349
350
# External interpreters can override as necessary to cache additional information
350
351
if inferred_result isa OptimizationState
351
352
inferred_result = inferred_result. src
352
353
end
353
354
if inferred_result isa CodeInfo
355
+ inferred_result. min_world = first (valid_worlds)
356
+ inferred_result. max_world = last (valid_worlds)
354
357
inferred_result = maybe_compress_codeinfo (interp, linfo, inferred_result)
355
358
end
356
359
# The global cache can only handle objects that codegen understands
@@ -360,7 +363,8 @@ function transform_result_for_cache(interp::AbstractInterpreter, linfo::MethodIn
360
363
return inferred_result
361
364
end
362
365
363
- function cache_result! (interp:: AbstractInterpreter , result:: InferenceResult , valid_worlds:: WorldRange )
366
+ function cache_result! (interp:: AbstractInterpreter , result:: InferenceResult )
367
+ valid_worlds = result. valid_worlds
364
368
# check if the existing linfo metadata is also sufficient to describe the current inference result
365
369
# to decide if it is worth caching this
366
370
already_inferred = already_inferred_quick_test (interp, result. linfo)
@@ -370,7 +374,7 @@ function cache_result!(interp::AbstractInterpreter, result::InferenceResult, val
370
374
371
375
# TODO : also don't store inferred code if we've previously decided to interpret this function
372
376
if ! already_inferred
373
- inferred_result = transform_result_for_cache (interp, result. linfo, result. src)
377
+ inferred_result = transform_result_for_cache (interp, result. linfo, valid_worlds, result. src)
374
378
code_cache (interp)[result. linfo] = CodeInstance (result, inferred_result, valid_worlds)
375
379
end
376
380
unlock_mi_inference (interp, result. linfo)
381
385
# update the MethodInstance
382
386
function finish (me:: InferenceState , interp:: AbstractInterpreter )
383
387
# prepare to run optimization passes on fulltree
388
+ s_edges = me. stmt_edges[1 ]
389
+ if s_edges === nothing
390
+ s_edges = []
391
+ me. stmt_edges[1 ] = s_edges
392
+ end
393
+ for edges in me. stmt_edges
394
+ edges === nothing && continue
395
+ edges === s_edges && continue
396
+ append! (s_edges, edges)
397
+ empty! (edges)
398
+ end
399
+ if me. src. edges != = nothing
400
+ append! (s_edges, me. src. edges)
401
+ me. src. edges = nothing
402
+ end
384
403
if me. limited && me. cached && me. parent != = nothing
385
404
# a top parent will be cached still, but not this intermediate work
386
405
# we can throw everything else away now
@@ -392,6 +411,7 @@ function finish(me::InferenceState, interp::AbstractInterpreter)
392
411
type_annotate! (me)
393
412
me. result. src = OptimizationState (me, OptimizationParams (interp), interp)
394
413
end
414
+ me. result. valid_worlds = me. valid_worlds
395
415
me. result. result = me. bestguess
396
416
nothing
397
417
end
@@ -404,20 +424,15 @@ function finish(src::CodeInfo, interp::AbstractInterpreter)
404
424
end
405
425
406
426
# record the backedges
407
- function store_backedges (frame:: InferenceState )
427
+ function store_backedges (frame:: InferenceResult , edges :: Vector{Any} )
408
428
toplevel = ! isa (frame. linfo. def, Method)
409
- if ! toplevel && (frame. cached || frame. parent != = nothing )
410
- caller = frame. result. linfo
411
- for edges in frame. stmt_edges
412
- store_backedges (caller, edges)
413
- end
414
- store_backedges (caller, frame. src. edges)
415
- frame. src. edges = nothing
429
+ if ! toplevel
430
+ store_backedges (frame. linfo, edges)
416
431
end
432
+ nothing
417
433
end
418
434
419
- store_backedges (caller, edges:: Nothing ) = nothing
420
- function store_backedges (caller, edges:: Vector )
435
+ function store_backedges (caller:: MethodInstance , edges:: Vector )
421
436
i = 1
422
437
while i <= length (edges)
423
438
to = edges[i]
0 commit comments