diff --git a/src/toplevel/graph.jl b/src/toplevel/graph.jl index 0364e761d..f99b7dd98 100644 --- a/src/toplevel/graph.jl +++ b/src/toplevel/graph.jl @@ -1,6 +1,6 @@ # computes strongly connected components of a control flow graph `cfg` -# NOTE adapted from https://github.com/JuliaGraphs/LightGraphs.jl/blob/6134e21484f2312b33ba753d47dc2fc4d6b35fac/src/connectivity.jl#L221-L311 -# since to load an entire LightGraphs.jl is a bit cost-ineffective in terms of a trade-off of latency vs. maintainability +# NOTE adapted from https://github.com/JuliaGraphs/Graphs.jl/blob/5878e7be4d68b2a1c179d1367aea670db115ebb5/src/connectivity.jl#L265-L357 +# since to load an entire Graphs.jl is a bit cost-ineffective in terms of a trade-off of latency vs. maintainability function strongly_connected_components(g::CFG) T = Int zero_t = zero(T) @@ -8,7 +8,6 @@ function strongly_connected_components(g::CFG) nvg = nv(g) count = one_t - index = zeros(T, nvg) # first time in which vertex is discovered stack = Vector{T}() # stores vertices which have been discovered and not yet assigned to any component onstack = zeros(Bool, nvg) # false if a vertex is waiting in the stack to receive a component assignment @@ -16,7 +15,6 @@ function strongly_connected_components(g::CFG) parents = zeros(T, nvg) # parent of every vertex in dfs components = Vector{Vector{T}}() # maintains a list of scc (order is not guaranteed in API) - dfs_stack = Vector{T}() @inbounds for s in vertices(g) @@ -32,14 +30,14 @@ function strongly_connected_components(g::CFG) push!(dfs_stack, s) while !isempty(dfs_stack) - v = dfs_stack[end] #end is the most recently added item + v = dfs_stack[end] # end is the most recently added item u = zero_t @inbounds for v_neighbor in outneighbors(g, v) if index[v_neighbor] == zero_t # unvisited neighbor found u = v_neighbor break - #GOTO A push u onto DFS stack and continue DFS + # GOTO A push u onto DFS stack and continue DFS elseif onstack[v_neighbor] # we have already seen n, but can update the lowlink of v # which has the effect of possibly keeping v on the stack until n is ready to pop. @@ -52,13 +50,15 @@ function strongly_connected_components(g::CFG) # we have fully explored the DFS tree from v. # time to start popping. popped = pop!(dfs_stack) - lowlink[parents[popped]] = min(lowlink[parents[popped]], lowlink[popped]) + lowlink[parents[popped]] = min( + lowlink[parents[popped]], lowlink[popped] + ) if index[v] == lowlink[v] # found a cycle in a completed dfs tree. component = Vector{T}() - while !isempty(stack) #break when popped == v + while !isempty(stack) # break when popped == v # drain stack until we see v. # everything on the stack until we see v is in the SCC rooted at v. popped = pop!(stack) @@ -75,7 +75,7 @@ function strongly_connected_components(g::CFG) push!(components, component) end - else #LABEL A + else # LABEL A # add unvisited neighbor to dfs index[u] = count lowlink[u] = count @@ -92,18 +92,18 @@ function strongly_connected_components(g::CFG) end # # assert with the original implementation - # components′ = LightGraphs.strongly_connected_components(cfg_to_sdg(g)) + # components′ = Graphs.strongly_connected_components(cfg_to_sdg(g)) # @assert Set(Set.(components)) == Set(Set.(components′)) return components end -# compatibility with LightGraphs.jl interfaces +# compatibility with Graphs.jl interfaces @inline nv(cfg::CFG) = length(cfg.blocks) @inline vertices(cfg::CFG) = 1:nv(cfg) @inline outneighbors(cfg::CFG, v) = cfg.blocks[v].succs -# import LightGraphs: SimpleDiGraph, add_edge!, LightGraphs +# using Graphs: Graphs, SimpleDiGraph, add_edge! # function cfg_to_sdg(cfg::CFG) # g = SimpleDiGraph(length(cfg.blocks)) # for (v, block) in enumerate(cfg.blocks)