[m-rev.] for post-commit review: Refactor profiler feedback code for implicit parallelism.

Paul Bone pbone at csse.unimelb.edu.au
Sun Jul 4 20:20:11 AEST 2010


For post commit review by Zoltan, and possibly Ian for compiler/prog_rep.m

Zoltan and I discussed adding a some tests for the feedback tool.  I have
choosen not do to that in this commit, but I home to do it soon.

---

Refactor profiler feedback code for implicit parallelism.

This change mostly re-factors the goal representation used to feedback implicit
parallelism information to the compiler.  The goal_rep datatype is now used
rather than the much simpler datatype.  (goal_rep is the same type that is used
by the declarative debugger).

This makes it easier for the compiler to match HLDS goals against goals from
the implicit parallelism analysis and will probably help in the future if the
analysis wants the compiler to re-order goals.

It also makes it easier to pretty-print the feedback sent to the compiler in
more detail.

mdbcomp/feedback.m:
    As above, redefine pard_goal as a type alias to
    goal_rep(pard_goal_annotation).
    
    Added a new type, candidate_par_conjunctions_proc, it represents candidate
    parallelisations within a procedure along with shared information for the
    procedure.

    Add a new predicate, convert_candidate_par_conjunctions_proc.

    Increment the feedback file format version number.

mdbcomp/program_representation.m:
    XXX: See about refactoring bytecode in/out put into one place.

    Add a new predicate transform_goal_rep for transforming a goal_rep
    structure from one arbitrary annotation type to another.

    Add extra predicates to aid in converting a prog_rep structure to and from
    bytecode.  This includes cut_byte/2 and can_fail_byte/2.

deep_profiler/program_representation_utils.m:
    Export print_goal_to_strings/4 so that it can be used when printing the
    feedback file reports. 

deep_profiler/mdprof_fb.automatic_parallelism.m:
    Conform to changes in mdbcomp/feedback.m

    Wrap some lines at 76 characters.

    Improve explanations in comments.

    Use the goal_rep pretty-printer to print the candidate parallel
    conjunctions feedback report.

deep_profiler/mdprof_feedback.m:
    Conform to changes in deep_profiler/mdprof_fb.automatic_parallelism.m

deep_profiler/program_representation_utils.m:
    Modify print_goal_to_strings to print determinisms and annotations on
    separate lines before each goal.

deep_profiler/display_report.m:
    Modify pretty printing of coverage annotations so that they make sense
    after modifying print_goal_to_strings/4. 

compiler/implicit_parallelism.m:
    Refactor goal matching code that compares HLDS goals to feedback goals.
    Goal matching is now more accurate and can more easily support goal
    re-ordering when parallelising code (this is not implemented yet).

    The code that builds parallel conjunctions has also been refactored.

    This pass now generates warnings if it is not able to parallelise 
    a candidate parallel conjunction in the feedback data.

    Insert deeper and later parallelizations before shallower or earlier ones,
    this makes it easier to continue to parallelise a procedure as it's goal
    tree changes due to parallelisation.

    Silently ignore duplicate candidate parallel conjunctions.

    Refuse to parallelise a procedure that has been parallelized explicitly.

compiler/prog_rep.m:
    Re-factor the hlds_goal to bytecode transformation, this transformation now
    goes via goal_rep.  We use the hlds_goal to goal_rep portion of this
    transformation in compiler/implicit_parallelism.m.

    Add variable names prefixed with DCG_ to the list of those introduced by
    the compiler.

compiler/goal_util.m:
    Modify maybe_transform_goal_at_goal_path so that it returns a value that
    can describe the different kinds of error that may be encountered.

    Add a new predicate, maybe_transform_goal_at_goal_path_with_instmap.  Given
    a goal, goal path and initial inst map this predicate recurses the goal
    structure following the goal path and maintaining the inst map.  It then
    uses a higher order value to transform the goal at it's destination before
    re-constructing the goal.  It is different to
    maybe_transform_goal_at_goal_path in that it passes the instmap to it's
    higher order argument, the instmap is correct for the state immediately
    before executing the goal in question.

compiler/hlds_pred.m:
    Include the procedure's varset in the information used to construct the
    program representation data that is included in deep profiling builds.

compiler/instmap.m:
    Add a useful function, apply_instmap_delta_sv.  This is the same as
    apply_instmap_delta except that it's arguments are in a more convenient
    order for state variable notation.

compiler/stack_layout.m:
    Export compute_var_number_map for the use of implicit_parallelism.m and
    prog_rep.m

compiler/error_util.m:
    Add a new error phase, 'phase_auto_parallelism'.  This is used for warnings
    issued from the automatic parallelisation transformation.

compiler/deep_profiling.m:
    Conform to changes in hlds_pred.m

compiler/mercury_compile_middle_passes.m:
    Conform to changes in implicit_parallelism.m

compiler/type_constraints.m:
    Conform to changes in goal_util.

Index: compiler/deep_profiling.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/deep_profiling.m,v
retrieving revision 1.102
diff -u -p -b -r1.102 deep_profiling.m
--- compiler/deep_profiling.m	4 Nov 2009 03:44:46 -0000	1.102
+++ compiler/deep_profiling.m	30 Jun 2010 12:41:15 -0000
@@ -572,8 +572,9 @@ make_deep_original_body(ModuleInfo, Proc
         MaybeDetism = no,
         proc_info_get_inferred_determinism(ProcInfo, Detism)
     ),
+    proc_info_get_varset(ProcInfo, Varset),
     DeepOriginalBody = deep_original_body(Body, HeadVars, Instmap, Vartypes,
-        Detism).
+        Detism, Varset).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/error_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/error_util.m,v
retrieving revision 1.73
diff -u -p -b -r1.73 error_util.m
--- compiler/error_util.m	30 Mar 2010 23:57:25 -0000	1.73
+++ compiler/error_util.m	1 Jul 2010 23:45:44 -0000
@@ -117,6 +117,7 @@
     ;       phase_dead_code
     ;       phase_termination_analysis
     ;       phase_accumulator_intro
+    ;       phase_auto_parallelism
     ;       phase_interface_gen
     ;       phase_code_gen.
 
@@ -669,6 +670,7 @@ get_maybe_mode_report_control(phase_simp
 get_maybe_mode_report_control(phase_dead_code) = no.
 get_maybe_mode_report_control(phase_termination_analysis) = no.
 get_maybe_mode_report_control(phase_accumulator_intro) = no.
+get_maybe_mode_report_control(phase_auto_parallelism) = no.
 get_maybe_mode_report_control(phase_interface_gen) = no.
 get_maybe_mode_report_control(phase_code_gen) = no.
 
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.172
diff -u -p -b -r1.172 goal_util.m
--- compiler/goal_util.m	9 Jan 2010 05:49:41 -0000	1.172
+++ compiler/goal_util.m	1 Jul 2010 06:03:25 -0000
@@ -407,16 +407,33 @@
 
 %-----------------------------------------------------------------------------%
 
+:- type maybe_transformed_goal
+    --->    ok(hlds_goal)
+    ;       error(string)
+    ;       goal_not_found.
+
     % Locate the goal described by the goal path and use its first argument to
     % transform that goal before rebuilding the goal tree and returning.  If
     % the goal is not found the result is no.  If the result of the higher
     % order argument is no then the result is no.
     %
-:- pred maybe_transform_goal_at_goal_path(pred(hlds_goal, maybe(hlds_goal)),
-    goal_path_consable, hlds_goal, maybe(hlds_goal)). 
+:- pred maybe_transform_goal_at_goal_path(
+    pred(hlds_goal, maybe_error(hlds_goal)),
+    goal_path_consable, hlds_goal, maybe_transformed_goal). 
 :- mode maybe_transform_goal_at_goal_path(pred(in, out) is det,
     in, in, out) is det.
 
+    % As above, except that we also compute the instmap during the traversal so
+    % that the transformation expressed by the higher order value can use the
+    % instmap at that point within the goal tree. 
+    %
+:- pred maybe_transform_goal_at_goal_path_with_instmap(
+    pred(instmap, hlds_goal, maybe_error(hlds_goal)), 
+    goal_path_consable, instmap, hlds_goal, maybe_transformed_goal). 
+:- mode maybe_transform_goal_at_goal_path_with_instmap(
+    pred(in, in, out) is det, 
+    in, in, in, out) is det.
+
     % Transform the given goal and all it's children according to the higher
     % order argument.  Children are transformed before their parents, therefore
     % the higher order argument will receive a goal with children that have
@@ -1955,7 +1972,7 @@ maybe_transform_goal_at_goal_path(Transf
             ; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
             ),
             % This search should never reach an atomic goal.
-            MaybeGoalExpr = no
+            MaybeGoal = goal_not_found 
         ;
             GoalExpr0 = conj(ConjType, Conjs0),
             (
@@ -1965,15 +1982,18 @@ maybe_transform_goal_at_goal_path(Transf
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     Conj0, MaybeConj),
                 (
-                    MaybeConj = yes(Conj),
+                    MaybeConj = ok(Conj),
                     list.replace_nth_det(Conjs0, ConjNum, Conj, Conjs),
-                    MaybeGoalExpr = yes(conj(ConjType, Conjs))
+                    GoalExpr = conj(ConjType, Conjs),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeConj = no,
-                    MaybeGoalExpr = no
+                    ( MaybeConj = error(_)
+                    ; MaybeConj = goal_not_found
+                    ),
+                    MaybeGoal = MaybeConj 
                 )
             ;
-                MaybeGoalExpr = no
+                MaybeGoal = goal_not_found 
             )
         ;
             GoalExpr0 = disj(Disjs0),
@@ -1984,15 +2004,18 @@ maybe_transform_goal_at_goal_path(Transf
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     Disj0, MaybeDisj),
                 (
-                    MaybeDisj = yes(Disj),
+                    MaybeDisj = ok(Disj),
                     list.replace_nth_det(Disjs0, DisjNum, Disj, Disjs),
-                    MaybeGoalExpr = yes(disj(Disjs))
+                    GoalExpr = disj(Disjs),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeDisj = no,
-                    MaybeGoalExpr = no
+                    ( MaybeDisj = error(_)
+                    ; MaybeDisj = goal_not_found
+                    ),
+                    MaybeGoal = MaybeDisj
                 )
             ;
-                MaybeGoalExpr = no
+                MaybeGoal = goal_not_found 
             )
         ;
             GoalExpr0 = switch(Var, CanFail, Cases0),
@@ -2004,16 +2027,19 @@ maybe_transform_goal_at_goal_path(Transf
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     CaseGoal0, MaybeCaseGoal),
                 (
-                    MaybeCaseGoal = yes(CaseGoal),
+                    MaybeCaseGoal = ok(CaseGoal),
                     Case = Case0 ^ case_goal := CaseGoal,
                     list.replace_nth_det(Cases0, CaseNum, Case, Cases),
-                    MaybeGoalExpr = yes(switch(Var, CanFail, Cases))
+                    GoalExpr = switch(Var, CanFail, Cases),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeCaseGoal = no,
-                    MaybeGoalExpr = no
+                    ( MaybeCaseGoal = error(_)
+                    ; MaybeCaseGoal = goal_not_found
+                    ),
+                    MaybeGoal = MaybeCaseGoal 
                 )
             ;
-                MaybeGoalExpr = no
+                MaybeGoal = goal_not_found 
             )
         ;
             GoalExpr0 = negation(SubGoal0),
@@ -2021,14 +2047,16 @@ maybe_transform_goal_at_goal_path(Transf
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     SubGoal0, MaybeSubGoal),
                 (
-                    MaybeSubGoal = yes(SubGoal),
-                    MaybeGoalExpr = yes(negation(SubGoal))
+                    MaybeSubGoal = ok(SubGoal),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := negation(SubGoal))
                 ;
-                    MaybeSubGoal = no,
-                    MaybeGoalExpr = no
+                    ( MaybeSubGoal = error(_)
+                    ; MaybeSubGoal = goal_not_found
+                    ),
+                    MaybeGoal = MaybeSubGoal
                 )
             ;
-                MaybeGoalExpr = no
+                MaybeGoal = goal_not_found 
             )
         ;
             GoalExpr0 = scope(Reason, SubGoal0),
@@ -2036,14 +2064,17 @@ maybe_transform_goal_at_goal_path(Transf
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     SubGoal0, MaybeSubGoal),
                 (
-                    MaybeSubGoal = yes(SubGoal),
-                    MaybeGoalExpr = yes(scope(Reason, SubGoal))
+                    MaybeSubGoal = ok(SubGoal),
+                    GoalExpr = scope(Reason, SubGoal),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeSubGoal = no,
-                    MaybeGoalExpr = no
+                    ( MaybeSubGoal = error(_)
+                    ; MaybeSubGoal = goal_not_found
+                    ),
+                    MaybeGoal = MaybeSubGoal
                 )
             ;
-                MaybeGoalExpr = no
+                MaybeGoal = goal_not_found 
             )
         ;
             GoalExpr0 = if_then_else(ExistVars, Cond0, Then0, Else0),
@@ -2051,54 +2082,241 @@ maybe_transform_goal_at_goal_path(Transf
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     Cond0, MaybeCond),
                 (
-                    MaybeCond = yes(Cond),
-                    MaybeGoalExpr = yes(if_then_else(ExistVars, Cond, Then0,
-                        Else0))
+                    MaybeCond = ok(Cond),
+                    GoalExpr = if_then_else(ExistVars, Cond, Then0, Else0),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeCond = no,
-                    MaybeGoalExpr = no
+                    ( MaybeCond = error(_)
+                    ; MaybeCond = goal_not_found
+                    ),
+                    MaybeGoal = MaybeCond 
                 )
             ; Step = step_ite_then ->
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     Then0, MaybeThen),
                 (
-                    MaybeThen = yes(Then),
-                    MaybeGoalExpr = yes(if_then_else(ExistVars, Cond0, Then,
-                        Else0))
+                    MaybeThen = ok(Then),
+                    GoalExpr = if_then_else(ExistVars, Cond0, Then, Else0),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeThen = no,
-                    MaybeGoalExpr = no
+                    ( MaybeThen = error(_)
+                    ; MaybeThen = goal_not_found
+                    ),
+                    MaybeGoal = MaybeThen 
                 )
             ; Step = step_ite_else ->
                 maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
                     Else0, MaybeElse),
                 (
-                    MaybeElse = yes(Else),
-                    MaybeGoalExpr = yes(if_then_else(ExistVars, Cond0, Then0,
-                        Else))
+                    MaybeElse = ok(Else),
+                    GoalExpr = if_then_else(ExistVars, Cond0, Then0, Else),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
                 ;
-                    MaybeElse = no,
-                    MaybeGoalExpr = no
+                    ( MaybeElse = error(_)
+                    ; MaybeElse = goal_not_found
+                    ),
+                    MaybeGoal = MaybeElse 
                 )
             ;
-                MaybeGoalExpr = no
+                MaybeGoal = goal_not_found
             )
         ;
             GoalExpr0 = shorthand(_),
             unexpected(this_file, 
                 "Shorthand goals should have been eliminated already")
+        )
+    ;
+        TransformP(Goal0, MaybeGoal0),
+        maybe_error_to_maybe_transformed_goal(MaybeGoal0, MaybeGoal)
+    ).
+
+maybe_transform_goal_at_goal_path_with_instmap(TransformP, TargetGoalPath0,
+        Instmap0, Goal0, MaybeGoal) :-
+    (
+        goal_path_consable_remove_first(TargetGoalPath0, Step, TargetGoalPath)
+    ->
+        GoalExpr0 = Goal0 ^ hlds_goal_expr,  
+        (
+            ( GoalExpr0 = unify(_, _, _, _, _) 
+            ; GoalExpr0 = plain_call(_, _, _, _, _, _)
+            ; GoalExpr0 = generic_call(_, _, _, _)
+            ; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
+            ),
+            % This search should never reach an atomic goal.
+            MaybeGoal = goal_not_found
+        ;
+            GoalExpr0 = conj(ConjType, Conjs0),
+            (
+                Step = step_conj(ConjNum),
+                list.index1(Conjs0, ConjNum, Conj0)
+            ->
+                list.take_upto(ConjNum - 1, Conjs0, HeadConjs),
+                HeadInstdeltas = map(
+                    (func(G) = goal_info_get_instmap_delta(G ^ hlds_goal_info)),
+                    HeadConjs),
+                foldl(apply_instmap_delta_sv, HeadInstdeltas, 
+                    Instmap0, Instmap),
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP, 
+                    TargetGoalPath, Instmap, Conj0, MaybeConj),
+                (
+                    MaybeConj = ok(Conj),
+                    list.replace_nth_det(Conjs0, ConjNum, Conj, Conjs),
+                    GoalExpr = conj(ConjType, Conjs),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeConj = error(_)
+                    ; MaybeConj = goal_not_found
         ),
+                    MaybeGoal = MaybeConj
+                )
+            ;
+                MaybeGoal = goal_not_found 
+            )
+        ;
+            GoalExpr0 = disj(Disjs0),
         (
-            MaybeGoalExpr = yes(GoalExpr),
-            MaybeGoal = yes(Goal0 ^ hlds_goal_expr := GoalExpr)
+                Step = step_disj(DisjNum),
+                list.index1(Disjs0, DisjNum, Disj0)
+            ->
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap0, Disj0, MaybeDisj),
+                (
+                    MaybeDisj = ok(Disj),
+                    list.replace_nth_det(Disjs0, DisjNum, Disj, Disjs),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := disj(Disjs))
+                ;
+                    ( MaybeDisj = error(_)
+                    ; MaybeDisj = goal_not_found
+                    ),
+                    MaybeGoal = MaybeDisj
+                )
         ;
-            MaybeGoalExpr = no,
-            MaybeGoal = no
+                MaybeGoal = goal_not_found
         )
     ;
-        TransformP(Goal0, MaybeGoal)
+            GoalExpr0 = switch(Var, CanFail, Cases0),
+            (
+                Step = step_switch(CaseNum, _MaybeNumConstructors),
+                list.index1(Cases0, CaseNum, Case0)
+            ->
+                CaseGoal0 = Case0 ^ case_goal,
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap0, CaseGoal0, MaybeCaseGoal),
+                (
+                    MaybeCaseGoal = ok(CaseGoal),
+                    Case = Case0 ^ case_goal := CaseGoal,
+                    list.replace_nth_det(Cases0, CaseNum, Case, Cases),
+                    GoalExpr = switch(Var, CanFail, Cases),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeCaseGoal = error(_)
+                    ; MaybeCaseGoal = goal_not_found
+                    ),
+                    MaybeGoal = MaybeCaseGoal
+                )
+            ;
+                MaybeGoal = goal_not_found 
+            )
+        ;
+            GoalExpr0 = negation(SubGoal0),
+            ( Step = step_neg ->
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap0, SubGoal0, MaybeSubGoal),
+                (
+                    MaybeSubGoal = ok(SubGoal),
+                    GoalExpr = negation(SubGoal),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeSubGoal = error(_)
+                    ; MaybeSubGoal = goal_not_found
+                    ),
+                    MaybeGoal = MaybeSubGoal
+                )
+            ;
+                MaybeGoal = goal_not_found 
+            )
+        ;
+            GoalExpr0 = scope(Reason, SubGoal0),
+            ( Step = step_scope(_MaybeCut) ->
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap0, SubGoal0, MaybeSubGoal),
+                (
+                    MaybeSubGoal = ok(SubGoal),
+                    GoalExpr = scope(Reason, SubGoal),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeSubGoal = error(_)
+                    ; MaybeSubGoal = goal_not_found
+                    ),
+                    MaybeGoal = MaybeSubGoal
+                )
+            ;
+                MaybeGoal = goal_not_found 
+            )
+        ;
+            GoalExpr0 = if_then_else(ExistVars, Cond0, Then0, Else0),
+            ( Step = step_ite_cond ->
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap0, Cond0, MaybeCond),
+                (
+                    MaybeCond = ok(Cond),
+                    GoalExpr = if_then_else(ExistVars, Cond, Then0, Else0),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeCond = error(_)
+                    ; MaybeCond = goal_not_found
+                    ),
+                    MaybeGoal = MaybeCond
+                )
+            ; Step = step_ite_then ->
+                apply_instmap_delta_sv(
+                    goal_info_get_instmap_delta(Cond0 ^ hlds_goal_info),
+                    Instmap0, Instmap),
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap, Then0, MaybeThen),
+                (
+                    MaybeThen = ok(Then),
+                    GoalExpr = if_then_else(ExistVars, Cond0, Then, Else0),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeThen = error(_)
+                    ; MaybeThen = goal_not_found
+                    ),
+                    MaybeGoal = MaybeThen
+                )
+            ; Step = step_ite_else ->
+                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
+                    TargetGoalPath, Instmap0, Else0, MaybeElse),
+                (
+                    MaybeElse = ok(Else),
+                    GoalExpr = if_then_else(ExistVars, Cond0, Then0, Else),
+                    MaybeGoal = ok(Goal0 ^ hlds_goal_expr := GoalExpr)
+                ;
+                    ( MaybeElse = error(_)
+                    ; MaybeElse = goal_not_found
+                    ),
+                    MaybeGoal = MaybeElse
+                )
+            ;
+                MaybeGoal = goal_not_found 
+            )
+        ;
+            GoalExpr0 = shorthand(_),
+            unexpected(this_file, 
+                "Shorthand goals should have been eliminated already")
+        )
+    ;
+        TransformP(Instmap0, Goal0, MaybeGoal0),
+        % These are different types, so we need to pattern match them here.
+        maybe_error_to_maybe_transformed_goal(MaybeGoal0, MaybeGoal)
     ).
 
