[m-rev.] diff: cleanup of par_lopo_control.m

Zoltan Somogyi zs at csse.unimelb.edu.au
Tue Oct 18 12:58:29 AEDT 2011


compiler/par_loop_control.m:
	Simplify some code. Fix some comments. Give some predicates
	more meaningful names.

Zoltan.

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/extra
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/extra
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/doc
cvs diff: Diffing boehm_gc/libatomic_ops/src
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/armcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops/tests
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/tests
cvs diff: Diffing boehm_gc/m4
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/par_loop_control.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/par_loop_control.m,v
retrieving revision 1.3
diff -u -b -r1.3 par_loop_control.m
--- compiler/par_loop_control.m	9 Oct 2011 09:56:20 -0000	1.3
+++ compiler/par_loop_control.m	17 Oct 2011 13:35:28 -0000
@@ -9,17 +9,25 @@
 % File: par_loop_control.m.
 % Author: pbone.
 %
-% This module implements the parallel loop control transformation.  Parallel
-% conjunctions spawn off their second operand, execute the first and then block
-% waiting for the completion of the second.  Therefore, when the second operand
-% contains a recursive call the blocked resource consumes memory that orght to
-% be avoided.
+% This module implements the parallel loop control transformation.
+% This transformation operates on procedure bodies that contain exactly one
+% recursive call which occurs in the second and last conjunct of a parallel
+% conjunction.
 %
-% This can be avoided by spawning off the first operand and continuing with the
-% second.  This is acheived by the loop control transformation which provides
-% further optimization by using a different structure for synchronization.
-% There is one barrier in a loop rather than N (for N recursions) and the
-% maximum number of contexts the loop may used is fixed.
+% Normally, this parallel conjunction would spawn off their second conjunct,
+% execute the first conjunct, and then block waiting for the completion of
+% the second. When the second conjunct contains a recursive call, the blocked
+% first computation will be a context, and will thus have a high memory
+% footprint due to its stacks. The objective of our transformation is to reduce
+% this memory footprint.
+%
+% The way we do this is by spawning off the first parallel conjunct, and
+% continuing execution of the second. Since the second conjunct is a recursive
+% call, we will continue spawning off first conjuncts until we reach a limit
+% that is imposed by a loop control structure. This limit prevents us from
+% swamping the available CPUs with too much work. It also allows us to
+% use one barrier for ALL the loop iterations, rather than one barrier
+% for EACH loop iteration.
 %
 % Consider this loop:
 %
@@ -47,9 +55,9 @@
 %       ),
 %       map(LC, M, Xs, Ys). % May not use tail recursion.
 %
-% The parallel conjunction is replaced with a wait_free_slot and spawn_off goals
-% for each conjunct except for the last, which is re-written to call the loop
-% control version of the predicate.
+% The parallel conjunction is replaced with a wait_free_slot goal and a
+% spawn_off goal for each conjunct except for the last. The last is re-written
+% to call the loop control version of the predicate.
 %
 % Rules:
 %
@@ -59,13 +67,14 @@
 %    replaced with the call to spawn_off.
 %
 % 2. There may be code _after_ the recursive call that consumes variables
-%    produced in the first conjunct.  This is safe because the barrier in the
-%    base case has been executed.  Any consumption before the recursive call
-%    will already be using a future and is safe.
+%    produced in the first conjunct. This is safe because we get to such code
+%    only *after* the barrier in the base case has been executed. Any
+%    consumption before the recursive call will already be using a future,
+%    and is therefore safe.
 %
-% 3. There _may not_ be more than one recursive call along any code-path.  That
-%    is to say, the code must be singly recursive so that the base case (and
-%    the barrier within) is executed exactly once.
+% 3. The predicate must be singly recursive, i.e. its body cannot have
+%    more than one recursive call along any execution path. We need this
+%    to ensure that the base case (and its barrier) is executed exactly once.
 %
 % 4. Multiple parallel conjunctions may exist within the body, but due to rule
 %    3, only one of them may contain a recursive call.
@@ -201,13 +210,13 @@
                 % There is no reachable recursive call in this goal.
 
     ;       seen_one_recursive_call_on_every_branch
-                % There is exactly one recursive call on every reachable
-                % branch, Therefore this single recursion can be used if it is
-                % within a parallel conjunction.
+            % There is exactly one recursive call on every reachable branch.
+            % Therefore this single recursion can be used if it is within
+            % a parallel conjunction.
 
     ;       seen_unusable_recursion
-                % There is recursion but we cannot use it.  This is caused
-                % by a number of different reasons, some are:
+            % There is recursion, but we cannot use it. There may be several
+            % reasons for why we cannot use the transformation, including
                 %   + Multiple recursion.
                 %   + Recursion on some but not all branches or in code that is
                 %     not det/cc_multi.
@@ -249,7 +258,7 @@
         ;
             GoalExpr = generic_call(_, _, _, _),
             % We cannot determine if a generic call is recursive or not,
-            % however it most likely is not.  In either case we cannot perform
+            % however it most likely is not. In either case, we cannot perform
             % the loop control transformation.
             SeenUsableRecursion0 = have_not_seen_recursive_call
         ;
@@ -268,25 +277,22 @@
                     GoalId, SeenUsableRecursion0)
             )
         ;
