File 1883-Remove-beam_digraph-using-graph-module-instead.patch of Package erlang
From 98e83675b7bcd3be6e38884eb36483383eb66029 Mon Sep 17 00:00:00 2001
From: Richard Carlsson <carlsson.richard@gmail.com>
Date: Fri, 9 Jan 2026 23:40:58 +0100
Subject: [PATCH 3/3] Remove beam_digraph, using graph module instead
---
lib/compiler/src/Makefile | 1 -
lib/compiler/src/beam_digraph.erl | 338 ----------------------------
lib/compiler/src/beam_ssa_alias.erl | 2 +-
lib/compiler/src/beam_ssa_bool.erl | 126 +++++------
lib/compiler/src/beam_ssa_recv.erl | 14 +-
lib/compiler/src/beam_ssa_ss.erl | 148 ++++++------
lib/compiler/src/compile.erl | 3 +-
lib/compiler/src/compiler.app.src | 3 +-
8 files changed, 147 insertions(+), 488 deletions(-)
delete mode 100644 lib/compiler/src/beam_digraph.erl
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index 631f76e3ee..7434a9b4d2 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -56,7 +56,6 @@ MODULES = \
beam_core_to_ssa \
beam_clean \
beam_dict \
- beam_digraph \
beam_disasm \
beam_doc \
beam_flatten \
diff --git a/lib/compiler/src/beam_digraph.erl b/lib/compiler/src/beam_digraph.erl
deleted file mode 100644
index 71a94bca14..0000000000
--- a/lib/compiler/src/beam_digraph.erl
+++ /dev/null
@@ -1,338 +0,0 @@
-
-%%
-%% %CopyrightBegin%
-%%
-%% SPDX-License-Identifier: Apache-2.0
-%%
-%% Copyright Ericsson AB 2019-2025. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% Digraph data type. Similar to the digraph module, but provides a
-%% functional API. The functional API allows us to revert to a
-%% previous version of the digraph when an optimization that may have
-%% damaged the digraph has failed.
-%%
-
--module(beam_digraph).
--moduledoc false.
-
--export([new/0,
- add_vertex/2, add_vertex/3, add_edge/3, add_edge/4,
- del_edge/2, del_edges/2,
- del_vertex/2,
- edges/1,
- foldv/3,
- has_vertex/2,
- is_path/3,
- in_degree/2, in_edges/2, in_neighbours/2,
- no_vertices/1,
- out_degree/2, out_edges/2, out_neighbours/2,
- vertex/2, vertex/3, vertices/1,
- reverse_postorder/2,
- roots/1,
- topsort/1,
- strong_components/2]).
-
-%% Debugging.
--define(DEBUG, false).
--if(?DEBUG).
--export([dump/1,dump/2,dump/3]).
--endif.
-
--import(lists, [foldl/3, reverse/1]).
-
--type edge_map() :: #{ vertex() => ordsets:ordset(vertex()) }.
--type vertice_map() :: #{ vertex() => label() }.
-
--record(dg, {vs = #{} :: vertice_map(),
- in_es = #{} :: edge_map(),
- out_es = #{} :: edge_map()}).
-
--type graph() :: #dg{}.
-
--type vertex() :: term().
--type label() :: term().
--type edge() :: {vertex(), vertex(), label()}.
-
--spec new() -> graph().
-new() -> #dg{}.
-
--spec add_vertex(graph(), vertex()) -> graph().
-add_vertex(Dg, V) ->
- add_vertex(Dg, V, vertex).
-
--spec add_vertex(graph(), vertex(), label()) -> graph().
-add_vertex(Dg, V, Label) ->
- #dg{vs=Vs0} = Dg,
- Vs = Vs0#{V=>Label},
- Dg#dg{vs=Vs}.
-
--spec del_vertex(graph(), vertex()) -> graph().
-del_vertex(Dg, V) ->
- #dg{vs=Vs0,in_es=InEsMap0,out_es=OutEsMap0} = Dg,
- InEs = maps:get(V, InEsMap0, []),
- OutEsMap = foldl(fun({From,_,_}=E, A) -> edge_map_del(From, E, A) end,
- maps:remove(V, OutEsMap0), InEs),
- OutEs = maps:get(V, OutEsMap0, []),
- InEsMap = foldl(fun({_,To,_}=E, A) -> edge_map_del(To, E, A) end,
- maps:remove(V, InEsMap0), OutEs),
- Vs = maps:remove(V, Vs0),
- Dg#dg{vs=Vs,in_es=InEsMap,out_es=OutEsMap}.
-
--spec add_edge(graph(), vertex(), vertex()) -> graph().
-add_edge(Dg, From, To) ->
- add_edge(Dg, From, To, edge).
-
--spec add_edge(graph(), vertex(), vertex(), label()) -> graph().
-add_edge(Dg, From, To, Label) ->
- #dg{in_es=InEsMap0,out_es=OutEsMap0} = Dg,
- Name = {From,To,Label},
- InEsMap = edge_map_add(To, Name, InEsMap0),
- OutEsMap = edge_map_add(From, Name, OutEsMap0),
- Dg#dg{in_es=InEsMap,out_es=OutEsMap}.
-
-edge_map_add(V, E, EsMap) ->
- Es0 = maps:get(V, EsMap, []),
- Es = ordsets:add_element(E, Es0),
- EsMap#{V=>Es}.
-
--spec del_edge(graph(), edge()) -> graph().
-del_edge(Dg, {From,To,_}=E) ->
- #dg{in_es=InEsMap0,out_es=OutEsMap0} = Dg,
- InEsMap = edge_map_del(To, E, InEsMap0),
- OutEsMap = edge_map_del(From, E, OutEsMap0),
- Dg#dg{in_es=InEsMap,out_es=OutEsMap}.
-
-edge_map_del(V, E, EsMap) ->
- Es0 = maps:get(V, EsMap, []),
- Es = Es0 -- [E],
- EsMap#{V:=Es}.
-
--spec del_edges(graph(), [edge()]) -> graph().
-del_edges(G, Es) when is_list(Es) ->
- foldl(fun(E, A) -> del_edge(A, E) end, G, Es).
-
-%% Fold over the vertices of the graph, the order is unspecified.
--spec foldv(graph(), fun((vertex(), label(), any()) -> any()), any()) -> any().
-foldv(#dg{vs=Vs}, Fun, Acc) ->
- maps:fold(Fun, Acc, Vs).
-
--spec has_vertex(graph(), vertex()) -> boolean().
-has_vertex(#dg{vs=Vs}, V) ->
- is_map_key(V, Vs).
-
--spec in_degree(graph(), vertex()) -> non_neg_integer().
-in_degree(#dg{in_es=InEsMap}, V) ->
- length(maps:get(V, InEsMap, [])).
-
--spec in_edges(graph(), vertex()) -> [edge()].
-in_edges(#dg{in_es=InEsMap}, V) ->
- maps:get(V, InEsMap, []).
-
--spec in_neighbours(graph(), vertex()) -> [vertex()].
-in_neighbours(#dg{in_es=InEsMap}, V) ->
- [From || {From,_,_} <:- maps:get(V, InEsMap, [])].
-
--spec is_path(graph(), vertex(), vertex()) -> boolean().
-is_path(G, From, To) ->
- Seen = sets:new(),
- try
- _ = is_path_1([From], To, G, Seen),
- false
- catch
- throw:true ->
- true
- end.
-
-is_path_1([To|_], To, _G, _Seen) ->
- throw(true);
-is_path_1([V|Vs], To, G, Seen0) ->
- case sets:is_element(V, Seen0) of
- true ->
- is_path_1(Vs, To, G, Seen0);
- false ->
- Seen1 = sets:add_element(V, Seen0),
- Successors = out_neighbours(G, V),
- Seen = is_path_1(Successors, To, G, Seen1),
- is_path_1(Vs, To, G, Seen)
- end;
-is_path_1([], _To, _G, Seen) ->
- Seen.
-
--spec out_degree(graph(), vertex()) -> non_neg_integer().
-out_degree(#dg{out_es=OutEsMap}, V) ->
- length(maps:get(V, OutEsMap, [])).
-
--spec out_edges(graph(), vertex()) -> [edge()].
-out_edges(#dg{out_es=OutEsMap}, V) ->
- maps:get(V, OutEsMap, []).
-
--spec out_neighbours(graph(), vertex()) -> [vertex()].
-out_neighbours(#dg{out_es=OutEsMap}, V) ->
- [To || {_,To,_} <:- maps:get(V, OutEsMap, [])].
-
--spec no_vertices(graph()) -> non_neg_integer().
-no_vertices(#dg{vs=Vs}) ->
- map_size(Vs).
-
--spec vertex(graph(), vertex()) -> label().
-vertex(#dg{vs=Vs}, V) ->
- map_get(V, Vs).
-
-%% As vertex/2 but if the vertex does not exist a default value is
-%% returned.
--spec vertex(graph(), vertex(), label()) -> label().
-vertex(#dg{vs=Vs}, V, Default) ->
- maps:get(V, Vs, Default).
-
--spec vertices(graph()) -> [{vertex(), label()}].
-vertices(#dg{vs=Vs}) ->
- maps:to_list(Vs).
-
--spec reverse_postorder(graph(), [vertex()]) -> [vertex()].
-reverse_postorder(G, Vs) ->
- Seen = sets:new(),
- {RPO, _} = reverse_postorder_1(Vs, G, Seen, []),
- RPO.
-
-reverse_postorder_1([V|Vs], G, Seen0, Acc0) ->
- case sets:is_element(V, Seen0) of
- true ->
- reverse_postorder_1(Vs, G, Seen0, Acc0);
- false ->
- Seen1 = sets:add_element(V, Seen0),
- Successors = out_neighbours(G, V),
- {Acc,Seen} = reverse_postorder_1(Successors, G, Seen1, Acc0),
- reverse_postorder_1(Vs, G, Seen, [V|Acc])
- end;
-reverse_postorder_1([], _, Seen, Acc) ->
- {Acc, Seen}.
-
--spec roots(graph()) -> [vertex()].
-roots(G) ->
- roots_1(vertices(G), G).
-
-roots_1([{V,_}|Vs], G) ->
- case in_degree(G, V) of
- 0 ->
- [V|roots_1(Vs, G)];
- _ ->
- roots_1(Vs, G)
- end;
-roots_1([], _G) -> [].
-
--spec topsort(graph()) -> [vertex()].
-topsort(G) ->
- Seen = roots(G),
- reverse_postorder(G, Seen).
-
--spec edges(graph()) -> [edge()].
-edges(#dg{out_es=OutEsMap}) ->
- maps:fold(fun(_, Es, Acc) ->
- Es ++ Acc
- end, [], OutEsMap).
-
-%%
-%% Kosaraju's algorithm
-%%
-%% Visit each node in reverse post order. If the node has not been assigned to
-%% a component yet, start a new component and add all of its in-neighbors to it
-%% if they don't yet belong to one. Keep going until all nodes have been
-%% visited.
-%%
-%% https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
-%%
-
--spec strong_components(graph(), [vertex()]) -> ComponentMap when
- %% Vertices together with their components.
- ComponentMap :: #{ vertex() => [vertex()] }.
-strong_components(G, Vs) ->
- sc_1(Vs, G, #{}, #{}).
-
-sc_1([V | Vs], G, Roots0, Components) when not is_map_key(V, Roots0) ->
- %% V has not been assigned to a component, start a new one with this one as
- %% the root.
- {Roots, Component} = sc_2([V], G, V, Roots0, []),
- sc_1(Vs, G, Roots, Components#{ V => Component });
-sc_1([V | Vs], G, Roots, Components0) ->
- %% V is already part of a component, copy it over.
- Root = map_get(V, Roots),
- Components = Components0#{ V => map_get(Root, Components0) },
-
- sc_1(Vs, G, Roots, Components);
-sc_1([], _G, _Roots, Components) ->
- Components.
-
-sc_2([V | Vs], G, Root, Roots, Acc) when not is_map_key(V, Roots) ->
- %% V has not been assigned to a component, so assign it to the current one.
- sc_2(in_neighbours(G, V) ++ Vs, G, Root, Roots#{ V => Root }, [V | Acc]);
-sc_2([_V | Vs], G, Root, Roots, Acc) ->
- %% V is already part of a component, skip it.
- sc_2(Vs, G, Root, Roots, Acc);
-sc_2([], _G, _Root, Roots, Acc) ->
- {Roots, reverse(Acc)}.
-
--if(?DEBUG).
-
-%%
-%% Dumps the graph as a string in dot (graphviz) format.
-%%
-%% Use dot(1) to convert to an image:
-%%
-%% dot [input] -T[format]
-%% dot graph_file -Tsvg > graph.svg
-
--spec dump(any()) -> any().
-dump(G) ->
- Formatter = fun(Node) -> io_lib:format("~p", [Node]) end,
- io:format("~s", [dump_1(G, Formatter)]).
-
--spec dump(any(), any()) -> any().
-dump(G, FileName) ->
- Formatter = fun(Node) -> io_lib:format("~p", [Node]) end,
- dump(G, FileName, Formatter).
-
--spec dump(any(), any(), any()) -> any().
-dump(G, FileName, Formatter) ->
- {ok, Fd} = file:open(FileName, [write]),
- io:fwrite(Fd, "~s", [dump_1(G, Formatter)]),
- file:close(Fd).
-
-dump_1(G, Formatter) ->
- Vs = maps:keys(G#dg.vs),
-
- {Map, Vertices} = dump_vertices(Vs, 0, Formatter,#{}, []),
- Edges = dump_edges(Vs, G, Map, []),
-
- io_lib:format("digraph g {~n~s~n~s~n}~n", [Vertices, Edges]).
-
-dump_vertices([V | Vs], Counter, Formatter, Map, Acc) ->
- VerticeSlug = io_lib:format(" ~p [label=\"~s\"]~n",
- [Counter, Formatter(V)]),
- dump_vertices(Vs, Counter + 1, Formatter,
- Map#{ V => Counter }, [VerticeSlug | Acc]);
-dump_vertices([], _Counter, _Formatter, Map, Acc) ->
- {Map, Acc}.
-
-dump_edges([V | Vs], G, Map, Acc) ->
- SelfId = map_get(V, Map),
- EdgeSlug = [io_lib:format(" ~p -> ~p~n", [SelfId, map_get(To, Map)]) ||
- {_, To, _} <- out_edges(G, V)],
- dump_edges(Vs, G, Map, [EdgeSlug | Acc]);
-dump_edges([], _G, _Map, Acc) ->
- Acc.
-
--endif.
diff --git a/lib/compiler/src/beam_ssa_alias.erl b/lib/compiler/src/beam_ssa_alias.erl
index 4a317254cc..e46856a5c7 100644
--- a/lib/compiler/src/beam_ssa_alias.erl
+++ b/lib/compiler/src/beam_ssa_alias.erl
@@ -99,7 +99,7 @@ fn(#b_local{name=#b_literal{val=N},arity=A}) ->
-type lbl2ss() :: #{ beam_ssa:label() => sharing_state() }.
--type sharing_state() :: any(). % A beam_digraph graph.
+-type sharing_state() :: any(). % A graph
-type type_db() :: #{ beam_ssa:b_var() := type() }.
diff --git a/lib/compiler/src/beam_ssa_bool.erl b/lib/compiler/src/beam_ssa_bool.erl
index f16bc29cc2..a64afe71b8 100644
--- a/lib/compiler/src/beam_ssa_bool.erl
+++ b/lib/compiler/src/beam_ssa_bool.erl
@@ -830,7 +830,7 @@ cdb_update_workset([], _Seen, Ws) -> Ws.
build_digraph(Bs, #b_br{succ=Succ,fail=Fail}, St0) ->
Ignore = ordsets:from_list([Succ,Fail]),
- G0 = beam_digraph:new(),
+ G0 = graph:new(),
{Map0,G1,St1} = build_mapping(Bs, #{}, G0, St0),
{Map,G2} = add_external_vertices(Ignore, Map0, G1),
{G,St} = build_digraph_1(Bs, G2, Map, St1),
@@ -848,13 +848,13 @@ build_mapping([{L,Blk}|Bs], Map0, G0, St0) ->
#b_blk{is=[]} -> br;
#b_blk{} -> initial
end,
- G = beam_digraph:add_vertex(G0, Vtx, Label),
+ G = graph:add_vertex(G0, Vtx, Label),
build_mapping(Bs, Map, G, St);
build_mapping([], Map, G, St) ->
{Map,G,St}.
add_external_vertices([V|Vs], Map0, G0) ->
- G = beam_digraph:add_vertex(G0, V, {external,#{}}),
+ G = graph:add_vertex(G0, V, {external,#{}}),
Map = Map0#{V=>V},
add_external_vertices(Vs, Map, G);
add_external_vertices([], Map, G) ->
@@ -890,11 +890,11 @@ build_digraph_is([], Last, From, Map, G0, St) ->
case Last of
#b_br{bool=#b_literal{val=true},succ=To0,fail=To0} ->
To = map_get(To0, Map),
- G = beam_digraph:add_edge(G0, From, To, next),
+ G = graph:add_edge(G0, From, To, next),
{G,St};
#b_br{bool=#b_var{}=Bool,succ=Succ0,fail=Fail0} ->
#{Succ0:=Succ,Fail0:=Fail} = Map,
- case beam_digraph:vertex(G0, From) of
+ case graph:vertex(G0, From) of
#b_set{dst=Bool} ->
G = add_succ_fail_edges(From, Succ, Fail, G0),
{G,St};
@@ -903,7 +903,7 @@ build_digraph_is([], Last, From, Map, G0, St) ->
not_possible();
br ->
G1 = add_succ_fail_edges(From, Succ, Fail, G0),
- G = beam_digraph:add_vertex(G1, From, {br,Bool}),
+ G = graph:add_vertex(G1, From, {br,Bool}),
{G,St}
end;
_ ->
@@ -911,14 +911,14 @@ build_digraph_is([], Last, From, Map, G0, St) ->
end.
build_digraph_is_1(I, Is, Last, Vtx, Map, G0, St0) ->
- G1 = beam_digraph:add_vertex(G0, Vtx, I),
+ G1 = graph:add_vertex(G0, Vtx, I),
case Is of
[] ->
build_digraph_is(Is, Last, Vtx, Map, G1, St0);
[_|_] ->
{NextVtx,St} = new_label(St0),
- G2 = beam_digraph:add_vertex(G1, NextVtx, initial),
- G = beam_digraph:add_edge(G2, Vtx, NextVtx, next),
+ G2 = graph:add_vertex(G1, NextVtx, initial),
+ G = graph:add_edge(G2, Vtx, NextVtx, next),
build_digraph_is(Is, Last, NextVtx, Map, G, St)
end.
@@ -996,7 +996,7 @@ opt_digraph_instr(#b_set{dst=Dst}=I, G0, St) ->
#b_set{op=phi,dst=Bool} ->
Vtx = get_vertex(Bool, St),
G2 = del_out_edges(Vtx, G1),
- G = beam_digraph:add_edge(G2, Vtx, Succ, next),
+ G = graph:add_edge(G2, Vtx, Succ, next),
redirect_test(Bool, {fail,Fail}, G, St);
#b_set{} ->
G1
@@ -1020,8 +1020,8 @@ ensure_single_use_1(Bool, Vtx, Uses, G) ->
(_) -> false
end, Uses) of
{[_],[_]} ->
- case {beam_digraph:vertex(G, Fail),
- beam_digraph:in_edges(G, Fail)} of
+ case {graph:vertex(G, Fail),
+ graph:in_edges(G, Fail)} of
{{external,Bs0}, [_]} ->
%% The only other use of the variable Bool
%% is in the failure block and it can only
@@ -1029,7 +1029,7 @@ ensure_single_use_1(Bool, Vtx, Uses, G) ->
%% replace it with the literal `false`
%% in that block.
Bs = Bs0#{Bool => #b_literal{val=false}},
- beam_digraph:add_vertex(G, Fail, {external,Bs});
+ graph:add_vertex(G, Fail, {external,Bs});
_ ->
not_possible()
end;
@@ -1040,8 +1040,8 @@ ensure_single_use_1(Bool, Vtx, Uses, G) ->
convert_to_br_node(I, Target, G0, St) ->
Vtx = get_vertex(I, St),
G1 = del_out_edges(Vtx, G0),
- G = beam_digraph:add_vertex(G1, Vtx, br),
- beam_digraph:add_edge(G, Vtx, Target, next).
+ G = graph:add_vertex(G1, Vtx, br),
+ graph:add_edge(G, Vtx, Target, next).
%% ensure_no_failing_instructions(First, Second, G, St) -> ok.
@@ -1056,7 +1056,7 @@ convert_to_br_node(I, Target, G0, St) ->
ensure_no_failing_instructions(First, Second, G, St) ->
Vs = covered(get_vertex(First, St), get_vertex(Second, St), G),
case any(fun(V) ->
- case beam_digraph:vertex(G, V) of
+ case graph:vertex(G, V) of
#b_set{op=Op} ->
can_fail(Op, V, G);
_ ->
@@ -1092,10 +1092,10 @@ eaten_by_phi(V, G) ->
end.
follow_branch(G, Br) ->
- case beam_digraph:vertex(G, Br) of
+ case graph:vertex(G, Br) of
br ->
- [To] = beam_digraph:out_neighbours(G, Br),
- beam_digraph:vertex(G, To);
+ [To] = graph:out_neighbours(G, Br),
+ graph:vertex(G, To);
_ ->
none
end.
@@ -1107,7 +1107,7 @@ follow_branch(G, Br) ->
order_args([#b_var{}=VarA,#b_var{}=VarB], G, St) ->
{VA,VB} = {get_vertex(VarA, St),get_vertex(VarB, St)},
- case beam_digraph:is_path(G, VA, VB) of
+ case graph:has_path(G, VA, VB) of
true ->
%% Core Erlang code generated by v3_core always
%% has operands already in correct order.
@@ -1115,7 +1115,7 @@ order_args([#b_var{}=VarA,#b_var{}=VarB], G, St) ->
false ->
%% Core Erlang code generated by other frontends
%% such as LFE may have the operands swapped.
- true = beam_digraph:is_path(G, VB, VA), %Assertion.
+ true = graph:has_path(G, VB, VA), %Assertion.
{VarB,VarB}
end;
order_args(_Args, _G, _St) ->
@@ -1159,7 +1159,7 @@ redirect_test_1(V, SuccFail, G) ->
redirect_phi(Phi, Args, SuccFail, G0, St) ->
PhiVtx = get_vertex(Phi, St),
- G = beam_digraph:add_vertex(G0, PhiVtx, br),
+ G = graph:add_vertex(G0, PhiVtx, br),
redirect_phi_1(PhiVtx, sort(Args), SuccFail, G, St).
redirect_phi_1(PhiVtx, [{#b_literal{val=false},FalseExit},
@@ -1219,15 +1219,15 @@ redirect_phi_1(PhiVtx, [{#b_literal{val=false},FalseExit},
%%
ensure_disjoint_paths(G0, BoolVtx, FalseExit),
- [FalseOut] = beam_digraph:out_edges(G0, FalseExit),
- G1 = beam_digraph:del_edge(G0, FalseOut),
+ [FalseOut] = graph:out_edges(G0, FalseExit),
+ G1 = graph:del_edge(G0, FalseOut),
case SuccFail of
{fail,Fail} ->
- G2 = beam_digraph:add_edge(G1, FalseExit, Fail, next),
+ G2 = graph:add_edge(G1, FalseExit, Fail, next),
G = add_succ_fail_edges(BoolVtx, PhiVtx, FalseExit, G2),
do_opt_digraph([SuccBool], G, St);
{succ,Succ} ->
- G2 = beam_digraph:add_edge(G1, FalseExit, PhiVtx, next),
+ G2 = graph:add_edge(G1, FalseExit, PhiVtx, next),
G = add_succ_fail_edges(BoolVtx, Succ, PhiVtx, G2),
do_opt_digraph([SuccBool], G, St)
end;
@@ -1241,9 +1241,9 @@ redirect_phi_1(PhiVtx, [{#b_literal{val=true},TrueExit},
%% must ensure that paths are disjoint.
ensure_disjoint_paths(G0, BoolVtx, TrueExit),
- [TrueOut] = beam_digraph:out_edges(G0, TrueExit),
- G1 = beam_digraph:del_edge(G0, TrueOut),
- G2 = beam_digraph:add_edge(G1, TrueExit, PhiVtx, next),
+ [TrueOut] = graph:out_edges(G0, TrueExit),
+ G1 = graph:del_edge(G0, TrueOut),
+ G2 = graph:add_edge(G1, TrueExit, PhiVtx, next),
G = add_succ_fail_edges(BoolVtx, PhiVtx, Fail, G2),
%% As as future improvement, we could follow TrueExit
%% back to its originating boolean expression and
@@ -1254,19 +1254,19 @@ redirect_phi_1(_PhiVtx, [{#b_literal{val=false},FalseExit},
SuccFail, G0, _St) ->
case SuccFail of
{fail,Fail} ->
- [FalseOut] = beam_digraph:out_edges(G0, FalseExit),
- G = beam_digraph:del_edge(G0, FalseOut),
- beam_digraph:add_edge(G, FalseExit, Fail, next);
+ [FalseOut] = graph:out_edges(G0, FalseExit),
+ G = graph:del_edge(G0, FalseOut),
+ graph:add_edge(G, FalseExit, Fail, next);
{succ,Succ} ->
- [TrueOut] = beam_digraph:out_edges(G0, TrueExit),
- G = beam_digraph:del_edge(G0, TrueOut),
- beam_digraph:add_edge(G, TrueExit, Succ, next)
+ [TrueOut] = graph:out_edges(G0, TrueExit),
+ G = graph:del_edge(G0, TrueOut),
+ graph:add_edge(G, TrueExit, Succ, next)
end;
redirect_phi_1(_PhiVtx, _Args, _SuccFail, _G, _St) ->
not_possible().
digraph_bool_def(G) ->
- Vs = beam_digraph:vertices(G),
+ Vs = graph:vertices_with_labels(G),
#{Dst => Vtx || {Vtx,#b_set{dst=Dst}} <- Vs}.
%% ensure_disjoint_paths(G, Vertex1, Vertex2) -> ok.
@@ -1275,7 +1275,7 @@ digraph_bool_def(G) ->
%% directions, but better safe than sorry.)
ensure_disjoint_paths(G, V1, V2) ->
- case beam_digraph:is_path(G, V1, V2) orelse beam_digraph:is_path(G, V2, V1) of
+ case graph:has_path(G, V1, V2) orelse graph:has_path(G, V2, V1) of
true -> not_possible();
false -> ok
end.
@@ -1294,7 +1294,7 @@ ensure_disjoint_paths(G, V1, V2) ->
%%%
shortcut_branches(Vtx, G, St) ->
- Vs = reverse(beam_digraph:reverse_postorder(G, [Vtx])),
+ Vs = reverse(graph:reverse_postorder(G, [Vtx])),
do_shortcut_branches(Vs, G, St).
do_shortcut_branches([V|Vs], G0, St) ->
@@ -1319,11 +1319,11 @@ do_shortcut_branches([], G, _St) -> G.
redirect_edge(_From, To, {_Label,To}, G) ->
G;
redirect_edge(From, To0, {Label,To}, G0) ->
- G = beam_digraph:del_edge(G0, {From,To0,Label}),
- beam_digraph:add_edge(G, From, To, Label).
+ G = graph:del_edge(G0, {From,To0,Label}),
+ graph:add_edge(G, From, To, Label).
eval_bs(Vtx, G, St) ->
- case beam_digraph:vertex(G, Vtx) of
+ case graph:vertex(G, Vtx) of
#b_set{op={bif,'=:='},args=[#b_var{}=Bool,#b_literal{val=true}]} ->
case get_def(Bool, G, St) of
#b_set{op=phi}=Phi ->
@@ -1359,7 +1359,7 @@ phi_bs(#b_set{op=phi,dst=PhiDst,args=PhiArgs}) ->
end.
eval_instr(Vtx, G, Bs) ->
- case beam_digraph:vertex(G, Vtx) of
+ case graph:vertex(G, Vtx) of
#b_set{} when map_size(Bs) =:= 0 ->
%% With no bindings, eval_safe_bool_expr() is
%% unlikely to do anything useful. If we would
@@ -1375,8 +1375,8 @@ eval_instr(Vtx, G, Bs) ->
br ->
%% We can shortcut this branch unless its
%% target is a phi node.
- [Next] = beam_digraph:out_neighbours(G, Vtx),
- case beam_digraph:vertex(G, Next) of
+ [Next] = graph:out_neighbours(G, Vtx),
+ case graph:vertex(G, Next) of
#b_set{op=phi} -> Vtx;
_ -> eval_instr(Next, G, Bs)
end;
@@ -1436,7 +1436,7 @@ eval_literal_args([], Acc) ->
%%%
ensure_init(Root, G, G0) ->
- Vs = beam_digraph:vertices(G),
+ Vs = graph:vertices_with_labels(G),
%% Build an ordset of a all variables used by the code
%% before the optimization.
@@ -1446,7 +1446,7 @@ ensure_init(Root, G, G0) ->
%% the digraph. Variables not included in this map have been
%% defined by code before the code in the digraph.
Vars = #{Dst => unset || {_,#b_set{dst=Dst}} <- Vs},
- RPO = beam_digraph:reverse_postorder(G, [Root]),
+ RPO = graph:reverse_postorder(G, [Root]),
ensure_init_1(RPO, Used, G, #{Root=>Vars}).
ensure_init_1([V|Vs], Used, G, InitMaps0) ->
@@ -1456,10 +1456,10 @@ ensure_init_1([], _, _, _) -> ok.
ensure_init_instr(Vtx, Used, G, InitMaps0) ->
VarMap0 = map_get(Vtx, InitMaps0),
- case beam_digraph:vertex(G, Vtx) of
+ case graph:vertex(G, Vtx) of
#b_set{dst=Dst}=I ->
do_ensure_init_instr(I, VarMap0, InitMaps0),
- OutVs = beam_digraph:out_neighbours(G, Vtx),
+ OutVs = graph:out_neighbours(G, Vtx),
VarMap = VarMap0#{Dst=>set},
InitMaps = InitMaps0#{Vtx:=VarMap},
ensure_init_successors(OutVs, G, VarMap, InitMaps);
@@ -1502,17 +1502,17 @@ ensure_init_instr(Vtx, Used, G, InitMaps0) ->
end
end;
_ ->
- OutVs = beam_digraph:out_neighbours(G, Vtx),
+ OutVs = graph:out_neighbours(G, Vtx),
ensure_init_successors(OutVs, G, VarMap0, InitMaps0)
end.
ensure_init_used(G) ->
- Vs = beam_digraph:vertices(G),
+ Vs = graph:vertices_with_labels(G),
ensure_init_used_1(Vs, G, []).
ensure_init_used_1([{Vtx,#b_set{dst=Dst}=I}|Vs], G, Acc0) ->
Acc1 = [beam_ssa:used(I)|Acc0],
- case beam_digraph:out_degree(G, Vtx) of
+ case graph:out_degree(G, Vtx) of
2 ->
Acc = [[Dst]|Acc1],
ensure_init_used_1(Vs, G, Acc);
@@ -1600,7 +1600,7 @@ digraph_to_ssa([], _G, Blocks, Seen) ->
{Blocks,Seen}.
digraph_to_ssa_blk(From, G, Blocks, Acc0) ->
- case beam_digraph:vertex(G, From) of
+ case graph:vertex(G, From) of
#b_set{dst=Dst}=I ->
case get_targets(From, G) of
{br,Succ,Fail} ->
@@ -1662,7 +1662,7 @@ get_def(#b_var{}=Bool, #st{defs=Defs}) ->
get_def(Var, G, #st{ldefs=LDefs,defs=Defs}) ->
case LDefs of
#{Var:=Vtx} ->
- beam_digraph:vertex(G, Vtx);
+ graph:vertex(G, Vtx);
#{} ->
%% Not in the graph. Returning definitions for phi nodes
%% outside the graph is useful for shortcut_branches().
@@ -1673,10 +1673,10 @@ get_def(Var, G, #st{ldefs=LDefs,defs=Defs}) ->
end.
add_succ_fail_edges(From, Succ, Fail, G0) ->
- G1 = beam_digraph:add_edge(G0, From, Succ, succ),
- G = beam_digraph:add_edge(G1, From, Fail, fail),
- case beam_digraph:out_edges(G0, From) of
- [{From,_,next}=E] -> beam_digraph:del_edge(G, E);
+ G1 = graph:add_edge(G0, From, Succ, succ),
+ G = graph:add_edge(G1, From, Fail, fail),
+ case graph:out_edges(G0, From) of
+ [{From,_,next}=E] -> graph:del_edge(G, E);
[] -> G
end.
@@ -1686,7 +1686,7 @@ get_vertex(#b_var{}=Var, #st{ldefs=LDefs}) ->
map_get(Var, LDefs).
get_targets(Vtx, G) when is_integer(Vtx) ->
- case beam_digraph:out_edges(G, Vtx) of
+ case graph:out_edges(G, Vtx) of
[{_,To,next}] ->
{br,To};
[{_,Succ,succ},{_,Fail,fail}] ->
@@ -1701,7 +1701,7 @@ get_targets(#b_var{}=Var, G, #st{ldefs=LDefs}) ->
get_targets(map_get(Var, LDefs), G).
del_out_edges(V, G) ->
- beam_digraph:del_edges(G, beam_digraph:out_edges(G, V)).
+ graph:del_edges(G, graph:out_edges(G, V)).
covered(From, To, G) ->
Seen0 = #{},
@@ -1711,7 +1711,7 @@ covered(From, To, G) ->
covered_1(To, To, _G, Seen) ->
{yes,Seen};
covered_1(From, To, G, Seen) ->
- Vs = beam_digraph:out_neighbours(G, From),
+ Vs = graph:out_neighbours(G, From),
covered_list(Vs, To, G, Seen, no).
covered_list([V|Vs], To, G, Seen0, AnyFound) ->
@@ -1734,10 +1734,10 @@ covered_list([], _, _, Seen, AnyFound) ->
{AnyFound,Seen}.
digraph_roots(G) ->
- digraph_roots_1(beam_digraph:vertices(G), G).
+ digraph_roots_1(graph:vertices(G), G).
-digraph_roots_1([{V,_}|Vs], G) ->
- case beam_digraph:in_degree(G, V) of
+digraph_roots_1([V|Vs], G) ->
+ case graph:in_degree(G, V) of
0 ->
[V|digraph_roots_1(Vs, G)];
_ ->
diff --git a/lib/compiler/src/beam_ssa_recv.erl b/lib/compiler/src/beam_ssa_recv.erl
index 77559a80ff..562147ce1a 100644
--- a/lib/compiler/src/beam_ssa_recv.erl
+++ b/lib/compiler/src/beam_ssa_recv.erl
@@ -119,7 +119,7 @@
format_error(OptInfo) ->
format_opt_info(OptInfo).
--record(scan, { graph=beam_digraph:new(),
+-record(scan, { graph=graph:new(),
module :: #{ beam_ssa:b_local() => {beam_ssa:block_map(),
[beam_ssa:b_var()],
[beam_ssa:b_var()]} },
@@ -317,16 +317,16 @@ scan_add_edge(From, To, State) ->
scan_add_edge(From, To, Label, State0) ->
State = scan_add_vertex(To, scan_add_vertex(From, State0)),
- Graph = beam_digraph:add_edge(State#scan.graph, From, To, Label),
+ Graph = graph:add_edge(State#scan.graph, From, To, Label),
State#scan{graph=Graph}.
scan_add_vertex(Vertex, #scan{graph=Graph0}=State) ->
- case beam_digraph:has_vertex(Graph0, Vertex) of
+ case graph:has_vertex(Graph0, Vertex) of
true ->
State;
false ->
- Graph = beam_digraph:add_vertex(Graph0, Vertex),
+ Graph = graph:add_vertex(Graph0, Vertex),
State#scan{graph=Graph}
end.
@@ -463,7 +463,7 @@ propagate_references_1([{Vertex, Ref} | VRefs], G, Acc0) ->
Acc0;
false ->
Acc1 = Acc0#{ Vertex => sets:add_element(Ref, Refs) },
- Next = pr_successors(beam_digraph:out_edges(G, Vertex), Ref),
+ Next = pr_successors(graph:out_edges(G, Vertex), Ref),
propagate_references_1(Next, G, Acc1)
end,
propagate_references_1(VRefs, G, Acc);
@@ -681,7 +681,7 @@ intersect_uses_1([{Vertex, Ref} | Vs], RefMap, Graph, Acc0) ->
{true, false} ->
%% This block lies between reference creation and the receive
%% block, add it to the intersection.
- Edges = beam_digraph:in_edges(Graph, Vertex),
+ Edges = graph:in_edges(Graph, Vertex),
Next = iu_predecessors(Edges, Ref),
ActiveRefs = sets:add_element(Ref, ActiveRefs0),
intersect_uses_1(Next, RefMap, Graph,
@@ -735,7 +735,7 @@ plan_markers_1(MakeRefs0, FuncId, UsageMap) ->
plan_clears(UsageMap, Graph) ->
maps:fold(fun({FuncId, _}=Vertex, ActiveRefs, Acc) ->
- Edges = beam_digraph:out_edges(Graph, Vertex),
+ Edges = graph:out_edges(Graph, Vertex),
case plan_clears_1(Edges, ActiveRefs, UsageMap) of
[_|_]=Clears ->
Clears0 = maps:get(FuncId, Acc, []),
diff --git a/lib/compiler/src/beam_ssa_ss.erl b/lib/compiler/src/beam_ssa_ss.erl
index f0ef95da45..f12f27fd67 100644
--- a/lib/compiler/src/beam_ssa_ss.erl
+++ b/lib/compiler/src/beam_ssa_ss.erl
@@ -22,7 +22,7 @@
%%
%% This module provides a database storing the sharing status for the
%% variables in a function. The database is represented as a graph
-%% (beam_digraph) where the nodes are variables and values. Edges are
+%% where the nodes are variables and values. Edges are
%% extraction and embedding operations. Nodes are labeled with the
%% sharing status of the variable and edges are labeled with the type
%% of extraction/embedding operation.
@@ -82,7 +82,7 @@
-define(ASSERT(Assert), skip).
-endif.
--type sharing_state() :: any(). % A beam_digraph graph.
+-type sharing_state() :: any(). % A graph
-type sharing_status() :: 'unique' | 'aliased' | 'no_info'.
-type element() :: 'hd' | 'tl' | non_neg_integer().
@@ -98,7 +98,7 @@ add_vertex(State, V, Status) ->
plain -> ok;
#b_literal{} -> ok
end),
- beam_digraph:add_vertex(State, V, Status).
+ graph:add_vertex(State, V, Status).
add_edge(State, Src, Dst, Lbl) ->
?ASSERT(begin
@@ -119,15 +119,15 @@ add_edge(State, Src, Dst, Lbl) ->
ok
end
end),
- beam_digraph:add_edge(State, Src, Dst, Lbl).
+ graph:add_edge(State, Src, Dst, Lbl).
-spec derive_from(beam_ssa:b_var(), beam_ssa:b_var(), sharing_state()) ->
sharing_state().
derive_from(Dst, Src, State) ->
?DP("Deriving ~p from ~p~nSS:~n~s~n", [Dst, Src, dump(State)]),
?assert_state(State),
- case {beam_digraph:vertex(State, Dst, unique),
- beam_digraph:vertex(State, Src, plain)} of
+ case {graph:vertex(State, Dst, unique),
+ graph:vertex(State, Src, plain)} of
{_,plain} ->
State;
{aliased,_} ->
@@ -146,7 +146,7 @@ derive_from(Dst, Src, State) ->
false ->
%% Source is not aliased and has not been embedded
%% in a term, record that it now is.
- State1 = case beam_digraph:has_vertex(State, Dst) of
+ State1 = case graph:has_vertex(State, Dst) of
true ->
State;
false ->
@@ -173,15 +173,15 @@ add_embedding(Dst, Src, Element, State0) ->
%% element.
State1 = case Src of
plain ->
- beam_digraph:add_vertex(State0, Src, unique);
+ graph:add_vertex(State0, Src, unique);
#b_literal{} ->
- beam_digraph:add_vertex(State0, Src, unique);
+ graph:add_vertex(State0, Src, unique);
_ ->
- case beam_digraph:has_vertex(State0, Src) of
+ case graph:has_vertex(State0, Src) of
true ->
State0;
false ->
- beam_digraph:add_vertex(State0, Src, unique)
+ graph:add_vertex(State0, Src, unique)
end
end,
@@ -196,7 +196,7 @@ add_embedding(Dst, Src, Element, State0) ->
%% If the variable being embedded ends up with more than one
%% out-edge, the source will be aliased, unless it is a plain value.
- case beam_digraph:out_edges(State, Src) of
+ case graph:out_edges(State, Src) of
[_] ->
State;
_ when Src =/= plain ->
@@ -215,13 +215,13 @@ add_embedding(Dst, Src, Element, State0) ->
extract(Dst, Src, Element, State) ->
?DP("Extracting ~p[~p] into ~p~n", [Src,Element,Dst]),
?assert_state(State),
- case beam_digraph:vertex(State, Src, plain) of
+ case graph:vertex(State, Src, plain) of
aliased ->
%% The pair/tuple is aliased, so what is extracted will be aliased.
?assert_state(set_status(Dst, aliased, State));
unique ->
%% The aggregate is unique, but elements can be aliased.
- OutEdges = beam_digraph:out_edges(State, Src),
+ OutEdges = graph:out_edges(State, Src),
?ASSERT(true = is_integer(Element)
orelse (Element =:= hd) orelse (Element =:= tl)),
?DP("dst: ~p, src: ~p, e: ~p, out-edges: ~p~n",
@@ -258,7 +258,7 @@ extract_element(Dst, Src, Element, [], State0) ->
extract_status_for_element(Element, Src, Dst, State0) ->
?DP(" extract_status_for_element(~p, ~p)~n", [Element, Src]),
- InEdges = beam_digraph:in_edges(State0, Src),
+ InEdges = graph:in_edges(State0, Src),
?DP(" in-edges: ~p~n", [InEdges]),
Embeddings = [Var || {Var,_,{embed,SE}} <- InEdges, Element =:= SE],
Extracts = [Ex || {_,_,{extract,_}}=Ex <- InEdges],
@@ -273,8 +273,8 @@ extract_status_for_element(Element, Src, Dst, State0) ->
?DP(" found embedding~n"),
?DP(" the source is ~p~n", [Var]),
?DP(" SS~n~s~n", [dump(State0)]),
- ?DP(" status ~p~n", [beam_digraph:vertex(State0, Var, unique)]),
- State = set_status(Dst, beam_digraph:vertex(State0, Var, unique),
+ ?DP(" status ~p~n", [graph:vertex(State0, Var, unique)]),
+ State = set_status(Dst, graph:vertex(State0, Var, unique),
State0),
?DP(" Returned SS~n~s~n", [dump(State)]),
?assert_state(State);
@@ -292,9 +292,9 @@ get_status_of_extracted_element(Aggregate, [First|Rest]=Elements, State) ->
%% extracts from unique aggregates. This implies that when the
%% chain is traced backwards, no aliased aggregates will be found,
%% but in case that invariant is ever broken, assert.
- ?ASSERT(unique = beam_digraph:vertex(State, Aggregate, unique)),
+ ?ASSERT(unique = graph:vertex(State, Aggregate, unique)),
?DP(" aggregate is unique~n"),
- InEdges = beam_digraph:in_edges(State, Aggregate),
+ InEdges = graph:in_edges(State, Aggregate),
Embeddings = [Src || {Src,_,{embed,E}} <- InEdges, First =:= E],
Extracts = [{Src,E} || {Src,_,{extract,E}} <- InEdges],
?DP(" embeddings ~p~n", [Embeddings]),
@@ -309,7 +309,7 @@ get_status_of_extracted_element(Aggregate, [First|Rest]=Elements, State) ->
end;
get_status_of_extracted_element(Aggregate, [], State) ->
?DP(" ~s(~p, [], ...)~n", [?FUNCTION_NAME, Aggregate]),
- S = beam_digraph:vertex(State, Aggregate, unique),
+ S = graph:vertex(State, Aggregate, unique),
?DP(" bottomed out, status is ~p~n", [S]),
S.
@@ -320,11 +320,11 @@ forward_status(Main, Other) ->
?DP("Forwarding state~n"),
?assert_state(Main),
?assert_state(Other),
- R = beam_digraph:foldv(
+ R = graph:fold_vertices(
Main,
fun(#b_var{}=V, S, Acc) when S =/= aliased ->
maybe
- true ?= beam_digraph:has_vertex(Other, V),
+ true ?= graph:has_vertex(Other, V),
aliased ?= get_status(V, Other),
set_status(V, aliased, Acc)
else
@@ -340,15 +340,15 @@ forward_status(Main, Other) ->
-spec get_status(beam_ssa:b_var(), sharing_state()) ->
sharing_status().
get_status(V=#b_var{}, State) ->
- beam_digraph:vertex(State, V, unique).
+ graph:vertex(State, V, unique).
-spec merge(sharing_state(), sharing_state()) -> sharing_state().
merge(StateA, StateB) ->
?DP("Merging states~n"),
?assert_state(StateA),
?assert_state(StateB),
- SizeA = beam_digraph:no_vertices(StateA),
- SizeB = beam_digraph:no_vertices(StateB),
+ SizeA = graph:no_vertices(StateA),
+ SizeB = graph:no_vertices(StateB),
%% Always merge the smaller state into the larger.
{Small,Large} = if SizeA < SizeB ->
{StateA,StateB};
@@ -360,14 +360,14 @@ merge(StateA, StateB) ->
?DP(dump(Small)),
?DP("Large:~n"),
?DP(dump(Large)),
- R = merge(Large, Small, beam_digraph:vertices(Small),
+ R = merge(Large, Small, graph:vertices_with_labels(Small),
sets:new(), sets:new()),
?assert_state(R).
merge(Dest, Source, [{V,VStatus}|Vertices], Edges0, Forced) ->
Edges = accumulate_edges(V, Source, Edges0),
- DestStatus = beam_digraph:vertex(Dest, V, false),
+ DestStatus = graph:vertex(Dest, V, false),
case {DestStatus,VStatus} of
{Status,Status} ->
%% Same status in both states.
@@ -402,7 +402,7 @@ merge1(Dest0, Source, [{plain,To,Lbl}|Edges], Fixups, Forced) ->
merge1(Dest, Source, Edges, Fixups, Forced);
merge1(Dest0, Source, [{From,To,Lbl}=Edge|Edges], Fixups, Forced) ->
?DP(" Adding edge ~p -> ~p, lbl: ~p~n", [From,To,Lbl]),
- OutEdges = beam_digraph:out_edges(Dest0, From),
+ OutEdges = graph:out_edges(Dest0, From),
case {ordsets:is_element(Edge, OutEdges),ordsets:is_empty(OutEdges)} of
{true,_} ->
?DP(" Already exists~n"),
@@ -431,7 +431,7 @@ merge1(Dest, _Source, [], Fixups, Forced) ->
merge2(Dest, _Source, sets:to_list(Fixups), Forced).
merge2(Dest0, _Source, [{alias,From,Lbl}|Fixups], Forced) ->
- OutEdges = beam_digraph:out_edges(Dest0, From),
+ OutEdges = graph:out_edges(Dest0, From),
Dest = foldl(fun({#b_var{},To,L}, Acc) when L =:= Lbl ->
set_status(To, aliased, Acc);
(_, Acc) ->
@@ -445,15 +445,15 @@ merge2(Dest0, _Source, [], Forced) ->
?assert_state(Dest).
accumulate_edges(V, State, Edges0) ->
- InEdges = beam_digraph:in_edges(State, V),
- OutEdges = beam_digraph:out_edges(State, V),
+ InEdges = graph:in_edges(State, V),
+ OutEdges = graph:out_edges(State, V),
foldl(fun sets:add_element/2,
foldl(fun sets:add_element/2, Edges0, InEdges),
OutEdges).
-spec new() -> sharing_state().
new() ->
- beam_digraph:new().
+ graph:new().
-spec phi(beam_ssa:b_var(), [beam_ssa:b_var()],
sharing_state(), non_neg_integer())
@@ -498,9 +498,9 @@ prune([{0,_}|_], _, _, _) ->
prune([{Depth,V}|Work], Killed, LiveVars, State0) ->
case is_safe_to_prune(V, LiveVars, State0) of
true ->
- State = beam_digraph:del_vertex(State0, V),
+ State = graph:del_vertex(State0, V),
Ins = [{Depth - 1, I}
- || I <- beam_digraph:in_neighbours(State0, V)],
+ || I <- graph:in_neighbours(State0, V)],
prune(Ins++Work, Killed, LiveVars, State);
false ->
prune(Work, Killed, LiveVars, State0)
@@ -514,7 +514,7 @@ is_safe_to_prune(V, LiveVars, State) ->
false;
false ->
%% Safe to prune if all out-neighbours are safe-to-prune.
- case beam_digraph:out_neighbours(State, V) of
+ case graph:out_neighbours(State, V) of
[] ->
true;
Outs ->
@@ -537,9 +537,9 @@ prune_by_add(LiveVars, State) ->
?assert_state(State),
?DP("Pruning to ~p~n", [sets:to_list(LiveVars)]),
?DP("~s~n", [dump(State)]),
- ?DP("Vertices: ~p~n", [beam_digraph:vertices(State)]),
+ ?DP("Vertices: ~p~n", [graph:vertices_with_labels(State)]),
R = prune_by_add([{0,V} || V <- sets:to_list(LiveVars),
- beam_digraph:has_vertex(State, V)],
+ graph:has_vertex(State, V)],
[], new(), State),
?DP("Pruned result~n~s~n", [dump(R)]),
?assert_state(R).
@@ -548,15 +548,15 @@ prune_by_add([{Depth0,V}|Wanted], Edges, New0, Old) ->
?DP("Looking at ~p~n", [V]),
?DP("Curr:~n~s~n", [dump(New0)]),
?DP("Wanted: ~p~n", [Wanted]),
- case beam_digraph:has_vertex(New0, V) of
+ case graph:has_vertex(New0, V) of
true ->
%% This variable is already added.
prune_by_add(Wanted, Edges, New0, Old);
false when Depth0 < ?SS_DEPTH_LIMIT ->
%% This variable has to be kept. Add it to the new graph.
- New = add_vertex(New0, V, beam_digraph:vertex(Old, V)),
+ New = add_vertex(New0, V, graph:vertex(Old, V)),
%% Add all incoming edges to this node.
- InEdges = beam_digraph:in_edges(Old, V),
+ InEdges = graph:in_edges(Old, V),
Depth = Depth0 + 1,
InNodes = [{Depth, From} || {From,_,_} <:- InEdges],
prune_by_add(InNodes ++ Wanted, InEdges ++ Edges, New, Old);
@@ -594,7 +594,7 @@ set_call_result(Dst, {unique,Elements}, SS0, Cnt0) ->
tl -> ok;
E when is_integer(E), E >= 0 -> ok
end),
- SS2 = beam_digraph:add_edge(SS1, V, Dst, {embed,Idx}),
+ SS2 = graph:add_edge(SS1, V, Dst, {embed,Idx}),
set_call_result(V, Element, SS2, Cnt+1)
end, {SS0,Cnt0}, Elements).
@@ -618,7 +618,7 @@ set_status(#b_var{}=V, Status, State0) ->
%% is embedded remains unchanged.
?DP("Setting status of ~p to ~p~n", [V,Status]),
- case beam_digraph:vertex(State0, V, unique) of
+ case graph:vertex(State0, V, unique) of
Status ->
%% Status is unchanged.
State0;
@@ -634,7 +634,7 @@ set_status(#b_var{}=V, Status, State0) ->
set_alias([#b_var{}=V|Vars], State0) ->
%% TODO: fold into the above
- case beam_digraph:vertex(State0, V, unique) of
+ case graph:vertex(State0, V, unique) of
aliased ->
set_alias(Vars, State0);
_ ->
@@ -645,9 +645,9 @@ set_alias([], State) ->
State.
get_alias_edges(V, State) ->
- OutEdges = [To || {#b_var{},To,_} <- beam_digraph:out_edges(State, V)],
+ OutEdges = [To || {#b_var{},To,_} <- graph:out_edges(State, V)],
EmbedEdges = [Src
- || {#b_var{}=Src,_,Lbl} <- beam_digraph:in_edges(State, V),
+ || {#b_var{}=Src,_,Lbl} <- graph:in_edges(State, V),
case Lbl of
embed -> true;
{embed,_} -> true;
@@ -657,11 +657,11 @@ get_alias_edges(V, State) ->
-spec size(sharing_state()) -> non_neg_integer().
size(State) ->
- beam_digraph:no_vertices(State).
+ graph:no_vertices(State).
-spec variables(sharing_state()) -> [beam_ssa:b_var()].
variables(State) ->
- [V || {V,_Lbl} <:- beam_digraph:vertices(State)].
+ graph:vertices(State).
-type call_in_arg_status() :: no_info
| unique
@@ -755,18 +755,18 @@ merge_in_arg(#b_var{}=V, Status, 0, State) ->
aliased
end;
merge_in_arg(#b_var{}=V, unique, _Cutoff, State) ->
- case beam_digraph:vertex(State, V, unique) of
+ case graph:vertex(State, V, unique) of
no_info ->
unique;
S ->
S
end;
merge_in_arg(#b_var{}=V, Status, Cutoff, State) ->
- case beam_digraph:vertex(State, V, unique) of
+ case graph:vertex(State, V, unique) of
aliased ->
aliased;
unique ->
- InEdges = beam_digraph:in_edges(State, V),
+ InEdges = graph:in_edges(State, V),
Elements = case Status of
{unique,Es} -> Es;
no_info -> #{}
@@ -861,7 +861,7 @@ merge_elements([{_Src,_,embed}|Rest], _Elements0, Cutoff, State) ->
merge_elements(Rest, no_info, Cutoff, State);
merge_elements([{Src,V,{extract,E}}], Elements, Cutoff, State) ->
?DP("Looking for an embedding of the ~p element from ~p~n", [E, Src]),
- InEdges = beam_digraph:in_edges(State, Src),
+ InEdges = graph:in_edges(State, Src),
case [Other || {Other,_,{embed,EdgeOp}} <- InEdges, EdgeOp =:= E] of
[Next] ->
?DP("Found: ~p~n", [Next]),
@@ -901,14 +901,14 @@ init_element(Idx, Status, Child, Cnt0, SS0) ->
tl -> ok;
I when is_integer(I), I >= 0 -> ok
end),
- SS = beam_digraph:add_edge(SS1, ElemV, Child, {embed,Idx}),
+ SS = graph:add_edge(SS1, ElemV, Child, {embed,Idx}),
{SS,Cnt}.
%% Internal helpers
-spec has_out_edges(beam_ssa:b_var(), sharing_state()) -> boolean().
has_out_edges(V, State) ->
- beam_digraph:out_edges(State, V) =/= [].
+ graph:out_edges(State, V) =/= [].
%% Debug support below
@@ -927,23 +927,23 @@ assert_state(State) ->
%% Check that we don't have edges between non-existing nodes
assert_bad_edges(State) ->
[{assert_variable_exists(F, State), assert_variable_exists(T, State)}
- || {F,T,_} <:- beam_digraph:edges(State)].
+ || {F,T,_} <:- graph:edges(State)].
%% Check that extracted and embedded elements of an aliased variable
%% are aliased.
assert_aliased_parent_implies_aliased(State) ->
- [assert_apia(A, State) || {A,aliased} <- beam_digraph:vertices(State)].
+ [assert_apia(A, State) || {A,aliased} <- graph:vertices_with_labels(State)].
assert_apia(Parent, State) ->
Children = [Child
- || {_,Child,Info} <:- beam_digraph:out_edges(State, Parent),
+ || {_,Child,Info} <:- graph:out_edges(State, Parent),
case Info of
{extract,_} -> true;
embed -> true;
{embed,_} -> false
end],
- [case beam_digraph:vertex(State, Child, unique) of
+ [case graph:vertex(State, Child, unique) of
aliased ->
ok;
_ ->
@@ -955,13 +955,13 @@ assert_apia(Parent, State) ->
%% Check that elements which are embedded twice or more times are
%% aliased.
assert_embedded_in_aliased_implies_aliased(State) ->
- [assert_eiaia(A, State) || {A,aliased} <- beam_digraph:vertices(State)].
+ [assert_eiaia(A, State) || {A,aliased} <- graph:vertices_with_labels(State)].
assert_eiaia(Embedder, State) ->
NotAliased = [ Src
- || {Src,_,embed} <- beam_digraph:in_edges(State, Embedder),
- beam_digraph:vertex(State, Src, unique) =/= aliased,
- beam_digraph:vertex(State, Src, unique) =/= no_info],
+ || {Src,_,embed} <- graph:in_edges(State, Embedder),
+ graph:vertex(State, Src, unique) =/= aliased,
+ graph:vertex(State, Src, unique) =/= no_info],
case NotAliased of
[] ->
State;
@@ -975,11 +975,11 @@ assert_eiaia(Embedder, State) ->
%% Check that elements which are embedded twice or more times are
%% aliased.
assert_multiple_embeddings_force_aliasing(State) ->
- [assert_mefa(V, State) || {V,unique} <- beam_digraph:vertices(State)].
+ [assert_mefa(V, State) || {V,unique} <- graph:vertices_with_labels(State)].
assert_mefa(V, State) ->
- NotAliased = [ B || {B,_,embed} <- beam_digraph:out_edges(State, V),
- beam_digraph:vertex(State, B, unique) =/= aliased],
+ NotAliased = [ B || {B,_,embed} <- graph:out_edges(State, V),
+ graph:vertex(State, B, unique) =/= aliased],
case NotAliased of
[_,_|_] ->
io:format("Expected ~p to be aliased in:~n~s.~n", [V, dump(State)]),
@@ -990,7 +990,7 @@ assert_mefa(V, State) ->
%% Check that elements which are extracted twice are aliased.
assert_multiple_extractions_force_aliasing(State) ->
- [assert_mxfa(V, State) || {V,_} <:- beam_digraph:vertices(State)].
+ [assert_mxfa(V, State) || V <:- graph:vertices(State)].
assert_mxfa(V, State) ->
%% Build a map of the extracted values keyed by element.
@@ -1002,11 +1002,11 @@ assert_mxfa(V, State) ->
Acc;
({_,_,{embed,_}}, Acc) ->
Acc
- end, #{}, beam_digraph:out_edges(State, V)),
+ end, #{}, graph:out_edges(State, V)),
Bad = maps:fold(
fun(_Elem, [_,_|_]=Vars, Acc) ->
[X || X <- Vars,
- beam_digraph:vertex(State, X, unique) =/= aliased]
+ graph:vertex(State, X, unique) =/= aliased]
++ Acc;
(_, _, Acc) ->
Acc
@@ -1020,12 +1020,12 @@ assert_mxfa(V, State) ->
end.
assert_variable_exists(plain, State) ->
- case beam_digraph:has_vertex(State, plain) of
+ case graph:has_vertex(State, plain) of
false ->
io:format("Expected ~p in~n ~s.~n", [plain, dump(State)]),
throw(assertion_failure);
_ ->
- case beam_digraph:vertex(State, plain, unique) of
+ case graph:vertex(State, plain, unique) of
unique -> State;
Other ->
io:format("Expected plain to be unique, was ~p, in:~n~p~n",
@@ -1036,7 +1036,7 @@ assert_variable_exists(plain, State) ->
assert_variable_exists(#b_literal{}, State) ->
State;
assert_variable_exists(#b_var{}=V, State) ->
- case beam_digraph:has_vertex(State, V) of
+ case graph:has_vertex(State, V) of
false ->
io:format("Expected ~p in~n~s.~n", [V, dump(State)]),
throw(assertion_failure);
@@ -1049,17 +1049,17 @@ assert_variable_exists(#b_var{}=V, State) ->
-ifdef(PROVIDE_DUMP).
-spec dump(sharing_state()) -> iolist().
dump(State) ->
- Ls = lists:enumerate(0, beam_digraph:vertices(State)),
- V2Id = #{ V=>Id || {Id,{V,_}} <- Ls },
+ Ls = lists:enumerate(0, graph:vertices(State)),
+ V2Id = #{ V=>Id || {Id,V} <- Ls },
[
"digraph G {\n",
[ io_lib:format(" ~p [label=\"~p:~p\",shape=\"box\"]~n",
- [Id,V,beam_digraph:vertex(State, V)])
+ [Id,V,graph:vertex(State, V)])
|| V:=Id <- V2Id],
[ io_lib:format(" ~p -> ~p [label=\"~p\"]~n",
[maps:get(From, V2Id, plain),
maps:get(To, V2Id),
Lbl])
- || {From,To,Lbl} <- beam_digraph:edges(State)],
+ || {From,To,Lbl} <- graph:edges(State)],
"}\n"].
-endif.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index f627aec471..d080321346 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -3125,8 +3125,7 @@ pre_load() ->
beam_clean,
beam_core_to_ssa,
beam_dict,
- beam_digraph,
- beam_doc,
+ beam_doc,
beam_flatten,
beam_jump,
beam_opcodes,
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index 7b1f0be40f..62efb772bc 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -31,7 +31,6 @@
beam_clean,
beam_core_to_ssa,
beam_dict,
- beam_digraph,
beam_disasm,
beam_doc,
beam_flatten,
@@ -87,5 +86,5 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["stdlib-6.0","kernel-8.4","erts-13.0",
+ {runtime_dependencies, ["stdlib-@OTP-19922@","kernel-8.4","erts-13.0",
"crypto-5.1"]}]}.
--
2.51.0