Skip to content

Commit fd5d0c1

Browse files
committed
Make slot-elision fully recursive
When slots depend on slots, the former algorithm misses connections.
1 parent 2e7c82d commit fd5d0c1

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

src/codeedges.jl

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,20 @@ function direct_links!(cl::CodeLinks, src::CodeInfo)
203203
push!(assign, i)
204204
end
205205
continue
206-
elseif isexpr(stmt, :method)
206+
elseif isa(stmt, Expr) && stmt.head trackedheads
207207
name = stmt.args[1]
208208
if isa(name, Symbol)
209209
assign = get(cl.nameassigns, name, nothing)
210210
if assign === nothing
211211
cl.nameassigns[name] = assign = Int[]
212212
end
213213
push!(assign, i)
214+
targetstore = get(cl.namepreds, name, nothing)
215+
if targetstore === nothing
216+
cl.namepreds[name] = targetstore = Links()
217+
end
218+
target = name=>targetstore
219+
add_links!(target, stmt, cl)
214220
end
215221
rhs = stmt
216222
target = SSAValue(i)=>cl.ssapreds[i]
@@ -294,7 +300,7 @@ function Base.push!(l::Links, id)
294300
return id
295301
end
296302

297-
## Phase 2: replacing name-links with statement-links
303+
## Phase 2: replacing slot-links with statement-links (and adding name-links to statement-links)
298304

299305
# Now that we know the full set of dependencies, we can safely replace references to names
300306
# by references to the relevant line numbers.
@@ -375,12 +381,23 @@ function CodeEdges(src::CodeInfo, cl::CodeLinks)
375381
end
376382
return dest
377383
end
384+
# The main task here is to elide the slot-dependencies and convert
385+
# everything to just ssas & names.
386+
# Hence we "follow" slot links to their non-slot leaves.
387+
function follow_links!(marked, l::Links, slotlinks, slotassigns, slothandled)
388+
pushall!(marked, l.ssas)
389+
for id in l.slots
390+
slothandled[id] && continue
391+
slothandled[id] = true
392+
pushall!(marked, slotassigns[id])
393+
follow_links!(marked, slotlinks[id], slotlinks, slotassigns, slothandled)
394+
end
395+
return marked
396+
end
378397

379-
src.inferred && error("supply lowered but not inferred code")
380-
cl = CodeLinks(src)
381-
# Phase 2: replace named intermediates (slot & named-variable references) with statement numbers
398+
# Replace/add named intermediates (slot & named-variable references) with statement numbers
382399
nstmts, nslots = length(src.code), length(src.slotnames)
383-
marked = BitSet() # working storage during resolution
400+
marked, slothandled = BitSet(), fill(false, nslots) # working storage during resolution
384401
edges = CodeEdges(nstmts)
385402
emptylink = Links()
386403
emptylist = Int[]
@@ -407,25 +424,19 @@ function CodeEdges(src::CodeInfo, cl::CodeLinks)
407424
# Assign the predecessors
408425
# For "named" predecessors, we depend only on their assignments
409426
empty!(marked)
410-
pushall!(marked, cl.ssapreds[i].ssas)
411-
pushall!(marked, linkpreds.ssas)
427+
fill!(slothandled, false)
428+
follow_links!(marked, linkpreds, cl.slotpreds, cl.slotassigns, slothandled)
412429
pushall!(marked, listassigns)
413-
for j in linkpreds.slots
414-
pushall!(marked, cl.slotassigns[j])
415-
end
416430
for key in linkpreds.names
417431
pushall!(marked, get(cl.nameassigns, key, emptylist))
418432
end
419433
delete!(marked, i)
420434
append!(edges.preds[i], marked)
421435
# Similarly for successors
422436
empty!(marked)
423-
pushall!(marked, cl.ssasuccs[i].ssas)
424-
pushall!(marked, linksuccs.ssas)
437+
fill!(slothandled, false)
438+
follow_links!(marked, linksuccs, cl.slotsuccs, cl.slotassigns, slothandled)
425439
pushall!(marked, listassigns)
426-
for j in linksuccs.slots
427-
pushall!(marked, cl.slotassigns[j])
428-
end
429440
for key in linksuccs.names
430441
pushall!(marked, get(cl.nameassigns, key, emptylist))
431442
end
@@ -451,6 +462,7 @@ function CodeEdges(src::CodeInfo, cl::CodeLinks)
451462
pushall!(marked, linksuccs.ssas)
452463
for j in linksuccs.slots
453464
pushall!(marked, cl.slotassigns[j])
465+
pushall!(marked, cl.slotsuccs[j].ssas)
454466
end
455467
for key in linksuccs.names
456468
pushall!(marked, get(cl.nameassigns, key, emptylist))

test/codeedges.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ end
208208
edges = CodeEdges(src)
209209
# Check that the StructParent name is discovered everywhere it is used
210210
var = edges.byname[:StructParent]
211-
@test var.preds[1] var.succs
211+
@test var.preds[end] var.succs
212212
isrequired = minimal_evaluation(src, edges)
213213
selective_eval_fromstart!(frame, isrequired, true)
214214
@test supertype(ModSelective.StructParent) === AbstractArray

0 commit comments

Comments
 (0)