-            GoalExpr = disj(Disjs),
-            % If the disjunction contains a recursive call at all then the
+            GoalExpr = disj(_),
+            % If the disjunction contains a recursive call at all, then the
             % recursive call is in an unusable context.
-            (
-                member(Disj, Disjs),
-                goal_calls(Disj, SelfPredProcId)
-            ->
+            ( goal_calls(Goal, SelfPredProcId) ->
                 SeenUsableRecursion0 = seen_unusable_recursion
             ;
                 SeenUsableRecursion0 = have_not_seen_recursive_call
             )
         ;
             GoalExpr = switch(_, _CanFail, Cases),
-            map(case_get_loop_control_par_conjs(SelfPredProcId), Cases,
+            list.map(case_get_loop_control_par_conjs(SelfPredProcId), Cases,
                 SeenUsableRecursionCases),
-            % If the switch can fail then there is effectively another branch
-            % that has no recursive call.  However, we don not need to test for
-            % it here as checking the determinism of the goal will detect such
-            % a case.
+            % If the switch can fail, then there is effectively another branch
+            % that has no recursive call. However, we do not need to test for
+            % this here, as checking the determinism of the goal will detect
+            % such cases.
             merge_loop_control_par_conjs_between_branches_list(
                 SeenUsableRecursionCases, SeenUsableRecursion0)
         ;
@@ -301,6 +307,8 @@
             GoalExpr = scope(_, SubGoal),
             goal_get_loop_control_par_conjs(SubGoal, SelfPredProcId,
                 SeenUsableRecursion0)
+            % If the scope does a cut, then any recursion inside SubGoal
+            % is unusable, but the determinism check below will catch that.
         ;
             GoalExpr = if_then_else(_, Cond, Then, Else),
             goal_get_loop_control_par_conjs(Cond, SelfPredProcId,
@@ -315,12 +323,13 @@
                     SeenUsableRecursionThen, SeenUsableRecursionElse,
                     SeenUsableRecursion0)
             ;
-                % We can't make use of any recursion found in the condition of
-                % an if-then-else.
+                % We cannot make use of any recursion found in the condition
+                % of an if-then-else.
                 ( SeenUsableRecursionCond =
                         seen_one_recursive_call_on_every_branch
                 ; SeenUsableRecursionCond = seen_unusable_recursion
-                ; SeenUsableRecursionCond = seen_usable_recursion_in_par_conj(_)
+                ; SeenUsableRecursionCond =
+                    seen_usable_recursion_in_par_conj(_)
                 ),
                 SeenUsableRecursion0 = seen_unusable_recursion
             )
@@ -329,8 +338,8 @@
             unexpected($module, $pred, "shorthand")
         ),
 
