Skip to content

Commit c642a71

Browse files
committed
optimize a bit
1 parent 616971c commit c642a71

File tree

3 files changed

+56
-91
lines changed

3 files changed

+56
-91
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 52 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -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
24702460
end
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
24822472
end

base/compiler/inferencestate.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ mutable struct InferenceState
9999
ssavalue_uses::Vector{BitSet} # ssavalue sparsity and restart info
100100
# TODO: Could keep this sparsely by doing structural liveness analysis ahead of time.
101101
bb_vartables::Vector{VarTable}
102-
pc_vartable::VarTable
103102
stmt_edges::Vector{Union{Nothing, Vector{Any}}}
104103
stmt_info::Vector{Any}
105104

@@ -152,17 +151,17 @@ mutable struct InferenceState
152151

153152
nslots = length(src.slotflags)
154153
slottypes = Vector{Any}(undef, nslots)
155-
pc_vartable = VarTable(undef, nslots)
154+
bb_vartable1 = VarTable(undef, nslots)
156155
bb_vartable_proto = VarTable(undef, nslots)
157156
argtypes = result.argtypes
158157
nargtypes = length(argtypes)
159158
for i in 1:nslots
160159
argtyp = (i > nargtypes) ? Bottom : argtypes[i]
161-
pc_vartable[i] = VarState(argtyp, i > nargtypes)
160+
bb_vartable1[i] = VarState(argtyp, i > nargtypes)
162161
bb_vartable_proto[i] = VarState(Bottom, i > nargtypes)
163162
slottypes[i] = argtyp
164163
end
165-
bb_vartables = VarTable[i == 1 ? copy(pc_vartable) : copy(bb_vartable_proto)
164+
bb_vartables = VarTable[i == 1 ? bb_vartable1 : copy(bb_vartable_proto)
166165
for i = 1:length(cfg.blocks)]
167166

168167
pclimitations = IdSet{InferenceState}()
@@ -193,7 +192,7 @@ mutable struct InferenceState
193192

194193
frame = new(
195194
linfo, world, mod, sptypes, slottypes, src, cfg,
196-
currbb, currpc, ip, was_reached, handler_at, ssavalue_uses, bb_vartables, pc_vartable, stmt_edges, stmt_info,
195+
currbb, currpc, ip, was_reached, handler_at, ssavalue_uses, bb_vartables, stmt_edges, stmt_info,
197196
pclimitations, limitations, cycle_backedges, callers_in_cycle, dont_work_on_me, parent, inferred,
198197
result, valid_worlds, bestguess, ipo_effects,
199198
params, restrict_abstract_call_sites, cached,

base/compiler/typelattice.jl

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -376,27 +376,6 @@ widenwrappedconditional(typ::LimitedAccuracy) = LimitedAccuracy(widenconditional
376376
ignorelimited(@nospecialize typ) = typ
377377
ignorelimited(typ::LimitedAccuracy) = typ.typ
378378

379-
function stupdate!(state::Nothing, changes::StateUpdate)
380-
newst = copy(changes.state)
381-
changeid = slot_id(changes.var)
382-
newst[changeid] = changes.vtype
383-
# remove any Conditional for this slot from the vtable
384-
# (unless this change is came from the conditional)
385-
if !changes.conditional
386-
for i = 1:length(newst)
387-
newtype = newst[i]
388-
if isa(newtype, VarState)
389-
newtypetyp = ignorelimited(newtype.typ)
390-
if isa(newtypetyp, Conditional) && slot_id(newtypetyp.var) == changeid
391-
newtypetyp = widenwrappedconditional(newtype.typ)
392-
newst[i] = VarState(newtypetyp, newtype.undef)
393-
end
394-
end
395-
end
396-
end
397-
return newst
398-
end
399-
400379
function stupdate!(state::VarTable, changes::StateUpdate)
401380
newstate = nothing
402381
changeid = slot_id(changes.var)
@@ -437,8 +416,6 @@ function stupdate!(state::VarTable, changes::VarTable)
437416
return newstate
438417
end
439418

440-
stupdate!(::Nothing, changes::VarTable) = copy(changes)
441-
442419
function stupdate1!(state::VarTable, change::StateUpdate)
443420
changeid = slot_id(change.var)
444421
# remove any Conditional for this slot from the catch block vtable
@@ -499,4 +476,3 @@ function stoverwrite1!(state::VarTable, change::StateUpdate)
499476
state[changeid] = newtype
500477
return state
501478
end
502-
stoverwrite1!(state::VarTable, ::Nothing) = state

0 commit comments

Comments
 (0)