+:- pred maybe_error_to_maybe_transformed_goal(maybe_error(hlds_goal)::in,
+    maybe_transformed_goal::out) is det.
+
+maybe_error_to_maybe_transformed_goal(ok(Goal), ok(Goal)).
+maybe_error_to_maybe_transformed_goal(error(Error), error(Error)).
+
 transform_all_goals(Transform, Goal0, Goal) :-
     GoalExpr0 = Goal0 ^ hlds_goal_expr,  
     (
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.259
diff -u -p -b -r1.259 hlds_pred.m
--- compiler/hlds_pred.m	10 Jun 2010 00:58:16 -0000	1.259
+++ compiler/hlds_pred.m	30 Jun 2010 12:41:15 -0000
@@ -1750,7 +1750,8 @@ attribute_list_to_attributes(Attributes,
                 dob_head_vars           :: list(prog_var),
                 dob_instmap             :: instmap,
                 dob_vartypes            :: vartypes,
-                dob_detism              :: determinism
+                dob_detism              :: determinism,
+                dob_varset              :: prog_varset
             ).
 
 :- type table_arg_infos
Index: compiler/implicit_parallelism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/implicit_parallelism.m,v
retrieving revision 1.17
diff -u -p -b -r1.17 implicit_parallelism.m
--- compiler/implicit_parallelism.m	13 May 2010 02:27:37 -0000	1.17
+++ compiler/implicit_parallelism.m	4 Jul 2010 09:51:27 -0000
@@ -21,17 +21,17 @@
 
 :- import_module hlds.hlds_module.
 
-:- import_module maybe.
+:- import_module io.
 
 %-----------------------------------------------------------------------------%
 
-    % apply_implicit_parallelism_transformation(!ModuleInfo, FeedbackFile, !IO)
+    % apply_implicit_parallelism_transformation(!ModuleInfo, !IO)
     %
     % Apply the implicit parallelism transformation using the specified
     % feedback file.
     %
 :- pred apply_implicit_parallelism_transformation(
-    module_info::in, maybe_error(module_info)::out) is det.
+    module_info::in, module_info::out, io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -49,6 +49,9 @@
 :- import_module libs.compiler_util.
 :- import_module libs.globals.
 :- import_module libs.options.
+:- import_module ll_backend.
+:- import_module ll_backend.prog_rep.
+:- import_module ll_backend.stack_layout.
 :- import_module mdbcomp.feedback.
 :- import_module mdbcomp.prim_data.
 :- import_module mdbcomp.program_representation.
@@ -63,27 +66,45 @@
 :- import_module int.
 :- import_module list.
 :- import_module map.
+:- import_module maybe.
 :- import_module pair.
 :- import_module require.
 :- import_module set.
 :- import_module string.
 :- import_module svmap.
+:- import_module term.
 :- import_module varset.
 
 %-----------------------------------------------------------------------------%
 
-apply_implicit_parallelism_transformation(ModuleInfo0, MaybeModuleInfo) :-
-    module_info_get_globals(ModuleInfo0, Globals),
+apply_implicit_parallelism_transformation(!ModuleInfo, !IO) :-
+    module_info_get_globals(!.ModuleInfo, Globals),
     lookup_bool_option(Globals, old_implicit_parallelism,
         UseOldImplicitParallelism), 
     (
         UseOldImplicitParallelism = yes,
-        apply_old_implicit_parallelism_transformation(ModuleInfo0,
-            MaybeModuleInfo)
+        apply_old_implicit_parallelism_transformation(!.ModuleInfo,
+            MaybeModuleInfo),
+        (
+            MaybeModuleInfo = ok(!:ModuleInfo)
+        ;
+            MaybeModuleInfo = error(Error),
+            sorry(this_file, "The old implicit parallelism code is not "
+                ++ "supported: " ++ Error)
+        )
     ;
         UseOldImplicitParallelism = no,
-        apply_new_implicit_parallelism_transformation(ModuleInfo0,
-            MaybeModuleInfo)
+        io_get_maybe_source_file_map(MaybeSourceFileMap, !IO),
+        (
+            MaybeSourceFileMap = yes(SourceFileMap)
+        ;
+            MaybeSourceFileMap = no,
+            error(this_file ++ "could not retrieve the source file map")
+        ),
+        apply_new_implicit_parallelism_transformation(SourceFileMap, Specs, 
+            !ModuleInfo),
+        write_error_specs(Specs, Globals, 0, _, 0, NumErrors, !IO),
+        module_info_incr_num_errors(NumErrors, !ModuleInfo)
     ).
 
 %-----------------------------------------------------------------------------%
@@ -95,29 +116,27 @@ apply_implicit_parallelism_transformatio
     --->    have_not_introduced_parallelism
     ;       introduced_parallelism.
 
-:- pred apply_new_implicit_parallelism_transformation(module_info::in,
-    maybe_error(module_info)::out) is det.
+:- pred apply_new_implicit_parallelism_transformation(source_file_map::in,
+    list(error_spec)::out, module_info::in, module_info::out) is det.
 
-apply_new_implicit_parallelism_transformation(ModuleInfo0, MaybeModuleInfo) :-
-    module_info_get_globals(ModuleInfo0, Globals0),
+apply_new_implicit_parallelism_transformation(SourceFileMap, Specs,
+        !ModuleInfo) :-
+    module_info_get_globals(!.ModuleInfo, Globals0),
     globals.get_maybe_feedback_info(Globals0, MaybeFeedbackInfo),
-    module_info_get_name(ModuleInfo0, ModuleName),
+    module_info_get_name(!.ModuleInfo, ModuleName),
     (
         yes(FeedbackInfo) = MaybeFeedbackInfo,
         get_implicit_parallelism_feedback(ModuleName, FeedbackInfo,
             ParallelismInfo)
     ->
-        some [!ModuleInfo]
-        (
-            !:ModuleInfo = ModuleInfo0,
-            
             % Retrieve and process predicates.
             module_info_predids(PredIds, !ModuleInfo),
             module_info_get_predicate_table(!.ModuleInfo, PredTable0),
             predicate_table_get_preds(PredTable0, PredMap0),
-            list.foldl2(maybe_parallelise_pred(!.ModuleInfo, ParallelismInfo), 
+        list.foldl3(maybe_parallelise_pred(!.ModuleInfo, ParallelismInfo), 
                 PredIds, PredMap0, PredMap, 
-                have_not_introduced_parallelism, IntroducedParallelism),
+            have_not_introduced_parallelism, IntroducedParallelism,
+            [], Specs),
             (
                 IntroducedParallelism = have_not_introduced_parallelism
             ;
@@ -125,12 +144,15 @@ apply_new_implicit_parallelism_transform
                 predicate_table_set_preds(PredMap, PredTable0, PredTable),
                 module_info_set_predicate_table(PredTable, !ModuleInfo),
                 module_info_set_contains_par_conj(!ModuleInfo)
-            ),
-            MaybeModuleInfo = ok(!.ModuleInfo)
         )
     ;
-        MaybeModuleInfo =
-            error("Insufficient feedback information for implicit parallelism") 
+        map.lookup(SourceFileMap, ModuleName, ModuleFilename), 
+        Context = context(ModuleFilename, 1),
+        Peices = [words("Implicit parallelism was requested but the"),
+            words("feedback file does not the candidate parallel"),
+            words("conjunctions feedback information.")],
+        Specs = [error_spec(severity_error, phase_auto_parallelism,
+            [simple_msg(Context, [always(Peices)])])]
     ).
 
     % Information retrieved from the feedback system to be used for
@@ -173,7 +195,7 @@ apply_new_implicit_parallelism_transform
     % label for a given module.
     %
 :- type module_candidate_par_conjs_map
-    == map(intra_module_proc_label, candidate_par_conjunction).
+    == map(intra_module_proc_label, candidate_par_conjunctions_proc).
 
 :- pred get_implicit_parallelism_feedback(module_name::in, feedback_info::in,
     parallelism_info::out) is semidet.
@@ -191,7 +213,7 @@ get_implicit_parallelism_feedback(Module
         SparkingDelay, LockingCost, CandidateParConjsMap).
 
 :- pred make_module_candidate_par_conjs_map(module_name::in,
-    assoc_list(string_proc_label, candidate_par_conjunction)::in,
+    assoc_list(string_proc_label, candidate_par_conjunctions_proc)::in,
     module_candidate_par_conjs_map::out) is det.
 
 make_module_candidate_par_conjs_map(ModuleName,
@@ -202,8 +224,9 @@ make_module_candidate_par_conjs_map(Modu
     CandidateParConjsMap = map.from_assoc_list(CandidateParConjsAssocList).
 
 :- pred cpc_proc_is_in_module(string::in, 
-    pair(string_proc_label, candidate_par_conjunction)::in,
-    pair(intra_module_proc_label, candidate_par_conjunction)::out) is semidet.
+    pair(string_proc_label, candidate_par_conjunctions_proc)::in,
+    pair(intra_module_proc_label, candidate_par_conjunctions_proc)::out) 
+    is semidet.
 
 cpc_proc_is_in_module(ModuleName, ProcLabel - CPC, IMProcLabel - CPC) :-
     ( 
@@ -220,16 +243,17 @@ cpc_proc_is_in_module(ModuleName, ProcLa
 
 :- pred maybe_parallelise_pred(module_info::in, parallelism_info::in, 
     pred_id::in, pred_table::in, pred_table::out,
-    introduced_parallelism::in, introduced_parallelism::out) is det.
+    introduced_parallelism::in, introduced_parallelism::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
 
 maybe_parallelise_pred(ModuleInfo, ParallelismInfo, PredId, !PredTable, 
-        !IntroducedParallelism) :-
+        !IntroducedParallelism, !Specs) :-
     map.lookup(!.PredTable, PredId, PredInfo0),
     ProcIds = pred_info_non_imported_procids(PredInfo0),
     pred_info_get_procedures(PredInfo0, ProcTable0),
-    list.foldl2(maybe_parallelise_proc(ModuleInfo, ParallelismInfo, PredId),
+    list.foldl3(maybe_parallelise_proc(ModuleInfo, ParallelismInfo, PredId),
         ProcIds, ProcTable0, ProcTable, have_not_introduced_parallelism,
-        ProcIntroducedParallelism),
+        ProcIntroducedParallelism, !Specs),
     (
         ProcIntroducedParallelism = have_not_introduced_parallelism
     ;
@@ -241,10 +265,11 @@ maybe_parallelise_pred(ModuleInfo, Paral
 
 :- pred maybe_parallelise_proc(module_info::in, parallelism_info::in, 
     pred_id::in, proc_id::in, proc_table::in, proc_table::out, 
-    introduced_parallelism::in, introduced_parallelism::out) is det.
+    introduced_parallelism::in, introduced_parallelism::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
 
 maybe_parallelise_proc(ModuleInfo, ParallelismInfo, PredId, ProcId, !ProcTable,
-        !IntroducedParallelism) :-
+        !IntroducedParallelism, !Specs) :-
     module_info_pred_proc_info(ModuleInfo, PredId, ProcId, 
         PredInfo, ProcInfo0),
     
@@ -255,8 +280,121 @@ maybe_parallelise_proc(ModuleInfo, Paral
     Mode = proc_id_to_int(ProcId),
     IMProcLabel = intra_module_proc_label(Name, Arity, PredOrFunc, Mode),
     CPCMap = ParallelismInfo ^ pi_cpc_map,
-    ( map.search(CPCMap, IMProcLabel, CPC) ->
+    ( map.search(CPCMap, IMProcLabel, CPCProc) ->
+        proc_info_get_has_parallel_conj(ProcInfo0, HasParallelConj), 
+        (
+            HasParallelConj = yes,
+            Spec = report_already_parallelised(PredInfo),
+            !:Specs = [Spec | !.Specs]
+        ;
+            HasParallelConj = no,
+            
         proc_info_get_goal(ProcInfo0, Goal0),
+            CPCProc = candidate_par_conjunctions_proc(VarTable, CPCs0),
+       
+            Context = goal_info_get_context(Goal0 ^ hlds_goal_info),
+            term.context_file(Context, FileName),
+            proc_info_get_vartypes(ProcInfo0, VarTypes),
+            % VarNumRep is not used by goal_to_goal_rep, byte is an arbitrary
+            % value.
+            VarNumRep = byte,
+            proc_info_get_headvars(ProcInfo0, HeadVars),
+            proc_info_get_varset(ProcInfo0, VarSet),
+            compute_var_number_map(HeadVars, VarSet, [], Goal0, VarNumMap),
+            ProgRepInfo = prog_rep_info(FileName, VarTypes, VarNumMap,
+                VarNumRep, ModuleInfo),
+            proc_info_get_initial_instmap(ProcInfo0, ModuleInfo, Instmap),
+
+            % Sort the candidate parallelisations so that we introduced
+            % parallelisations in a order that allows us to continue to insert
+            % parallelisations even as the goal tree changes.  In particular,
+            % insert deeper parallelisations before shallower ones, and later
+            % ones before earlier ones.
+            sort_and_remove_dups(compare_candidate_par_conjunctions, 
+                CPCs0, CPCs),
+            foldl3(maybe_parallelise_goal(PredInfo, ProgRepInfo, VarTable, 
+                    Instmap),
+                CPCs, Goal0, Goal, !IntroducedParallelism, !Specs),
+            (
+                !.IntroducedParallelism = introduced_parallelism,
+                % In the future we'll specialise the procedure for parallelism,
+                % We don't do that now so simply replace the procedure's body.
+                proc_info_set_goal(Goal, ProcInfo0, ProcInfo1),
+                proc_info_set_has_parallel_conj(yes, ProcInfo1, ProcInfo),
+                svmap.det_update(ProcId, ProcInfo, !ProcTable)
+            ;
+                !.IntroducedParallelism = have_not_introduced_parallelism
+            )
+        )
+    ;
+        true
+    ).
+
+:- pred compare_candidate_par_conjunctions(candidate_par_conjunction::in,
+    candidate_par_conjunction::in, comparison_result::out) is det.
+
+compare_candidate_par_conjunctions(CPCA, CPCB, Result) :-
+    cpc_goal_path_consable_det(CPCA, GoalPathA),
+    cpc_goal_path_consable_det(CPCB, GoalPathB),
+    compare_goal_paths(GoalPathA, GoalPathB, Result).
+
+:- pred cpc_goal_path_consable_det(candidate_par_conjunction::in, 
+    goal_path_consable::out) is det.
+
+cpc_goal_path_consable_det(CPC, GoalPathConsable) :-
+    goal_path_from_string_det(CPC ^ cpc_goal_path, GoalPath),
+    goal_path_consable(GoalPath, GoalPathConsable).
+
+:- pred compare_goal_paths(goal_path_consable::in, goal_path_consable::in,
+    comparison_result::out) is det.
+
+compare_goal_paths(GoalPathA, GoalPathB, Result) :-
+    ( goal_path_consable_remove_first(GoalPathA, StepA, RestA) ->
+        ( goal_path_consable_remove_first(GoalPathB, StepB, RestB) ->
+            compare(Result0, StepA, StepB),
+            % Reverse the ordering here so that later goals are sorted before
+            % earlier ones, this way parallelisations are placed inside later
+            % goals first.
+            (
+                Result0 = (=),
+                compare_goal_paths(RestA, RestB, Result)
+            ;
+                Result0 = (<),
+                Result = (>)
+            ;
+                Result0 = (>),
+                Result = (<)
+            )
+        ;
+            % GoalPathA is longer than GoalPathB.  Make A 'less than' B so that
+            % deeper parallelisations are insearted first.
+            Result = (<)
+        )
+    ;
+        ( goal_path_consable_remove_first(GoalPathB, _, _) ->
+            % B is 'less than' A, see above.
+            Result = (>)
+        ;
+            % Both goal paths are empty.
+            Result = (=)
+        )
+    ).
+            
+    % maybe_parallelise_goal(ProgRepInfo, VarTable, CPC, !Goal, 
+    %   !IntroducedParallelism).
+    %
+    % Attempt to parallelise some part of !.Goal returning !:Goal.
+    % If !.IntroducedParallelism = have_not_introduced_parallelism then !Goal
+    % will be unmodified.
+    %
+:- pred maybe_parallelise_goal(pred_info::in, prog_rep_info::in, 
+    var_table::in, instmap::in, candidate_par_conjunction::in,
+    hlds_goal::in, hlds_goal::out,
+    introduced_parallelism::in, introduced_parallelism::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+maybe_parallelise_goal(PredInfo, ProgRepInfo, VarTable, Instmap0, CPC, Goal0,
+        Goal, !IntroducedParallelism, !Specs) :-
         TargetGoalPathString = CPC ^ cpc_goal_path,
         ( goal_path_from_string(TargetGoalPathString, TargetGoalPathPrime) ->
             TargetGoalPath = TargetGoalPathPrime
@@ -264,80 +402,119 @@ maybe_parallelise_proc(ModuleInfo, Paral
             unexpected(this_file, 
                 "Invalid goal path in CPC Feedback Information")
         ),
-        maybe_parallelise_goal(ProcInfo0, CPC, TargetGoalPath, 
-            Goal0, MaybeGoal),
+    goal_path_consable(TargetGoalPath, TargetGoalPathC),
+    
+    maybe_transform_goal_at_goal_path_with_instmap(
+        maybe_parallelise_conj(ProgRepInfo, VarTable, CPC),
+        TargetGoalPathC, Instmap0, Goal0, MaybeGoal),
         (
-            MaybeGoal = yes(Goal),
-            % In the future we'll specialise the procedure for parallelism,  We
-            % don't do that now so simply replace the procedure's body.
-            proc_info_set_goal(Goal, ProcInfo0, ProcInfo1),
-            proc_info_set_has_parallel_conj(yes, ProcInfo1, ProcInfo),
-            svmap.det_update(ProcId, ProcInfo, !ProcTable),
+        MaybeGoal = ok(Goal),
             !:IntroducedParallelism = introduced_parallelism
         ;
-            MaybeGoal = no
-        )
+        (
+            MaybeGoal = error(Error)
     ;
-        true 
+            MaybeGoal = goal_not_found,
+            Error = "Could not find goal in procedure; "
+                    ++ "perhaps the program has changed"
+        ),
+        Goal = Goal0,
+        Spec = report_failed_parallelisation(PredInfo, TargetGoalPathString,
+            Error),
+        !:Specs = [Spec | !.Specs]
     ).
 
-    % maybe_parallelise_goal(ModuleInfo, CPC, GoalPath, Goal, MaybeGoal).
-    %
-    % Parallelise a goal addressed by GoalPath within Goal producing MaybeGoal
-    % if found.  The goal to parallelise must be a conjunction with conjuncts
-    % matching those described in CPC.
-    %
-    % As this predicate recurses deeper into the goal tree GoalPath becomes
-    % smaller as goal path steps are popped off the end and followed.
-    %
-    % Try to parallelise the given conjunction within this goal.
-    %
-:- pred maybe_parallelise_goal(proc_info::in, candidate_par_conjunction::in,
-    goal_path::in, hlds_goal::in, maybe(hlds_goal)::out) is det.
+:- func report_failed_parallelisation(pred_info, string, string) =
+    error_spec.
 
-maybe_parallelise_goal(ProcInfo, CPC, TargetGoalPath, 
-        Goal0, MaybeGoal) :-
-    goal_path_consable(TargetGoalPath, TargetGoalPathC),
-    maybe_transform_goal_at_goal_path(maybe_parallelise_conj(ProcInfo, CPC),
-        TargetGoalPathC, Goal0, MaybeGoal).
+report_failed_parallelisation(PredInfo, GoalPath, Error) = Spec :-
+    % Should the severity be informational?
+    PredOrFunc = pred_info_is_pred_or_func(PredInfo),
+    ModuleName = pred_info_module(PredInfo),
+    PredName = pred_info_name(PredInfo),
+    Arity = pred_info_orig_arity(PredInfo),
+    Peices = [words("In"), p_or_f(PredOrFunc),
+        sym_name_and_arity(qualified(ModuleName, PredName) / Arity),
+        suffix(":"), nl,
+        words("Warning: could not auto-parallelise"), quote(GoalPath), 
+        suffix(":"), words(Error)],
+    pred_info_get_context(PredInfo, Context),
+    Spec = error_spec(severity_warning, phase_auto_parallelism,
+        [simple_msg(Context, [always(Peices)])]).
 
-:- pred maybe_parallelise_conj(proc_info::in, candidate_par_conjunction::in,
-    hlds_goal::in, maybe(hlds_goal)::out) is det.
+:- func report_already_parallelised(pred_info) = error_spec.
 
-maybe_parallelise_conj(ProcInfo, CPC, Goal0, MaybeGoal) :-
-    GoalExpr0 = Goal0 ^ hlds_goal_expr,
+report_already_parallelised(PredInfo) = Spec :-
+    % Should the severity be informational?
+    PredOrFunc = pred_info_is_pred_or_func(PredInfo),
+    ModuleName = pred_info_module(PredInfo),
+    PredName = pred_info_name(PredInfo),
+    Arity = pred_info_orig_arity(PredInfo),
+    Peices = [words("In"), p_or_f(PredOrFunc),
+        sym_name_and_arity(qualified(ModuleName, PredName) / Arity),
+        suffix(":"), nl,
+        words("Warning: this procedure contains explicit parallel"),
+        words("conjunctions, it will not be automatically parallelised.")],
+    pred_info_get_context(PredInfo, Context),
+    Spec = error_spec(severity_warning, phase_auto_parallelism,
+        [simple_msg(Context, [always(Peices)])]).
+
+:- pred maybe_parallelise_conj(prog_rep_info::in, var_table::in, 
+    candidate_par_conjunction::in, instmap::in, hlds_goal::in,
+    maybe_error(hlds_goal)::out) is det.
+
+maybe_parallelise_conj(ProgRepInfo, VarTable, CPC, Instmap0, Goal0, MaybeGoal) :-
+    Goal0 = hlds_goal(GoalExpr0, _GoalInfo0),
     % We've reached the point indicated by the goal path, Find the
     % conjuncts that we wish to parallelise.
     PartitionNum = CPC ^ cpc_partition_number,
-    FeedbackParConjuncts = CPC ^ cpc_conjs, 
     (
         GoalExpr0 = conj(plain_conj, Conjs0),
         flatten_conj(Conjs0, Conjs1),
-        find_partition(PartitionNum, Conjs1, GoalsBeforePartition,
-            yes(Partition0), GoalsAfterPartition),
-        build_par_conjuncts(ProcInfo, Partition0, FeedbackParConjuncts,
-            yes(ParConjuncts), GoalsBefore, GoalsAfter)
+        find_partition(PartitionNum, Conjs1, yes(PartitionInConj))
     ->
-        create_conj_from_list(ParConjuncts, parallel_conj, ParConjunction),
-        Conjs = GoalsBeforePartition ++ GoalsBefore ++ 
-            [ ParConjunction | GoalsAfter ++ GoalsAfterPartition ], 
+        GoalsBeforePartition = PartitionInConj ^ pic_goals_before,
+        GoalsBeforeInstDeltas = map(
+            (func(G) = goal_info_get_instmap_delta(G ^ hlds_goal_info)),
+            GoalsBeforePartition),
+        foldl(apply_instmap_delta_sv, GoalsBeforeInstDeltas,
+            Instmap0, Instmap),
+        Partition0 = PartitionInConj ^ pic_partition,
+        build_par_conjunction(ProgRepInfo, VarTable, Instmap, Partition0, CPC,
+            MaybeParConjunction),
+        (
+            MaybeParConjunction = ok(ParConjunction),
+            GoalsAfterPartition = PartitionInConj ^ pic_goals_after,
+            Conjs = GoalsBeforePartition ++ ParConjunction ++
+                GoalsAfterPartition, 
         GoalExpr = conj(plain_conj, Conjs),
-        MaybeGoal = yes(hlds_goal(GoalExpr, Goal0 ^ hlds_goal_info))
+            MaybeGoal = ok(hlds_goal(GoalExpr, Goal0 ^ hlds_goal_info))
+        ;
+            MaybeParConjunction = error(Error),
+            MaybeGoal = error(Error)
+        )
     ;
-        MaybeGoal = no
+        MaybeGoal = error("Could not find partition within conjunction: "
+                ++ "perhaps the program has changed")
+    ).
+
+:- type partition_in_conj
+    --->    partition_in_conj(
+                pic_goals_before        :: hlds_goals,
+                pic_partition           :: hlds_goals,
+                pic_goals_after         :: hlds_goals
     ).
 
-:- pred find_partition(int::in, list(hlds_goal)::in, list(hlds_goal)::out,
-    maybe(list(hlds_goal))::out, list(hlds_goal)::out) is det.
+:- pred find_partition(int::in, list(hlds_goal)::in,
+    maybe(partition_in_conj)::out) is det.
 
-find_partition(_, [], [], no, []).
-find_partition(PartitionNum0, [Goal | Goals], GoalsBefore, MaybePartition,
-        GoalsAfter) :-
+find_partition(_, [], no).
+find_partition(PartitionNum0, [Goal | Goals], MaybePartition) :-
     ( PartitionNum0 = 1 ->
         % We've found the correct partition.
-        GoalsBefore = [],
         find_end_of_partition(Goals, Partition, GoalsAfter),
-        MaybePartition = yes([ Goal | Partition ])
+        MaybePartition = yes(
+            partition_in_conj([], [ Goal | Partition ], GoalsAfter))
     ;
         goal_is_atomic(Goal, GoalIsAtomic),
         (
@@ -347,9 +524,18 @@ find_partition(PartitionNum0, [Goal | Go
             GoalIsAtomic = goal_is_nonatomic,
             PartitionNum = PartitionNum0 - 1
         ),
-        find_partition(PartitionNum, Goals, GoalsBefore0, MaybePartition,
-            GoalsAfter),
-        GoalsBefore = [ Goal | GoalsBefore0 ]
+        find_partition(PartitionNum, Goals, MaybePartition0),
+        (
+            MaybePartition0 = yes(PartitionInConj0),
+            PartitionInConj0 = 
+                partition_in_conj(GoalsBefore0, Partition, GoalsAfter),
+            PartitionInConj = 
+                partition_in_conj([Goal | GoalsBefore0], Partition, GoalsAfter),
+            MaybePartition = yes(PartitionInConj)
+        ;
+            MaybePartition0 = no,
+            MaybePartition = MaybePartition0
+        )
     ).
 
 :- pred find_end_of_partition(list(hlds_goal)::in, list(hlds_goal)::out, 
@@ -364,204 +550,269 @@ find_end_of_partition([ Goal | Goals ], 
         Partition = [ Goal | Partition0 ]
     ;
         GoalIsAtomic = goal_is_nonatomic,
-        Partition = [ Goal ],
-        GoalsAfter = Goals
+        Partition = [],
+        GoalsAfter = [Goal | Goals]
     ).
 
-:- pred build_par_conjuncts(proc_info::in, hlds_goals::in, list(seq_conj)::in, 
-    maybe(hlds_goals)::out, hlds_goals::out, hlds_goals::out) is det.
+:- pred build_par_conjunction(prog_rep_info::in, var_table::in, instmap::in,
+    hlds_goals::in, candidate_par_conjunction::in, 
+    maybe_error(hlds_goals)::out) is det.
 
-build_par_conjuncts(ProcInfo, Goals, FeedbackParConjuncts0,
-        MaybeParConjuncts, GoalsBefore, GoalsAfter) :-
-    (
-        FeedbackParConjuncts0 = [ FeedbackParConjunct | FeedbackParConjuncts ],
-        FeedbackParConjunct = seq_conj(FeedbackSeqConjuncts),
-        build_seq_conjuncts(ProcInfo, Goals, FeedbackSeqConjuncts,
-            MaybeSeqConjuncts0, GoalsBefore, GoalsAfterSeqConj),
-        (
-            MaybeSeqConjuncts0 = yes(SeqConjuncts0),
-            build_par_conjuncts(ProcInfo, GoalsAfterSeqConj,
-                FeedbackParConjuncts, MaybeParConjuncts0, GoalsBefore0,
-                GoalsAfter0),
-            (
-                MaybeParConjuncts0 = yes(ParConjuncts0),
-                % GoalsBefore0 must be put into either the current parallel
-                % conjunct or the next parallel conjunct.
-                (
-                    ParConjuncts0 = [],
-                    % If there are no parallel conjuncts remaining then
-                    % schedule all these goals after the parallel conjunction,
-                    % this is a trivial conservative strategy.
-                    GoalsAfter = GoalsBefore0 ++ GoalsAfter0,
-                    SeqConjuncts = SeqConjuncts0
-                ;
-                    ParConjuncts0 = [_ | _],
-                    GoalsAfter = GoalsAfter0,
-                    SeqConjuncts = SeqConjuncts0,
-                    (
-                        GoalsBefore0 = []
-                    ;
-                        GoalsBefore0 = [_ | _],
-                        sorry(this_file, 
-                          "Extra goals found during automatic parallelisation")
-                    )
+build_par_conjunction(ProcRepInfo, VarTable, Instmap0, !.Goals, CPC,
+        MaybeParConjunction) :-
+    GoalRepsBefore = CPC ^ cpc_goals_before,
+    GoalRepsAfter = CPC ^ cpc_goals_after,
+    ParConjReps = CPC ^ cpc_conjs,
+    some [!Instmap] (
+        !:Instmap = Instmap0,
+        build_seq_conjuncts(ProcRepInfo, VarTable, GoalRepsBefore,
+            MaybeGoalsBefore, !Goals, !Instmap),
+        build_par_conjuncts(ProcRepInfo, VarTable, ParConjReps,
+            MaybeParConjuncts, !Goals, !Instmap),
+        build_seq_conjuncts(ProcRepInfo, VarTable, GoalRepsAfter,
+            MaybeGoalsAfter, !Goals, !Instmap),
+        _ = !.Instmap
                 ),
-                create_conj_from_list(SeqConjuncts, plain_conj, ParConjunct),
-                % Mercury only supports parallelisation of deterministic code,
-                % furthermore it's just not a good idea to parallelise anything
-                % that is impure.
-                ( model_det_and_at_least_semipure(ParConjunct) ->
-                    MaybeParConjuncts = yes([ ParConjunct | ParConjuncts0 ])
+    (
+        MaybeGoalsBefore = yes(GoalsBefore),
+        (
+            MaybeParConjuncts = yes(ParConjuncts),
+            (
+                MaybeGoalsAfter = yes(GoalsAfter),
+                ( !.Goals = [] ->
+
+                    create_conj_from_list(ParConjuncts, parallel_conj,
+                        ParConjunction),
+                    MaybeParConjunction = ok(GoalsBefore ++ 
+                        [ParConjunction | GoalsAfter])
                 ;
-                    MaybeParConjuncts = no
+                    MaybeParConjunction = error("There where goals left-over after "
+                        ++ "constructing the parallel conjunction")
                 )
             ;
-                MaybeParConjuncts0 = no,
-                MaybeParConjuncts = no,
-                GoalsAfter = Goals
+                MaybeGoalsAfter = no,
+                MaybeParConjunction = error("The goals after the parallel "
+                    ++ "conjunction do not match those in the feedback file")
             )
         ;
-            MaybeSeqConjuncts0 = no,
             MaybeParConjuncts = no,
-            GoalsAfter = Goals
+            MaybeParConjunction = error("The goals within the parallel "
+                ++ "conjunction do not match those in the feedback file")
         )
     ;
-        FeedbackParConjuncts0 = [],
-        MaybeParConjuncts = yes([]),
-        GoalsBefore = [],
-        GoalsAfter = Goals
+        MaybeGoalsBefore = no,
+        MaybeParConjunction = error("The goals before the parallel "
+            ++ "conjunction do not match those in the feedback file")
     ).
 
-:- pred build_seq_conjuncts(proc_info::in, hlds_goals::in, list(pard_goal)::in,
-    maybe(hlds_goals)::out, hlds_goals::out, hlds_goals::out) is det.
+:- pred build_par_conjuncts(prog_rep_info::in, var_table::in, 
+    list(seq_conj)::in, maybe(hlds_goals)::out, 
+    hlds_goals::in, hlds_goals::out, instmap::in, instmap::out) is det.
 
-build_seq_conjuncts(ProcInfo, Goals, FeedbackSeqConjuncts0, MaybeSeqConjuncts,
-        GoalsBefore, GoalsAfter) :-
+build_par_conjuncts(_, _, [], yes([]), !Goals, !Instmap).
+build_par_conjuncts(ProcRepInfo, VarTable, [GoalRep | GoalReps], MaybeConjs,
+        !Goals, !Instmap) :-
+    GoalRep = seq_conj(SeqConjs),
+    build_seq_conjuncts(ProcRepInfo, VarTable, SeqConjs, MaybeConj, !Goals, 
+        !Instmap),
     (
-        FeedbackSeqConjuncts0 = [ FeedbackSeqConjunct | FeedbackSeqConjuncts ],
-        pard_goal_match_hlds_goal(ProcInfo, FeedbackSeqConjunct, Goals,
-            MaybeGoal, GoalsBefore0, GoalsAfter0),
+        MaybeConj = yes(Conj0),
+        create_conj_from_list(Conj0, plain_conj, Conj), 
+        build_par_conjuncts(ProcRepInfo, VarTable, GoalReps, MaybeConjs0,
+            !Goals, !Instmap),
         (
-            MaybeGoal = yes(Goal),
-            GoalsBefore = GoalsBefore0,
-            SeqConjunct = Goal,
-            build_seq_conjuncts(ProcInfo, GoalsAfter0, FeedbackSeqConjuncts,
-                MaybeSeqConjuncts0, GoalsBetween, GoalsAfter),
+            MaybeConjs0 = yes(Conjs0),
+            MaybeConjs = yes([Conj | Conjs0])
+        ;
+            MaybeConjs0 = no,
+            MaybeConjs = no
+        )
+    ;
+        MaybeConj = no,
+        MaybeConjs = no
+    ).
+
+:- pred build_seq_conjuncts(prog_rep_info::in, var_table::in, 
+    list(pard_goal)::in, maybe(hlds_goals)::out, 
+    hlds_goals::in, hlds_goals::out, instmap::in, instmap::out) is det.
+
+build_seq_conjuncts(_, _, [], yes([]), !Goals, !Instmap).
+build_seq_conjuncts(ProcRepInfo, VarTable, [GoalRep | GoalReps], MaybeConjs,
+        !Goals, !Instmap) :-
+    ( 
+        !.Goals = [Goal | !:Goals],
+        ( pard_goal_match_hlds_goal(ProcRepInfo, VarTable, !.Instmap, GoalRep, 
+                Goal) ->
+            InstmapDelta = goal_info_get_instmap_delta(Goal ^ hlds_goal_info),
+            apply_instmap_delta_sv(InstmapDelta, !Instmap),
+            build_seq_conjuncts(ProcRepInfo, VarTable, GoalReps, MaybeConjs0,
+                !Goals, !Instmap),
             (
-                MaybeSeqConjuncts0 = yes(SeqConjuncts0),
-                SeqConjuncts = [ SeqConjunct | 
-                    (GoalsBetween ++ SeqConjuncts0) ],
-                MaybeSeqConjuncts = yes(SeqConjuncts)
+                MaybeConjs0 = yes(Conjs0),
+                MaybeConjs = yes([Goal | Conjs0])
             ;
-                MaybeSeqConjuncts0 = no,
-                MaybeSeqConjuncts = no
+                MaybeConjs0 = no,
+                MaybeConjs = no
             )
         ;
-            MaybeGoal = no,
-            MaybeSeqConjuncts = no,
-            GoalsBefore = [],
-            GoalsAfter = Goals
+            MaybeConjs = no
         )
     ;
-        FeedbackSeqConjuncts0 = [],
-        MaybeSeqConjuncts = yes([]),
-        GoalsBefore = [],
-        GoalsAfter = Goals
+        !.Goals = [],
+        MaybeConjs = no
     ).
 
-:- pred pard_goal_match_hlds_goal(proc_info::in, pard_goal::in,
-    hlds_goals::in, maybe(hlds_goal)::out, hlds_goals::out, hlds_goals::out)
-    is det.
+:- pred pard_goal_match_hlds_goal(prog_rep_info::in, var_table::in,
+    instmap::in, pard_goal::in, hlds_goal::in) is semidet.
 
-pard_goal_match_hlds_goal(_ProcInfo, _, [], no, [], []).
-pard_goal_match_hlds_goal(ProcInfo, InnerGoal, [ Goal | Goals ], MaybeGoal,
-        GoalsBefore, GoalsAfter) :-
-    proc_info_get_varset(ProcInfo, Varset),
-    GoalExpr = Goal ^ hlds_goal_expr,
+pard_goal_match_hlds_goal(ProgRepInfo, VarTable, Instmap, GoalRep1, Goal) :-
+    goal_to_goal_rep(ProgRepInfo, Instmap, Goal, GoalRep2),
+    goal_reps_match(VarTable, GoalRep1, GoalRep2).
+
+:- pred goal_reps_match(var_table::in, goal_rep(A)::in, goal_rep(B)::in) 
+    is semidet.
+
+goal_reps_match(VarTable, goal_rep(GoalExpr1, Detism, _), 
+        goal_rep(GoalExpr2, Detism, _)) :-
+    goal_expr_reps_match(VarTable, GoalExpr1, GoalExpr2).
+
+:- pred goal_expr_reps_match(var_table::in, goal_expr_rep(A)::in, 
+    goal_expr_rep(B)::in) is semidet.
+
+goal_expr_reps_match(VarTable, conj_rep(Conjs1), conj_rep(Conjs2)) :-
+    zip_all_true(goal_reps_match(VarTable), Conjs1, Conjs2).
+goal_expr_reps_match(VarTable, disj_rep(Disjs1), disj_rep(Disjs2)) :-
+    zip_all_true(goal_reps_match(VarTable), Disjs1, Disjs2).
+goal_expr_reps_match(VarTable, switch_rep(VarRep1, CanFail, Cases1),
+        switch_rep(VarRep2, CanFail, Cases2)) :-
+    % Note that cases can appear in a different order and goals would still be
+    % equivalent.  We don't handle this.
+    var_reps_match(VarTable, VarRep1, VarRep2),
+    zip_all_true(case_reps_match(VarTable), Cases1, Cases2).
+goal_expr_reps_match(VarTable, ite_rep(Cond1, Then1, Else1), 
+        ite_rep(Cond2, Then2, Else2)) :-
+    goal_reps_match(VarTable, Cond1, Cond2),
+    goal_reps_match(VarTable, Then1, Then2),
+    goal_reps_match(VarTable, Else1, Else2).
+goal_expr_reps_match(VarTable, negation_rep(SubGoal1),
+        negation_rep(SubGoal2)) :- 
+    goal_reps_match(VarTable, SubGoal1, SubGoal2).
+goal_expr_reps_match(VarTable, scope_rep(SubGoal1, MaybeCut),
+        scope_rep(SubGoal2, MaybeCut)) :-
+    goal_reps_match(VarTable, SubGoal1, SubGoal2).
+goal_expr_reps_match(VarTable, atomic_goal_rep(_, _, _, AtomicGoal1),
+        atomic_goal_rep(_, _, _, AtomicGoal2)) :-
+    % We don't compare names and file numbers, a trivial change made by the
+    % user could change the line number dramatically without changing how the
+    % program should be parallelised.
+    %
+    % Vars are not matched here either, we only consider the vars within the
+    % atomic_goal_rep structures.
+    atomic_goal_reps_match(VarTable, AtomicGoal1, AtomicGoal2).
+
+:- pred atomic_goal_reps_match(var_table::in, atomic_goal_rep::in,
+    atomic_goal_rep::in) is semidet.
+
+atomic_goal_reps_match(VarTable, AtomicRepA, AtomicRepB) :-
     (
-        ( GoalExpr = unify(_, _, _, _, _)
-        ; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
-        ),
         (
-            ( InnerGoal = pg_call(_, _, _)
-            ; InnerGoal = pg_cheap_call(_, _)
-            ),
-            Match = no
+            AtomicRepA = unify_construct_rep(VarA, ConsId, ArgsA),
+            AtomicRepB = unify_construct_rep(VarB, ConsId, ArgsB)
         ;
-            InnerGoal = pg_other_atomic_goal,
-            Match = yes
-        )
+            AtomicRepA = unify_deconstruct_rep(VarA, ConsId, ArgsA),
+            AtomicRepB = unify_deconstruct_rep(VarB, ConsId, ArgsB)
     ;
-        (
-            GoalExpr = plain_call(_, _, Args, Builtin, _, _)
+            AtomicRepA = higher_order_call_rep(VarA, ArgsA),
+            AtomicRepB = higher_order_call_rep(VarB, ArgsB)
         ;
-            GoalExpr = generic_call(_, Args, _, _),
-            Builtin = not_builtin
-        ),
-        (
-            ( InnerGoal = pg_call(Callee, FbArgs, _)
-            ; InnerGoal = pg_cheap_call(Callee, FbArgs)
+            AtomicRepA = method_call_rep(VarA, MethodNum, ArgsA),
+            AtomicRepB = method_call_rep(VarB, MethodNum, ArgsB)
             ),
-            % Try to match the callee and the vars.
-            (
-                Builtin = not_builtin,
-                (
+        var_reps_match(VarTable, VarA, VarB),
+        zip_all_true(var_reps_match(VarTable), ArgsA, ArgsB)
+    ;
                     (
-                        GoalExpr = generic_call(_, _, _, _),
-                        Callee = unknown_callee
+            AtomicRepA = partial_deconstruct_rep(VarA, ConsId, MaybeArgsA),
+            AtomicRepB = partial_deconstruct_rep(VarB, ConsId, MaybeArgsB)
                     ;
-                        GoalExpr = plain_call(_, _, _, _, _, SymName),
-                        Callee = named_callee(ModuleName, ProcName),
-                        match_sym_name(SymName, ModuleName, ProcName)
+            AtomicRepA = partial_construct_rep(VarA, ConsId, MaybeArgsA),
+            AtomicRepB = partial_construct_rep(VarB, ConsId, MaybeArgsB)
                     ),
-                    map(args_match(Varset), Args, FbArgs)
-                ->
-                    Match = yes
+        var_reps_match(VarTable, VarA, VarB),
+        zip_all_true(maybe_var_reps_match(VarTable), MaybeArgsA, MaybeArgsB)
                 ;
-                    Match = no
-                )
+        (
+            AtomicRepA = unify_assign_rep(VarA1, VarA2),
+            AtomicRepB = unify_assign_rep(VarB1, VarB2)
             ;
-                ( Builtin = inline_builtin
-                ; Builtin = out_of_line_builtin
+            AtomicRepA = cast_rep(VarA1, VarA2),
+            AtomicRepB = cast_rep(VarB1, VarB2)
+        ;
+            AtomicRepA = unify_simple_test_rep(VarA1, VarA2),
+            AtomicRepB = unify_simple_test_rep(VarB1, VarB2)
                 ),
-                Match = no
-            )
+        var_reps_match(VarTable, VarA1, VarB1),
+        var_reps_match(VarTable, VarA2, VarB2)
         ;
-            InnerGoal = pg_other_atomic_goal,
             (
-                Builtin = not_builtin,
-                Match = no
+            AtomicRepA = pragma_foreign_code_rep(ArgsA),
+            AtomicRepB = pragma_foreign_code_rep(ArgsB)
             ;
-                ( Builtin = inline_builtin
-                ; Builtin = out_of_line_builtin
-                ),
-                Match = yes 
-            )
-        )
+            AtomicRepA = plain_call_rep(ModuleName, PredName, ArgsA),
+            AtomicRepB = plain_call_rep(ModuleName, PredName, ArgsB)
     ;
-        ( GoalExpr = conj(_, _)
-        ; GoalExpr = disj(_)
-        ; GoalExpr = switch(_, _, _)
-        ; GoalExpr = negation(_)
-        ; GoalExpr = scope(_, _)
-        ; GoalExpr = if_then_else(_, _, _, _)
-        ; GoalExpr = shorthand(_)
-        ),
-        unexpected(this_file, 
-            "Found non-atomic goal in pard_goal_match_hlds_goal")
+            AtomicRepA = builtin_call_rep(ModuleName, PredName, ArgsA),
+            AtomicRepB = builtin_call_rep(ModuleName, PredName, ArgsB)
+        ;
+            AtomicRepA = event_call_rep(EventName, ArgsA),
+            AtomicRepB = event_call_rep(EventName, ArgsB)
     ),
-    (
-        Match = yes,
-        MaybeGoal = yes(Goal),
-        GoalsBefore = [],
-        GoalsAfter = Goals
-    ;
-        Match = no,
-        pard_goal_match_hlds_goal(ProcInfo, InnerGoal, Goals, MaybeGoal,
-            GoalsBefore0, GoalsAfter),
-        GoalsBefore = [ Goal | GoalsBefore0 ]
+        zip_all_true(var_reps_match(VarTable), ArgsA, ArgsB)
     ).
 
+:- pred case_reps_match(var_table::in, case_rep(A)::in, case_rep(B)::in)
+    is semidet.
+
+case_reps_match(VarTable, case_rep(ConsId, OtherConsIds, GoalRep1),
+        case_rep(ConsId, OtherConsIds, GoalRep2)) :-
+    goal_reps_match(VarTable, GoalRep1, GoalRep2).
+
+:- pred var_reps_match(var_table::in, var_rep::in, var_rep::in) is semidet.
+
+var_reps_match(VarTable, VarA, VarB) :-
+    ( search_var_name(VarTable, VarA, _) ->
+        % Variables named by the programmer _must_ match, we expect to find
+        % them in the var table, and that they would be identical.  (Since one
+        % of the variables will be built using it's name and the var table
+        % constructed when converting the original code to byte code).
+        VarA = VarB
+    ;
+        % Unamed variables match implicitly.  They will usually be identical be
+        % we allow this to be releaxed so that the program may change a little
+        % after being profiled but before being parallelised.
+        true
+    ).
+
+:- pred maybe_var_reps_match(var_table::in, 
+    maybe(var_rep)::in, maybe(var_rep)::in) is semidet.
+
+maybe_var_reps_match(_, no, no).
+maybe_var_reps_match(VarTable, yes(VarA), yes(VarB)) :-
+    var_reps_match(VarTable, VarA, VarB).
+
+    % zip_all_true(Pred, ListA, ListB)
+    %
+    % True when lists have equal length and every corresponding pair of values
+    % from the lists satisifies Pred.
+    %
+:- pred zip_all_true(pred(A, B), list(A), list(B)).
+:- mode zip_all_true(pred(in, in) is semidet, in, in) is semidet.
+
+zip_all_true(_, [], []).
+zip_all_true(Pred, [A | As], [B | Bs]) :-
+    Pred(A, B),
+    zip_all_true(Pred, As, Bs).
+
 :- pred match_sym_name(sym_name::in, string::in, string::in) is semidet.
 
 match_sym_name(unqualified(ProcName), _, ProcName).
Index: compiler/instmap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/instmap.m,v
retrieving revision 1.66
diff -u -p -b -r1.66 instmap.m
--- compiler/instmap.m	3 Sep 2009 23:57:26 -0000	1.66
+++ compiler/instmap.m	30 Jun 2010 12:41:15 -0000
@@ -216,6 +216,12 @@
 :- pred apply_instmap_delta(instmap::in, instmap_delta::in,
     instmap::out) is det.
 
+    % A version of apply_instmap_delta that can be conveniently used with foldl
+    % or in state variable notation.
+    %
+:- pred apply_instmap_delta_sv(instmap_delta::in, instmap::in, instmap::out)
+    is det.
+
     % Given two instmap_deltas, overlay the entries in the second instmap_delta
     % on top of those in the first to produce a new instmap_delta.
     %
@@ -779,6 +785,9 @@ apply_instmap_delta(reachable(InstMappin
         reachable(InstMappingDelta), reachable(InstMapping)) :-
     map.overlay(InstMapping0, InstMappingDelta, InstMapping).
 
+apply_instmap_delta_sv(Delta, !Instmap) :-
+    apply_instmap_delta(!.Instmap, Delta, !:Instmap).
+
 instmap_delta_apply_instmap_delta(InstMap1, InstMap2, How, InstMap) :-
     (
         InstMap1 = unreachable,
Index: compiler/mercury_compile_middle_passes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile_middle_passes.m,v
retrieving revision 1.4
diff -u -p -b -r1.4 mercury_compile_middle_passes.m
--- compiler/mercury_compile_middle_passes.m	10 Jun 2010 00:58:17 -0000	1.4
+++ compiler/mercury_compile_middle_passes.m	2 Jul 2010 06:33:15 -0000
@@ -877,14 +877,7 @@ maybe_implicit_parallelism(Verbose, Stat
         maybe_write_string(Verbose, "% Applying implicit " ++
             "parallelism...\n", !IO),
         maybe_flush_output(Verbose, !IO),
-        apply_implicit_parallelism_transformation(!.HLDS, MaybeHLDS),
-        (
-            MaybeHLDS = ok(!:HLDS)
-        ;
-            MaybeHLDS = error(Error),
-            io.write_string(Error ++ "\n", !IO),
-            io.set_exit_status(1, !IO)
-        ),
+        apply_implicit_parallelism_transformation(!HLDS, !IO),
         maybe_write_string(Verbose, "% done.\n", !IO),
         maybe_report_stats(Stats, !IO)
     ;
Index: compiler/prog_rep.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_rep.m,v
retrieving revision 1.68
diff -u -p -b -r1.68 prog_rep.m
--- compiler/prog_rep.m	30 Oct 2009 03:33:18 -0000	1.68
+++ compiler/prog_rep.m	3 Jul 2010 05:33:13 -0000
@@ -25,6 +25,7 @@
 :- import_module hlds.instmap.
 :- import_module ll_backend.stack_layout.
 :- import_module parse_tree.prog_data.
+:- import_module mdbcomp.program_representation.
 
 :- import_module list.
 :- import_module map.
@@ -60,6 +61,20 @@
     string_table::in, string_table::out, list(int)::out) is det.
 
 %---------------------------------------------------------------------------%
+
+:- type prog_rep_info
+    --->    prog_rep_info(
+                pri_filename    :: string,
+                pri_vartypes    :: vartypes,
+                pri_var_num_map :: var_num_map,
+                pri_var_num_rep :: var_num_rep,
+                pri_module_info :: module_info
+            ).
+
+:- pred goal_to_goal_rep(prog_rep_info::in, instmap::in, hlds_goal::in, 
+    goal_rep::out) is det.
+
+%---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -73,26 +88,18 @@
 :- import_module libs.compiler_util.
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
-:- import_module mdbcomp.program_representation.
 :- import_module parse_tree.prog_util.
 
 :- import_module int.
 :- import_module maybe.
 :- import_module set.
+:- import_module std_util.
 :- import_module string.
 :- import_module term.
+:- import_module unit.
 
 %---------------------------------------------------------------------------%
 
-:- type prog_rep_info
-    --->    prog_rep_info(
-                pri_filename    :: string,
-                pri_vartypes    :: vartypes,
-                pri_var_num_map :: var_num_map,
-                pri_var_num_rep :: var_num_rep,
-                pri_module_info :: module_info
-            ).
-
 represent_proc_as_bytecodes(HeadVars, Goal, InstMap0, VarTypes, VarNumMap,
         ModuleInfo, IncludeVarTable, ProcDetism, !StringTable, ProcRepBytes) :-
     Goal = hlds_goal(_, GoalInfo),
@@ -196,6 +203,7 @@ compiler_introduced_varname(VarName) :-
     ; Prefix = "TypeInfo_"
     ; Prefix = "TypeCtorInfo_"
     ; Prefix = "STATE_VARIABLE_"
+    ; Prefix = "DCG_"
     ),
     prefix(VarName, Prefix).
 
@@ -204,167 +212,148 @@ compiler_introduced_varname(VarName) :-
 :- pred goal_to_byte_list(hlds_goal::in, instmap::in, prog_rep_info::in,
     list(int)::out, string_table::in, string_table::out) is det.
 
-goal_to_byte_list(hlds_goal(GoalExpr, GoalInfo), InstMap0, Info, Bytes,
-        !StringTable) :-
+goal_to_byte_list(Goal, InstMap0, Info, Bytes, !StringTable) :-
+    goal_to_goal_rep(Info, InstMap0, Goal, GoalRep),
+    goal_rep_to_byte_list(Info, GoalRep, Bytes, !StringTable).
+
+goal_to_goal_rep(Info, Instmap0, hlds_goal(GoalExpr, GoalInfo), GoalRep) :-
+    Detism = goal_info_get_determinism(GoalInfo),
+    detism_to_detism_rep(Detism, DetismRep),
+    GoalRep = goal_rep(GoalExprRep, DetismRep, unit),
     (
         GoalExpr = conj(ConjType, Goals),
         expect(unify(ConjType, plain_conj), this_file,
             "non-plain conjunction and declarative debugging"),
-        conj_to_byte_list(Goals, InstMap0, Info, ConjBytes, !StringTable),
-        ExprBytes = [goal_type_to_byte(goal_conj)] ++
-            length_to_byte_list(Goals) ++ ConjBytes
+        conj_to_conj_rep(Info, Instmap0, Goals, GoalReps),
+        GoalExprRep = conj_rep(GoalReps)
     ;
         GoalExpr = disj(Goals),
-        disj_to_byte_list(Goals, InstMap0, Info, DisjBytes, !StringTable),
-        ExprBytes = [goal_type_to_byte(goal_disj)] ++
-            length_to_byte_list(Goals) ++ DisjBytes
+        % Since eash disjunct begins with the same instmap we can use map
+        map(goal_to_goal_rep(Info, Instmap0), Goals, GoalReps),
+        GoalExprRep = disj_rep(GoalReps)
     ;
         GoalExpr = negation(SubGoal),
-        goal_to_byte_list(SubGoal, InstMap0, Info, SubGoalBytes, !StringTable),
-        ExprBytes = [goal_type_to_byte(goal_neg)] ++ SubGoalBytes
+        goal_to_goal_rep(Info, Instmap0, SubGoal, SubGoalRep),
+        GoalExprRep = negation_rep(SubGoalRep)
     ;
         GoalExpr = if_then_else(_, Cond, Then, Else),
         Cond = hlds_goal(_, CondGoalInfo),
-        InstMapDelta = goal_info_get_instmap_delta(CondGoalInfo),
-        instmap.apply_instmap_delta(InstMap0, InstMapDelta, InstMap1),
-        goal_to_byte_list(Cond, InstMap0, Info, CondBytes, !StringTable),
-        goal_to_byte_list(Then, InstMap1, Info, ThenBytes, !StringTable),
-        goal_to_byte_list(Else, InstMap0, Info, ElseBytes, !StringTable),
-        ExprBytes = [goal_type_to_byte(goal_ite)] ++
-            CondBytes ++ ThenBytes ++ ElseBytes
+        InstmapDelta = goal_info_get_instmap_delta(CondGoalInfo),
+        instmap.apply_instmap_delta(Instmap0, InstmapDelta, InstmapAfterCond),
+        goal_to_goal_rep(Info, Instmap0, Cond, CondRep),
+        goal_to_goal_rep(Info, InstmapAfterCond, Then, ThenRep),
+        goal_to_goal_rep(Info, Instmap0, Else, ElseRep),
+        GoalExprRep = ite_rep(CondRep, ThenRep, ElseRep)
+    ;
+        GoalExpr = switch(Var, CanFail, Cases),
+        map(case_to_case_rep(Info, Instmap0), Cases, CasesRep),
+        (
+            CanFail = can_fail,
+            CanFailRep = switch_can_fail_rep
+        ;
+            CanFail = cannot_fail,
+            CanFailRep = switch_can_not_fail_rep
+        ),
+        VarRep = var_to_var_rep(Info, Var),
+        GoalExprRep = switch_rep(VarRep, CanFailRep, CasesRep)
+    ;
+        GoalExpr = scope(_, SubGoal),
+        SubGoal = hlds_goal(_, SubGoalInfo),
+        goal_to_goal_rep(Info, Instmap0, SubGoal, SubGoalRep), 
+        OuterDetism = goal_info_get_determinism(GoalInfo),
+        InnerDetism = goal_info_get_determinism(SubGoalInfo),
+        ( InnerDetism = OuterDetism ->
+            MaybeCut = scope_is_no_cut 
+        ;
+            MaybeCut = scope_is_cut
+        ),
+        GoalExprRep = scope_rep(SubGoalRep, MaybeCut)
     ;
+        ( GoalExpr = unify(_, _, _, _, _)
+        ; GoalExpr = generic_call(_, _, _, _)
+        ; GoalExpr = plain_call(_, _, _, _, _, _)
+        ; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
+        ),
+        (
         GoalExpr = unify(_, _, _, Uni, _),
-        atomic_goal_info_to_byte_list(GoalInfo, InstMap0, Info,
-            AtomicBytes, BoundVars, !StringTable),
         (
             Uni = assign(Target, Source),
-            ExprBytes = [goal_type_to_byte(goal_assign)] ++
-                var_to_byte_list(Info, Target) ++
-                var_to_byte_list(Info, Source) ++
-                AtomicBytes
-        ;
-            Uni = construct(Var, ConsId, Args, ArgModes, _, _, _),
-            cons_id_to_byte_list(ConsId, ConsIdBytes, !StringTable),
+                AtomicGoalRep = unify_assign_rep(
+                    var_to_var_rep(Info, Target), 
+                    var_to_var_rep(Info, Source))
+            ;
+                ( Uni = construct(Var, ConsId, Args, ArgModes, _, _, _)
+                ; Uni = deconstruct(Var, ConsId, Args, ArgModes, _, _)
+                ),
+                VarRep = var_to_var_rep(Info, Var),
+                ConsIdRep = cons_id_rep(ConsId),
+                ArgsRep = map(var_to_var_rep(Info), Args),
+                filter_input_args(Info, ArgModes, Args, MaybeArgs),
+                MaybeArgsRep = map(map_maybe(var_to_var_rep(Info)), MaybeArgs),
+                (
+                    Uni = construct(_, _, _, _, _, _, _),
             ( list.all_true(lhs_final_is_ground(Info), ArgModes) ->
-                ExprBytes = [goal_type_to_byte(goal_construct)] ++
-                    var_to_byte_list(Info, Var) ++
-                    ConsIdBytes ++
-                    vars_to_byte_list(Info, Args) ++
-                    AtomicBytes
+                        AtomicGoalRep = unify_construct_rep(VarRep, ConsIdRep, 
+                            ArgsRep)
             ;
-                filter_input_args(Info, ArgModes, Args, MaybeArgs),
-                ExprBytes = [goal_type_to_byte(goal_partial_construct)] ++
-                    var_to_byte_list(Info, Var) ++
-                    ConsIdBytes ++
-                    maybe_vars_to_byte_list(Info, MaybeArgs) ++
-                    AtomicBytes
+                        AtomicGoalRep = partial_construct_rep(VarRep, ConsIdRep,
+                            MaybeArgsRep)
             )
         ;
-            Uni = deconstruct(Var, ConsId, Args, ArgModes, _, _),
-            cons_id_to_byte_list(ConsId, ConsIdBytes, !StringTable),
+                    Uni = deconstruct(_, _, _, _, _, _),
             ( list.member(Var, BoundVars) ->
-                filter_input_args(Info, ArgModes, Args, MaybeArgs),
-                ExprBytes = [goal_type_to_byte(goal_partial_deconstruct)]++
-                    var_to_byte_list(Info, Var) ++
-                    ConsIdBytes ++
-                    maybe_vars_to_byte_list(Info, MaybeArgs) ++
-                    AtomicBytes
+                        AtomicGoalRep = partial_deconstruct_rep(VarRep,
+                            ConsIdRep, MaybeArgsRep)
             ;
-                ExprBytes = [goal_type_to_byte(goal_deconstruct)] ++
-                    var_to_byte_list(Info, Var) ++
-                    ConsIdBytes ++
-                    vars_to_byte_list(Info, Args) ++
-                    AtomicBytes
+                        AtomicGoalRep = unify_deconstruct_rep(VarRep, ConsIdRep,
+                            ArgsRep)
+                    )
             )
         ;
             Uni = simple_test(Var1, Var2),
-            ExprBytes = [goal_type_to_byte(goal_simple_test)] ++
-                var_to_byte_list(Info, Var1) ++
-                var_to_byte_list(Info, Var2) ++
-                AtomicBytes
+                AtomicGoalRep = unify_simple_test_rep(
+                    var_to_var_rep(Info, Var1), 
+                    var_to_var_rep(Info, Var2))
         ;
             Uni = complicated_unify(_, _, _),
             unexpected(this_file, "goal_expr_to_byte_list: complicated_unify")
         )
     ;
-        GoalExpr = switch(SwitchVar, CanFail, Cases),
-        cases_to_byte_list(Cases, InstMap0, Info, CasesBytes, !StringTable),
-        CanFailByte = can_fail_to_byte(CanFail),
-        ExprBytes = [goal_type_to_byte(goal_switch)] ++
-            [CanFailByte] ++
-            var_to_byte_list(Info, SwitchVar) ++
-            length_to_byte_list(Cases) ++ CasesBytes
-    ;
-        GoalExpr = scope(_, SubGoal),
-        SubGoal = hlds_goal(_, SuboalInfo),
-        OuterDetism = goal_info_get_determinism(GoalInfo),
-        InnerDetism = goal_info_get_determinism(SuboalInfo),
-        ( InnerDetism = OuterDetism ->
-            MaybeCut = 0
-        ;
-            MaybeCut = 1
-        ),
-        goal_to_byte_list(SubGoal, InstMap0, Info, GoalBytes, !StringTable),
-        ExprBytes = [goal_type_to_byte(goal_scope)] ++ [MaybeCut] ++ GoalBytes
-    ;
         GoalExpr = generic_call(GenericCall, Args, _, _),
-        atomic_goal_info_to_byte_list(GoalInfo, InstMap0, Info,
-            AtomicBytes, _BoundVars, !StringTable),
+            ArgsRep = map(var_to_var_rep(Info), Args),
         (
             GenericCall = higher_order(PredVar, _, _, _),
-            ExprBytes = [goal_type_to_byte(goal_ho_call)] ++
-                var_to_byte_list(Info, PredVar) ++
-                vars_to_byte_list(Info, Args) ++
-                AtomicBytes
+                PredVarRep = var_to_var_rep(Info, PredVar),
+                AtomicGoalRep = higher_order_call_rep(PredVarRep, ArgsRep)
         ;
-            GenericCall = class_method(Var, MethodNum, _, _),
-            ExprBytes = [goal_type_to_byte(goal_method_call)] ++
-                var_to_byte_list(Info, Var) ++
-                method_num_to_byte_list(MethodNum) ++
-                vars_to_byte_list(Info, Args) ++
-                AtomicBytes
+                GenericCall = class_method(Var, Num, _, _),
+                VarRep = var_to_var_rep(Info, Var),
+                AtomicGoalRep = method_call_rep(VarRep, Num, ArgsRep)
         ;
             GenericCall = event_call(EventName),
-            string_to_byte_list(EventName, EventNameBytes, !StringTable),
-            ExprBytes = [goal_type_to_byte(goal_event_call)] ++
-                EventNameBytes ++
-                vars_to_byte_list(Info, Args) ++
-                AtomicBytes
+                AtomicGoalRep = event_call_rep(EventName, ArgsRep)
         ;
             GenericCall = cast(_),
-            ( Args = [InputArg, OutputArg] ->
-                ExprBytes = [goal_type_to_byte(goal_cast)] ++
-                    var_to_byte_list(Info, OutputArg) ++
-                    var_to_byte_list(Info, InputArg) ++
-                    AtomicBytes
+                ( ArgsRep = [InputArgRep, OutputArgRep] ->
+                    AtomicGoalRep = cast_rep(OutputArgRep, InputArgRep) 
             ;
-                unexpected(this_file, "goal_expr_to_byte_list: cast arity != 2")
+                    unexpected(this_file, 
+                        "goal_expr_goal_expr_rep: cast arity != 2")
             )
         )
     ;
         GoalExpr = plain_call(PredId, _, Args, Builtin, _, _),
-        atomic_goal_info_to_byte_list(GoalInfo, InstMap0, Info,
-            AtomicBytes, _BoundVars, !StringTable),
         module_info_pred_info(Info ^ pri_module_info, PredId, PredInfo),
         ModuleSymName = pred_info_module(PredInfo),
         ModuleName = sym_name_to_string(ModuleSymName),
         PredName = pred_info_name(PredInfo),
-        string_to_byte_list(ModuleName, ModuleNameBytes, !StringTable),
-        string_to_byte_list(PredName, PredNameBytes, !StringTable),
+            ArgsRep = map(var_to_var_rep(Info), Args),
         (
             Builtin = not_builtin,
-            ExprBytes = [goal_type_to_byte(goal_plain_call)] ++
-                ModuleNameBytes ++
-                PredNameBytes ++
-                vars_to_byte_list(Info, Args) ++
-                AtomicBytes
+                AtomicGoalRep = plain_call_rep(ModuleName, PredName, ArgsRep)
         ;
             Builtin = inline_builtin,
-            ExprBytes = [goal_type_to_byte(goal_builtin_call)] ++
-                ModuleNameBytes ++
-                PredNameBytes ++
-                vars_to_byte_list(Info, Args) ++
-                AtomicBytes
+                AtomicGoalRep = builtin_call_rep(ModuleName, PredName, ArgsRep)
         ;
             Builtin = out_of_line_builtin,
             unexpected(this_file,
@@ -372,23 +361,218 @@ goal_to_byte_list(hlds_goal(GoalExpr, Go
         )
     ;
         GoalExpr = call_foreign_proc(_, _PredId, _, Args, _, _, _),
-        ArgVars = list.map(foreign_arg_var, Args),
-        atomic_goal_info_to_byte_list(GoalInfo, InstMap0, Info,
-            AtomicBytes, _BoundVars, !StringTable),
-        ExprBytes = [goal_type_to_byte(goal_foreign)] ++
-            vars_to_byte_list(Info, ArgVars) ++ AtomicBytes
+            ArgVarsRep = list.map(
+                compose(var_to_var_rep(Info), foreign_arg_var), Args),
+            AtomicGoalRep = pragma_foreign_code_rep(ArgVarsRep)
+        ),
+        goal_info_to_atomic_goal_rep_fields(GoalInfo, Instmap0, Info, 
+            FileName, LineNo, BoundVars),
+        BoundVarsRep = map(var_to_var_rep(Info), BoundVars),
+        GoalExprRep = atomic_goal_rep(FileName, LineNo, BoundVarsRep, 
+            AtomicGoalRep)
     ;
         GoalExpr = shorthand(_),
         % These should have been expanded out by now.
         unexpected(this_file, "goal_expr_to_byte_list: unexpected shorthand")
-    ),
+    ).
     
-    % Include determinism in the bytecode.
-    Detism = goal_info_get_determinism(GoalInfo),
-    DetismByte = represent_determinism(Detism),
+:- pred conj_to_conj_rep(prog_rep_info::in, instmap::in, list(hlds_goal)::in,
+    list(goal_rep)::out) is det.
+
+conj_to_conj_rep(_, _, [], []).
+conj_to_conj_rep(Info, Instmap0, [Conj | Conjs], [ConjRep | ConjReps]) :-
+    goal_to_goal_rep(Info, Instmap0, Conj, ConjRep),
+    GoalInfo = Conj ^ hlds_goal_info,
+    InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
+    instmap.apply_instmap_delta(Instmap0, InstmapDelta, Instmap1),
+    conj_to_conj_rep(Info, Instmap1, Conjs, ConjReps).
+
+:- pred case_to_case_rep(prog_rep_info::in, instmap::in, 
+    case::in, case_rep::out) is det.
+
+case_to_case_rep(Info, Instmap, case(FirstConsId, OtherConsIds, Goal), 
+        case_rep(FirstConsIdRep, OtherConsIdsRep, GoalRep)) :-
+    goal_to_goal_rep(Info, Instmap, Goal, GoalRep),
+    cons_id_to_cons_id_rep(FirstConsId, FirstConsIdRep),
+    map(cons_id_to_cons_id_rep, OtherConsIds, OtherConsIdsRep).
+
+:- pred cons_id_to_cons_id_rep(cons_id::in, cons_id_arity_rep::out) is det.
+
+cons_id_to_cons_id_rep(ConsId, cons_id_arity_rep(ConsIdName, Arity)) :-
+    ConsIdName = cons_id_rep(ConsId),
+    MaybeArity = cons_id_maybe_arity(ConsId),
+    (
+        MaybeArity = yes(Arity)
+    ;
+        MaybeArity = no,
+        Arity = 0
+    ).
+
+:- pred detism_to_detism_rep(determinism::in, detism_rep::out) is det.
 
+detism_to_detism_rep(detism_det, det_rep).
+detism_to_detism_rep(detism_semi, semidet_rep).
+detism_to_detism_rep(detism_multi, multidet_rep).
+detism_to_detism_rep(detism_non, nondet_rep).
+detism_to_detism_rep(detism_cc_multi, cc_multidet_rep).
+detism_to_detism_rep(detism_cc_non, cc_nondet_rep).
+detism_to_detism_rep(detism_erroneous, erroneous_rep).
+detism_to_detism_rep(detism_failure, failure_rep).
+
+:- pred goal_rep_to_byte_list(prog_rep_info::in, goal_rep::in, 
+    list(int)::out, string_table::in, string_table::out) is det.
+
+goal_rep_to_byte_list(Info, goal_rep(GoalExpr, Detism, _), Bytes, !StringTable) :-
+    (
+        GoalExpr = conj_rep(GoalReps),
+        map_foldl(goal_rep_to_byte_list(Info), GoalReps, ConjBytesList,
+            !StringTable),
+        ExprBytes = [goal_type_to_byte(goal_conj)] ++
+            length_to_byte_list(GoalReps) ++ condense(ConjBytesList)
+    ;
+        GoalExpr = disj_rep(GoalReps),
+        map_foldl(goal_rep_to_byte_list(Info), GoalReps, DisjBytesList,
+            !StringTable),
+        ExprBytes = [goal_type_to_byte(goal_disj)] ++
+            length_to_byte_list(GoalReps) ++ condense(DisjBytesList)
+    ;
+        GoalExpr = negation_rep(SubGoal),
+        goal_rep_to_byte_list(Info, SubGoal, SubGoalBytes, !StringTable),
+        ExprBytes = [goal_type_to_byte(goal_neg)] ++ SubGoalBytes
+    ;
+        GoalExpr = ite_rep(Cond, Then, Else), 
+        goal_rep_to_byte_list(Info, Cond, CondBytes, !StringTable),
+        goal_rep_to_byte_list(Info, Then, ThenBytes, !StringTable),
+        goal_rep_to_byte_list(Info, Else, ElseBytes, !StringTable),
+        ExprBytes = [goal_type_to_byte(goal_ite)] ++
+            CondBytes ++ ThenBytes ++ ElseBytes
+    ;
+        GoalExpr = atomic_goal_rep(FileName, Line, BoundVars, AtomicGoalRep),
+        string_to_byte_list(FileName, FileNameBytes, !StringTable),
+        AtomicBytes = FileNameBytes ++ lineno_to_byte_list(Line) ++
+            var_reps_to_byte_list(Info, BoundVars), 
+        (
+            AtomicGoalRep = unify_assign_rep(Target, Source),
+            ExprBytes = [goal_type_to_byte(goal_assign)] ++
+                var_rep_to_byte_list(Info, Target) ++
+                var_rep_to_byte_list(Info, Source) ++
+                AtomicBytes
+        ;
+            ( AtomicGoalRep = unify_construct_rep(_, _, _)
+            ; AtomicGoalRep = unify_deconstruct_rep(_, _, _)
+            ; AtomicGoalRep = partial_construct_rep(_, _, _)
+            ; AtomicGoalRep = partial_deconstruct_rep(_, _, _)
+            ),
+            (
+                (
+                    AtomicGoalRep = unify_construct_rep(Var, ConsId, Args),
+                    AtomicTypeByte = goal_type_to_byte(goal_construct) 
+                ; 
+                    AtomicGoalRep = unify_deconstruct_rep(Var, ConsId, Args),
+                    AtomicTypeByte = goal_type_to_byte(goal_deconstruct)
+                ),
+                ArgsBytes = var_reps_to_byte_list(Info, Args)
+            ;
+                (
+                    AtomicGoalRep = partial_deconstruct_rep(Var, ConsId,
+                        MaybeArgs),
+                    AtomicTypeByte = 
+                        goal_type_to_byte(goal_partial_deconstruct)
+                ;
+                    AtomicGoalRep = partial_construct_rep(Var, ConsId,
+                        MaybeArgs),
+                    AtomicTypeByte = goal_type_to_byte(goal_partial_construct)
+                ),
+                ArgsBytes = maybe_var_reps_to_byte_list(Info, MaybeArgs)
+            ),
+            string_to_byte_list(ConsId, ConsIdBytes, !StringTable),
+            VarBytes = var_rep_to_byte_list(Info, Var),
+            ExprBytes = [AtomicTypeByte] ++ VarBytes ++ ConsIdBytes ++
+                ArgsBytes ++ AtomicBytes
+        ;
+            AtomicGoalRep = unify_simple_test_rep(Var1, Var2),
+            ExprBytes = [goal_type_to_byte(goal_simple_test)] ++
+                var_rep_to_byte_list(Info, Var1) ++
+                var_rep_to_byte_list(Info, Var2) ++
+                AtomicBytes
+        ;
+            AtomicGoalRep = higher_order_call_rep(PredVar, Args),
+            ExprBytes = [goal_type_to_byte(goal_ho_call)] ++
+                var_rep_to_byte_list(Info, PredVar) ++
+                var_reps_to_byte_list(Info, Args) ++
+                AtomicBytes
+        ;
+            AtomicGoalRep = method_call_rep(Var, MethodNum, Args),
+            ExprBytes = [goal_type_to_byte(goal_method_call)] ++
+                var_rep_to_byte_list(Info, Var) ++
+                method_num_to_byte_list(MethodNum) ++
+                var_reps_to_byte_list(Info, Args) ++
+                AtomicBytes
+        ;
+            AtomicGoalRep = event_call_rep(EventName, Args),
+            string_to_byte_list(EventName, EventNameBytes, !StringTable),
+            ExprBytes = [goal_type_to_byte(goal_event_call)] ++
+                EventNameBytes ++
+                var_reps_to_byte_list(Info, Args) ++
+                AtomicBytes
+        ;
+            AtomicGoalRep = cast_rep(Target, Source),
+            ExprBytes = [goal_type_to_byte(goal_cast)] ++
+                var_rep_to_byte_list(Info, Target) ++
+                var_rep_to_byte_list(Info, Source) ++
+                AtomicBytes
+        ;
+            (
+                AtomicGoalRep = plain_call_rep(ModuleName, PredName, Args),
+                CallType = goal_plain_call
+            ;   
+                AtomicGoalRep = builtin_call_rep(ModuleName, PredName, Args),
+                CallType = goal_builtin_call
+            ),
+            string_to_byte_list(ModuleName, ModuleNameBytes, !StringTable),
+            string_to_byte_list(PredName, PredNameBytes, !StringTable),
+            ExprBytes = [goal_type_to_byte(CallType)] ++
+                ModuleNameBytes ++
+                PredNameBytes ++
+                var_reps_to_byte_list(Info, Args) ++
+                AtomicBytes
+        ;
+            AtomicGoalRep = pragma_foreign_code_rep(Args),
+            ExprBytes = [goal_type_to_byte(goal_foreign)] ++
+                var_reps_to_byte_list(Info, Args) ++ AtomicBytes
+        )
+    ;
+        GoalExpr = switch_rep(SwitchVar, CanFail, Cases),
+        map_foldl(case_rep_to_byte_list(Info), Cases, CasesBytesList,
+            !StringTable),
+        can_fail_byte(CanFail, CanFailByte),
+        ExprBytes = [goal_type_to_byte(goal_switch)] ++
+            [CanFailByte] ++
+            var_rep_to_byte_list(Info, SwitchVar) ++
+            length_to_byte_list(Cases) ++ condense(CasesBytesList) 
+    ;
+        GoalExpr = scope_rep(SubGoal, MaybeCut),
+        cut_byte(MaybeCut, MaybeCutByte),
+        goal_rep_to_byte_list(Info, SubGoal, SubGoalBytes, !StringTable),  
+        ExprBytes = [goal_type_to_byte(goal_scope)] ++ [MaybeCutByte] ++ 
+            SubGoalBytes
+    ),
+    determinism_representation(Detism, DetismByte),
     Bytes = ExprBytes ++ [DetismByte].
 
+:- pred case_rep_to_byte_list(prog_rep_info::in, case_rep::in, list(int)::out,
+    string_table::in, string_table::out) is det.
+
+case_rep_to_byte_list(Info, Case, Bytes, !StringTable) :-
+    Case = case_rep(MainConsId, OtherConsIds, Goal),
+    goal_rep_to_byte_list(Info, Goal, GoalBytes, !StringTable),
+    cons_id_and_arity_rep_to_byte_list(MainConsId, MainConsIdBytes,
+        !StringTable),
+    map_foldl(cons_id_and_arity_rep_to_byte_list, 
+        OtherConsIds, OtherConsIdsByteLists, !StringTable),
+    Bytes = MainConsIdBytes ++ length_to_byte_list(OtherConsIds) ++
+        condense(OtherConsIdsByteLists) ++ GoalBytes.
+
 :- pred lhs_final_is_ground(prog_rep_info::in, uni_mode::in) is semidet.
 
 lhs_final_is_ground(Info, (_ - _) -> (LHSFinalInst - _)) :-
@@ -418,12 +602,11 @@ filter_input_args(_, [_ | _], [], _) :-
 
 %---------------------------------------------------------------------------%
 
-:- pred atomic_goal_info_to_byte_list(hlds_goal_info::in, instmap::in,
-    prog_rep_info::in, list(int)::out, list(prog_var)::out,
-    string_table::in, string_table::out) is det.
+:- pred goal_info_to_atomic_goal_rep_fields(hlds_goal_info::in, instmap::in,
+    prog_rep_info::in, string::out, int::out, list(prog_var)::out) is det.
 
-atomic_goal_info_to_byte_list(GoalInfo, InstMap0, Info, Bytes, BoundVars,
-        !StringTable) :-
+goal_info_to_atomic_goal_rep_fields(GoalInfo, Instmap0, Info, FileName, LineNo,
+        BoundVars) :-
     Context = goal_info_get_context(GoalInfo),
     term.context_file(Context, FileName0),
     ( FileName0 = Info ^ pri_filename ->
@@ -432,28 +615,18 @@ atomic_goal_info_to_byte_list(GoalInfo, 
         FileName = FileName0
     ),
     term.context_line(Context, LineNo),
-    InstMapDelta = goal_info_get_instmap_delta(GoalInfo),
-    instmap.apply_instmap_delta(InstMap0, InstMapDelta, InstMap),
-    instmap_changed_vars(InstMap0, InstMap, Info ^ pri_vartypes,
+    InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
+    instmap.apply_instmap_delta(Instmap0, InstmapDelta, Instmap),
+    instmap_changed_vars(Instmap0, Instmap, Info ^ pri_vartypes,
         Info ^ pri_module_info, ChangedVars),
-    set.to_sorted_list(ChangedVars, BoundVars),
-    string_to_byte_list(FileName, FileNameBytes, !StringTable),
-    Bytes = FileNameBytes ++
-        lineno_to_byte_list(LineNo) ++
-        vars_to_byte_list(Info, BoundVars).
+    set.to_sorted_list(ChangedVars, BoundVars).
 
-:- pred cons_id_and_arity_to_byte_list(cons_id::in, list(int)::out,
-    string_table::in, string_table::out) is det.
+:- pred cons_id_and_arity_rep_to_byte_list(cons_id_arity_rep::in, 
+    list(int)::out, string_table::in, string_table::out) is det.
 
-cons_id_and_arity_to_byte_list(ConsId, ConsIdBytes, !StringTable) :-
-    cons_id_to_byte_list(ConsId, FunctorBytes, !StringTable),
-    MaybeArity = cons_id_maybe_arity(ConsId),
-    (
-        MaybeArity = yes(Arity)
-    ;
-        MaybeArity = no,
-        Arity = 0
-    ),
+cons_id_and_arity_rep_to_byte_list(ConsIdArity, ConsIdBytes, !StringTable) :-
+    ConsIdArity = cons_id_arity_rep(ConsId, Arity),
+    string_to_byte_list(ConsId, FunctorBytes, !StringTable),
     short_to_byte_list(Arity, ArityBytes),
     ConsIdBytes = FunctorBytes ++ ArityBytes.
 
@@ -491,49 +664,6 @@ sym_base_name_to_string(qualified(_, Str
 
 %---------------------------------------------------------------------------%
 
-:- pred conj_to_byte_list(hlds_goals::in, instmap::in, prog_rep_info::in,
-    list(int)::out, string_table::in, string_table::out) is det.
-
-conj_to_byte_list([], _, _, [], !StringTable).
-conj_to_byte_list([Goal | Goals], InstMap0, Info, Bytes, !StringTable) :-
-    goal_to_byte_list(Goal, InstMap0, Info, GoalBytes, !StringTable),
-    Goal = hlds_goal(_, GoalInfo),
-    InstMapDelta = goal_info_get_instmap_delta(GoalInfo),
-    instmap.apply_instmap_delta(InstMap0, InstMapDelta, InstMap1),
-    conj_to_byte_list(Goals, InstMap1, Info, GoalsBytes, !StringTable),
-    Bytes = GoalBytes ++ GoalsBytes.
-
-%---------------------------------------------------------------------------%
-
-:- pred disj_to_byte_list(hlds_goals::in, instmap::in, prog_rep_info::in,
-    list(int)::out, string_table::in, string_table::out) is det.
-
-disj_to_byte_list([], _, _, [], !StringTable).
-disj_to_byte_list([Goal | Goals], InstMap0, Info, Bytes, !StringTable) :-
-    goal_to_byte_list(Goal, InstMap0, Info, GoalBytes, !StringTable),
-    disj_to_byte_list(Goals, InstMap0, Info, GoalsBytes, !StringTable),
-    Bytes = GoalBytes ++ GoalsBytes.
-
-%---------------------------------------------------------------------------%
-
-:- pred cases_to_byte_list(list(case)::in, instmap::in, prog_rep_info::in,
-    list(int)::out, string_table::in, string_table::out) is det.
-
-cases_to_byte_list([], _, _, [], !StringTable).
-cases_to_byte_list([Case | Cases], InstMap0, Info, Bytes, !StringTable) :-
-    Case = case(MainConsId, OtherConsIds, Goal),
-    cons_id_and_arity_to_byte_list(MainConsId, MainConsIdBytes, !StringTable),
-    list.map_foldl(cons_id_and_arity_to_byte_list, OtherConsIds,
-        OtherConsIdsByteLists, !StringTable),
-    list.condense(OtherConsIdsByteLists, OtherConsIdsBytes),
-    NumOtherConsIdBytes = length_to_byte_list(OtherConsIds),
-    goal_to_byte_list(Goal, InstMap0, Info, GoalBytes, !StringTable),
-    cases_to_byte_list(Cases, InstMap0, Info, CasesBytes, !StringTable),
-    Bytes = MainConsIdBytes ++ NumOtherConsIdBytes ++ OtherConsIdsBytes
-        ++ GoalBytes ++ CasesBytes.
-
-%---------------------------------------------------------------------------%
-
 % The operations to convert primitive constructs to bytecode.
 %
 % We use the operations defined in bytecode_data. Each of the functions below
@@ -552,39 +682,43 @@ string_to_byte_list(String, Bytes, !Stri
     stack_layout.lookup_string_in_table(String, Index, !StringTable),
     int32_to_byte_list(Index, Bytes).
 
-:- func vars_to_byte_list(prog_rep_info, list(prog_var)) = list(int).
+:- func var_reps_to_byte_list(prog_rep_info, list(var_rep)) = list(int).
 
-vars_to_byte_list(Info, Vars) =
+var_reps_to_byte_list(Info, Vars) =
     length_to_byte_list(Vars) ++
-    list.condense(list.map(var_to_byte_list(Info), Vars)).
+    list.condense(list.map(var_rep_to_byte_list(Info), Vars)).
+
+:- func var_to_var_rep(prog_rep_info, prog_var) = int.
 
-:- func var_to_byte_list(prog_rep_info, prog_var) = list(int).
+var_to_var_rep(Info, Var) = Num :-
+    map.lookup(Info ^ pri_var_num_map, Var, Num - _).
 
-var_to_byte_list(Info, Var) = Bytes :-
-    map.lookup(Info ^ pri_var_num_map, Var, VarNum - _),
+:- func var_rep_to_byte_list(prog_rep_info, var_rep) = list(int).
+
+var_rep_to_byte_list(Info, Var) = Bytes :-
     (
         Info ^ pri_var_num_rep = byte,
-        Bytes = [VarNum]
+        Bytes = [Var]
     ;
         Info ^ pri_var_num_rep = short,
-        short_to_byte_list(VarNum, Bytes)
+        short_to_byte_list(Var, Bytes)
     ).
 
-:- func maybe_vars_to_byte_list(prog_rep_info, list(maybe(prog_var))) =
+:- func maybe_var_reps_to_byte_list(prog_rep_info, list(maybe(var_rep))) =
     list(int).
 
-maybe_vars_to_byte_list(Info, Vars) =
+maybe_var_reps_to_byte_list(Info, Vars) =
     length_to_byte_list(Vars) ++
-    list.condense(list.map(maybe_var_to_byte_list(Info), Vars)).
+    list.condense(list.map(maybe_var_rep_to_byte_list(Info), Vars)).
 
-:- func maybe_var_to_byte_list(prog_rep_info, maybe(prog_var)) = list(int).
+:- func maybe_var_rep_to_byte_list(prog_rep_info, maybe(var_rep)) = list(int).
 
-maybe_var_to_byte_list(Info, MaybeVar) = Bytes :-
-    % This is not the most efficient representation, however maybe(prog_var)s
+maybe_var_rep_to_byte_list(Info, MaybeVar) = Bytes :-
+    % This is not the most efficient representation, however maybe(var_rep)s
     % are only used for partial unifications which are rare.
     (
         MaybeVar = yes(Var),
-        Bytes = [1 | var_to_byte_list(Info, Var)]
+        Bytes = [1 | var_rep_to_byte_list(Info, Var)]
     ;
         MaybeVar = no,
         Bytes = [0]
@@ -602,7 +736,7 @@ head_vars_to_byte_list(Info, InitialInst
     prog_var) = list(int).
 
 head_var_to_byte_list(Info, InitialInstmap, InstmapDelta, Var) = Bytes :-
-    var_to_byte_list(Info, Var) = VarBytes,
+    var_rep_to_byte_list(Info, var_to_var_rep(Info, Var)) = VarBytes,
     ModuleInfo = Info ^ pri_module_info,
     instmap_lookup_var(InitialInstmap, Var, InitialInst),
     ( instmap_delta_search_var(InstmapDelta, Var, FinalInstPrime) ->
@@ -649,11 +783,6 @@ lineno_to_byte_list(VarNum) = Bytes :-
 method_num_to_byte_list(VarNum) = Bytes :-
     short_to_byte_list(VarNum, Bytes).
 
-:- func can_fail_to_byte(can_fail) = int.
-
-can_fail_to_byte(can_fail) = 0.
-can_fail_to_byte(cannot_fail) = 1.
-
 %---------------------------------------------------------------------------%
 
 :- func this_file = string.
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.150
diff -u -p -b -r1.150 stack_layout.m
--- compiler/stack_layout.m	30 Oct 2009 03:33:18 -0000	1.150
+++ compiler/stack_layout.m	30 Jun 2010 12:41:15 -0000
@@ -30,12 +30,14 @@
 :- module ll_backend.stack_layout.
 :- interface.
 
+:- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
 :- import_module ll_backend.continuation_info.
 :- import_module ll_backend.global_data.
 :- import_module ll_backend.layout.
 :- import_module ll_backend.llds.
+:- import_module ll_backend.prog_rep.
 :- import_module mdbcomp.prim_data.
 :- import_module mdbcomp.program_representation.
 :- import_module parse_tree.prog_data.
@@ -87,6 +89,12 @@
     string_table::in, string_table::out) is det.
 
 %---------------------------------------------------------------------------%
+
+:- pred compute_var_number_map(list(prog_var)::in, prog_varset::in,
+    assoc_list(int, internal_layout_info)::in, hlds_goal::in,
+    var_num_map::out) is det.
+
+%---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -96,7 +104,6 @@
 :- import_module check_hlds.type_util.
 :- import_module hlds.code_model.
 :- import_module hlds.goal_util.
-:- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module hlds.hlds_rtti.
 :- import_module hlds.instmap.
@@ -107,7 +114,6 @@
 :- import_module ll_backend.layout.
 :- import_module ll_backend.layout_out.
 :- import_module ll_backend.ll_pseudo_type_info.
-:- import_module ll_backend.prog_rep.
 :- import_module ll_backend.trace_gen.
 :- import_module parse_tree.prog_event.
 
@@ -622,18 +628,9 @@ construct_proc_layout(Params, PLI, ProcL
                 DeepOriginalBody = DeepProfInfo ^ pdpi_orig_body,
                 DeepOriginalBody = deep_original_body(BytecodeBody,
                     BytecodeHeadVars, BytecodeInstMap, BytecodeVarTypes,
-                    BytecodeDetism),
-                some [!VarNumMap, !Counter] (
-                    !:VarNumMap = map.init,
-                    !:Counter = counter.init(1),
-                    goal_util.goal_vars(BytecodeBody, BodyVarSet),
-                    set.to_sorted_list(BodyVarSet, BodyVars),
-                    list.foldl2(add_var_to_var_number_map(VarSet),
-                        BodyVars, !VarNumMap, !Counter),
-                    list.foldl2(add_var_to_var_number_map(VarSet),
-                        BytecodeHeadVars, !VarNumMap, !.Counter, _),
-                    BytecodeVarNumMap = !.VarNumMap
-                )
+                    BytecodeDetism, BytecodeVarSet),
+                compute_var_number_map(BytecodeHeadVars, BytecodeVarSet, [],
+                    BytecodeBody, BytecodeVarNumMap)
             ;
                 MaybeDeepProfInfo = no,
                 MaybeProcStaticSlotName = no,
@@ -1205,10 +1202,6 @@ construct_var_name_rvals([Var - Name | V
 
 %---------------------------------------------------------------------------%
 
-:- pred compute_var_number_map(list(prog_var)::in, prog_varset::in,
-    assoc_list(int, internal_layout_info)::in, hlds_goal::in,
-    var_num_map::out) is det.
-
 compute_var_number_map(HeadVars, VarSet, Internals, Goal, VarNumMap) :-
     some [!VarNumMap, !Counter] (
         !:VarNumMap = map.init,
Index: compiler/type_constraints.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/type_constraints.m,v
retrieving revision 1.8
diff -u -p -b -r1.8 type_constraints.m
--- compiler/type_constraints.m	3 Feb 2010 23:23:37 -0000	1.8
+++ compiler/type_constraints.m	1 Jul 2010 05:17:24 -0000
@@ -411,15 +411,15 @@ apply_pred_data_to_goal((GoalPath0 - Pre
     program_representation.goal_path_consable(GoalPath0, GoalPath),
     (
         goal_util.maybe_transform_goal_at_goal_path(set_goal_pred_id(PredId),
-            GoalPath, !.Goal, yes(GoalPrime))
+            GoalPath, !.Goal, ok(GoalPrime))
     ->
         !:Goal = GoalPrime
     ;
         true
     ).
 
-:- pred set_goal_pred_id(pred_id::in, hlds_goal::in, maybe(hlds_goal)::out)
-    is det.
+:- pred set_goal_pred_id(pred_id::in, hlds_goal::in, 
+    maybe_error(hlds_goal)::out) is det.
 
 set_goal_pred_id(PredId, hlds_goal(Expression0, Info), MaybeGoal) :-
     ( Expression0 = plain_call(_, _, _, _, _, _) ->
@@ -433,9 +433,9 @@ set_goal_pred_id(PredId, hlds_goal(Expre
                 int_to_string(pred_id_to_int(PredId)) ++ "\n", !IO)
         ),
         NewCall = Expression0 ^ call_pred_id := PredId,
-        MaybeGoal = yes(hlds_goal(NewCall, Info))
+        MaybeGoal = ok(hlds_goal(NewCall, Info))
     ;
-        MaybeGoal = no
+        MaybeGoal = error("Goal was not a plain call") 
     ).
 
     % The following predicates extract the disjuncts from type constraints.
Index: deep_profiler/display_report.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/display_report.m,v
retrieving revision 1.23
diff -u -p -b -r1.23 display_report.m
--- deep_profiler/display_report.m	2 Oct 2009 04:37:57 -0000	1.23
+++ deep_profiler/display_report.m	30 Jun 2010 12:41:15 -0000
@@ -1668,20 +1668,21 @@ display_report_procrep_coverage_info(Pre
 coverage_to_cord_string(Coverage, cord.singleton(String)) :-
     (
         Coverage = coverage_unknown,
-        String = " _ - _"
+        String0 = "_ - _"
     ;
         Coverage = coverage_known(Before, After),
-        String = string.format(" %d - %d", [i(Before), i(After)])
+        String0 = string.format("%d - %d", [i(Before), i(After)])
     ;
         Coverage = coverage_known_same(Count),
-        String = string.format(" %d - %d", [i(Count), i(Count)])
+        String0 = string.format("%d - %d", [i(Count), i(Count)])
     ;
         Coverage = coverage_known_before(Before),
-        String = string.format(" %d - _", [i(Before)])
+        String0 = string.format("%d - _", [i(Before)])
     ;
         Coverage = coverage_known_after(After),
-        String = string.format(" _ - %d", [i(After)])
-    ).
+        String0 = string.format("_ - %d", [i(After)])
+    ),
+    String = "Coverage: " ++ String0.
 
 %-----------------------------------------------------------------------------%
 %
Index: deep_profiler/mdprof_fb.automatic_parallelism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/mdprof_fb.automatic_parallelism.m,v
retrieving revision 1.8
diff -u -p -b -r1.8 mdprof_fb.automatic_parallelism.m
--- deep_profiler/mdprof_fb.automatic_parallelism.m	8 Jun 2010 13:00:51 -0000	1.8
+++ deep_profiler/mdprof_fb.automatic_parallelism.m	30 Jun 2010 12:41:15 -0000
@@ -74,8 +74,8 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred create_candidate_parallel_conj_report(
-    pair(string_proc_label, candidate_par_conjunction(pard_goal))::in, 
+:- pred create_candidate_parallel_conj_proc_report(
+    pair(string_proc_label, candidate_par_conjunctions_proc)::in, 
     cord(string)::out) is det.
 
 %-----------------------------------------------------------------------------%
@@ -138,11 +138,10 @@ candidate_parallel_conjunctions(Opts, De
     RootCliqueCost = build_cs_cost_csq(1, float(TotalCallseqs) + 1.0),
     RootParallelism = no_parallelism,
     candidate_parallel_conjunctions_clique(Opts, Deep, RootCliqueCost,
-        RootParallelism, RootCliquePtr, ConjunctionsMultiMap, Messages),
+        RootParallelism, RootCliquePtr, ConjunctionsMap, Messages),
 
-    multi_map.to_flat_assoc_list(ConjunctionsMultiMap,
-        ConjunctionsAssocList0),
-    map_values_only(convert_candidate_par_conjunction(
+    map.to_assoc_list(ConjunctionsMap, ConjunctionsAssocList0),
+    map_values_only(convert_candidate_par_conjunctions_proc(
             pard_goal_detail_to_pard_goal),
         ConjunctionsAssocList0, ConjunctionsAssocList),
     CandidateParallelConjunctions =
@@ -153,20 +152,24 @@ candidate_parallel_conjunctions(Opts, De
 :- pred pard_goal_detail_to_pard_goal(pard_goal_detail::in, pard_goal::out) 
     is det.
 
-pard_goal_detail_to_pard_goal(pard_goal_detail(PGT, _, _, _), PG) :-
+pard_goal_detail_to_pard_goal(!Goal) :-
+    transform_goal_rep(pard_goal_detail_annon_to_pard_goal_annon, !Goal).
+
+:- pred pard_goal_detail_annon_to_pard_goal_annon(
+    pard_goal_detail_annotation::in, pard_goal_annotation::out) is det.
+
+pard_goal_detail_annon_to_pard_goal_annon(PGD, PG) :-
+    PGT = PGD ^ pgd_pg_type,
     (
-        PGT = pgt_call(Callee, VarNames, _Vars, CostPercall, _, _),
-        PG = pg_call(Callee, VarNames, CostPercall)
-    ;
-        PGT = pgt_cheap_call(Callee, VarNames, _, _, _),
-        PG = pg_cheap_call(Callee, VarNames)
+        PGT = pgt_call(CostCSQ, CostAboveThreshold, _, _),
+        CostPercall = cs_cost_get_percall(CostCSQ),
+        PG = pard_goal_call(CostPercall, CostAboveThreshold)
     ;
         PGT = pgt_other_atomic_goal,
-        PG = pg_other_atomic_goal
+        PG = pard_goal_other_atomic
     ;
         PGT = pgt_non_atomic_goal,
-        error(this_file ++ 
-            "Unexpected: non atomic goal in pard_goal_detail_to_pard_goal")
+        PG = pard_goal_non_atomic
     ).
 
 %----------------------------------------------------------------------------%
@@ -178,7 +181,8 @@ pard_goal_detail_to_pard_goal(pard_goal_
                 ipi_opts            :: candidate_parallel_conjunctions_opts,
                 ipi_call_sites      :: map(goal_path, clique_call_site_report),
                 ipi_rec_call_sites  :: map(goal_path, cs_cost_csq),
-                ipi_var_table       :: var_table
+                ipi_var_table       :: var_table,
+                ipi_proc_label      :: string_proc_label
             ).
 
     % A representation of a goal within a parallel conjunction.  We don't have
@@ -187,65 +191,49 @@ pard_goal_detail_to_pard_goal(pard_goal_
     % required by the compiler and therefore not part of the feedback file
     % format.
     %
-:- type pard_goal_detail
+:- type pard_goal_detail == goal_rep(pard_goal_detail_annotation).
+
+:- type pard_goal_detail_annotation
     --->    pard_goal_detail(
                 pgd_pg_type             :: pard_goal_type,
                     % The type and type-specific values of the pard goal.
 
-                pgd_detism              :: detism_rep,
-                    % The determinism of the call.
-
-                pgd_conj_num            :: int,
-                    % The place within the conjunction that this conjunct
-                    % lies.
-
-                pgd_inst_map_info       :: inst_map_info
+                pgd_inst_map_info       :: inst_map_info,
                     % The inst map info attached to the original goal.
+
+                pgd_original_path       :: goal_path
+                    % The original goal path of this goal.
             ).
 
 :- inst pard_goal_detail(T)
-    ---> pard_goal_detail(T, ground, ground, ground).
+    ---> pard_goal_detail(T, ground, ground).
 
 :- type pard_goal_type 
     --->    pgt_call(
-                pgtc_callee             :: callee_rep,
-                    
-                pgtc_var_names          :: list(maybe(string)),
-                    % The names of variables (if user defined) given as
-                    % arguments to this call.
-
-                pgtc_vars               :: list(var_rep),
-                    % The actual variables given as arguments to this call.
-
-                pgtc_cost_percall       :: float,
+                pgtc_cost                   :: cs_cost_csq,
                     % The per-call cost of this call in call sequence counts.
              
+                pgtc_coat_above_threshold   :: cost_above_par_threshold,
+             
                 pgtc_args               :: list(var_mode_and_use),
                     % The argument modes and use information.
 
                 pgtc_call_site          :: clique_call_site_report
                     % The call site report from the deep profiler.
             )
-    ;       pgt_cheap_call(
-                pgtcc_callee            :: callee_rep,
-                pgtcc_var_names         :: list(maybe(string)),
-                pgtcc_vars              :: list(var_rep),
-                pgtcc_args              :: list(var_mode_and_use),
-                pgtcc_cost              :: cs_cost_csq 
-            )
     ;       pgt_other_atomic_goal
     ;       pgt_non_atomic_goal.
 
 :- inst pgt_call 
-    --->    pgt_call(ground, ground, ground, ground, ground, ground).
+    --->    pgt_call(ground, bound(cost_above_par_threshold), ground, 
+                ground).
 
 :- inst pgt_atomic_goal
-    --->    pgt_call(ground, ground, ground, ground, ground, ground)
-    ;       pgt_cheap_call(ground, ground, ground, ground, ground)
+    --->    pgt_call(ground, ground, ground, ground)
     ;       pgt_other_atomic_goal.
     
-    % A variable, it's mode and it's usage in the callee.  The mode information
-    % is also summarised within the variable use information.
+    % A variable, it's mode and it's usage in the callee.  The mode
+    % information is also summarised within the variable use information.
     %
 :- type var_mode_and_use
     --->    var_mode_and_use(
@@ -255,7 +243,7 @@ pard_goal_detail_to_pard_goal(pard_goal_
             ).
 
 :- type candidate_par_conjunctions ==
-    multi_map(string_proc_label, candidate_par_conjunction(pard_goal_detail)).
+    map(string_proc_label, candidate_par_conjunctions_proc(pard_goal_detail)).
 
 :- type pard_goals_partition
     --->    pard_goals_partition(
@@ -439,13 +427,31 @@ candidate_parallel_conjunctions_clique_p
                 ProcCandidatesByGoalPath),
             CallSiteReports, CSCandidatesList, CSMessagesList),
       
-        list.foldl(multi_map.merge, CSCandidatesList, multi_map.init,
-            CSCandidates),
-        Candidates = multi_map.merge(ProcCandidates, CSCandidates),
+        list.foldl(map.union(merge_candidate_par_conjs_proc),
+            CSCandidatesList, map.init, CSCandidates),
+        map.union(merge_candidate_par_conjs_proc, ProcCandidates,
+            CSCandidates, Candidates),
         !:Messages = !.Messages ++ cord_list_to_cord(CSMessagesList),
         Messages = !.Messages
     ).
 
+:- pred merge_candidate_par_conjs_proc(
+    candidate_par_conjunctions_proc(T)::in,
+    candidate_par_conjunctions_proc(T)::in, 
+    candidate_par_conjunctions_proc(T)::out) is det.
+
+merge_candidate_par_conjs_proc(A, B, Result) :-
+    A = candidate_par_conjunctions_proc(VarTableA, CPCsA),
+    B = candidate_par_conjunctions_proc(VarTableB, CPCsB),
+    Result = candidate_par_conjunctions_proc(VarTableA, CPCs),
+    CPCs = CPCsA ++ CPCsB,
+    ( VarTableA = VarTableB ->
+        true
+    ;
+        error(this_file ++ 
+            "merge_candidate_par_conjs_proc: var tables do not match")
+    ).
+
 :- pred candidate_parallel_conjunctions_call_site(
     candidate_parallel_conjunctions_opts::in, deep::in, set(proc_desc)::in,
     clique_is_recursive::in, map(goal_path, cs_cost_csq)::in,
@@ -473,7 +479,8 @@ candidate_parallel_conjunctions_call_sit
             CliqueIsRecursive, RecursiveCallSiteCostMap, CliqueProcMap,
             CliquePtr, CallSiteDesc, Parallelism),
         CalleePerfs, CandidatesList, MessagesList),
-    list.foldl(multi_map.merge, CandidatesList, multi_map.init, Candidates),
+    list.foldl(map.union(merge_candidate_par_conjs_proc), CandidatesList, 
+        map.init, Candidates),
     Messages = cord_list_to_cord(MessagesList).
 
 :- pred parallelism_probability(
@@ -483,7 +490,10 @@ candidate_parallel_conjunctions_call_sit
 
 parallelism_probability(Candidates, ConjGoalPath, ParallelismProbability,
         ParallelismAmount) :-
-    ( goal_path_remove_last(ConjGoalPath, GoalPath, step_conj(ConjNum)) ->
+    (
+        % Is the goal named by ConjGoalPath immediatly within a conjunction?
+        goal_path_remove_last(ConjGoalPath, GoalPath, step_conj(_)) 
+    ->
         StringGoalPath = goal_path_to_string(GoalPath),
         ( multi_map.search(Candidates, StringGoalPath, CandidateList) ->
             (
@@ -493,7 +503,7 @@ parallelism_probability(Candidates, Conj
                 promise_equivalent_solutions [Amount] some [Candidate, Conj] (
                     member(Candidate, CandidateList),
                     parallel_amount(Candidate ^ cpc_conjs, Conj, Amount),
-                    ConjNum = Conj ^ pgd_conj_num
+                    GoalPath = Conj ^ goal_annotation ^ pgd_original_path
                 )
             ->
                 % XXX: Wait until we have the new calculations for how
@@ -512,10 +522,11 @@ parallelism_probability(Candidates, Conj
             ParallelismAmount = no_parallelism
         )
     ;
-        % We may not be able to remove this goal if it is not directly in a
-        % conjunction.  Perhaps it's directly within some branch goal or at the
-        % root of a goal path.  In these cases it is not in a parallel
-        % conjunction so the parallelism probability is 0.0. 
+        % This goal is not directly in a conjunction.  Perhaps it's directly
+        % within some branch goal or at the root of a goal path.  In these
+        % cases it is not in a parallel conjunction so the parallelism
+        % probability is 0.0.
+        % XXX: This assumption is true now but may change in the future.
         ParallelismProbability = impossible,
         ParallelismAmount = no_parallelism 
     ).
@@ -549,7 +560,7 @@ candidate_parallel_conjunctions_callee(O
         ( member(CliqueEntryProc, ProcsAnalysed0) ->
             % If we've analysed this clique in this proc already then don't do
             % it again.
-            Candidates = multi_map.init,
+            Candidates = map.init,
             Messages = cord.empty
         ;
             map.lookup(CliqueProcReportMap, CliqueEntryProc, CliqueProcReport),
@@ -576,7 +587,7 @@ candidate_parallel_conjunctions_callee(O
             % duplication of code.
             not cs_cost_get_total(CSCost) > float(Opts ^ cpc_clique_threshold)
         ->
-            Candidates = multi_map.init, 
+            Candidates = map.init, 
             Messages = cord.empty,
             trace [compile_time(flag("debug_cpc_search")), io(!IO)] (
                 CSPercallCost = cs_cost_get_percall(CSCost),
@@ -593,7 +604,7 @@ candidate_parallel_conjunctions_callee(O
             exceeded_desired_parallelism(Opts ^ cpc_desired_parallelism,
                 Parallelism)
         ->
-            Candidates = multi_map.init, 
+            Candidates = map.init, 
             Messages = cord.empty,
             trace [compile_time(flag("debug_cpc_search")), io(!IO)] (
                 io.format("D: Not entering clique: %d, " ++
@@ -1120,7 +1131,7 @@ candidate_parallel_conjunctions_proc(Opt
         ->
             % Silently skip over any code from the runtime, we can't expect to
             % find it's procedure representation.
-            Candidates = multi_map.init,
+            Candidates = map.init,
             CandidatesByGoalPath = map.init
         ;
             progrep_search_proc(ProgRep, ProcLabel, ProcRep) 
@@ -1129,22 +1140,23 @@ candidate_parallel_conjunctions_proc(Opt
             ProcDefnRep ^ pdr_goal = Goal0,
             ProcDefnRep ^ pdr_var_table = VarTable,
             Info = implicit_parallelism_info(Deep, ProgRep, Opts,
-                CallSitesMap, RecursiveCallSiteCostMap, VarTable),
+                CallSitesMap, RecursiveCallSiteCostMap, VarTable, ProcLabel),
             goal_annotate_with_instmap(Goal0, Goal,
                 initial_inst_map(ProcDefnRep), _FinalInstMap,
                 SeenDuplicateInstantiation, _ConsumedVars, _BoundVars),
-            goal_get_conjunctions_worth_parallelising(Goal, empty_goal_path,
-                Info, ProcLabel, Candidates0, MessagesA),
+            goal_get_conjunctions_worth_parallelising(Info, Goal,
+                empty_goal_path, Candidates0, MessagesA),
             !:Messages = !.Messages ++ MessagesA,
             (
                 SeenDuplicateInstantiation =
                     have_not_seen_duplicate_instantiation,
-                list.foldl2(build_candidate_par_conjunction_maps(ProcLabel),
-                    Candidates0, multi_map.init, Candidates, 
-                    map.init, CandidatesByGoalPath)
+                list.foldl2(
+                    build_candidate_par_conjunction_maps(ProcLabel, VarTable),
+                    Candidates0, map.init, Candidates, 
+                    multi_map.init, CandidatesByGoalPath)
             ;
                 SeenDuplicateInstantiation = seen_duplicate_instantiation,
-                Candidates = multi_map.init,
+                Candidates = map.init,
                 CandidatesByGoalPath = map.init,
                 append_message(proc(ProcLabel), 
                     notice_duplicate_instantiation(length(Candidates0)),
@@ -1153,7 +1165,7 @@ candidate_parallel_conjunctions_proc(Opt
         ;
             % Builtin procedures cannot be found in the program representation,
             % and cannot be parallelised either.
-            Candidates = multi_map.init,
+            Candidates = map.init,
             CandidatesByGoalPath = map.init,
             append_message(proc(ProcLabel), warning_cannot_lookup_proc_defn,
                 !Messages)
@@ -1162,7 +1174,7 @@ candidate_parallel_conjunctions_proc(Opt
     ).
 
 :- pred build_candidate_par_conjunction_maps(string_proc_label::in,
-    candidate_par_conjunction(pard_goal_detail)::in, 
+    var_table::in, candidate_par_conjunction(pard_goal_detail)::in, 
     candidate_par_conjunctions::in, candidate_par_conjunctions::out,
     multi_map(goal_path_string, 
         candidate_par_conjunction(pard_goal_detail))::in,
@@ -1170,51 +1182,65 @@ candidate_parallel_conjunctions_proc(Opt
         candidate_par_conjunction(pard_goal_detail))::out)
     is det.
 
-build_candidate_par_conjunction_maps(ProcLabel, Candidate, !Map, !GPMap) :- 
-    multi_map.set(!.Map, ProcLabel, Candidate, !:Map),
+build_candidate_par_conjunction_maps(ProcLabel, VarTable, Candidate, !Map, !GPMap) :-
+    ( map.search(!.Map, ProcLabel, CandidateProc0) ->
+        CandidateProc0 = candidate_par_conjunctions_proc(VarTablePrime, CPCs0),
+        CPCs = [ Candidate | CPCs0 ],
+        ( VarTable = VarTablePrime ->
+            true
+        ;
+            error(this_file ++ 
+                "build_candidate_par_conjunction_maps: Var tables do not match")
+        )
+    ;
+        CPCs = [ Candidate ]
+    ),
+    CandidateProc = candidate_par_conjunctions_proc(VarTable, CPCs),
+    svmap.set(ProcLabel, CandidateProc, !Map),
     GoalPath = Candidate ^ cpc_goal_path,
     multi_map.set(!.GPMap, GoalPath, Candidate, !:GPMap).
     
-:- pred goal_get_conjunctions_worth_parallelising(goal_rep(inst_map_info)::in, 
-    goal_path::in, implicit_parallelism_info::in, string_proc_label::in,
+:- pred goal_get_conjunctions_worth_parallelising(
+    implicit_parallelism_info::in,
+    goal_rep(inst_map_info)::in, goal_path::in, 
     list(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::out) is det.
 
-goal_get_conjunctions_worth_parallelising(Goal, GoalPath, Info, ProcLabel, 
-        Candidates, Messages) :-
+goal_get_conjunctions_worth_parallelising(Info, Goal, GoalPath, Candidates,
+        Messages) :-
     Goal = goal_rep(GoalExpr, _, _),
     (
         (
             GoalExpr = conj_rep(Conjuncts),
-            conj_get_conjunctions_worth_parallelising(Conjuncts, GoalPath, 1,
-                Info, ProcLabel, CandidatesA, MessagesA),
-            conj_build_candidate_conjunctions(Conjuncts, GoalPath, 
-                Info, ProcLabel, MessagesB, CandidatesB),
+            conj_get_conjunctions_worth_parallelising(Info, 
+                Conjuncts, GoalPath, 1, CandidatesA, MessagesA),
+            conj_build_candidate_conjunctions(Info, Conjuncts,
+                GoalPath, MessagesB, CandidatesB),
             Messages = MessagesA ++ MessagesB,
             Candidates = CandidatesA ++ CandidatesB
         ;
             GoalExpr = disj_rep(Disjuncts),
-            disj_get_conjunctions_worth_parallelising(Disjuncts, GoalPath, 1,
-                Info, ProcLabel, Candidates, Messages)
+            disj_get_conjunctions_worth_parallelising(Info,
+                Disjuncts, GoalPath, 1, Candidates, Messages)
         ;
             GoalExpr = switch_rep(_, _, Cases),
-            switch_case_get_conjunctions_worth_parallelising(Cases, GoalPath, 1,
-                Info, ProcLabel, Candidates, Messages)
+            switch_case_get_conjunctions_worth_parallelising(Info, Cases,
+                GoalPath, 1, Candidates, Messages)
         ;
             GoalExpr = ite_rep(Cond, Then, Else),
-            ite_get_conjunctions_worth_parallelising(Cond, Then, Else,
-                GoalPath, Info, ProcLabel, Candidates, Messages)
+            ite_get_conjunctions_worth_parallelising(Info, Cond, Then, Else,
+                GoalPath, Candidates, Messages)
         ;
             GoalExpr = scope_rep(SubGoal, MaybeCut),
             ScopeGoalPath = 
                 goal_path_add_at_end(GoalPath, step_scope(MaybeCut)),
-            goal_get_conjunctions_worth_parallelising(SubGoal, ScopeGoalPath,
-                Info, ProcLabel, Candidates, Messages) 
+            goal_get_conjunctions_worth_parallelising(Info, SubGoal,
+                ScopeGoalPath, Candidates, Messages) 
         ;
             GoalExpr = negation_rep(SubGoal),
             NegGoalPath = goal_path_add_at_end(GoalPath, step_neg),
-            goal_get_conjunctions_worth_parallelising(SubGoal, NegGoalPath,
-                Info, ProcLabel, Candidates, Messages) 
+            goal_get_conjunctions_worth_parallelising(Info, SubGoal, 
+                NegGoalPath, Candidates, Messages) 
         )
     ;
         GoalExpr = atomic_goal_rep(_, _, _, _),
@@ -1223,96 +1249,99 @@ goal_get_conjunctions_worth_parallelisin
     ).
 
 :- pred conj_get_conjunctions_worth_parallelising(
-    list(goal_rep(inst_map_info))::in, goal_path::in, int::in,
-    implicit_parallelism_info::in, string_proc_label::in,
+    implicit_parallelism_info::in, list(goal_rep(inst_map_info))::in,
+    goal_path::in, int::in,
     list(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::out) is det.
 
-conj_get_conjunctions_worth_parallelising([], _, _, _, _, [], cord.empty).
-conj_get_conjunctions_worth_parallelising([Conj | Conjs], GoalPath,
-        ConjunctNum, Info, ProcLabel, Candidates, Messages) :-
+conj_get_conjunctions_worth_parallelising(_, [], _, _, [], cord.empty).
+conj_get_conjunctions_worth_parallelising(Info, [Conj | Conjs], GoalPath,
+        ConjunctNum, Candidates, Messages) :-
     ConjGoalPath = goal_path_add_at_end(GoalPath, step_conj(ConjunctNum)),
-    goal_get_conjunctions_worth_parallelising(Conj, ConjGoalPath, Info,
-        ProcLabel, CandidatesHead, MessagesHead), 
+    goal_get_conjunctions_worth_parallelising(Info, Conj, ConjGoalPath,
+        CandidatesHead, MessagesHead), 
     
-    conj_get_conjunctions_worth_parallelising(Conjs, GoalPath, ConjunctNum+1,
-        Info, ProcLabel, CandidatesTail, MessagesTail),
+    conj_get_conjunctions_worth_parallelising(Info, Conjs, GoalPath,
+        ConjunctNum+1, CandidatesTail, MessagesTail),
 
     Candidates = CandidatesHead ++ CandidatesTail,
     Messages = MessagesHead ++ MessagesTail.
 
 :- pred disj_get_conjunctions_worth_parallelising(
-    list(goal_rep(inst_map_info))::in, goal_path::in, int::in,
-    implicit_parallelism_info::in, string_proc_label::in,
+    implicit_parallelism_info::in, list(goal_rep(inst_map_info))::in,
+    goal_path::in, int::in,
     list(candidate_par_conjunction(pard_goal_detail))::out, cord(message)::out) 
     is det.
 
-disj_get_conjunctions_worth_parallelising([], _, _, _, _, [], cord.empty).
-disj_get_conjunctions_worth_parallelising([Disj | Disjs], GoalPath, DisjNum,
-        Info, ProcLabel, Candidates, Messages) :-
+disj_get_conjunctions_worth_parallelising(_, [], _, _, [], cord.empty).
+disj_get_conjunctions_worth_parallelising(Info, [Disj | Disjs], GoalPath, DisjNum,
+        Candidates, Messages) :-
     DisjGoalPath = goal_path_add_at_end(GoalPath, step_disj(DisjNum)),
-    goal_get_conjunctions_worth_parallelising(Disj, DisjGoalPath, Info,
-        ProcLabel, HeadCandidates, HeadMessages),
-    disj_get_conjunctions_worth_parallelising(Disjs, GoalPath, DisjNum + 1,
-        Info, ProcLabel, TailCandidates, TailMessages),
+    goal_get_conjunctions_worth_parallelising(Info, Disj, DisjGoalPath,
+        HeadCandidates, HeadMessages),
+    disj_get_conjunctions_worth_parallelising(Info, Disjs, GoalPath, 
+        DisjNum + 1, TailCandidates, TailMessages),
     Candidates = HeadCandidates ++ TailCandidates,
     Messages = HeadMessages ++ TailMessages.
 
 :- pred switch_case_get_conjunctions_worth_parallelising(
-    list(case_rep(inst_map_info))::in, goal_path::in, int::in,
-    implicit_parallelism_info::in, string_proc_label::in,
-    list(candidate_par_conjunction(pard_goal_detail))::out, cord(message)::out) is det.
+    implicit_parallelism_info::in, list(case_rep(inst_map_info))::in,
+    goal_path::in, int::in,
+    list(candidate_par_conjunction(pard_goal_detail))::out, 
+    cord(message)::out) is det.
 
-switch_case_get_conjunctions_worth_parallelising([], _, _, _, _, [],
+switch_case_get_conjunctions_worth_parallelising(_, [], _, _, [],
         cord.empty).
-switch_case_get_conjunctions_worth_parallelising([Case | Cases], GoalPath,
-        CaseNum, Info, ProcLabel, Candidates, Messages) :-
+switch_case_get_conjunctions_worth_parallelising(Info, [Case | Cases], GoalPath,
+        CaseNum, Candidates, Messages) :-
     Case = case_rep(_, _, Goal),
     CaseGoalPath = goal_path_add_at_end(GoalPath, step_switch(CaseNum, no)),
-    goal_get_conjunctions_worth_parallelising(Goal, CaseGoalPath, Info,
-        ProcLabel, HeadCandidates, HeadMessages),
-    switch_case_get_conjunctions_worth_parallelising(Cases, GoalPath, 
-        CaseNum + 1, Info, ProcLabel, TailCandidates,
-        TailMessages),
+    goal_get_conjunctions_worth_parallelising(Info, Goal, CaseGoalPath,
+        HeadCandidates, HeadMessages),
+    switch_case_get_conjunctions_worth_parallelising(Info, Cases, GoalPath, 
+        CaseNum + 1, TailCandidates, TailMessages),
     Candidates = HeadCandidates ++ TailCandidates,
     Messages = HeadMessages ++ TailMessages.
 
-:- pred ite_get_conjunctions_worth_parallelising(goal_rep(inst_map_info)::in,
+:- pred ite_get_conjunctions_worth_parallelising(
+    implicit_parallelism_info::in, goal_rep(inst_map_info)::in,
     goal_rep(inst_map_info)::in, goal_rep(inst_map_info)::in, goal_path::in,
-    implicit_parallelism_info::in, string_proc_label::in,
-    list(candidate_par_conjunction(pard_goal_detail))::out, cord(message)::out) is det.
+    list(candidate_par_conjunction(pard_goal_detail))::out, cord(message)::out)
+    is det.
 
-ite_get_conjunctions_worth_parallelising(Cond, Then, Else, GoalPath, Info,
-        ProcLabel, Candidates, Messages) :-
+ite_get_conjunctions_worth_parallelising(Info, Cond, Then, Else, GoalPath,
+        Candidates, Messages) :-
     CondGoalPath = goal_path_add_at_end(GoalPath, step_ite_cond),
     ThenGoalPath = goal_path_add_at_end(GoalPath, step_ite_then),
     ElseGoalPath = goal_path_add_at_end(GoalPath, step_ite_else),
-    goal_get_conjunctions_worth_parallelising(Cond, CondGoalPath, Info,
-        ProcLabel, CondCandidates, CondMessages),
-    goal_get_conjunctions_worth_parallelising(Then, ThenGoalPath, Info, 
-        ProcLabel, ThenCandidates, ThenMessages),
-    goal_get_conjunctions_worth_parallelising(Else, ElseGoalPath, Info, 
-        ProcLabel, ElseCandidates, ElseMessages),
+    goal_get_conjunctions_worth_parallelising(Info, Cond, CondGoalPath, 
+        CondCandidates, CondMessages),
+    goal_get_conjunctions_worth_parallelising(Info, Then, ThenGoalPath,
+        ThenCandidates, ThenMessages),
+    goal_get_conjunctions_worth_parallelising(Info, Else, ElseGoalPath,
+        ElseCandidates, ElseMessages),
     Candidates = CondCandidates ++ ThenCandidates ++ ElseCandidates,
     Messages = CondMessages ++ ThenMessages ++ ElseMessages.
 
     % At the end of every conjunction we call this predicate to check the list
     % of calls we've found and make any parallelisation decisions.
     %
-:- pred conj_build_candidate_conjunctions(list(goal_rep(inst_map_info))::in, 
-    goal_path::in, implicit_parallelism_info::in, string_proc_label::in,
-    cord(message)::out, list(candidate_par_conjunction(pard_goal_detail))::out)
-    is det.
+:- pred conj_build_candidate_conjunctions( implicit_parallelism_info::in,
+    list(goal_rep(inst_map_info))::in, goal_path::in,
+    cord(message)::out, 
+    list(candidate_par_conjunction(pard_goal_detail))::out) is det.
 
-conj_build_candidate_conjunctions(Conjs, GoalPath, Info, ProcLabel, Messages,
+conj_build_candidate_conjunctions(Info, Conjs, GoalPath, Messages, 
         Candidates) :-
     some [!Messages] 
     (
         !:Messages = cord.empty,
+        ProcLabel = Info ^ ipi_proc_label,
         Location = goal(ProcLabel, GoalPath),
 
-        conj_to_pard_goal_list(Conjs, GoalPath, 1, Info, [], PardGoals, 0,
-            NumCostlyCalls),
+        map_foldl(goal_to_pard_goal(Info, GoalPath, 
+            ( func(Num) = step_conj(Num) ) ), Conjs, PardGoals, 1, _),
+        foldl(count_costly_calls, PardGoals, 0, NumCostlyCalls),
         ( NumCostlyCalls > 1 -> 
             append_message(Location,
                 info_found_conjs_above_callsite_threshold(NumCostlyCalls),
@@ -1336,6 +1365,24 @@ conj_build_candidate_conjunctions(Conjs,
         Messages = !.Messages
     ).
 
+:- pred count_costly_calls(pard_goal_detail::in, int::in, int::out) is det.
+
+count_costly_calls(Goal, !NumCostlyCalls) :-
+    GoalType = Goal ^ goal_annotation ^ pgd_pg_type,
+    (
+        GoalType = pgt_call(_, CostAboveThreshold, _, _),
+        (
+            CostAboveThreshold = cost_above_par_threshold,
+            !:NumCostlyCalls = !.NumCostlyCalls + 1
+        ;
+            CostAboveThreshold = cost_not_above_par_threshold
+        )
+    ;
+        GoalType = pgt_other_atomic_goal
+    ;
+        GoalType = pgt_non_atomic_goal
+    ).
+
 :- pred partition_pard_goals(program_location::in, 
     list(pard_goal_detail)::in,
     list(pard_goal_detail)::in, list(pard_goal_detail)::out,
@@ -1361,13 +1408,16 @@ partition_pard_goals(Location, [], !Part
     reverse(!Partitions).
 partition_pard_goals(Location, [ PG | PGs ], !Partition, !PartitionNum,
         !NumCostlyCalls, !Partitions, !Messages) :-
-    PGType = PG ^ pgd_pg_type,
+    PGType = PG ^ goal_annotation ^ pgd_pg_type,
     (
         (
-            PGType = pgt_call(_, _, _, _, _, _),
+            PGType = pgt_call(_, CostAboveThreshold, _, _),
+            (
+                CostAboveThreshold = cost_above_par_threshold,
             !:NumCostlyCalls = !.NumCostlyCalls + 1
         ;
-            PGType = pgt_cheap_call(_, _, _, _, _)
+                CostAboveThreshold = cost_not_above_par_threshold
+            )
         ;
             PGType = pgt_other_atomic_goal
         ),
@@ -1395,8 +1445,8 @@ partition_pard_goals(Location, [ PG | PG
     pard_goals_partition::in,
     maybe(candidate_par_conjunction(pard_goal_detail))::out) is det.
 
-pardgoals_build_candidate_conjunction(Info, DependencyMaps, Location, GoalPath,
-        GoalsPartition, MaybeCandidate) :-
+pardgoals_build_candidate_conjunction(Info, DependencyMaps, Location,
+        GoalPath, GoalsPartition, MaybeCandidate) :-
     % Setting up the first parallel conjunct is a different algorithm to the
     % latter ones, at this point we have the option of moving goals from before
     % the first costly call to either before or during the parallel
@@ -1440,8 +1490,9 @@ pardgoals_build_candidate_conjunction(In
 
                 convert_candidate_par_conjunction(pard_goal_detail_to_pard_goal,
                     Candidate, FBCandidate),
-                create_candidate_parallel_conj_report(ProcLabel - FBCandidate, 
-                    Report),
+                VarTable = Info ^ ipi_var_table,
+                create_candidate_parallel_conj_report(VarTable,
+                    ProcLabel, FBCandidate, Report),
                 io.write_string("Not parallelising conjunction, " ++ 
                     "insufficient speedup:\n", !IO),
                 io.write_string(append_list(cord.list(Report)), !IO)
@@ -1457,25 +1508,27 @@ pardgoals_build_candidate_conjunction(In
             )
     ;       costly_call_not_found.
 
-:- inst find_costly_call_result
-    --->    costly_call_found(ground, pard_goal_detail(pgt_call), ground)
-    ;       costly_call_not_found.
-
 :- pred find_costly_call(cord(pard_goal_detail)::in, cord(pard_goal_detail)::in,
-    find_costly_call_result::out(find_costly_call_result)) is det.
+    find_costly_call_result::out) is det.
 
 find_costly_call(Goals, GoalsBefore0, Result) :-
     ( head_tail(Goals, Goal, GoalsTail) ->
-        GoalType = Goal ^ pgd_pg_type,
+        GoalType = Goal ^ goal_annotation ^ pgd_pg_type,
         ( 
-            GoalType = pgt_call(_, _, _, _, _, _),
-            Result = costly_call_found(GoalsBefore0, Goal, GoalsTail)
+            (
+                GoalType = pgt_call(_, CostAboveThreshold, _, _)
         ;
-            ( GoalType = pgt_cheap_call(_, _, _, _, _)
-            ; GoalType = pgt_other_atomic_goal
+                GoalType = pgt_other_atomic_goal,
+                CostAboveThreshold = cost_not_above_par_threshold
             ),
+            (
+                CostAboveThreshold = cost_above_par_threshold,
+                Result = costly_call_found(GoalsBefore0, Goal, GoalsTail)
+            ;
+                CostAboveThreshold = cost_not_above_par_threshold,
             GoalsBefore = snoc(GoalsBefore0, Goal),
             find_costly_call(GoalsTail, GoalsBefore, Result)
+            )
         ;
             GoalType = pgt_non_atomic_goal,
             error(this_file ++ "Found non-atomic goal")
@@ -1577,7 +1630,8 @@ find_best_parallelisation_nondet(Info, L
             nl_indent(1) ++ singleton("Couldn't find first call\n"),
         error(append_list(cord.list(Error)))
     ),
-    FirstCallCallSite = FirstCall ^ pgd_pg_type ^ pgtc_call_site,
+    FirstCallCallSite = FirstCall ^ goal_annotation ^ pgd_pg_type 
+        ^ pgtc_call_site,
     NumCalls = FirstCallCallSite ^ ccsr_call_site_summary ^
         perf_row_calls,
    
@@ -1902,20 +1956,13 @@ par_conj_overlap_is_dependant(peo_conjun
         IsDependent = conjuncts_are_dependant
     ).
 
-:- pred pg_get_conj_num(pard_goal_detail::in, int::out) is det.
-
-pg_get_conj_num(PG, PG ^ pgd_conj_num).
-
 :- pred pardgoal_calc_cost(pard_goal_detail::in, float::in, float::out) 
     is det.
 
 pardgoal_calc_cost(Goal, !Cost) :-
-    GoalType = Goal ^ pgd_pg_type,
+    GoalType = Goal ^ goal_annotation ^ pgd_pg_type,
     (
-        GoalType = pgt_call(_, _, _, CostPercall, _, _),
-        !:Cost = !.Cost + CostPercall
-    ; 
-        GoalType = pgt_cheap_call(_, _, _, _, Cost),
+        GoalType = pgt_call(Cost, _, _, _),
         ( cs_cost_get_calls(Cost) > 0.0 ->
             !:Cost = !.Cost + cs_cost_get_percall(Cost)
         ;
@@ -1982,7 +2029,7 @@ insert_empty_set(K, !Map) :-
 
 build_dependency_map([], _ConjNum, !VarDepMap, !Map, !RevMap).
 build_dependency_map([PG | PGs], ConjNum, !VarDepMap, !Map, !RevMap) :-
-    InstMapInfo = PG ^ pgd_inst_map_info,
+    InstMapInfo = PG ^ goal_annotation ^ pgd_inst_map_info,
     
     % For each variable consumed by a goal we find out which goals instantiate
     % that variable and add them as it's dependencies along with their
@@ -2035,7 +2082,7 @@ add_var_to_var_dep_map(ConjNum, Var, !Va
     map(var_rep, float)::in, map(var_rep, float)::out) is det.
 
 get_productions_map(Goal, !Time, !Executions, !Map) :-
-    InstMapInfo = Goal ^ pgd_inst_map_info,
+    InstMapInfo = Goal ^ goal_annotation ^ pgd_inst_map_info,
     BoundVars = InstMapInfo ^ im_bound_vars,
     adjust_time_for_waits(!Time, !Executions),
     fold(var_production_time_to_map(!.Time, Goal), BoundVars, !Map),
@@ -2114,7 +2161,7 @@ var_production_time_to_map(TimeBefore, G
     assoc_list(var_rep, float)::in, assoc_list(var_rep, float)::out) is det.
 
 get_consumptions_list(Goal, !Vars, !Time, !List) :-
-    InstMapInfo = Goal ^ pgd_inst_map_info,
+    InstMapInfo = Goal ^ goal_annotation ^ pgd_inst_map_info,
     AllConsumptionVars = InstMapInfo ^ im_consumed_vars,
     ConsumptionVars = intersect(!.Vars, AllConsumptionVars),
     map(var_consumptions(!.Time, Goal),
@@ -2153,16 +2200,13 @@ var_consumptions(TimeBefore, Goal, Var, 
     float::in, pard_goal_detail::in, var_rep::in, float::out) is det.
 
 var_first_use_time(FindProdOrCons, TimeBefore, Goal, Var, Time) :-
-    GoalType = Goal ^ pgd_pg_type,
+    GoalType = Goal ^ goal_annotation ^ pgd_pg_type,
     (
+        GoalType = pgt_call(Cost, _, Args, _),
+        CostPercall = cs_cost_get_percall(Cost),
+        find_arg_by_var(Args, Var, MaybeArg),
         ( 
-            GoalType = pgt_call(_Callee, _, Vars, CostPercall, Args, _CallSite)
-        ; 
-            GoalType = pgt_cheap_call(_Callee, _, Vars, Args, Cost),
-            CostPercall = cs_cost_get_percall(Cost)
-        ),
-        ( nth_member_search(Vars, Var, NthArg) ->
-            index1_det(Args, NthArg, Arg),
+            MaybeArg = yes(Arg),
             Use = Arg ^ vmu_use,
             UseType = Use ^ vui_use_type,
             (
@@ -2212,6 +2256,7 @@ var_first_use_time(FindProdOrCons, TimeB
                 )
             )
         ;
+            MaybeArg = no,
             (
                 FindProdOrCons = find_production,
                 error("var_first_use_time: "
@@ -2238,13 +2283,24 @@ var_first_use_time(FindProdOrCons, TimeB
     ),
     Time = TimeBefore + UseTime.
 
+:- pred find_arg_by_var(list(var_mode_and_use)::in, var_rep::in,
+    maybe(var_mode_and_use)::out) is det. 
+
+find_arg_by_var([], _, no).
+find_arg_by_var([Arg | Args], Var, MaybeArg) :-
+    ( Arg = var_mode_and_use(Var, _, _) ->
+        MaybeArg = yes(Arg)
+    ;
+        find_arg_by_var(Args, Var, MaybeArg)
+    ).
+
 %----------------------------------------------------------------------------%
 
 :- pred pardgoal_consumed_vars_accum(pard_goal_detail::in,
     set(var_rep)::in, set(var_rep)::out) is det.
 
 pardgoal_consumed_vars_accum(Goal, !Vars) :-
-    RefedVars = Goal ^ pgd_inst_map_info ^ im_consumed_vars,
+    RefedVars = Goal ^ goal_annotation ^ pgd_inst_map_info ^ im_consumed_vars,
     set.union(RefedVars, !Vars).
 
     % Check if it is appropriate to parallelise this call.  That is it must be
@@ -2293,15 +2349,6 @@ maybe_costly_call(Info, GoalPath, Atomic
         ; AtomicGoal = method_call_rep(_, _, Args)
         ; AtomicGoal = plain_call_rep(_, _, Args)
         ),
-        (
-            ( AtomicGoal = higher_order_call_rep(_, _)
-            ; AtomicGoal = method_call_rep(_, _, _)
-            ),
-            Callee = unknown_callee 
-        ; 
-            AtomicGoal = plain_call_rep(ModuleName, CalleeName, _),
-            Callee = named_callee(ModuleName, CalleeName)
-        ),
         map.lookup(Info ^ ipi_call_sites, GoalPath, CallSite),
         % Lookup var use information.
         CallSiteKind = CallSite ^ ccsr_kind_and_callee,
@@ -2329,19 +2376,18 @@ maybe_costly_call(Info, GoalPath, Atomic
                         VarUseInfo)
                 ), Args, VarModeAndUses)
         ),
-        map(maybe_search_var_name(Info ^ ipi_var_table), Args, VarNames),
 
+        % XXX: The goal annotations cannot represent reasons why a goal can't
+        % be parallelised, for example it could be nondet, semidet or
+        % impure.
         ( can_parallelise_call(Info, Detism, CallSite) ->
-            CostPercall = cs_cost_get_percall(get_call_site_cost(Info,
-                CallSite)),
-            GoalType = 
-                pgt_call(Callee, VarNames, Args, CostPercall, VarModeAndUses,
-                    CallSite)
+            CostAboveThreshold = cost_above_par_threshold
         ;
+            CostAboveThreshold = cost_not_above_par_threshold
+        ),
             CallSiteCost = get_call_site_cost(Info, CallSite),
-            GoalType = pgt_cheap_call(Callee, VarNames, Args, VarModeAndUses,
-                CallSiteCost)
-        )
+        GoalType = pgt_call(CallSiteCost, CostAboveThreshold, VarModeAndUses,
+            CallSite) 
     ).
 
 :- pred var_get_mode(inst_map::in, inst_map::in, var_rep::in, var_mode_rep::out)
@@ -2352,52 +2398,74 @@ var_get_mode(InstMapBefore, InstMapAfter
     inst_map_get(InstMapAfter, VarRep, InstAfter, _),
     VarModeRep = var_mode_rep(InstBefore, InstAfter).
 
-    % Transform a conjunction of goals into a list of pard goals..
-    %
-    % The results are returned in the order that they appear.
+    % Transform a goal in a conjunction into a pard_goal.
     %
-:- pred conj_to_pard_goal_list(list(goal_rep(inst_map_info))::in,
-    goal_path::in, int::in, implicit_parallelism_info::in,
-    list(pard_goal_detail)::in, list(pard_goal_detail)::out,
+:- pred goal_to_pard_goal(implicit_parallelism_info::in, goal_path::in,
+    (func(int) = goal_path_step)::in,
+    goal_rep(inst_map_info)::in, pard_goal_detail::out,
     int::in, int::out) is det.
 
-conj_to_pard_goal_list([], _, _, _, !PardGoals, !NumCostlyCalls) :-
-    list.reverse(!PardGoals).
-
-conj_to_pard_goal_list([Goal | Goals], GoalPath0, ConjNum, Info,
-        !PardGoals, !NumCostlyCalls) :-
-    Goal = goal_rep(GoalExpr, Detism, InstMapInfo),
-    (
-        ( GoalExpr = conj_rep(_)
-        ; GoalExpr = disj_rep(_)
-        ; GoalExpr = switch_rep(_, _, _)
-        ; GoalExpr = ite_rep(_, _, _)
-        ; GoalExpr = negation_rep(_)
-        ; GoalExpr = scope_rep(_, _)
+goal_to_pard_goal(Info, GoalPath0, Step, !Goal, !GoalNum) :-
+    !.Goal = goal_rep(GoalExpr0, Detism, InstMapInfo),
+    GoalPath = goal_path_add_at_end(GoalPath0, Step(!.GoalNum)),
+    !:GoalNum = !.GoalNum + 1,
+    (
+        (
+            GoalExpr0 = conj_rep(Conjs0),
+            map_foldl(goal_to_pard_goal(Info, GoalPath, 
+                ( func(Num) = step_conj(Num) ) ), Conjs0, Conjs, 1, _),
+            GoalExpr = conj_rep(Conjs)
+        ;
+            GoalExpr0 = disj_rep(Disjs0),
+            map_foldl(goal_to_pard_goal(Info, GoalPath,
+                ( func(Num) = step_disj(Num) ) ), Disjs0, Disjs, 1, _),
+            GoalExpr = disj_rep(Disjs)
+        ;
+            GoalExpr0 = switch_rep(Var, CanFail, Cases0),
+            map_foldl(case_to_pard_goal(Info, GoalPath), Cases0, Cases, 1, _),
+            GoalExpr = switch_rep(Var, CanFail, Cases)
+        ; 
+            GoalExpr0 = ite_rep(Cond0, Then0, Else0),
+            goal_to_pard_goal(Info, GoalPath, func(_) = step_ite_cond, 
+                Cond0, Cond, 1, _),
+            goal_to_pard_goal(Info, GoalPath, func(_) = step_ite_then, 
+                Then0, Then, 1, _),
+            goal_to_pard_goal(Info, GoalPath, func(_) = step_ite_else, 
+                Else0, Else, 1, _),
+            GoalExpr = ite_rep(Cond, Then, Else)
+        ; 
+            GoalExpr0 = negation_rep(SubGoal0),
+            goal_to_pard_goal(Info, GoalPath, func(_) = step_neg,
+                SubGoal0, SubGoal, 1, _),
+            GoalExpr = negation_rep(SubGoal)
+        ; 
+            GoalExpr0 = scope_rep(SubGoal0, MaybeCut),
+            goal_to_pard_goal(Info, GoalPath, func(_) = step_neg,
+                SubGoal0, SubGoal, 1, _),
+            GoalExpr = scope_rep(SubGoal, MaybeCut)
         ),
         % XXX: We my consider lifting calls out of non-atomic goals so that
         % they can be parallelised,  or parallelising the whole non-atomic
         % goal.
         PardGoalType = pgt_non_atomic_goal
     ;
-        GoalExpr = atomic_goal_rep(_Context, _Line, _BoundVars, AtomicGoal),
-        GoalPath = goal_path_add_at_end(GoalPath0, step_conj(ConjNum)),
+        GoalExpr0 = atomic_goal_rep(Context, Line, BoundVars, AtomicGoal),
+        GoalExpr = atomic_goal_rep(Context, Line, BoundVars, AtomicGoal),
         maybe_costly_call(Info, GoalPath, AtomicGoal, Detism,
-            InstMapInfo, PardGoalType),
-        (
-            PardGoalType = pgt_call(_, _, _, _, _, _),
-            !:NumCostlyCalls = !.NumCostlyCalls + 1
-        ;
-            PardGoalType = pgt_cheap_call(_, _, _, _, _)
-        ;
-            PardGoalType = pgt_other_atomic_goal
-        )
+            InstMapInfo, PardGoalType)
     ),
-    PardGoal = pard_goal_detail(PardGoalType, Detism, ConjNum,
-        InstMapInfo),
-    !:PardGoals = [PardGoal | !.PardGoals],
-    conj_to_pard_goal_list(Goals, GoalPath0, ConjNum+1, Info, 
-        !PardGoals, !NumCostlyCalls).
+    PardGoalAnnotation = pard_goal_detail(PardGoalType, InstMapInfo, GoalPath),
+    !:Goal = goal_rep(GoalExpr, Detism, PardGoalAnnotation).
+
+:- pred case_to_pard_goal(implicit_parallelism_info::in, goal_path::in,
+    case_rep(inst_map_info)::in, case_rep(pard_goal_detail_annotation)::out, 
+    int::in, int::out) is det.
+
+case_to_pard_goal(Info, GoalPath0, !Case, !GoalNum) :-
+    !.Case = case_rep(ConsId, OtherConsId, Goal0),
+    goal_to_pard_goal(Info, GoalPath0, 
+        ( func(Num) = step_switch(Num, no) ), Goal0, Goal, !GoalNum),
+    !:Case = case_rep(ConsId, OtherConsId, Goal).
 
     % are_conjuncts_dependant(CallOutputs, InstMap, VarModeAndUse, !DepVars),
     %
@@ -2836,7 +2904,20 @@ transitive_map_insert(K, V, !Map) :-
 
 %-----------------------------------------------------------------------------%
 
-create_candidate_parallel_conj_report(Proc - CandidateParConjunction, Report) :-
+create_candidate_parallel_conj_proc_report(Proc - CandidateParConjunctionProc, 
+        Report) :-
+    CandidateParConjunctionProc = 
+        candidate_par_conjunctions_proc(VarTable, CandidateParConjunctions),
+    map(create_candidate_parallel_conj_report(VarTable, Proc), 
+        CandidateParConjunctions, Reports),
+    Report = cord_list_to_cord(Reports). 
+
+:- pred create_candidate_parallel_conj_report(var_table::in,
+    string_proc_label::in, candidate_par_conjunction(pard_goal)::in,
+    cord(string)::out) is det.
+
+create_candidate_parallel_conj_report(VarTable, Proc, CandidateParConjunction,
+        Report) :-
     print_proc_label_to_string(Proc, ProcString),
     CandidateParConjunction = candidate_par_conjunction(GoalPath,
         PartNum, IsDependant, GoalsBefore, Conjs, GoalsAfter, ParExecMetrics),
@@ -2874,29 +2955,34 @@ create_candidate_parallel_conj_report(Pr
         ReportHeaderStr),
     ReportHeader = singleton(ReportHeaderStr),
 
-    format_sequential_conjuncts(3, GoalsBefore, empty, ReportGoalsBefore),
-    format_parallel_conjunction(3, Conjs, ReportParConj),
-    format_sequential_conjuncts(3, GoalsAfter, empty, ReportGoalsAfter),
+    format_sequential_conjuncts(VarTable, 3, GoalsBefore, empty, 
+        ReportGoalsBefore),
+    format_parallel_conjunction(VarTable, 3, Conjs, ReportParConj),
+    format_sequential_conjuncts(VarTable, 3, GoalsAfter, empty, 
+        ReportGoalsAfter),
 
     Report = snoc(ReportHeader ++ ReportGoalsBefore ++ ReportParConj ++ 
         ReportGoalsAfter, "\n").
 
-:- pred format_parallel_conjunction(int::in, 
+:- pred format_parallel_conjunction(var_table::in, int::in, 
     list(seq_conj(pard_goal))::in, cord(string)::out) is det.
 
-format_parallel_conjunction(Indent, Conjs, Report) :-
+format_parallel_conjunction(VarTable, Indent, Conjs, Report) :-
     IndentStr = indent(Indent),
     Report0 = IndentStr ++ singleton("(\n"),
-    format_parallel_conjuncts(Indent, Conjs, Report0, Report). 
+    format_parallel_conjuncts(VarTable, Indent, Conjs, Report0, Report). 
 
-:- pred format_parallel_conjuncts(int::in, list(seq_conj(pard_goal))::in,
-    cord(string)::in, cord(string)::out) is det.
+:- pred format_parallel_conjuncts(var_table::in, int::in, 
+    list(seq_conj(pard_goal))::in, cord(string)::in, cord(string)::out) 
+    is det.
 
-format_parallel_conjuncts(Indent, [], !Report) :-
+format_parallel_conjuncts(_VarTable, Indent, [], !Report) :-
     IndentStr = indent(Indent),
     !:Report = snoc(!.Report ++ IndentStr, ")\n").
-format_parallel_conjuncts(Indent, [ Conj | Conjs ], !Report) :-
-    format_sequential_conjunction(Indent + 1, Conj, ConjReport),
+format_parallel_conjuncts(VarTable, Indent, [ Conj | Conjs ], !Report) :-
+    Conj = seq_conj(Goals),
+    format_sequential_conjuncts(VarTable, Indent + 1, Goals, 
+        empty, ConjReport),
     !:Report = !.Report ++ ConjReport,
     (
         Conjs = []
@@ -2904,50 +2990,47 @@ format_parallel_conjuncts(Indent, [ Conj
         Conjs = [_ | _],
         !:Report = snoc(!.Report ++ indent(Indent), "&\n")
     ),
-    format_parallel_conjuncts(Indent, Conjs, !Report).
+    format_parallel_conjuncts(VarTable, Indent, Conjs, !Report).
 
-:- pred format_sequential_conjunction(int::in, seq_conj(pard_goal)::in,
-    cord(string)::out) is det.
-
-format_sequential_conjunction(Indent, seq_conj(Conjs), Report) :-
-    format_sequential_conjuncts(Indent, Conjs, empty, Report).
-
-:- pred format_sequential_conjuncts(int::in, list(pard_goal)::in,
-    cord(string)::in, cord(string)::out) is det.
+:- pred format_sequential_conjuncts(var_table::in, int::in,
+    list(pard_goal)::in, cord(string)::in, cord(string)::out) is det.
 
-format_sequential_conjuncts(_Indent, [], !Report).
-format_sequential_conjuncts(Indent, [ Conj | Conjs ], !Report) :-
-    format_pard_goal(Indent, Conj, ConjReport),
-    !:Report = !.Report ++ ConjReport,
+format_sequential_conjuncts(VarTable, Indent, Conjs, !Report) :-
+    % The determinism is an assumption here.
     (
-        Conjs = [],
-        !:Report = snoc(!.Report, "\n")
+        Conjs = []
     ;
         Conjs = [_ | _],
-        !:Report = snoc(!.Report, ",\n")
-    ),
-    format_sequential_conjuncts(Indent, Conjs, !Report).
+        Conj = goal_rep(conj_rep(Conjs), det_rep, pard_goal_non_atomic),
+        print_goal_to_strings(VarTable, Indent, Conj, ConjReport),
+        !:Report = !.Report ++ ConjReport
+    ).
 
-:- pred format_pard_goal(int::in, pard_goal::in, cord(string)::out) is det.
+:- instance goal_annotation(pard_goal_annotation) where [
+        pred(print_goal_annotation_to_strings/2) is 
+            format_pard_goal_annotation
+    ].
 
-format_pard_goal(Indent, Goal, Report) :-
+:- pred format_pard_goal_annotation(pard_goal_annotation::in, 
+    cord(string)::out) is det.
+
+format_pard_goal_annotation(GoalAnnotation, Report) :-
     (
+        GoalAnnotation = pard_goal_call(CostPercall, CostAboveThreshold),
         (
-            Goal = pg_call(Callee, Vars, CostPercall),
-            Line1 = singleton(format("%% cost: %f\n", [f(CostPercall)]))
+            CostAboveThreshold = cost_above_par_threshold,
+            CostAboveThresholdStr = "above threshold"
         ;
-            Goal = pg_cheap_call(Callee, Vars),
-            Line1 = singleton("% Cheap call\n")
+            CostAboveThreshold = cost_not_above_par_threshold,
+            CostAboveThresholdStr = "not above threshold"
         ),
-        format_callee(Callee, CalleeReport),
-        ColsUsed = indent_size(Indent) + length(CalleeReport) + 1,
-        format_vars(Indent + 1, ColsUsed, Vars, empty, VarsReport),
-        Line2 = indent(Indent) ++ singleton(CalleeReport) ++ singleton("(") 
-            ++ VarsReport ++ singleton(")"),
-        Report = indent(Indent) ++ Line1 ++ Line2
+        Report = singleton(format("cost: %f ", [f(CostPercall)])) ++ 
+            singleton(CostAboveThresholdStr) ++ singleton(")")
     ;
-        Goal = pg_other_atomic_goal,
-        Report = indent(Indent) ++ singleton("other_atomic_goal")
+        ( GoalAnnotation = pard_goal_other_atomic
+        ; GoalAnnotation = pard_goal_non_atomic
+        ),
+        Report = cord.empty
     ).
 
 :- pred format_vars(int::in, int::in, list(maybe(string))::in, 
Index: deep_profiler/mdprof_feedback.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/mdprof_feedback.m,v
retrieving revision 1.23
diff -u -p -b -r1.23 mdprof_feedback.m
--- deep_profiler/mdprof_feedback.m	8 Jun 2010 13:00:51 -0000	1.23
+++ deep_profiler/mdprof_feedback.m	30 Jun 2010 12:41:15 -0000
@@ -194,7 +194,7 @@ create_feedback_report(feedback_data_can
             "    Parallel Conjunctions:\n\n",
         [f(DesiredParallelism), i(SparkingCost), i(SparkingDelay),
          i(LockingCost), i(NumConjs)])),
-    map(create_candidate_parallel_conj_report, Conjs, ReportConjs),
+    map(create_candidate_parallel_conj_proc_report, Conjs, ReportConjs),
     Report = append_list(list(ReportHeader ++ cord_list_to_cord(ReportConjs))).
 
 :- func help_message = string.
Index: deep_profiler/program_representation_utils.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/program_representation_utils.m,v
retrieving revision 1.23
diff -u -p -b -r1.23 program_representation_utils.m
--- deep_profiler/program_representation_utils.m	30 Apr 2010 13:09:54 -0000	1.23
+++ deep_profiler/program_representation_utils.m	30 Jun 2010 12:41:15 -0000
@@ -46,6 +46,13 @@
     %
 :- pred print_proc_label_to_string(string_proc_label::in, string::out) is det.
 
+    % print_goal_to_strings(VarTable, Indent, Goal, Strings).
+    %
+    % Print a goal (recursively) to a string representation.
+    %
+:- pred print_goal_to_strings(var_table::in, int::in, goal_rep(GoalAnn)::in,
+    cord(string)::out) is det <= goal_annotation(GoalAnn).
+
 %----------------------------------------------------------------------------%
 
 :- typeclass goal_annotation(T) where [
@@ -225,30 +232,45 @@ print_proc_label_to_string(ProcLabel, St
 
 %-----------------------------------------------------------------------------%
 
-:- pred print_goal_to_strings(var_table::in, int::in, goal_rep(GoalAnn)::in,
-    cord(string)::out) is det <= goal_annotation(GoalAnn).
-
 print_goal_to_strings(VarTable, Indent, GoalRep, Strings) :-
     GoalRep = goal_rep(GoalExprRep, DetismRep, GoalAnnotation),
-    detism_to_string(DetismRep, DetismString),
-    print_goal_annotation_to_strings(GoalAnnotation, GoalAnnotationString),
+    detism_to_string(DetismRep, DetismString0),
+    print_goal_annotation_to_strings(GoalAnnotation, GoalAnnotationString0),
+   
+    % Indicate which detisms and annotations apply to whole conjunctions.
+    ( GoalExprRep = conj_rep(_) ->
+        AnnotationPrefix = cord.singleton("% conj: ")
+    ;
+        AnnotationPrefix = cord.singleton("% ")
+    ),
+    GoalAnnotationString1 = AnnotationPrefix ++ GoalAnnotationString0,
+    DetismString = AnnotationPrefix ++ DetismString0,
+
+    % Don't print empty annotations, including their newline.
+    ( not is_empty(GoalAnnotationString0) ->
+        GoalAnnotationString = nl_indent(Indent) ++ GoalAnnotationString1
+    ;
+        GoalAnnotationString = cord.empty
+    ),
+    Strings = indent(Indent) ++ DetismString ++ 
+        GoalAnnotationString ++ 
+        nl ++ ExprString,
     (
         GoalExprRep = conj_rep(ConjGoalReps),
-        print_conj_to_strings(VarTable, Indent, ConjGoalReps, Strings)
+        print_conj_to_strings(VarTable, Indent, ConjGoalReps, ExprString)
     ;
         GoalExprRep = disj_rep(DisjGoalReps),
         print_disj_to_strings(VarTable, Indent, DisjGoalReps, no, DisjString),
-        Strings = indent(Indent) ++ DetismString ++ GoalAnnotationString ++
-            cord.singleton(" (\n") ++ DisjString ++ indent(Indent) ++
+        ExprString = indent(Indent) ++ 
+            cord.singleton("(\n") ++ DisjString ++ indent(Indent) ++
             cord.singleton(")\n")
     ;
         GoalExprRep = switch_rep(SwitchVarRep, CanFail, CasesRep),
         lookup_var_name(VarTable, SwitchVarRep, SwitchVarName),
-        string.format(" %s switch on %s\n",
+        string.format("%s switch on %s\n",
             [s(string(CanFail)), s(SwitchVarName)], SwitchOnString),
         print_switch_to_strings(VarTable, Indent, CasesRep, no, SwitchString),
-        Strings = indent(Indent) ++ DetismString ++ GoalAnnotationString ++
-            cord.singleton(SwitchOnString) ++
+        ExprString = indent(Indent) ++ cord.singleton(SwitchOnString) ++ 
             indent(Indent) ++ cord.singleton("(\n") ++ SwitchString ++
             indent(Indent) ++ cord.singleton(")\n")
     ;
@@ -257,16 +279,15 @@ print_goal_to_strings(VarTable, Indent, 
         print_goal_to_strings(VarTable, Indent + 1, ThenRep, ThenString),
         print_goal_to_strings(VarTable, Indent + 1, ElseRep, ElseString),
         IndentString = indent(Indent),
-        Strings = IndentString ++ DetismString ++ GoalAnnotationString ++
-            cord.singleton(" (\n") ++ CondString ++ IndentString ++
-            cord.singleton("->\n") ++ ThenString ++ IndentString ++
-            cord.singleton(";\n") ++ ElseString ++ IndentString ++
-            cord.singleton(")\n")
+        ExprString = IndentString ++ cord.singleton("(\n") ++ CondString ++ 
+            IndentString ++ cord.singleton("->\n") ++ ThenString ++ 
+            IndentString ++ cord.singleton(";\n") ++ ElseString ++ 
+            IndentString ++ cord.singleton(")\n")
     ;
         GoalExprRep = negation_rep(SubGoalRep),
         print_goal_to_strings(VarTable, Indent + 1, SubGoalRep, SubGoalString),
-        Strings = indent(Indent) ++ cord.singleton("not (\n") ++ SubGoalString
-            ++ indent(Indent) ++ cord.singleton(")\n")
+        ExprString = indent(Indent) ++ cord.singleton("not (\n") ++ 
+            SubGoalString ++ indent(Indent) ++ cord.singleton(")\n")
     ;
         GoalExprRep = scope_rep(SubGoalRep, MaybeCut),
         (
@@ -277,14 +298,14 @@ print_goal_to_strings(VarTable, Indent, 
             CutString = cord.empty
         ),
         print_goal_to_strings(VarTable, Indent + 1, SubGoalRep, SubGoalString),
-        Strings = indent(Indent) ++ DetismString ++ GoalAnnotationString ++
-            cord.singleton(" scope") ++ CutString ++ cord.singleton(" (\n") ++
+        ExprString = indent(Indent) ++ cord.singleton("scope") ++ CutString ++ 
+            cord.singleton(" (\n") ++
             SubGoalString ++ indent(Indent) ++ cord.singleton(")\n")
     ;
         GoalExprRep = atomic_goal_rep(_FileName, _LineNumber,
             _BoundVars, AtomicGoalRep),
-        print_atomic_goal_to_strings(GoalAnnotationString, VarTable, Indent,
-            DetismRep, AtomicGoalRep, Strings)
+        print_atomic_goal_to_strings(VarTable, AtomicGoalRep, ExprString0),
+        ExprString = indent(Indent) ++ ExprString0
     ).
 
 :- pred print_conj_to_strings(var_table::in, int::in,
@@ -364,15 +385,14 @@ print_switch_to_strings(VarTable, Indent
 print_cons_id_and_arity_to_strings(Indent, ConsIdArityRep, Strings) :-
     ConsIdArityRep = cons_id_arity_rep(ConsIdRep, Arity),
     string.format("%% case %s/%d\n", [s(ConsIdRep), i(Arity)], String),
-    Strings = cord.snoc(indent(Indent + 1), String).
+    Strings = cord.snoc(indent(Indent), String).
 
 %-----------------------------------------------------------------------------%
 
-:- pred print_atomic_goal_to_strings(cord(string)::in, var_table::in, int::in,
-    detism_rep::in, atomic_goal_rep::in, cord(string)::out) is det.
+:- pred print_atomic_goal_to_strings(var_table::in, atomic_goal_rep::in, 
+    cord(string)::out) is det.
 
-print_atomic_goal_to_strings(GoalAnnotationString, VarTable, Indent, DetismRep,
-        AtomicGoalRep, Strings) :-
+print_atomic_goal_to_strings(VarTable, AtomicGoalRep, Strings) :-
     (
         (
             AtomicGoalRep = unify_construct_rep(VarRep, ConsIdRep, ArgReps),
@@ -382,7 +402,7 @@ print_atomic_goal_to_strings(GoalAnnotat
             UnifyOp = "=>"
         ),
         lookup_var_name(VarTable, VarRep, VarName),
-        string.format(" %s %s %s", [s(VarName), s(UnifyOp), s(ConsIdRep)],
+        string.format("%s %s %s", [s(VarName), s(UnifyOp), s(ConsIdRep)],
             UnifyString),
         print_args_to_strings(lookup_var_name, VarTable, ArgReps, ArgsString),
         Strings0 = cord.cons(UnifyString, ArgsString)
@@ -397,7 +417,7 @@ print_atomic_goal_to_strings(GoalAnnotat
             UnifyOp = "=>"
         ),
         lookup_var_name(VarTable, VarRep, VarName),
-        string.format(" %s %s %s", [s(VarName), s(UnifyOp), s(ConsIdRep)],
+        string.format("%s %s %s", [s(VarName), s(UnifyOp), s(ConsIdRep)],
             UnifyString),
         print_args_to_strings(print_maybe_var, VarTable, MaybeArgReps,
             ArgsString),
@@ -406,59 +426,57 @@ print_atomic_goal_to_strings(GoalAnnotat
         AtomicGoalRep = unify_assign_rep(TargetRep, SourceRep),
         lookup_var_name(VarTable, TargetRep, TargetName),
         lookup_var_name(VarTable, SourceRep, SourceName),
-        string.format(" %s := %s", [s(TargetName), s(SourceName)], String),
+        string.format("%s := %s", [s(TargetName), s(SourceName)], String),
         Strings0 = cord.singleton(String)
     ;
         AtomicGoalRep = cast_rep(TargetRep, SourceRep),
         lookup_var_name(VarTable, TargetRep, TargetName),
         lookup_var_name(VarTable, SourceRep, SourceName),
-        string.format(" cast %s to %s", [s(SourceName), s(TargetName)], String),
+        string.format("cast %s to %s", [s(SourceName), s(TargetName)], String),
         Strings0 = cord.singleton(String)
     ;
         AtomicGoalRep = unify_simple_test_rep(TargetRep, SourceRep),
         lookup_var_name(VarTable, TargetRep, TargetName),
         lookup_var_name(VarTable, SourceRep, SourceName),
-        string.format(" %s == %s", [s(SourceName), s(TargetName)], String),
+        string.format("%s == %s", [s(SourceName), s(TargetName)], String),
         Strings0 = cord.singleton(String)
     ;
         AtomicGoalRep = pragma_foreign_code_rep(Args),
         print_args_to_strings(lookup_var_name, VarTable, Args, ArgsString),
-        Strings0 = cord.singleton(" foreign_proc(") ++ ArgsString ++
+        Strings0 = cord.singleton("foreign_proc(") ++ ArgsString ++
             cord.singleton(")")
     ;
         AtomicGoalRep = higher_order_call_rep(HOVarRep, Args),
         lookup_var_name(VarTable, HOVarRep, HOVarName),
-        string.format(" %s(", [s(HOVarName)], HeadString),
+        string.format("%s(", [s(HOVarName)], HeadString),
         print_args_to_strings(lookup_var_name, VarTable, Args, ArgsString),
         Strings0 = cord.singleton(HeadString) ++ ArgsString ++
             cord.singleton(")")
     ;
         AtomicGoalRep = method_call_rep(TCIVarRep, MethodNumber, Args),
         lookup_var_name(VarTable, TCIVarRep, TCIVarName),
-        string.format(" method %d of %s(", [i(MethodNumber), s(TCIVarName)],
+        string.format("method %d of %s(", [i(MethodNumber), s(TCIVarName)],
             HeadString),
         print_args_to_strings(lookup_var_name, VarTable, Args, ArgsString),
         Strings0 = cord.singleton(HeadString) ++ ArgsString ++
             cord.singleton(")")
     ;
         AtomicGoalRep = plain_call_rep(Module, Pred, Args),
-        string.format(" %s.%s", [s(Module), s(Pred)], HeadString),
+        string.format("%s.%s", [s(Module), s(Pred)], HeadString),
         print_args_to_strings(lookup_var_name, VarTable, Args, ArgsString),
         Strings0 = cord.cons(HeadString, ArgsString)
     ;
         AtomicGoalRep = builtin_call_rep(Module, Pred, Args),
-        string.format(" builtin %s.%s", [s(Module), s(Pred)], HeadString),
+        string.format("builtin %s.%s", [s(Module), s(Pred)], HeadString),
         print_args_to_strings(lookup_var_name, VarTable, Args, ArgsString),
         Strings0 = cord.cons(HeadString, ArgsString)
     ;
         AtomicGoalRep = event_call_rep(Event, Args),
-        string.format(" event %s", [s(Event)], HeadString),
+        string.format("event %s", [s(Event)], HeadString),
         print_args_to_strings(lookup_var_name, VarTable, Args, ArgsString),
         Strings0 = cord.cons(HeadString, ArgsString)
     ),
-    detism_to_string(DetismRep, DetismString),
-    Strings = indent(Indent) ++ DetismString ++ GoalAnnotationString ++
-        Strings0 ++ nl.
+    Strings = Strings0 ++ nl.
 
 %-----------------------------------------------------------------------------%
 
@@ -519,6 +537,10 @@ indent(N) =
         cord.singleton("  ") ++ indent(N - 1)
     ).
 
+:- func nl_indent(int) = cord(string).
+
+nl_indent(N) = nl ++ indent(N).
+
 :- pred detism_to_string(detism_rep::in, cord(string)::out) is det.
 
 detism_to_string(Detism, DetismStrCord) :-
Index: mdbcomp/feedback.m
===================================================================
RCS file: /home/mercury1/repository/mercury/mdbcomp/feedback.m,v
retrieving revision 1.11
diff -u -p -b -r1.11 feedback.m
--- mdbcomp/feedback.m	8 Jun 2010 13:00:51 -0000	1.11
+++ mdbcomp/feedback.m	1 Jul 2010 04:33:31 -0000
@@ -26,7 +26,6 @@
 :- import_module int.
 :- import_module io.
 :- import_module list.
-:- import_module maybe.
 :- import_module string.
 
 %-----------------------------------------------------------------------------%
@@ -82,7 +81,7 @@
                     % variable in call sequence counts.
 
                 conjunctions        :: assoc_list(string_proc_label,
-                                        candidate_par_conjunction(pard_goal))
+                                        candidate_par_conjunctions_proc)
                     % Assoclist of procedure labels and candidate parallel
                     % conjunctions.
             ).
@@ -96,6 +95,20 @@
     --->    stat_mean
     ;       stat_median.
 
+    % The set of candidate parallel conjunctions within a procedure.
+    %
+:- type candidate_par_conjunctions_proc(GoalType)
+    --->    candidate_par_conjunctions_proc(
+                cpcp_var_table  :: var_table,
+                    % A variable name table for the variables that have
+                    % sensible names.
+                                        
+                cpcp_par_conjs  :: list(candidate_par_conjunction(GoalType))
+            ).
+
+:- type candidate_par_conjunctions_proc ==
+    candidate_par_conjunctions_proc(pard_goal).
+
     % A conjunction that is a candidate for parallelisation, it is identified
     % by a procedure label, goal path to the conjunction and the call sites
     % within the conjunction that are to be parallelised.
@@ -158,37 +171,43 @@
     % A parallelised goal (pard_goal), a goal within a parallel conjunction.
     % We don't yet have to represent many types of goals or details about them.
     %
-:- type pard_goal
-    --->    pg_call(
-                % This is a call that we're considering parallelising.  It has
-                % a significant enough cost to be considered for
-                % parallelisation.
-                
-                pgc_callee                  :: callee_rep,
+:- type pard_goal == goal_rep(pard_goal_annotation).
                     
-                pgc_vars                    :: list(maybe(string)),
-                    % The names of variables (if used defined) given as
-                    % arguments to this call.
+:- type pard_goal_annotation
+    --->    pard_goal_call(
+                % A call goal,  These are the most interesting goals WRT
+                % parallelisation.
                     
-                pgc_cost_percall            :: float
+                pgc_cost_percall            :: float,
                     % The per-call cost of this call in call sequence counts.
-            )
-    ;       pg_cheap_call(
-                % This call is to cheap to be considered for parallelisation,
-                % we track it in the feedback information to help inform the
-                % compiler about _how_ to parallelise calls around it.
                 
-                pgcc_callee                  :: callee_rep,
-                pgcc_vars                    :: list(maybe(string))
-                    % As above.
+                pgc_coat_above_threshold    :: cost_above_par_threshold
             )
-    ;       pg_other_atomic_goal.
+    ;       pard_goal_other_atomic
                 % Some other (cheap) atomic goal.
 
+    ;       pard_goal_non_atomic.
+                % A non-atomic goal.
+
+:- type cost_above_par_threshold
+    --->    cost_above_par_threshold
+                % The goal has a significant enough cost to be considered for
+                % parallelisation.
+
+    ;       cost_not_above_par_threshold.
+                % The goal is to cheap to be considered for parallelisation,
+                % we track it in the feedback information to help inform the
+                % compiler about _how_ to parallelise calls around it.
+
 :- type conjuncts_are_dependant
     --->    conjuncts_are_dependant
     ;       conjuncts_are_independent.
 
+:- pred convert_candidate_par_conjunctions_proc(pred(A, B),
+    candidate_par_conjunctions_proc(A), candidate_par_conjunctions_proc(B)).
+:- mode convert_candidate_par_conjunctions_proc(pred(in, out) is det, 
+    in, out) is det.
+
 :- pred convert_candidate_par_conjunction(pred(A, B), 
     candidate_par_conjunction(A), candidate_par_conjunction(B)).
 :- mode convert_candidate_par_conjunction(pred(in, out) is det, in, out) is det.
@@ -734,7 +753,7 @@ feedback_first_line = "Mercury Compiler 
 
 :- func feedback_version = string.
 
-feedback_version = "8".
+feedback_version = "9".
 
 %-----------------------------------------------------------------------------%
 %
@@ -743,6 +762,11 @@ feedback_version = "8".
 % XXX: These and their types should probably be moved to a new module.
 %
 
+convert_candidate_par_conjunctions_proc(Conv, CPCProcA, CPCProcB) :-
+    CPCProcA = candidate_par_conjunctions_proc(VarTable, CPCA),
+    map(convert_candidate_par_conjunction(Conv), CPCA, CPCB),
+    CPCProcB = candidate_par_conjunctions_proc(VarTable, CPCB).
+
 convert_candidate_par_conjunction(Conv, CPC0, CPC) :-
     CPC0 = candidate_par_conjunction(GoalPath, PartNum, IsDependent, 
         GoalsBefore0, Conjs0, GoalsAfter0, Metrics),
Index: mdbcomp/program_representation.m
===================================================================
RCS file: /home/mercury1/repository/mercury/mdbcomp/program_representation.m,v
retrieving revision 1.50
diff -u -p -b -r1.50 program_representation.m
--- mdbcomp/program_representation.m	27 Apr 2010 03:39:28 -0000	1.50
+++ mdbcomp/program_representation.m	30 Jun 2010 12:41:15 -0000
@@ -416,6 +416,12 @@
     %
 :- pred case_get_goal(case_rep(T)::in, goal_rep(T)::out) is det.
 
+    % Transform a goal representation annotated with T into one annotated with
+    % U.
+    %
+:- pred transform_goal_rep(pred(T, U), goal_rep(T), goal_rep(U)).
+:- mode transform_goal_rep(pred(in, out) is det, in, out) is det.
+
 %-----------------------------------------------------------------------------%
 
     % Describe a call site.
@@ -667,6 +673,16 @@
 :- mode var_num_rep_byte(in, out) is det.
 :- mode var_num_rep_byte(out, in) is semidet.
 
+    % Represent whether a scope goal cuts away solutions or not.
+    %
+:- pred cut_byte(maybe_cut, int).
+:- mode cut_byte(in, out) is det.
+:- mode cut_byte(out, in) is semidet.
+
+:- pred can_fail_byte(switch_can_fail_rep, int).
+:- mode can_fail_byte(in, out) is det.
+:- mode can_fail_byte(out, in) is semidet.
+
 %-----------------------------------------------------------------------------%
 
 :- pred trace_read_proc_defn_rep(bytecode_bytes::in, label_layout::in,
@@ -828,6 +844,55 @@ proc_defn_rep_type = type_of(_ : proc_de
 
 goal_rep_type = type_of(_ : goal_rep).
 
+transform_goal_rep(Pred, Goal0, Goal) :-
+    Goal0 = goal_rep(Expr0, Detism, A),
+    transform_goal_expr(Pred, Expr0, Expr),
+    Pred(A, B),
+    Goal = goal_rep(Expr, Detism, B).
+
+:- pred transform_goal_expr(pred(T, U), goal_expr_rep(T), goal_expr_rep(U)).
+:- mode transform_goal_expr(pred(in, out) is det, in, out) is det.
+
+transform_goal_expr(Pred, Expr0, Expr) :-
+    (
+        Expr0 = conj_rep(Conjs0),
+        map(transform_goal_rep(Pred), Conjs0, Conjs),
+        Expr = conj_rep(Conjs)
+    ;
+        Expr0 = disj_rep(Disjs0),
+        map(transform_goal_rep(Pred), Disjs0, Disjs),
+        Expr = disj_rep(Disjs)
+    ;
+        Expr0 = switch_rep(Var, CanFail, Cases0),
+        map(transform_switch_case(Pred), Cases0, Cases),
+        Expr = switch_rep(Var, CanFail, Cases)
+    ;
+        Expr0 = ite_rep(Cond0, Then0, Else0),
+        transform_goal_rep(Pred, Cond0, Cond),
+        transform_goal_rep(Pred, Then0, Then),
+        transform_goal_rep(Pred, Else0, Else),
+        Expr = ite_rep(Cond, Then, Else)
+    ;
+        Expr0 = negation_rep(NegGoal0),
+        transform_goal_rep(Pred, NegGoal0, NegGoal),
+        Expr = negation_rep(NegGoal)
+    ;
+        Expr0 = scope_rep(SubGoal0, MaybeCut),
+        transform_goal_rep(Pred, SubGoal0, SubGoal),
+        Expr = scope_rep(SubGoal, MaybeCut)
+    ;
+        Expr0 = atomic_goal_rep(Filename, Lineno, BoundVars, AtomicGoal),
+        Expr = atomic_goal_rep(Filename, Lineno, BoundVars, AtomicGoal)
+    ).
+        
+:- pred transform_switch_case(pred(T, U), case_rep(T), case_rep(U)).
+:- mode transform_switch_case(pred(in, out) is det, in, out) is det.
+
+transform_switch_case(Pred, Case0, Case) :-
+    Case0 = case_rep(ConsId, OtherConsIds, Goal0),
+    transform_goal_rep(Pred, Goal0, Goal),
+    Case = case_rep(ConsId, OtherConsIds, Goal).
+
 %-----------------------------------------------------------------------------%
 
     % Goal paths are stored as a list in reverse order, that is the inner most
@@ -1418,10 +1483,8 @@ read_goal(VarNumRep, ByteCode, StringTab
         ;
             GoalType = goal_scope,
             read_byte(ByteCode, MaybeCutByte, !Pos),
-            ( MaybeCutByte = 0 ->
-                MaybeCut = scope_is_no_cut
-            ; MaybeCutByte = 1 ->
-                MaybeCut = scope_is_cut
+            ( cut_byte(MaybeCutPrime, MaybeCutByte) ->
+                MaybeCut = MaybeCutPrime
             ;
                 error("read_goal: bad maybe_cut")
             ),
@@ -1662,6 +1725,12 @@ read_switch_can_fail(Bytecode, CanFail, 
         error("read_goal: bad switch_can_fail")
     ).
 
+cut_byte(scope_is_no_cut, 0).
+cut_byte(scope_is_cut, 1).
+
+can_fail_byte(switch_can_fail_rep, 0).
+can_fail_byte(switch_can_not_fail_rep, 1).
+
     % An abstraction to read the given number of items using the higher order
     % predicate.
     %
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20100704/4950f358/attachment.sig>


More information about the reviews mailing list