@@ -2247,13 +2247,26 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
22472247 ssavaluetypes = frame. src. ssavaluetypes:: Vector{Any}
22482248 bbs = frame. cfg. blocks
22492249 nbbs = length (bbs)
2250- analyzed_bbs = BitSet () # TODO a better check for unanalyzed states
2250+ update_bbstate! = let analyzed_bbs = BitSet (), states = frame. bb_vartables
2251+ @inline function (bb:: Int , vartable:: VarTable )
2252+ if bb in analyzed_bbs
2253+ newstate = stupdate! (states[bb], vartable)
2254+ else
2255+ # if a basic block hasn't been analyzed yet,
2256+ # we can update its state a bit more aggressively
2257+ newstate = stoverwrite! (states[bb], vartable)
2258+ push! (analyzed_bbs, bb)
2259+ end
2260+ return newstate
2261+ end
2262+ end
22512263
22522264 if frame. currbb != 1
22532265 frame. currbb = _bits_findnext (W. bits, 1 ):: Int # next basic block
22542266 end
22552267
2256- stoverwrite! (frame. pc_vartable, frame. bb_vartables[frame. currbb])
2268+ states = frame. bb_vartables
2269+ currstate = copy (states[frame. currbb])
22572270 while frame. currbb <= nbbs
22582271 delete! (W, frame. currbb)
22592272 frame. currpc = first (bbs[frame. currbb]. stmts)
@@ -2274,7 +2287,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
22742287 @goto branch
22752288 elseif isa (stmt, GotoIfNot)
22762289 condx = stmt. cond
2277- condt = abstract_eval_value (interp, condx, frame . pc_vartable , frame)
2290+ condt = abstract_eval_value (interp, condx, currstate , frame)
22782291 if condt === Bottom
22792292 empty! (frame. pclimitations)
22802293 @goto find_next_bb
@@ -2313,25 +2326,21 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
23132326 # We continue with the true branch, but process the false
23142327 # branch here.
23152328 if isa (condt, Conditional)
2316- false_vartable = stoverwrite1! (copy (frame. pc_vartable),
2317- conditional_changes (frame. pc_vartable, condt. elsetype, condt. var))
2318- if falsebb in analyzed_bbs
2319- newstate = stupdate! (frame. bb_vartables[falsebb], false_vartable)
2329+ else_change = conditional_change (currstate, condt. elsetype, condt. var)
2330+ if else_change != = nothing
2331+ false_vartable = stoverwrite1! (copy (currstate), else_change)
23202332 else
2321- newstate = frame. bb_vartables[falsebb] = stupdate! (nothing , false_vartable)
2322- push! (analyzed_bbs, falsebb)
2333+ false_vartable = currstate
23232334 end
2324- stoverwrite1! (frame. pc_vartable,
2325- conditional_changes (frame. pc_vartable, condt. vtype, condt. var))
2326- else
2327- if falsebb in analyzed_bbs
2328- newstate = stupdate! (frame. bb_vartables[falsebb], frame. pc_vartable)
2329- else
2330- newstate = frame. bb_vartables[falsebb] = stupdate! (nothing , frame. pc_vartable)
2331- push! (analyzed_bbs, falsebb)
2335+ newstate = update_bbstate! (falsebb, false_vartable)
2336+ then_change = conditional_change (currstate, condt. vtype, condt. var)
2337+ if then_change != = nothing
2338+ stoverwrite1! (currstate, then_change)
23322339 end
2340+ else
2341+ newstate = update_bbstate! (falsebb, currstate)
23332342 end
2334- if newstate != = nothing || ! was_reached (frame, first (bbs[falsebb] . stmts))
2343+ if newstate != = nothing
23352344 handle_control_backedge! (frame, frame. currpc, stmt. dest)
23362345 push! (W, falsebb)
23372346 end
@@ -2340,8 +2349,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
23402349 end
23412350 elseif isa (stmt, ReturnNode)
23422351 bestguess = frame. bestguess
2343- rt = abstract_eval_value (interp, stmt. val, frame . pc_vartable , frame)
2344- rt = widenreturn (rt, bestguess, nargs, slottypes, frame . pc_vartable )
2352+ rt = abstract_eval_value (interp, stmt. val, currstate , frame)
2353+ rt = widenreturn (rt, bestguess, nargs, slottypes, currstate )
23452354 # narrow representation of bestguess slightly to prepare for tmerge with rt
23462355 if rt isa InterConditional && bestguess isa Const
23472356 let slot_id = rt. slot
@@ -2379,12 +2388,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
23792388 # Propagate entry info to exception handler
23802389 l = stmt. args[1 ]:: Int
23812390 catchbb = block_for_inst (frame. cfg, l)
2382- if catchbb in analyzed_bbs
2383- newstate = stupdate! (frame. bb_vartables[catchbb], frame. pc_vartable)
2384- else
2385- newstate = frame. bb_vartables[catchbb] = stupdate! (nothing , frame. pc_vartable)
2386- push! (analyzed_bbs, catchbb)
2387- end
2391+ newstate = update_bbstate! (catchbb, currstate)
23882392 if newstate != = nothing
23892393 push! (W, catchbb)
23902394 end
@@ -2395,12 +2399,12 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
23952399 end
23962400 # Process non control-flow statements
23972401 (; changes, type) = abstract_eval_basic_statement (interp,
2398- stmt, frame . pc_vartable , frame)
2402+ stmt, currstate , frame)
23992403 if type === Union{}
24002404 @goto find_next_bb
24012405 end
24022406 if changes != = nothing
2403- stoverwrite1! (frame . pc_vartable , changes)
2407+ stoverwrite1! (currstate , changes)
24042408 let cur_hand = frame. handler_at[frame. currpc], l, enter
24052409 while cur_hand != 0
24062410 enter = frame. src. code[cur_hand]:: Expr
@@ -2409,8 +2413,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
24092413 # propagate new type info to exception handler
24102414 # the handling for Expr(:enter) propagates all changes from before the try/catch
24112415 # so this only needs to propagate any changes
2412- if stupdate1! (frame . bb_vartables [exceptbb], changes) || ! was_reached (frame, first (bbs[exceptbb] . stmts) )
2413- push! (frame . ip , exceptbb)
2416+ if stupdate1! (states [exceptbb], changes)
2417+ push! (W , exceptbb)
24142418 end
24152419 cur_hand = frame. handler_at[cur_hand]
24162420 end
@@ -2427,56 +2431,42 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
24272431 end
24282432 end # for frame.currpc in frame.currpc:bbend
24292433
2430- # Case 1: Fallthrough termination
2431- @label fallthrough
2432- nextbb = frame. currbb + 1
2433-
2434- # Case 2: Directly branch to a different BB
2435- @label branch
2436- if nextbb in analyzed_bbs
2437- newstate = stupdate! (frame. bb_vartables[nextbb], frame. pc_vartable)
2438- else
2439- newstate = frame. bb_vartables[nextbb] = stupdate! (nothing , frame. pc_vartable)
2440- push! (analyzed_bbs, nextbb)
2441- end
2442- if newstate != = nothing || ! was_reached (frame, first (bbs[nextbb]. stmts))
2443- push! (W, nextbb)
2434+ # Case 1: Fallthrough termination
2435+ begin @label fallthrough
2436+ nextbb = frame. currbb + 1
24442437 end
2445- @goto find_next_bb
24462438
2447- # TODO : Restore optimization
2448- if nextbb <= nbbs
2449- newstate = stupdate! (frame . bb_vartables[ nextbb], frame . pc_vartable )
2439+ # Case 2: Directly branch to a different BB
2440+ begin @label branch
2441+ newstate = update_bbstate! ( nextbb, currstate )
24502442 if newstate != = nothing
2451- frame. currbb = nextbb
2452- frame. currpc = first (bbs[nextbb]. stmts)
2453- stoverwrite! (frame. pc_vartable, newstate)
2454- continue
2443+ push! (W, nextbb)
24552444 end
24562445 end
24572446
2458- # Case 3: Control flow ended along the current path (converged, return or throw)
2459- @label find_next_bb
2460- frame. currbb = _bits_findnext (W. bits, 1 ):: Int # next basic block
2461- frame. currbb == - 1 && break # the working set is empty
2462- frame. currbb > nbbs && break
2447+ # Case 3: Control flow ended along the current path (converged, return or throw)
2448+ begin @label find_next_bb
2449+ frame. currbb = _bits_findnext (W. bits, 1 ):: Int # next basic block
2450+ frame. currbb == - 1 && break # the working set is empty
2451+ frame. currbb > nbbs && break
24632452
2464- frame. currpc = first (bbs[frame. currbb]. stmts)
2465- stoverwrite! (frame. pc_vartable, frame. bb_vartables[frame. currbb])
2453+ frame. currpc = first (bbs[frame. currbb]. stmts)
2454+ stoverwrite! (currstate, states[frame. currbb])
2455+ end
24662456 end # while frame.currbb <= nbbs
24672457
24682458 frame. dont_work_on_me = false
24692459 nothing
24702460end
24712461
2472- function conditional_changes (changes :: VarTable , @nospecialize (typ), var:: SlotNumber )
2473- oldtyp = changes [slot_id (var)]. typ
2462+ function conditional_change (state :: VarTable , @nospecialize (typ), var:: SlotNumber )
2463+ oldtyp = state [slot_id (var)]. typ
24742464 # approximate test for `typ ∩ oldtyp` being better than `oldtyp`
24752465 # since we probably formed these types with `typesubstract`, the comparison is likely simple
24762466 if ignorelimited (typ) ⊑ ignorelimited (oldtyp)
24772467 # typ is better unlimited, but we may still need to compute the tmeet with the limit "causes" since we ignored those in the comparison
24782468 oldtyp isa LimitedAccuracy && (typ = tmerge (typ, LimitedAccuracy (Bottom, oldtyp. causes)))
2479- return StateUpdate (var, VarState (typ, false ), changes , true )
2469+ return StateUpdate (var, VarState (typ, false ), state , true )
24802470 end
24812471 return nothing
24822472end
0 commit comments