[m-rev.] for review: granularity control

Zoltan Somogyi zs at csse.unimelb.edu.au
Thu Nov 2 20:35:12 AEDT 2006


For review by Peter Wang.

Zoltan.

Add an optional pass that tries to avoid generating too many parallel goals.
The first transformation implemented by this pass is to transform parallel
conjunctions into goals of the form

	( queues already contain lot of work ->
		sequential version of parallel conjunction
	;
		parallel conjunction as before
	)

if they contain recursive calls.

The effect of this transformation is to reduce the overhead of the new par_fib
test case from:

	fib(35): sequential 189 vs parallel 5770

to

	fib(35): sequential 189 vs parallel 1090

i.e. a speedup of more than a factor of five.

compiler/granularity.m:
	New module that implements this transformation. I intend to add other,
	more sophisticated transformations in the future.

compiler/transform_hlds.m:
	Add granularity.m as one of the submodules of transform_hlds.m.

compiler/mercury_compile.m:
	Invoke the new pass.

	Invoke dep_par_conj only if needed.

	Fix some stage numbers.

compiler/notes/compiler_design.html:
	Document the new module.

	Document some modules that should have been documented earlier.

	Fix a hurried deletion of a reference to the Aditi backend.

compiler/goal_util.m:
	Add some utility functions for use by the new module.

compiler/simplify.m:
	Record the information mercury_compile.m needs in order to check
	whether we have any parallelism for granularity.m and dep_par_conj.m
	to process.

compiler/hlds_module.m:
	Add a slot to the module_info to record the information from
	simplify.m. Clean up some interfaces.

compiler/add_type.m:
	Conform to the change to hlds_module.m.

compiler/dependency_graph.m:
	Delete unnecessary module qualifications, and rename some predicates
	to avoid potential ambiguities.

compiler/options.m:
	Add the options required for controlling the new transformation.

	Rename an option's internal name to avoid conflict with a language
	keyword (the user-visible name remains unchanged).

	Move some options around to put them in logical groups.

doc/user_guide.texi:
	Document the new options.

	Fix some omissions in some earlier options.

compiler/handle_options.m:
compiler/termination.m:
	Conform to the option rename.

compiler/quantification.m:
	Rename some predicates to avoid ambiguities.

library/private_builtin.m:
	Add a predicate for use by the new transformation.

tests/par_conj/par_fib.{m,exp}:
	A new test case: a version of fib for use in testing parallelism.

tests/par_conj/Mmakefile:
	Enable the new test case.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_type.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_type.m,v
retrieving revision 1.21
diff -u -b -r1.21 add_type.m
--- compiler/add_type.m	2 Oct 2006 05:21:08 -0000	1.21
+++ compiler/add_type.m	2 Nov 2006 05:56:55 -0000
@@ -219,7 +219,7 @@
         globals.lookup_bool_option(Globals, make_optimization_interface,
             MakeOptInt),
         ( Body = hlds_foreign_type(_) ->
-            module_info_contains_foreign_type(!ModuleInfo)
+            module_info_set_contains_foreign_type(!ModuleInfo)
         ;
             true
         ),
Index: compiler/dependency_graph.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dependency_graph.m,v
retrieving revision 1.90
diff -u -b -r1.90 dependency_graph.m
--- compiler/dependency_graph.m	20 Aug 2006 08:20:58 -0000	1.90
+++ compiler/dependency_graph.m	1 Nov 2006 22:39:18 -0000
@@ -54,13 +54,13 @@
 
     % Build the dependency graph of procedures.
     %
-:- pred dependency_graph.build_pred_dependency_graph(module_info::in,
-    include_imported::in, dependency_info(pred_id)::out) is det.
+:- pred build_pred_dependency_graph(module_info::in, include_imported::in,
+    dependency_info(pred_id)::out) is det.
 
     % Build the dependency graph of predicates.
     %
-:- pred dependency_graph.build_proc_dependency_graph(module_info::in,
-    include_imported::in, dependency_info(pred_proc_id)::out) is det.
+:- pred build_proc_dependency_graph(module_info::in, include_imported::in,
+    dependency_info(pred_proc_id)::out) is det.
 
     % Output a form of the static call graph to a file, in a format suitable
     % for use in .dependency_info files. After the heading, the format of
@@ -68,31 +68,31 @@
     %
     %   CallerModeDecl \t CalleeModeDecl
     %
-:- pred dependency_graph.write_dependency_graph(module_info::in,
-    module_info::out, io::di, io::uo) is det.
+:- pred write_dependency_graph(module_info::in, module_info::out,
+    io::di, io::uo) is det.
 
     % Output a form of the static call graph to a file for use by the profiler.
     % There is no heading, and the format of each line is
     %
     %   CallerLabel \t CalleeLabel
     %
-:- pred dependency_graph.write_prof_dependency_graph(module_info::in,
-    module_info::out, io::di, io::uo) is det.
+:- pred write_prof_dependency_graph(module_info::in, module_info::out,
+    io::di, io::uo) is det.
 
     % Given the list of predicates in a strongly connected component
     % of the dependency graph, a list of the higher SCCs in the module
     % and a module_info, find out which members of the SCC can be
     % called from outside the SCC.
     %
-:- pred dependency_graph.get_scc_entry_points(list(pred_proc_id)::in,
-    dependency_ordering::in, module_info::in, list(pred_proc_id)::out) is det.
+:- pred get_scc_entry_points(list(pred_proc_id)::in, dependency_ordering::in,
+    module_info::in, list(pred_proc_id)::out) is det.
 
-    % write_graph(Graph, WriteNode, WriteEdge)
+    % write_graph(Graph, WriteNode, WriteEdge):
     %
     % Write out the dependency graph using WriteNode to decide what to output
     % for a node in the dependency graph and WriteEdge for an edge.
     %