-        % If the goal might fail or might succeed more than once then the
-        % recursion is unusable for loop control.
+        % If the goal might fail or might succeed more than once, then any
+        % recursion in it is unusable for loop control.
         (
             ( SeenUsableRecursion0 = have_not_seen_recursive_call
             ; SeenUsableRecursion0 = seen_unusable_recursion
@@ -344,7 +353,7 @@
                 ( Detism = detism_det
                 ; Detism = detism_cc_multi
                 ),
-                SeenUsableRecursion0 = SeenUsableRecursion
+                SeenUsableRecursion = SeenUsableRecursion0
             ;
                 ( Detism = detism_semi
                 ; Detism = detism_multi
@@ -363,9 +372,9 @@
 
     % Analyze the parallel conjunction for a usable recursive call.
     %
-    % If any but the last conjunct contain a recursive call then that call is
-    % unusable.  If only the last conjunct contains a recursive call then it is
-    % usable.
+    % If any but the last conjunct contains a recursive call, then that
+    % recursive call is unusable. If only the last conjunct contains
+    % a recursive call, then that recursion is usable.
     %
 :- pred par_conj_get_loop_control_par_conjs(list(hlds_goal)::in,
     pred_proc_id::in, goal_id::in, seen_usable_recursion::out) is det.
@@ -376,8 +385,8 @@
         Conjs = [],
         unexpected($module, $pred, "Empty parallel conjunction")
     ;
-        Conjs = [_ | _],
-        par_conj_get_loop_control_par_conjs_2(Conjs, SelfPredProcId,
+        Conjs = [Head | Tail],
+        par_conj_get_loop_control_par_conjs_lag(Head, Tail, SelfPredProcId,
             SeenUsableRecursion0),
         (
             SeenUsableRecursion0 = have_not_seen_recursive_call,
@@ -393,11 +402,10 @@
         )
     ).
 
-:- pred par_conj_get_loop_control_par_conjs_2(
-    list(hlds_goal)::in(non_empty_list), pred_proc_id::in,
-    seen_usable_recursion::out) is det.
+:- pred par_conj_get_loop_control_par_conjs_lag(hlds_goal::in,
+    list(hlds_goal)::in, pred_proc_id::in, seen_usable_recursion::out) is det.
 
-par_conj_get_loop_control_par_conjs_2([Conj | Conjs], SelfPredProcId,
+par_conj_get_loop_control_par_conjs_lag(Conj, Conjs, SelfPredProcId,
         SeenUsableRecursion) :-
     goal_get_loop_control_par_conjs(Conj, SelfPredProcId,
         SeenUsableRecursion0),
@@ -407,7 +415,7 @@
         Conjs = [],
         SeenUsableRecursion = SeenUsableRecursion0
     ;
-        Conjs = [_ | _],
+        Conjs = [Head | Tail],
         % This is not the last conjunct.  Therefore any recursion it contains
         % is unusable.
         (
@@ -419,7 +427,7 @@
         ;
             SeenUsableRecursion0 = have_not_seen_recursive_call,
             % Analyze the rest of the conjunction.
-            par_conj_get_loop_control_par_conjs_2(Conjs, SelfPredProcId,
+            par_conj_get_loop_control_par_conjs_lag(Head, Tail, SelfPredProcId,
                 SeenUsableRecursion)
         )
     ).
@@ -492,7 +500,8 @@
 merge_loop_control_par_conjs_between_branches_list([],
         have_not_seen_recursive_call).
 merge_loop_control_par_conjs_between_branches_list([Seen | Seens], Result) :-
-    foldl(merge_loop_control_par_conjs_between_branches, Seens, Seen, Result).
+    list.foldl(merge_loop_control_par_conjs_between_branches, Seens,
+        Seen, Result).
 
 :- pred merge_loop_control_par_conjs_between_branches(
     seen_usable_recursion::in, seen_usable_recursion::in,
@@ -583,7 +592,7 @@
     pred_info_get_class_context(OldPredInfo, ClassConstraints),
     pred_info_get_arg_types(OldPredInfo, ArgTypes0),
 
-    some [!PredInfo] (
+    some [!PredInfo, !Body, !VarSet, !VarTypes] (
         % Construct the pred info structure.  We initially construct it with
         % the old proc info which will be replaced below.
         pred_info_create(ModuleName, PredSym, PredOrFunc, Context, Origin,
@@ -599,17 +608,17 @@
         ),
         PredProcId = proc(PredId, ProcId),
 
-        % Now transform the predicate, this could not be done earlier because
+        % Now transform the predicate. This could not be done earlier because
         % we needed to know the new PredProcId to re-write the recursive calls
         % in the body.
         proc_info_get_argmodes(OldProcInfo, ArgModes0),
         proc_info_get_headvars(OldProcInfo, HeadVars0),
-        proc_info_get_varset(OldProcInfo, VarSet0),
-        proc_info_get_vartypes(OldProcInfo, VarTypes0),
-        proc_info_get_goal(OldProcInfo, Body0),
+        proc_info_get_varset(OldProcInfo, !:VarSet),
+        proc_info_get_vartypes(OldProcInfo, !:VarTypes),
+        proc_info_get_goal(OldProcInfo, !:Body),
 
-        varset.new_named_var("LC", LCVar, VarSet0, VarSet1),
-        map.det_insert(LCVar, loop_control_var_type, VarTypes0, VarTypes1),
+        varset.new_named_var("LC", LCVar, !VarSet),
+        map.det_insert(LCVar, loop_control_var_type, !VarTypes),
         should_preserve_tail_recursion(!.ModuleInfo, PreserveTailRecursion),
         get_lc_wait_free_slot_proc(!.ModuleInfo, WaitFreeSlotProc),
         get_lc_join_and_terminate_proc(!.ModuleInfo, JoinAndTerminateProc),
@@ -618,14 +627,12 @@
             PredProcId, PredSym, PreserveTailRecursion, WaitFreeSlotProc,
             lc_wait_free_slot_name, JoinAndTerminateProc,
             lc_join_and_terminate_name),
-        goal_loop_control_all_paths(Info, RecParConjIds,
-            ContainingGoalMap, Body0, Body1, VarSet1, VarSet,
-            VarTypes1, VarTypes),
+        goal_loop_control_all_recursive_paths(Info, RecParConjIds,
+            ContainingGoalMap, !Body, !VarSet, !VarTypes),
 
         % Fixup the remaining recursive calls, and add barriers in the base
         % cases.
-        goal_loop_control_fixup(Info, RecParConjIds, _,
-            Body1, Body),
+        goal_update_non_loop_control_paths(Info, RecParConjIds, _, !Body),
 
         % Now create the new proc_info structure.
         HeadVars = [LCVar | HeadVars0],
@@ -637,8 +644,8 @@
         proc_info_get_inst_varset(OldProcInfo, InstVarSet),
         proc_info_get_rtti_varmaps(OldProcInfo, RttiVarMaps),
         proc_info_get_inferred_determinism(OldProcInfo, Detism),
-        proc_info_create(Context, VarSet, VarTypes, HeadVars, InstVarSet,
-            ArgModes, detism_decl_none, Detism, Body, RttiVarMaps,
+        proc_info_create(Context, !.VarSet, !.VarTypes, HeadVars, InstVarSet,
+            ArgModes, detism_decl_none, Detism, !.Body, RttiVarMaps,
             address_is_not_taken, map.init, ProcInfo),
 
         % Update the other structures
@@ -680,21 +687,22 @@
     --->    preserve_tail_recursion
     ;       do_not_preserve_tail_recursion.
 
-:- pred goal_loop_control_all_paths(loop_control_info::in, list(goal_id)::in,
-    containing_goal_map::in, hlds_goal::in, hlds_goal::out,
+:- pred goal_loop_control_all_recursive_paths(loop_control_info::in,
+    list(goal_id)::in, containing_goal_map::in, hlds_goal::in, hlds_goal::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
 
-goal_loop_control_all_paths(Info, GoalIds, ContainingGoalMap, !Goal,
+goal_loop_control_all_recursive_paths(Info, GoalIds, ContainingGoalMap, !Goal,
         !VarSet, !VarTypes) :-
-    GoalPaths = map(goal_id_to_forward_path(ContainingGoalMap), GoalIds),
-    foldl3(goal_loop_control(Info), GoalPaths, !Goal, !VarSet,
-        !VarTypes).
+    GoalPaths = list.map(goal_id_to_forward_path(ContainingGoalMap), GoalIds),
+    list.foldl3(goal_loop_control_one_recursive_path(Info), GoalPaths,
+        !Goal, !VarSet, !VarTypes).
 
-:- pred goal_loop_control(loop_control_info::in, forward_goal_path::in,
-    hlds_goal::in, hlds_goal::out, prog_varset::in, prog_varset::out,
-    vartypes::in, vartypes::out) is det.
+:- pred goal_loop_control_one_recursive_path(loop_control_info::in,
+    forward_goal_path::in, hlds_goal::in, hlds_goal::out,
+    prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
 
-goal_loop_control(Info, GoalPath0, !Goal, !VarSet, !VarTypes) :-
+goal_loop_control_one_recursive_path(Info, GoalPath0, !Goal,
+        !VarSet, !VarTypes) :-
     !.Goal = hlds_goal(GoalExpr0, GoalInfo),
     ( goal_path_remove_first(GoalPath0, GoalPath, Step) ->
         format("Couldn't follow goal path step: \"%s\"", [s(string(Step))],
@@ -705,8 +713,8 @@
                 GoalExpr0 = conj(plain_conj, Conjs0),
                 list.index1(Conjs0, N, Conj0)
             ->
-                goal_loop_control(Info, GoalPath, Conj0, Conj,
-                    !VarSet, !VarTypes),
+                goal_loop_control_one_recursive_path(Info, GoalPath,
+                    Conj0, Conj, !VarSet, !VarTypes),
                 det_replace_nth(Conjs0, N, Conj, Conjs),
                 GoalExpr = conj(plain_conj, Conjs)
             ;
@@ -719,8 +727,8 @@
                 list.index1(Cases0, N, Case0)
             ->
                 Goal0 = Case0 ^ case_goal,
-                goal_loop_control(Info, GoalPath, Goal0, Goal,
-                    !VarSet, !VarTypes),
+                goal_loop_control_one_recursive_path(Info, GoalPath,
+                    Goal0, Goal, !VarSet, !VarTypes),
                 Case = Case0 ^ case_goal := Goal,
                 det_replace_nth(Cases0, N, Case, Cases),
                 GoalExpr = switch(Var, CanFail, Cases)
@@ -730,8 +738,8 @@
         ;
             Step = step_ite_then,
             ( GoalExpr0 = if_then_else(Vars, Cond, Then0, Else) ->
-                goal_loop_control(Info, GoalPath, Then0, Then,
-                    !VarSet, !VarTypes),
+                goal_loop_control_one_recursive_path(Info, GoalPath,
+                    Then0, Then, !VarSet, !VarTypes),
                 GoalExpr = if_then_else(Vars, Cond, Then, Else)
             ;
                 unexpected($module, $pred, ErrorString)
@@ -739,8 +747,8 @@
         ;
             Step = step_ite_else,
             ( GoalExpr0 = if_then_else(Vars, Cond, Then, Else0) ->
-                goal_loop_control(Info, GoalPath, Else0, Else,
-                    !VarSet, !VarTypes),
+                goal_loop_control_one_recursive_path(Info, GoalPath,
+                    Else0, Else, !VarSet, !VarTypes),
                 GoalExpr = if_then_else(Vars, Cond, Then, Else)
             ;
                 unexpected($module, $pred, ErrorString)
@@ -748,8 +756,8 @@
         ;
             Step = step_scope(_),
             ( GoalExpr0 = scope(Reason, SubGoal0) ->
-                goal_loop_control(Info, GoalPath, SubGoal0, SubGoal,
-                    !VarSet, !VarTypes),
+                goal_loop_control_one_recursive_path(Info, GoalPath,
+                    SubGoal0, SubGoal, !VarSet, !VarTypes),
                 GoalExpr = scope(Reason, SubGoal)
             ;
                 unexpected($module, $pred, ErrorString)
@@ -771,7 +779,7 @@
         fixup_goal_info(Info, !Goal)
     ;
         ( GoalExpr0 = conj(parallel_conj, Conjs) ->
-            par_conj_loop_control(Info, reverse(Conjs), GoalInfo, !:Goal,
+            par_conj_loop_control(Info, Conjs, GoalInfo, !:Goal,
                 !VarSet, !VarTypes)
         ;
             unexpected($module, $pred, "expected parallel conjunction")
@@ -782,57 +790,61 @@
     hlds_goal_info::in, hlds_goal::out, prog_varset::in, prog_varset::out,
     vartypes::in, vartypes::out) is det.
 
-par_conj_loop_control(_, [], _, _, !VarSet, !VarTypes) :-
-    unexpected($module, $pred, "empty parallel conjunction").
-par_conj_loop_control(Info, [LastConj0 | RevConjs], GoalInfo, Goal, !VarSet,
+par_conj_loop_control(Info, Conjuncts0, GoalInfo, Goal, !VarSet,
         !VarTypes) :-
+    list.det_split_last(Conjuncts0, EarlierConjuncts0, LastConjunct0),
     % Re-write the recursive call in the last conjunct.
-    goal_rewrite_recursive_call(Info, LastConj0, LastConj, _),
-    goal_to_conj_list(LastConj, LastConjGoals),
+    goal_rewrite_recursive_call(Info, LastConjunct0, LastConjunct, _),
+    goal_to_conj_list(LastConjunct, LastConjGoals),
 
     % Process the remaining conjuncts.
-    par_conj_loop_control2(Info, RevConjs, LastConjGoals, Goals, !VarSet,
-        !VarTypes),
-    create_conj_from_list(Goals, plain_conj, Goal0),
+    rewrite_nonrecursive_par_conjuncts(Info,
+        EarlierConjuncts0, EarlierConjuncts, !VarSet, !VarTypes),
+    Conjuncts = EarlierConjuncts ++ LastConjGoals,
+    % XXX The point of calling create_conj_from_list is that it sets up
+    % the goal_info of Goal0 appropriately. Why call it if we then immediately
+    % overwrite the goal_info?
+    create_conj_from_list(Conjuncts, plain_conj, Goal0),
     Goal1 = Goal0 ^ hlds_goal_info := GoalInfo,
     fixup_goal_info(Info, Goal1, Goal).
 
     % Process each of the conjuncts in reverse order, building the new
     % expression from them.
     %
-:- pred par_conj_loop_control2(loop_control_info::in, list(hlds_goal)::in,
+:- pred rewrite_nonrecursive_par_conjuncts(loop_control_info::in,
     list(hlds_goal)::in, list(hlds_goal)::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
 
-par_conj_loop_control2(_, [], LaterGoals, LaterGoals, !VarSet, !VarTypes).
-par_conj_loop_control2(Info, [Conj0 | RevConjs], LaterGoals, Goals, !VarSet,
-        !VarTypes) :-
+rewrite_nonrecursive_par_conjuncts(_, [], [], !VarSet, !VarTypes).
+rewrite_nonrecursive_par_conjuncts(Info, [Conjunct0 | Conjuncts0], Goals,
+        !VarSet, !VarTypes) :-
     % Create the "get free slot" call..
-    create_get_free_slot_goal(Info, LCSVar, GetFreeSlotGoal, !VarSet,
-        !VarTypes),
+    create_get_free_slot_goal(Info, LCSVar, GetFreeSlotGoal,
+        !VarSet, !VarTypes),
 
     % Add a join_and_terminate goal to the end of Conj0 forming Conj.
-    create_join_and_termiate_goal(Info, LCVar, LCSVar, JoinAndTermiateGoal),
-    Conj0GoalInfo = Conj0 ^ hlds_goal_info,
-    goal_to_conj_list(Conj0, Conj0Goals),
-    ConjGoals = Conj0Goals ++ [JoinAndTermiateGoal],
+    create_join_and_terminate_goal(Info, LCVar, LCSVar, JoinAndTerminateGoal),
+    Conjunct0GoalInfo = Conjunct0 ^ hlds_goal_info,
+    goal_to_conj_list(Conjunct0, Conjunct0Goals),
+    ConjunctGoals = Conjunct0Goals ++ [JoinAndTerminateGoal],
     some [!NonLocals] (
-        !:NonLocals = goal_info_get_nonlocals(Conj0GoalInfo),
-        insert(LCSVar, !NonLocals),
-        insert(LCVar, !NonLocals),
-        goal_info_set_nonlocals(!.NonLocals, Conj0GoalInfo, ConjGoalInfo)
+        !:NonLocals = goal_info_get_nonlocals(Conjunct0GoalInfo),
+        set_of_var.insert(LCSVar, !NonLocals),
+        set_of_var.insert(LCVar, !NonLocals),
+        goal_info_set_nonlocals(!.NonLocals,
+            Conjunct0GoalInfo, ConjunctGoalInfo)
     ),
-    conj_list_to_goal(ConjGoals, ConjGoalInfo, Conj),
+    conj_list_to_goal(ConjunctGoals, ConjunctGoalInfo, Conjunct),
 
-    % Wrap Conj in the loop control scope.
+    % Wrap Conjunct in the loop control scope.
     LCVar = Info ^ lci_lc_var,
-    ScopeGoalInfo = ConjGoalInfo,
-    ScopeGoal = hlds_goal(scope(loop_control(LCVar, LCSVar), Conj),
-        ScopeGoalInfo),
-
-    % Process earlier conjuncts.
-    Goals0 = [GetFreeSlotGoal, ScopeGoal | LaterGoals],
-    par_conj_loop_control2(Info, RevConjs, Goals0, Goals, !VarSet, !VarTypes).
+    ScopeGoalInfo = ConjunctGoalInfo,
+    ScopeGoalExpr = scope(loop_control(LCVar, LCSVar), Conjunct),
+    ScopeGoal = hlds_goal(ScopeGoalExpr, ScopeGoalInfo),
+
+    rewrite_nonrecursive_par_conjuncts(Info, Conjuncts0, TailGoals,
+        !VarSet, !VarTypes),
+    Goals = [GetFreeSlotGoal, ScopeGoal | TailGoals].
 
     % Re-write any recursive calls in this goal.
     %
@@ -871,31 +883,29 @@
         )
     ;
         GoalExpr0 = conj(ConjType, Conjs0),
-        map2(goal_rewrite_recursive_call(Info), Conjs0, Conjs,
+        list.map2(goal_rewrite_recursive_call(Info), Conjs0, Conjs,
             FixupGoalInfoConjs),
         goals_fixup_goal_info(FixupGoalInfoConjs, FixupGoalInfo),
         GoalExpr = conj(ConjType, Conjs)
     ;
         GoalExpr0 = disj(Disjs0),
-        map2(goal_rewrite_recursive_call(Info), Disjs0, Disjs,
+        list.map2(goal_rewrite_recursive_call(Info), Disjs0, Disjs,
             FixupGoalInfoDisjs),
         goals_fixup_goal_info(FixupGoalInfoDisjs, FixupGoalInfo),
         GoalExpr = disj(Disjs)
     ;
         GoalExpr0 = switch(Var, CanFail, Cases0),
-        map2(case_rewrite_recursive_call(Info), Cases0, Cases,
+        list.map2(case_rewrite_recursive_call(Info), Cases0, Cases,
             FixupGoalInfoCases),
         goals_fixup_goal_info(FixupGoalInfoCases, FixupGoalInfo),
         GoalExpr = switch(Var, CanFail, Cases)
     ;
         GoalExpr0 = negation(SubGoal0),
-        goal_rewrite_recursive_call(Info, SubGoal0, SubGoal,
-            FixupGoalInfo),
+        goal_rewrite_recursive_call(Info, SubGoal0, SubGoal, FixupGoalInfo),
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        goal_rewrite_recursive_call(Info, SubGoal0, SubGoal,
-            FixupGoalInfo),
+        goal_rewrite_recursive_call(Info, SubGoal0, SubGoal, FixupGoalInfo),
         GoalExpr = scope(Reason, SubGoal)
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
@@ -951,18 +961,20 @@
     %     conjunctions so that they call the inner procedure and pass the loop
     %     control variable.
     %
-:- pred goal_loop_control_fixup(loop_control_info::in,
+:- pred goal_update_non_loop_control_paths(loop_control_info::in,
     list(goal_id)::in, fixup_goal_info::out,
     hlds_goal::in, hlds_goal::out) is det.
 
-goal_loop_control_fixup(Info, RecParConjIds, FixupGoalInfo, !Goal) :-
+goal_update_non_loop_control_paths(Info, RecParConjIds, FixupGoalInfo,
+        !Goal) :-
     GoalInfo0 = !.Goal ^ hlds_goal_info,
     GoalId = goal_info_get_goal_id(GoalInfo0),
     (
-        % This goal is one of the trasnformed parallel conjunctions, nothing
-        % needs to be done.
-        % XXX: This may not work, I don't know if the goal ID is maintained.
-        member(GoalId, RecParConjIds)
+        % This goal is one of the transformed parallel conjunctions,
+        % nothing needs to be done.
+        % XXX What if the last conjunct contains a base case?
+        % XXX This may not work, I don't know if the goal ID is maintained.
+        list.member(GoalId, RecParConjIds)
     ->
         FixupGoalInfo = do_not_fixup_goal_info
     ;
@@ -990,7 +1002,7 @@
             ; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
             ),
             % These cannot be a recursive call and they cannot be a base case
-            % since that is detected above.
+            % since base cases are detected above.
             unexpected($module, $pred, "Non-recursive atomic goal")
         ;
             GoalExpr0 = plain_call(PredId, ProcId, Args0, Builtin,
@@ -1008,16 +1020,18 @@
             FixupGoalInfo = fixup_goal_info
         ;
             GoalExpr0 = conj(ConjType, Conjs0),
-            conj_loop_control_fixup(Info, RecParConjIds, FixupGoalInfo,
-                Conjs0, Conjs),
+            expect(unify(ConjType, plain_conj), $module, $pred,
+                "parallel conjunction"),
+            conj_update_non_loop_control_paths(Info, RecParConjIds,
+                FixupGoalInfo, Conjs0, Conjs),
             GoalExpr = conj(ConjType, Conjs)
         ;
             GoalExpr0 = disj(_),
             sorry($module, $pred, "disjunction")
         ;
             GoalExpr0 = switch(Var, CanFail, Cases0),
-            map2(case_loop_control_fixup(Info, RecParConjIds), Cases0, Cases,
-                FixupGoalInfos),
+            list.map2(case_update_non_loop_control_paths(Info, RecParConjIds),
+                Cases0, Cases, FixupGoalInfos),
             goals_fixup_goal_info(FixupGoalInfos, FixupGoalInfo),
             GoalExpr = switch(Var, CanFail, Cases)
         ;
@@ -1025,15 +1039,17 @@
             sorry($module, $pred, "negation")
         ;
             GoalExpr0 = scope(Reason, SubGoal0),
-            goal_loop_control_fixup(Info, RecParConjIds, FixupGoalInfo,
-                SubGoal0, SubGoal),
+            goal_update_non_loop_control_paths(Info, RecParConjIds,
+                FixupGoalInfo, SubGoal0, SubGoal),
             GoalExpr = scope(Reason, SubGoal)
         ;
             GoalExpr0 = if_then_else(ExistVars, Cond, Then0, Else0),
-            goal_loop_control_fixup(Info, RecParConjIds, FixupGoalInfoThen,
-                Then0, Then),
-            goal_loop_control_fixup(Info, RecParConjIds, FixupGoalInfoElse,
-                Else0, Else),
+            % There may not be any recursive calls in Cond; if there are,
+            % we don not apply the transformation.
+            goal_update_non_loop_control_paths(Info, RecParConjIds,
+                FixupGoalInfoThen, Then0, Then),
+            goal_update_non_loop_control_paths(Info, RecParConjIds,
+                FixupGoalInfoElse, Else0, Else),
             goals_fixup_goal_info([FixupGoalInfoThen, FixupGoalInfoElse],
                 FixupGoalInfo),
             GoalExpr = if_then_else(ExistVars, Cond, Then, Else)
@@ -1047,7 +1063,7 @@
             some [!NonLocals, !GoalInfo] (
                 !:GoalInfo = !.Goal ^ hlds_goal_info,
                 !:NonLocals = goal_info_get_nonlocals(!.GoalInfo),
-                insert(Info ^ lci_lc_var, !NonLocals),
+                set_of_var.insert(Info ^ lci_lc_var, !NonLocals),
                 goal_info_set_nonlocals(!.NonLocals, !GoalInfo),
                 goal_info_set_purity(purity_impure, !GoalInfo),
                 !Goal ^ hlds_goal_info := !.GoalInfo
@@ -1057,37 +1073,54 @@
         )
     ).
 
-:- pred conj_loop_control_fixup(loop_control_info::in, list(goal_id)::in,
-    fixup_goal_info::out, list(hlds_goal)::in, list(hlds_goal)::out) is det.
+    % As goal_update_non_loop_control_paths, but for a conjunction.
+    %
+:- pred conj_update_non_loop_control_paths(loop_control_info::in,
+    list(goal_id)::in, fixup_goal_info::out,
+    list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
-conj_loop_control_fixup(_Info, _RecGoalIds, do_not_fixup_goal_info, [], []).
-conj_loop_control_fixup(Info, RecGoalIds, FixupGoalInfo,
-        [!.Conj | !.Conjs], [!:Conj | !:Conjs]) :-
-    (
-        not goal_calls(!.Conj, Callee),
-        (
+conj_update_non_loop_control_paths(_Info, _RecGoalIds, do_not_fixup_goal_info,
+        [], []).
+conj_update_non_loop_control_paths(Info, RecGoalIds, FixupGoalInfo,
+        [Conj0 | Conjs0], [Conj | Conjs]) :-
+    (
+        not goal_calls(Conj0, Callee),
+        (
+            % XXX At the moment, we require that all recursive calls be
+            % inside parallel conjunctions, and all those recursive calls
+            % have by now been transformed to call the inner procedure instead.
+            % So the first part of this disjunction cannot succeed.
             Callee = Info ^ lci_rec_pred_proc_id
         ;
             Callee = Info ^ lci_inner_pred_proc_id
         )
     ->
-        % This Conj does not make a recursive call or contain a recursive
+        % Conj0 does not make a recursive call or contain a recursive
         % parallel conjunction.  We don't need to transform it.
-        conj_loop_control_fixup(Info, RecGoalIds, FixupGoalInfo, !Conjs)
+        Conj = Conj0,
+        conj_update_non_loop_control_paths(Info, RecGoalIds, FixupGoalInfo,
+            Conjs0, Conjs)
     ;
         % This Conj has something that needs to be transformed.
-        goal_loop_control_fixup(Info, RecGoalIds, FixupGoalInfo, !Conj)
-        % There's not going to be anything else in this conjunct that needs to
-        % be transformed, we don't make a recursive call.
+        goal_update_non_loop_control_paths(Info, RecGoalIds, FixupGoalInfo,
+            Conj0, Conj),
+        % There is not going to be anything else in this conjunct
+        % that needs to be transformed, we don't make a recursive call.
+        Conjs = Conjs0
     ).
 
-:- pred case_loop_control_fixup(loop_control_info::in, list(goal_id)::in,
-    case::in, case::out, fixup_goal_info::out) is det.
+    % As goal_update_non_loop_control_paths, but for a case.
+    % Note that this argument order is needed by a higher order call above.
+    %
+:- pred case_update_non_loop_control_paths(loop_control_info::in,
+    list(goal_id)::in, case::in, case::out, fixup_goal_info::out) is det.
 
-case_loop_control_fixup(Info, RecParConjIds, !Case, FixupGoalInfo) :-
+case_update_non_loop_control_paths(Info, RecParConjIds, !Case,
+        FixupGoalInfo) :-
     some [!Goal] (
         !:Goal = !.Case ^ case_goal,
-        goal_loop_control_fixup(Info, RecParConjIds, FixupGoalInfo, !Goal),
+        goal_update_non_loop_control_paths(Info, RecParConjIds,
+            FixupGoalInfo, !Goal),
         !Case ^ case_goal := !.Goal
     ).
 
@@ -1123,20 +1156,18 @@
     varset.new_named_var("LC", LCVar, !VarSet),
     map.det_insert(LCVar, loop_control_var_type, !VarTypes),
     get_lc_create_proc(ModuleInfo, LCCreatePredId, LCCreateProcId),
-    goal_info_init(list_to_set([NumContextsVar, LCVar]),
-        instmap_delta_bind_var(LCVar), detism_det, purity_pure,
-        LCCreateGoalInfo),
-    Goal = hlds_goal(plain_call(LCCreatePredId,
-            LCCreateProcId, [NumContextsVar, LCVar], not_builtin, no,
-            lc_create_name),
-        LCCreateGoalInfo).
+    GoalExpr = plain_call(LCCreatePredId, LCCreateProcId,
+        [NumContextsVar, LCVar], not_builtin, no, lc_create_name),
+    goal_info_init(set_of_var.list_to_set([NumContextsVar, LCVar]),
+        instmap_delta_bind_var(LCVar), detism_det, purity_pure, GoalInfo),
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
 %----------------------------------------------------------------------------%
 
-:- pred create_join_and_termiate_goal(loop_control_info::in, prog_var::in,
+:- pred create_join_and_terminate_goal(loop_control_info::in, prog_var::in,
     prog_var::in, hlds_goal::out) is det.
 
-create_join_and_termiate_goal(Info, LCVar, LCSVar, Goal) :-
+create_join_and_terminate_goal(Info, LCVar, LCSVar, Goal) :-
     proc(PredId, ProcId) = Info ^ lci_join_and_terminate_proc,
     SymName = Info ^ lci_join_and_terminate_proc_name,
 
@@ -1174,15 +1205,19 @@
 :- pred fixup_goal_info(loop_control_info::in, hlds_goal::in, hlds_goal::out)
     is det.
 
-fixup_goal_info(Info, hlds_goal(GoalExpr, !.GoalInfo),
-        hlds_goal(GoalExpr, !:GoalInfo)) :-
+fixup_goal_info(Info, Goal0, Goal) :-
+    some [!GoalInfo, !NonLocals] (
+        Goal0 = hlds_goal(GoalExpr, !:GoalInfo),
+
     LCVar = Info ^ lci_lc_var,
-    some [!NonLocals] (
         !:NonLocals = goal_info_get_nonlocals(!.GoalInfo),
-        insert(LCVar, !NonLocals),
-        goal_info_set_nonlocals(!.NonLocals, !GoalInfo)
-    ),
-    goal_info_set_purity(purity_impure, !GoalInfo).
+        set_of_var.insert(LCVar, !NonLocals),
+        goal_info_set_nonlocals(!.NonLocals, !GoalInfo),
+
+        goal_info_set_purity(purity_impure, !GoalInfo),
+
+        Goal = hlds_goal(GoalExpr, !.GoalInfo)
+    ).
 
 %----------------------------------------------------------------------------%
 
@@ -1216,13 +1251,13 @@
 
         % Create a variable for the number of worker contexts, we control this
         % in the compiler so that it can be adjusted using profiler feedback
-        % (for auto-parallelisation), but for now we just set it using a runtime
-        % call so that it can be tuned.
+        % (for auto-parallelisation), but for now we just set it using
+        % a runtime call so that it can be tuned.
         varset.new_named_var("NumContexts", NumContextsVar, !VarSet),
         map.det_insert(NumContextsVar, builtin_type(builtin_type_int),
             !VarTypes),
-        get_lc_default_num_contexts_proc(ModuleInfo, LCDefaultNumContextsPredId,
-            LCDefaultNumContextsProcId),
+        get_lc_default_num_contexts_proc(ModuleInfo,
+            LCDefaultNumContextsPredId, LCDefaultNumContextsProcId),
         goal_info_init(list_to_set([NumContextsVar]),
             instmap_delta_bind_var(NumContextsVar),
             detism_det, purity_pure, GetNumContextsGoalInfo),
cvs diff: Diffing compiler/notes
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
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/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/fixed
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_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_cairo
cvs diff: Diffing extras/graphics/mercury_cairo/samples
cvs diff: Diffing extras/graphics/mercury_cairo/samples/data
cvs diff: Diffing extras/graphics/mercury_cairo/tutorial
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/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/monte
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
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/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
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/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
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/appengine
cvs diff: Diffing samples/appengine/war
cvs diff: Diffing samples/appengine/war/WEB-INF
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/c_interface/standalone_c
cvs diff: Diffing samples/concurrency
cvs diff: Diffing samples/concurrency/dining_philosophers
cvs diff: Diffing samples/concurrency/midimon
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/java_interface
cvs diff: Diffing samples/java_interface/java_calls_mercury
cvs diff: Diffing samples/java_interface/mercury_calls_java
cvs diff: Diffing samples/lazy_list
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
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 ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
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
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
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