Skip to content

Commit 366a224

Browse files
committed
typeinfer: De-duplicate backedges as they are stored
Since the caller CodeInstance is always part of the identity that we are de-duplicating on, this makes the linear scan much faster than it is in `gf.c`
1 parent 3f96528 commit 366a224

File tree

1 file changed

+54
-28
lines changed

1 file changed

+54
-28
lines changed

Compiler/src/typeinfer.jl

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -687,12 +687,17 @@ function finishinfer!(me::InferenceState, interp::AbstractInterpreter, cycleid::
687687
nothing
688688
end
689689

690-
# record the backedges
691-
function store_backedges(caller::CodeInstance, edges::SimpleVector)
692-
isa(caller.def.def, Method) || return # don't add backedges to toplevel method instance
693-
i = 1
694-
while true
695-
i > length(edges) && return nothing
690+
# Iterate a series of back-edges that need registering, based on the provided forward edge list.
691+
# Back-edges are returned as (invokesig, item), where the item is a Binding, MethodInstance, or
692+
# MethodTable.
693+
struct ForwardToBackedgeIterator
694+
forward_edges::SimpleVector
695+
end
696+
697+
function Base.iterate(it::ForwardToBackedgeIterator, i::Int = 1)
698+
edges = it.forward_edges
699+
i > length(edges) && return nothing
700+
while i length(edges)
696701
item = edges[i]
697702
if item isa Int
698703
i += 2
@@ -702,34 +707,55 @@ function store_backedges(caller::CodeInstance, edges::SimpleVector)
702707
i += 1
703708
continue
704709
elseif isa(item, Core.Binding)
705-
i += 1
706-
maybe_add_binding_backedge!(item, caller)
707-
continue
710+
return ((nothing, item), i + 1)
708711
end
709712
if isa(item, CodeInstance)
710-
item = item.def
711-
end
712-
if isa(item, MethodInstance) # regular dispatch
713-
ccall(:jl_method_instance_add_backedge, Cvoid, (Any, Any, Any), item, nothing, caller)
714-
i += 1
713+
item = get_ci_mi(item)
714+
return ((nothing, item), i + 1)
715+
elseif isa(item, MethodInstance) # regular dispatch
716+
return ((nothing, item), i + 1)
715717
else
718+
invokesig = item
716719
callee = edges[i+1]
717-
if isa(callee, MethodTable) # abstract dispatch (legacy style edges)
718-
ccall(:jl_method_table_add_backedge, Cvoid, (Any, Any, Any), callee, item, caller)
719-
i += 2
720-
continue
721-
elseif isa(callee, Method)
722-
# ignore `Method`-edges (from e.g. failed `abstract_call_method`)
723-
i += 2
724-
continue
725-
# `invoke` edge
726-
elseif isa(callee, CodeInstance)
727-
callee = get_ci_mi(callee)
720+
isa(callee, Method) && (i += 2; continue) # ignore `Method`-edges (from e.g. failed `abstract_call_method`)
721+
if isa(callee, MethodTable)
722+
# abstract dispatch (legacy style edges)
723+
return ((invokesig, callee), i + 2)
728724
else
729-
callee = callee::MethodInstance
725+
# `invoke` edge
726+
callee = isa(callee, CodeInstance) ? get_ci_mi(callee) : callee::MethodInstance
727+
return ((invokesig, callee), i + 2)
728+
end
729+
end
730+
end
731+
return nothing
732+
end
733+
734+
# record the backedges
735+
function store_backedges(caller::CodeInstance, edges::SimpleVector)
736+
isa(caller.def.def, Method) || return # don't add backedges to toplevel method instance
737+
738+
backedges = ForwardToBackedgeIterator(edges)
739+
for (i, (invokesig, item)) in enumerate(backedges)
740+
# check for any duplicate edges we've already registered
741+
duplicate_found = false
742+
for (i′, (invokesig′, item′)) in enumerate(backedges)
743+
i == i′ && break
744+
if item′ === item && invokesig′ == invokesig
745+
duplicate_found = true
746+
break
747+
end
748+
end
749+
750+
if !duplicate_found
751+
if item isa Core.Binding
752+
maybe_add_binding_backedge!(item, caller)
753+
elseif item isa MethodTable
754+
ccall(:jl_method_table_add_backedge, Cvoid, (Any, Any, Any), item, invokesig, caller)
755+
else
756+
item::MethodInstance
757+
ccall(:jl_method_instance_add_backedge, Cvoid, (Any, Any, Any), item, invokesig, caller)
730758
end
731-
ccall(:jl_method_instance_add_backedge, Cvoid, (Any, Any, Any), callee, item, caller)
732-
i += 2
733759
end
734760
end
735761
nothing

0 commit comments

Comments
 (0)