[m-rev.] for preliminary review: Add option to break trans-opt dependencies.
Peter Wang
novalazy at gmail.com
Mon Dec 19 17:48:18 AEDT 2022
Hi,
Here is a patch to improve parallel making of .trans_opt files.
The naming of things is rather clunky.
Here are times for "mmake -j32 trans_opts" in the library directory,
using the attached mer_std.make-trans-opt-deps file:
- without the new option
real 0m39.742s
user 2m11.086s
sys 0m5.166s
- with --make-trans-opt-deps-spec
real 0m18.700s
user 1m42.337s
sys 0m4.331s
It should be possible to improve it by deleting more (unnecessary)
dependencies on .trans_opt files.
A diff showing the changes to the .trans_opt files is attached.
The analysis results are mostly improved, with only a few regressions.
The information of interest in the mer_std.make-trans-opt-deps file is
all in the %-commented out lines. For a given source module, we want to
prevent the compiler reading another module's .trans_opt file.
Therefore, I'm thinking the file should state the negative dependencies
directly, e.g.
foo - {
not bar,
not baz
}
This is of course similar to my pragma no_trans_opt proposal,
only contained in a single file (arguably better).
Peter
-------------- next part --------------
diff --git a/compiler/generate_dep_d_files.m b/compiler/generate_dep_d_files.m
index 4c7277722..1467db53f 100644
--- a/compiler/generate_dep_d_files.m
+++ b/compiler/generate_dep_d_files.m
@@ -76,6 +76,7 @@
:- import_module parse_tree.module_dep_info.
:- import_module parse_tree.module_deps_graph.
:- import_module parse_tree.parse_error.
+:- import_module parse_tree.parse_sym_name.
:- import_module parse_tree.prog_item.
:- import_module parse_tree.read_modules.
:- import_module parse_tree.write_deps_file.
@@ -83,12 +84,16 @@
:- import_module bool.
:- import_module digraph.
+:- import_module int.
:- import_module list.
:- import_module map.
:- import_module maybe.
+:- import_module mercury_term_parser.
:- import_module pair.
:- import_module set.
:- import_module string.
+:- import_module term.
+:- import_module term_context.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -191,7 +196,6 @@ generate_dependencies(Globals, Mode, Search, ModuleName, DepsMap0, !IO) :-
% Compute the interface deps graph and the implementation deps
% graph from the deps map.
-
digraph.init(IntDepsGraph0),
digraph.init(ImpDepsGraph0),
map.values(DepsMap, DepsList),
@@ -200,19 +204,10 @@ generate_dependencies(Globals, Mode, Search, ModuleName, DepsMap0, !IO) :-
maybe_output_imports_graph(Globals, ModuleName,
IntDepsGraph, ImpDepsGraph, !IO),
- % Compute the trans-opt deps ordering, by doing an approximate
- % topological sort of the implementation deps, and then finding
- % the subset of those for which of those we have (or can make)
- % trans-opt files.
-
- digraph.atsort(ImpDepsGraph, ImpDepsOrdering0),
- maybe_output_module_order(Globals, ModuleName, ImpDepsOrdering0, !IO),
- list.map(set.to_sorted_list, ImpDepsOrdering0, ImpDepsOrdering),
- list.condense(ImpDepsOrdering, TransOptDepsOrdering0),
- globals.lookup_accumulating_option(Globals, intermod_directories,
- IntermodDirs),
- get_opt_deps(Globals, yes, IntermodDirs, other_ext(".trans_opt"),
- TransOptDepsOrdering0, TransOptDepsOrdering, !IO),
+ % XXX create ImpDepsOrdering only if we will write a .order file
+ digraph.atsort(ImpDepsGraph, ImpDepsOrdering),
+ maybe_output_module_order(Globals, ModuleName, other_ext(".order"),
+ ImpDepsOrdering, !IO),
trace [compiletime(flag("deps_graph")), runtime(env("DEPS_GRAPH")),
io(!TIO)]
@@ -228,7 +223,6 @@ generate_dependencies(Globals, Mode, Search, ModuleName, DepsMap0, !IO) :-
% implementation dependencies. (We used to take the transitive closure
% of the interface dependencies, but we now include implementation
% details in the interface files).
-
digraph.tc(ImpDepsGraph, TransImpDepsGraph),
digraph.compose(ImpDepsGraph, TransImpDepsGraph, IndirectDepsGraph),
@@ -240,9 +234,61 @@ generate_dependencies(Globals, Mode, Search, ModuleName, DepsMap0, !IO) :-
% and assume that the each module's `.opt' file might import any
% of that module's implementation dependencies; in actual fact,
% it will be some subset of that.
-
digraph.tc(ImpDepsGraph, IndirectOptDepsGraph),
+ % Compute the trans-opt deps for the purposes of making trans-opt
+ % files. This is normally equal to transitive closure of the indirect
+ % dependencies (i.e. IndirectOptDepsGraph) since a module may read the
+ % `.trans_opt' file of any directly or indirectly imported module.
+ %
+ % To deal with cycles in the graph, we impose an arbitrary order on
+ % modules so that, when making the trans-opt file for a module
+ % "earlier" in the cycle, the compiler may read the trans-opt files
+ % of modules "later" in the cycle, but not vice versa.
+ %
+ % The problem with that is twofold:
+ % - Lack of parallelism. The trans-opt files for modules within a
+ % single SCC have to be made one after another.
+ % - The arbitrary ordering is likely to produce sub-optimal
+ % information transfer between trans-opt files.
+ %
+ % To improve the situation, we allow the user to specify a file
+ % (see read_make_trans_opt_deps_spec) to manually remove edges in the
+ % dependency graph, thereby breaking up SCCs and, ideally, converting
+ % the graph into a dag.
+ globals.lookup_maybe_string_option(Globals,
+ make_trans_opt_deps_spec, MaybeSpecFileName),
+ (
+ MaybeSpecFileName = yes(SpecFileName),
+ read_make_trans_opt_deps_spec(SpecFileName, MaybeSpec, !IO),
+ (
+ MaybeSpec = ok(Spec),
+ remove_edges_for_make_trans_opt_deps(Spec,
+ ImpDepsGraph, MakeTransOptDepsGraph0),
+ digraph.tc(MakeTransOptDepsGraph0, MakeTransOptDepsGraph)
+ ;
+ MaybeSpec = error(SpecError),
+ string.format("cannot parse %s: %s",
+ [s(SpecFileName), s(SpecError)], SpecMessage),
+ report_error(ErrorStream, SpecMessage, !IO),
+ MakeTransOptDepsGraph = IndirectOptDepsGraph
+ )
+ ;
+ MaybeSpecFileName = no,
+ MakeTransOptDepsGraph = IndirectOptDepsGraph
+ ),
+ digraph.atsort(MakeTransOptDepsGraph, MakeTransOptDepsOrdering0),
+ maybe_output_module_order(Globals, ModuleName,
+ other_ext(".order-make-trans-opt"), MakeTransOptDepsOrdering0,
+ !IO),
+ list.map(set.to_sorted_list, MakeTransOptDepsOrdering0,
+ MakeTransOptDepsOrdering1),
+ list.condense(MakeTransOptDepsOrdering1, MakeTransOptDepsOrdering2),
+ globals.lookup_accumulating_option(Globals, intermod_directories,
+ IntermodDirs),
+ get_opt_deps(Globals, yes, IntermodDirs, other_ext(".trans_opt"),
+ MakeTransOptDepsOrdering2, MakeTransOptDepsOrdering, !IO),
+
(
Mode = output_d_file_only,
DFilesToWrite = [ModuleDep]
@@ -253,7 +299,7 @@ generate_dependencies(Globals, Mode, Search, ModuleName, DepsMap0, !IO) :-
generate_dependencies_write_d_files(Globals, DFilesToWrite,
IntDepsGraph, ImpDepsGraph,
IndirectDepsGraph, IndirectOptDepsGraph,
- TransOptDepsOrdering, DepsMap, !IO)
+ MakeTransOptDepsGraph, MakeTransOptDepsOrdering, DepsMap, !IO)
),
% For Java, the main target is actually a shell script which will set
@@ -418,6 +464,226 @@ write_edge(Stream, GenNodeName, A, B, !IO) :-
sym_name_to_node_id(Name) =
"\"" ++ sym_name_to_string(Name) ++ "\"".
+%---------------------------------------------------------------------------%
+
+:- type make_trans_opt_deps_spec == map(module_name, set(module_name)).
+
+ % The --make-trans-opts-deps-spec file shall contain a term of the form:
+ %
+ % { PAIRS... }.
+ %
+ % where PAIRS is a comma-separated list of pairs:
+ %
+ % M - { ALLOWED... }
+ %
+ % M is a Mercury module name.
+ % ALLOWED is a comma-separated list of module names.
+ %
+ % Such a pair specifies that for the module M,
+ % if it has a cyclic dependency on T,
+ % but T is not included in ALLOWED,
+ % then the edge M -> T is removed from the dependency graph
+ % for the purposes of making trans-opt files.
+ % In other words, in the process of making M.trans_opt,
+ % the compiler may not read T.trans_opt.
+ %
+ % To make the file less verbose, `builtin' and `private_builtin' are
+ % implicitly included in the ALLOWED list unless M is itself
+ % `builtin' or `private_builtin'.
+ %
+:- pred read_make_trans_opt_deps_spec(string::in,
+ maybe_error(make_trans_opt_deps_spec)::out, io::di, io::uo) is det.
+
+read_make_trans_opt_deps_spec(FileName, Result, !IO) :-
+ io.read_named_file_as_string(FileName, ReadResult, !IO),
+ (
+ ReadResult = ok(Contents),
+ read_term_from_string(FileName, Contents, _EndPos, ReadTerm),
+ (
+ ReadTerm = eof,
+ Result = error("expected term, got EOF")
+ ;
+ ReadTerm = error(Error, LineNum),
+ string.format("line %d: %s", [i(LineNum), s(Error)], Msg),
+ Result = error(Msg)
+ ;
+ ReadTerm = term(_VarSet, Term),
+ parse_make_trans_opt_deps_spec(Term, ParseResult, map.init, Spec),
+ (
+ ParseResult = ok,
+ % XXX check for EOF
+ Result = ok(Spec)
+ ;
+ ParseResult = error(Error),
+ Result = error(Error)
+ )
+ )
+ ;
+ ReadResult = error(Error),
+ Result = error(io.error_message(Error))
+ ).
+
+:- pred parse_make_trans_opt_deps_spec(term::in, maybe_error::out,
+ make_trans_opt_deps_spec::in, make_trans_opt_deps_spec::out) is det.
+
+parse_make_trans_opt_deps_spec(Term, Result, !Spec) :-
+ ( if Term = functor(atom("{}"), TermArgs, _Context) then
+ parse_make_trans_opt_deps_spec_pairs(TermArgs, Result, !Spec)
+ else
+ get_term_context(Term) = context(_FileName, LineNum),
+ string.format("line %d: expected {}", [i(LineNum)], Msg),
+ Result = error(Msg)
+ ).
+
+:- pred parse_make_trans_opt_deps_spec_pairs(list(term)::in, maybe_error::out,
+ make_trans_opt_deps_spec::in, make_trans_opt_deps_spec::out) is det.
+
+parse_make_trans_opt_deps_spec_pairs([], ok, !Spec).
+parse_make_trans_opt_deps_spec_pairs([Term | Terms], Result, !Spec) :-
+ parse_make_trans_opt_deps_spec_pair(Term, Result0, !Spec),
+ (
+ Result0 = ok,
+ parse_make_trans_opt_deps_spec_pairs(Terms, Result, !Spec)
+ ;
+ Result0 = error(Error),
+ Result = error(Error)
+ ).
+
+:- pred parse_make_trans_opt_deps_spec_pair(term::in, maybe_error::out,
+ make_trans_opt_deps_spec::in, make_trans_opt_deps_spec::out) is det.
+
+parse_make_trans_opt_deps_spec_pair(Term, Result, !Spec) :-
+ ( if
+ Term = functor(atom("-"), TermArgs, _Context),
+ TermArgs = [LeftTerm, RightTerm],
+ try_parse_symbol_name(LeftTerm, SourceName)
+ then
+ ( if
+ ( SourceName = unqualified("builtin")
+ ; SourceName = unqualified("private_builtin")
+ )
+ then
+ set.init(TargetSet0)
+ else
+ TargetSet0 = set.from_sorted_list(
+ [unqualified("builtin"), unqualified("private_builtin")])
+ ),
+ parse_make_trans_opt_deps_spec_target_set(RightTerm, Result0,
+ TargetSet0, TargetSet),
+ (
+ Result0 = ok,
+ ( if map.insert(SourceName, TargetSet, !Spec) then
+ Result = ok
+ else
+ get_term_context(Term) = context(_FileName, LineNum),
+ string.format("line %d: duplicate source module %s",
+ [i(LineNum), s(sym_name_to_string(SourceName))], Msg),
+ Result = error(Msg)
+ )
+ ;
+ Result0 = error(Error),
+ Result = error(Error)
+ )
+ else
+ get_term_context(Term) = context(_FileName, LineNum),
+ string.format("line %d: expected -/2", [i(LineNum)], Msg),
+ Result = error(Msg)
+ ).
+
+:- pred parse_make_trans_opt_deps_spec_target_set(term::in, maybe_error::out,
+ set(module_name)::in, set(module_name)::out) is det.
+
+parse_make_trans_opt_deps_spec_target_set(Term, Result, !TargetSet) :-
+ ( if Term = functor(atom("{}"), TermArgs, _Context) then
+ foldl2(parse_make_trans_opt_deps_spec_target, TermArgs,
+ ok, Result0, [], TargetList),
+ (
+ Result0 = ok,
+ set.insert_list(TargetList, !TargetSet),
+ Result = ok
+ ;
+ Result0 = error(Error),
+ Result = error(Error)
+ )
+ else
+ get_term_context(Term) = context(_FileName, LineNum),
+ string.format("line %d: expected {}", [i(LineNum)], Msg),
+ Result = error(Msg)
+ ).
+
+:- pred parse_make_trans_opt_deps_spec_target(term::in,
+ maybe_error::in, maybe_error::out,
+ list(module_name)::in, list(module_name)::out) is det.
+
+parse_make_trans_opt_deps_spec_target(Term, !Result, !ModuleNames) :-
+ ( if try_parse_symbol_name(Term, ModuleName) then
+ !:ModuleNames = [ModuleName | !.ModuleNames]
+ else
+ (
+ !.Result = ok,
+ get_term_context(Term) = context(_FileName, LineNum),
+ string.format("line %d: expected module name", [i(LineNum)], Msg),
+ !:Result = error(Msg)
+ ;
+ !.Result = error(_)
+ )
+ ).
+
+%---------------------------------------------------------------------------%
+
+:- pred remove_edges_for_make_trans_opt_deps(make_trans_opt_deps_spec::in,
+ digraph(module_name)::in, digraph(module_name)::out) is det.
+
+remove_edges_for_make_trans_opt_deps(Spec, !Graph) :-
+ SCCs = set.to_sorted_list(digraph.cliques(!.Graph)),
+ map.foldl(remove_edges_for_make_trans_opt_deps_2(SCCs), Spec, !Graph).
+
+:- pred remove_edges_for_make_trans_opt_deps_2(
+ list(set(digraph_key(module_name)))::in,
+ module_name::in, set(module_name)::in,
+ digraph(module_name)::in, digraph(module_name)::out) is det.
+
+remove_edges_for_make_trans_opt_deps_2(SCCs, SourceName, AllowedTargets,
+ !Graph) :-
+ ( if
+ digraph.search_key(!.Graph, SourceName, SourceKey),
+ find_scc(SCCs, SourceKey, SCC),
+ set.count(SCC) > 1
+ then
+ set.foldl(
+ remove_edges_for_make_trans_opt_deps_3(SourceKey, AllowedTargets),
+ SCC, !Graph)
+ else
+ true
+ ).
+
+:- pred find_scc(list(set(digraph_key(module_name)))::in,
+ digraph_key(module_name)::in, set(digraph_key(module_name))::out)
+ is semidet.
+
+find_scc([SCC | SCCs], Module, FoundSCC) :-
+ ( if set.contains(SCC, Module) then
+ FoundSCC = SCC
+ else
+ find_scc(SCCs, Module, FoundSCC)
+ ).
+
+:- pred remove_edges_for_make_trans_opt_deps_3(digraph_key(module_name)::in,
+ set(module_name)::in, digraph_key(module_name)::in,
+ digraph(module_name)::in, digraph(module_name)::out) is det.
+
+remove_edges_for_make_trans_opt_deps_3(SourceKey, AllowedTargets, TargetKey,
+ !Graph) :-
+ ( if
+ SourceKey \= TargetKey,
+ digraph.lookup_vertex(!.Graph, TargetKey, TargetName),
+ not set.contains(AllowedTargets, TargetName)
+ then
+ digraph.delete_edge(SourceKey, TargetKey, !Graph)
+ else
+ true
+ ).
+
%---------------------------------------------------------------------------%
:- end_module parse_tree.generate_dep_d_files.
%---------------------------------------------------------------------------%
diff --git a/compiler/options.m b/compiler/options.m
index 7d27b7819..def491228 100644
--- a/compiler/options.m
+++ b/compiler/options.m
@@ -387,6 +387,7 @@
; show_developer_type_repns
; show_dependency_graph
; imports_graph
+ ; make_trans_opt_deps_spec
; dump_trace_counts
; dump_hlds
; dump_hlds_pred_id
@@ -1436,6 +1437,7 @@ optdef(oc_aux_output, show_all_type_repns, bool(no)).
optdef(oc_aux_output, show_developer_type_repns, bool(no)).
optdef(oc_aux_output, show_dependency_graph, bool(no)).
optdef(oc_aux_output, imports_graph, bool(no)).
+optdef(oc_aux_output, make_trans_opt_deps_spec, maybe_string(no)).
optdef(oc_aux_output, dump_trace_counts, accumulating([])).
optdef(oc_aux_output, dump_hlds, accumulating([])).
optdef(oc_aux_output, dump_hlds_pred_id, accumulating([])).
@@ -2388,6 +2390,7 @@ long_option("show-developer-type-repns", show_developer_type_repns).
long_option("show-developer-type-representations", show_developer_type_repns).
long_option("show-dependency-graph", show_dependency_graph).
long_option("imports-graph", imports_graph).
+long_option("make-trans-opt-deps-spec", make_trans_opt_deps_spec).
long_option("dump-trace-counts", dump_trace_counts).
long_option("dump-hlds", dump_hlds).
long_option("hlds-dump", dump_hlds).
diff --git a/compiler/write_deps_file.m b/compiler/write_deps_file.m
index 6cb5cbcda..d74eb4da6 100644
--- a/compiler/write_deps_file.m
+++ b/compiler/write_deps_file.m
@@ -32,10 +32,11 @@
:- type maybe_intermod_deps
---> no_intermod_deps
; intermod_deps(
- id_int_deps :: set(module_name),
- id_imp_deps :: set(module_name),
- id_indirect_deps :: set(module_name),
- id_fim_deps :: set(module_name)
+ id_int_deps :: set(module_name),
+ id_imp_deps :: set(module_name),
+ id_indirect_deps :: set(module_name),
+ id_fim_deps :: set(module_name),
+ id_make_trans_opt_deps :: set(module_name)
).
% write_dependency_file(Globals, BurdenedAugCompUnit, MaybeIntermodDeps,
@@ -66,8 +67,8 @@
maybe(list(module_name))::in, io::di, io::uo) is det.
% generate_dependencies_write_d_files(Globals, Modules,
- % IntDepsRel, ImplDepsRel, IndirectDepsRel, IndirectOptDepsRel,
- % TransOptOrder, DepsMap, !IO):
+ % IntDepsGraph, ImplDepsGraph, IndirectDepsGraph, IndirectOptDepsGraph,
+ % MakeTransOptDepsGraph, TransOptOrder, DepsMap, !IO):
%
% This predicate writes out the .d files for all the modules in the
% Modules list.
@@ -78,11 +79,15 @@
% IndirectOptDepsGraph gives the indirect optimization dependencies
% (this includes dependencies via `.opt' and `.trans_opt' files).
% These are all computed from the DepsMap.
+ %
+ % MakeTransOptDepsGraph gives the trans-opt dependency graph for the
+ % purposes of making `.trans_opt' files.
% TransOptOrder gives the ordering that is used to determine
% which other modules the .trans_opt files may depend on.
%
:- pred generate_dependencies_write_d_files(globals::in, list(deps)::in,
deps_graph::in, deps_graph::in, deps_graph::in, deps_graph::in,
+ deps_graph::in,
list(module_name)::in, deps_map::in, io::di, io::uo) is det.
% Write out the `.dv' file, using the information collected in the
@@ -97,7 +102,7 @@
:- pred generate_dependencies_write_dep_file(globals::in, file_name::in,
module_name::in, deps_map::in, io::di, io::uo) is det.
-:- pred maybe_output_module_order(globals::in, module_name::in,
+:- pred maybe_output_module_order(globals::in, module_name::in, other_ext::in,
list(set(module_name))::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
@@ -283,7 +288,8 @@ generate_d_file(Globals, BurdenedAugCompUnit, IntermodDeps,
IndirectIntSpecs = AugCompUnit ^ acu_indirect_int2_specs,
map.keys_as_set(IndirectIntSpecs, IndirectDeps)
;
- IntermodDeps = intermod_deps(IntDeps, ImpDeps, IndirectDeps, _FIMDeps),
+ IntermodDeps = intermod_deps(IntDeps, ImpDeps, IndirectDeps, _FIMDeps,
+ _MakeTransOptDeps),
set.union(IntDeps, ImpDeps, LongDeps0)
),
PublicChildrenMap = ParseTreeModuleSrc ^ ptms_int_includes,
@@ -303,10 +309,17 @@ generate_d_file(Globals, BurdenedAugCompUnit, IntermodDeps,
set.difference(ShortDeps0, LongDeps, ShortDeps1),
set.delete(ModuleName, ShortDeps1, ShortDeps),
+ (
+ IntermodDeps = no_intermod_deps,
+ MakeTransOptDeps = LongDeps
+ ;
+ IntermodDeps = intermod_deps(_, _, _, _, MakeTransOptDeps0),
+ set.delete(ModuleName, MakeTransOptDeps0, MakeTransOptDeps)
+ ),
module_name_to_file_name(Globals, $pred, do_not_create_dirs,
- ext_other(other_ext(".trans_opt_date")),
- ModuleName, TransOptDateFileName, !IO),
- construct_trans_opt_deps_rule(Globals, MaybeTransOptDeps, LongDeps,
+ ext_other(other_ext(".trans_opt_date")), ModuleName,
+ TransOptDateFileName, !IO),
+ construct_trans_opt_deps_rule(Globals, MaybeTransOptDeps, MakeTransOptDeps,
TransOptDateFileName, MmakeRulesTransOpt, !IO),
construct_fact_tables_entries(ModuleMakeVarName,
@@ -406,17 +419,25 @@ generate_d_file(Globals, BurdenedAugCompUnit, IntermodDeps,
maybe(list(module_name))::in, set(module_name)::in, string::in,
list(mmake_entry)::out, io::di, io::uo) is det.
-construct_trans_opt_deps_rule(Globals, MaybeTransOptDeps, LongDeps,
+construct_trans_opt_deps_rule(Globals, MaybeTransOptDeps, MakeTransOptDeps0,
TransOptDateFileName, MmakeRulesTransOpt, !IO) :-
(
- MaybeTransOptDeps = yes(TransOptDeps0),
- set.intersect(set.list_to_set(TransOptDeps0), LongDeps,
- TransOptDateDeps),
+ MaybeTransOptDeps = yes(TransOptDeps),
+ % XXX TransOptDeps and MakeTransOptDeps0 are confusing and should
+ % be renamed.
+ %
+ % MakeTransOptDeps0 is what allows the user to remove edges from the
+ % trans-opt dependency graph.
+ %
+ % Taking the intersection with TransOptDeps removes any circularity
+ % that may remain.
+ set.intersect(set.list_to_set(TransOptDeps), MakeTransOptDeps0,
+ MakeTransOptDeps),
% Note that maybe_read_dependency_file searches for
% this exact pattern.
make_module_file_names_with_suffix(Globals,
ext_other(other_ext(".trans_opt")),
- set.to_sorted_list(TransOptDateDeps), TransOptDateDepsFileNames,
+ set.to_sorted_list(MakeTransOptDeps), TransOptDateDepsFileNames,
!IO),
MmakeRuleTransOpt = mmake_simple_rule("trans_opt_deps",
mmake_rule_is_not_phony,
@@ -850,7 +871,7 @@ construct_foreign_import_rules(Globals, AugCompUnit, IntermodDeps,
_ModuleVersionNumber),
ModuleName = ParseTreeModuleSrc ^ ptms_module_name,
(
- IntermodDeps = intermod_deps(_, _, _, ForeignImportedModuleNamesSet)
+ IntermodDeps = intermod_deps(_, _, _, ForeignImportedModuleNamesSet, _)
;
IntermodDeps = no_intermod_deps,
some [!FIMSpecs] (
@@ -1236,24 +1257,25 @@ construct_subdirs_shorthand_rule(Globals, ModuleName, OtherExt,
%---------------------------------------------------------------------------%
-generate_dependencies_write_d_files(_, [], _, _, _, _, _, _, !IO).
+generate_dependencies_write_d_files(_, [], _, _, _, _, _, _, _, !IO).
generate_dependencies_write_d_files(Globals, [Dep | Deps],
IntDepsGraph, ImpDepsGraph, IndirectDepsGraph, IndirectOptDepsGraph,
- TransOptOrder, DepsMap, !IO) :-
+ MakeTransOptDepsGraph, TransOptOrder, DepsMap, !IO) :-
generate_dependencies_write_d_file(Globals, Dep,
IntDepsGraph, ImpDepsGraph, IndirectDepsGraph, IndirectOptDepsGraph,
- TransOptOrder, DepsMap, !IO),
+ MakeTransOptDepsGraph, TransOptOrder, DepsMap, !IO),
generate_dependencies_write_d_files(Globals, Deps,
IntDepsGraph, ImpDepsGraph, IndirectDepsGraph, IndirectOptDepsGraph,
- TransOptOrder, DepsMap, !IO).
+ MakeTransOptDepsGraph, TransOptOrder, DepsMap, !IO).
:- pred generate_dependencies_write_d_file(globals::in, deps::in,
deps_graph::in, deps_graph::in, deps_graph::in, deps_graph::in,
- list(module_name)::in, deps_map::in, io::di, io::uo) is det.
+ deps_graph::in, list(module_name)::in, deps_map::in, io::di, io::uo)
+ is det.
generate_dependencies_write_d_file(Globals, Dep,
IntDepsGraph, ImpDepsGraph, IndirectDepsGraph, IndirectOptDepsGraph,
- TransOptOrder, _DepsMap, !IO) :-
+ MakeTransOptDepsGraph, TransOptOrder, _DepsMap, !IO) :-
% XXX The fact that _DepsMap is unused here may be a bug.
Dep = deps(_, BurdenedModule),
BurdenedModule = burdened_module(Baggage, ParseTreeModuleSrc),
@@ -1284,8 +1306,11 @@ generate_dependencies_write_d_file(Globals, Dep,
IndirectDeps)
),
+ get_dependencies_from_graph(MakeTransOptDepsGraph, ModuleName,
+ MakeTransOptDeps),
+
IntermodDeps = intermod_deps(IntDeps, ImpDeps, IndirectDeps,
- IndirectOptDeps),
+ IndirectOptDeps, MakeTransOptDeps),
% Compute the trans-opt dependencies for this module. To avoid
% the possibility of cycles, each module is only allowed to depend
@@ -2407,12 +2432,12 @@ get_source_file(DepsMap, ModuleName, FileName) :-
%---------------------------------------------------------------------------%
-maybe_output_module_order(Globals, ModuleName, DepsOrdering, !IO) :-
+maybe_output_module_order(Globals, ModuleName, Ext, DepsOrdering, !IO) :-
globals.lookup_bool_option(Globals, generate_module_order, Order),
(
Order = yes,
module_name_to_file_name(Globals, $pred, do_create_dirs,
- ext_other(other_ext(".order")), ModuleName, OrdFileName, !IO),
+ ext_other(Ext), ModuleName, OrdFileName, !IO),
get_progress_output_stream(Globals, ModuleName, ProgressStream, !IO),
globals.lookup_bool_option(Globals, verbose, Verbose),
string.format("%% Creating module order file `%s'...",
diff --git a/doc/user_guide.texi b/doc/user_guide.texi
index 82ee78a65..8c76955c0 100644
--- a/doc/user_guide.texi
+++ b/doc/user_guide.texi
@@ -201,14 +201,14 @@ generates both @file{.int} and @file{.int2} files.)
@findex --make-private-interface
@findex --make-optimization-interface
@findex --make-transitive-optimization-interface
- at findex --make-trans-opt-int
+ at findex --make-trans-opt
Files whose names end in @file{.opt} are used for inter-module optimization,
and are created using the @samp{--make-optimization-interface}
(or @samp{--make-opt-int}) option.
Similarly, files whose name ends in @file{.trans_opt}
are used for transitive inter-module optimization,
and are created using the @samp{--make-transitive-optimization-interface}
-(or @samp{--make-trans-opt-int}) option.
+(or @samp{--make-trans-opt}) option.
Since the interface of a module changes less often than its implementation,
the @file{.int}, @file{.int0}, @file{.int2}, @file{.int3}, @file{.opt},
-------------- next part --------------
{
private_builtin - {},
builtin - {
private_builtin
},
array - {
exception,
int,
list,
%pretty_printer,
require,
string,
type_desc
},
/*
assoc_list - {
list,
pair,
require,
string,
type_desc
},
benchmarking - {
bool,
int,
io,
list,
maybe,
mutvar,
require,
string
},
*/
bitmap - {
bool,
char,
exception,
int,
%io, % write_bitmap becomes can_loop
list,
maybe,
require,
stream,
string
},
/*
bool - {
enum,
list
},
calendar - {
char,
int,
io,
list,
require,
string,
time
},
*/
char - {
enum,
int,
list,
%pretty_printer,
require,
%term_io,
uint,
uint16,
uint8
},
/*
construct - {
int,
list,
maybe,
require,
rtti_implementation,
type_desc,
univ
},
cord - {
int,
list
},
deconstruct - {
construct,
int,
list,
maybe,
require,
rtti_implementation,
type_desc,
univ
},
dir - {
bool,
char,
exception,
int,
io,
io.file,
list,
maybe,
require,
std_util,
string,
unit
},
enum - {
require
},
*/
exception - {
%io,
%list,
maybe,
%solutions,
%stm_builtin,
%store,
%string,
unit,
univ
},
float - {
exception,
int,
%pretty_printer,
string
},
int - {
%array,
enum,
%exception,
%pretty_printer,
%string,
uint
},
int16 - {
%exception,
int,
%pretty_printer,
require,
%string,
uint,
uint16
},
int32 - {
%exception,
int,
%pretty_printer,
require,
%string,
uint,
uint32
},
int64 - {
%exception,
int,
%pretty_printer,
require,
%string,
uint,
uint64
},
int8 - {
%exception,
int,
%pretty_printer,
require,
%string,
uint,
uint8
},
/*
integer - {
char,
exception,
float,
int,
int16,
int32,
int64,
int8,
list,
require,
string,
uint,
uint16,
uint32,
uint64,
uint8
},
*/
io - {
array,
%benchmarking,
bitmap,
bool,
char,
deconstruct,
%dir,
exception,
int,
int16,
int32,
int64,
int8,
io.call_system,
io.environment,
io.file,
io.primitives_read,
io.primitives_write,
io.stream_db,
io.stream_ops,
io.text_read,
list,
map,
maybe,
%mercury_term_parser,
require,
rtti_implementation,
stream,
%stream.string_writer,
string,
table_builtin,
term,
term_conversion,
term_subst,
time,
type_desc,
uint16,
uint32,
uint64,
uint8,
univ
},
io.call_system - {
string
},
io.environment - {
assoc_list,
list,
map,
maybe,
pair
},
io.file - {
io.environment,
time
},
io.primitives_read - {
char
},
io.primitives_write - {
char
},
io.stream_db - {
map,
maybe
},
io.stream_ops - {
% deletes some implicit deps from parent module
},
io.text_read - {
array,
bitmap,
char,
int,
int64,
io.primitives_read,
list
},
list - {
int,
%pretty_printer,
require
%set_tree234,
%string,
%term
},
map - {
assoc_list,
int,
list,
maybe,
pair,
require,
set,
%term,
tree234
},
maybe - {
%list
},
/*
mercury_term_lexer - {
char,
int,
integer,
io,
list,
require,
string
},
mercury_term_parser - {
bool,
char,
float,
integer,
io,
list,
map,
maybe,
mercury_term_lexer,
ops,
require,
string,
term,
term_context,
uint,
varset
},
ops - {
require,
uint
},
pretty_printer - {
array,
bool,
char,
deconstruct,
float,
int,
io,
list,
map,
ops,
require,
stream,
string,
term_io,
tree234,
type_desc,
uint,
univ,
version_array
},
*/
% It is useful to keep 'require' and 'exception' low in the order
% to improves termination/exception analysis for many modules.
require - {
exception
%list,
%string,
%type_desc
},
rtti_implementation - {
array,
bitmap,
bool,
char,
%deconstruct,
int,
int16,
int32,
list,
maybe,
require,
string,
%term_io,
type_desc,
univ
},
set - {
bool,
list,
require,
set_ordlist
%term
},
set_ordlist - {
bool,
cord,
list,
require
%term
},
set_tree234 - {
bool,
cord,
int,
list,
require,
set,
string
%term
},
/*
solutions - {
bool,
list,
mutvar,
require,
set
},
std_util - {
int
},
stm_builtin - {
exception,
io,
univ
},
store - {
deconstruct,
io,
require
},
stream - {
bool,
char,
list
},
*/
stream.string_writer - {
array,
bitmap,
%calendar,
char,
deconstruct,
int,
integer,
io,
io.stream_db,
list,
ops,
require,
rtti_implementation,
string,
%term_io,
type_desc,
univ,
version_array
},
string - {
%assoc_list,
bool,
char,
%deconstruct,
int,
list,
maybe,
%ops,
pair,
%pretty_printer,
require,
%string.format,
%string.to_string,
%term_io,
uint,
uint8
},
string.format - {
% deletes some implicit dep
bool,
exception,
float,
int,
int16,
int32,
int64,
int8,
integer,
list,
require,
string.parse_runtime,
string.parse_util,
uint,
uint16,
uint32,
uint64,
uint8
},
string.parse_runtime - {
% deletes some implicit dep
int,
list,
string.parse_util
},
string.parse_util - {
% deletes some implicit dep
int,
list
},
/*
string.to_string - {
array,
bitmap,
deconstruct,
int,
ops,
rtti_implementation,
term_io,
type_desc,
univ,
version_array
},
*/
table_builtin - {
%io,
require,
univ
},
/*
term - {
enum,
int,
integer,
list,
map,
term_context,
term_int,
term_subst,
term_unify,
term_vars,
uint
},
term_conversion - {
array,
bitmap,
construct,
deconstruct,
int,
integer,
list,
require,
string,
term,
term_context,
term_int,
term_subst,
type_desc,
univ,
version_array
},
*/
term_int - {
integer,
list
%term
},
/*
term_io - {
bool,
char,
int,
integer,
io,
list,
mercury_term_lexer,
ops,
stream,
stream.string_writer,
string,
term,
varset
},
*/
term_subst - {
list,
map,
require,
%term,
term_context
},
term_unify - {
list,
map,
%term,
term_context,
term_subst,
term_vars
},
term_vars - {
list
%term
},
time - {
bool,
exception,
int,
%io,
list,
maybe,
require,
string
},
tree234 - {
assoc_list,
bool,
int,
%io,
list,
maybe,
pair,
%pretty_printer,
require,
set,
string
%term
},
type_desc - {
list,
require,
%rtti_implementation,
string
},
uint - {
enum,
exception,
%pretty_printer,
require
%string
},
uint16 - {
exception,
int,
%pretty_printer,
require,
%string,
uint
},
uint32 - {
exception,
int,
%pretty_printer,
require,
%string,
uint
},
uint64 - {
exception,
int,
%pretty_printer,
require,
%string,
uint
},
uint8 - {
exception,
int,
%pretty_printer,
require,
%string,
uint
},
univ - {
%list,
%require, % either require or univ needs to lower than the other
%string,
%type_desc
},
/*
varset - {
assoc_list,
int,
list,
map,
maybe,
pair,
require,
set,
string,
term,
term_subst
},
*/
version_array - {
exception,
int,
list,
%pretty_printer,
string
}
}.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: results.txt.gz
Type: application/gzip
Size: 8960 bytes
Desc: not available
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20221219/61555ac0/attachment-0001.gz>
More information about the reviews
mailing list