-:- pred dependency_graph.write_graph(dependency_info::in,
+:- pred write_graph(dependency_info::in,
     pred(pred_proc_id, io, io)::pred(in, di, uo) is det,
     pred(pred_proc_id, pred_proc_id, io, io)::pred(in, in, di, uo) is det,
     io::di, io::uo) is det.
@@ -102,8 +102,8 @@
     % Write out each of the Nodes in the Graph using WriteNode and
     % any edges originating in Nodes, using WriteEdge.
     %
-:- pred dependency_graph.write_graph_nodes(list(pred_proc_id)::in,
-    dependency_graph::in, pred(pred_proc_id, io, io)::pred(in, di, uo) is det,
+:- pred write_graph_nodes(list(pred_proc_id)::in, dependency_graph::in,
+    pred(pred_proc_id, io, io)::pred(in, di, uo) is det,
     pred(pred_proc_id, pred_proc_id, io, io)::pred(in, in, di, uo) is det,
     io::di, io::uo) is det.
 
@@ -149,59 +149,54 @@
         MaybeDepInfo = yes(_)
     ;
         MaybeDepInfo = no,
-        dependency_graph.build_dependency_graph(!.ModuleInfo,
-            do_not_include_imported, DepInfo),
+        build_dependency_graph(!.ModuleInfo, do_not_include_imported, DepInfo),
         module_info_set_dependency_info(DepInfo, !ModuleInfo)
     ).
 
 module_info_rebuild_dependency_info(!ModuleInfo, DepInfo) :-
-    dependency_graph.build_dependency_graph(!.ModuleInfo,
-        do_not_include_imported, DepInfo),
+    build_dependency_graph(!.ModuleInfo, do_not_include_imported, DepInfo),
     module_info_set_dependency_info(DepInfo, !ModuleInfo).
 
-dependency_graph.build_proc_dependency_graph(ModuleInfo, Imported, DepInfo) :-
-    dependency_graph.build_dependency_graph(ModuleInfo, Imported, DepInfo).
+build_proc_dependency_graph(ModuleInfo, Imported, DepInfo) :-
+    build_dependency_graph(ModuleInfo, Imported, DepInfo).
 
-dependency_graph.build_pred_dependency_graph(ModuleInfo, Imported, DepInfo) :-
-    dependency_graph.build_dependency_graph(ModuleInfo, Imported, DepInfo).
+build_pred_dependency_graph(ModuleInfo, Imported, DepInfo) :-
+    build_dependency_graph(ModuleInfo, Imported, DepInfo).
 
-    % Traverse the module structure, calling `dependency_graph.add_arcs'
+    % Traverse the module structure, calling `add_dependency_arcs'
     % for each procedure body.
     %
-:- pred dependency_graph.build_dependency_graph(module_info::in,
-    include_imported::in, dependency_info(T)::out) is det
-    <= dependency_node(T).
+:- pred build_dependency_graph(module_info::in, include_imported::in,
+    dependency_info(T)::out) is det <= dependency_node(T).
 
-dependency_graph.build_dependency_graph(ModuleInfo, Imported, !:DepInfo) :-
+build_dependency_graph(ModuleInfo, Imported, !:DepInfo) :-
     module_info_predids(ModuleInfo, PredIds),
     relation.init(DepGraph0),
-    dependency_graph.add_nodes(PredIds, ModuleInfo, Imported,
-        DepGraph0, DepGraph1),
-    dependency_graph.add_arcs(PredIds, ModuleInfo, Imported,
-        DepGraph1, DepGraph),
+    add_dependency_nodes(PredIds, ModuleInfo, Imported, DepGraph0, DepGraph1),
+    add_dependency_arcs(PredIds, ModuleInfo, Imported, DepGraph1, DepGraph),
     hlds_dependency_info_init(!:DepInfo),
     hlds_dependency_info_set_dependency_graph(DepGraph, !DepInfo),
     relation.atsort(DepGraph, DepOrd0),
-    dependency_graph.sets_to_lists(DepOrd0, [], DepOrd),
+    sets_to_lists(DepOrd0, [], DepOrd),
     hlds_dependency_info_set_dependency_ordering(DepOrd, !DepInfo).
 
-:- pred dependency_graph.sets_to_lists(list(set(T))::in, list(list(T))::in,
+:- pred sets_to_lists(list(set(T))::in, list(list(T))::in,
     list(list(T))::out) is det.
 
-dependency_graph.sets_to_lists([], Xs, Xs).
-dependency_graph.sets_to_lists([X | Xs], Ys, Zs) :-
+sets_to_lists([], Xs, Xs).
+sets_to_lists([X | Xs], Ys, Zs) :-
     set.to_sorted_list(X, Y),
-    dependency_graph.sets_to_lists(Xs, [Y | Ys], Zs).
+    sets_to_lists(Xs, [Y | Ys], Zs).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- typeclass dependency_node(T) where [
-    pred dependency_graph.add_nodes(list(pred_id)::in, module_info::in,
+    pred add_dependency_nodes(list(pred_id)::in, module_info::in,
         include_imported::in,
         dependency_graph(T)::in, dependency_graph(T)::out) is det,
 
-    pred dependency_graph.add_arcs(list(pred_id)::in, module_info::in,
+    pred add_dependency_arcs(list(pred_id)::in, module_info::in,
         include_imported::in,
         dependency_graph(T)::in, dependency_graph(T)::out) is det,
 
@@ -209,31 +204,25 @@
 ].
 
 :- instance dependency_node(pred_proc_id) where [
-    pred(dependency_graph.add_nodes/5) is
-        dependency_graph.add_pred_proc_nodes,
-    pred(dependency_graph.add_arcs/5) is
-        dependency_graph.add_pred_proc_arcs,
+    pred(add_dependency_nodes/5) is add_pred_proc_nodes,
+    pred(add_dependency_arcs/5) is add_pred_proc_arcs,
     func(dependency_node/1) is id
 ].
 
 :- instance dependency_node(pred_id) where [
-    pred(dependency_graph.add_nodes/5) is
-        dependency_graph.add_pred_nodes,
-    pred(dependency_graph.add_arcs/5) is
-        dependency_graph.add_pred_arcs,
+    pred(add_dependency_nodes/5) is add_pred_nodes,
+    pred(add_dependency_arcs/5) is add_pred_arcs,
     func(dependency_node/1) is pred_proc_id_get_pred_id
 ].
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_pred_proc_nodes(list(pred_id)::in,
-    module_info::in, include_imported::in,
-    dependency_graph::in, dependency_graph::out) is det.
+:- pred add_pred_proc_nodes(list(pred_id)::in, module_info::in,
+    include_imported::in, dependency_graph::in, dependency_graph::out) is det.
 
-dependency_graph.add_pred_proc_nodes([], _ModuleInfo, _, !DepGraph).
-dependency_graph.add_pred_proc_nodes([PredId | PredIds], ModuleInfo, Imported,
-        !DepGraph) :-
+add_pred_proc_nodes([], _ModuleInfo, _, !DepGraph).
+add_pred_proc_nodes([PredId | PredIds], ModuleInfo, Imported, !DepGraph) :-
     module_info_preds(ModuleInfo, PredTable),
     map.lookup(PredTable, PredId, PredInfo),
     (
@@ -245,28 +234,25 @@
         Imported = include_imported,
         ProcIds = pred_info_procids(PredInfo)
     ),
-    dependency_graph.add_proc_nodes(ProcIds, PredId, ModuleInfo, !DepGraph),
-    dependency_graph.add_pred_proc_nodes(PredIds, ModuleInfo, Imported,
-        !DepGraph).
+    add_proc_nodes(ProcIds, PredId, ModuleInfo, !DepGraph),
+    add_pred_proc_nodes(PredIds, ModuleInfo, Imported, !DepGraph).
 
-:- pred dependency_graph.add_proc_nodes(list(proc_id)::in, pred_id::in,
+:- pred add_proc_nodes(list(proc_id)::in, pred_id::in,
     module_info::in, dependency_graph::in, dependency_graph::out) is det.
 
-dependency_graph.add_proc_nodes([], _PredId, _ModuleInfo, !DepGraph).
-dependency_graph.add_proc_nodes([ProcId | ProcIds], PredId, ModuleInfo,
-        !DepGraph) :-
+add_proc_nodes([], _PredId, _ModuleInfo, !DepGraph).
+add_proc_nodes([ProcId | ProcIds], PredId, ModuleInfo, !DepGraph) :-
     relation.add_element(!.DepGraph, proc(PredId, ProcId), _, !:DepGraph),
-    dependency_graph.add_proc_nodes(ProcIds, PredId, ModuleInfo, !DepGraph).
+    add_proc_nodes(ProcIds, PredId, ModuleInfo, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_pred_nodes(list(pred_id)::in, module_info::in,
+:- pred add_pred_nodes(list(pred_id)::in, module_info::in,
     include_imported::in,
     dependency_graph(pred_id)::in, dependency_graph(pred_id)::out) is det.
 
-dependency_graph.add_pred_nodes([], _ModuleInfo, _, DepGraph, DepGraph).
-dependency_graph.add_pred_nodes([PredId | PredIds], ModuleInfo,
-        IncludeImported, !DepGraph) :-
+add_pred_nodes([], _ModuleInfo, _, DepGraph, DepGraph).
+add_pred_nodes([PredId | PredIds], ModuleInfo, IncludeImported, !DepGraph) :-
     module_info_preds(ModuleInfo, PredTable),
     map.lookup(PredTable, PredId, PredInfo),
     % Don't bother adding nodes (or arcs) for predicates
@@ -279,19 +265,16 @@
     ;
         relation.add_element(!.DepGraph, PredId, _, !:DepGraph)
     ),
-    dependency_graph.add_pred_nodes(PredIds, ModuleInfo, IncludeImported,
-        !DepGraph).
+    add_pred_nodes(PredIds, ModuleInfo, IncludeImported, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_pred_proc_arcs(list(pred_id)::in,
-    module_info::in, include_imported::in,
-    dependency_graph::in, dependency_graph::out) is det.
+:- pred add_pred_proc_arcs(list(pred_id)::in, module_info::in,
+    include_imported::in, dependency_graph::in, dependency_graph::out) is det.
 
-dependency_graph.add_pred_proc_arcs([], _ModuleInfo, _, !DepGraph).
-dependency_graph.add_pred_proc_arcs([PredId | PredIds], ModuleInfo, Imported,
-        !DepGraph) :-
+add_pred_proc_arcs([], _ModuleInfo, _, !DepGraph).
+add_pred_proc_arcs([PredId | PredIds], ModuleInfo, Imported, !DepGraph) :-
     module_info_preds(ModuleInfo, PredTable),
     map.lookup(PredTable, PredId, PredInfo),
     (
@@ -303,18 +286,15 @@
         Imported = include_imported,
         ProcIds = pred_info_procids(PredInfo)
     ),
-    dependency_graph.add_proc_arcs(ProcIds, PredId, ModuleInfo, Imported,
-        !DepGraph),
-    dependency_graph.add_pred_proc_arcs(PredIds, ModuleInfo, Imported,
-        !DepGraph).
+    add_proc_arcs(ProcIds, PredId, ModuleInfo, Imported, !DepGraph),
+    add_pred_proc_arcs(PredIds, ModuleInfo, Imported, !DepGraph).
+
+:- pred add_proc_arcs(list(proc_id)::in, pred_id::in, module_info::in,
+    include_imported::in, dependency_graph::in, dependency_graph::out) is det.
 
-:- pred dependency_graph.add_proc_arcs(list(proc_id)::in, pred_id::in,
-    module_info::in, include_imported::in,
-    dependency_graph::in, dependency_graph::out) is det.
-
-dependency_graph.add_proc_arcs([], _PredId, _ModuleInfo, _, !DepGraph).
-dependency_graph.add_proc_arcs([ProcId | ProcIds], PredId, ModuleInfo,
-        IncludeImported, !DepGraph) :-
+add_proc_arcs([], _PredId, _ModuleInfo, _, !DepGraph).
+add_proc_arcs([ProcId | ProcIds], PredId, ModuleInfo, IncludeImported,
+        !DepGraph) :-
     module_info_preds(ModuleInfo, PredTable0),
     map.lookup(PredTable0, PredId, PredInfo0),
     pred_info_get_procedures(PredInfo0, ProcTable0),
@@ -324,7 +304,7 @@
         proc_info_get_goal(ProcInfo0, Goal),
 
         relation.lookup_element(!.DepGraph, proc(PredId, ProcId), Caller),
-        dependency_graph.add_arcs_in_goal(Goal, Caller, !DepGraph)
+        add_dependency_arcs_in_goal(Goal, Caller, !DepGraph)
     ;
         IncludeImported = include_imported,
         pred_info_get_import_status(PredInfo0, ImportStatus),
@@ -335,21 +315,18 @@
             Imported = no,
             proc_info_get_goal(ProcInfo0, Goal),
             relation.lookup_element(!.DepGraph, proc(PredId, ProcId), Caller),
-            dependency_graph.add_arcs_in_goal(Goal, Caller, !DepGraph)
+            add_dependency_arcs_in_goal(Goal, Caller, !DepGraph)
         )
     ),
-    dependency_graph.add_proc_arcs(ProcIds, PredId, ModuleInfo,
-        IncludeImported, !DepGraph).
+    add_proc_arcs(ProcIds, PredId, ModuleInfo, IncludeImported, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_pred_arcs(list(pred_id)::in, module_info::in,
-    include_imported::in,
+:- pred add_pred_arcs(list(pred_id)::in, module_info::in, include_imported::in,
     dependency_graph(pred_id)::in, dependency_graph(pred_id)::out) is det.
 
-dependency_graph.add_pred_arcs([], _ModuleInfo, _, !DepGraph).
-dependency_graph.add_pred_arcs([PredId | PredIds], ModuleInfo,
-        IncludeImported, !DepGraph) :-
+add_pred_arcs([], _ModuleInfo, _, !DepGraph).
+add_pred_arcs([PredId | PredIds], ModuleInfo, IncludeImported, !DepGraph) :-
     module_info_preds(ModuleInfo, PredTable),
     map.lookup(PredTable, PredId, PredInfo),
     (
@@ -363,10 +340,9 @@
         get_clause_list_any_order(ClausesRep, Clauses),
         Goals = list.map(func(clause(_, Goal, _, _)) = Goal, Clauses),
         relation.lookup_element(!.DepGraph, PredId, Caller),
-        dependency_graph.add_arcs_in_list(Goals, Caller, !DepGraph)
+        add_dependency_arcs_in_list(Goals, Caller, !DepGraph)
     ),
-    dependency_graph.add_pred_arcs(PredIds, ModuleInfo, IncludeImported,
-        !DepGraph).
+    add_pred_arcs(PredIds, ModuleInfo, IncludeImported, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -378,45 +354,33 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_arcs_in_goal(hlds_goal::in, relation_key::in,
+:- pred add_dependency_arcs_in_goal(hlds_goal::in, relation_key::in,
     dependency_graph(T)::in, dependency_graph(T)::out) is det
     <= dependency_node(T).
 
-dependency_graph.add_arcs_in_goal(Goal - _GoalInfo, PPId, !DepGraph) :-
-    dependency_graph.add_arcs_in_goal_2(Goal, PPId, !DepGraph).
-
-%-----------------------------------------------------------------------------%
-
-:- pred dependency_graph.add_arcs_in_goal_2(hlds_goal_expr::in,
-    relation_key::in, dependency_graph(T)::in, dependency_graph(T)::out) is det
-    <= dependency_node(T).
-
-dependency_graph.add_arcs_in_goal_2(conj(_, Goals), Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_list(Goals, Caller, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(disj(Goals), Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_list(Goals, Caller, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(switch(_Var, _Det, Cases), Caller,
-        !DepGraph) :-
-    dependency_graph.add_arcs_in_cases(Cases, Caller, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(if_then_else(_Vars, Cond, Then, Else),
-        Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_goal(Cond, Caller, !DepGraph),
-    dependency_graph.add_arcs_in_goal(Then, Caller, !DepGraph),
-    dependency_graph.add_arcs_in_goal(Else, Caller, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(negation(Goal), Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_goal(Goal, Caller, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(scope(_, Goal), Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_goal(Goal, Caller, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(generic_call(_, _, _, _), _, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(plain_call(PredId, ProcId, _, Builtin,
-        _, _), Caller, !DepGraph) :-
+add_dependency_arcs_in_goal(GoalExpr - _GoalInfo, Caller, !DepGraph) :-
+    (
+        ( GoalExpr = conj(_, Goals)
+        ; GoalExpr = disj(Goals)
+        ),
+        add_dependency_arcs_in_list(Goals, Caller, !DepGraph)
+    ;
+        GoalExpr = switch(_Var, _Det, Cases),
+        add_dependency_arcs_in_cases(Cases, Caller, !DepGraph)
+    ;
+        GoalExpr = if_then_else(_Vars, Cond, Then, Else),
+        add_dependency_arcs_in_goal(Cond, Caller, !DepGraph),
+        add_dependency_arcs_in_goal(Then, Caller, !DepGraph),
+        add_dependency_arcs_in_goal(Else, Caller, !DepGraph)
+    ;
+        ( GoalExpr = negation(Goal)
+        ; GoalExpr = scope(_, Goal)
+        ),
+        add_dependency_arcs_in_goal(Goal, Caller, !DepGraph)
+    ;
+        GoalExpr = generic_call(_, _, _, _)
+    ;
+        GoalExpr = plain_call(PredId, ProcId, _, Builtin, _, _),
     ( Builtin = inline_builtin ->
         true
     ;
@@ -430,76 +394,64 @@
         ;
             true
         )
-    ).
-
-dependency_graph.add_arcs_in_goal_2(unify(_,_,_,Unify,_), Caller,
-        !DepGraph) :-
+        )
+    ;
+        GoalExpr = unify(_,_,_,Unify,_),
     (
         Unify = assign(_, _)
     ;
         Unify = simple_test(_, _)
     ;
         Unify = construct(_, Cons, _, _, _, _, _),
-        dependency_graph.add_arcs_in_cons(Cons, Caller, !DepGraph)
+            add_dependency_arcs_in_cons(Cons, Caller, !DepGraph)
     ;
         Unify = deconstruct(_, Cons, _, _, _, _),
-        dependency_graph.add_arcs_in_cons(Cons, Caller, !DepGraph)
+            add_dependency_arcs_in_cons(Cons, Caller, !DepGraph)
     ;
         Unify = complicated_unify(_, _, _)
+        )
+    ;
+        GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
+    ;
+        GoalExpr = shorthand(ShorthandGoal),
+        ShorthandGoal = bi_implication(LHS, RHS),
+        add_dependency_arcs_in_list([LHS, RHS], Caller, !DepGraph)
     ).
 
-% There can be no dependencies within a foreign_proc
-dependency_graph.add_arcs_in_goal_2(
-    call_foreign_proc(_, _, _, _, _, _, _), _, !DepGraph).
-
-dependency_graph.add_arcs_in_goal_2(shorthand(ShorthandGoal), Caller,
-        !DepGraph) :-
-    dependency_graph.add_arcs_in_goal_2_shorthand(ShorthandGoal, Caller,
-        !DepGraph).
-
-:- pred dependency_graph.add_arcs_in_goal_2_shorthand(shorthand_goal_expr::in,
-    relation_key::in, dependency_graph(T)::in, dependency_graph(T)::out)
-    is det <= dependency_node(T).
-
-dependency_graph.add_arcs_in_goal_2_shorthand(bi_implication(LHS, RHS),
-        Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_list([LHS, RHS], Caller, !DepGraph).
-
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_arcs_in_list(list(hlds_goal)::in,
+:- pred add_dependency_arcs_in_list(list(hlds_goal)::in,
     relation_key::in, dependency_graph(T)::in, dependency_graph(T)::out) is det
     <= dependency_node(T).
 
-dependency_graph.add_arcs_in_list([], _Caller, !DepGraph).
-dependency_graph.add_arcs_in_list([Goal|Goals], Caller, !DepGraph) :-
-    dependency_graph.add_arcs_in_goal(Goal, Caller, !DepGraph),
-    dependency_graph.add_arcs_in_list(Goals, Caller, !DepGraph).
+add_dependency_arcs_in_list([], _Caller, !DepGraph).
+add_dependency_arcs_in_list([Goal|Goals], Caller, !DepGraph) :-
+    add_dependency_arcs_in_goal(Goal, Caller, !DepGraph),
+    add_dependency_arcs_in_list(Goals, Caller, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_arcs_in_cases(list(case)::in, relation_key::in,
+:- pred add_dependency_arcs_in_cases(list(case)::in, relation_key::in,
     dependency_graph(T)::in, dependency_graph(T)::out) is det
     <= dependency_node(T).
 
-dependency_graph.add_arcs_in_cases([], _Caller, !DepGraph).
-dependency_graph.add_arcs_in_cases([case(Cons, Goal) | Goals], Caller,
-        !DepGraph) :-
-    dependency_graph.add_arcs_in_cons(Cons, Caller, !DepGraph),
-    dependency_graph.add_arcs_in_goal(Goal, Caller, !DepGraph),
-    dependency_graph.add_arcs_in_cases(Goals, Caller, !DepGraph).
+add_dependency_arcs_in_cases([], _Caller, !DepGraph).
+add_dependency_arcs_in_cases([case(Cons, Goal) | Goals], Caller, !DepGraph) :-
+    add_dependency_arcs_in_cons(Cons, Caller, !DepGraph),
+    add_dependency_arcs_in_goal(Goal, Caller, !DepGraph),
+    add_dependency_arcs_in_cases(Goals, Caller, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 
-:- pred dependency_graph.add_arcs_in_cons(cons_id::in, relation_key::in,
+:- pred add_dependency_arcs_in_cons(cons_id::in, relation_key::in,
     dependency_graph(T)::in, dependency_graph(T)::out) is det
     <= dependency_node(T).
 
-dependency_graph.add_arcs_in_cons(cons(_, _), _Caller, !DepGraph).
-dependency_graph.add_arcs_in_cons(int_const(_), _Caller, !DepGraph).
-dependency_graph.add_arcs_in_cons(string_const(_), _Caller, !DepGraph).
-dependency_graph.add_arcs_in_cons(float_const(_), _Caller, !DepGraph).
-dependency_graph.add_arcs_in_cons(pred_const(ShroudedPredProcId, _), Caller,
+add_dependency_arcs_in_cons(cons(_, _), _Caller, !DepGraph).
+add_dependency_arcs_in_cons(int_const(_), _Caller, !DepGraph).
+add_dependency_arcs_in_cons(string_const(_), _Caller, !DepGraph).
+add_dependency_arcs_in_cons(float_const(_), _Caller, !DepGraph).
+add_dependency_arcs_in_cons(pred_const(ShroudedPredProcId, _), Caller,
         !DepGraph) :-
     PredProcId = unshroud_pred_proc_id(ShroudedPredProcId),
     (
@@ -512,15 +464,15 @@
     ;
         true
     ).
-dependency_graph.add_arcs_in_cons(type_ctor_info_const(_, _, _), _, !DepGraph).
-dependency_graph.add_arcs_in_cons(base_typeclass_info_const(_, _, _, _), _,
+add_dependency_arcs_in_cons(type_ctor_info_const(_, _, _), _, !DepGraph).
+add_dependency_arcs_in_cons(base_typeclass_info_const(_, _, _, _), _,
     !DepGraph).
-dependency_graph.add_arcs_in_cons(type_info_cell_constructor(_), _, !DepGraph).
-dependency_graph.add_arcs_in_cons(typeclass_info_cell_constructor, _,
+add_dependency_arcs_in_cons(type_info_cell_constructor(_), _, !DepGraph).
+add_dependency_arcs_in_cons(typeclass_info_cell_constructor, _,
     !DepGraph).
-dependency_graph.add_arcs_in_cons(tabling_info_const(_), _Caller, !DepGraph).
-dependency_graph.add_arcs_in_cons(deep_profiling_proc_layout(_), _, !DepGraph).
-dependency_graph.add_arcs_in_cons(table_io_decl(_), _Caller, !DepGraph).
+add_dependency_arcs_in_cons(tabling_info_const(_), _Caller, !DepGraph).
+add_dependency_arcs_in_cons(deep_profiling_proc_layout(_), _, !DepGraph).
+add_dependency_arcs_in_cons(table_io_decl(_), _Caller, !DepGraph).
 
 %-----------------------------------------------------------------------------%
 
@@ -581,9 +533,9 @@
 write_prof_dep_graph_link(ModuleInfo, Parent, Child, !IO) :-
     Parent = proc(PPredId, PProcId),    % Caller
     Child = proc(CPredId, CProcId),     % Callee
-    dependency_graph.output_label(ModuleInfo, PPredId, PProcId, !IO),
+    output_label_dependency(ModuleInfo, PPredId, PProcId, !IO),
     io.write_string("\t", !IO),
-    dependency_graph.output_label(ModuleInfo, CPredId, CProcId, !IO),
+    output_label_dependency(ModuleInfo, CPredId, CProcId, !IO),
     io.write_string("\n", !IO).
 
 :- pred write_dep_graph_link(module_info::in,
@@ -644,10 +596,10 @@
 
     % Print out the label corresponding to the given pred_id and proc_id.
     %
-:- pred output_label(module_info::in, pred_id::in, proc_id::in, io::di, io::uo)
-    is det.
+:- pred output_label_dependency(module_info::in, pred_id::in, proc_id::in,
+    io::di, io::uo) is det.
 
-output_label(ModuleInfo, PredId, ProcId, !IO) :-
+output_label_dependency(ModuleInfo, PredId, ProcId, !IO) :-
     ProcLabel = make_proc_label(ModuleInfo, PredId, ProcId),
     output_proc_label(ProcLabel, !IO).
 
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.140
diff -u -b -r1.140 goal_util.m
--- compiler/goal_util.m	1 Nov 2006 02:31:05 -0000	1.140
+++ compiler/goal_util.m	2 Nov 2006 08:43:33 -0000
@@ -190,6 +190,22 @@
 :- mode goal_calls_pred_id(in, in) is semidet.
 :- mode goal_calls_pred_id(in, out) is nondet.
 
+    % goal_calls_proc_in_list(Goal, PredProcIds):
+    %
+    % Returns the subset of PredProcIds that are called from somewhere inside
+    % Goal via plain_call.
+    %
+:- func goal_calls_proc_in_list(hlds_goal, list(pred_proc_id))
+    = list(pred_proc_id).
+
+    % goal_list_calls_proc_in_list(Goal, PredProcIds):
+    %
+    % Returns the subset of PredProcIds that are called from somewhere inside
+    % Goals via plain_call.
+    %
+:- func goal_list_calls_proc_in_list(list(hlds_goal), list(pred_proc_id))
+    = list(pred_proc_id).
+
     % Test whether the goal contains a reconstruction
     % (a construction where the `cell_to_reuse' field is `yes(_)').
     %
@@ -1298,6 +1314,76 @@
 
 %-----------------------------------------------------------------------------%
 
+goal_calls_proc_in_list(Goal, PredProcIds) = CalledPredProcIds :-
+    goal_calls_proc_in_list_2(Goal, PredProcIds, set.init, CalledSet),
+    set.to_sorted_list(CalledSet, CalledPredProcIds).
+
+goal_list_calls_proc_in_list(Goals, PredProcIds) = CalledPredProcIds :-
+    goal_list_calls_proc_in_list_2(Goals, PredProcIds, set.init, CalledSet),
+    set.to_sorted_list(CalledSet, CalledPredProcIds).
+
+:- pred goal_calls_proc_in_list_2(hlds_goal::in, list(pred_proc_id)::in,
+    set(pred_proc_id)::in, set(pred_proc_id)::out) is det.
+
+goal_calls_proc_in_list_2(GoalExpr - _GoalInfo, PredProcIds, !CalledSet) :-
+    (
+        GoalExpr = unify(_, _, _, _, _)
+    ;
+        GoalExpr = plain_call(PredId, ProcId, _, _, _, _),
+        ( list.member(proc(PredId, ProcId), PredProcIds) ->
+            svset.insert(proc(PredId, ProcId), !CalledSet)
+        ;
+            true
+        )
+    ;
+        GoalExpr = generic_call(_, _, _, _)
+    ;
+        GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
+    ;
+        GoalExpr = conj(_, Goals),
+        goal_list_calls_proc_in_list_2(Goals, PredProcIds, !CalledSet)
+    ;
+        GoalExpr = disj(Goals),
+        goal_list_calls_proc_in_list_2(Goals, PredProcIds, !CalledSet)
+    ;
+        GoalExpr = switch(_, _, Cases),
+        case_list_calls_proc_in_list(Cases, PredProcIds, !CalledSet)
+    ;
+        GoalExpr = if_then_else(_, Cond, Then, Else),
+        goal_calls_proc_in_list_2(Cond, PredProcIds, !CalledSet),
+        goal_calls_proc_in_list_2(Then, PredProcIds, !CalledSet),
+        goal_calls_proc_in_list_2(Else, PredProcIds, !CalledSet)
+    ;
+        GoalExpr = negation(Goal),
+        goal_calls_proc_in_list_2(Goal, PredProcIds, !CalledSet)
+    ;
+        GoalExpr = scope(_, Goal),
+        goal_calls_proc_in_list_2(Goal, PredProcIds, !CalledSet)
+    ;
+        GoalExpr = shorthand(_),
+        unexpected(this_file, "goal__calls_proc_in_list_2: shorthand")
+    ).
+
+:- pred goal_list_calls_proc_in_list_2(list(hlds_goal)::in,
+    list(pred_proc_id)::in, set(pred_proc_id)::in, set(pred_proc_id)::out)
+    is det.
+
+goal_list_calls_proc_in_list_2([], _, !CalledSet).
+goal_list_calls_proc_in_list_2([Goal | Goals], PredProcIds, !CalledSet) :-
+    goal_calls_proc_in_list_2(Goal, PredProcIds, !CalledSet),
+    goal_list_calls_proc_in_list_2(Goals, PredProcIds, !CalledSet).
+
+:- pred case_list_calls_proc_in_list(list(case)::in, list(pred_proc_id)::in,
+    set(pred_proc_id)::in, set(pred_proc_id)::out) is det.
+
+case_list_calls_proc_in_list([], _, !CalledSet).
+case_list_calls_proc_in_list([Case | Cases], PredProcIds, !CalledSet) :-
+    Case = case(_, Goal),
+    goal_calls_proc_in_list_2(Goal, PredProcIds, !CalledSet),
+    case_list_calls_proc_in_list(Cases, PredProcIds, !CalledSet).
+
+%-----------------------------------------------------------------------------%
+
 goal_contains_reconstruction(_Goal - _) :-
     % This will only succeed on the alias branch with structure reuse.
     semidet_fail.
Index: compiler/granularity.m
===================================================================
RCS file: compiler/granularity.m
diff -N compiler/granularity.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/granularity.m	2 Nov 2006 08:49:15 -0000
@@ -0,0 +1,238 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2006 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+% 
+% File: granularity.m.
+% Author: zs.
+% 
+%-----------------------------------------------------------------------------%
+
+:- module transform_hlds.granularity.
+:- interface.
+
+:- import_module hlds.hlds_module.
+
+%-----------------------------------------------------------------------------%
+
+:- pred control_granularity(module_info::in, module_info::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds.goal_util.
+:- import_module hlds.hlds_pred.
+:- import_module hlds.hlds_goal.
+:- import_module hlds.instmap.
+:- import_module hlds.pred_table.
+:- import_module hlds.quantification.
+:- import_module libs.compiler_util.
+:- import_module libs.globals.
+:- import_module libs.options.
+:- import_module transform_hlds.dependency_graph.
+:- import_module mdbcomp.
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.prog_data.
+
+:- import_module bool.
+:- import_module list.
+:- import_module map.
+:- import_module maybe.
+:- import_module pair.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+control_granularity(!ModuleInfo) :-
+    module_info_rebuild_dependency_info(!ModuleInfo, DepInfo),
+    hlds_dependency_info_get_dependency_ordering(DepInfo, SCCs),
+    list.foldl(runtime_granularity_test_in_scc, SCCs, !ModuleInfo).
+
+:- pred runtime_granularity_test_in_scc(list(pred_proc_id)::in,
+    module_info::in, module_info::out) is det.
+
+runtime_granularity_test_in_scc(SCC, !ModuleInfo) :-
+    list.foldl(runtime_granularity_test_in_proc(SCC), SCC, !ModuleInfo).
+
+:- pred runtime_granularity_test_in_proc(list(pred_proc_id)::in,
+    pred_proc_id::in, module_info::in, module_info::out) is det.
+
+runtime_granularity_test_in_proc(SCC, proc(PredId, ProcId), !ModuleInfo) :-
+    module_info_preds(!.ModuleInfo, PredTable0),
+    map.lookup(PredTable0, PredId, PredInfo0),
+    pred_info_get_markers(PredInfo0, Markers),
+    ( check_marker(Markers, marker_may_have_parallel_conj) ->
+        pred_info_get_procedures(PredInfo0, ProcTable0),
+        map.lookup(ProcTable0, ProcId, ProcInfo0),
+        proc_info_get_goal(ProcInfo0, Goal0),
+        runtime_granularity_test_in_goal(Goal0, Goal, no, Changed,
+            SCC, !.ModuleInfo),
+        (
+            Changed = no
+        ;
+            Changed = yes,
+            proc_info_set_goal(Goal, ProcInfo0, ProcInfo1),
+            requantify_proc(ProcInfo1, ProcInfo),
+            map.det_update(ProcTable0, ProcId, ProcInfo, ProcTable),
+            pred_info_set_procedures(ProcTable, PredInfo0, PredInfo),
+            map.det_update(PredTable0, PredId, PredInfo, PredTable),
+            module_info_set_preds(PredTable, !ModuleInfo)
+        )
+    ;
+        % There is no parallelism in this procedure, so there is no granularity
+        % to control.
+        true
+    ).
+
+:- pred runtime_granularity_test_in_goal(hlds_goal::in, hlds_goal::out,
+    bool::in, bool::out, list(pred_proc_id)::in, module_info::in) is det.
+
+runtime_granularity_test_in_goal(GoalExpr0 - GoalInfo, GoalExpr - GoalInfo,
+        !Changed, SCC, ModuleInfo) :-
+    (
+        GoalExpr0 = conj(parallel_conj, Goals0),
+        runtime_granularity_test_in_goals(Goals0, Goals, !Changed, SCC,
+            ModuleInfo),
+        module_info_get_globals(ModuleInfo, Globals),
+        globals.get_target(Globals, Target),
+        (
+            Target = target_c,
+            ModuleName = mercury_std_lib_module_name("private_builtin"),
+            CalledSCCPredProcIds = goal_list_calls_proc_in_list(Goals, SCC),
+            (
+                CalledSCCPredProcIds = [],
+                GoalExpr = conj(parallel_conj, Goals)
+            ;
+                CalledSCCPredProcIds = [_ | _],
+                ProcName = "evaluate_parallelism_condition",
+                globals.lookup_int_option(Globals, parallelism_target,
+                    NumCPUs),
+                NumCPUsStr = string.int_to_string(NumCPUs),
+                Code = "SUCCESS_INDICATOR = " ++
+                    "MR_num_outstanding_contexts_and_sparks > " ++
+                    NumCPUsStr ++ ";",
+                Args = [],
+                ExtraArgs = [],
+                MaybeRuntimeCond = no,
+                Features = [],
+                InstMapDeltaSrc = [],
+                goal_info_get_context(GoalInfo, Context),
+                some [!Attributes] (
+                    !:Attributes = default_attributes(lang_c),
+                    set_purity(purity_semipure, !Attributes),
+                    set_may_call_mercury(proc_will_not_call_mercury,
+                        !Attributes),
+                    set_terminates(proc_terminates, !Attributes),
+                    set_may_throw_exception(proc_will_not_throw_exception,
+                        !Attributes),
+                    set_may_call_mm_tabled(will_not_call_mm_tabled,
+                        !Attributes),
+                    set_may_modify_trail(proc_will_not_modify_trail,
+                        !Attributes),
+                    Attributes = !.Attributes
+                ),
+                generate_foreign_proc(ModuleName, ProcName, predicate,
+                    only_mode, detism_semi, purity_semipure, Attributes,
+                    Args, ExtraArgs, MaybeRuntimeCond, Code, Features,
+                    InstMapDeltaSrc, ModuleInfo, Context, Cond),
+
+                Then = conj(parallel_conj, Goals) - GoalInfo,
+                Else = conj(plain_conj, Goals) - GoalInfo,
+                IfThenElse = if_then_else([], Cond, Then, Else) - GoalInfo,
+                Reason = promise_purity(dont_make_implicit_promises,
+                    purity_pure),
+                GoalExpr = scope(Reason, IfThenElse),
+                !:Changed = yes
+            )
+        ;
+            ( Target = target_il
+            ; Target = target_java
+            ; Target = target_asm
+            ),
+            % This should have caught by mercury_compile.m.
+            unexpected(this_file, "runtime_granularity_test_in_goal: " ++
+                "unsupported target language")
+        )
+    ;
+        GoalExpr0 = conj(plain_conj, Goals0),
+        runtime_granularity_test_in_goals(Goals0, Goals, !Changed, SCC,
+            ModuleInfo),
+        GoalExpr = conj(plain_conj, Goals)
+    ;
+        GoalExpr0 = disj(Goals0),
+        runtime_granularity_test_in_goals(Goals0, Goals, !Changed, SCC,
+            ModuleInfo),
+        GoalExpr = disj(Goals)
+    ;
+        GoalExpr0 = switch(Var, CanFail, Cases0),
+        runtime_granularity_test_in_cases(Cases0, Cases, !Changed, SCC,
+            ModuleInfo),
+        GoalExpr = switch(Var, CanFail, Cases)
+    ;
+        GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
+        runtime_granularity_test_in_goal(Cond0, Cond, !Changed, SCC,
+            ModuleInfo),
+        runtime_granularity_test_in_goal(Then0, Then, !Changed, SCC,
+            ModuleInfo),
+        runtime_granularity_test_in_goal(Else0, Else, !Changed, SCC,
+            ModuleInfo),
+        GoalExpr = if_then_else(Vars, Cond, Then, Else)
+    ;
+        GoalExpr0 = negation(Goal0),
+        runtime_granularity_test_in_goal(Goal0, Goal, !Changed, SCC,
+            ModuleInfo),
+        GoalExpr = negation(Goal)
+    ;
+        GoalExpr0 = scope(Reason, Goal0),
+        runtime_granularity_test_in_goal(Goal0, Goal, !Changed, SCC,
+            ModuleInfo),
+        GoalExpr = scope(Reason, Goal)
+    ;
+        ( GoalExpr0 = plain_call(_, _, _, _, _, _)
+        ; GoalExpr0 = generic_call(_, _, _, _)
+        ; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
+        ; GoalExpr0 = unify(_, _, _, _, _)
+        ),
+        GoalExpr = GoalExpr0
+    ;
+        GoalExpr0 = shorthand(_),
+        unexpected(this_file, "runtime_granularity_test_in_goal: shorthand")
+    ).
+
+:- pred runtime_granularity_test_in_goals(
+    list(hlds_goal)::in, list(hlds_goal)::out, bool::in, bool::out,
+    list(pred_proc_id)::in, module_info::in) is det.
+
+runtime_granularity_test_in_goals([], [], !Changed, _, _).
+runtime_granularity_test_in_goals([Goal0 | Goals0], [Goal | Goals], !Changed,
+        SCC, ModuleInfo) :-
+    runtime_granularity_test_in_goal(Goal0, Goal, !Changed, SCC, ModuleInfo),
+    runtime_granularity_test_in_goals(Goals0, Goals, !Changed, SCC,
+        ModuleInfo).
+
+:- pred runtime_granularity_test_in_cases( list(case)::in, list(case)::out,
+    bool::in, bool::out, list(pred_proc_id)::in, module_info::in) is det.
+
+runtime_granularity_test_in_cases([], [], !Changed, _, _).
+runtime_granularity_test_in_cases([Case0 | Cases0], [Case | Cases], !Changed,
+        SCC, ModuleInfo) :-
+    Case0 = case(ConsId, Goal0),
+    runtime_granularity_test_in_goal(Goal0, Goal, !Changed, SCC, ModuleInfo),
+    Case = case(ConsId, Goal),
+    runtime_granularity_test_in_cases(Cases0, Cases, !Changed, SCC,
+        ModuleInfo).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "granularity.m".
+
+%-----------------------------------------------------------------------------%
+:- end_module transform_hlds.granularity.
+%-----------------------------------------------------------------------------%
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.277
diff -u -b -r1.277 handle_options.m
--- compiler/handle_options.m	1 Nov 2006 02:31:06 -0000	1.277
+++ compiler/handle_options.m	2 Nov 2006 04:18:16 -0000
@@ -738,10 +738,10 @@
 
         option_implies(structure_reuse_analysis, structure_sharing_analysis,
             bool(yes), !Globals),
-        option_implies(verbose_check_termination, check_termination,bool(yes),
+        option_implies(verbose_check_termination, termination_check, bool(yes),
             !Globals),
-        option_implies(check_termination, termination, bool(yes), !Globals),
-        option_implies(check_termination, warn_missing_trans_opt_files,
+        option_implies(termination_check, termination, bool(yes), !Globals),
+        option_implies(termination_check, warn_missing_trans_opt_files,
             bool(yes), !Globals),
         option_implies(verbose_check_termination2, check_termination2,
             bool(yes), !Globals),
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.167
diff -u -b -r1.167 hlds_goal.m
--- compiler/hlds_goal.m	5 Sep 2006 06:21:25 -0000	1.167
+++ compiler/hlds_goal.m	2 Nov 2006 02:40:25 -0000
@@ -2480,8 +2480,8 @@
 
 :- func this_file = string.
 
-this_file = "hlds_goal".
+this_file = "hlds_goal.m".
 
 %-----------------------------------------------------------------------------%
-:- end_module hlds_goal.
+:- end_module hlds.hlds_goal.
 %-----------------------------------------------------------------------------%
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_module.m,v
retrieving revision 1.143
diff -u -b -r1.143 hlds_module.m
--- compiler/hlds_module.m	22 Oct 2006 09:14:24 -0000	1.143
+++ compiler/hlds_module.m	2 Nov 2006 05:39:06 -0000
@@ -39,6 +39,7 @@
 :- import_module parse_tree.prog_item.
 :- import_module recompilation.
 
+:- import_module bool.
 :- import_module list.
 :- import_module map.
 :- import_module maybe.
@@ -56,7 +57,6 @@
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
 
-:- import_module bool.
 :- import_module int.
 :- import_module string.
 :- import_module svmap.
@@ -334,9 +334,15 @@
 :- pred module_info_set_globals(globals::in,
     module_info::in, module_info::out) is det.
 
-:- pred module_info_contains_foreign_type(module_info::in) is semidet.
+:- pred module_info_get_contains_foreign_type(module_info::in, bool::out)
+    is det.
+
+:- pred module_info_set_contains_foreign_type(module_info::in,
+    module_info::out) is det.
+
+:- pred module_info_get_contains_par_conj(module_info::in, bool::out) is det.
 
-:- pred module_info_contains_foreign_type(module_info::in, module_info::out)
+:- pred module_info_set_contains_par_conj(module_info::in, module_info::out)
     is det.
 
 :- pred module_info_get_foreign_decl(module_info::in, foreign_decl_info::out)
@@ -664,6 +670,7 @@
     --->    module_sub_info(
                 module_name                 :: module_name,
                 globals                     :: globals,
+                contains_par_conj           :: bool,
                 contains_foreign_type       :: bool,
                 foreign_decl_info           :: foreign_decl_info,
                 foreign_body_info           :: foreign_body_info,
@@ -752,10 +759,10 @@
                 % Information about which procedures implement structure reuse.
                 structure_reuse_map         :: structure_reuse_map,
 
-                % The modules which have already been calculated as being
-                % used.  Currently this is the module imports inherited from
-                % the parent modules plus those calculated during expansion
-                % of equivalence types and insts.
+                % The modules which have already been calculated as being used.
+                % Currently this is the module imports inherited from the
+                % parent modules plus those calculated during expansion of
+                % equivalence types and insts.
                 used_modules                :: used_modules,
 
                 % All the directly imported module specifiers in the interface.
@@ -798,8 +805,8 @@
     map.init(FieldNameTable),
 
     map.init(NoTagTypes),
-    ModuleSubInfo = module_sub_info(Name, Globals, no, [], [], [], [], no, 0,
-        [], [], StratPreds, UnusedArgInfo, ExceptionInfo, TrailingInfo,
+    ModuleSubInfo = module_sub_info(Name, Globals, no, no, [], [], [], [],
+        no, 0, [], [], StratPreds, UnusedArgInfo, ExceptionInfo, TrailingInfo,
         MM_TablingInfo, map.init, counter.init(1), ImportedModules,
         IndirectlyImportedModules, TypeSpecInfo, NoTagTypes, no, [],
         init_analysis_info(mmc), [], [],
@@ -857,8 +864,9 @@
 
 module_info_get_name(MI, MI ^ sub_info ^ module_name).
 module_info_get_globals(MI, MI ^ sub_info ^ globals).
-module_info_contains_foreign_type(MI) :-
-    MI ^ sub_info ^ contains_foreign_type = yes.
+module_info_get_contains_foreign_type(MI,
+    MI ^ sub_info ^ contains_foreign_type).
+module_info_get_contains_par_conj(MI, MI ^ sub_info ^ contains_par_conj).
 module_info_get_foreign_decl(MI, MI ^ sub_info ^ foreign_decl_info).
 module_info_get_foreign_body_code(MI, MI ^ sub_info ^ foreign_body_info).
 module_info_get_foreign_import_module(MI,
@@ -955,8 +963,10 @@
 
 module_info_set_globals(NewVal, MI,
     MI ^ sub_info ^ globals := NewVal).
-module_info_contains_foreign_type(MI,
+module_info_set_contains_foreign_type(MI,
     MI ^ sub_info ^ contains_foreign_type := yes).
+module_info_set_contains_par_conj(MI,
+    MI ^ sub_info ^ contains_par_conj := yes).
 module_info_set_foreign_decl(NewVal, MI,
     MI ^ sub_info ^ foreign_decl_info := NewVal).
 module_info_set_foreign_body_code(NewVal, MI,
@@ -1275,6 +1285,7 @@
 :- pred hlds_dependency_info_get_dependency_graph(dependency_info(T)::in,
     dependency_graph(T)::out) is det.
 
+    % XXX document whether the dependency_ordering is ascending or descending.
 :- pred hlds_dependency_info_get_dependency_ordering(dependency_info(T)::in,
     dependency_ordering(T)::out) is det.
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.412
diff -u -b -r1.412 mercury_compile.m
--- compiler/mercury_compile.m	25 Oct 2006 03:39:04 -0000	1.412
+++ compiler/mercury_compile.m	2 Nov 2006 06:55:32 -0000
@@ -94,6 +94,7 @@
 :- import_module transform_hlds.ctgc.structure_reuse.analysis.
 :- import_module transform_hlds.ctgc.structure_sharing.
 :- import_module transform_hlds.ctgc.structure_sharing.analysis.
+:- import_module transform_hlds.granularity.
 :- import_module transform_hlds.dep_par_conj.
 :- import_module transform_hlds.size_prof.
 :- import_module ll_backend.deep_profiling.
@@ -2505,19 +2506,22 @@
     maybe_dump_hlds(!.HLDS, 175, "lco", !DumpInfo, !IO),
 
     maybe_eliminate_dead_procs(Verbose, Stats, !HLDS, !IO),
-    maybe_dump_hlds(!.HLDS, 190, "dead_procs", !DumpInfo, !IO),
+    maybe_dump_hlds(!.HLDS, 180, "dead_procs", !DumpInfo, !IO),
    
     maybe_analyse_mm_tabling(Verbose, Stats, !HLDS, !IO),
-    maybe_dump_hlds(!.HLDS, 200, "mm_tabling_analysis", !DumpInfo, !IO),
+    maybe_dump_hlds(!.HLDS, 185, "mm_tabling_analysis", !DumpInfo, !IO),
 
     maybe_structure_sharing_analysis(Verbose, Stats, !HLDS, !IO), 
-    maybe_dump_hlds(!.HLDS, 210, "structure_sharing", !DumpInfo, !IO), 
+    maybe_dump_hlds(!.HLDS, 190, "structure_sharing", !DumpInfo, !IO),
 
     maybe_structure_reuse_analysis(Verbose, Stats, !HLDS, !IO), 
-    maybe_dump_hlds(!.HLDS, 212, "structure_reuse", !DumpInfo, !IO), 
+    maybe_dump_hlds(!.HLDS, 195, "structure_reuse", !DumpInfo, !IO),
+
+    maybe_control_granularity(Verbose, Stats, !HLDS, !IO),
+    maybe_dump_hlds(!.HLDS, 200, "granularity", !DumpInfo, !IO),
 
     maybe_dependent_par_conj(Verbose, Stats, !HLDS, !IO),
-    maybe_dump_hlds(!.HLDS, 214, "dependent_par_conj", !DumpInfo, !IO), 
+    maybe_dump_hlds(!.HLDS, 205, "dependent_par_conj", !DumpInfo, !IO),
     
     % If we are compiling in a deep profiling grade then now rerun simplify.
     % The reason for doing this now is that we want to take advantage of any
@@ -3819,11 +3823,47 @@
         Sharing = no
     ).
 
+:- pred maybe_control_granularity(bool::in, bool::in,
+    module_info::in, module_info::out, io::di, io::uo) is det.
+
+maybe_control_granularity(Verbose, Stats, !HLDS, !IO) :-
+    module_info_get_globals(!.HLDS, Globals),
+    globals.lookup_bool_option(Globals, parallel, Parallel),
+    globals.lookup_bool_option(Globals, control_granularity, Control),
+    module_info_get_contains_par_conj(!.HLDS, ContainsParConj),
+    (
+        Parallel = yes,
+        Control = yes,
+        ContainsParConj = yes
+    ->
+        globals.get_target(Globals, Target),
+        (
+            Target = target_c,
+            maybe_write_string(Verbose,
+                "% Granularity control transformation...\n", !IO),
+            maybe_flush_output(Verbose, !IO),
+            control_granularity(!HLDS),
+            maybe_write_string(Verbose, "% done.\n", !IO),
+            maybe_report_stats(Stats, !IO)
+        ;
+            ( Target = target_il
+            ; Target = target_java
+            ; Target = target_asm
+            )
+            % Leave the HLDS alone. We cannot implement parallelism,
+            % so there is not point in controlling its granularity.
+        )
+    ;
+        true
+    ).
+
 :- pred maybe_dependent_par_conj(bool::in, bool::in,
     module_info::in, module_info::out, io::di, io::uo) is det.
 
 maybe_dependent_par_conj(Verbose, Stats, !HLDS, !IO) :- 
-    % XXX only do this if the module actually has parallel conjunctions
+    module_info_get_contains_par_conj(!.HLDS, ContainsParConj),
+    (
+        ContainsParConj = yes,
     % This pass also converts dependent parallel conjunctions into
     % plain conjunctions if we are not building in a parallel grade.
     maybe_write_string(Verbose,
@@ -3831,7 +3871,10 @@
     maybe_flush_output(Verbose, !IO), 
     dependent_par_conj(!HLDS, !IO), 
     maybe_write_string(Verbose, "% done.\n", !IO),
-    maybe_report_stats(Stats, !IO).
+        maybe_report_stats(Stats, !IO)
+    ;
+        ContainsParConj = no
+    ).
 
 :- pred maybe_structure_reuse_analysis(bool::in, bool::in,
     module_info::in, module_info::out, io::di, io::uo) is det.
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.533
diff -u -b -r1.533 options.m
--- compiler/options.m	1 Nov 2006 02:31:09 -0000	1.533
+++ compiler/options.m	2 Nov 2006 09:31:28 -0000
@@ -537,13 +537,16 @@
     ;       deforestation_cost_factor
     ;       deforestation_vars_threshold
     ;       deforestation_size_threshold
-    ;       termination
-    ;       check_termination
-    ;       verbose_check_termination
-    ;       termination_single_args
-    ;       termination_norm
-    ;       termination_error_limit
-    ;       termination_path_limit
+    ;       analyse_trail_usage
+    ;       optimize_trail_usage
+    ;       analyse_mm_tabling
+    ;       untuple
+    ;       tuple
+    ;       tuple_trace_counts_file
+    ;       tuple_costs_ratio
+    ;       tuple_min_args
+    ;       control_granularity
+    ;       parallelism_target
 
     % Stuff for the CTGC system (structure sharing / structure reuse).
     ;       structure_sharing_analysis
@@ -552,6 +555,15 @@
     ;           structure_reuse_constraint
     ;           structure_reuse_constraint_arg
 
+    % Stuff for the old termination analyser.
+    ;       termination
+    ;       termination_check
+    ;       verbose_check_termination
+    ;       termination_single_args
+    ;       termination_norm
+    ;       termination_error_limit
+    ;       termination_path_limit
+
     % Stuff for the new termination analyser.
     ;       termination2
     ;          check_termination2
@@ -563,14 +575,6 @@
     ;          term2_maximum_matrix_size
     ;       analyse_exceptions
     ;       analyse_closures
-    ;       analyse_trail_usage
-    ;       optimize_trail_usage
-    ;       analyse_mm_tabling
-    ;       untuple
-    ;       tuple
-    ;       tuple_trace_counts_file
-    ;       tuple_costs_ratio
-    ;       tuple_min_args
 
     %   - HLDS->LLDS
     ;       smart_indexing
@@ -1184,7 +1188,7 @@
     transitive_optimization             -   bool(no),
     intermodule_analysis                -   bool(no),
     analysis_repeat                     -   int(0),
-    check_termination                   -   bool(no),
+    termination_check                   -   bool(no),
     verbose_check_termination           -   bool(no),
     structure_sharing_analysis          -   bool(no), 
     structure_sharing_widening          -   int(0),
@@ -1287,6 +1291,8 @@
     tuple_trace_counts_file             -   string(""),
     tuple_costs_ratio                   -   int(100),
     tuple_min_args                      -   int(4),
+    control_granularity                 -   bool(no),
+    parallelism_target                  -   int(4),
 
     % HLDS -> LLDS
     smart_indexing                      -   bool(no),
@@ -1986,9 +1992,9 @@
 long_option("deforestation-size-threshold", deforestation_size_threshold).
 long_option("enable-termination",   termination).
 long_option("enable-term",          termination).
-long_option("check-termination",    check_termination).
-long_option("check-term",           check_termination).
-long_option("chk-term",             check_termination).
+long_option("check-termination",    termination_check).
+long_option("check-term",           termination_check).
+long_option("chk-term",             termination_check).
 long_option("verbose-check-termination",verbose_check_termination).
 long_option("verb-check-term",      verbose_check_termination).
 long_option("verb-chk-term",        verbose_check_termination).
@@ -2032,6 +2038,8 @@
 long_option("tuple-trace-counts-file",  tuple_trace_counts_file).
 long_option("tuple-costs-ratio",    tuple_costs_ratio).
 long_option("tuple-min-args",       tuple_min_args).
+long_option("control-granularity",  control_granularity).
+long_option("parallelism-target",   parallelism_target).
 
 % CTGC related options.
 long_option("structure-sharing",    structure_sharing_analysis).
@@ -4164,7 +4172,7 @@
         "\tIdentify those goals that do not call procedures",
         "\tthat are evaluated using minimal model tabling.",
         "\tThis information is used to reduce the overhead",
-        "\tof minimal model tabling."
+        "\tof minimal model tabling.",
         % "--untuple",
         % "\tExpand out procedure arguments when the argument type",
         % "\tis a tuple or a type with exactly one functor.",
@@ -4189,7 +4197,13 @@
         % "\tThe minimum number of input arguments that the tupling",
         % "\ttransformation will consider passing together as a",
         % "\ttuple. This is mostly to speed up the compilation",
-        % "\tprocess by not pursuing (presumably) unfruitful searches."
+        % "\tprocess by not pursuing (presumably) unfruitful searches.",
+        "--control-granularity",
+        "\tDon't try to generate more parallelism than the machine can",
+        "\thandle, which is specified using --parallelism-target.",
+        "--parallelism-target N",
+        "\tSpecified the number of CPUs of the target machine, for use by",
+        "\tthe --control-granularity option."
     ]).
 
 :- pred options_help_hlds_llds_optimization(io::di, io::uo) is det.
Index: compiler/quantification.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/quantification.m,v
retrieving revision 1.109
diff -u -b -r1.109 quantification.m
--- compiler/quantification.m	15 Oct 2006 23:26:50 -0000	1.109
+++ compiler/quantification.m	2 Nov 2006 02:53:39 -0000
@@ -69,7 +69,7 @@
     --->    ordinary_nonlocals
     ;       code_gen_nonlocals.
 
-:- pred implicitly_quantify_clause_body(nonlocals_to_recompute::in,
+:- pred implicitly_quantify_clause_body_general(nonlocals_to_recompute::in,
     list(prog_var)::in, list(quant_warning)::out,
     hlds_goal::in, hlds_goal::out, prog_varset::in, prog_varset::out,
     vartypes::in, vartypes::out, rtti_varmaps::in, rtti_varmaps::out) is det.
@@ -81,7 +81,7 @@
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
     rtti_varmaps::in, rtti_varmaps::out) is det.
 
-:- pred implicitly_quantify_goal(nonlocals_to_recompute::in,
+:- pred implicitly_quantify_goal_general(nonlocals_to_recompute::in,
     set(prog_var)::in, list(quant_warning)::out,
     hlds_goal::in, hlds_goal::out, prog_varset::in, prog_varset::out,
     vartypes::in, vartypes::out, rtti_varmaps::in, rtti_varmaps::out) is det.
@@ -92,7 +92,7 @@
     hlds_goal::in, hlds_goal::out, prog_varset::in, prog_varset::out,
     vartypes::in, vartypes::out, rtti_varmaps::in, rtti_varmaps::out) is det.
 
-:- pred requantify_proc(nonlocals_to_recompute::in,
+:- pred requantify_proc_general(nonlocals_to_recompute::in,
     proc_info::in, proc_info::out) is det.
 
     % As above, with `ordinary_nonlocals' passed as the first argument.
@@ -197,27 +197,27 @@
 
 %-----------------------------------------------------------------------------%
 
-implicitly_quantify_clause_body(HeadVars, Warnings,
-        !Goal, !Varset, !VarTypes, !RttiVarMaps) :-
-    implicitly_quantify_clause_body(ordinary_nonlocals, HeadVars, Warnings,
-        !Goal, !Varset, !VarTypes, !RttiVarMaps).
+implicitly_quantify_clause_body(HeadVars,
+        Warnings, !Goal, !Varset, !VarTypes, !RttiVarMaps) :-
+    implicitly_quantify_clause_body_general(ordinary_nonlocals, HeadVars,
+        Warnings, !Goal, !Varset, !VarTypes, !RttiVarMaps).
 
-implicitly_quantify_clause_body(RecomputeNonLocals, HeadVars, Warnings,
+implicitly_quantify_clause_body_general(RecomputeNonLocals, HeadVars, Warnings,
         !Goal, !Varset, !VarTypes, !RttiVarMaps) :-
     list_to_set(HeadVars, OutsideVars),
-    implicitly_quantify_goal(RecomputeNonLocals, OutsideVars, Warnings,
+    implicitly_quantify_goal_general(RecomputeNonLocals, OutsideVars, Warnings,
         !Goal, !Varset, !VarTypes, !RttiVarMaps).
 
 requantify_proc(ProcInfo0, ProcInfo) :-
-    requantify_proc(ordinary_nonlocals, ProcInfo0, ProcInfo).
+    requantify_proc_general(ordinary_nonlocals, ProcInfo0, ProcInfo).
 
-requantify_proc(RecomputeNonLocals, !ProcInfo) :-
+requantify_proc_general(RecomputeNonLocals, !ProcInfo) :-
     proc_info_get_headvars(!.ProcInfo, HeadVars),
     proc_info_get_varset(!.ProcInfo, Varset0),
     proc_info_get_vartypes(!.ProcInfo, VarTypes0),
     proc_info_get_goal(!.ProcInfo, Goal0),
     proc_info_get_rtti_varmaps(!.ProcInfo, RttiVarmaps0),
-    implicitly_quantify_clause_body(RecomputeNonLocals, HeadVars, _,
+    implicitly_quantify_clause_body_general(RecomputeNonLocals, HeadVars, _,
         Goal0, Goal, Varset0, Varset, VarTypes0, VarTypes,
         RttiVarmaps0, RttiVarmaps),
     proc_info_set_varset(Varset, !ProcInfo),
@@ -227,10 +227,10 @@
 
 implicitly_quantify_goal(OutsideVars, Warnings, !Goal, !Varset, !VarTypes, 
         !RttiVarMaps) :-
-    implicitly_quantify_goal(ordinary_nonlocals, OutsideVars, Warnings,
+    implicitly_quantify_goal_general(ordinary_nonlocals, OutsideVars, Warnings,
         !Goal, !Varset, !VarTypes, !RttiVarMaps).
 
-implicitly_quantify_goal(RecomputeNonLocals, OutsideVars, Warnings,
+implicitly_quantify_goal_general(RecomputeNonLocals, OutsideVars, Warnings,
         !Goal, !Varset, !VarTypes, !RttiVarMaps) :-
     implicitly_quantify_goal_2(ordinary_nonlocals, OutsideVars, Warnings,
         !Goal, !Varset, !VarTypes, !RttiVarMaps),
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.194
diff -u -b -r1.194 simplify.m
--- compiler/simplify.m	15 Oct 2006 23:40:13 -0000	1.194
+++ compiler/simplify.m	2 Nov 2006 06:04:00 -0000
@@ -345,11 +345,13 @@
         !:MaybeSpecs = yes(ProcAnyModeSpecSet - ProcAllModeSpecSet)
     ),
     % This is ugly, but we want to avoid running the dependent parallel
-    % conjunction pass on predicates not containing parallel conjunctions
-    % (nearly all of them).  Since simplification is always done, we use it
-    % to mark predicates containing parallel conjunctions.
+    % conjunction pass on predicates and even modules that do not contain
+    % parallel conjunctions (nearly all of them).  Since simplification
+    % is always done, we use it to mark modules and predicates containing
+    % parallel conjunctions.
     (
         MayHaveParallelConj = yes,
+        module_info_set_contains_par_conj(!ModuleInfo),
         pred_info_get_markers(!.PredInfo, Markers0),
         add_marker(marker_may_have_parallel_conj, Markers0, Markers),
         pred_info_set_markers(Markers, !PredInfo)
Index: compiler/termination.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/termination.m,v
retrieving revision 1.69
diff -u -b -r1.69 termination.m
--- compiler/termination.m	22 Aug 2006 05:04:10 -0000	1.69
+++ compiler/termination.m	2 Nov 2006 04:19:26 -0000
@@ -499,7 +499,7 @@
     module_info::in, module_info::out, io::di, io::uo) is det.
 
 report_termination_errors(SCC, Errors, !ModuleInfo, !IO) :-
-    globals.io_lookup_bool_option(check_termination, NormalErrors, !IO),
+    globals.io_lookup_bool_option(termination_check, NormalErrors, !IO),
     globals.io_lookup_bool_option(verbose_check_termination,
         VerboseErrors, !IO),
     (
Index: compiler/transform_hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/transform_hlds.m,v
retrieving revision 1.24
diff -u -b -r1.24 transform_hlds.m
--- compiler/transform_hlds.m	28 Jun 2006 04:46:18 -0000	1.24
+++ compiler/transform_hlds.m	2 Nov 2006 02:46:59 -0000
@@ -83,6 +83,7 @@
 :- include_module size_prof.
 :- include_module tupling.
 :- include_module untupling.
+:- include_module granularity.
 :- include_module dep_par_conj.
 
 :- include_module mmc_analysis.
cvs diff: Diffing compiler/notes
Index: compiler/notes/compiler_design.html
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.123
diff -u -b -r1.123 compiler_design.html
--- compiler/notes/compiler_design.html	15 Sep 2006 11:14:37 -0000	1.123
+++ compiler/notes/compiler_design.html	2 Nov 2006 07:22:42 -0000
@@ -116,10 +116,10 @@
                <li> 6b. output code
      	       (MLDS -> C or MLDS -> MSIL or MLDS -> Java, etc.)
                </ul>
-          <li> d. bytecode back-end
+          <li> c. bytecode back-end
                <br> Package: bytecode_backend.m
                <ul type=disc>
-               <li> 4d. code generation (annotated HLDS -> bytecode)
+               <li> 4c. code generation (annotated HLDS -> bytecode)
                </ul>
           <li> There's also a package backend_libs.m which contains
 	       modules which are shared between several different back-ends.
@@ -1054,6 +1054,30 @@
   even the user doesn't, and automatically constructed unification and
   comparison predicates are often dead as well.
 
+<li> elimination of dead procedures (dead_proc_elim.m). Inlining, higher-order
+  specialization and the elimination of unused args can make procedures dead
+  even the user doesn't, and automatically constructed unification and
+  comparison predicates are often dead as well.
+
+<li> tupling.m looks for predicates that pass around several arguments,
+  and modifies the code to pass around a single tuple of these arguments
+  insteead if this looks like reducing the cost of parameter passing.
+
+<li> untupling.m does the opposite of tupling.m: it replaces tuple arguments
+  with their components. This can be useful both for finding out how much
+  tupling has already been done manually in the source code, and to break up
+  manual tupling in favor of possibly more profitable automatic tupling.
+
+<li> dep_par_conj.m transforms parallel conjunctions to add the wait and signal
+  operations required by dependent AND parallelism. To maximize the amount of
+  parallelism available, it tries to push the signals as early as possible
+  in producers and the waits as late as possible in the consumers, creating
+  specialized versions of predicates as needed.
+
+<li> granularity.m tries to ensure that programs do not generate too much
+  parallelism. Its goal is to minimize parallelism's overhead while still
+  gaining all the parallelism the machine can actually exploit.
+
 </ul>
 
 <p>
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.496
diff -u -b -r1.496 user_guide.texi
--- doc/user_guide.texi	2 Oct 2006 10:14:38 -0000	1.496
+++ doc/user_guide.texi	2 Nov 2006 09:31:27 -0000
@@ -7332,7 +7332,7 @@
 unused argument elimination across module boundaries.
 This option is not yet fully implemented.
 
- at item --analysis-repeat <n>
+ at item --analysis-repeat @var{n}
 @findex --analysis-repeat
 The maximum number of times to repeat analyses of suboptimal modules with
 @samp{--intermodule-analyses} (default: 0).  This option only works with
@@ -7468,7 +7468,7 @@
 of the goal.
 
 @sp 1
- at item --unneeded-code-copy-limit
+ at item --unneeded-code-copy-limit @var{limit}
 @findex --unneeded-code-copy-limit
 Gives the maximum number of places to which a goal may be copied
 when removing it from computation paths on which its outputs are not needed.
@@ -7500,7 +7500,7 @@
 chapter of the Mercury Language Reference Manual for more details.
 
 @sp 1
- at item --higher-order-size-limit
+ at item --higher-order-size-limit @var{limit}
 @findex --higher-order-size-limit
 Set the maximum goal size of specialized versions created by
 @samp{--optimize-higher-order} and @samp{--type-specialization}.
@@ -7508,8 +7508,8 @@
 and branched goals.
 
 @sp 1
- at item --higher-order-arg-limit
- at item --higher-order-arg-limit
+ at item --higher-order-arg-limit @var{limit}
+ at findex --higher-order-arg-limit
 Set the maximum size of higher-order arguments to
 be specialized by @samp{--optimize-higher-order} and
 @samp{--type-specialization}.
@@ -7575,21 +7575,20 @@
 repeated traversals over data structures within a conjunction.
 
 @sp 1
- at item --deforestation-depth-limit
+ at item --deforestation-depth-limit @var{limit}
 @findex --deforestation-depth-limit
-Specify a depth limit to prevent infinite loops in the
-deforestation algorithm.
+Specify a depth limit to prevent infinite loops in the deforestation algorithm.
 A value of -1 specifies no depth limit. The default is 4.
 
 @sp 1
- at item --deforestation-vars-threshold
+ at item --deforestation-vars-threshold @var{threshold}
 @findex --deforestation-vars-threshold
 Specify a rough limit on the number of variables
 in a procedure created by deforestation.
 A value of -1 specifies no limit. The default is 200.
 
 @sp 1
- at item --deforestation-size-threshold
+ at item --deforestation-size-threshold @var{threshold}
 @findex --deforestation-size-threshold
 Specify a rough limit on the size of a goal
 to be optimized by deforestation.
@@ -7598,9 +7597,8 @@
 @sp 1
 @item --analyse-exceptions
 @findex --analyse-exceptions
-Try to identify those procedures that cannot throw an
-exception.  This information can be used by some
-optimization passes.
+Try to identify those procedures that cannot throw an exception.
+This information can be used by some optimization passes.
 
 @c XXX The documentation `--analyse-closures' can be uncommented
 @c when we actually have something that makes use of it.
@@ -7615,18 +7613,16 @@
 @sp 1
 @item --analyse-trail-usage
 @findex --analyse-trail-usage
-Enable trail usage analysis.  Identify those
-procedures that will not modify the trail.
-This information is used to reduce the overhead
-of trailing.
+Enable trail usage analysis.
+Identify those procedures that will not modify the trail.
+This information is used to reduce the overhead of trailing.
 
 @sp 1
 @item --analyse-mm-tabling
 @findex --analyse-mm-tabling
 Identify those goals that do not calls procedures
 that are evaluated using minimal model tabling.
-This information is used to reduce the overhead
-of minimal model tabling.
+This information is used to reduce the overhead of minimal model tabling.
 
 @c @sp 1
 @c @item --untuple
@@ -7672,6 +7668,18 @@
 @c tuple. This is mostly to speed up the compilation
 @c process by not pursuing (presumably) unfruitful searches.
 
+ at sp 1
+ at item --control-granularity
+ at findex --control-granularity
+Don't try to generate more parallelism than the machine can handle,
+which is specified using --parallelism-target.
+
+ at sp 1
+ at item --parallelism-target @var{num_cpus}
+ at findex --parallelism-target
+Specifies the number of CPUs of the target machine,
+for use by --control-granularity option.
+
 @end table
 
 @node MLDS backend (MLDS -> MLDS) optimization options
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
Index: library/private_builtin.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/private_builtin.m,v
retrieving revision 1.164
diff -u -b -r1.164 private_builtin.m
--- library/private_builtin.m	23 Oct 2006 11:38:42 -0000	1.164
+++ library/private_builtin.m	2 Nov 2006 03:40:24 -0000
@@ -1540,6 +1540,8 @@
 
 :- import_module io.
 
+:- semipure pred evaluate_parallelism_condition is semidet.
+
 :- semipure pred trace_evaluate_runtime_condition is semidet.
 
 :- semipure pred trace_get_io_state(io::uo) is det.
@@ -1549,6 +1551,14 @@
 :- implementation.
 
 :- pragma foreign_proc("C",
+    evaluate_parallelism_condition,
+    [will_not_call_mercury, thread_safe, promise_semipure],
+"
+    /* All uses of this predicate should override the body. */
+    MR_fatal_error(""evaluate_parallelism_condition called"");
+").
+
+:- pragma foreign_proc("C",
     trace_evaluate_runtime_condition,
     [will_not_call_mercury, thread_safe, promise_semipure],
 "
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
Index: tests/par_conj/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/par_conj/Mmakefile,v
retrieving revision 1.9
diff -u -b -r1.9 Mmakefile
--- tests/par_conj/Mmakefile	20 Oct 2006 02:07:31 -0000	1.9
+++ tests/par_conj/Mmakefile	2 Nov 2006 09:16:18 -0000
@@ -51,6 +51,7 @@
 INDEP_PAR_CONJ_PROGS = \
 	indep_par_append \
 	indep_par_nested \
+	par_fib \
 	threads_hang
 
 # These tests require debugging, which hasn't been implemented for
Index: tests/par_conj/par_fib.exp
===================================================================
RCS file: tests/par_conj/par_fib.exp
diff -N tests/par_conj/par_fib.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/par_conj/par_fib.exp	2 Nov 2006 09:15:37 -0000
@@ -0,0 +1 @@
+14930352
Index: tests/par_conj/par_fib.m
===================================================================
RCS file: tests/par_conj/par_fib.m
diff -N tests/par_conj/par_fib.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/par_conj/par_fib.m	2 Nov 2006 09:07:56 -0000
@@ -0,0 +1,61 @@
+% vim: ts=4 sw=4 et ft=mercury
+
+:- module par_fib.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+:- implementation.
+
+:- import_module benchmarking.
+:- import_module int.
+:- import_module list.
+:- import_module require.
+:- import_module string.
+
+main(!IO) :-
+	perform_trial(35, Res),
+    io.write_int(Res, !IO),
+    io.nl(!IO).
+
+:- pred perform_trial(int::in, int::out) is cc_multi.
+
+perform_trial(N, Res) :-
+	trial(N, Res, SeqTime, ParTime),
+    trace [compile_time(flag("show_times")), io(!IO)] (
+        io.format("fib(%d): sequential %d vs parallel %d\n",
+            [i(N), i(SeqTime), i(ParTime)], !IO)
+    ).
+
+:- pred trial(int::in, int::out, int::out, int::out) is cc_multi.
+
+trial(N, SeqRes, SeqTime, ParTime) :-
+	benchmark_det(seq_fib, N, SeqRes, 1, SeqTime),
+	benchmark_det(par_fib, N, ParRes, 1, ParTime),
+	require(unify(SeqRes, ParRes), "parallelism produces wrong answer").
+
+:- pred seq_fib(int::in, int::out) is det.
+
+seq_fib(N, F) :-
+	( N < 2 ->
+		F = 1
+	;
+		seq_fib(N - 1, F1),
+		seq_fib(N - 2, F2),
+		F = F1 + F2
+	).
+
+:- pred par_fib(int::in, int::out) is det.
+
+par_fib(N, F) :-
+	( N < 2 ->
+		F = 1
+	;
+		( par_fib(N - 1, F1)
+		& par_fib(N - 2, F2)
+		),
+		F = F1 + F2
+	).
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list