[m-rev.] for post-commit review: goal ids

Zoltan Somogyi zs at csse.unimelb.edu.au
Mon Dec 20 18:46:07 AEDT 2010


For review by anyone. I don't particularly care whether it makes it to
the release branch or not.

Zoltan.

The existing representation of goal_paths is suboptimal for several reasons.

- Sometimes we need forward goal paths (e.g. to look up goals), and sometimes
  we need reverse goal paths (e.g. when computing goal paths in the first
  place). We had two types for them, but
  
  - their names, goal_path and goal_path_consable, were not expressive, and
  - we could store only one of them in goal_infos.

- Testing whether goal A is a subgoal of goal B is quite error-prone using
  either form of goal paths.

- Using a goal path as a key in a map, which several compiler passes want to
  do, requires lots of expensive comparisons.

This diff replaces most uses of goal paths with goal ids. A goal id is an
integer, so it can be used as a key in faster maps, or even in arrays.
Every goal in the body of a procedure gets its id allocated in a depth first
search. Since we process each goal before we dive into is descendants,
the goal representing the whole body of a procedure always gets goal id 0.
The depth first traversal also builds up a map (the containing goal map)
that tells us the parent goal of ever subgoal, with the obvious exception
of the root goal itself. From the containing goal map, one can compute
both reverse and forward goal paths. It can also serve as the basis of an
efficient test of whether the goal identified by goal id A is an ancestor
of another goal identified by goal id B. We don't yet use this test,
but I expect we will in the future.

mdbcomp/program_representation.m:
	Add the goal_id type.

	Replace the existing goal_path and goal_path_consable types
	with two new types, forward_goal_path and reverse_goal_path.
	Since these now have wrappers around the list of goal path steps
	that identify each kind of goal path, it is now ok to expose their
	representations. This makes several compiler passes easier to code.

	Update the set of operations on goal paths to work on the new data
	structures.

	Add a couple of step types to represent lambdas and try goals.
	Their omission prior to this would have been a bug for constraint-based
	mode analysis, or any other compiler pass prior to the expansion out
	of lambda and try goals that wanted to use goal paths to identify
	subgoals.

browser/declarative_tree.m:
mdbcomp/rtti_access.m:
mdbcomp/slice_and_dice.m:
mdbcomp/trace_counts.m:
slice/mcov.m:
deep_profiler/*.m:
	Conform to the changes in goal path representation.

compiler/hlds_goal:
	Replace the goal_path field with a goal_id field in the goal_info,
	indicating that from now on, this should be used to identify goals.

	Keep a reverse_goal_path field in the goal_info for use by RBMM and
	CTGC. Those analyses were too hard to convert to using goal_ids,
	especially since RBMM uses goal_paths to identify goals in multi-pass
	algorithms that should be one-pass and should not NEED to identify
	any goals for later processing.

compiler/goal_path:
	Add predicates to fill in goal_ids, and update the predicates
	filling in the now deprecated reverse goal path fields.

	Add the operations needed by the rest of the compiler
	on goal ids and containing goal maps.

	Remove the option to set goal paths using "mode equivalent steps".
	Constraint based mode analysis now uses goal ids, and can now
	do its own equivalent optimization quite simply.

	Move the goal_path module from the check_hlds package to the hlds
	package.

compiler/*.m:
	Conform to the changes in goal path representation.

	Most modules now use goal_ids to identify goals, and use a containing
	goal map to convert the goal ids to goal paths when needed.
	However, the ctgc and rbmm modules still use (reverse) goal paths.

library/digraph.m:
library/group.m:
library/injection.m:
library/pprint.m:
library/pretty_printer.m:
library/term_to_xml.m:
	Minor style improvements.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/extra
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/extra
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/doc
cvs diff: Diffing boehm_gc/libatomic_ops/src
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/armcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops/tests
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/m4
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
Index: browser/declarative_tree.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/declarative_tree.m,v
retrieving revision 1.62
diff -u -r1.62 declarative_tree.m
--- browser/declarative_tree.m	7 Dec 2010 03:09:13 -0000	1.62
+++ browser/declarative_tree.m	7 Dec 2010 03:38:41 -0000
@@ -772,7 +772,7 @@
                 % No if start_loc is cur_goal; and yes wrapped around the
                 % goal path of the call in the parent procedure if start_loc
                 % is parent_goal.
-                maybe(goal_path),
+                maybe(reverse_goal_path),
 
                 % The body of the procedure indicated by start_loc.
                 maybe(proc_defn_rep)
@@ -787,7 +787,7 @@
     ;       parent_goal(R, trace_node(R)).
 
 :- type goal_and_path
-    --->    goal_and_path(goal_rep, goal_path).
+    --->    goal_and_path(goal_rep, reverse_goal_path).
 
 :- type goal_and_path_list ==   list(goal_and_path).
 
@@ -797,7 +797,7 @@
                 int,                % line number
                 list(var_rep),      % vars bound by the atomic goal
                 atomic_goal_rep,    % the atomic goal itself
-                goal_path,          % its goal path
+                reverse_goal_path,  % its goal path
                 maybe(R)            % if the atomic goal is a call,
                                     % the id of the call's exit event
             ).
@@ -897,7 +897,7 @@
     ).
 
 :- pred trace_dependency_in_proc_defn_rep(S::in, term_path::in,
-    start_loc(R)::in, int::in, int::in, R::in, maybe(goal_path)::in,
+    start_loc(R)::in, int::in, int::in, R::in, maybe(reverse_goal_path)::in,
     proc_defn_rep::in, subterm_origin(edt_node(R))::out) is det
     <= annotated_trace(S, R).
 
@@ -915,8 +915,8 @@
     HeadVars = list.map(head_var_to_var, ProcDefnRep ^ pdr_head_vars),
     GoalRep = ProcDefnRep ^ pdr_goal,
     is_traced_grade(AllTraced),
-    MaybePrims = make_primitive_list(Store, 
-        [goal_and_path(GoalRep, empty_goal_path)], Contour, StartPath, ArgNum,
+    MaybePrims = make_primitive_list(Store,
+        [goal_and_path(GoalRep, rgp([]))], Contour, StartPath, ArgNum,
         TotalArgs, HeadVars, AllTraced, []),
     (
         MaybePrims = yes(primitive_list_and_var(Primitives, Var,
@@ -1016,7 +1016,7 @@
     CallPrecId = CallNode ^ call_preceding,
     CallAtom = get_trace_call_atom(CallNode),
     CallPathStr = get_goal_path_from_maybe_label(CallNode ^ call_return_label),
-    goal_path_from_string_det(CallPathStr, CallPath),
+    rev_goal_path_from_string_det(CallPathStr, CallPath),
     StartLoc = parent_goal(CallId, CallNode),
     absolute_arg_num(ArgPos, CallAtom, ArgNum),
     TotalArgs = length(CallAtom ^ atom_args),
@@ -1158,7 +1158,7 @@
     % subterms.
     %
 :- func make_primitive_list(S, goal_and_path_list,
-    assoc_list(R, trace_node(R)), maybe(goal_path), int, int,
+    assoc_list(R, trace_node(R)), maybe(reverse_goal_path), int, int,
     list(var_rep), bool, list(annotated_primitive(R)))
     = maybe(primitive_list_and_var(R)) <= annotated_trace(S, R).
 
@@ -1212,12 +1212,12 @@
     ).
 
 :- pred contour_at_end_path(assoc_list(R, trace_node(R))::in,
-    maybe(goal_path)::in) is semidet.
+    maybe(reverse_goal_path)::in) is semidet.
 
 contour_at_end_path([_ - Node], yes(EndPath)) :-
     Node = node_call(_, _, _, _, _, _, MaybeReturnLabel, _, _, _),
     CallPathStr = get_goal_path_from_maybe_label(MaybeReturnLabel),
-    goal_path_from_string_det(CallPathStr, CallPath),
+    rev_goal_path_from_string_det(CallPathStr, CallPath),
     CallPath = EndPath.
 
 :- pred next_goal_generates_internal_event(list(goal_and_path)::in) is semidet.
@@ -1236,9 +1236,9 @@
     % along the remaining contour. If it cannot match a higher order call
     % to a contour event and AllTraced is no, then it returns "no".
     %
-:- func match_goal_to_contour_event(S, goal_rep, goal_path, goal_and_path_list,
-    assoc_list(R, trace_node(R)), maybe(goal_path), int, int,
-    list(var_rep), bool, list(annotated_primitive(R)))
+:- func match_goal_to_contour_event(S, goal_rep, reverse_goal_path,
+    goal_and_path_list, assoc_list(R, trace_node(R)), maybe(reverse_goal_path),
+    int, int, list(var_rep), bool, list(annotated_primitive(R)))
     = maybe(primitive_list_and_var(R)) <= annotated_trace(S, R).
 
 match_goal_to_contour_event(Store, Goal, Path, GoalPaths, Contour, MaybeEnd,
@@ -1252,7 +1252,7 @@
             Primitives0)
     ;
         GoalExpr = scope_rep(InnerGoal, MaybeCut),
-        InnerPath = goal_path_add_at_end(Path, step_scope(MaybeCut)),
+        InnerPath = rev_goal_path_add_at_end(Path, step_scope(MaybeCut)),
         InnerAndPath = goal_and_path(InnerGoal, InnerPath),
         MaybePrims = make_primitive_list(Store, [InnerAndPath | GoalPaths],
             Contour, MaybeEnd, ArgNum, TotalArgs, HeadVars, AllTraced,
@@ -1283,8 +1283,8 @@
                 ContourHeadNode = node_later_disj(_, Label, _)
             ),
             DisjPathStr = get_goal_path_from_label_layout(Label),
-            goal_path_from_string_det(DisjPathStr, DisjPath),
-            goal_path_remove_last(DisjPath, DisjInitialPath, DisjLastStep),
+            rev_goal_path_from_string_det(DisjPathStr, DisjPath),
+            rev_goal_path_remove_last(DisjPath, DisjInitialPath, DisjLastStep),
             DisjInitialPath = Path,
             DisjLastStep = step_disj(N)
         ->
@@ -1303,8 +1303,8 @@
             Contour = [_ - ContourHeadNode | ContourTail],
             ContourHeadNode = node_switch(_, Label),
             ArmPathStr = get_goal_path_from_label_layout(Label),
-            goal_path_from_string_det(ArmPathStr, ArmPath),
-            goal_path_remove_last(ArmPath, ArmInitialPath, ArmLastStep),
+            rev_goal_path_from_string_det(ArmPathStr, ArmPath),
+            rev_goal_path_remove_last(ArmPath, ArmInitialPath, ArmLastStep),
             ArmInitialPath = Path,
             ArmLastStep = step_switch(N, _)
         ->
@@ -1324,12 +1324,12 @@
             Contour = [_ - ContourHeadNode | ContourTail],
             ContourHeadNode = node_cond(_, Label, _),
             CondPathStr = get_goal_path_from_label_layout(Label),
-            goal_path_from_string_det(CondPathStr, CondPath),
-            goal_path_remove_last(CondPath, CondInitialPath, CondLastStep),
+            rev_goal_path_from_string_det(CondPathStr, CondPath),
+            rev_goal_path_remove_last(CondPath, CondInitialPath, CondLastStep),
             CondInitialPath = Path,
             CondLastStep = step_ite_cond
         ->
-            ThenPath = goal_path_add_at_end(Path, step_ite_then),
+            ThenPath = rev_goal_path_add_at_end(Path, step_ite_then),
             CondAndPath = goal_and_path(Cond, CondPath),
             ThenAndPath = goal_and_path(Then, ThenPath),
             MaybePrims = make_primitive_list(Store,
@@ -1341,12 +1341,12 @@
             cond_node_from_id(Store, ElseCondId, CondNode),
             CondNode = node_cond(_, Label, _),
             CondPathStr = get_goal_path_from_label_layout(Label),
-            goal_path_from_string_det(CondPathStr, CondPath),
-            goal_path_remove_last(CondPath, CondInitialPath, CondLastStep),
+            rev_goal_path_from_string_det(CondPathStr, CondPath),
+            rev_goal_path_remove_last(CondPath, CondInitialPath, CondLastStep),
             CondInitialPath = Path,
             CondLastStep = step_ite_cond
         ->
-            ElsePath = goal_path_add_at_end(Path, step_ite_else),
+            ElsePath = rev_goal_path_add_at_end(Path, step_ite_else),
             ElseAndPath = goal_and_path(Else, ElsePath),
             MaybePrims = make_primitive_list(Store, [ElseAndPath | GoalPaths],
                 ContourTail, MaybeEnd, ArgNum, TotalArgs, HeadVars, AllTraced,
@@ -1370,7 +1370,7 @@
         ->
             % The end of the primitive list is somewhere inside
             % NegGoal.
-            NegPath = goal_path_add_at_end(Path, step_neg),
+            NegPath = rev_goal_path_add_at_end(Path, step_neg),
             NegAndPath = goal_and_path(NegGoal, NegPath),
             MaybePrims = make_primitive_list(Store, [NegAndPath], ContourTail,
                 MaybeEnd, ArgNum, TotalArgs, HeadVars, AllTraced, Primitives0)
@@ -1412,8 +1412,8 @@
     % more likely for the majority of untraced calls).
     %
 :- func match_atomic_goal_to_contour_event(S, string, int,
-    list(var_rep), atomic_goal_rep, list(var_rep), goal_path,
-    list(goal_and_path), assoc_list(R, trace_node(R)), maybe(goal_path),
+    list(var_rep), atomic_goal_rep, list(var_rep), reverse_goal_path,
+    list(goal_and_path), assoc_list(R, trace_node(R)), maybe(reverse_goal_path),
     int, int, list(var_rep), bool, list(annotated_primitive(R))) =
     maybe(primitive_list_and_var(R)) <= annotated_trace(S, R).
 
@@ -1429,7 +1429,7 @@
                 MaybeReturnLabel, _, _, _),
             Atom = get_trace_call_atom(ContourHeadNode),
             CallPathStr = get_goal_path_from_maybe_label( MaybeReturnLabel),
-            goal_path_from_string_det(CallPathStr, CallPath),
+            rev_goal_path_from_string_det(CallPathStr, CallPath),
             CallPath = EndPath
         ->
             (
@@ -1800,13 +1800,13 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred add_paths_to_conjuncts(list(goal_rep)::in, goal_path::in, int::in,
-    goal_and_path_list::out) is det.
+:- pred add_paths_to_conjuncts(list(goal_rep)::in, reverse_goal_path::in,
+    int::in, goal_and_path_list::out) is det.
 
 add_paths_to_conjuncts([], _, _, []).
 add_paths_to_conjuncts([Goal | Goals], ParentPath, N,
         [goal_and_path(Goal, Path) | GoalAndPaths]) :-
-    Path = goal_path_add_at_end(ParentPath, step_conj(N)),
+    Path = rev_goal_path_add_at_end(ParentPath, step_conj(N)),
     add_paths_to_conjuncts(Goals, ParentPath, N + 1, GoalAndPaths).
 
 %-----------------------------------------------------------------------------%
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/build_mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/build_mode_constraints.m,v
retrieving revision 1.37
diff -u -r1.37 build_mode_constraints.m
--- compiler/build_mode_constraints.m	15 Dec 2010 06:29:28 -0000	1.37
+++ compiler/build_mode_constraints.m	20 Dec 2010 07:08:43 -0000
@@ -35,8 +35,8 @@
 
 %-----------------------------------------------------------------------------%
 
-    % This represents the conjunction of the constraints it
-    % contains (which typically will refer to only one predicate).
+    % This represents the conjunction of the constraints it contains
+    % (which typically will refer to only one predicate).
     %
 :- type mode_constraints == pred_p_c_constraints.
 
@@ -46,23 +46,22 @@
     %
 :- type mc_var_info
     --->    mc_var_info(
+                % Produces constraint variables for producer/consumer
+                % constraints.
                 mc_varset   ::  mc_varset,
-                            % Produces constraint variables
-                            % for producer/consumer constraints.
 
+                % Bimap between constraint variables and the abstract
+                % representation of the proposition they represent.
                 rep_var_map ::  mc_var_map
-                            % Bimap between constraint variables
-                            % and the abstract representation
-                            % of the proposition they represent.
             ).
 
-    % A map between the constraint variables (mc_var) and what they
-    % represent ie the proposition that some program variable is
-    % produced at some goal path (for a particular predicate).
-    %
-    % This provides a quick way of looking up the constraint variable we
-    % need when we want to constrain the position in which a program
-    % variable can be produced.
+    % A map between the constraint variables (mc_var) and what they represent,
+    % i.e. the proposition that some program variable is produced at some goal
+    % (in a particular predicate).
+    %
+    % This provides a quick way of looking up the constraint variable we need
+    % when we want to constrain the position in which a program variable
+    % can be produced.
     %
 :- type mc_var_map == bimap(mc_rep_var, mc_var).
 
@@ -75,19 +74,18 @@
 :- type nonlocals == set(prog_var).
 
     % In order to uniquely distinguish a prog_var that may not be
-    % unique amongst predicates, this data structure is used to
-    % specify the predicate to which this prog_var is intended to
-    % apply.
+    % unique amongst predicates, this data structure is used to specify
+    % the predicate to which this prog_var is intended to apply.
     %
 :- type mc_prog_var ---> prog_var `in` pred_id.
 
     % An abstract representation of a mode constraint variable.
     %
-    % ProgVar `in` PredId, `at` GoalPath represents the constraint
-    % variable of the proposition that ProgVar is produced at
-    % goal GoalPath in predicate PredId.
+    % (ProgVar `in` PredId) `at` GoalId represents the constraint variable
+    % of the proposition that ProgVar is produced at goal GoalId
+    % in predicate PredId.
     %
-:- type mc_rep_var ---> mc_prog_var `at` goal_path.
+:- type mc_rep_var ---> mc_prog_var `at` goal_id.
 
 %-----------------------------------------------------------------------------%
 
@@ -99,11 +97,10 @@
     % constraint variables that describe whether or not a head variable
     % is produced by a call to the predicate.
     %
-    % (We do this all at once because intra-SCC calls refer to the
-    % production of program variables at the head of the callee,
-    % and the caller doesn't neccessarily have access to the
-    % relevant prog_varset to create the necessary constraint
-    % variables.)
+    % (We do this all at once because intra-SCC calls refer to the production
+    % of program variables at the head of the callee, and the caller doesn't
+    % neccessarily have access to the relevant prog_varset to create the
+    % necessary constraint variables.)
     %
 :- pred add_mc_vars_for_scc_heads(module_info::in, list(pred_id)::in,
     mc_var_info::in, mc_var_info::out) is det.
@@ -111,12 +108,11 @@
     % add_mc_vars_for_goal(PredId, ProgVarset, Goal, !VarInfo)
     %
     % For each nonlocal of Goal, makes sure a constraint variable exists
-    % in VarInfo representing the proposition that the nonlocal is
-    % produced at that Goal. Other variables are either local and must
-    % be produced at the current path or do not occur in the goal and so
-    % are not produced at the current path (although some such
-    % constraint variables are created later so as to simplify
-    % constraint generation).
+    % in VarInfo representing the proposition that the nonlocal is produced
+    % at that Goal. Other variables are either local and must be produced
+    % at the current path or do not occur in the goal and so are not produced
+    % at the current path (although some such constraint variables are
+    % created later so as to simplify constraint generation).
     %
     % NOTE: this predicate *does* recurse on subgoals.
     %
@@ -126,11 +122,10 @@
     % add_clauses_constraints(ModuleInfo, PredId, PredInfo, !VarInfo,
     %   !Constraints)
     %
-    % Adds to Constraints the constraints for the body of predicate
-    % PredId, from the module described in ModuleInfo. (PredInfo should
-    % be the unpacked info for PredId from ModuleInfo, and VarInfo is
-    % included to keep track of mode constraint variables for that
-    % module.)
+    % Adds to Constraints the constraints for the body of predicate PredId,
+    % from the module described in ModuleInfo. (PredInfo should be the unpacked
+    % info for PredId from ModuleInfo, and VarInfo is included to keep track
+    % of mode constraint variables for that module.)
     %
 :- pred add_clauses_constraints(module_info::in, pred_id::in, pred_info::in,
     mc_var_info::in, mc_var_info::out,
@@ -139,24 +134,22 @@
     % mode_decls_constraints(ModuleInfo, VarMap, PredId, Decls,
     %   HeadVarsList, Constraints)
     %
-    % Constraints is the disjunction of the constraints for
-    % individual declared modes being satisfied.  ie
+    % Constraints is the disjunction of the constraints for individual declared
+    % modes being satisfied, i.e.
     % disj([ConstraintsForMode1, ..., ConstraintsForModen])
     %
-    % The constraints for a predicate with declared modes is the
-    % disjunction of the constraints for each declared mode. If,
-    % according to the mode declaration, a variable is not initially
-    % free then it is constrained so that it cannot be produced by a
-    % call to this predicate; if a variable is initially free and
-    % becomes not free then it is constrained so as to be produced by
-    % the predicate. Otherwise it is free -> free and is constrained
-    % so as to not be produced.
+    % The constraints for a predicate with declared modes is the disjunction
+    % of the constraints for each declared mode. If, according to the mode
+    % declaration, a variable is not initially free, then it is constrained
+    % so that it cannot be produced by a call to this predicate; if a variable
+    % is initially free and becomes not free then it is constrained so as
+    % to be produced by the predicate. Otherwise it is free -> free and is
+    % constrained so as to not be produced.
     %
-    % NOTE: if Decls is an empty list, this is interpreted as
-    % there being no modes for which the predicate can be executed
-    % and the returned constraints are [disj([])] which cannot be
-    % satisfied. Predicates with mode inference requested should
-    % not be handled by this.
+    % NOTE: if Decls is an empty list, this is interpreted as there being
+    % no modes for which the predicate can be executed and the returned
+    % constraints are [disj([])] which cannot be satisfied. Predicates
+    % with mode inference requested should not be handled by this.
     %
 :- pred mode_decls_constraints(module_info::in, mc_var_map::in, pred_id::in,
     list(list(mer_mode))::in, list(args)::in, list(mc_constraint)::out) is det.
@@ -165,13 +158,12 @@
     %   Decl, Args, !VarInfo, !Constraints)
     %
     % Constrains (in the Constraints) the production of Args at the head
-    % of predicate PredId when called in mode ProcId with declaration
-    % Decl.  If, according to the mode declaration, a variable is not
-    % initially free then it is constrained so that it cannot be
-    % produced by a call to this predicate; if a variable is initially
-    % free and becomes not free then it is constrained so as to be
-    % produced by the predicate.  Otherwise it is free -> free and is
-    % constrained so as to not be produced.
+    % of predicate PredId when called in mode ProcId with declaration Decl.
+    % If, according to the mode declaration, a variable is not initially free,
+    % then it is constrained so that it cannot be produced by a call to this
+    % predicate; if a variable is initially free and becomes not free then
+    % it is constrained so as to be produced by the predicate. Otherwise it is
+    % free -> free and is constrained so as to not be produced.
     %
 :- pred add_mode_decl_constraints(module_info::in, pred_id::in, proc_id::in,
     list(mer_mode)::in, args::in, mc_var_info::in, mc_var_info::out,
@@ -182,10 +174,10 @@
     %
 :- func var_info_init = mc_var_info.
 
-    % rep_var_to_string(ProgVarset, ProgVar `in` PredId `at` GoalPath)
+    % rep_var_to_string(ProgVarset, ProgVar `in` PredId `at` GoalId)
     %
     % returns a string representation of the constraint variable with
-    % the abstract representation given, in format "ProgVarName.GoalPath" -
+    % the abstract representation given, in format "ProgVarName.GoalId" -
     % the ProgVarset should have the ProgVarName in it for ProgVar,
     % and should therefore be taken from predicate PredId.
     %
@@ -285,18 +277,17 @@
     mc_var_info::in, mc_var_info::out) is det.
 
 add_mc_var_for_pred_head(ProgVarset, PredId, HeadVar, !VarInfo) :-
-    prog_var_at_path(ProgVarset, PredId, HeadVar, empty_goal_path, _,
-        !VarInfo).
+    prog_var_at_path(ProgVarset, PredId, HeadVar, goal_id(0), _, !VarInfo).
 
 %-----------------------------------------------------------------------------%
 
-add_mc_vars_for_goal(PredId, ProgVarset, hlds_goal(GoalExpr, GoalInfo),
-        !VarInfo) :-
+add_mc_vars_for_goal(PredId, ProgVarset, Goal, !VarInfo) :-
+    Goal = hlds_goal(GoalExpr, GoalInfo),
     Nonlocals = goal_info_get_nonlocals(GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
 
     set.to_sorted_list(Nonlocals, NlsList),
-    prog_vars_at_path(ProgVarset, PredId, NlsList, GoalPath, _, !VarInfo),
+    prog_vars_at_path(ProgVarset, PredId, NlsList, GoalId, _, !VarInfo),
 
     % Switch on GoalExpr for recursion
     (
@@ -310,30 +301,23 @@
             % XXX handle this
         )
     ;
-        GoalExpr = plain_call(_, _, _, _, _, _)
-    ;
-        GoalExpr = generic_call(_, _, _, _)
-    ;
         GoalExpr = switch(_, _, Cases),
-        Goals = list.map(func(case(_, _, Goal)) = Goal, Cases),
+        Goals = list.map(func(case(_, _, CaseGoal)) = CaseGoal, Cases),
         list.foldl(add_mc_vars_for_goal(PredId, ProgVarset), Goals, !VarInfo)
     ;
-        GoalExpr = unify(_, _, _, _, _)
-    ;
         GoalExpr = disj(Goals),
         list.foldl(add_mc_vars_for_goal(PredId, ProgVarset), Goals, !VarInfo)
     ;
-        GoalExpr = negation(Goal),
-        add_mc_vars_for_goal(PredId, ProgVarset, Goal, !VarInfo)
-    ;   GoalExpr = scope(_, Goal),
-        add_mc_vars_for_goal(PredId, ProgVarset, Goal, !VarInfo)
+        GoalExpr = negation(SubGoal),
+        add_mc_vars_for_goal(PredId, ProgVarset, SubGoal, !VarInfo)
+    ;
+        GoalExpr = scope(_, SubGoal),
+        add_mc_vars_for_goal(PredId, ProgVarset, SubGoal, !VarInfo)
     ;
         GoalExpr = if_then_else(_, Cond, Then, Else),
         Goals = [Cond, Then, Else],
         list.foldl(add_mc_vars_for_goal(PredId, ProgVarset), Goals, !VarInfo)
     ;
-        GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
-    ;
         GoalExpr = shorthand(ShortHand),
         (
             ShortHand = atomic_goal(_, _, _, _, _, _, _),
@@ -345,6 +329,12 @@
             ShortHand = try_goal(_, _, _),
             sorry(this_file, "add_mc_vars_for_goal: try_goal")
         )
+    ;
+        ( GoalExpr = plain_call(_, _, _, _, _, _)
+        ; GoalExpr = generic_call(_, _, _, _)
+        ; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
+        ; GoalExpr = unify(_, _, _, _, _)
+        )
     ).
 
 %-----------------------------------------------------------------------------%
@@ -379,10 +369,9 @@
         % Temporarily form the disjunction implied by the goal path
         % annotations.
         MainGoal = disj(Goals),
-        HeadGoalPath = empty_goal_path,
         Nonlocals = proc_arg_vector_to_set(HeadVars),
         add_goal_expr_constraints(ModuleInfo, ProgVarset, PredId, MainGoal,
-            Context, HeadGoalPath, Nonlocals, !VarInfo, !Constraints)
+            Context, goal_id(0), Nonlocals, !VarInfo, !Constraints)
     ).
 
     % add_goal_constraints(ModuleInfo, ProgVarset, PredId, Goal,
@@ -400,24 +389,24 @@
 
 add_goal_constraints(ModuleInfo, ProgVarset, PredId, Goal,
         !VarInfo, !Constraints) :-
-    Goal = hlds_goal(GoalExpr, GoalInfo), 
+    Goal = hlds_goal(GoalExpr, GoalInfo),
     Nonlocals = goal_info_get_nonlocals(GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
     Context = goal_info_get_context(GoalInfo),
     trace [compile_time(flag("goal_mode_constraints")), io(!IO)] (
         GoalDesc = describe_goal(ModuleInfo, ProgVarset, Goal),
         io.format("constraints for %s:\n", [s(GoalDesc)], !IO)
     ),
     add_goal_expr_constraints(ModuleInfo, ProgVarset, PredId, GoalExpr,
-        Context, GoalPath, Nonlocals, !VarInfo, !Constraints).
+        Context, GoalId, Nonlocals, !VarInfo, !Constraints).
 
     % add_goal_expr_constraints(ModuleInfo, ProgVarset, PredId, GoalExpr,
-    %   Context, GoalPath, Nonlocals, !VarInfo, !Constraints)
+    %   Context, GoalId, Nonlocals, !VarInfo, !Constraints)
     %
     % Adds goal constraints to Constraints to describe the producing and
     % consuming goals for Nonlocals, with respect to GoalExpr and its
     % subgoals.
-    % Context and GoalPath refer to the position of GoalExpr, in the
+    % Context and GoalId refer to the position of GoalExpr, in the
     % source file for the module described in ModuleInfo, and in the
     % body of predicate PredId respectively.
     % VarInfo is used to keep track of the meaning of any constraint
@@ -425,14 +414,14 @@
     % all of the variables in Nonlocals.
     %
 :- pred add_goal_expr_constraints(module_info::in, prog_varset::in,
-    pred_id::in, hlds_goal_expr::in, prog_context::in, goal_path::in,
+    pred_id::in, hlds_goal_expr::in, prog_context::in, goal_id::in,
     nonlocals::in, mc_var_info::in, mc_var_info::out,
     mode_constraints::in, mode_constraints::out) is det.
 
 add_goal_expr_constraints(ModuleInfo, ProgVarset, PredId, GoalExpr,
-        Context, GoalPath, Nonlocals, !VarInfo, !Constraints) :-
+        Context, GoalId, Nonlocals, !VarInfo, !Constraints) :-
     (
-        GoalExpr = conj(ConjType, Goals), 
+        GoalExpr = conj(ConjType, Goals),
         (
             ConjType = plain_conj,
             list.foldl(
@@ -445,8 +434,10 @@
             map.foldl(
                 add_local_var_conj_constraints(!.VarInfo ^ mc_varset, Context),
                 locals_positions(ConjConstraintsInfo), !Constraints),
-            map.foldl2(add_nonlocal_var_conj_constraints(ProgVarset, PredId,
-                Context, GoalPath), nonlocals_positions(ConjConstraintsInfo),
+            map.foldl2(
+                add_nonlocal_var_conj_constraints(ProgVarset, PredId,
+                    Context, GoalId),
+                nonlocals_positions(ConjConstraintsInfo),
                 !VarInfo, !Constraints)
         ;
             ConjType = parallel_conj,
@@ -463,7 +454,7 @@
             pred_info_get_clauses_info(CalleePredInfo, CalleeClausesInfo),
             clauses_info_get_headvar_list(CalleeClausesInfo, CalleeHeadVars),
             add_mode_infer_callee(CalleePredId, !Constraints),
-            add_call_headvar_constraints(ProgVarset, Context, GoalPath,
+            add_call_headvar_constraints(ProgVarset, Context, GoalId,
                 CallerPredId, Args, CalleePredId, CalleeHeadVars,
                 !VarInfo, !Constraints)
         ;
@@ -473,7 +464,7 @@
             list.map(proc_info_get_argmodes, CalleeProcInfos,
                 CalleeArgModeDecls),
             add_call_mode_decls_constraints(ModuleInfo, ProgVarset, Context,
-                CallerPredId, CalleeArgModeDecls, GoalPath, Args, !VarInfo,
+                CallerPredId, CalleeArgModeDecls, GoalId, Args, !VarInfo,
                 !Constraints)
         )
     ;
@@ -501,20 +492,20 @@
         unexpected(this_file, "switch")
     ;
         GoalExpr = unify(LHSvar, RHS, _Mode, _Kind, _UnifyContext),
-        prog_var_at_path(ProgVarset, PredId, LHSvar, GoalPath,
+        prog_var_at_path(ProgVarset, PredId, LHSvar, GoalId,
             LHSvarProducedHere, !VarInfo),
         (
             RHS = rhs_var(RHSvar),
             % Goal: LHSvar = RHSvar
             % At most one of the left and right hand sides of a unification
             % is produced at the unification.
-            prog_var_at_path(ProgVarset, PredId, RHSvar, GoalPath,
+            prog_var_at_path(ProgVarset, PredId, RHSvar, GoalId,
                 RHSvarProducedHere, !VarInfo),
             not_both(!.VarInfo ^ mc_varset, Context,
                 LHSvarProducedHere, RHSvarProducedHere, !Constraints)
         ;
             RHS = rhs_functor(_Functor, _IsExistConstr, Args),
-            prog_vars_at_path(ProgVarset, PredId, Args, GoalPath,
+            prog_vars_at_path(ProgVarset, PredId, Args, GoalId,
                 ArgsProducedHere, !VarInfo),
             (
                 ArgsProducedHere = [OneArgProducedHere, _Two| _],
@@ -543,11 +534,11 @@
         )
     ;
         GoalExpr = disj(Goals),
-        nonlocals_at_path_and_subpaths(ProgVarset, PredId, GoalPath,
-            DisjunctGoalPaths, Nonlocals, NonlocalsHere, NonlocalsAtDisjuncts,
+        nonlocals_at_path_and_subpaths(ProgVarset, PredId, GoalId,
+            DisjunctGoalIds, Nonlocals, NonlocalsHere, NonlocalsAtDisjuncts,
             !VarInfo),
         GoalInfos = list.map(get_hlds_goal_info, Goals),
-        DisjunctGoalPaths = list.map(goal_info_get_goal_path, GoalInfos),
+        DisjunctGoalIds = list.map(goal_info_get_goal_id, GoalInfos),
 
         list.foldl2(add_goal_constraints(ModuleInfo, ProgVarset, PredId),
             Goals, !VarInfo, !Constraints),
@@ -562,14 +553,14 @@
     ;
         GoalExpr = negation(Goal),
         Goal = hlds_goal(_, NegatedGoalInfo),
-        NegatedGoalPath = goal_info_get_goal_path(NegatedGoalInfo),
+        NegatedGoalId = goal_info_get_goal_id(NegatedGoalInfo),
         VarMap = rep_var_map(!.VarInfo),
-        NonlocalsAtPath = set.fold(
-            cons_prog_var_at_path(VarMap, PredId, GoalPath),
+        NonlocalsAtId = set.fold(
+            cons_prog_var_at_path(VarMap, PredId, GoalId),
             Nonlocals, []),
         NonlocalsConstraintVars = set.fold(
-            cons_prog_var_at_path(VarMap, PredId, NegatedGoalPath),
-            Nonlocals, NonlocalsAtPath),
+            cons_prog_var_at_path(VarMap, PredId, NegatedGoalId),
+            Nonlocals, NonlocalsAtId),
 
         add_goal_constraints(ModuleInfo, ProgVarset, PredId, Goal, !VarInfo,
             !Constraints),
@@ -582,19 +573,19 @@
     ;
         GoalExpr = scope(_Reason, Goal),
         Goal = hlds_goal(_, SomeGoalInfo),
-        SomeGoalPath = goal_info_get_goal_path(SomeGoalInfo),
+        SomeGoalId = goal_info_get_goal_id(SomeGoalInfo),
 
         % If a program variable is produced by the sub-goal of the some
         % statement, it is produced at the main goal as well
         % - here we pair up equivalent mode constraint vars and
         % then constrain them to reflect this.
         NonlocalsList = set.to_sorted_list(Nonlocals),
-        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, GoalPath,
+        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, GoalId,
             NonlocalsHere, !VarInfo),
-        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, SomeGoalPath,
+        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, SomeGoalId,
             NonlocalsAtSubGoal, !VarInfo),
         EquivVarss = list.map_corresponding(
-            func(NlAtPath, NlAtSubPath) = [NlAtPath, NlAtSubPath],
+            func(NlAtId, NlAtSubId) = [NlAtId, NlAtSubId],
             NonlocalsHere, NonlocalsAtSubGoal),
         list.foldl(equivalent(!.VarInfo ^ mc_varset, Context), EquivVarss,
             !Constraints),
@@ -606,17 +597,17 @@
         Cond = hlds_goal(_, CondInfo),
         Then = hlds_goal(_, ThenInfo),
         Else = hlds_goal(_, ElseInfo),
-        CondPath = goal_info_get_goal_path(CondInfo),
-        ThenPath = goal_info_get_goal_path(ThenInfo),
-        ElsePath = goal_info_get_goal_path(ElseInfo),
+        CondId = goal_info_get_goal_id(CondInfo),
+        ThenId = goal_info_get_goal_id(ThenInfo),
+        ElseId = goal_info_get_goal_id(ElseInfo),
 
-        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, GoalPath,
+        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, GoalId,
             NonlocalsHere, !VarInfo),
-        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, CondPath,
+        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, CondId,
             NonlocalsAtCond, !VarInfo),
-        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, ThenPath,
+        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, ThenId,
             NonlocalsAtThen, !VarInfo),
-        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, ElsePath,
+        prog_vars_at_path(ProgVarset, PredId, NonlocalsList, ElseId,
             NonlocalsAtElse, !VarInfo),
         NonlocalsList = set.to_sorted_list(Nonlocals),
 
@@ -628,9 +619,9 @@
         list.filter(set.contains(CondNonlocals), ExistVars, NonlocalToCond),
         list.filter(set.contains(ThenNonlocals), NonlocalToCond,
             LocalAndShared),
-        prog_vars_at_path(ProgVarset, PredId, LocalAndShared, CondPath,
+        prog_vars_at_path(ProgVarset, PredId, LocalAndShared, CondId,
             LocalAndSharedAtCond, !VarInfo),
-        prog_vars_at_path(ProgVarset, PredId, LocalAndShared, ThenPath,
+        prog_vars_at_path(ProgVarset, PredId, LocalAndShared, ThenId,
             LocalAndSharedAtThen, !VarInfo),
 
         add_goal_constraints(ModuleInfo, ProgVarset, PredId, Cond, !VarInfo,
@@ -671,7 +662,7 @@
             % This pred should strip the disj(conj()) for the single
             % declaration.
             add_call_mode_decls_constraints(ModuleInfo, ProgVarset, Context,
-                PredId, [Decl], GoalPath, CallArgs, !VarInfo, !Constraints)
+                PredId, [Decl], GoalId, CallArgs, !VarInfo, !Constraints)
         ;
             unexpected(this_file, "no mode declaration for foreign proc")
         )
@@ -705,7 +696,7 @@
     % that it is produced by a call to the predicate).
     HeadVarsMCVars =
         list.map(list.map(
-                lookup_prog_var_at_path(VarMap, PredId, empty_goal_path)),
+                lookup_prog_var_at_path(VarMap, PredId, goal_id(0))),
             HeadVarsList),
 
     % Make the constraints for each declaration.
@@ -725,7 +716,7 @@
     proc_info_get_varset(ProcInfo, ProgVarset),
     proc_info_get_context(ProcInfo, Context),
 
-    prog_vars_at_path(ProgVarset, PredId, Args, empty_goal_path, ArgsAtHead, 
+    prog_vars_at_path(ProgVarset, PredId, Args, goal_id(0), ArgsAtHead,
         !VarInfo),
 
     DeclConstraints = mode_decl_constraints(ModuleInfo, ArgsAtHead, Decl),
@@ -735,11 +726,11 @@
         DeclConstraints, !Constraints).
 
     % add_call_mode_decls_constraints(ModuleInfo, ProgVarset, Context,
-    %   CallingPred, Decls, GoalPath, CallArgs, !VarInfo, !Constraints)
+    %   CallingPred, Decls, GoalId, CallArgs, !VarInfo, !Constraints)
     %
     % Adds the following to the mode_constraints:
     % disj([ConstraintsForMode1, ..., ConstraintsForModeN])
-    % with context Context, and goal path GoalPath (of the position of
+    % with context Context, and goal path GoalId (of the position of
     % the call). ConstraintsForModei are the constraints for when the
     % callee is called in the ith mode of Decls.
     % Assumes CallArgs to be the program variables from CallingPred
@@ -763,12 +754,12 @@
     %
 :- pred add_call_mode_decls_constraints(module_info::in,
     prog_varset::in, prog_context::in, pred_id::in, list(list(mer_mode))::in,
-    goal_path::in, args::in, mc_var_info::in, mc_var_info::out,
+    goal_id::in, args::in, mc_var_info::in, mc_var_info::out,
     mode_constraints::in, mode_constraints::out) is det.
 
 add_call_mode_decls_constraints(ModuleInfo, ProgVarset, CallContext,
-        CallingPred, Decls, GoalPath, CallArgs, !VarInfo, !Constraints) :-
-    prog_vars_at_path(ProgVarset, CallingPred, CallArgs, GoalPath,
+        CallingPred, Decls, GoalId, CallArgs, !VarInfo, !Constraints) :-
+    prog_vars_at_path(ProgVarset, CallingPred, CallArgs, GoalId,
         CallArgsHere, !VarInfo),
     ModeSpecificConstraints = list.condense(list.map(
         mode_decl_constraints(ModuleInfo, CallArgsHere),
@@ -781,7 +772,7 @@
             mc_disj(ModeSpecificConstraints), !Constraints)
     ).
 
-    % add_call_headvar_constraints(ProgVarset, Context, GoalPath, Caller,
+    % add_call_headvar_constraints(ProgVarset, Context, GoalId, Caller,
     %   CallArgs, Callee, HeadVars, CallArgs, !VarInfo, !Constraints):
     %
     % Forms constraints that, when satisfied, mean any call arg will be
@@ -795,15 +786,15 @@
     % throughout the whole body of the calling predicate.
     %
 :- pred add_call_headvar_constraints(prog_varset::in, prog_context::in,
-    goal_path::in, pred_id::in, args::in, pred_id::in, args::in,
+    goal_id::in, pred_id::in, args::in, pred_id::in, args::in,
     mc_var_info::in, mc_var_info::out, mode_constraints::in,
     mode_constraints::out) is det.
 
-add_call_headvar_constraints(ProgVarset, Context, GoalPath, CallerPredId,
+add_call_headvar_constraints(ProgVarset, Context, GoalId, CallerPredId,
         CallArgs, CalleePredId, CalleeHeadVars, !VarInfo, !Constraints) :-
-    prog_vars_at_path(ProgVarset, CalleePredId, CalleeHeadVars, empty_goal_path,
+    prog_vars_at_path(ProgVarset, CalleePredId, CalleeHeadVars, goal_id(0),
         HeadVarsAtHead, !VarInfo),
-    prog_vars_at_path(ProgVarset, CallerPredId, CallArgs, GoalPath,
+    prog_vars_at_path(ProgVarset, CallerPredId, CallArgs, GoalId,
         CallArgsHere, !VarInfo),
 
     % If the head var is produced by the body of the callee, then the
@@ -873,7 +864,7 @@
 add_goal_nonlocals_to_conjunct_production_maps(VarMap, PredId, Nonlocals,
         hlds_goal(_SubGoalExpr, SubGoalInfo), !ConjConstraintsInfo) :-
     SubGoalNonlocals = goal_info_get_nonlocals(SubGoalInfo),
-    SubGoalPath = goal_info_get_goal_path(SubGoalInfo),
+    SubGoalId = goal_info_get_goal_id(SubGoalInfo),
 
     % These are variables nonlocal to the conjunction that
     % appear in this particular conjunct.
@@ -888,39 +879,37 @@
         !:NonlocalsMap = !.ConjConstraintsInfo ^ nonlocals_positions,
 
         set.fold(add_variable_to_conjunct_production_map(VarMap, PredId,
-            SubGoalPath), Local, !LocalsMap),
+            SubGoalId), Local, !LocalsMap),
         set.fold(add_variable_to_conjunct_production_map(VarMap, PredId,
-            SubGoalPath), Nonlocal, !NonlocalsMap),
+            SubGoalId), Nonlocal, !NonlocalsMap),
 
-        !:ConjConstraintsInfo = !.ConjConstraintsInfo ^ locals_positions :=
-            !.LocalsMap,
-        !:ConjConstraintsInfo = !.ConjConstraintsInfo ^ nonlocals_positions :=
-            !.NonlocalsMap
+        !ConjConstraintsInfo ^ locals_positions := !.LocalsMap,
+        !ConjConstraintsInfo ^ nonlocals_positions := !.NonlocalsMap
     ).
 
-    % add_variable_to_conjunct_production_map(VarMap, PredId, GoalPath
+    % add_variable_to_conjunct_production_map(VarMap, PredId, GoalId
     %   ProgVar, !ConjunctProductionMap)
     %
     % A subsection of add_goal_nonlocals_to_conjunct_production_maps,
     % puts into the ConjunctProductionMap the key ProgVar with the
     % constraint variable found in VarMap, that represents the
-    % proposition that ProgVar is bound at GoalPath in predicate PredId.
+    % proposition that ProgVar is bound at GoalId in predicate PredId.
     %
 :- pred add_variable_to_conjunct_production_map(
-    mc_var_map::in, pred_id::in, goal_path::in, prog_var::in,
+    mc_var_map::in, pred_id::in, goal_id::in, prog_var::in,
     conjunct_production_map::in, conjunct_production_map::out) is det.
 
-add_variable_to_conjunct_production_map(VarMap, PredId, GoalPath, ProgVar,
+add_variable_to_conjunct_production_map(VarMap, PredId, GoalId, ProgVar,
         !ConjunctProductionMap) :-
-    MCVar = lookup_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar),
+    MCVar = lookup_prog_var_at_path(VarMap, PredId, GoalId, ProgVar),
     svmulti_map.set(ProgVar, MCVar, !ConjunctProductionMap).
 
-    % add_nonlocal_var_conj_constraints(ProgVarset, PredId, Context, GoalPath,
+    % add_nonlocal_var_conj_constraints(ProgVarset, PredId, Context, GoalId,
     %     ProgVar, ProgVarAtConjuncts, !VarInfo, !Constraints)
     %
     % Adds conjunction constraints concerning ProgVar, a variable
     % in predicate PredID, to Constraints. The conjunction should
-    % exist at the position indicated by GoalPath in the predicate,
+    % exist at the position indicated by GoalId in the predicate,
     % and have context Context in the source file. ProgVarset should
     % contain a string name for ProgVar.
     % ProgVar should be a variable in the nonlocal set of the conjunction,
@@ -931,19 +920,18 @@
     % conjunct in which it appears.
     %
 :- pred add_nonlocal_var_conj_constraints(prog_varset::in, pred_id::in,
-    prog_context::in, goal_path::in, prog_var::in, list(mc_var)::in,
+    prog_context::in, goal_id::in, prog_var::in, list(mc_var)::in,
     mc_var_info::in, mc_var_info::out, mode_constraints::in,
     mode_constraints::out) is det.
 
-add_nonlocal_var_conj_constraints(ProgVarset, PredId, Context, GoalPath,
-    ProgVar, ProgVarAtConjuncts, !VarInfo, !Constraints) :-
-
+add_nonlocal_var_conj_constraints(ProgVarset, PredId, Context, GoalId,
+        ProgVar, ProgVarAtConjuncts, !VarInfo, !Constraints) :-
     equiv_disj(!.VarInfo ^ mc_varset, Context,
-        ProgVarAtGoalPath, ProgVarAtConjuncts, !Constraints),
+        ProgVarAtGoalId, ProgVarAtConjuncts, !Constraints),
     at_most_one(!.VarInfo ^ mc_varset, Context,
         ProgVarAtConjuncts, !Constraints),
 
-    prog_var_at_path(ProgVarset, PredId, ProgVar, GoalPath, ProgVarAtGoalPath,
+    prog_var_at_path(ProgVarset, PredId, ProgVar, GoalId, ProgVarAtGoalId,
         !VarInfo).
 
     % add_local_var_conj_constraints(MCVarSet, Context, ProgVar, MCVars,
@@ -976,75 +964,75 @@
 
 %-----------------------------------------------------------------------------%
 
-    % prog_var_at_path(ProgVarset, PredId, ProgVar, GoalPath, MCVar, !VarInfo)
+    % prog_var_at_path(ProgVarset, PredId, ProgVar, GoalId, MCVar, !VarInfo)
     %
     % MCVar is the constraint variable corresponding to the proposition
-    % that ProgVar is created at GoalPath in predicate PredId,
+    % that ProgVar is created at GoalId in predicate PredId,
     % it is created if necessary and stored in VarInfo (in which
     % case we need a string name of ProgVar in ProgVarset).
     %
 :- pred prog_var_at_path(prog_varset::in, pred_id::in, prog_var::in,
-    goal_path::in, mc_var::out, mc_var_info::in, mc_var_info::out) is det.
+    goal_id::in, mc_var::out, mc_var_info::in, mc_var_info::out) is det.
 
-prog_var_at_path(ProgVarset, PredId, ProgVar, GoalPath, MCVar, !VarInfo) :-
+prog_var_at_path(ProgVarset, PredId, ProgVar, GoalId, MCVar, !VarInfo) :-
     !.VarInfo = mc_var_info(MCVarset0, VarMap0),
-    ensure_prog_var_at_path(ProgVarset, PredId, GoalPath, ProgVar,
+    ensure_prog_var_at_path(ProgVarset, PredId, GoalId, ProgVar,
         MCVarset0, MCVarset, VarMap0, VarMap),
-    MCVar = lookup_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar),
+    MCVar = lookup_prog_var_at_path(VarMap, PredId, GoalId, ProgVar),
     !:VarInfo = mc_var_info(MCVarset, VarMap).
 
-    % prog_var_at_paths(ProgVarset, PredId, ProgVar, GoalPaths, MCVars,
+    % prog_var_at_paths(ProgVarset, PredId, ProgVar, GoalIds, MCVars,
     %   !VarInfo)
     %
     % MCVars are the constraint variables corresponding to propositions
-    % that ProgVar is created at GoalPath in predicate PredId, for each
-    % GoalPath in GoalPaths. The constraint variables are created if
-    % necessary and stored in VarInfo (in which case we need a string
-    % name of ProgVar in ProgVarset).
+    % that ProgVar is created at GoalId in predicate PredId, for each
+    % GoalId in GoalIds. The constraint variables are created if necessary
+    % and stored in VarInfo (in which case we need a string name of ProgVar
+    % in ProgVarset).
     %
 :- pred prog_var_at_paths(prog_varset::in, pred_id::in, prog_var::in,
-    list(goal_path)::in, list(mc_var)::out, mc_var_info::in,
+    list(goal_id)::in, list(mc_var)::out, mc_var_info::in,
     mc_var_info::out) is det.
 
-prog_var_at_paths(ProgVarset, PredID, ProgVar, GoalPaths, MCVars, !VarInfo) :-
+prog_var_at_paths(ProgVarset, PredID, ProgVar, GoalIds, MCVars, !VarInfo) :-
     list.map_foldl(prog_var_at_path(ProgVarset, PredID, ProgVar),
-        GoalPaths, MCVars, !VarInfo).
+        GoalIds, MCVars, !VarInfo).
 
-    % prog_vars_at_path(ProgVarset, PredId, ProgVars, GoalPath, MCVars,
+    % prog_vars_at_path(ProgVarset, PredId, ProgVars, GoalId, MCVars,
     %   !VarInfo)
     %
     % MCVars are the constraint variables corresponding to propositions
-    % that ProgVar is created at GoalPath in predicate PredId, for each
+    % that ProgVar is created at GoalId in predicate PredId, for each
     % ProgVar in ProgVars. They are created if necessary and stored in
     % VarInfo (in which case we will need a string name for ProgVar from
     % ProgVarset).
     %
 :- pred prog_vars_at_path(prog_varset::in, pred_id::in, list(prog_var)::in,
-    goal_path::in, list(mc_var)::out, mc_var_info::in, mc_var_info::out)
+    goal_id::in, list(mc_var)::out, mc_var_info::in, mc_var_info::out)
     is det.
 
-prog_vars_at_path(ProgVarset, PredId, ProgVars, GoalPath, MCVars, !VarInfo) :-
+prog_vars_at_path(ProgVarset, PredId, ProgVars, GoalId, MCVars, !VarInfo) :-
     list.map_foldl(
         (pred(ProgVar::in, MCVar::out, !.VarInfo::in, !:VarInfo::out) is det :-
-            prog_var_at_path(ProgVarset, PredId, ProgVar, GoalPath, MCVar,
+            prog_var_at_path(ProgVarset, PredId, ProgVar, GoalId, MCVar,
                 !VarInfo)
         ), ProgVars, MCVars, !VarInfo).
 
-    % ensure_prog_var_at_path(ProgVarset, PredId, GoalPath, ProgVar,
+    % ensure_prog_var_at_path(ProgVarset, PredId, GoalId, ProgVar,
     %   !Varset, !VarMap)
     %
     % Adds, if necessary, to Varset and VarMap the constraint variable
     % and its abstract representation that represents the proposition
-    % that ProgVar is produced at GoalPath in PredId (in some mode
-    % of execution). ProgVarset should contain a string name for ProgVar.
+    % that ProgVar is produced at GoalId in PredId (in some mode of execution).
+    % ProgVarset should contain a string name for ProgVar.
     %
-:- pred ensure_prog_var_at_path(prog_varset::in, pred_id::in, goal_path::in,
+:- pred ensure_prog_var_at_path(prog_varset::in, pred_id::in, goal_id::in,
     prog_var::in, mc_varset::in, mc_varset::out,
     mc_var_map::in, mc_var_map::out) is det.
 
-ensure_prog_var_at_path(ProgVarset, PredId, GoalPath, ProgVar,
+ensure_prog_var_at_path(ProgVarset, PredId, GoalId, ProgVar,
         !Varset, !VarMap) :-
-    RepVar = (ProgVar `in` PredId) `at` GoalPath,
+    RepVar = (ProgVar `in` PredId) `at` GoalId,
     ( bimap.search(!.VarMap, RepVar, _) ->
         true
     ;
@@ -1053,86 +1041,80 @@
         svbimap.det_insert(RepVar, NewMCVar, !VarMap)
     ).
 
-    % lookup_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar)
-    %   = ConstraintVar:
+    % lookup_prog_var_at_path(VarMap, PredId, GoalId, ProgVar) = ConstraintVar:
     %
     % Consults the VarMap to get the constraint variable ConstraintVar
-    % that represents the proposition that ProgVar is produced at
-    % GoalPath in predicate PredId. The lookup function will report an
-    % error if the key (ProgVar `in` PredId) `at` GoalPath does not
-    % exist in the map.
+    % that represents the proposition that ProgVar is produced at GoalId
+    % in predicate PredId. The lookup function will report an error
+    % if the key (ProgVar `in` PredId) `at` GoalId does not exist in the map.
     %
-:- func lookup_prog_var_at_path(mc_var_map, pred_id, goal_path, prog_var)
+:- func lookup_prog_var_at_path(mc_var_map, pred_id, goal_id, prog_var)
     = mc_var.
 
-lookup_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar) =
-    bimap.lookup(VarMap, ((ProgVar `in` PredId) `at` GoalPath)).
+lookup_prog_var_at_path(VarMap, PredId, GoalId, ProgVar) =
+    bimap.lookup(VarMap, ((ProgVar `in` PredId) `at` GoalId)).
 
     % Retrieves the mode constraint var as per prog_var_at_path, but
     % attaches it to the list supplied rather than return it directly.
     %
-:- func cons_prog_var_at_path(mc_var_map, pred_id, goal_path, prog_var,
+:- func cons_prog_var_at_path(mc_var_map, pred_id, goal_id, prog_var,
     list(mc_var)) = list(mc_var).
 
-cons_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar, MCVars) =
-    [lookup_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar) | MCVars].
+cons_prog_var_at_path(VarMap, PredId, GoalId, ProgVar, MCVars) =
+    [lookup_prog_var_at_path(VarMap, PredId, GoalId, ProgVar) | MCVars].
 
-    % prog_var_at_paths(VarMap, GoalPaths, ProgVar) = ConstraintVars
+    % prog_var_at_paths(VarMap, GoalIds, ProgVar) = ConstraintVars
     % consults the map to form a list of the constraint variable
     % propositions that ProgVar is produced at each of the paths in
-    % GoalPaths respectively.  The lookup function will report an
-    % error if the key (ProgVar `in` PredId) `at` GoalPath does not
-    % exist in the map for any of the 'GoalPath's in GoalPaths.
+    % GoalIds respectively.  The lookup function will report an
+    % error if the key (ProgVar `in` PredId) `at` GoalId does not
+    % exist in the map for any of the goal ids in GoalIds.
     %
-:- func prog_var_at_paths(mc_var_map, pred_id, list(goal_path), prog_var) =
+:- func prog_var_at_paths(mc_var_map, pred_id, list(goal_id), prog_var) =
     list(mc_var).
 
-prog_var_at_paths(VarMap, PredId, GoalPaths, ProgVar) =
+prog_var_at_paths(VarMap, PredId, GoalIds, ProgVar) =
     list.map(
-        func(GoalPath) =
-            lookup_prog_var_at_path(VarMap, PredId, GoalPath, ProgVar),
-        GoalPaths).
-
-    % nonlocals_at_path_and_subpaths(ProgVarset, GoalPath, SubPaths,
-    %   Nonlocals, NonlocalsAtPath, NonlocalsAtSubPaths, !VarInfo)
-    %
-    % consults the VarInfo to find constraint variables associated
-    % with each of the program variables in the Nonlocals set for a
-    % GoalPath eg a conjunction and its SubPaths (ie the individual
-    % conjuncts), although it doesn't check that the SubPaths are
-    % indeed subpaths of GoalPath.  Nonlocals are converted to a
-    % sorted list so the Nth entry of NonlocalsAtPath and the Nth
-    % entry of NonlocalsAtSubPaths are respectively the constraint
-    % variable at the goal and a list of the constraint variables
-    % for the subgoals, for the same program variable.
+        func(GoalId) =
+            lookup_prog_var_at_path(VarMap, PredId, GoalId, ProgVar),
+        GoalIds).
+
+    % nonlocals_at_path_and_subpaths(ProgVarset, GoalId, SubIds,
+    %   Nonlocals, NonlocalsAtId, NonlocalsAtSubIds, !VarInfo)
+    %
+    % consults the VarInfo to find constraint variables associated with
+    % each of the program variables in the Nonlocals set for a GoalId,
+    % e.g. a conjunction and its SubIds (i.e. the individual conjuncts),
+    % although it doesn't check that the SubIds are indeed subpaths of
+    % GoalId. Nonlocals are converted to a sorted list so the Nth entry
+    % of NonlocalsAtId and the Nth entry of NonlocalsAtSubIds are
+    % respectively the constraint variable at the goal and a list of the
+    % %constraint variables for the subgoals, for the same program variable.
     %
 :- pred nonlocals_at_path_and_subpaths(prog_varset::in, pred_id::in,
-    goal_path::in, list(goal_path)::in, nonlocals::in, list(mc_var)::out,
+    goal_id::in, list(goal_id)::in, nonlocals::in, list(mc_var)::out,
     list(list(mc_var))::out, mc_var_info::in, mc_var_info::out) is det.
 
-nonlocals_at_path_and_subpaths(ProgVarset, PredId, GoalPath, SubPaths,
-        Nonlocals, NonlocalsAtPath, NonlocalsAtSubPaths, !VarInfo) :-
-    prog_vars_at_path(ProgVarset, PredId, NonlocalsList, GoalPath,
-        NonlocalsAtPath, !VarInfo),
+nonlocals_at_path_and_subpaths(ProgVarset, PredId, GoalId, SubIds,
+        Nonlocals, NonlocalsAtId, NonlocalsAtSubIds, !VarInfo) :-
+    prog_vars_at_path(ProgVarset, PredId, NonlocalsList, GoalId,
+        NonlocalsAtId, !VarInfo),
     list.map_foldl(
-        (pred(Nl::in, NlAtSubPaths::out, !.VInfo::in, !:VInfo::out) is det :-
-            prog_var_at_paths(ProgVarset, PredId, Nl, SubPaths,
-                NlAtSubPaths, !VInfo)
-        ), NonlocalsList, NonlocalsAtSubPaths, !VarInfo),
+        (pred(Nl::in, NlAtSubIds::out, !.VInfo::in, !:VInfo::out) is det :-
+            prog_var_at_paths(ProgVarset, PredId, Nl, SubIds, NlAtSubIds,
+                !VInfo)
+        ), NonlocalsList, NonlocalsAtSubIds, !VarInfo),
     NonlocalsList = set.to_sorted_list(Nonlocals).
 
 %----------------------------------------------------------------------------%
 
 var_info_init = mc_var_info(varset.init, bimap.init).
 
-rep_var_to_string(ProgVarset, (ProgVar `in` _) `at` GoalPath) = RepString :-
-    GoalPathString = goal_path_to_string(GoalPath),
+rep_var_to_string(ProgVarset, (ProgVar `in` _) `at` GoalId) = RepString :-
+    GoalId = goal_id(GoalIdNum),
+    GoalIdString = string.int_to_string(GoalIdNum),
     varset.lookup_name(ProgVarset, ProgVar, ProgVarString),
-    ( GoalPathString = "" ->
-        RepString = ProgVarString
-    ;
-        RepString = ProgVarString ++ "." ++ GoalPathString
-    ).
+    RepString = ProgVarString ++ "." ++ GoalIdString.
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.197
diff -u -r1.197 call_gen.m
--- compiler/call_gen.m	15 Dec 2010 06:29:29 -0000	1.197
+++ compiler/call_gen.m	15 Dec 2010 06:33:13 -0000
@@ -65,6 +65,7 @@
 
 :- import_module backend_libs.builtin_ops.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_llds.
 :- import_module hlds.hlds_module.
 :- import_module hlds.instmap.
@@ -106,11 +107,20 @@
     get_next_label(ReturnLabel, !CI),
     call_gen.call_comment(!.CI, PredId, CodeModel, CallComment),
     Context = goal_info_get_context(GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    get_containing_goal_map(!.CI, MaybeContainingGoalMap),
+    (
+        MaybeContainingGoalMap = yes(ContainingGoalMap),
+        GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
+        MaybeGoalPath = yes(GoalPath)
+    ;
+        MaybeContainingGoalMap = no,
+        MaybeGoalPath = no
+    ),
     CallCode = from_list([
         llds_instr(livevals(LiveVals), ""),
         llds_instr(llcall(Address, code_label(ReturnLabel), ReturnLiveLvalues,
-            Context, GoalPath, CallModel), CallComment),
+            Context, MaybeGoalPath, CallModel), CallComment),
         llds_instr(label(ReturnLabel), "continuation label")
     ]),
 
@@ -132,7 +142,7 @@
         goal_info_has_feature(GoalInfo, feature_debug_tail_rec_call),
         MaybeTraceInfo = yes(TraceInfo)
     ->
-        generate_tailrec_event_code(TraceInfo, ArgsInfos, GoalPath, Context,
+        generate_tailrec_event_code(TraceInfo, ArgsInfos, GoalId, Context,
             TraceTailRecResetAndEventCode, TailRecLabel, !CI),
         JumpCode = from_list([
             llds_instr(livevals(LiveVals), ""),
@@ -227,7 +237,7 @@
     % Make the call.
     get_next_label(ReturnLabel, !CI),
     Context = goal_info_get_context(GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
 
     % Figure out what variables will be live at the return point, and where,
     % for use in the accurate garbage collector, and in the debugger.
@@ -239,10 +249,19 @@
     handle_return(OutArgsInfos, GoalInfo, NonLiveOutputs,
         ReturnInstMap, ReturnLiveLvalues, !CI),
 
+    get_containing_goal_map(!.CI, MaybeContainingGoalMap),
+    (
+        MaybeContainingGoalMap = yes(ContainingGoalMap),
+        GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
+        MaybeGoalPath = yes(GoalPath)
+    ;
+        MaybeContainingGoalMap = no,
+        MaybeGoalPath = no
+    ),
     CallCode = from_list([
         llds_instr(livevals(LiveVals), ""),
         llds_instr(llcall(CodeAddr, code_label(ReturnLabel), ReturnLiveLvalues,
-            Context, GoalPath, CallModel), "Setup and call"),
+            Context, MaybeGoalPath, CallModel), "Setup and call"),
         llds_instr(label(ReturnLabel), "Continuation label")
     ]),
 
Index: compiler/check_hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/check_hlds.m,v
retrieving revision 1.23
diff -u -r1.23 check_hlds.m
--- compiler/check_hlds.m	25 Sep 2009 05:13:01 -0000	1.23
+++ compiler/check_hlds.m	20 Mar 2010 15:16:27 -0000
@@ -93,8 +93,6 @@
 % Output XML representation useful for documentation of module
 :- include_module xml_documentation.
 
-:- include_module goal_path.
-
 %-----------------------------------------------------------------------------%
 
 :- implementation.
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.379
diff -u -r1.379 code_info.m
--- compiler/code_info.m	15 Dec 2010 06:29:30 -0000	1.379
+++ compiler/code_info.m	15 Dec 2010 06:33:13 -0000
@@ -32,6 +32,7 @@
 
 :- import_module check_hlds.type_util.
 :- import_module hlds.code_model.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_llds.
@@ -113,7 +114,7 @@
 :- pred code_info_init(bool::in, globals::in, pred_id::in, proc_id::in,
     pred_info::in, proc_info::in, abs_follow_vars::in, module_info::in,
     static_cell_info::in, resume_point_info::out, trace_slot_info::out,
-    code_info::out) is det.
+    maybe(containing_goal_map)::in, code_info::out) is det.
 
     % Get the globals table.
     %
@@ -234,6 +235,12 @@
 
 :- pred get_lcmc_null(code_info::in, bool::out) is det.
 
+:- pred get_containing_goal_map(code_info::in, maybe(containing_goal_map)::out)
+    is det.
+
+:- pred get_containing_goal_map_det(code_info::in, containing_goal_map::out)
+    is det.
+
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -371,8 +378,9 @@
                 cis_auto_comments       :: bool,
 
                 % The setting of --optimize-constructor-last-call-null.
-                cis_lcmc_null           :: bool
+                cis_lcmc_null           :: bool,
 
+                cis_containing_goal_map :: maybe(containing_goal_map)
             ).
 
 :- type code_info_loc_dep
@@ -465,7 +473,7 @@
 
 code_info_init(SaveSuccip, Globals, PredId, ProcId, PredInfo, ProcInfo,
         FollowVars, ModuleInfo, StaticCellInfo, ResumePoint, TraceSlotInfo,
-        CodeInfo) :-
+        MaybeContainingGoalMap, CodeInfo) :-
     proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InstMap),
     proc_info_get_liveness_info(ProcInfo, Liveness),
     CodeModel = proc_info_interface_code_model(ProcInfo),
@@ -551,7 +559,8 @@
             EmitRegionOps,
             OptRegionOps,
             AutoComments,
-            LCMCNull
+            LCMCNull,
+            MaybeContainingGoalMap
         ),
         code_info_loc_dep(
             Liveness,
@@ -682,6 +691,7 @@
 get_opt_region_ops(CI, CI ^ code_info_static ^ cis_opt_region_ops).
 get_auto_comments(CI, CI ^ code_info_static ^ cis_auto_comments).
 get_lcmc_null(CI, CI ^ code_info_static ^ cis_lcmc_null).
+get_containing_goal_map(CI, CI ^ code_info_static ^ cis_containing_goal_map).
 get_forward_live_vars(CI, CI ^ code_info_loc_dep ^ cild_forward_live_vars).
 get_instmap(CI, CI ^ code_info_loc_dep ^ cild_instmap).
 get_zombies(CI, CI ^ code_info_loc_dep ^ cild_zombies).
@@ -740,6 +750,15 @@
 set_used_env_vars(UEV, CI,
     CI ^ code_info_persistent ^ cip_used_env_vars := UEV).
 
+get_containing_goal_map_det(CI, ContainingGoalMap) :-
+    get_containing_goal_map(CI, MaybeContainingGoalMap),
+    (
+        MaybeContainingGoalMap = yes(ContainingGoalMap)
+    ;
+        MaybeContainingGoalMap = no,
+        unexpected(this_file, "get_containing_goal_map_det: no map")
+    ).
+
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
@@ -863,8 +882,8 @@
     %
 :- pred succip_is_used(code_info::in, code_info::out) is det.
 
-:- pred add_trace_layout_for_label(label::in, term.context::in,
-    trace_port::in, bool::in, goal_path::in, maybe(user_event_info)::in,
+:- pred add_trace_layout_for_label(label::in, term.context::in, trace_port::in,
+    bool::in, forward_goal_path::in, maybe(user_event_info)::in,
     layout_label_info::in, code_info::in, code_info::out) is det.
 
 :- pred get_cur_proc_label(code_info::in, proc_label::out) is det.
@@ -1070,10 +1089,10 @@
 succip_is_used(!CI) :-
     set_succip_used(yes, !CI).
 
-add_trace_layout_for_label(Label, Context, Port, IsHidden, Path,
+add_trace_layout_for_label(Label, Context, Port, IsHidden, GoalPath,
         MaybeSolverEventInfo, Layout, !CI) :-
     get_layout_info(!.CI, Internals0),
-    Exec = yes(trace_port_layout_info(Context, Port, IsHidden, Path,
+    Exec = yes(trace_port_layout_info(Context, Port, IsHidden, GoalPath,
         MaybeSolverEventInfo, Layout)),
     (
         Label = internal_label(LabelNum, _)
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.98
diff -u -r1.98 continuation_info.m
--- compiler/continuation_info.m	15 Dec 2010 06:29:32 -0000	1.98
+++ compiler/continuation_info.m	20 Dec 2010 07:29:51 -0000
@@ -265,14 +265,14 @@
                 port_context    :: prog_context,
                 port_type       :: trace_port,
                 port_is_hidden  :: bool,
-                port_path       :: goal_path,
+                port_path       :: forward_goal_path,
                 port_user       :: maybe(user_event_info),
                 port_label      :: layout_label_info
             ).
 
 :- type return_layout_info
     --->    return_layout_info(
-                assoc_list(code_addr, pair(prog_context, goal_path)),
+                assoc_list(code_addr, pair(prog_context, forward_goal_path)),
                 layout_label_info
             ).
 
@@ -451,9 +451,8 @@
                 call_live_on_return     :: list(liveinfo),
                 call_context            :: term.context,
 
-                % The position of the call in the body; meaningful only if
-                % tracing is enabled.
-                call_goal_path          :: goal_path
+                % The position of the call in the body if tracing is enabled.
+                call_goal_path          :: maybe(forward_goal_path)
             ).
 
     % Process the list of instructions for this proc, adding
@@ -466,20 +465,21 @@
     % Get all the continuation info from the call instructions.
     global_data_get_proc_layout(!.GlobalData, PredProcId, ProcLayoutInfo0),
     Internals0 = ProcLayoutInfo0 ^ pli_internal_map,
-    GetCallInfo = (pred(Instr::in, Call::out) is semidet :-
-        Instr = llds_instr(llcall(Target, code_label(ReturnLabel), LiveInfo,
-            Context, GoalPath, _), _Comment),
-        Call = call_info(ReturnLabel, Target, LiveInfo, Context, GoalPath)
-    ),
-    list.filter_map(GetCallInfo, Instructions, Calls),
-
+    list.filter_map(get_call_info, Instructions, Calls),
     % Process the continuation label info.
     list.foldl(process_continuation(WantReturnInfo), Calls,
         Internals0, Internals),
-
     ProcLayoutInfo = ProcLayoutInfo0 ^ pli_internal_map := Internals,
     global_data_update_proc_layout(PredProcId, ProcLayoutInfo, !GlobalData).
 
+:- pred get_call_info(instruction::in, call_info::out) is semidet.
+
+get_call_info(Instr, Call) :-
+    Instr = llds_instr(Uinstr, _Comment),
+    Uinstr = llcall(Target, Return, LiveInfo, Context, GoalPath, _),
+    Return = code_label(ReturnLabel),
+    Call = call_info(ReturnLabel, Target, LiveInfo, Context, GoalPath).
+
 %-----------------------------------------------------------------------------%
 
     % Collect the liveness information from a single return label
@@ -509,27 +509,35 @@
     ),
     (
         WantReturnInfo = yes,
-        convert_return_data(LiveInfoList, VarInfoSet, TypeInfoMap),
         (
-            Return0 = no,
-            Layout = layout_label_info(VarInfoSet, TypeInfoMap),
-            ReturnInfo = return_layout_info(
-                [Target - (Context - MaybeGoalPath)], Layout),
-            Return = yes(ReturnInfo)
+            MaybeGoalPath = no,
+            %  XXX We used to handle these situations by using an empty path.
+            %  XXX Should we throw an exception?
+            Return = Return0
         ;
-            % If a var is known to be dead on return from one call, it cannot
-            % be accessed on returning from the other calls that reach the same
-            % return address either.
-            Return0 = yes(ReturnInfo0),
-            ReturnInfo0 = return_layout_info(TargetsContexts0, Layout0),
-            Layout0 = layout_label_info(LV0, TV0),
-            set.intersect(LV0, VarInfoSet, LV),
-            map.intersect(set.intersect, TV0, TypeInfoMap, TV),
-            Layout = layout_label_info(LV, TV),
-            TargetContexts = [Target - (Context - MaybeGoalPath)
-                | TargetsContexts0],
-            ReturnInfo = return_layout_info(TargetContexts, Layout),
-            Return = yes(ReturnInfo)
+            MaybeGoalPath = yes(GoalPath),
+            convert_return_data(LiveInfoList, VarInfoSet, TypeInfoMap),
+            (
+                Return0 = no,
+                Layout = layout_label_info(VarInfoSet, TypeInfoMap),
+                ReturnInfo = return_layout_info(
+                    [Target - (Context - GoalPath)], Layout),
+                Return = yes(ReturnInfo)
+            ;
+                % If a var is known to be dead on return from one call,
+                % it cannot be accessed on returning from the other calls
+                % that reach the same return address either.
+                Return0 = yes(ReturnInfo0),
+                ReturnInfo0 = return_layout_info(TargetsContexts0, Layout0),
+                Layout0 = layout_label_info(LV0, TV0),
+                set.intersect(LV0, VarInfoSet, LV),
+                map.intersect(set.intersect, TV0, TypeInfoMap, TV),
+                Layout = layout_label_info(LV, TV),
+                TargetContexts = [Target - (Context - GoalPath)
+                    | TargetsContexts0],
+                ReturnInfo = return_layout_info(TargetContexts, Layout),
+                Return = yes(ReturnInfo)
+            )
         )
     ;
         WantReturnInfo = no,
Index: compiler/coverage_profiling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/coverage_profiling.m,v
retrieving revision 1.3
diff -u -r1.3 coverage_profiling.m
--- compiler/coverage_profiling.m	15 Dec 2010 06:29:32 -0000	1.3
+++ compiler/coverage_profiling.m	17 Dec 2010 02:55:08 -0000
@@ -15,6 +15,7 @@
 
 :- interface.
 
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
@@ -34,9 +35,10 @@
     % Perform the coverage profiling transformation on the given goal,
     % and return a list of the coverage points created.
     %
-:- pred coverage_prof_transform_goal(module_info::in, pred_proc_id::in,
-    maybe(deep_recursion_info)::in, hlds_goal::in, hlds_goal::out, 
-    prog_var_set_types::in, prog_var_set_types::out, 
+:- pred coverage_prof_transform_proc_body(module_info::in, pred_proc_id::in,
+    containing_goal_map::in, maybe(deep_recursion_info)::in,
+    hlds_goal::in, hlds_goal::out,
+    prog_var_set_types::in, prog_var_set_types::out,
     list(coverage_point_info)::out) is det.
 
 %-----------------------------------------------------------------------------%
@@ -79,7 +81,9 @@
                 ci_module_info              :: module_info,
                 ci_pred_proc_id             :: pred_proc_id,
                 ci_maybe_rec_info           :: maybe(deep_recursion_info),
-                ci_coverage_profiling_opts  :: coverage_profiling_options
+                ci_coverage_profiling_opts  :: coverage_profiling_options,
+
+                ci_containing_goal_map      :: containing_goal_map
             ).
 
 :- type coverage_data_type
@@ -148,11 +152,11 @@
         CoverageAfterGoal, BranchIf, BranchSwitch, BranchDisj,
         UsePortCounts, UseTrivial, RunFirstPass).
 
-coverage_prof_transform_goal(ModuleInfo, PredProcId, MaybeRecInfo, !Goal, 
-        !VarInfo, CoveragePoints) :-
+coverage_prof_transform_proc_body(ModuleInfo, PredProcId, ContainingGoalMap,
+        MaybeRecInfo, !Goal, !VarInfo, CoveragePoints) :-
     coverage_profiling_options(ModuleInfo, CoverageProfilingOptions),
     CoverageInfo0 = init_proc_coverage_info(!.VarInfo, ModuleInfo,
-        PredProcId, MaybeRecInfo, CoverageProfilingOptions),
+        PredProcId, MaybeRecInfo, CoverageProfilingOptions, ContainingGoalMap),
     RunFirstPass = CoverageProfilingOptions ^ cpo_run_first_pass,
     (
         RunFirstPass = yes,
@@ -184,9 +188,9 @@
 coverage_prof_second_pass_goal(Goal0, Goal, 
         CoverageBeforeKnown, NextCoverageBeforeKnown, !Info, AddedImpurity) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
-    Detism = GoalInfo0 ^ goal_info_get_determinism,
+    Detism = goal_info_get_determinism(GoalInfo0),
+    GoalId = goal_info_get_goal_id(GoalInfo0),
     CPOptions = !.Info ^ ci_coverage_profiling_opts,
-    GoalPath = goal_info_get_goal_path(GoalInfo0),
 
     % Currently the first pass is unsupported, we don't make use of the
     % information it provides in IsMDProfInst.
@@ -197,10 +201,11 @@
         IsMDProfInst = goal_is_not_mdprof_inst,
         CoverageBeforeKnown = coverage_before_unknown
     ->
+        GoalId = goal_id(GoalNum),
         UnknownMsg = string.format(
-            "coverage_prof_second_pass_goal: Coverage information is unknown\n"
-            ++ "\tGoalPath: %s",
-            [s(goal_path_to_string(GoalPath))]),
+            "coverage_prof_second_pass_goal: " ++
+            "Coverage information is unknown for goal_id %d\n",
+            [i(GoalNum)]),
         unexpected(this_file, UnknownMsg)
     ;
         true
@@ -350,7 +355,9 @@
     Goal1 = hlds_goal(GoalExpr1, GoalInfo1),
     (
         MaybeAddCP = yes(CPType),
-        CPInfo = coverage_point_info(GoalPath, CPType),
+        ContainingGoalMap = !.Info ^ ci_containing_goal_map,
+        RevGoalPath = goal_id_to_reverse_path(ContainingGoalMap, GoalId),
+        CPInfo = coverage_point_info(RevGoalPath, CPType),
 
         make_coverage_point(CPOptions, CPInfo, CPGoals, !Info),
         create_conj_from_list([Goal1 | CPGoals], plain_conj, Goal),
@@ -489,7 +496,9 @@
     % Insert the coverage point if we decided to above.
     (
         InsertCP = yes,
-        DisjPath = goal_info_get_goal_path(HeadDisjunct0 ^ hlds_goal_info),
+        DisjId = goal_info_get_goal_id(HeadDisjunct0 ^ hlds_goal_info),
+        ContainingGoalMap = !.Info ^ ci_containing_goal_map,
+        DisjPath = goal_id_to_reverse_path(ContainingGoalMap, DisjId),
         HeadCoveragePoint = coverage_point_info(DisjPath, cp_type_branch_arm),
         insert_coverage_point_before(CPOptions, HeadCoveragePoint,
             HeadDisjunct1, HeadDisjunct, !Info),
@@ -585,7 +594,9 @@
     % Possibly insert coverage point at the start of the case.
     (
         InsertCP = yes,
-        CasePath = goal_info_get_goal_path(Goal0 ^ hlds_goal_info),
+        CaseId = goal_info_get_goal_id(Goal0 ^ hlds_goal_info),
+        ContainingGoalMap = !.Info ^ ci_containing_goal_map,
+        CasePath = goal_id_to_reverse_path(ContainingGoalMap, CaseId),
         CoveragePoint = coverage_point_info(CasePath, cp_type_branch_arm),
         insert_coverage_point_before(CPOptions, CoveragePoint, Goal1, Goal,
             !Info),
@@ -648,9 +659,11 @@
         CPOBranchIf = yes,
         IsMDProfInst = goal_is_not_mdprof_inst
     ->
+        ContainingGoalMap = !.Info ^ ci_containing_goal_map,
         (
             CoverageKnownBeforeThen0 = coverage_before_unknown,
-            ThenPath = goal_info_get_goal_path(Then0 ^ hlds_goal_info),
+            ThenId = goal_info_get_goal_id(Then0 ^ hlds_goal_info),
+            ThenPath = goal_id_to_reverse_path(ContainingGoalMap, ThenId),
             InsertCPThen = yes(coverage_point_info(ThenPath,
                 cp_type_branch_arm))
         ;
@@ -658,7 +671,8 @@
             InsertCPThen = no
         ),
         % Always insert a coverage point for the else branch.
-        ElsePath = goal_info_get_goal_path(Else0 ^ hlds_goal_info),
+        ElseId = goal_info_get_goal_id(Else0 ^ hlds_goal_info),
+        ElsePath = goal_id_to_reverse_path(ContainingGoalMap, ElseId),
         InsertCPElse = yes(coverage_point_info(ElsePath, cp_type_branch_arm)),
         CoverageKnownBeforeThen = coverage_before_known,
         CoverageKnownBeforeElse = coverage_before_known
@@ -713,13 +727,14 @@
     % defaults.
     %
 :- func init_proc_coverage_info(prog_var_set_types, module_info, pred_proc_id,
-    maybe(deep_recursion_info), coverage_profiling_options) =
-    proc_coverage_info.
+    maybe(deep_recursion_info), coverage_profiling_options,
+    containing_goal_map) = proc_coverage_info.
 
 init_proc_coverage_info(VarInfo, ModuleInfo, PredProcId, MaybeRecInfo,
-        CoverageProfilingOptions) = CoverageInfo :-
+        CoverageProfilingOptions, ContainingGoalMap) = CoverageInfo :-
     CoverageInfo = proc_coverage_info(map.init, counter.init(0), VarInfo,
-        ModuleInfo, PredProcId, MaybeRecInfo, CoverageProfilingOptions).
+        ModuleInfo, PredProcId, MaybeRecInfo, CoverageProfilingOptions,
+        ContainingGoalMap).
 
     % Used to describe if coverage information is known at a partiular point
     % within a procedure.
Index: compiler/ctgc.util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ctgc.util.m,v
retrieving revision 1.22
diff -u -r1.22 ctgc.util.m
--- compiler/ctgc.util.m	15 Dec 2010 06:29:32 -0000	1.22
+++ compiler/ctgc.util.m	15 Dec 2010 06:33:14 -0000
@@ -26,8 +26,7 @@
 
     % Check if some of the predicates are "special" predicates (as in
     % "special_pred_map" known from module_info) or not defined in the
-    % current module, as these predicates are not analysed by the CTGC
-    % system.
+    % current module, as these predicates are not analysed by the CTGC system.
     %
 :- pred some_preds_requiring_no_analysis(module_info::in,
     list(pred_proc_id)::in) is semidet.
@@ -90,8 +89,8 @@
 pred_requires_no_analysis(ModuleInfo, PredId) :-
     module_info_pred_info(ModuleInfo, PredId, PredInfo),
     pred_info_get_import_status(PredInfo, Status),
-    % We handle `:- external' predicates later.  In that sense, they do *not*
-    % require that we don't analyse them.
+    % We handle `:- external' predicates later. In that sense,
+    % they do *not* require that we don't analyse them.
     Status = status_imported(_).
 
 pred_requires_analysis(ModuleInfo, PredId) :-
@@ -111,8 +110,6 @@
 
 get_variable_renaming(ModuleInfo, PPId, ActualArgs) = VariableRenaming :-
     module_info_pred_proc_info(ModuleInfo, PPId, _PredInfo, ProcInfo),
-
-    % head variables.
     proc_info_get_headvars(ProcInfo, FormalVars),
     map.from_corresponding_lists(FormalVars, ActualArgs, VariableRenaming).
 
Index: compiler/deep_profiling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/deep_profiling.m,v
retrieving revision 1.105
diff -u -r1.105 deep_profiling.m
--- compiler/deep_profiling.m	10 Sep 2010 05:14:57 -0000	1.105
+++ compiler/deep_profiling.m	13 Sep 2010 01:03:25 -0000
@@ -54,6 +54,7 @@
 :- import_module check_hlds.mode_util.
 :- import_module check_hlds.type_util.
 :- import_module hlds.code_model.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_out.
@@ -577,6 +578,7 @@
     --->    deep_info(
                 deep_module_info        :: module_info,
                 deep_pred_proc_id       :: pred_proc_id,
+                deep_containing_goal_map:: containing_goal_map,
                 deep_current_csd        :: prog_var,
                 deep_site_num_counter   :: counter,
                 deep_call_sites         :: cord(call_site_static_data),
@@ -592,12 +594,15 @@
 
 deep_prof_transform_normal_proc(ModuleInfo, PredProcId, !ProcInfo,
         DeepLayoutInfo) :-
+    fill_goal_id_slots_in_proc(ModuleInfo, ContainingGoalMap, !ProcInfo),
+
     module_info_get_globals(ModuleInfo, Globals),
-    proc_info_get_goal(!.ProcInfo, Goal0),
-    Goal0 = hlds_goal(_, GoalInfo0),
     proc_info_get_varset(!.ProcInfo, VarSet0),
     proc_info_get_vartypes(!.ProcInfo, VarTypes0),
-    some [!VarInfo] (
+    some [!VarInfo, !DeepInfo, !Goal] (
+        proc_info_get_goal(!.ProcInfo, !:Goal),
+        !.Goal = hlds_goal(_, GoalInfo0),
+
         !:VarInfo = prog_var_set_types(VarSet0, VarTypes0),
         generate_var("TopCSD", c_pointer_type, TopCSD, !VarInfo),
         generate_var("MiddleCSD", c_pointer_type, MiddleCSD, !VarInfo),
@@ -610,26 +615,26 @@
 
         proc_info_get_maybe_deep_profile_info(!.ProcInfo, MaybeDeepProfInfo),
         extract_deep_rec_info(MaybeDeepProfInfo, MaybeRecInfo),
-        DeepInfo0 = deep_info(ModuleInfo, PredProcId, MiddleCSD,
-            counter.init(0), cord.empty, !.VarInfo, FileName, MaybeRecInfo),
+        !:DeepInfo = deep_info(ModuleInfo, PredProcId, ContainingGoalMap,
+            MiddleCSD, counter.init(0), cord.empty, !.VarInfo, FileName,
+            MaybeRecInfo),
 
         % This call transforms the goals of the procedure.
-        deep_prof_transform_goal(empty_goal_path, Goal0, Goal1, _,
-            DeepInfo0, DeepInfo),
-        !:VarInfo = DeepInfo ^ deep_varinfo,
-        CallSites = cord.list(DeepInfo ^ deep_call_sites),
+        deep_prof_transform_goal(!Goal, _, !DeepInfo),
+        !:VarInfo = !.DeepInfo ^ deep_varinfo,
+        CallSites = cord.list(!.DeepInfo ^ deep_call_sites),
 
         % Do coverage profiling if requested.
         globals.lookup_bool_option(Globals, coverage_profiling,
             DoCoverageProfiling),
         (
             DoCoverageProfiling = yes,
-            coverage_prof_transform_goal(ModuleInfo, PredProcId, MaybeRecInfo,
-                Goal1, TransformedGoal, !VarInfo, CoveragePoints)
+            coverage_prof_transform_proc_body(ModuleInfo, PredProcId,
+                ContainingGoalMap, MaybeRecInfo, !Goal, !VarInfo,
+                CoveragePoints)
         ;
             DoCoverageProfiling = no,
-            CoveragePoints = [],
-            TransformedGoal = Goal1
+            CoveragePoints = []
         ),
 
         (
@@ -661,15 +666,13 @@
             maybe_generate_activation_ptr(UseActivationCounts, TopCSD,
                 MiddleCSD, MaybeActivationPtr, ExcpVars, !VarInfo),
             build_det_proc_body(ModuleInfo, TopCSD, MiddleCSD, ProcStaticVar,
-                MaybeActivationPtr, GoalInfo0, BindProcStaticVarGoal,
-                TransformedGoal, Goal)
+                MaybeActivationPtr, GoalInfo0, BindProcStaticVarGoal, !Goal)
         ;
             CodeModel = model_semi,
             maybe_generate_activation_ptr(UseActivationCounts, TopCSD,
                 MiddleCSD, MaybeActivationPtr, ExcpVars, !VarInfo),
             build_semi_proc_body(ModuleInfo, TopCSD, MiddleCSD, ProcStaticVar,
-                MaybeActivationPtr, GoalInfo0, BindProcStaticVarGoal,
-                TransformedGoal, Goal)
+                MaybeActivationPtr, GoalInfo0, BindProcStaticVarGoal, !Goal)
         ;
             CodeModel = model_non,
             generate_outermost_proc_dyns(UseActivationCounts, TopCSD,
@@ -677,26 +680,28 @@
                 ExcpVars, !VarInfo),
             build_non_proc_body(ModuleInfo, TopCSD, MiddleCSD,
                 ProcStaticVar, MaybeOldActivationPtr, NewOutermostProcDyn,
-                GoalInfo0, BindProcStaticVarGoal, TransformedGoal, Goal)
+                GoalInfo0, BindProcStaticVarGoal, !Goal)
         ),
 
-        !.VarInfo = prog_var_set_types(Vars, VarTypes)
-    ),
-    proc_info_set_varset(Vars, !ProcInfo),
-    proc_info_set_vartypes(VarTypes, !ProcInfo),
-    proc_info_set_goal(Goal, !ProcInfo),
-    DeepLayoutInfo = hlds_deep_layout(ProcStatic, ExcpVars).
+        !.VarInfo = prog_var_set_types(Vars, VarTypes),
+        proc_info_set_varset(Vars, !ProcInfo),
+        proc_info_set_vartypes(VarTypes, !ProcInfo),
+        proc_info_set_goal(!.Goal, !ProcInfo),
+        DeepLayoutInfo = hlds_deep_layout(ProcStatic, ExcpVars)
+    ).
 
     % Transform an inner procedure for deep profiling. Inner procedures are
     % created by the tail recursion preservation pass above.
     %
     % XXX: Inner procedures have no coverage profiling transformation done to
-    % them yet.  This is because they are currently broken, and hence disabled.
+    % them yet. This is because they are currently broken, and hence disabled.
     %
 :- pred deep_prof_transform_inner_proc(module_info::in, pred_proc_id::in,
     proc_info::in, proc_info::out) is det.
 
 deep_prof_transform_inner_proc(ModuleInfo, PredProcId, !ProcInfo) :-
+    fill_goal_id_slots_in_proc(ModuleInfo, ContainingGoalMap, !ProcInfo),
+
     proc_info_get_goal(!.ProcInfo, Goal0),
     Goal0 = hlds_goal(_, GoalInfo0),
     proc_info_get_varset(!.ProcInfo, VarSet0),
@@ -709,18 +714,17 @@
 
     proc_info_get_maybe_deep_profile_info(!.ProcInfo, MaybeDeepProfInfo),
     extract_deep_rec_info(MaybeDeepProfInfo, MaybeRecInfo),
-    DeepInfo0 = deep_info(ModuleInfo, PredProcId, MiddleCSD,
+    DeepInfo0 = deep_info(ModuleInfo, PredProcId, ContainingGoalMap, MiddleCSD,
         counter.init(0), cord.empty, VarInfo1, FileName, MaybeRecInfo),
 
-    deep_prof_transform_goal(empty_goal_path, Goal0, TransformedGoal, _,
-        DeepInfo0, DeepInfo),
+    deep_prof_transform_goal(Goal0, Goal, _, DeepInfo0, DeepInfo),
 
     VarInfo = DeepInfo ^ deep_varinfo,
     VarInfo = prog_var_set_types(VarSet, VarTypes),
 
     proc_info_set_varset(VarSet, !ProcInfo),
     proc_info_set_vartypes(VarTypes, !ProcInfo),
-    proc_info_set_goal(TransformedGoal, !ProcInfo).
+    proc_info_set_goal(Goal, !ProcInfo).
 
 :- func is_proc_in_interface(module_info, pred_id, proc_id) = bool.
 
@@ -927,21 +931,20 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred deep_prof_transform_goal(goal_path::in, hlds_goal::in, hlds_goal::out,
+:- pred deep_prof_transform_goal(hlds_goal::in, hlds_goal::out,
     bool::out, deep_info::in, deep_info::out) is det.
 
-deep_prof_transform_goal(Path, Goal0, Goal, AddedImpurity, !DeepInfo) :-
+deep_prof_transform_goal(Goal0, Goal, AddedImpurity, !DeepInfo) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
-    goal_info_set_goal_path(Path, GoalInfo0, GoalInfo1),
-    goal_info_set_mdprof_inst(goal_is_not_mdprof_inst, GoalInfo1, GoalInfo2),
-    Goal1 = hlds_goal(GoalExpr0, GoalInfo2),
+    goal_info_set_mdprof_inst(goal_is_not_mdprof_inst, GoalInfo0, GoalInfo1),
+    Goal1 = hlds_goal(GoalExpr0, GoalInfo1),
     (
         GoalExpr0 = plain_call(_, _, _, BuiltinState, _, _),
         (
             ( BuiltinState = out_of_line_builtin
             ; BuiltinState = not_builtin
             ),
-            deep_prof_wrap_call(Path, Goal1, Goal, !DeepInfo),
+            deep_prof_wrap_call(Goal1, Goal, !DeepInfo),
             AddedImpurity = yes
         ;
             BuiltinState = inline_builtin,
@@ -954,7 +957,7 @@
             ( GenericCall = higher_order(_, _, _, _)
             ; GenericCall = class_method(_, _, _, _)
             ),
-            deep_prof_wrap_call(Path, Goal1, Goal, !DeepInfo),
+            deep_prof_wrap_call(Goal1, Goal, !DeepInfo),
             AddedImpurity = yes
         ;
             ( GenericCall = event_call(_)
@@ -966,7 +969,7 @@
     ;
         GoalExpr0 = call_foreign_proc(Attrs, _, _, _, _, _, _),
         ( get_may_call_mercury(Attrs) = proc_may_call_mercury ->
-            deep_prof_wrap_foreign_code(Path, Goal1, Goal, !DeepInfo),
+            deep_prof_wrap_foreign_code(Goal1, Goal, !DeepInfo),
             AddedImpurity = yes
         ;
             Goal = Goal1,
@@ -978,55 +981,34 @@
         AddedImpurity = no
     ;
         GoalExpr0 = conj(ConjType, Goals0),
-        deep_prof_transform_conj(0, ConjType, Path, Goals0, Goals,
-            AddedImpurity, !DeepInfo),
-        add_impurity_if_needed(AddedImpurity, GoalInfo2, GoalInfo),
+        deep_prof_transform_conj(ConjType, Goals0, Goals, AddedImpurity,
+            !DeepInfo),
+        add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo),
         GoalExpr = conj(ConjType, Goals),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = disj(Goals0),
-        deep_prof_transform_disj(0, Path, Goals0, Goals, AddedImpurity,
-            !DeepInfo),
-        add_impurity_if_needed(AddedImpurity, GoalInfo2, GoalInfo),
+        deep_prof_transform_disj(Goals0, Goals, AddedImpurity, !DeepInfo),
+        add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo),
         GoalExpr = disj(Goals),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = switch(Var, CanFail, Cases0),
-        % XXX: This computation seems broken, it's been disabled so I can
-        % relyably implement coverage profiling.  Test it on
-        % erlang_rtti_implementation.deconstruct_2/9-2 whose switch's type has
-        % 25 constructors yet this computes 27.  Are constructors different to
-        % functors?
-        % zs: this computation is NOT broken.
-        % ModuleInfo = !.DeepInfo ^ deep_module_info,
-        % VarTypes = !.DeepInfo ^ deep_varinfo ^ varinfo_vartypes,
-        % map.lookup(VarTypes, Var, Type),
-        % ( switch_type_num_functors(ModuleInfo, Type, NumFunctors) ->
-        %     MaybeNumFunctors = yes(NumFunctors)
-        % ;
-        %     MaybeNumFunctors = no
-        % ),
-        MaybeNumFunctors = no,
-        deep_prof_transform_switch(MaybeNumFunctors, 0, Path, Cases0, Cases,
-            AddedImpurity, !DeepInfo),
-        add_impurity_if_needed(AddedImpurity, GoalInfo2, GoalInfo),
+        deep_prof_transform_switch(Cases0, Cases, AddedImpurity, !DeepInfo),
+        add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo),
         GoalExpr = switch(Var, CanFail, Cases),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = negation(SubGoal0),
-        deep_prof_transform_goal(goal_path_add_at_end(Path, step_neg),
-            SubGoal0, SubGoal, AddedImpurity, !DeepInfo),
-        add_impurity_if_needed(AddedImpurity, GoalInfo2, GoalInfo),
+        deep_prof_transform_goal(SubGoal0, SubGoal, AddedImpurity, !DeepInfo),
+        add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo),
         GoalExpr = negation(SubGoal),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = if_then_else(IVars, Cond0, Then0, Else0),
-        deep_prof_transform_goal(goal_path_add_at_end(Path, step_ite_cond),
-            Cond0, Cond, AddedImpurityC, !DeepInfo),
-        deep_prof_transform_goal(goal_path_add_at_end(Path, step_ite_then),
-            Then0, Then, AddedImpurityT, !DeepInfo),
-        deep_prof_transform_goal(goal_path_add_at_end(Path, step_ite_else),
-            Else0, Else, AddedImpurityE, !DeepInfo),
+        deep_prof_transform_goal(Cond0, Cond, AddedImpurityC, !DeepInfo),
+        deep_prof_transform_goal(Then0, Then, AddedImpurityT, !DeepInfo),
+        deep_prof_transform_goal(Else0, Else, AddedImpurityE, !DeepInfo),
         (
             ( AddedImpurityC = yes
             ; AddedImpurityT = yes
@@ -1037,16 +1019,15 @@
         ;
             AddedImpurity = no
         ),
-        add_impurity_if_needed(AddedImpurity, GoalInfo2, GoalInfo),
+        add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo),
         GoalExpr = if_then_else(IVars, Cond, Then, Else),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = scope(Reason0, SubGoal0),
         SubGoal0 = hlds_goal(_, InnerInfo),
-        OuterDetism = goal_info_get_determinism(GoalInfo2),
+        OuterDetism = goal_info_get_determinism(GoalInfo1),
         InnerDetism = goal_info_get_determinism(InnerInfo),
         ( InnerDetism = OuterDetism ->
-            MaybeCut = scope_is_no_cut,
             Reason = Reason0,
             AddForceCommit = no
         ;
@@ -1058,7 +1039,6 @@
             % and the deep profiling transformation will make it impure
             % as well.
 
-            MaybeCut = scope_is_cut,
             ( Reason0 = commit(_) ->
                 Reason = commit(force_pruning),
                 AddForceCommit = no
@@ -1067,7 +1047,6 @@
                 AddForceCommit = yes
             )
         ),
-        ScopedGoalPath = goal_path_add_at_end(Path, step_scope(MaybeCut)),
         ( Reason = from_ground_term(_, from_ground_term_construct) ->
             % We must annotate the scope goal and its children with a default
             % deep profiling information structure, this is required by the
@@ -1076,10 +1055,10 @@
                 SubGoal0, SubGoal),
             AddedImpurity = no
         ;
-            deep_prof_transform_goal(ScopedGoalPath, SubGoal0, SubGoal,
-                AddedImpurity, !DeepInfo)
+            deep_prof_transform_goal(SubGoal0, SubGoal, AddedImpurity,
+                !DeepInfo)
         ),
-        add_impurity_if_needed(AddedImpurity, GoalInfo2, GoalInfo),
+        add_impurity_if_needed(AddedImpurity, GoalInfo1, GoalInfo),
         (
             AddForceCommit = no,
             Goal = hlds_goal(scope(Reason, SubGoal), GoalInfo)
@@ -1096,7 +1075,7 @@
             "deep_prof_transform_goal: shorthand should have gone by now")
     ).
 
-:- pred deep_prof_mark_goal_as_not_mdprof_inst( hlds_goal::in, hlds_goal::out)
+:- pred deep_prof_mark_goal_as_not_mdprof_inst(hlds_goal::in, hlds_goal::out)
     is det.
 
 deep_prof_mark_goal_as_not_mdprof_inst(Goal0, Goal) :-
@@ -1104,19 +1083,16 @@
     goal_info_set_mdprof_inst(goal_is_not_mdprof_inst, GoalInfo0, GoalInfo),
     Goal = Goal0 ^ hlds_goal_info := GoalInfo.
 
-:- pred deep_prof_transform_conj(int::in,
-    conj_type::in, goal_path::in,
+:- pred deep_prof_transform_conj(conj_type::in,
     list(hlds_goal)::in, list(hlds_goal)::out, bool::out,
     deep_info::in, deep_info::out) is det.
 
-deep_prof_transform_conj(_, _, _, [], [], no, !DeepInfo).
-deep_prof_transform_conj(N, ConjType, Path, [Goal0 | Goals0], Goals,
+deep_prof_transform_conj(_, [], [], no, !DeepInfo).
+deep_prof_transform_conj(ConjType, [Goal0 | Goals0], Goals,
         AddedImpurity, !DeepInfo) :-
-    N1 = N + 1,
-    deep_prof_transform_goal(goal_path_add_at_end(Path, step_conj(N1)),
-        Goal0, Goal, AddedImpurityFirst, !DeepInfo),
-    deep_prof_transform_conj(N1, ConjType, Path, Goals0,
-        TailGoals, AddedImpurityLater, !DeepInfo),
+    deep_prof_transform_goal(Goal0, Goal, AddedImpurityFirst, !DeepInfo),
+    deep_prof_transform_conj(ConjType, Goals0, TailGoals,
+        AddedImpurityLater, !DeepInfo),
     Goal = hlds_goal(GoalExpr, _),
     (
         GoalExpr = conj(plain_conj, Conjuncts),
@@ -1128,42 +1104,39 @@
     ),
     bool.or(AddedImpurityFirst, AddedImpurityLater, AddedImpurity).
 
-:- pred deep_prof_transform_disj(int::in, goal_path::in,
-    list(hlds_goal)::in, list(hlds_goal)::out, bool::out,
-    deep_info::in, deep_info::out) is det.
+:- pred deep_prof_transform_disj(list(hlds_goal)::in, list(hlds_goal)::out,
+    bool::out, deep_info::in, deep_info::out) is det.
 
-deep_prof_transform_disj(_, _, [], [], no, !DeepInfo).
-deep_prof_transform_disj(N, Path, [Goal0 | Goals0], [Goal | Goals],
+deep_prof_transform_disj([], [], no, !DeepInfo).
+deep_prof_transform_disj([Goal0 | Goals0], [Goal | Goals],
         AddedImpurity, !DeepInfo) :-
-    N1 = N + 1,
-    deep_prof_transform_goal(goal_path_add_at_end(Path, step_disj(N1)),
-        Goal0, Goal, AddedImpurityFirst, !DeepInfo),
-    deep_prof_transform_disj(N1, Path, Goals0, Goals, AddedImpurityLater,
+    deep_prof_transform_goal(Goal0, Goal, AddedImpurityFirst, !DeepInfo),
+    deep_prof_transform_disj(Goals0, Goals, AddedImpurityLater,
         !DeepInfo),
     bool.or(AddedImpurityFirst, AddedImpurityLater, AddedImpurity).
 
-:- pred deep_prof_transform_switch(maybe(int)::in, int::in, goal_path::in,
-    list(case)::in, list(case)::out, bool::out,
+:- pred deep_prof_transform_switch(list(case)::in, list(case)::out, bool::out,
     deep_info::in, deep_info::out) is det.
 
-deep_prof_transform_switch(_, _, _, [], [], no, !DeepInfo).
-deep_prof_transform_switch(MaybeNumCases, N, Path,
-        [Case0 | Cases0], [Case | Cases], AddedImpurity, !DeepInfo) :-
-    N1 = N + 1,
+deep_prof_transform_switch([], [], no, !DeepInfo).
+deep_prof_transform_switch([Case0 | Cases0], [Case | Cases], AddedImpurity,
+        !DeepInfo) :-
     Case0 = case(MainConsId, OtherConsIds, Goal0),
-    deep_prof_transform_goal(
-        goal_path_add_at_end(Path, step_switch(N1, MaybeNumCases)),
-        Goal0, Goal, AddedImpurityFirst, !DeepInfo),
+    deep_prof_transform_goal(Goal0, Goal, AddedImpurityFirst, !DeepInfo),
     Case = case(MainConsId, OtherConsIds, Goal),
-    deep_prof_transform_switch(MaybeNumCases, N1, Path, Cases0, Cases,
+    deep_prof_transform_switch(Cases0, Cases,
         AddedImpurityLater, !DeepInfo),
     bool.or(AddedImpurityFirst, AddedImpurityLater, AddedImpurity).
 
-:- pred deep_prof_wrap_call(goal_path::in, hlds_goal::in, hlds_goal::out,
+:- pred deep_prof_wrap_call(hlds_goal::in, hlds_goal::out,
     deep_info::in, deep_info::out) is det.
 
-deep_prof_wrap_call(GoalPath, Goal0, Goal, !DeepInfo) :-
+deep_prof_wrap_call(Goal0, Goal, !DeepInfo) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
+    GoalId = goal_info_get_goal_id(GoalInfo0),
+    ContainingGoalMap = !.DeepInfo ^ deep_containing_goal_map,
+    GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
+
     ModuleInfo = !.DeepInfo ^ deep_module_info,
     GoalFeatures = goal_info_get_features(GoalInfo0),
     goal_info_remove_feature(feature_deep_tail_rec_call, GoalInfo0, GoalInfo1),
@@ -1172,8 +1145,8 @@
         MdprofInstGoalInfo),
 
     % We need to make the call itself impure. If we didn't do so,
-    % then simplify could eliminate the goal (e.g. if it was a duplicate
-    % call). The result would be a prepare_for_{...}_call whose execution
+    % then simplify could eliminate the goal (e.g. if it was a duplicate call).
+    % The result would be a prepare_for_{...}_call whose execution
     % is not followed by the execution of the call port code of the callee.
     % This would leave the MR_csd_callee_ptr field NULL, which violates
     % invariants of the deep profiling tree (which allows this field to be
@@ -1473,12 +1446,14 @@
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ).
 
-:- pred deep_prof_wrap_foreign_code(goal_path::in,
-    hlds_goal::in, hlds_goal::out, deep_info::in, deep_info::out) is det.
+:- pred deep_prof_wrap_foreign_code(hlds_goal::in, hlds_goal::out,
+    deep_info::in, deep_info::out) is det.
 
-deep_prof_wrap_foreign_code(GoalPath, Goal0, Goal, !DeepInfo) :-
-    Goal0 = hlds_goal(_, GoalInfo0),
-    ModuleInfo = !.DeepInfo ^ deep_module_info,
+deep_prof_wrap_foreign_code(Goal0, Goal, !DeepInfo) :-
+    Goal0 = hlds_goal(_GoalExpr0, GoalInfo0),
+    GoalId = goal_info_get_goal_id(GoalInfo0),
+    ContainingGoalMap = !.DeepInfo ^ deep_containing_goal_map,
+    GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
 
     SiteNumCounter0 = !.DeepInfo ^ deep_site_num_counter,
     counter.allocate(SiteNum, SiteNumCounter0, SiteNumCounter),
@@ -1486,6 +1461,7 @@
         VarInfo),
     generate_deep_const_unify(int_const(SiteNum), SiteNumVar, SiteNumVarGoal),
 
+    ModuleInfo = !.DeepInfo ^ deep_module_info,
     generate_deep_det_call(ModuleInfo, "prepare_for_callback", 1,
         [SiteNumVar], [], PrepareGoal),
 
@@ -1497,8 +1473,8 @@
 
     make_impure(GoalInfo0, GoalInfo1),
     goal_info_set_mdprof_inst(goal_is_mdprof_inst, GoalInfo1, GoalInfo),
-    Goal = hlds_goal(conj(plain_conj, [SiteNumVarGoal, PrepareGoal, Goal0]),
-        GoalInfo),
+    GoalExpr = conj(plain_conj, [SiteNumVarGoal, PrepareGoal, Goal0]),
+    Goal = hlds_goal(GoalExpr, GoalInfo),
     !DeepInfo ^ deep_site_num_counter := SiteNumCounter,
     !DeepInfo ^ deep_varinfo := VarInfo,
     !DeepInfo ^ deep_call_sites :=
Index: compiler/format_call.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/format_call.m,v
retrieving revision 1.21
diff -u -r1.21 format_call.m
--- compiler/format_call.m	8 Nov 2010 03:43:42 -0000	1.21
+++ compiler/format_call.m	8 Nov 2010 04:23:39 -0000
@@ -90,7 +90,7 @@
 %
 % If there are any such replacements, we perform a second backward traversal of
 % the procedure body, looking for the goals to be replaced, which we identity
-% by goal_path.
+% by goal_id.
 %
 % For each call we want to optimize, we also want to delete the code that
 % constructs the format string and the lists of poly_types. The first pass
@@ -136,7 +136,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_pred.
 :- import_module hlds.instmap.
@@ -170,7 +170,7 @@
 
 :- type format_call_site
     --->    format_call_site(
-                fcs_goal_path               :: goal_path,
+                fcs_goal_id                 :: goal_id,
                 fcs_string_var              :: prog_var,
                 fcs_values_var              :: prog_var,
                 fcs_call_kind               :: format_call_kind,
@@ -310,7 +310,7 @@
         !VarSet, !VarTypes) :-
     map.init(ConjMaps0),
     counter.init(0, Counter0),
-    fill_goal_path_slots_in_goal(Goal0, !.VarTypes, ModuleInfo, Goal1),
+    fill_goal_id_slots_in_proc_body(ModuleInfo, !.VarTypes, _, Goal0, Goal1),
     format_call_traverse_goal(ModuleInfo, Goal1, _, [], FormatCallSites,
         Counter0, _Counter, ConjMaps0, ConjMaps, map.init, PredMap,
         set_tree234.init, _),
@@ -318,8 +318,8 @@
     globals.lookup_bool_option(Globals, optimize_format_calls, OptFormatCalls),
     list.foldl4(
         check_format_call_site(ModuleInfo, OptFormatCalls, ConjMaps, PredMap),
-        FormatCallSites, map.init, GoalPathMap, [], Specs, !VarSet, !VarTypes),
-    ( map.is_empty(GoalPathMap) ->
+        FormatCallSites, map.init, GoalIdMap, [], Specs, !VarSet, !VarTypes),
+    ( map.is_empty(GoalIdMap) ->
         % We have not found anything to improve in Goal1.
         MaybeGoal = no
     ;
@@ -332,20 +332,20 @@
         ToDeleteVars0 = set_tree234.init,
         NeededVarsSet = set_tree234.sorted_list_to_set(
             set.to_sorted_list(NeededVars0)),
-        opt_format_call_sites_in_goal(Goal1, Goal, GoalPathMap, _,
+        opt_format_call_sites_in_goal(Goal1, Goal, GoalIdMap, _,
             NeededVarsSet, _NeededVars, ToDeleteVars0, _ToDeleteVars),
         MaybeGoal = yes(Goal)
     ).
 
 :- pred check_format_call_site(module_info::in, bool::in, conj_maps::in,
     conj_pred_map::in, format_call_site::in,
-    fc_goal_path_map::in, fc_goal_path_map::out,
+    fc_goal_id_map::in, fc_goal_id_map::out,
     list(error_spec)::in, list(error_spec)::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
 
 check_format_call_site(ModuleInfo, OptFormatCalls, ConjMaps, PredMap,
-        FormatCallSite, !GoalPathMap, !Specs, !VarSet, !VarTypes) :-
-    FormatCallSite = format_call_site(GoalPath, StringVar, ValuesVar, Kind,
+        FormatCallSite, !GoalIdMap, !Specs, !VarSet, !VarTypes) :-
+    FormatCallSite = format_call_site(GoalId, StringVar, ValuesVar, Kind,
         ModuleName, Name, Arity, Context, CurId),
     SymName = qualified(ModuleName, Name),
 
@@ -438,10 +438,10 @@
                 OptFormatCalls = no
             ;
                 OptFormatCalls = yes,
-                try_create_replacement_goal(ModuleInfo, GoalPath,
+                try_create_replacement_goal(ModuleInfo, GoalId,
                     Kind, FormatString, StringVar1,
                     ValuesToDeleteVars, WhatToPrints,
-                    !GoalPathMap, !VarSet, !VarTypes)
+                    !GoalIdMap, !VarSet, !VarTypes)
             )
         )
     ;
@@ -449,15 +449,15 @@
         true
     ).
 
-:- pred try_create_replacement_goal(module_info::in, goal_path::in,
+:- pred try_create_replacement_goal(module_info::in, goal_id::in,
     format_call_kind::in, string::in, prog_var::in,
     list(prog_var)::in, list(what_to_print)::in,
-    fc_goal_path_map::in, fc_goal_path_map::out,
+    fc_goal_id_map::in, fc_goal_id_map::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
 
-try_create_replacement_goal(ModuleInfo, GoalPath, Kind,
+try_create_replacement_goal(ModuleInfo, GoalId, Kind,
         FormatString, StringVar, ValuesToDeleteVars,
-        WhatToPrints, !GoalPathMap, !VarSet, !VarTypes) :-
+        WhatToPrints, !GoalIdMap, !VarSet, !VarTypes) :-
     string.to_char_list(FormatString, FormatStringChars),
     VarsToPrint = list.map(project_var_to_print, WhatToPrints),
     % Note that every predicate or function that this code generates calls to
@@ -474,7 +474,7 @@
             AllToDeleteVars = [StringVar | ValuesToDeleteVars],
             FCOptGoalInfo = fc_opt_goal_info(ReplacementGoal,
                 set_tree234.list_to_set(AllToDeleteVars)),
-            svmap.det_insert(GoalPath, FCOptGoalInfo, !GoalPathMap)
+            svmap.det_insert(GoalId, FCOptGoalInfo, !GoalIdMap)
         ;
             % create_string_format_replacement does not (yet) recognize
             % all possible format strings. We cannot optimize the ones
@@ -497,7 +497,7 @@
             AllToDeleteVars = [StringVar | ValuesToDeleteVars],
             FCOptGoalInfo = fc_opt_goal_info(ReplacementGoal,
                 set_tree234.list_to_set(AllToDeleteVars)),
-            svmap.det_insert(GoalPath, FCOptGoalInfo, !GoalPathMap)
+            svmap.det_insert(GoalId, FCOptGoalInfo, !GoalIdMap)
         ;
             % create_string_format_replacement does not (yet) recognize
             % all possible format strings. We cannot optimize the ones
@@ -683,9 +683,9 @@
                 Kind, StringVar, ValuesVar)
         ->
             Arity = pred_info_orig_arity(PredInfo),
-            GoalPath = goal_info_get_goal_path(GoalInfo),
+            GoalId = goal_info_get_goal_id(GoalInfo),
             Context = goal_info_get_context(GoalInfo),
-            FormatCallSite = format_call_site(GoalPath, StringVar, ValuesVar,
+            FormatCallSite = format_call_site(GoalId, StringVar, ValuesVar,
                 Kind, ModuleName, Name, Arity, Context, CurId),
             !:FormatCallSites = [FormatCallSite | !.FormatCallSites],
             set_tree234.insert_list([StringVar, ValuesVar], !RelevantVars)
@@ -885,23 +885,23 @@
                 fcogi_unneeded_vars     :: set_tree234(prog_var)
             ).
 
-:- type fc_goal_path_map == map(goal_path, fc_opt_goal_info).
+:- type fc_goal_id_map == map(goal_id, fc_opt_goal_info).
 
-    % Traverse the goal, looking for call sites in !.GoalPathMap. If we
+    % Traverse the goal, looking for call sites in !.GoalIdMap. If we
     % find them, we replace them with the corresponding goal.
     %
 :- pred opt_format_call_sites_in_goal(hlds_goal::in, hlds_goal::out,
-    fc_goal_path_map::in, fc_goal_path_map::out,
+    fc_goal_id_map::in, fc_goal_id_map::out,
     set_tree234(prog_var)::in, set_tree234(prog_var)::out,
     set_tree234(prog_var)::in, set_tree234(prog_var)::out) is det.
 
-opt_format_call_sites_in_goal(Goal0, Goal, !GoalPathMap,
+opt_format_call_sites_in_goal(Goal0, Goal, !GoalIdMap,
         !NeededVars, !ToDeleteVars) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo),
     (
         GoalExpr0 = plain_call(_, _, _, _, _, _),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
-        ( svmap.remove(GoalPath, OptGoalInfo, !GoalPathMap) ->
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        ( svmap.remove(GoalId, OptGoalInfo, !GoalIdMap) ->
             OptGoalInfo = fc_opt_goal_info(ReplacementGoal, GoalToDeleteVars),
             Goal = ReplacementGoal,
             set_tree234.union(!.ToDeleteVars, GoalToDeleteVars, !:ToDeleteVars)
@@ -961,12 +961,12 @@
         % XXX Check that this works for parallel conjunctions.
         GoalExpr0 = conj(ConjType, Conjuncts0),
         opt_format_call_sites_in_conj(Conjuncts0, Conjuncts,
-            !GoalPathMap, !NeededVars, !ToDeleteVars),
+            !GoalIdMap, !NeededVars, !ToDeleteVars),
         GoalExpr = conj(ConjType, Conjuncts),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = disj(Disjuncts0),
-        opt_format_call_sites_in_disj(Disjuncts0, Disjuncts, !GoalPathMap,
+        opt_format_call_sites_in_disj(Disjuncts0, Disjuncts, !GoalIdMap,
             !.NeededVars, [], NeededVarsSets,
             !.ToDeleteVars, [], ToDeleteVarsSets),
         !:NeededVars = set_tree234.union_list(NeededVarsSets),
@@ -975,7 +975,7 @@
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = switch(SwitchVar, CanFail, Cases0),
-        opt_format_call_sites_in_switch(Cases0, Cases, !GoalPathMap,
+        opt_format_call_sites_in_switch(Cases0, Cases, !GoalIdMap,
             !.NeededVars, [], NeededVarsSets,
             !.ToDeleteVars, [], ToDeleteVarsSets),
         !:NeededVars = set_tree234.union_list(NeededVarsSets),
@@ -984,13 +984,13 @@
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
-        opt_format_call_sites_in_goal(Else0, Else, !GoalPathMap,
+        opt_format_call_sites_in_goal(Else0, Else, !GoalIdMap,
             !.NeededVars, NeededVarsBeforeElse,
             !.ToDeleteVars, ToDeleteVarsBeforeElse),
-        opt_format_call_sites_in_goal(Then0, Then, !GoalPathMap,
+        opt_format_call_sites_in_goal(Then0, Then, !GoalIdMap,
             !.NeededVars, NeededVarsBeforeThen,
             !.ToDeleteVars, ToDeleteVarsBeforeThen),
-        opt_format_call_sites_in_goal(Cond0, Cond, !GoalPathMap,
+        opt_format_call_sites_in_goal(Cond0, Cond, !GoalIdMap,
             NeededVarsBeforeThen, NeededVarsBeforeCond,
             ToDeleteVarsBeforeThen, ToDeleteVarsBeforeCond),
         set_tree234.union(NeededVarsBeforeCond, NeededVarsBeforeElse,
@@ -1004,7 +1004,7 @@
         % SubGoal0 cannot generate anything in !.ToDeleteVars, but it can add
         % to both !:NeededVars and !:ToDeleteVars.
         opt_format_call_sites_in_goal(SubGoal0, SubGoal,
-            !GoalPathMap, !NeededVars, !ToDeleteVars),
+            !GoalIdMap, !NeededVars, !ToDeleteVars),
         GoalExpr = negation(SubGoal),
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
@@ -1019,7 +1019,7 @@
             Goal = Goal0
         ;
             opt_format_call_sites_in_goal(SubGoal0, SubGoal,
-                !GoalPathMap, !NeededVars, !ToDeleteVars),
+                !GoalIdMap, !NeededVars, !ToDeleteVars),
             GoalExpr = scope(Reason, SubGoal),
             Goal = hlds_goal(GoalExpr, GoalInfo)
         )
@@ -1029,10 +1029,10 @@
             ShortHand0 = atomic_goal(AtomicType, OuterVars, InnerVars,
                 OutputVars, MainGoal0, OrElseGoals0, OrElseInners),
             opt_format_call_sites_in_goal(MainGoal0, MainGoal,
-                !GoalPathMap, !.NeededVars, NeededVarsMain,
+                !GoalIdMap, !.NeededVars, NeededVarsMain,
                 !.ToDeleteVars, ToDeleteVarsMain),
             opt_format_call_sites_in_disj(OrElseGoals0, OrElseGoals,
-                !GoalPathMap, !.NeededVars, [], NeededVarsSets,
+                !GoalIdMap, !.NeededVars, [], NeededVarsSets,
                 !.ToDeleteVars, [], ToDeleteVarsSets),
             !:NeededVars =
                 set_tree234.union_list([NeededVarsMain | NeededVarsSets]),
@@ -1045,7 +1045,7 @@
         ;
             ShortHand0 = try_goal(MaybeIO, ResultVar, SubGoal0),
             opt_format_call_sites_in_goal(SubGoal0, SubGoal,
-                !GoalPathMap, !NeededVars, !ToDeleteVars),
+                !GoalIdMap, !NeededVars, !ToDeleteVars),
             ShortHand = try_goal(MaybeIO, ResultVar, SubGoal),
             GoalExpr = shorthand(ShortHand)
         ;
@@ -1059,63 +1059,63 @@
 
 :- pred opt_format_call_sites_in_conj(
     list(hlds_goal)::in, list(hlds_goal)::out,
-    fc_goal_path_map::in, fc_goal_path_map::out,
+    fc_goal_id_map::in, fc_goal_id_map::out,
     set_tree234(prog_var)::in, set_tree234(prog_var)::out,
     set_tree234(prog_var)::in, set_tree234(prog_var)::out) is det.
 
-opt_format_call_sites_in_conj([], [], !GoalPathMap,
+opt_format_call_sites_in_conj([], [], !GoalIdMap,
         !NeededVars, !ToDeleteVars).
-opt_format_call_sites_in_conj([Goal0 | Goals0], [Goal | Goals], !GoalPathMap,
+opt_format_call_sites_in_conj([Goal0 | Goals0], [Goal | Goals], !GoalIdMap,
         !NeededVars, !ToDeleteVars) :-
     % We traverse conjunctions backwards.
-    opt_format_call_sites_in_conj(Goals0, Goals, !GoalPathMap,
+    opt_format_call_sites_in_conj(Goals0, Goals, !GoalIdMap,
         !NeededVars, !ToDeleteVars),
-    opt_format_call_sites_in_goal(Goal0, Goal, !GoalPathMap,
+    opt_format_call_sites_in_goal(Goal0, Goal, !GoalIdMap,
         !NeededVars, !ToDeleteVars).
 
 :- pred opt_format_call_sites_in_disj(
     list(hlds_goal)::in, list(hlds_goal)::out,
-    fc_goal_path_map::in, fc_goal_path_map::out,
+    fc_goal_id_map::in, fc_goal_id_map::out,
     set_tree234(prog_var)::in,
     list(set_tree234(prog_var))::in, list(set_tree234(prog_var))::out,
     set_tree234(prog_var)::in,
     list(set_tree234(prog_var))::in, list(set_tree234(prog_var))::out)
     is det.
 
-opt_format_call_sites_in_disj([], [], !GoalPathMap,
+opt_format_call_sites_in_disj([], [], !GoalIdMap,
         _, !NeededVarsSets, _, !ToDeleteVarsSets).
-opt_format_call_sites_in_disj([Goal0 | Goals0], [Goal | Goals], !GoalPathMap,
+opt_format_call_sites_in_disj([Goal0 | Goals0], [Goal | Goals], !GoalIdMap,
         NeededVars0, !NeededVarsSets, ToDeleteVars0, !ToDeleteVarsSets) :-
     % The order of traversal does not matter for disjunctions, since the
     % disjuncts are independent. This order is more efficient.
-    opt_format_call_sites_in_goal(Goal0, Goal, !GoalPathMap,
+    opt_format_call_sites_in_goal(Goal0, Goal, !GoalIdMap,
         NeededVars0, NeededVars, ToDeleteVars0, ToDeleteVars),
     !:NeededVarsSets = [NeededVars | !.NeededVarsSets],
     !:ToDeleteVarsSets = [ToDeleteVars | !.ToDeleteVarsSets],
-    opt_format_call_sites_in_disj(Goals0, Goals, !GoalPathMap,
+    opt_format_call_sites_in_disj(Goals0, Goals, !GoalIdMap,
         NeededVars0, !NeededVarsSets, ToDeleteVars0, !ToDeleteVarsSets).
 
 :- pred opt_format_call_sites_in_switch(list(case)::in, list(case)::out,
-    fc_goal_path_map::in, fc_goal_path_map::out,
+    fc_goal_id_map::in, fc_goal_id_map::out,
     set_tree234(prog_var)::in,
     list(set_tree234(prog_var))::in, list(set_tree234(prog_var))::out,
     set_tree234(prog_var)::in,
     list(set_tree234(prog_var))::in, list(set_tree234(prog_var))::out)
     is det.
 
-opt_format_call_sites_in_switch([], [], !GoalPathMap,
+opt_format_call_sites_in_switch([], [], !GoalIdMap,
         _, !NeededVarsSets, _, !ToDeleteVarsSets).
-opt_format_call_sites_in_switch([Case0 | Cases0], [Case | Cases], !GoalPathMap,
+opt_format_call_sites_in_switch([Case0 | Cases0], [Case | Cases], !GoalIdMap,
         NeededVars0, !NeededVarsSets, ToDeleteVars0, !ToDeleteVarsSets) :-
     % The order of traversal does not matter for switches, since the
     % switch arms are independent. This order is more efficient.
     Case0 = case(FirstConsId, LaterConsIds, Goal0),
-    opt_format_call_sites_in_goal(Goal0, Goal, !GoalPathMap,
+    opt_format_call_sites_in_goal(Goal0, Goal, !GoalIdMap,
         NeededVars0, NeededVars, ToDeleteVars0, ToDeleteVars),
     !:NeededVarsSets = [NeededVars | !.NeededVarsSets],
     !:ToDeleteVarsSets = [ToDeleteVars | !.ToDeleteVarsSets],
     Case = case(FirstConsId, LaterConsIds, Goal),
-    opt_format_call_sites_in_switch(Cases0, Cases, !GoalPathMap,
+    opt_format_call_sites_in_switch(Cases0, Cases, !GoalIdMap,
         NeededVars0, !NeededVarsSets, ToDeleteVars0, !ToDeleteVarsSets).
 
 %-----------------------------------------------------------------------------%
Index: compiler/goal_path.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_path.m,v
retrieving revision 1.56
diff -u -r1.56 goal_path.m
--- compiler/goal_path.m	15 Dec 2010 06:29:36 -0000	1.56
+++ compiler/goal_path.m	20 Dec 2010 04:39:44 -0000
@@ -9,49 +9,109 @@
 % File: goal_path.m.
 % Main author: zs.
 %
-% This module looks after goal paths, which associate each goal with its
-% position in a procedure definition,
+% This module looks after goal ids, which give every goal a unique id within
+% its procedure definition, and goal paths, which map each goal id to its
+% goal's position in the procedure definition.
 %
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- module check_hlds.goal_path.
+:- module hlds.goal_path.
 :- interface.
 
-:- import_module hlds.
+:- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_goal.
-:- import_module hlds.hlds_pred.
 :- import_module hlds.hlds_module.
+:- import_module hlds.hlds_pred.
+:- import_module mdbcomp.program_representation.
 :- import_module parse_tree.
 :- import_module parse_tree.prog_data.
 
-:- import_module bool.
+:- import_module bimap.
+:- import_module map.
+
+:- type containing_goal
+    --->    whole_body_goal
+            % This goal is the entire body of its procedure.
+    ;       containing_goal(goal_id, goal_path_step).
+            % This goal is an contained immediately inside the larger goal
+            % identified by the goal_id, from which you need to take the
+            % given goal_path step to get to this goal.
+            %
+            % The goal_id of the containing goal is guaranteed to be always
+            % less than the goal_id of this goal.
+
+:- type containing_goal_map == map(goal_id, containing_goal).
+:- type goal_forward_path_map == map(goal_id, forward_goal_path).
+:- type goal_reverse_path_map == map(goal_id, reverse_goal_path).
+:- type goal_reverse_path_bimap == bimap(goal_id, reverse_goal_path).
+
+    % goal_id_inside(ContainingGoalMap, GoalIdA, GoalIdB):
+    %
+    % Succeeds if GoalIdB denotes a goal *inside* the goal denoted by GoalIdA.
+    % (It considers a goal to be inside itself.)
+    %
+:- pred goal_id_inside(containing_goal_map::in,
+    goal_id::in, goal_id::in) is semidet.
+
+    % Convert a goal_id to a forward goal path.
+    %
+:- func goal_id_to_forward_path(containing_goal_map, goal_id) =
+    forward_goal_path.
+
+    % Convert a goal_id to a reverse goal path.
+    %
+:- func goal_id_to_reverse_path(containing_goal_map, goal_id) =
+    reverse_goal_path.
+
+    % Given a containing_goal_map, create a map that maps each goal_id in it
+    % to a forwward goal path.
+    %
+:- func create_forward_goal_path_map(containing_goal_map) =
+    goal_forward_path_map.
+
+    % Given a containing_goal_map, create a map that maps each goal_id in it
+    % to a reverse goal path.
+    %
+:- func create_reverse_goal_path_map(containing_goal_map) =
+    goal_reverse_path_map.
+
+    % Given a containing_goal_map, create a map that maps each goal_id in it
+    % to a reverse goal path, and back.
+    %
+:- func create_reverse_goal_path_bimap(containing_goal_map) =
+    goal_reverse_path_bimap.
 
 %-----------------------------------------------------------------------------%
 
-    % IMPORTANT: the type constraint_id in hlds_data.m makes use of
-    % goal_paths to identify constraints between the typechecking pass
-    % and the polymorphism pass. For this reason, goal paths should not
-    % be recalculated anywhere between these two passes. See the XXX
-    % comment near the declaration of constraint_id.
+    % IMPORTANT: the type constraint_id in hlds_data.m makes use of goal ids
+    % to identify goals that impose constraints between the typechecking pass
+    % and the polymorphism pass. For this reason, goal ids should not be
+    % recalculated anywhere between these two passes. See the XXX comment
+    % near the declaration of constraint_id.
     %
-:- pred fill_goal_path_slots(module_info::in, proc_info::in, proc_info::out)
-    is det.
+:- pred fill_goal_id_slots_in_proc(module_info::in,
+    containing_goal_map::out, proc_info::in, proc_info::out) is det.
 
-    % Fill in the goal_paths for goals in the clauses_info of the predicate.
-    % Clauses are given goal paths `disj(1)', ...,  `disj(N)'. If the bool
-    % argument is true then the goal paths are stored in a form where any
-    % prefix consisting of `disj(_)', `neg', `exist(_)' and `ite_else'
-    % components is removed. This is used to optimise the constraint-based
-    % mode analysis where the instantiatedness of a variable at such a goal
-    % path is always equivalent to its instantiatedness at the parent goal
-    % path.
+:- pred fill_goal_id_slots_in_proc_body(module_info::in, vartypes::in,
+    containing_goal_map::out, hlds_goal::in, hlds_goal::out) is det.
+
+    % Fill in the goal_ids for goals in the clauses_info.
+    % Clauses are given goal paths `disj(1)', ...,  `disj(N)'.
     %
-:- pred fill_goal_path_slots_in_clauses(module_info::in, bool::in,
-    pred_info::in, pred_info::out) is det.
+:- pred fill_goal_id_slots_in_clauses(module_info::in,
+    containing_goal_map::out, clauses_info::in, clauses_info::out) is det.
 
-:- pred fill_goal_path_slots_in_goal(hlds_goal::in, vartypes::in,
-    module_info::in, hlds_goal::out) is det.
+%-----------------------------------------------------------------------------%
+
+    % Fill in the goal path slots in the given procedure.
+    % This predicate is here ONLY to support the RBMM and GTGC modules,
+    % which are hard to transition to make use of goal_ids instead;
+    % all new code should instead use the predicates above that fill in
+    % the goal_id slots instead.
+    %
+:- pred fill_goal_path_slots_in_proc(module_info::in,
+    proc_info::in, proc_info::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -59,98 +119,364 @@
 :- implementation.
 
 :- import_module check_hlds.type_util.
-:- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_goal.
 :- import_module mdbcomp.
-:- import_module mdbcomp.program_representation.
 :- import_module parse_tree.prog_data.
 
+:- import_module assoc_list.
 :- import_module cord.
 :- import_module int.
 :- import_module list.
-:- import_module map.
 :- import_module maybe.
 :- import_module pair.
 :- import_module require.
+:- import_module svbimap.
+:- import_module svmap.
+
+%-----------------------------------------------------------------------------%
+
+goal_id_inside(ContainingGoalId, GoalIdA, GoalIdB) :-
+    (
+        GoalIdB = GoalIdA
+    ;
+        map.lookup(ContainingGoalId, GoalIdB, GoalContainingB),
+        GoalContainingB = containing_goal(ParentGoalIdB, _),
+        goal_id_inside(ContainingGoalId, GoalIdA, ParentGoalIdB)
+    ).
+
+goal_id_to_forward_path(ContainingGoalMap, GoalId) = GoalPath :-
+    StepsCord = goal_id_to_steps(ContainingGoalMap, GoalId),
+    Steps = cord.list(StepsCord),
+    GoalPath = fgp(Steps).
+
+goal_id_to_reverse_path(ContainingGoalMap, GoalId) = GoalPath :-
+    StepsCord = goal_id_to_steps(ContainingGoalMap, GoalId),
+    Steps = cord.list(StepsCord),
+    list.reverse(Steps, RevSteps),
+    GoalPath = rgp(RevSteps).
+
+:- func goal_id_to_steps(containing_goal_map, goal_id) =
+    cord(goal_path_step).
+
+goal_id_to_steps(ContainingGoalMap, GoalId) = Steps :-
+    map.lookup(ContainingGoalMap, GoalId, ContainingGoal),
+    (
+        ContainingGoal = whole_body_goal,
+        Steps = cord.empty
+    ;
+        ContainingGoal = containing_goal(ParentGoalId, LastStep),
+        EarlierSteps = goal_id_to_steps(ContainingGoalMap, ParentGoalId),
+        Steps = cord.snoc(EarlierSteps, LastStep)
+    ).
+
+create_forward_goal_path_map(ContainingGoalMap) = ForwardGoalPathMap :-
+    ReverseGoalPathMap = create_reverse_goal_path_map(ContainingGoalMap),
+    map.map_values_only(rgp_to_fgp, ReverseGoalPathMap, ForwardGoalPathMap).
+
+:- pred rgp_to_fgp(reverse_goal_path::in, forward_goal_path::out) is det.
+
+rgp_to_fgp(rgp(RevSteps), fgp(Steps)) :-
+    list.reverse(RevSteps, Steps).
+
+create_reverse_goal_path_map(ContainingGoalMap) = ReverseGoalPathMap :-
+    map.to_assoc_list(ContainingGoalMap, ContainingGoalList),
+    create_reverse_goal_path_map_2(ContainingGoalList,
+        map.init, ReverseGoalPathMap).
+
+:- pred create_reverse_goal_path_map_2(
+    assoc_list(goal_id, containing_goal)::in,
+    map(goal_id, reverse_goal_path)::in, map(goal_id, reverse_goal_path)::out)
+    is det.
+
+create_reverse_goal_path_map_2([], !ReverseGoalPathMap).
+create_reverse_goal_path_map_2([Head | Tail], !ReverseGoalPathMap) :-
+    Head = GoalId - ContainingGoal,
+    (
+        ContainingGoal = whole_body_goal,
+        GoalReversePath = rgp([])
+    ;
+        ContainingGoal = containing_goal(ContainingGoalId, Step),
+        map.lookup(!.ReverseGoalPathMap, ContainingGoalId,
+            ContainingGoalReversePath),
+        ContainingGoalReversePath = rgp(ContainingGoalReverseSteps),
+        GoalReverseSteps = [Step | ContainingGoalReverseSteps],
+        GoalReversePath = rgp(GoalReverseSteps)
+    ),
+    svmap.det_insert(GoalId, GoalReversePath, !ReverseGoalPathMap),
+    create_reverse_goal_path_map_2(Tail, !ReverseGoalPathMap).
+
+create_reverse_goal_path_bimap(ContainingGoalMap) = ReverseGoalPathBiMap :-
+    map.to_assoc_list(ContainingGoalMap, ContainingGoalList),
+    create_reverse_goal_path_bimap_2(ContainingGoalList,
+        bimap.init, ReverseGoalPathBiMap).
+
+:- pred create_reverse_goal_path_bimap_2(
+    assoc_list(goal_id, containing_goal)::in,
+    bimap(goal_id, reverse_goal_path)::in,
+    bimap(goal_id, reverse_goal_path)::out) is det.
+
+create_reverse_goal_path_bimap_2([], !ReverseGoalPathBiMap).
+create_reverse_goal_path_bimap_2([Head | Tail], !ReverseGoalPathBiMap) :-
+    Head = GoalId - ContainingGoal,
+    (
+        ContainingGoal = whole_body_goal,
+        GoalReversePath = rgp([])
+    ;
+        ContainingGoal = containing_goal(ContainingGoalId, Step),
+        bimap.lookup(!.ReverseGoalPathBiMap, ContainingGoalId,
+            ContainingGoalReversePath),
+        ContainingGoalReversePath = rgp(ContainingGoalReverseSteps),
+        GoalReverseSteps = [Step | ContainingGoalReverseSteps],
+        GoalReversePath = rgp(GoalReverseSteps)
+    ),
+    svbimap.det_insert(GoalId, GoalReversePath, !ReverseGoalPathBiMap),
+    create_reverse_goal_path_bimap_2(Tail, !ReverseGoalPathBiMap).
 
 %-----------------------------------------------------------------------------%
 
 :- type slot_info
     --->    slot_info(
-                slot_info_vartypes                  :: vartypes,
                 slot_info_module_info               :: module_info,
-                slot_info_omit_mode_equiv_prefix    :: bool
+                slot_info_vartypes                  :: vartypes
             ).
 
-fill_goal_path_slots(ModuleInfo, !Proc) :-
-    proc_info_get_goal(!.Proc, Goal0),
-    proc_info_get_vartypes(!.Proc, VarTypes),
-    fill_goal_path_slots_in_goal(Goal0, VarTypes, ModuleInfo, Goal),
-    proc_info_set_goal(Goal, !Proc).
+fill_goal_id_slots_in_proc(ModuleInfo, ContainingGoalMap, !ProcInfo) :-
+    proc_info_get_vartypes(!.ProcInfo, VarTypes),
+    proc_info_get_goal(!.ProcInfo, Goal0),
+    fill_goal_id_slots_in_proc_body(ModuleInfo, VarTypes,
+        ContainingGoalMap, Goal0, Goal),
+    proc_info_set_goal(Goal, !ProcInfo).
+
+fill_goal_id_slots_in_proc_body(ModuleInfo, VarTypes, ContainingGoalMap,
+        Goal0, Goal) :-
+    SlotInfo = slot_info(ModuleInfo, VarTypes),
+    fill_goal_id_slots(SlotInfo, whole_body_goal, 0, _,
+        map.init, ContainingGoalMap, Goal0, Goal).
 
-fill_goal_path_slots_in_clauses(ModuleInfo, OmitModeEquivPrefix, !PredInfo) :-
-    pred_info_get_clauses_info(!.PredInfo, ClausesInfo0),
+fill_goal_id_slots_in_clauses(ModuleInfo, ContainingGoalMap,
+        ClausesInfo0, ClausesInfo) :-
     clauses_info_get_clauses_rep(ClausesInfo0, ClausesRep0, ItemNumbers),
     get_clause_list(ClausesRep0, Clauses0),
     clauses_info_get_vartypes(ClausesInfo0, VarTypes),
-    SlotInfo = slot_info(VarTypes, ModuleInfo, OmitModeEquivPrefix),
-    list.map_foldl(fill_slots_in_clause(SlotInfo), Clauses0, Clauses, 1, _),
+    SlotInfo = slot_info(ModuleInfo, VarTypes),
+    list.map_foldl3(fill_slots_in_clause(SlotInfo),
+        Clauses0, Clauses, 1, _, 1, _, map.init, ContainingGoalMap),
     set_clause_list(Clauses, ClausesRep),
     clauses_info_set_clauses_rep(ClausesRep, ItemNumbers,
-        ClausesInfo0, ClausesInfo),
-    pred_info_set_clauses_info(ClausesInfo, !PredInfo).
+        ClausesInfo0, ClausesInfo).
 
 :- pred fill_slots_in_clause(slot_info::in, clause::in, clause::out,
-    int::in, int::out) is det.
+    int::in, int::out, int::in, int::out,
+    containing_goal_map::in, containing_goal_map::out) is det.
 
-fill_slots_in_clause(SlotInfo, Clause0, Clause, ClauseNum, ClauseNum + 1) :-
+fill_slots_in_clause(SlotInfo, Clause0, Clause, !GoalNum, !ClauseNum,
+        !ContainingGoalMap) :-
     Clause0 = clause(ProcIds, Goal0, Lang, Context),
-    fill_goal_slots(singleton_goal_path(step_disj(ClauseNum)), SlotInfo,
+    ContainingGoal = containing_goal(whole_body_goal_id,
+        step_disj(!.ClauseNum)),
+    !:ClauseNum = !.ClauseNum + 1,
+    fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
         Goal0, Goal),
     Clause = clause(ProcIds, Goal, Lang, Context).
 
-fill_goal_path_slots_in_goal(Goal0, VarTypes, ModuleInfo, Goal) :-
-    SlotInfo = slot_info(VarTypes, ModuleInfo, no),
-    fill_goal_slots(empty_goal_path, SlotInfo, Goal0, Goal).
+fill_goal_path_slots_in_proc(ModuleInfo, !Proc) :-
+    proc_info_get_goal(!.Proc, Goal0),
+    proc_info_get_vartypes(!.Proc, VarTypes),
+    SlotInfo = slot_info(ModuleInfo, VarTypes),
+    fill_goal_path_slots([], SlotInfo, Goal0, Goal),
+    proc_info_set_goal(Goal, !Proc).
+
+%-----------------------------------------------------------------------------%
 
-:- pred fill_goal_slots(goal_path::in, slot_info::in,
+:- pred fill_goal_id_slots(slot_info::in, containing_goal::in,
+    int::in, int::out, containing_goal_map::in, containing_goal_map::out,
     hlds_goal::in, hlds_goal::out) is det.
 
-fill_goal_slots(Path0, SlotInfo,
-        hlds_goal(Expr0, Info0), hlds_goal(Expr, Info)) :-
-    OmitModeEquivPrefix = SlotInfo ^ slot_info_omit_mode_equiv_prefix,
+fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
+        Goal0, Goal) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
+    GoalId = goal_id(!.GoalNum),
+    !:GoalNum = !.GoalNum + 1,
+    goal_info_set_goal_id(GoalId, GoalInfo0, GoalInfo),
+    svmap.det_insert(GoalId, ContainingGoal, !ContainingGoalMap),
     (
-        OmitModeEquivPrefix = yes,
-        PathSteps0 = goal_path_to_list(Path0),
-        list.takewhile(mode_equiv_step, PathSteps0, _, PathSteps),
-        Path = list_to_goal_path(PathSteps)
+        ( GoalExpr0 = plain_call(_, _, _, _, _, _)
+        ; GoalExpr0 = generic_call(_, _, _, _)
+        ; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
+        ),
+        GoalExpr = GoalExpr0
+    ;
+        GoalExpr0 = unify(LHS, RHS0, Mode, Kind, Context),
+        (
+            RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
+                NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal0),
+            fill_goal_id_slots(SlotInfo,
+                containing_goal(GoalId, step_lambda),
+                !GoalNum, !ContainingGoalMap, LambdaGoal0, LambdaGoal),
+            RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
+                NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal),
+            GoalExpr = unify(LHS, RHS,  Mode, Kind, Context)
+        ;
+            ( RHS0 = rhs_var(_)
+            ; RHS0 = rhs_functor(_, _, _)
+            ),
+            GoalExpr = GoalExpr0
+        )
+    ;
+        GoalExpr0 = conj(ConjType, Goals0),
+        fill_conj_id_slots(SlotInfo, GoalId, 0, !GoalNum, !ContainingGoalMap,
+            Goals0, Goals),
+        GoalExpr = conj(ConjType, Goals)
+    ;
+        GoalExpr0 = disj(Goals0),
+        fill_disj_id_slots(SlotInfo, GoalId, 0, !GoalNum, !ContainingGoalMap,
+            Goals0, Goals),
+        GoalExpr = disj(Goals)
+    ;
+        GoalExpr0 = switch(Var, CanFail, Cases0),
+        VarTypes = SlotInfo ^ slot_info_vartypes,
+        ModuleInfo = SlotInfo ^ slot_info_module_info,
+        map.lookup(VarTypes, Var, Type),
+        ( switch_type_num_functors(ModuleInfo, Type, NumFunctors) ->
+            MaybeNumFunctors = yes(NumFunctors)
+        ;
+            MaybeNumFunctors = no
+        ),
+        fill_switch_id_slots(SlotInfo, GoalId, 0, MaybeNumFunctors, !GoalNum,
+            !ContainingGoalMap, Cases0, Cases),
+        GoalExpr = switch(Var, CanFail, Cases)
+    ;
+        GoalExpr0 = negation(SubGoal0),
+        fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_neg),
+            !GoalNum, !ContainingGoalMap, SubGoal0, SubGoal),
+        GoalExpr = negation(SubGoal)
     ;
-        OmitModeEquivPrefix = no,
-        Path = Path0
+        GoalExpr0 = scope(Reason, SubGoal0),
+        % We should consider not filling in the goal path slots inside
+        % from_ground_term_construct scopes, since we do not use them
+        % for anything.
+        SubGoal0 = hlds_goal(_, InnerInfo),
+        OuterDetism = goal_info_get_determinism(GoalInfo),
+        InnerDetism = goal_info_get_determinism(InnerInfo),
+        ( InnerDetism = OuterDetism ->
+            MaybeCut = scope_is_no_cut
+        ;
+            MaybeCut = scope_is_cut
+        ),
+        fill_goal_id_slots(SlotInfo,
+            containing_goal(GoalId, step_scope(MaybeCut)),
+            !GoalNum, !ContainingGoalMap, SubGoal0, SubGoal),
+        GoalExpr = scope(Reason, SubGoal)
+    ;
+        GoalExpr0 = if_then_else(A, Cond0, Then0, Else0),
+        fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_ite_cond),
+            !GoalNum, !ContainingGoalMap, Cond0, Cond),
+        fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_ite_then),
+            !GoalNum, !ContainingGoalMap, Then0, Then),
+        fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_ite_else),
+            !GoalNum, !ContainingGoalMap, Else0, Else),
+        GoalExpr = if_then_else(A, Cond, Then, Else)
+    ;
+        GoalExpr0 = shorthand(ShortHand0),
+        (
+            ShortHand0 = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
+                MainGoal0, OrElseGoals0, OrElseInners),
+            fill_goal_id_slots(SlotInfo,
+                containing_goal(GoalId, step_atomic_main),
+                !GoalNum, !ContainingGoalMap, MainGoal0, MainGoal),
+            fill_orelse_id_slots(SlotInfo, GoalId, 0, !GoalNum,
+                !ContainingGoalMap, OrElseGoals0, OrElseGoals),
+            ShortHand = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
+                MainGoal, OrElseGoals, OrElseInners)
+        ;
+            ShortHand0 = try_goal(MaybeIO, ResultVar, SubGoal0),
+            fill_goal_id_slots(SlotInfo, containing_goal(GoalId, step_try),
+                !GoalNum, !ContainingGoalMap, SubGoal0, SubGoal),
+            ShortHand = try_goal(MaybeIO, ResultVar, SubGoal)
+        ;
+            ShortHand0 = bi_implication(_, _),
+            % These should have been expanded out by now.
+            unexpected(this_file, "fill_goal_id_slots: bi_implication")
+        ),
+        GoalExpr = shorthand(ShortHand)
     ),
-    goal_info_set_goal_path(Path, Info0, Info),
-    fill_expr_slots(Info, Path0, SlotInfo, Expr0, Expr).
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
-:- pred mode_equiv_step(goal_path_step::in) is semidet.
+:- pred fill_conj_id_slots(slot_info::in, goal_id::in, int::in,
+    int::in, int::out, containing_goal_map::in, containing_goal_map::out,
+    list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
-mode_equiv_step(Step) :-
-    ( Step = step_disj(_)
-    ; Step = step_neg
-    ; Step = step_scope(_)
-    ; Step = step_ite_else
-    ).
+fill_conj_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
+fill_conj_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
+        [Goal0 | Goals0], [Goal | Goals]) :-
+    N1 = N0 + 1,
+    ContainingGoal = containing_goal(GoalId, step_conj(N1)),
+    fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
+        Goal0, Goal),
+    fill_conj_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
+        Goals0, Goals).
+
+:- pred fill_disj_id_slots(slot_info::in, goal_id::in, int::in,
+    int::in, int::out, containing_goal_map::in, containing_goal_map::out,
+    list(hlds_goal)::in, list(hlds_goal)::out) is det.
+
+fill_disj_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
+fill_disj_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
+        [Goal0 | Goals0], [Goal | Goals]) :-
+    N1 = N0 + 1,
+    ContainingGoal = containing_goal(GoalId, step_disj(N1)),
+    fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
+        Goal0, Goal),
+    fill_disj_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
+        Goals0, Goals).
+
+:- pred fill_switch_id_slots(slot_info::in, goal_id::in,
+    int::in, maybe(int)::in, int::in, int::out,
+    containing_goal_map::in, containing_goal_map::out,
+    list(case)::in, list(case)::out) is det.
+
+fill_switch_id_slots(_, _, _, _, !GoalNum, !ContainingGoalMap, [], []).
+fill_switch_id_slots(SlotInfo, GoalId, N0, MaybeNumFunctors, 
+        !GoalNum, !ContainingGoalMap, [Case0 | Cases0], [Case | Cases]) :-
+    Case0 = case(MainConsId, OtherConsIds, Goal0),
+    N1 = N0 + 1,
+    ContainingGoal =
+        containing_goal(GoalId, step_switch(N1, MaybeNumFunctors)),
+    fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
+        Goal0, Goal),
+    Case = case(MainConsId, OtherConsIds, Goal),
+    fill_switch_id_slots(SlotInfo, GoalId, N1, MaybeNumFunctors,
+        !GoalNum, !ContainingGoalMap, Cases0, Cases).
+
+:- pred fill_orelse_id_slots(slot_info::in, goal_id::in, int::in,
+    int::in, int::out, containing_goal_map::in, containing_goal_map::out,
+    list(hlds_goal)::in, list(hlds_goal)::out) is det.
+
+fill_orelse_id_slots(_, _, _, !GoalNum, !ContainingGoalMap, [], []).
+fill_orelse_id_slots(SlotInfo, GoalId, N0, !GoalNum, !ContainingGoalMap,
+        [Goal0 | Goals0], [Goal | Goals]) :-
+    N1 = N0 + 1,
+    ContainingGoal = containing_goal(GoalId, step_atomic_orelse(N1)),
+    fill_goal_id_slots(SlotInfo, ContainingGoal, !GoalNum, !ContainingGoalMap,
+        Goal0, Goal),
+    fill_orelse_id_slots(SlotInfo, GoalId, N1, !GoalNum, !ContainingGoalMap,
+        Goals0, Goals).
 
-:- pred fill_expr_slots(hlds_goal_info::in, goal_path::in, slot_info::in,
-    hlds_goal_expr::in, hlds_goal_expr::out) is det.
+%-----------------------------------------------------------------------------%
+
+:- pred fill_goal_path_slots(list(goal_path_step)::in, slot_info::in,
+    hlds_goal::in, hlds_goal::out) is det.
 
-fill_expr_slots(GoalInfo, Path0, SlotInfo, GoalExpr0, GoalExpr) :-
+fill_goal_path_slots(RevSteps0, SlotInfo, Goal0, Goal) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
+    goal_info_set_reverse_goal_path(rgp(RevSteps0), GoalInfo0, GoalInfo),
     (
         GoalExpr0 = conj(ConjType, Goals0),
-        fill_conj_slots(Path0, 0, SlotInfo, Goals0, Goals),
+        fill_conj_path_slots(RevSteps0, 0, SlotInfo, Goals0, Goals),
         GoalExpr = conj(ConjType, Goals)
     ;
         GoalExpr0 = disj(Goals0),
-        fill_disj_slots(Path0, 0, SlotInfo, Goals0, Goals),
+        fill_disj_path_slots(RevSteps0, 0, SlotInfo, Goals0, Goals),
         GoalExpr = disj(Goals)
     ;
         GoalExpr0 = switch(Var, CanFail, Cases0),
@@ -162,11 +488,12 @@
         ;
             MaybeNumFunctors = no
         ),
-        fill_switch_slots(Path0, 0, MaybeNumFunctors, SlotInfo, Cases0, Cases),
+        fill_switch_path_slots(RevSteps0, 0, MaybeNumFunctors, SlotInfo,
+            Cases0, Cases),
         GoalExpr = switch(Var, CanFail, Cases)
     ;
         GoalExpr0 = negation(SubGoal0),
-        fill_goal_slots(goal_path_add_at_end(Path0, step_neg), SlotInfo,
+        fill_goal_path_slots([step_neg | RevSteps0], SlotInfo,
             SubGoal0, SubGoal),
         GoalExpr = negation(SubGoal)
     ;
@@ -182,24 +509,24 @@
         ;
             MaybeCut = scope_is_cut
         ),
-        fill_goal_slots(goal_path_add_at_end(Path0, step_scope(MaybeCut)),
-            SlotInfo, SubGoal0, SubGoal),
+        fill_goal_path_slots([step_scope(MaybeCut) | RevSteps0], SlotInfo,
+            SubGoal0, SubGoal),
         GoalExpr = scope(Reason, SubGoal)
     ;
-        GoalExpr0 = if_then_else(A, Cond0, Then0, Else0),
-        fill_goal_slots(goal_path_add_at_end(Path0, step_ite_cond), SlotInfo,
+        GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
+        fill_goal_path_slots([step_ite_cond | RevSteps0], SlotInfo,
             Cond0, Cond),
-        fill_goal_slots(goal_path_add_at_end(Path0, step_ite_then), SlotInfo,
+        fill_goal_path_slots([step_ite_then | RevSteps0], SlotInfo,
             Then0, Then),
-        fill_goal_slots(goal_path_add_at_end(Path0, step_ite_else), SlotInfo,
+        fill_goal_path_slots([step_ite_else | RevSteps0], SlotInfo,
             Else0, Else),
-        GoalExpr = if_then_else(A, Cond, Then, Else)
+        GoalExpr = if_then_else(Vars, Cond, Then, Else)
     ;
         GoalExpr0 = unify(LHS, RHS0, Mode, Kind, Context),
         (
             RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
                 NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal0),
-            fill_goal_slots(Path0, SlotInfo, LambdaGoal0, LambdaGoal),
+            fill_goal_path_slots(RevSteps0, SlotInfo, LambdaGoal0, LambdaGoal),
             RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
                 NonLocals, QuantVars, LambdaModes, Detism, LambdaGoal)
         ;
@@ -220,65 +547,72 @@
         (
             ShortHand0 = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
                 MainGoal0, OrElseGoals0, OrElseInners),
-            fill_goal_slots(goal_path_add_at_end(Path0, step_atomic_main), 
-                SlotInfo, MainGoal0, MainGoal),
-            fill_orelse_slots(Path0, 0, SlotInfo, OrElseGoals0, OrElseGoals),
+            fill_goal_path_slots([step_atomic_main | RevSteps0], SlotInfo,
+                MainGoal0, MainGoal),
+            fill_orelse_path_slots(RevSteps0, 0, SlotInfo,
+                OrElseGoals0, OrElseGoals),
             ShortHand = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
                 MainGoal, OrElseGoals, OrElseInners)
         ;
             ShortHand0 = try_goal(MaybeIO, ResultVar, SubGoal0),
-            fill_goal_slots(Path0, SlotInfo, SubGoal0, SubGoal),
+            fill_goal_path_slots(RevSteps0, SlotInfo, SubGoal0, SubGoal),
             ShortHand = try_goal(MaybeIO, ResultVar, SubGoal)
         ;
             ShortHand0 = bi_implication(_, _),
             % These should have been expanded out by now.
-            unexpected(this_file, "fill_expr_slots: unexpected bi_implication")
+            unexpected(this_file, "fill_goal_path_slots: bi_implication")
         ),
         GoalExpr = shorthand(ShortHand)
-    ).
+    ),
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
-:- pred fill_conj_slots(goal_path::in, int::in, slot_info::in,
+:- pred fill_conj_path_slots(list(goal_path_step)::in, int::in, slot_info::in,
     list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
-fill_conj_slots(_, _, _, [], []).
-fill_conj_slots(Path0, N0, SlotInfo, [Goal0 | Goals0], [Goal | Goals]) :-
+fill_conj_path_slots(_, _, _, [], []).
+fill_conj_path_slots(RevSteps0, N0, SlotInfo,
+        [Goal0 | Goals0], [Goal | Goals]) :-
     N1 = N0 + 1,
-    fill_goal_slots(goal_path_add_at_end(Path0, step_conj(N1)), SlotInfo, 
+    fill_goal_path_slots([step_conj(N1) | RevSteps0], SlotInfo, 
         Goal0, Goal),
-    fill_conj_slots(Path0, N1, SlotInfo, Goals0, Goals).
+    fill_conj_path_slots(RevSteps0, N1, SlotInfo, Goals0, Goals).
 
-:- pred fill_disj_slots(goal_path::in, int::in, slot_info::in,
+:- pred fill_disj_path_slots(list(goal_path_step)::in, int::in, slot_info::in,
     list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
-fill_disj_slots(_, _, _, [], []).
-fill_disj_slots(Path0, N0, SlotInfo, [Goal0 | Goals0], [Goal | Goals]) :-
+fill_disj_path_slots(_, _, _, [], []).
+fill_disj_path_slots(RevSteps0, N0, SlotInfo,
+        [Goal0 | Goals0], [Goal | Goals]) :-
     N1 = N0 + 1,
-    fill_goal_slots(goal_path_add_at_end(Path0, step_disj(N1)), SlotInfo, 
+    fill_goal_path_slots([step_disj(N1) | RevSteps0], SlotInfo, 
         Goal0, Goal),
-    fill_disj_slots(Path0, N1, SlotInfo, Goals0, Goals).
+    fill_disj_path_slots(RevSteps0, N1, SlotInfo, Goals0, Goals).
 
-:- pred fill_switch_slots(goal_path::in, int::in, maybe(int)::in,
-    slot_info::in, list(case)::in, list(case)::out) is det.
+:- pred fill_switch_path_slots(list(goal_path_step)::in,
+    int::in, maybe(int)::in, slot_info::in,
+    list(case)::in, list(case)::out) is det.
 
-fill_switch_slots(_, _, _, _, [], []).
-fill_switch_slots(Path0, N0, MaybeNumFunctors, SlotInfo,
+fill_switch_path_slots(_, _, _, _, [], []).
+fill_switch_path_slots(RevSteps0, N0, MaybeNumFunctors, SlotInfo,
         [Case0 | Cases0], [Case | Cases]) :-
     Case0 = case(MainConsId, OtherConsIds, Goal0),
     N1 = N0 + 1,
-    CasePath = goal_path_add_at_end(Path0, step_switch(N1, MaybeNumFunctors)),
-    fill_goal_slots(CasePath, SlotInfo, Goal0, Goal),
+    fill_goal_path_slots([step_switch(N1, MaybeNumFunctors) | RevSteps0],
+        SlotInfo, Goal0, Goal),
     Case = case(MainConsId, OtherConsIds, Goal),
-    fill_switch_slots(Path0, N1, MaybeNumFunctors, SlotInfo, Cases0, Cases).
+    fill_switch_path_slots(RevSteps0, N1, MaybeNumFunctors, SlotInfo,
+        Cases0, Cases).
 
-:- pred fill_orelse_slots(goal_path::in, int::in, slot_info::in,
-    list(hlds_goal)::in, list(hlds_goal)::out) is det.
+:- pred fill_orelse_path_slots(list(goal_path_step)::in, int::in,
+    slot_info::in, list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
-fill_orelse_slots(_, _, _, [], []).
-fill_orelse_slots(Path0, N0, SlotInfo, [Goal0 | Goals0], [Goal | Goals]) :-
+fill_orelse_path_slots(_, _, _, [], []).
+fill_orelse_path_slots(RevSteps0, N0, SlotInfo,
+        [Goal0 | Goals0], [Goal | Goals]) :-
     N1 = N0 + 1,
-    fill_goal_slots(goal_path_add_at_end(Path0, step_atomic_orelse(N1)),
-        SlotInfo, Goal0, Goal),
-    fill_orelse_slots(Path0, N1, SlotInfo, Goals0, Goals).
+    fill_goal_path_slots([step_atomic_orelse(N1) | RevSteps0], SlotInfo,
+        Goal0, Goal),
+    fill_orelse_path_slots(RevSteps0, N1, SlotInfo, Goals0, Goals).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.175
diff -u -r1.175 goal_util.m
--- compiler/goal_util.m	15 Dec 2010 06:29:36 -0000	1.175
+++ compiler/goal_util.m	15 Dec 2010 06:33:16 -0000
@@ -258,12 +258,6 @@
     cons_id::in, hlds_goal::out, prog_varset::in, prog_varset::out,
     vartypes::in, vartypes::out, module_info::in, module_info::out) is det.
 
-    % Transform an if-then-else into ( Cond, Then ; \+ Cond, Else ),
-    % since magic.m and rl_gen.m don't handle if-then-elses.
-    %
-:- pred if_then_else_to_disjunction(hlds_goal::in, hlds_goal::in,
-    hlds_goal::in, hlds_goal_info::in, hlds_goal_expr::out) is det.
-
 %-----------------------------------------------------------------------------%
 
     % Flatten a list of goals of a conjunction.
@@ -418,29 +412,27 @@
     % order argument is no then the result is no.
     %
 :- 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.
+    pred(hlds_goal, maybe_error(hlds_goal))::in(pred(in, out) is det),
+    forward_goal_path::in, hlds_goal::in, maybe_transformed_goal::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.
+    pred(instmap, hlds_goal, maybe_error(hlds_goal))::
+        in(pred(in, in, out) is det), 
+    forward_goal_path::in, instmap::in, hlds_goal::in,
+    maybe_transformed_goal::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
     % already been transformed.
     %
-:- pred transform_all_goals(pred(hlds_goal, hlds_goal), hlds_goal, hlds_goal).
-:- mode transform_all_goals(pred(in, out) is det, in, out) is det.
+:- pred transform_all_goals(
+    pred(hlds_goal, hlds_goal)::in(pred(in, out) is det),
+    hlds_goal::in, hlds_goal::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -1405,97 +1397,6 @@
 
 %-----------------------------------------------------------------------------%
 
-if_then_else_to_disjunction(Cond0, Then, Else, GoalInfo, Goal) :-
-    compute_disjunct_goal_info(Cond0, Then, GoalInfo, CondThenInfo),
-    conj_list_to_goal([Cond0, Then], CondThenInfo, CondThen),
-
-    Cond0 = hlds_goal(_, CondInfo0),
-    CondDetism0 = goal_info_get_determinism(CondInfo0),
-
-    determinism_components(CondDetism0, CondCanFail0, CondMaxSoln0),
-
-    % Add a commit inside the negation of the condition in the else branch
-    % if the condition can succeed more than once.
-    (
-        CondMaxSoln0 = at_most_many,
-        CondMaxSoln = at_most_one,
-        determinism_components(CondDetism, CondCanFail0, CondMaxSoln),
-        goal_info_set_determinism(CondDetism, CondInfo0, CondInfo),
-        Cond = hlds_goal(scope(commit(dont_force_pruning), Cond0), CondInfo)
-    ;
-        ( CondMaxSoln0 = at_most_zero
-        ; CondMaxSoln0 = at_most_one
-        ; CondMaxSoln0 = at_most_many_cc
-        ),
-        CondDetism = CondDetism0,
-        CondInfo = CondInfo0,
-        Cond = Cond0
-    ),
-
-    det_negation_det(CondDetism, MaybeNegCondDet),
-    (
-        MaybeNegCondDet = yes(NegCondDet1),
-        NegCondDet = NegCondDet1
-    ;
-        MaybeNegCondDet = no,
-        unexpected(this_file,
-            "if_then_else_to_disjunction: "
-                ++ "inappropriate determinism in a negation.")
-    ),
-    determinism_components(NegCondDet, _, NegCondMaxSoln),
-    (
-        NegCondMaxSoln = at_most_zero,
-        instmap_delta_init_unreachable(NegCondDelta)
-    ;
-        ( NegCondMaxSoln = at_most_one
-        ; NegCondMaxSoln = at_most_many
-        ; NegCondMaxSoln = at_most_many_cc
-        ),
-        instmap_delta_init_reachable(NegCondDelta)
-    ),
-    CondNonLocals = goal_info_get_nonlocals(CondInfo),
-    CondPurity = goal_info_get_purity(CondInfo),
-    goal_info_init(CondNonLocals, NegCondDelta, NegCondDet, CondPurity,
-        NegCondInfo),
-
-    compute_disjunct_goal_info(hlds_goal(negation(Cond), NegCondInfo), Else,
-        GoalInfo, NegCondElseInfo),
-    conj_list_to_goal([hlds_goal(negation(Cond), NegCondInfo), Else],
-        NegCondElseInfo, NegCondElse),
-    Goal = disj([CondThen, NegCondElse]).
-
-    % Compute a hlds_goal_info for a pair of conjoined goals.
-    %
-:- pred compute_disjunct_goal_info(hlds_goal::in, hlds_goal::in,
-    hlds_goal_info::in, hlds_goal_info::out) is det.
-
-compute_disjunct_goal_info(Goal1, Goal2, GoalInfo, CombinedInfo) :-
-    Goal1 = hlds_goal(_, GoalInfo1),
-    Goal2 = hlds_goal(_, GoalInfo2),
-
-    NonLocals1 = goal_info_get_nonlocals(GoalInfo1),
-    NonLocals2 = goal_info_get_nonlocals(GoalInfo2),
-    OuterNonLocals = goal_info_get_nonlocals(GoalInfo),
-    set.union(NonLocals1, NonLocals2, CombinedNonLocals0),
-    set.intersect(CombinedNonLocals0, OuterNonLocals, CombinedNonLocals),
-
-    Delta1 = goal_info_get_instmap_delta(GoalInfo1),
-    Delta2 = goal_info_get_instmap_delta(GoalInfo2),
-    instmap_delta_apply_instmap_delta(Delta1, Delta2, test_size,
-        CombinedDelta0),
-    instmap_delta_restrict(OuterNonLocals, CombinedDelta0, CombinedDelta),
-
-    Detism1 = goal_info_get_determinism(GoalInfo1),
-    Detism2 = goal_info_get_determinism(GoalInfo2),
-    det_conjunction_detism(Detism1, Detism2, CombinedDetism),
-
-    goal_list_purity([Goal1, Goal2], CombinedPurity),
-
-    goal_info_init(CombinedNonLocals, CombinedDelta,
-        CombinedDetism, CombinedPurity, CombinedInfo).
-
-%-----------------------------------------------------------------------------%
-
 flatten_conj([], []).
 flatten_conj([Goal | Goals0], Goals) :-
     flatten_conj(Goals0, Goals1),
@@ -1950,11 +1851,31 @@
 
 %-----------------------------------------------------------------------------%
 
-maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath0, Goal0,
-        MaybeGoal) :-
+maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+        Goal0, MaybeGoal) :-
+    TargetGoalPath = fgp(TargetGoalSteps),
+    maybe_transform_goal_at_goal_path_2(TransformP,
+        TargetGoalSteps, Goal0, MaybeGoal).
+
+maybe_transform_goal_at_goal_path_with_instmap(TransformP, TargetGoalPath,
+        InstMap, Goal0, MaybeGoal) :-
+    TargetGoalPath = fgp(TargetGoalSteps),
+    maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+        TargetGoalSteps, InstMap, Goal0, MaybeGoal).
+
+:- pred maybe_transform_goal_at_goal_path_2(
+    pred(hlds_goal, maybe_error(hlds_goal))::in(pred(in, out) is det),
+    list(goal_path_step)::in, hlds_goal::in, maybe_transformed_goal::out)
+    is det.
+
+maybe_transform_goal_at_goal_path_2(TransformP, TargetGoalSteps,
+        Goal0, MaybeGoal) :-
     (
-        goal_path_consable_remove_first(TargetGoalPath0, Step, TargetGoalPath)
-    ->
+        TargetGoalSteps = [],
+        TransformP(Goal0, MaybeGoal0),
+        maybe_error_to_maybe_transformed_goal(MaybeGoal0, MaybeGoal)
+    ;
+        TargetGoalSteps = [FirstStep | LaterSteps],
         GoalExpr0 = Goal0 ^ hlds_goal_expr,  
         (
             ( GoalExpr0 = unify(_, _, _, _, _) 
@@ -1967,10 +1888,10 @@
         ;
             GoalExpr0 = conj(ConjType, Conjs0),
             (
-                Step = step_conj(ConjNum),
+                FirstStep = step_conj(ConjNum),
                 list.index1(Conjs0, ConjNum, Conj0)
             ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     Conj0, MaybeConj),
                 (
                     MaybeConj = ok(Conj),
@@ -1989,10 +1910,10 @@
         ;
             GoalExpr0 = disj(Disjs0),
             (
-                Step = step_disj(DisjNum),
+                FirstStep = step_disj(DisjNum),
                 list.index1(Disjs0, DisjNum, Disj0)
             ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     Disj0, MaybeDisj),
                 (
                     MaybeDisj = ok(Disj),
@@ -2011,11 +1932,11 @@
         ;
             GoalExpr0 = switch(Var, CanFail, Cases0),
             (
-                Step = step_switch(CaseNum, _MaybeNumConstructors),
+                FirstStep = step_switch(CaseNum, _MaybeNumConstructors),
                 list.index1(Cases0, CaseNum, Case0)
             ->
                 CaseGoal0 = Case0 ^ case_goal,
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     CaseGoal0, MaybeCaseGoal),
                 (
                     MaybeCaseGoal = ok(CaseGoal),
@@ -2034,8 +1955,8 @@
             )
         ;
             GoalExpr0 = negation(SubGoal0),
-            ( Step = step_neg ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+            ( FirstStep = step_neg ->
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     SubGoal0, MaybeSubGoal),
                 (
                     MaybeSubGoal = ok(SubGoal),
@@ -2051,8 +1972,8 @@
             )
         ;
             GoalExpr0 = scope(Reason, SubGoal0),
-            ( Step = step_scope(_MaybeCut) ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+            ( FirstStep = step_scope(_MaybeCut) ->
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     SubGoal0, MaybeSubGoal),
                 (
                     MaybeSubGoal = ok(SubGoal),
@@ -2069,8 +1990,8 @@
             )
         ;
             GoalExpr0 = if_then_else(ExistVars, Cond0, Then0, Else0),
-            ( Step = step_ite_cond ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+            ( FirstStep = step_ite_cond ->
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     Cond0, MaybeCond),
                 (
                     MaybeCond = ok(Cond),
@@ -2082,8 +2003,8 @@
                     ),
                     MaybeGoal = MaybeCond 
                 )
-            ; Step = step_ite_then ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+            ; FirstStep = step_ite_then ->
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     Then0, MaybeThen),
                 (
                     MaybeThen = ok(Then),
@@ -2095,8 +2016,8 @@
                     ),
                     MaybeGoal = MaybeThen 
                 )
-            ; Step = step_ite_else ->
-                maybe_transform_goal_at_goal_path(TransformP, TargetGoalPath,
+            ; FirstStep = step_ite_else ->
+                maybe_transform_goal_at_goal_path_2(TransformP, LaterSteps,
                     Else0, MaybeElse),
                 (
                     MaybeElse = ok(Else),
@@ -2116,16 +2037,22 @@
             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,
+:- pred maybe_transform_goal_at_goal_path_with_instmap_2(
+    pred(instmap, hlds_goal, maybe_error(hlds_goal))::
+        in(pred(in, in, out) is det), 
+    list(goal_path_step)::in, instmap::in, hlds_goal::in,
+    maybe_transformed_goal::out) is det. 
+
+maybe_transform_goal_at_goal_path_with_instmap_2(TransformP, TargetGoalSteps,
         Instmap0, Goal0, MaybeGoal) :-
     (
-        goal_path_consable_remove_first(TargetGoalPath0, Step, TargetGoalPath)
-    ->
+        TargetGoalSteps = [],
+        TransformP(Instmap0, Goal0, MaybeGoal0),
+        maybe_error_to_maybe_transformed_goal(MaybeGoal0, MaybeGoal)
+    ;
+        TargetGoalSteps = [FirstStep | LaterSteps],
         GoalExpr0 = Goal0 ^ hlds_goal_expr,  
         (
             ( GoalExpr0 = unify(_, _, _, _, _) 
@@ -2138,7 +2065,7 @@
         ;
             GoalExpr0 = conj(ConjType, Conjs0),
             (
-                Step = step_conj(ConjNum),
+                FirstStep = step_conj(ConjNum),
                 list.index1(Conjs0, ConjNum, Conj0)
             ->
                 list.take_upto(ConjNum - 1, Conjs0, HeadConjs),
@@ -2147,8 +2074,8 @@
                     HeadConjs),
                 foldl(apply_instmap_delta_sv, HeadInstdeltas, 
                     Instmap0, Instmap),
-                maybe_transform_goal_at_goal_path_with_instmap(TransformP, 
-                    TargetGoalPath, Instmap, Conj0, MaybeConj),
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP, 
+                    LaterSteps, Instmap, Conj0, MaybeConj),
                 (
                     MaybeConj = ok(Conj),
                     list.replace_nth_det(Conjs0, ConjNum, Conj, Conjs),
@@ -2166,11 +2093,11 @@
         ;
             GoalExpr0 = disj(Disjs0),
             (
-                Step = step_disj(DisjNum),
+                FirstStep = step_disj(DisjNum),
                 list.index1(Disjs0, DisjNum, Disj0)
             ->
-                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
-                    TargetGoalPath, Instmap0, Disj0, MaybeDisj),
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap0, Disj0, MaybeDisj),
                 (
                     MaybeDisj = ok(Disj),
                     list.replace_nth_det(Disjs0, DisjNum, Disj, Disjs),
@@ -2187,12 +2114,12 @@
         ;
             GoalExpr0 = switch(Var, CanFail, Cases0),
             (
-                Step = step_switch(CaseNum, _MaybeNumConstructors),
+                FirstStep = 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),
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap0, CaseGoal0, MaybeCaseGoal),
                 (
                     MaybeCaseGoal = ok(CaseGoal),
                     Case = Case0 ^ case_goal := CaseGoal,
@@ -2210,9 +2137,9 @@
             )
         ;
             GoalExpr0 = negation(SubGoal0),
-            ( Step = step_neg ->
-                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
-                    TargetGoalPath, Instmap0, SubGoal0, MaybeSubGoal),
+            ( FirstStep = step_neg ->
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap0, SubGoal0, MaybeSubGoal),
                 (
                     MaybeSubGoal = ok(SubGoal),
                     GoalExpr = negation(SubGoal),
@@ -2228,9 +2155,9 @@
             )
         ;
             GoalExpr0 = scope(Reason, SubGoal0),
-            ( Step = step_scope(_MaybeCut) ->
-                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
-                    TargetGoalPath, Instmap0, SubGoal0, MaybeSubGoal),
+            ( FirstStep = step_scope(_MaybeCut) ->
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap0, SubGoal0, MaybeSubGoal),
                 (
                     MaybeSubGoal = ok(SubGoal),
                     GoalExpr = scope(Reason, SubGoal),
@@ -2246,9 +2173,9 @@
             )
         ;
             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),
+            ( FirstStep = step_ite_cond ->
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap0, Cond0, MaybeCond),
                 (
                     MaybeCond = ok(Cond),
                     GoalExpr = if_then_else(ExistVars, Cond, Then0, Else0),
@@ -2259,12 +2186,12 @@
                     ),
                     MaybeGoal = MaybeCond
                 )
-            ; Step = step_ite_then ->
+            ; FirstStep = 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),
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap, Then0, MaybeThen),
                 (
                     MaybeThen = ok(Then),
                     GoalExpr = if_then_else(ExistVars, Cond0, Then, Else0),
@@ -2275,9 +2202,9 @@
                     ),
                     MaybeGoal = MaybeThen
                 )
-            ; Step = step_ite_else ->
-                maybe_transform_goal_at_goal_path_with_instmap(TransformP,
-                    TargetGoalPath, Instmap0, Else0, MaybeElse),
+            ; FirstStep = step_ite_else ->
+                maybe_transform_goal_at_goal_path_with_instmap_2(TransformP,
+                    LaterSteps, Instmap0, Else0, MaybeElse),
                 (
                     MaybeElse = ok(Else),
                     GoalExpr = if_then_else(ExistVars, Cond0, Then0, Else),
@@ -2296,10 +2223,6 @@
             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,
@@ -2308,7 +2231,7 @@
 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) :-
+transform_all_goals(TransformP, Goal0, Goal) :-
     GoalExpr0 = Goal0 ^ hlds_goal_expr,  
     (
         ( GoalExpr0 = unify(_, _, _, _, _) 
@@ -2319,33 +2242,33 @@
         GoalExpr = GoalExpr0
     ;
         GoalExpr0 = conj(ConjType, Conjs0),
-        list.map(transform_all_goals(Transform), Conjs0, Conjs),
+        list.map(transform_all_goals(TransformP), Conjs0, Conjs),
         GoalExpr = conj(ConjType, Conjs)
     ;
         GoalExpr0 = disj(Disjs0),
-        list.map(transform_all_goals(Transform), Disjs0, Disjs),
+        list.map(transform_all_goals(TransformP), Disjs0, Disjs),
         GoalExpr = disj(Disjs)
     ;
         GoalExpr0 = switch(Var, CanFail, Cases0),
         list.map((pred(Case0::in, Case::out) is det :-
                 GoalI0 = Case0 ^ case_goal,
-                transform_all_goals(Transform, GoalI0, GoalI),
+                transform_all_goals(TransformP, GoalI0, GoalI),
                 Case = Case0 ^ case_goal := GoalI
             ), Cases0, Cases),
         GoalExpr = switch(Var, CanFail, Cases)
     ;
         GoalExpr0 = negation(SubGoal0),
-        transform_all_goals(Transform, SubGoal0, SubGoal),
+        transform_all_goals(TransformP, SubGoal0, SubGoal),
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        transform_all_goals(Transform, SubGoal0, SubGoal),
+        transform_all_goals(TransformP, SubGoal0, SubGoal),
         GoalExpr = scope(Reason, SubGoal)
     ;
         GoalExpr0 = if_then_else(ExistVars, Cond0, Then0, Else0),
-        transform_all_goals(Transform, Cond0, Cond),
-        transform_all_goals(Transform, Then0, Then),
-        transform_all_goals(Transform, Else0, Else),
+        transform_all_goals(TransformP, Cond0, Cond),
+        transform_all_goals(TransformP, Then0, Then),
+        transform_all_goals(TransformP, Else0, Else),
         GoalExpr = if_then_else(ExistVars, Cond, Then, Else)
     ;
         GoalExpr0 = shorthand(_),
@@ -2353,7 +2276,7 @@
             "Shorthand goals should have been eliminated already")
     ),
     Goal1 = Goal0 ^ hlds_goal_expr := GoalExpr, 
-    Transform(Goal1, Goal).
+    TransformP(Goal1, Goal).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds.m,v
retrieving revision 1.227
diff -u -r1.227 hlds.m
--- compiler/hlds.m	4 Feb 2010 02:20:40 -0000	1.227
+++ compiler/hlds.m	20 Mar 2010 15:16:21 -0000
@@ -34,10 +34,10 @@
 :- include_module special_pred.
 
 % Modules for creating the HLDS
+:- include_module hhf.
 :- include_module make_hlds.
 :- include_module make_tags.
 :- include_module quantification.
-:- include_module hhf.
 
 % Modules for pretty-printing it.
 :- include_module hlds_desc.
@@ -47,14 +47,15 @@
 :- include_module arg_info.
 :- include_module code_model.
 :- include_module goal_form.
+:- include_module goal_path.
 :- include_module goal_util.
 :- include_module headvar_names.
 :- include_module hlds_code_util.
 :- include_module hlds_error_util.
+:- include_module hlds_statistics.
 :- include_module mark_static_terms.
 :- include_module mark_tail_calls.
 :- include_module passes_aux.
-:- include_module hlds_statistics.
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/hlds_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_data.m,v
retrieving revision 1.129
diff -u -r1.129 hlds_data.m
--- compiler/hlds_data.m	15 Dec 2010 06:29:37 -0000	1.129
+++ compiler/hlds_data.m	15 Dec 2010 06:33:16 -0000
@@ -845,6 +845,7 @@
 
     % Optimize the user_inst_table for lookups. This just sorts
     % the cached list of inst_ids.
+    %
 :- pred user_inst_table_optimize(user_inst_table::in, user_inst_table::out)
     is det.
 
@@ -989,28 +990,35 @@
 :- type hlds_class_defn
     --->    hlds_class_defn(
                 class_status            :: import_status,
+
+                % SuperClasses.
                 class_supers            :: list(prog_constraint),
-                                        % SuperClasses
+
+                % Functional dependencies.
                 class_fundeps           :: hlds_class_fundeps,
-                                        % Functional dependencies
+
+                % All ancestors which have fundeps on them.
                 class_fundep_ancestors  :: list(prog_constraint),
-                                        % All ancestors which have fundeps
-                                        % on them.
+
+                % ClassVars.
                 class_vars              :: list(tvar),
-                                        % ClassVars
+
+                % Kinds of class_vars.
                 class_kinds             :: tvar_kind_map,
-                                        % Kinds of class_vars.
+
+                % The interface from the original declaration, used by
+                % intermod.m to % write out the interface for a local typeclass
+                % to the `.opt' file.
                 class_interface         :: class_interface,
-                                        % The interface from the original
-                                        % declaration, used by intermod.m to
-                                        % write out the interface for a local
-                                        % typeclass to the `.opt' file.
+
+                % Methods.
                 class_hlds_interface    :: hlds_class_interface,
-                                        % Methods
+
+                % VarNames.
                 class_tvarset           :: tvarset,
-                                        % VarNames
+
+                % Location of declaration.
                 class_context           :: prog_context
-                                        % Location of declaration
             ).
 
     % In the HLDS, functional dependencies are represented using
@@ -1050,32 +1058,35 @@
     %
 :- type hlds_instance_defn
     --->    hlds_instance_defn(
+                % Module of the instance declaration.
                 instance_module         :: module_name,
-                                        % module of the instance decl
+
+                % Import status of the instance declaration.
                 instance_status         :: import_status,
-                                        % import status of the instance
-                                        % declaration
+
+                % Context of declaration.
                 instance_context        :: prog_context,
-                                        % context of declaration
+
+                % Constraints on the instance declaration.
                 instance_constraints    :: list(prog_constraint),
-                                        % Constraints on the instance
-                                        % declaration.
+
+                % ClassTypes
                 instance_types          :: list(mer_type),
-                                        % ClassTypes
+
+                % Methods
                 instance_body           :: instance_body,
-                                        % Methods
+
+                % After check_typeclass, we will know the pred_ids and proc_ids
+                % of all the methods.
                 instance_hlds_interface :: maybe(hlds_class_interface),
-                                        % After check_typeclass, we will know
-                                        % the pred_ids and proc_ids of all
-                                        % the methods.
+
+                % VarNames
                 instance_tvarset        :: tvarset,
-                                        % VarNames
+
+                % "Proofs" of how to build the typeclass_infos for the
+                % superclasses of this class (that is, the constraints
+                % on the class declaration), for this instance.
                 instance_proofs         :: constraint_proof_map
-                                        % "Proofs" of how to build the
-                                        % typeclass_infos for the superclasses
-                                        % of this class (that is, the
-                                        % constraints on the class
-                                        % declaration), for this instance.
             ).
 
 %-----------------------------------------------------------------------------%
@@ -1114,13 +1125,14 @@
     %
 :- type constraint_id
     --->    constraint_id(
+                % Assumed or unproven.
                 constraint_type,
-                    % Assumed or unproven.
 
-                goal_path,
-                    % The location of the atomic goal which is constrained.
+                % The id of the atomic goal which is constrained.
+                goal_id,
 
-                int % The position of the constraint.
+                % The position of the constraint.
+                int
             ).
 
 :- type constraint_type
@@ -1141,29 +1153,26 @@
 
 :- type hlds_constraints
     --->    constraints(
+                % Unproven constraints. These are the constraints that we must
+                % prove (that is, universal constraints from the goal being
+                % checked, or existential constraints on the head).
                 unproven    :: list(hlds_constraint),
-                            % Unproven constraints. These are the constraints
-                            % that we must prove (that is, universal
-                            % constraints from the goal being checked, or
-                            % existential constraints on the head).
 
+                % Assumed constraints. These are constraints we can use in
+                % proofs (that is, existential constraints from the goal being
+                % checked, or universal constraints on the head).
                 assumed     :: list(hlds_constraint),
-                            % Assumed constraints. These are constraints
-                            % we can use in proofs (that is, existential
-                            % constraints from the goal being checked, or
-                            % universal constraints on the head).
 
+                % Constraints that are known to be redundant. This includes
+                % constraints that have already been proved as well as
+                % constraints that are ancestors of other unproven, assumed
+                % or redundant constraints. Not all such constraints are
+                % included, only those which may be used for the purposes
+                % of improvement.
                 redundant   :: redundant_constraints,
-                            % Constraints that are known to be redundant.
-                            % This includes constraints that have already been
-                            % proved as well as constraints that are ancestors
-                            % of other unproven, assumed or redundant
-                            % constraints.  Not all such constraints are
-                            % included, only those which may be used for
-                            % the purposes of improvement.
 
+                % Ancestors of assumed constraints.
                 ancestors   :: ancestor_constraints
-                            % Ancestors of assumed constraints.
             ).
 
     % Redundant constraints are partitioned by class, which helps us
@@ -1221,7 +1230,7 @@
 :- pred make_head_hlds_constraints(class_table::in, tvarset::in,
     prog_constraints::in, hlds_constraints::out) is det.
 
-:- pred make_body_hlds_constraints(class_table::in, tvarset::in, goal_path::in,
+:- pred make_body_hlds_constraints(class_table::in, tvarset::in, goal_id::in,
     prog_constraints::in, hlds_constraints::out) is det.
 
     % make_hlds_constraints(ClassTable, TVarSet, UnprovenConstraints,
@@ -1240,7 +1249,7 @@
     hlds_constraints::out) is det.
 
 :- pred make_hlds_constraint_list(list(prog_constraint)::in,
-    constraint_type::in, goal_path::in, list(hlds_constraint)::out) is det.
+    constraint_type::in, goal_id::in, list(hlds_constraint)::out) is det.
 
 :- pred merge_hlds_constraints(hlds_constraints::in, hlds_constraints::in,
     hlds_constraints::out) is det.
@@ -1268,10 +1277,10 @@
     redundant_constraints::in, redundant_constraints::out) is det.
 
 :- pred lookup_hlds_constraint_list(constraint_map::in, constraint_type::in,
-    goal_path::in, int::in, list(prog_constraint)::out) is det.
+    goal_id::in, int::in, list(prog_constraint)::out) is det.
 
 :- pred search_hlds_constraint_list(constraint_map::in, constraint_type::in,
-    goal_path::in, int::in, list(prog_constraint)::out) is semidet.
+    goal_id::in, int::in, list(prog_constraint)::out) is semidet.
 
 %-----------------------------------------------------------------------------%
 
@@ -1290,20 +1299,20 @@
 make_head_hlds_constraints(ClassTable, TVarSet, ProgConstraints,
         Constraints) :-
     ProgConstraints = constraints(UnivConstraints, ExistConstraints),
-    GoalPath = empty_goal_path,
-    make_hlds_constraint_list(UnivConstraints, assumed, GoalPath,
+    GoalId = goal_id(0),
+    make_hlds_constraint_list(UnivConstraints, assumed, GoalId,
         AssumedConstraints),
-    make_hlds_constraint_list(ExistConstraints, unproven, GoalPath,
+    make_hlds_constraint_list(ExistConstraints, unproven, GoalId,
         UnprovenConstraints),
     make_hlds_constraints(ClassTable, TVarSet, UnprovenConstraints,
         AssumedConstraints, Constraints).
 
-make_body_hlds_constraints(ClassTable, TVarSet, GoalPath, ProgConstraints,
+make_body_hlds_constraints(ClassTable, TVarSet, GoalId, ProgConstraints,
         Constraints) :-
     ProgConstraints = constraints(UnivConstraints, ExistConstraints),
-    make_hlds_constraint_list(UnivConstraints, unproven, GoalPath,
+    make_hlds_constraint_list(UnivConstraints, unproven, GoalId,
         UnprovenConstraints),
-    make_hlds_constraint_list(ExistConstraints, assumed, GoalPath,
+    make_hlds_constraint_list(ExistConstraints, assumed, GoalId,
         AssumedConstraints),
     make_hlds_constraints(ClassTable, TVarSet, UnprovenConstraints,
         AssumedConstraints, Constraints).
@@ -1317,22 +1326,22 @@
         Assumed, map.init, Ancestors),
     Constraints = constraints(Unproven, Assumed, Redundant, Ancestors).
 
-make_hlds_constraint_list(ProgConstraints, ConstraintType, GoalPath,
+make_hlds_constraint_list(ProgConstraints, ConstraintType, GoalId,
         Constraints) :-
-    make_hlds_constraint_list_2(ProgConstraints, ConstraintType, GoalPath,
+    make_hlds_constraint_list_2(ProgConstraints, ConstraintType, GoalId,
         1, Constraints).
 
 :- pred make_hlds_constraint_list_2(list(prog_constraint)::in,
-    constraint_type::in, goal_path::in, int::in,
-    list(hlds_constraint)::out) is det.
+    constraint_type::in, goal_id::in, int::in, list(hlds_constraint)::out)
+    is det.
 
 make_hlds_constraint_list_2([], _, _, _, []).
 make_hlds_constraint_list_2([ProgConstraint | ProgConstraints], ConstraintType,
-        GoalPath, N, [HLDSConstraint | HLDSConstraints]) :-
+        GoalId, N, [HLDSConstraint | HLDSConstraints]) :-
     ProgConstraint = constraint(Name, Types),
-    Id = constraint_id(ConstraintType, GoalPath, N),
+    Id = constraint_id(ConstraintType, GoalId, N),
     HLDSConstraint = constraint([Id], Name, Types),
-    make_hlds_constraint_list_2(ProgConstraints, ConstraintType, GoalPath,
+    make_hlds_constraint_list_2(ProgConstraints, ConstraintType, GoalId,
         N + 1, HLDSConstraints).
 
 merge_hlds_constraints(ConstraintsA, ConstraintsB, Constraints) :-
@@ -1450,10 +1459,10 @@
     ),
     svmap.set(ClassId, Constraints, !Redundant).
 
-lookup_hlds_constraint_list(ConstraintMap, ConstraintType, GoalPath, Count,
+lookup_hlds_constraint_list(ConstraintMap, ConstraintType, GoalId, Count,
         Constraints) :-
     (
-        search_hlds_constraint_list_2(ConstraintMap, ConstraintType, GoalPath,
+        search_hlds_constraint_list_2(ConstraintMap, ConstraintType, GoalId,
             Count, [], Constraints0)
     ->
         Constraints = Constraints0
@@ -1461,25 +1470,25 @@
         unexpected(this_file, "lookup_hlds_constraint_list: not found")
     ).
 
-search_hlds_constraint_list(ConstraintMap, ConstraintType, GoalPath, Count,
+search_hlds_constraint_list(ConstraintMap, ConstraintType, GoalId, Count,
         Constraints) :-
-    search_hlds_constraint_list_2(ConstraintMap, ConstraintType, GoalPath,
+    search_hlds_constraint_list_2(ConstraintMap, ConstraintType, GoalId,
         Count, [], Constraints).
 
 :- pred search_hlds_constraint_list_2(constraint_map::in, constraint_type::in,
-    goal_path::in, int::in, list(prog_constraint)::in,
+    goal_id::in, int::in, list(prog_constraint)::in,
     list(prog_constraint)::out) is semidet.
 
-search_hlds_constraint_list_2(ConstraintMap, ConstraintType, GoalPath, Count,
+search_hlds_constraint_list_2(ConstraintMap, ConstraintType, GoalId, Count,
         !Constraints) :-
     ( Count = 0 ->
         true
     ;
-        ConstraintId = constraint_id(ConstraintType, GoalPath, Count),
+        ConstraintId = constraint_id(ConstraintType, GoalId, Count),
         map.search(ConstraintMap, ConstraintId, Constraint),
         !:Constraints = [Constraint | !.Constraints],
         search_hlds_constraint_list_2(ConstraintMap, ConstraintType,
-            GoalPath, Count - 1, !Constraints)
+            GoalId, Count - 1, !Constraints)
     ).
 
 %-----------------------------------------------------------------------------%
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.217
diff -u -r1.217 hlds_goal.m
--- compiler/hlds_goal.m	15 Dec 2010 06:29:38 -0000	1.217
+++ compiler/hlds_goal.m	15 Dec 2010 06:33:16 -0000
@@ -1260,7 +1260,8 @@
 :- func goal_info_get_code_gen_nonlocals(hlds_goal_info) = set(prog_var).
 :- func goal_info_get_purity(hlds_goal_info) = purity.
 :- func goal_info_get_features(hlds_goal_info) = set(goal_feature).
-:- func goal_info_get_goal_path(hlds_goal_info) = goal_path.
+:- func goal_info_get_goal_id(hlds_goal_info) = goal_id.
+:- func goal_info_get_reverse_goal_path(hlds_goal_info) = reverse_goal_path.
 :- func goal_info_get_code_gen_info(hlds_goal_info) = hlds_goal_code_gen_info.
 :- func goal_info_get_ho_values(hlds_goal_info) = ho_values.
 :- func goal_info_get_maybe_rbmm(hlds_goal_info) = maybe(rbmm_goal_info).
@@ -1286,7 +1287,9 @@
     hlds_goal_info::in, hlds_goal_info::out) is det.
 :- pred goal_info_set_features(set(goal_feature)::in,
     hlds_goal_info::in, hlds_goal_info::out) is det.
-:- pred goal_info_set_goal_path(goal_path::in,
+:- pred goal_info_set_goal_id(goal_id::in,
+    hlds_goal_info::in, hlds_goal_info::out) is det.
+:- pred goal_info_set_reverse_goal_path(reverse_goal_path::in,
     hlds_goal_info::in, hlds_goal_info::out) is det.
 :- pred goal_info_set_code_gen_info(hlds_goal_code_gen_info::in,
     hlds_goal_info::in, hlds_goal_info::out) is det.
@@ -1903,8 +1906,8 @@
                 % which optimisers may wish to know about.
 /*  5 */        gi_features         :: set(goal_feature),
 
-                % The path to this goal from the root.
-/*  6 */        gi_goal_path        :: goal_path,
+                % An value that uniquely identifies this goal in its procedure.
+/*  6 */        gi_goal_id          :: goal_id,
 
 /*  7 */        gi_code_gen_info    :: hlds_goal_code_gen_info,
 
@@ -1918,6 +1921,8 @@
     --->    extra_goal_info(
                 egi_context             :: prog_context,
 
+                egi_rev_goal_path       :: reverse_goal_path,
+
                 egi_ho_vals             :: ho_values,
 
                 % Any information related to structure reuse (CTGC).
@@ -1938,9 +1943,9 @@
     set.init(NonLocals),
     term.context_init(Context),
     set.init(Features),
-    GoalPath = empty_goal_path,
+    GoalId = goal_id(-1),
     GoalInfo = goal_info(Detism, InstMapDelta, NonLocals, purity_pure,
-        Features, GoalPath, no_code_gen_info,
+        Features, GoalId, no_code_gen_info,
         hlds_goal_extra_info_init(Context)).
 
 :- pragma inline(goal_info_init/2).
@@ -1950,24 +1955,24 @@
     instmap_delta_init_unreachable(InstMapDelta),
     set.init(NonLocals),
     set.init(Features),
-    GoalPath = empty_goal_path,
+    GoalId = goal_id(-1),
     GoalInfo = goal_info(Detism, InstMapDelta, NonLocals, purity_pure,
-        Features, GoalPath, no_code_gen_info,
+        Features, GoalId, no_code_gen_info,
         hlds_goal_extra_info_init(Context)).
 
 goal_info_init(NonLocals, InstMapDelta, Detism, Purity, GoalInfo) :-
     set.init(Features),
     term.context_init(Context),
-    GoalPath = empty_goal_path,
+    GoalId = goal_id(-1),
     GoalInfo = goal_info(Detism, InstMapDelta, NonLocals, Purity,
-        Features, GoalPath, no_code_gen_info,
+        Features, GoalId, no_code_gen_info,
         hlds_goal_extra_info_init(Context)).
 
 goal_info_init(NonLocals, InstMapDelta, Detism, Purity, Context, GoalInfo) :-
     set.init(Features),
-    GoalPath = empty_goal_path,
+    GoalId = goal_id(-1),
     GoalInfo = goal_info(Detism, InstMapDelta, NonLocals, Purity,
-        Features, GoalPath, no_code_gen_info,
+        Features, GoalId, no_code_gen_info,
         hlds_goal_extra_info_init(Context)).
 
 impure_init_goal_info(NonLocals, InstMapDelta, Determinism) = GoalInfo :-
@@ -2021,7 +2026,7 @@
 
 hlds_goal_extra_info_init(Context) = ExtraInfo :-
     HO_Values = map.init,
-    ExtraInfo = extra_goal_info(Context, HO_Values, no, no, no, no).
+    ExtraInfo = extra_goal_info(Context, rgp([]), HO_Values, no, no, no, no).
 
 :- func ctgc_goal_info_init = ctgc_goal_info.
 
@@ -2035,7 +2040,9 @@
 goal_info_get_nonlocals(GoalInfo) = GoalInfo ^ gi_nonlocals.
 goal_info_get_purity(GoalInfo) = GoalInfo ^ gi_purity.
 goal_info_get_features(GoalInfo) = GoalInfo ^ gi_features.
-goal_info_get_goal_path(GoalInfo) = GoalInfo ^ gi_goal_path.
+goal_info_get_goal_id(GoalInfo) = GoalInfo ^ gi_goal_id.
+goal_info_get_reverse_goal_path(GoalInfo) =
+    GoalInfo ^ gi_extra ^ egi_rev_goal_path.
 goal_info_get_code_gen_info(GoalInfo) = GoalInfo ^ gi_code_gen_info.
 goal_info_get_context(GoalInfo) = GoalInfo ^ gi_extra ^ egi_context.
 goal_info_get_ho_values(GoalInfo) = GoalInfo ^ gi_extra ^ egi_ho_vals.
@@ -2055,8 +2062,10 @@
     !GoalInfo ^ gi_purity := Purity.
 goal_info_set_features(Features, !GoalInfo) :-
     !GoalInfo ^ gi_features := Features.
-goal_info_set_goal_path(GoalPath, !GoalInfo) :-
-    !GoalInfo ^ gi_goal_path := GoalPath.
+goal_info_set_goal_id(GoalId, !GoalInfo) :-
+    !GoalInfo ^ gi_goal_id := GoalId.
+goal_info_set_reverse_goal_path(RevGoalPath, !GoalInfo) :-
+    !GoalInfo ^ gi_extra ^ egi_rev_goal_path := RevGoalPath.
 goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo) :-
     !GoalInfo ^ gi_code_gen_info := CodeGenInfo.
 goal_info_set_context(Context, !GoalInfo) :-
@@ -2719,8 +2728,8 @@
         CodeGenInfo = llds_code_gen_info(LldsInfo)
     ),
 
-    ExtraInfo0 = extra_goal_info(Context, HO_Values, MaybeCTGC0, MaybeRBMM0,
-        MaybeMCI0, MaybeDPInfo0),
+    ExtraInfo0 = extra_goal_info(Context, RevGoalPath, HO_Values,
+        MaybeCTGC0, MaybeRBMM0, MaybeMCI0, MaybeDPInfo0),
     (
         MaybeCTGC0 = no,
         MaybeCTGC = no
@@ -2780,8 +2789,8 @@
         MaybeMCI = yes(MCI)
     ),
     MaybeDPInfo = MaybeDPInfo0,
-    ExtraInfo = extra_goal_info(Context, HO_Values, MaybeCTGC, MaybeRBMM,
-        MaybeMCI, MaybeDPInfo),
+    ExtraInfo = extra_goal_info(Context, RevGoalPath, HO_Values,
+        MaybeCTGC, MaybeRBMM, MaybeMCI, MaybeDPInfo),
 
     !:GoalInfo = goal_info(Detism, InstMapDelta, NonLocals, Purity,
         Features, GoalPath, CodeGenInfo, ExtraInfo).
Index: compiler/hlds_out_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out_goal.m,v
retrieving revision 1.2
diff -u -r1.2 hlds_out_goal.m
--- compiler/hlds_out_goal.m	10 Sep 2010 05:14:58 -0000	1.2
+++ compiler/hlds_out_goal.m	13 Sep 2010 01:03:26 -0000
@@ -168,13 +168,14 @@
         true
     ),
     ( string.contains_char(DumpOptions, 'P') ->
-        Path = goal_info_get_goal_path(GoalInfo),
-        ( Path = empty_goal_path ->
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        GoalId = goal_id(GoalIdNum),
+        ( GoalIdNum < 0 ->
             true
         ;
             write_indent(Indent, !IO),
-            io.write_string("% goal path: ", !IO),
-            io.write_string(goal_path_to_string(Path), !IO),
+            io.write_string("% goal id: ", !IO),
+            io.write_int(GoalIdNum, !IO),
             io.write_string("\n", !IO)
         )
     ;
Index: compiler/hlds_out_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out_pred.m,v
retrieving revision 1.2
diff -u -r1.2 hlds_out_pred.m
--- compiler/hlds_out_pred.m	15 Dec 2010 06:29:38 -0000	1.2
+++ compiler/hlds_out_pred.m	17 Dec 2010 02:53:09 -0000
@@ -1040,9 +1040,9 @@
     int::in, int::out, io::di, io::uo) is det.
 
 write_hlds_ps_coverage_point(CoveragePointInfo, !SlotNum, !IO) :-
-    CoveragePointInfo = coverage_point_info(GoalPath, PointType),
+    CoveragePointInfo = coverage_point_info(RevGoalPath, PointType),
     io.format("%% coverage point slot %d: goal path <%s>, type %s\n",
-        [i(!.SlotNum), s(goal_path_to_string(GoalPath)),
+        [i(!.SlotNum), s(rev_goal_path_to_string(RevGoalPath)),
             s(coverage_point_to_string(PointType))], !IO),
     !:SlotNum = !.SlotNum + 1.
 
@@ -1196,7 +1196,7 @@
 :- pred write_constraint_id(constraint_id::in, io::di, io::uo) is det.
 
 write_constraint_id(ConstraintId, !IO) :-
-    ConstraintId = constraint_id(ConstraintType, GoalPath, N),
+    ConstraintId = constraint_id(ConstraintType, GoalId, N),
     (
         ConstraintType = assumed,
         io.write_string("(E, ", !IO)
@@ -1204,7 +1204,9 @@
         ConstraintType = unproven,
         io.write_string("(A, ", !IO)
     ),
-    io.write_strings(["""", goal_path_to_string(GoalPath), """, "], !IO),
+    GoalId = goal_id(GoalIdNum),
+    io.write_int(GoalIdNum, !IO),
+    io.write_string(", ", !IO),
     io.write_int(N, !IO),
     io.write_char(')', !IO).
 
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.262
diff -u -r1.262 hlds_pred.m
--- compiler/hlds_pred.m	15 Dec 2010 06:29:38 -0000	1.262
+++ compiler/hlds_pred.m	15 Dec 2010 06:33:17 -0000
@@ -1678,27 +1678,27 @@
                 normal_type_subst       :: string,
                 normal_file_name        :: string,
                 normal_line_number      :: int,
-                normal_goal_path        :: goal_path
+                normal_goal_path        :: forward_goal_path
             )
     ;       special_call(
                 special_file_name       :: string,
                 special_line_number     :: int,
-                special_goal_path       :: goal_path
+                special_goal_path       :: forward_goal_path
             )
     ;       higher_order_call(
                 higher_order_file_name  :: string,
                 ho_line_number          :: int,
-                ho_goal_path            :: goal_path
+                ho_goal_path            :: forward_goal_path
             )
     ;       method_call(
                 method_file_name        :: string,
                 method_line_number      :: int,
-                method_goal_path        :: goal_path
+                method_goal_path        :: forward_goal_path
             )
     ;       callback(
                 callback_file_name      :: string,
                 callback_line_number    :: int,
-                callback_goal_path      :: goal_path
+                callback_goal_path      :: forward_goal_path
             ).
 
 :- type hlds_proc_static
Index: compiler/implicit_parallelism.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/implicit_parallelism.m,v
retrieving revision 1.24
diff -u -r1.24 implicit_parallelism.m
--- compiler/implicit_parallelism.m	14 Oct 2010 04:02:22 -0000	1.24
+++ compiler/implicit_parallelism.m	6 Dec 2010 08:04:00 -0000
@@ -6,8 +6,8 @@
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
 %
-% File : implicit_parallelism.m.
-% Author: tannier, pbone.
+% File: implicit_parallelism.m.
+% Authors: tannier, pbone.
 %
 % This module uses deep profiling feedback information generated by
 % mdprof_feedback to introduce parallel conjunctions where it could be
@@ -81,7 +81,7 @@
 apply_implicit_parallelism_transformation(!ModuleInfo, !IO) :-
     module_info_get_globals(!.ModuleInfo, Globals),
     lookup_bool_option(Globals, old_implicit_parallelism,
-        UseOldImplicitParallelism), 
+        UseOldImplicitParallelism),
     (
         UseOldImplicitParallelism = yes,
         apply_old_implicit_parallelism_transformation(!.ModuleInfo,
@@ -102,7 +102,7 @@
             MaybeSourceFileMap = no,
             error(this_file ++ "could not retrieve the source file map")
         ),
-        apply_new_implicit_parallelism_transformation(SourceFileMap, Specs, 
+        apply_new_implicit_parallelism_transformation(SourceFileMap, Specs,
             !ModuleInfo),
         write_error_specs(Specs, Globals, 0, _, 0, NumErrors, !IO),
         module_info_incr_num_errors(NumErrors, !ModuleInfo)
@@ -134,8 +134,8 @@
         module_info_get_valid_predids(PredIds, !ModuleInfo),
         module_info_get_predicate_table(!.ModuleInfo, PredTable0),
         predicate_table_get_preds(PredTable0, PredMap0),
-        list.foldl3(maybe_parallelise_pred(!.ModuleInfo, ParallelismInfo), 
-            PredIds, PredMap0, PredMap, 
+        list.foldl3(maybe_parallelise_pred(!.ModuleInfo, ParallelismInfo),
+            PredIds, PredMap0, PredMap,
             have_not_introduced_parallelism, IntroducedParallelism,
             [], Specs),
         (
@@ -147,7 +147,7 @@
             module_info_set_contains_par_conj(!ModuleInfo)
         )
     ;
-        map.lookup(SourceFileMap, ModuleName, ModuleFilename), 
+        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"),
@@ -190,10 +190,10 @@
     parallelism_info::out) is semidet.
 
 get_implicit_parallelism_feedback(ModuleName, FeedbackInfo, ParallelismInfo) :-
-    FeedbackData = 
+    FeedbackData =
         feedback_data_candidate_parallel_conjunctions(_, _),
     get_feedback_data(FeedbackInfo, FeedbackData),
-    FeedbackData = 
+    FeedbackData =
         feedback_data_candidate_parallel_conjunctions(Parameters, AssocList),
     make_module_candidate_par_conjs_map(ModuleName, AssocList,
         CandidateParConjsMap),
@@ -210,30 +210,30 @@
         CandidateParConjsAssocList0, CandidateParConjsAssocList),
     CandidateParConjsMap = map.from_assoc_list(CandidateParConjsAssocList).
 
-:- pred cpc_proc_is_in_module(string::in, 
+:- pred cpc_proc_is_in_module(string::in,
     pair(string_proc_label, candidate_par_conjunctions_proc)::in,
-    pair(intra_module_proc_label, candidate_par_conjunctions_proc)::out) 
+    pair(intra_module_proc_label, candidate_par_conjunctions_proc)::out)
     is semidet.
 
 cpc_proc_is_in_module(ModuleName, ProcLabel - CPC, IMProcLabel - CPC) :-
-    ( 
+    (
         ProcLabel = str_ordinary_proc_label(PredOrFunc, _, DefModule, Name,
             Arity, Mode)
-    ; 
+    ;
         ProcLabel = str_special_proc_label(_, _, DefModule, Name, Arity, Mode),
-        PredOrFunc = pf_predicate 
+        PredOrFunc = pf_predicate
     ),
     ModuleName = DefModule,
     IMProcLabel = intra_module_proc_label(Name, Arity, PredOrFunc, Mode).
 
 %-----------------------------------------------------------------------------%
 
-:- pred maybe_parallelise_pred(module_info::in, parallelism_info::in, 
+:- 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,
     list(error_spec)::in, list(error_spec)::out) is det.
 
-maybe_parallelise_pred(ModuleInfo, ParallelismInfo, PredId, !PredTable, 
+maybe_parallelise_pred(ModuleInfo, ParallelismInfo, PredId, !PredTable,
         !IntroducedParallelism, !Specs) :-
     map.lookup(!.PredTable, PredId, PredInfo0),
     ProcIds = pred_info_non_imported_procids(PredInfo0),
@@ -250,16 +250,16 @@
         svmap.det_update(PredId, PredInfo, !PredTable)
     ).
 
-:- pred maybe_parallelise_proc(module_info::in, parallelism_info::in, 
-    pred_id::in, proc_id::in, proc_table::in, proc_table::out, 
+:- 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,
     list(error_spec)::in, list(error_spec)::out) is det.
 
 maybe_parallelise_proc(ModuleInfo, ParallelismInfo, PredId, ProcId, !ProcTable,
         !IntroducedParallelism, !Specs) :-
-    module_info_pred_proc_info(ModuleInfo, PredId, ProcId, 
+    module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
         PredInfo, ProcInfo0),
-    
+
     % Lookup the Candidate Parallel Conjunction (CPC) Map for this procedure.
     Name = pred_info_name(PredInfo),
     Arity = pred_info_orig_arity(PredInfo),
@@ -268,17 +268,17 @@
     IMProcLabel = intra_module_proc_label(Name, Arity, PredOrFunc, Mode),
     CPCMap = ParallelismInfo ^ pi_cpc_map,
     ( map.search(CPCMap, IMProcLabel, CPCProc) ->
-        proc_info_get_has_parallel_conj(ProcInfo0, HasParallelConj), 
+        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),
@@ -292,14 +292,15 @@
                 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,
+            % Sort the candidate parallelisations so that we introduce
+            % parallelisations in an 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, 
+            sort_and_remove_dups(compare_candidate_par_conjunctions,
                 CPCs0, CPCs),
-            foldl3(maybe_parallelise_goal(PredInfo, ProgRepInfo, VarTable, 
+            foldl3(
+                maybe_parallelise_goal(PredInfo, ProgRepInfo, VarTable,
                     Instmap),
                 CPCs, Goal0, Goal, !IntroducedParallelism, !Specs),
             (
@@ -321,30 +322,25 @@
     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).
+    goal_path_from_string_det(CPCA ^ cpc_goal_path, fgp(StepsA)),
+    goal_path_from_string_det(CPCB ^ cpc_goal_path, fgp(StepsB)),
+    compare_goal_paths(StepsA, StepsB, Result).
 
-:- pred compare_goal_paths(goal_path_consable::in, goal_path_consable::in,
+:- pred compare_goal_paths(list(goal_path_step)::in, list(goal_path_step)::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),
+compare_goal_paths(StepsA, StepsB, Result) :-
+    (
+        StepsA = [FirstStepA | LaterStepsA],
+        (
+            StepsB = [FirstStepB | LaterStepsB],
+            compare(Result0, FirstStepA, FirstStepB),
             % Reverse the ordering here so that later goals are sorted before
-            % earlier ones, this way parallelisations are placed inside later
+            % earlier ones. This way parallelisations are placed inside later
             % goals first.
             (
                 Result0 = (=),
-                compare_goal_paths(RestA, RestB, Result)
+                compare_goal_paths(LaterStepsA, LaterStepsB, Result)
             ;
                 Result0 = (<),
                 Result = (>)
@@ -353,28 +349,32 @@
                 Result = (<)
             )
         ;
-            % GoalPathA is longer than GoalPathB.  Make A 'less than' B so that
+            StepsB = [],
+            % StepsA is longer than StepsB. Make A 'less than' B so that
             % deeper parallelisations are insearted first.
             Result = (<)
         )
     ;
-        ( goal_path_consable_remove_first(GoalPathB, _, _) ->
+        StepsA = [],
+        (
+            StepsB = [_ | _],
             % B is 'less than' A, see above.
             Result = (>)
         ;
+            StepsB = [],
             % Both goal paths are empty.
             Result = (=)
         )
     ).
-            
-    % maybe_parallelise_goal(ProgRepInfo, VarTable, CPC, !Goal, 
+
+    % 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, 
+:- 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,
@@ -386,14 +386,12 @@
     ( goal_path_from_string(TargetGoalPathString, TargetGoalPathPrime) ->
         TargetGoalPath = TargetGoalPathPrime
     ;
-        unexpected(this_file, 
+        unexpected(this_file,
             "Invalid goal path in CPC Feedback Information")
     ),
-    goal_path_consable(TargetGoalPath, TargetGoalPathC),
-    
     maybe_transform_goal_at_goal_path_with_instmap(
         maybe_parallelise_conj(ProgRepInfo, VarTable, CPC),
-        TargetGoalPathC, Instmap0, Goal0, MaybeGoal),
+        TargetGoalPath, Instmap0, Goal0, MaybeGoal),
     (
         MaybeGoal = ok(Goal),
         !:IntroducedParallelism = introduced_parallelism
@@ -403,7 +401,7 @@
         ;
             MaybeGoal = goal_not_found,
             Error = "Could not find goal in procedure; "
-                    ++ "perhaps the program has changed"
+                ++ "perhaps the program has changed"
         ),
         Goal = Goal0,
         Spec = report_failed_parallelisation(PredInfo, TargetGoalPathString,
@@ -423,10 +421,10 @@
     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), 
+        words("Warning: could not auto-parallelise"), quote(GoalPath),
         suffix(":"), words(Error)],
     pred_info_get_context(PredInfo, Context),
-    % XXX Make this a warning or error if the user wants compilation to 
+    % XXX Make this a warning or error if the user wants compilation to
     % abort.
     Spec = error_spec(severity_informational, phase_auto_parallelism,
         [simple_msg(Context, [always(Peices)])]).
@@ -448,11 +446,12 @@
     Spec = error_spec(severity_warning, phase_auto_parallelism,
         [simple_msg(Context, [always(Peices)])]).
 
-:- pred maybe_parallelise_conj(prog_rep_info::in, var_table::in, 
+:- 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) :-
+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.
@@ -460,7 +459,7 @@
     (
         GoalExpr0 = conj(plain_conj, Conjs0),
         flatten_conj(Conjs0, Conjs1),
-        find_first_goal(FirstGoalRep, Conjs1, ProgRepInfo, VarTable, Instmap0, 
+        find_first_goal(FirstGoalRep, Conjs1, ProgRepInfo, VarTable, Instmap0,
             found_first_goal(GoalsBefore, FirstGoal, OtherGoals))
     ->
         GoalsBeforeInstDeltas = map(
@@ -468,13 +467,13 @@
             GoalsBefore),
         foldl(apply_instmap_delta_sv, GoalsBeforeInstDeltas,
             Instmap0, Instmap),
-        build_par_conjunction(ProgRepInfo, VarTable, Instmap, 
+        build_par_conjunction(ProgRepInfo, VarTable, Instmap,
             [FirstGoal | OtherGoals], CPC, MaybeParConjunction),
         (
             MaybeParConjunction = ok(
                 par_conjunction_and_remaining_goals(ParConjunction,
                 RemainingGoals)),
-            Conjs = GoalsBefore ++ ParConjunction ++ RemainingGoals, 
+            Conjs = GoalsBefore ++ ParConjunction ++ RemainingGoals,
             GoalExpr = conj(plain_conj, Conjs),
             MaybeGoal = ok(hlds_goal(GoalExpr, Goal0 ^ hlds_goal_info))
         ;
@@ -483,10 +482,10 @@
         )
     ;
         MaybeGoal = error("Could not find partition within conjunction: "
-                ++ "perhaps the program has changed")
+            ++ "perhaps the program has changed")
     ).
 
-:- pred cpc_get_first_goal(candidate_par_conjunction::in, pard_goal::out) 
+:- pred cpc_get_first_goal(candidate_par_conjunction::in, pard_goal::out)
     is det.
 
 cpc_get_first_goal(CPC, FirstGoal) :-
@@ -522,8 +521,8 @@
 find_first_goal(GoalRep, [Goal | Goals], ProcRepInfo, VarTable, !.Instmap,
         Result) :-
     (
-        pard_goal_match_hlds_goal(ProcRepInfo, VarTable, !.Instmap, GoalRep, 
-            Goal) 
+        pard_goal_match_hlds_goal(ProcRepInfo, VarTable, !.Instmap, GoalRep,
+            Goal)
     ->
         Result = found_first_goal([], Goal, Goals)
     ;
@@ -593,19 +592,19 @@
             ++ "conjunction do not match those in the feedback file")
     ).
 
-:- pred build_par_conjuncts(prog_rep_info::in, var_table::in, 
-    list(seq_conj)::in, maybe(hlds_goals)::out, 
+:- 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_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, 
+    build_seq_conjuncts(ProcRepInfo, VarTable, SeqConjs, MaybeConj, !Goals,
         !Instmap),
     (
         MaybeConj = yes(Conj0),
-        create_conj_from_list(Conj0, plain_conj, Conj), 
+        create_conj_from_list(Conj0, plain_conj, Conj),
         build_par_conjuncts(ProcRepInfo, VarTable, GoalReps, MaybeConjs0,
             !Goals, !Instmap),
         (
@@ -620,16 +619,16 @@
         MaybeConjs = no
     ).
 
-:- pred build_seq_conjuncts(prog_rep_info::in, var_table::in, 
-    list(pard_goal)::in, maybe(hlds_goals)::out, 
+:- 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, 
+        ( 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),
@@ -657,14 +656,14 @@
     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) 
+:- 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_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, 
+:- 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)) :-
@@ -677,13 +676,13 @@
     % 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), 
+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)) :- 
+        negation_rep(SubGoal2)) :-
     goal_reps_match(VarTable, SubGoal1, SubGoal2).
 goal_expr_reps_match(VarTable, scope_rep(SubGoal1, MaybeCut),
         scope_rep(SubGoal2, MaybeCut)) :-
@@ -781,7 +780,7 @@
         true
     ).
 
-:- pred maybe_var_reps_match(var_table::in, 
+:- pred maybe_var_reps_match(var_table::in,
     maybe(var_rep)::in, maybe(var_rep)::in) is semidet.
 
 maybe_var_reps_match(_, no, no).
@@ -814,7 +813,7 @@
 match_sym_module_name(qualified(SymName, Name), [Name | Names]) :-
     match_sym_module_name(SymName, Names).
 
-:- pred args_match(prog_varset::in, prog_var::in, maybe(string)::in) 
+:- pred args_match(prog_varset::in, prog_var::in, maybe(string)::in)
     is semidet.
 
 args_match(_, _, no).
@@ -905,7 +904,7 @@
         )
     ;
         MaybeModuleInfo =
-            error("Insufficient feedback information for implicit parallelism") 
+            error("Insufficient feedback information for implicit parallelism")
     ).
 
     % This predicate isn't really necessary as this entire module should use
Index: compiler/interval.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/interval.m,v
retrieving revision 1.43
diff -u -r1.43 interval.m
--- compiler/interval.m	15 Dec 2010 06:29:40 -0000	1.43
+++ compiler/interval.m	15 Dec 2010 06:33:17 -0000
@@ -57,7 +57,7 @@
 :- type save_point
     --->    save_point(
                 save_point_type,
-                goal_path
+                goal_id
             ).
 
 :- type branch_construct
@@ -74,10 +74,10 @@
 :- type anchor
     --->    anchor_proc_start
     ;       anchor_proc_end
-    ;       anchor_branch_start(branch_construct, goal_path)
-    ;       anchor_cond_then(goal_path)
-    ;       anchor_branch_end(branch_construct, goal_path)
-    ;       anchor_call_site(goal_path).
+    ;       anchor_branch_start(branch_construct, goal_id)
+    ;       anchor_cond_then(goal_id)
+    ;       anchor_branch_end(branch_construct, goal_id)
+    ;       anchor_call_site(goal_id).
 
 :- type interval_id
     --->    interval_id(int).
@@ -115,9 +115,9 @@
                 ii_interval_params      :: interval_params,
                 ii_flushed_later        :: set(prog_var),
                 ii_accessed_later       :: set(prog_var),
-                ii_branch_resume_map    :: map(goal_path, resume_save_status),
-                ii_branch_end_map       :: map(goal_path, branch_end_info),
-                ii_cond_end_map         :: map(goal_path, interval_id),
+                ii_branch_resume_map    :: map(goal_id, resume_save_status),
+                ii_branch_end_map       :: map(goal_id, branch_end_info),
+                ii_cond_end_map         :: map(goal_id, interval_id),
                 ii_cur_interval         :: interval_id,
                 ii_interval_counter     :: counter,
                 ii_open_intervals       :: set(interval_id),
@@ -443,8 +443,8 @@
             NondetLiveVars),
         VarsOnStack0 = set.union_list([ForwardVars, ResumeVars,
             NondetLiveVars]),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
-        CallAnchor = anchor_call_site(GoalPath),
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        CallAnchor = anchor_call_site(GoalId),
         get_cur_interval(AfterCallId, !.IntervalInfo),
         new_interval_id(BeforeCallId, !IntervalInfo),
         record_interval_start(AfterCallId, CallAnchor, !IntervalInfo),
@@ -545,8 +545,8 @@
 reached_branch_end(GoalInfo, MaybeResumeGoal, Construct,
         StartAnchor, EndAnchor, BeforeIntervalId, AfterIntervalId,
         MaybeResumeVars, !IntervalInfo, !Acc) :-
-    GoalPath = goal_info_get_goal_path(GoalInfo),
-    record_branch_end_info(GoalPath, !IntervalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    record_branch_end_info(GoalId, !IntervalInfo),
     (
         MaybeResumeGoal = yes(hlds_goal(_ResumeGoalExpr, ResumeGoalInfo)),
         goal_info_maybe_get_resume_point(ResumeGoalInfo, ResumePoint),
@@ -559,7 +559,7 @@
         HasResumeSave = has_no_resume_save,
         MaybeResumeVars = no
     ),
-    record_branch_resume(GoalPath, HasResumeSave, !IntervalInfo),
+    record_branch_resume(GoalId, HasResumeSave, !IntervalInfo),
     ( goal_info_maybe_get_store_map(GoalInfo, StoreMap) ->
         map.sorted_keys(StoreMap, StoreMapVarList),
         set.sorted_list_to_set(StoreMapVarList, StoreMapVars),
@@ -567,8 +567,8 @@
     ;
         unexpected(this_file, "reached_branch_end: no store map")
     ),
-    EndAnchor = anchor_branch_end(Construct, GoalPath),
-    StartAnchor = anchor_branch_start(Construct, GoalPath),
+    EndAnchor = anchor_branch_end(Construct, GoalId),
+    StartAnchor = anchor_branch_start(Construct, GoalId),
     assign_open_intervals_to_anchor(EndAnchor, !IntervalInfo),
     CodeModel = goal_info_get_code_model(GoalInfo),
     (
@@ -615,12 +615,12 @@
     interval_info::in, interval_info::out) is det.
 
 reached_cond_then(GoalInfo, !IntervalInfo) :-
-    GoalPath = goal_info_get_goal_path(GoalInfo),
-    record_cond_end(GoalPath, !IntervalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    record_cond_end(GoalId, !IntervalInfo),
     get_cur_interval(ThenStartId, !.IntervalInfo),
     record_interval_start(ThenStartId, CondThenAnchor, !IntervalInfo),
     new_interval_id(CondTailId, !IntervalInfo),
-    CondThenAnchor = anchor_cond_then(GoalPath),
+    CondThenAnchor = anchor_cond_then(GoalId),
     record_interval_end(CondTailId, CondThenAnchor, !IntervalInfo),
     record_interval_succ(CondTailId, ThenStartId, !IntervalInfo),
     set_cur_interval(CondTailId, !IntervalInfo),
@@ -653,19 +653,18 @@
     interval_info::in, interval_info::out) is det.
 
 set_open_intervals(OpenIntervals, !IntervalInfo) :-
-    !:IntervalInfo = !.IntervalInfo ^ ii_open_intervals := OpenIntervals.
+    !IntervalInfo ^ ii_open_intervals := OpenIntervals.
 
 :- pred no_open_intervals(interval_info::in, interval_info::out) is det.
 
 no_open_intervals(!IntervalInfo) :-
-    !:IntervalInfo = !.IntervalInfo ^ ii_open_intervals := set.init.
+    !IntervalInfo ^ ii_open_intervals := set.init.
 
 :- pred one_open_interval(interval_id::in, interval_info::in,
     interval_info::out) is det.
 
 one_open_interval(IntervalId, !IntervalInfo) :-
-    !:IntervalInfo = !.IntervalInfo ^ ii_open_intervals :=
-        set.make_singleton_set(IntervalId).
+    !IntervalInfo ^ ii_open_intervals := set.make_singleton_set(IntervalId).
 
 :- pred assign_open_intervals_to_anchor(anchor::in,
     interval_info::in, interval_info::out) is det.
@@ -691,7 +690,7 @@
         svmap.det_insert(Anchor, AnchorFollowInfo,
             AnchorFollowMap0, AnchorFollowMap)
     ),
-    !:IntervalInfo = !.IntervalInfo ^ ii_anchor_follow_map := AnchorFollowMap.
+    !IntervalInfo ^ ii_anchor_follow_map := AnchorFollowMap.
 
 :- pred gather_interval_vars(map(interval_id, set(prog_var))::in,
     interval_id::in, set(prog_var)::in, set(prog_var)::out) is det.
@@ -722,29 +721,29 @@
     counter.allocate(Num, Counter0, Counter),
     Id = interval_id(Num),
     svmap.det_insert(Id, set.init, IntervalVars0, IntervalVars),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_counter := Counter,
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_vars := IntervalVars.
+    !IntervalInfo ^ ii_interval_counter := Counter,
+    !IntervalInfo ^ ii_interval_vars := IntervalVars.
 
-:- pred record_branch_end_info(goal_path::in,
+:- pred record_branch_end_info(goal_id::in,
     interval_info::in, interval_info::out) is det.
 
-record_branch_end_info(GoalPath, !IntervalInfo) :-
+record_branch_end_info(GoalId, !IntervalInfo) :-
     FlushedLater = !.IntervalInfo ^ ii_flushed_later,
     AccessedLater = !.IntervalInfo ^ ii_accessed_later,
     CurInterval = !.IntervalInfo ^ ii_cur_interval,
     BranchEndMap0 = !.IntervalInfo ^ ii_branch_end_map,
     BranchEndInfo = branch_end_info(FlushedLater, AccessedLater, CurInterval),
-    svmap.det_insert(GoalPath, BranchEndInfo, BranchEndMap0, BranchEndMap),
-    !:IntervalInfo = !.IntervalInfo ^ ii_branch_end_map := BranchEndMap.
+    svmap.det_insert(GoalId, BranchEndInfo, BranchEndMap0, BranchEndMap),
+    !IntervalInfo ^ ii_branch_end_map := BranchEndMap.
 
-:- pred record_cond_end(goal_path::in, interval_info::in, interval_info::out)
+:- pred record_cond_end(goal_id::in, interval_info::in, interval_info::out)
     is det.
 
-record_cond_end(GoalPath, !IntervalInfo) :-
+record_cond_end(GoalId, !IntervalInfo) :-
     CurInterval = !.IntervalInfo ^ ii_cur_interval,
     CondEndMap0 = !.IntervalInfo ^ ii_cond_end_map,
-    svmap.det_insert(GoalPath, CurInterval, CondEndMap0, CondEndMap),
-    !:IntervalInfo = !.IntervalInfo ^ ii_cond_end_map := CondEndMap.
+    svmap.det_insert(GoalId, CurInterval, CondEndMap0, CondEndMap),
+    !IntervalInfo ^ ii_cond_end_map := CondEndMap.
 
 :- pred record_interval_end(interval_id::in, anchor::in,
     interval_info::in, interval_info::out) is det.
@@ -752,7 +751,7 @@
 record_interval_end(Id, End, !IntervalInfo) :-
     EndMap0 = !.IntervalInfo ^ ii_interval_end,
     svmap.det_insert(Id, End, EndMap0, EndMap),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_end := EndMap.
+    !IntervalInfo ^ ii_interval_end := EndMap.
 
 :- pred record_interval_start(interval_id::in, anchor::in,
     interval_info::in, interval_info::out) is det.
@@ -760,7 +759,7 @@
 record_interval_start(Id, Start, !IntervalInfo) :-
     StartMap0 = !.IntervalInfo ^ ii_interval_start,
     svmap.det_insert(Id, Start, StartMap0, StartMap),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_start := StartMap.
+    !IntervalInfo ^ ii_interval_start := StartMap.
 
 :- pred record_interval_succ(interval_id::in, interval_id::in,
     interval_info::in, interval_info::out) is det.
@@ -772,7 +771,7 @@
     ;
         svmap.det_insert(Id, [Succ], SuccMap0, SuccMap)
     ),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_succ := SuccMap.
+    !IntervalInfo ^ ii_interval_succ := SuccMap.
 
 :- pred record_interval_no_succ(interval_id::in,
     interval_info::in, interval_info::out) is det.
@@ -784,7 +783,7 @@
     ;
         svmap.det_insert(Id, [], SuccMap0, SuccMap)
     ),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_succ := SuccMap.
+    !IntervalInfo ^ ii_interval_succ := SuccMap.
 
 record_interval_vars(Id, NewVars, !IntervalInfo) :-
     VarsMap0 = !.IntervalInfo ^ ii_interval_vars,
@@ -795,7 +794,7 @@
         set.list_to_set(NewVars, Vars),
         svmap.det_insert(Id, Vars, VarsMap0, VarsMap)
     ),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_vars := VarsMap.
+    !IntervalInfo ^ ii_interval_vars := VarsMap.
 
 delete_interval_vars(Id, ToDeleteVars, DeletedVars, !IntervalInfo) :-
     VarsMap0 = !.IntervalInfo ^ ii_interval_vars,
@@ -803,7 +802,7 @@
     DeletedVars = set.intersect(Vars0, ToDeleteVars),
     Vars = set.difference(Vars0, DeletedVars),
     svmap.det_update(Id, Vars, VarsMap0, VarsMap),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_vars := VarsMap,
+    !IntervalInfo ^ ii_interval_vars := VarsMap,
 
     % The deletions are recorded only for debugging. The algorithm itself
     % does not need this information to be recorded.
@@ -815,7 +814,7 @@
         Deletions = [DeletedVars],
         svmap.det_insert(Id, Deletions, DeleteMap0, DeleteMap)
     ),
-    !:IntervalInfo = !.IntervalInfo ^ ii_interval_delvars := DeleteMap.
+    !IntervalInfo ^ ii_interval_delvars := DeleteMap.
 
 :- pred require_in_regs(list(prog_var)::in, interval_info::in,
     interval_info::out) is det.
@@ -830,7 +829,7 @@
 require_flushed(Vars, !IntervalInfo) :-
     FlushedLater0 = !.IntervalInfo ^ ii_flushed_later,
     FlushedLater = set.union(FlushedLater0, Vars),
-    !:IntervalInfo = !.IntervalInfo ^ ii_flushed_later := FlushedLater.
+    !IntervalInfo ^ ii_flushed_later := FlushedLater.
 
 :- pred require_access(list(prog_var)::in,
     interval_info::in, interval_info::out) is det.
@@ -838,16 +837,16 @@
 require_access(Vars, !IntervalInfo) :-
     AccessedLater0 = !.IntervalInfo ^ ii_accessed_later,
     svset.insert_list(Vars, AccessedLater0, AccessedLater),
-    !:IntervalInfo = !.IntervalInfo ^ ii_accessed_later := AccessedLater.
+    !IntervalInfo ^ ii_accessed_later := AccessedLater.
 
-:- pred record_branch_resume(goal_path::in, resume_save_status::in,
+:- pred record_branch_resume(goal_id::in, resume_save_status::in,
     interval_info::in, interval_info::out) is det.
 
-record_branch_resume(GoalPath, ResumeSaveStatus, !IntervalInfo) :-
+record_branch_resume(GoalId, ResumeSaveStatus, !IntervalInfo) :-
     BranchResumeMap0 = !.IntervalInfo ^ ii_branch_resume_map,
-    svmap.det_insert(GoalPath, ResumeSaveStatus,
+    svmap.det_insert(GoalId, ResumeSaveStatus,
         BranchResumeMap0, BranchResumeMap),
-    !:IntervalInfo = !.IntervalInfo ^ ii_branch_resume_map := BranchResumeMap.
+    !IntervalInfo ^ ii_branch_resume_map := BranchResumeMap.
 
 :- pred record_model_non_anchor(anchor::in, interval_info::in,
     interval_info::out) is det.
@@ -855,7 +854,7 @@
 record_model_non_anchor(Anchor, !IntervalInfo) :-
     ModelNonAnchors0 = !.IntervalInfo ^ ii_model_non_anchors,
     svset.insert(Anchor, ModelNonAnchors0, ModelNonAnchors),
-    !:IntervalInfo = !.IntervalInfo ^ ii_model_non_anchors := ModelNonAnchors.
+    !IntervalInfo ^ ii_model_non_anchors := ModelNonAnchors.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -1134,8 +1133,8 @@
             MaybeNeedAcrossCall),
         MaybeNeedAcrossCall = yes(_NeedAcrossCall)
     ->
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
-        Anchor = anchor_call_site(GoalPath),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
+        Anchor = anchor_call_site(GoalId),
         lookup_inserts(InsertMap, Anchor, Inserts),
         insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, Inserts,
             MaybeFeature)
@@ -1234,9 +1233,9 @@
 
 construct_anchors(Construct, Goal, StartAnchor, EndAnchor) :-
     Goal = hlds_goal(_, GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
-    StartAnchor = anchor_branch_start(Construct, GoalPath),
-    EndAnchor = anchor_branch_end(Construct, GoalPath).
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    StartAnchor = anchor_branch_start(Construct, GoalId),
+    EndAnchor = anchor_branch_end(Construct, GoalId).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/layout_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/layout_out.m,v
retrieving revision 1.111
diff -u -r1.111 layout_out.m
--- compiler/layout_out.m	15 Dec 2010 06:29:41 -0000	1.111
+++ compiler/layout_out.m	17 Dec 2010 02:53:32 -0000
@@ -1095,7 +1095,7 @@
     coverage_point_info::in, int::in, int::out, io::di, io::uo) is det.
 
 output_proc_static_cp_static_slot(AutoComments, CoveragePoint, !Slot, !IO) :-
-    CoveragePoint = coverage_point_info(GoalPath, CPType),
+    CoveragePoint = coverage_point_info(RevGoalPath, CPType),
     io.write_string("{ ", !IO),
     (
         AutoComments = yes,
@@ -1104,7 +1104,7 @@
         AutoComments = no
     ),
     io.write_string("""", !IO),
-    GoalPathString = goal_path_to_string(GoalPath),
+    GoalPathString = rev_goal_path_to_string(RevGoalPath),
     io.write_string(GoalPathString, !IO),
     io.write_string(""", ", !IO),
     coverage_point_type_c_value(CPType, CPTypeCValue),
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.176
diff -u -r1.176 liveness.m
--- compiler/liveness.m	15 Dec 2010 06:29:41 -0000	1.176
+++ compiler/liveness.m	15 Dec 2010 06:33:18 -0000
@@ -219,8 +219,6 @@
 
 %-----------------------------------------------------------------------------%
 
-%-----------------------------------------------------------------------------%
-
 detect_liveness_preds_parallel(!HLDS) :-
     module_info_get_valid_predids(PredIds, !HLDS),
     detect_liveness_preds_parallel_2(PredIds, !.HLDS, !HLDS).
@@ -287,23 +285,23 @@
     globals.lookup_int_option(Globals, debug_liveness, DebugLiveness),
     pred_id_to_int(PredId, PredIdInt),
     trace [io(!IO)] (
-        maybe_debug_liveness("\nbefore liveness",
-            DebugLiveness, PredIdInt, Goal0, VarSet, ModuleInfo, !IO)
+        maybe_debug_liveness(ModuleInfo, "\nbefore liveness",
+            DebugLiveness, PredIdInt, VarSet, Goal0, !IO)
     ),
 
     initial_liveness(!.ProcInfo, PredId, ModuleInfo, Liveness0),
     detect_liveness_in_goal(Goal0, Goal1, Liveness0, _, LiveInfo),
 
     trace [io(!IO)] (
-        maybe_debug_liveness("\nafter liveness",
-            DebugLiveness, PredIdInt, Goal1, VarSet, ModuleInfo, !IO)
+        maybe_debug_liveness(ModuleInfo, "\nafter liveness",
+            DebugLiveness, PredIdInt, VarSet, Goal1, !IO)
     ),
 
     initial_deadness(!.ProcInfo, LiveInfo, ModuleInfo, Deadness0),
     detect_deadness_in_goal(Goal1, Goal2, Deadness0, _, Liveness0, LiveInfo),
     trace [io(!IO)] (
-        maybe_debug_liveness("\nafter deadness",
-            DebugLiveness, PredIdInt, Goal2, VarSet, ModuleInfo, !IO)
+        maybe_debug_liveness(ModuleInfo, "\nafter deadness",
+            DebugLiveness, PredIdInt, VarSet, Goal2, !IO)
     ),
 
     (
@@ -315,8 +313,8 @@
     ->
         delay_death_proc_body(Goal2, Goal3, VarSet, Liveness0),
         trace [io(!IO)] (
-            maybe_debug_liveness("\nafter delay death",
-                DebugLiveness, PredIdInt, Goal3, VarSet, ModuleInfo, !IO)
+            maybe_debug_liveness(ModuleInfo, "\nafter delay death",
+                DebugLiveness, PredIdInt, VarSet, Goal3, !IO)
         )
     ;
         Goal3 = Goal2
@@ -334,17 +332,17 @@
     detect_resume_points_in_goal(Goal3, Goal, Liveness0, _,
         LiveInfo, ResumeVars0),
     trace [io(!IO)] (
-        maybe_debug_liveness("\nafter resume point",
-            DebugLiveness, PredIdInt, Goal, VarSet, ModuleInfo, !IO)
+        maybe_debug_liveness(ModuleInfo, "\nafter resume point",
+            DebugLiveness, PredIdInt, VarSet, Goal, !IO)
     ),
     proc_info_set_goal(Goal, !ProcInfo),
     proc_info_set_liveness_info(Liveness0, !ProcInfo).
 
-:- pred maybe_debug_liveness(string::in, int::in, int::in,
-    hlds_goal::in, prog_varset::in, module_info::in, io::di, io::uo) is det.
+:- pred maybe_debug_liveness(module_info::in, string::in, int::in, int::in,
+    prog_varset::in, hlds_goal::in, io::di, io::uo) is det.
 
-maybe_debug_liveness(Message, DebugLiveness, PredIdInt,
-        Goal, VarSet, ModuleInfo, !IO) :-
+maybe_debug_liveness(ModuleInfo, Message, DebugLiveness, PredIdInt, VarSet,
+        Goal, !IO) :-
     ( DebugLiveness = PredIdInt ->
         io.write_string(Message, !IO),
         io.write_string(":\n", !IO),
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.369
diff -u -r1.369 llds.m
--- compiler/llds.m	15 Dec 2010 06:29:42 -0000	1.369
+++ compiler/llds.m	15 Dec 2010 06:33:18 -0000
@@ -299,12 +299,12 @@
             % *appears* to be unused by the following code.
 
     ;       llcall(code_addr, code_addr, list(liveinfo), term.context,
-                goal_path, call_model)
+                maybe(forward_goal_path), call_model)
             % llcall(Target, Continuation, _, _, _) is the same as
             % succip = Continuation; goto(Target).
             % The third argument is the live value info for the values live
             % on return. The fourth argument gives the context of the call.
-            % The fifth gives the goal path of the call in the body of the
+            % The fifth gives the goal id of the call in the body of the
             % procedure; it is meaningful only if execution tracing is enabled.
             % The last gives the code model of the called procedure, and if
             % it is model_non, says whether tail recursion elimination is
Index: compiler/mark_tail_calls.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mark_tail_calls.m,v
retrieving revision 1.2
diff -u -r1.2 mark_tail_calls.m
--- compiler/mark_tail_calls.m	5 Aug 2010 03:07:08 -0000	1.2
+++ compiler/mark_tail_calls.m	23 Aug 2010 08:10:16 -0000
@@ -146,8 +146,8 @@
         GoalExpr0 = unify(_, _, _, Unify0, _),
         Goal = Goal0,
         (
-            ( Unify0 = construct(_, _, _, _, _, __, _)
-            ; Unify0 = deconstruct(_, _, _, _, __, _)
+            ( Unify0 = construct(_, _, _, _, _, _, _)
+            ; Unify0 = deconstruct(_, _, _, _, _, _)
             ; Unify0 = simple_test(_, _)
             ; Unify0 = complicated_unify(_, _, _)
             ),
Index: compiler/mercury_compile_front_end.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile_front_end.m,v
retrieving revision 1.7
diff -u -r1.7 mercury_compile_front_end.m
--- compiler/mercury_compile_front_end.m	15 Dec 2010 06:29:45 -0000	1.7
+++ compiler/mercury_compile_front_end.m	15 Dec 2010 06:33:19 -0000
@@ -629,7 +629,7 @@
         ModeConstraints = yes,
         maybe_write_string(Verbose, "% Dumping mode constraints...\n", !IO),
         maybe_flush_output(Verbose, !IO),
-        maybe_benchmark_modes(mode_constraints.process_module,
+        maybe_benchmark_modes(mc_process_module,
             "mode-constraints", !HLDS, !IO),
         maybe_write_string(Verbose, "% done.\n", !IO),
         maybe_report_stats(Stats, !IO)
Index: compiler/mercury_compile_llds_back_end.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile_llds_back_end.m,v
retrieving revision 1.9
diff -u -r1.9 mercury_compile_llds_back_end.m
--- compiler/mercury_compile_llds_back_end.m	15 Dec 2010 06:29:45 -0000	1.9
+++ compiler/mercury_compile_llds_back_end.m	15 Dec 2010 06:33:19 -0000
@@ -50,9 +50,9 @@
 :- import_module backend_libs.rtti.
 :- import_module backend_libs.type_class_info.
 :- import_module backend_libs.type_ctor_info.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.simplify.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_out.
 :- import_module hlds.hlds_out.hlds_out_util.
@@ -171,9 +171,6 @@
     allocate_store_map(Verbose, Stats, !HLDS, !IO),
     maybe_dump_hlds(!.HLDS, 340, "store_map", !DumpInfo, !IO),
 
-    maybe_goal_paths(Verbose, Stats, !HLDS, !IO),
-    maybe_dump_hlds(!.HLDS, 345, "precodegen", !DumpInfo, !IO),
-
     generate_llds_code_for_module(!.HLDS, Verbose, Stats, !GlobalData, !:LLDS,
         !IO),
 
@@ -370,14 +367,6 @@
         "% Allocating storage locations for live vars in ",
         PredId, ProcId, !.HLDS, !IO),
     allocate_store_maps(final_allocation, !.HLDS, PredProcId, !ProcInfo),
-    globals.get_trace_level(Globals, TraceLevel),
-    ( given_trace_level_is_none(TraceLevel) = no ->
-        write_proc_progress_message("% Calculating goal paths in ",
-            PredId, ProcId, !.HLDS, !IO),
-        fill_goal_path_slots(!.HLDS, !ProcInfo)
-    ;
-        true
-    ),
     write_proc_progress_message("% Generating low-level (LLDS) code for ",
         PredId, ProcId, !.HLDS, !IO),
     generate_proc_code(PredInfo, !.ProcInfo, PredId, ProcId, !.HLDS,
@@ -527,23 +516,6 @@
     maybe_write_string(Verbose, " done.\n", !IO),
     maybe_report_stats(Stats, !IO).
 
-:- pred maybe_goal_paths(bool::in, bool::in,
-    module_info::in, module_info::out, io::di, io::uo) is det.
-
-maybe_goal_paths(Verbose, Stats, !HLDS, !IO) :-
-    module_info_get_globals(!.HLDS, Globals),
-    globals.get_trace_level(Globals, TraceLevel),
-    ( given_trace_level_is_none(TraceLevel) = no ->
-        maybe_write_string(Verbose, "% Calculating goal paths...", !IO),
-        maybe_flush_output(Verbose, !IO),
-        process_all_nonimported_procs(update_proc(fill_goal_path_slots),
-            !HLDS),
-        maybe_write_string(Verbose, " done.\n", !IO),
-        maybe_report_stats(Stats, !IO)
-    ;
-        true
-    ).
-
 :- pred generate_llds_code_for_module(module_info::in, bool::in, bool::in,
     global_data::in, global_data::out, list(c_procedure)::out,
     io::di, io::uo) is det.
Index: compiler/mercury_compile_middle_passes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile_middle_passes.m,v
retrieving revision 1.9
diff -u -r1.9 mercury_compile_middle_passes.m
--- compiler/mercury_compile_middle_passes.m	15 Dec 2010 06:29:45 -0000	1.9
+++ compiler/mercury_compile_middle_passes.m	20 Dec 2010 03:17:19 -0000
@@ -1067,7 +1067,7 @@
         ReuseAnalysis = yes,
         maybe_write_string(Verbose, "% Structure reuse analysis...\n", !IO),
         maybe_flush_output(Verbose, !IO),
-        structure_reuse_analysis(!HLDS, !IO),
+        perform_structure_reuse_analysis(!HLDS, !IO),
         maybe_write_string(Verbose, "% done.\n", !IO),
         maybe_report_stats(Stats, !IO)
     ;
Index: compiler/mode_constraint_robdd.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_constraint_robdd.m,v
retrieving revision 1.15
diff -u -r1.15 mode_constraint_robdd.m
--- compiler/mode_constraint_robdd.m	4 Sep 2008 11:41:00 -0000	1.15
+++ compiler/mode_constraint_robdd.m	28 Mar 2010 01:51:16 -0000
@@ -26,6 +26,7 @@
 :- import_module parse_tree.
 :- import_module parse_tree.prog_data.
 :- import_module hlds.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_pred.
 :- import_module mdbcomp.
 :- import_module mdbcomp.program_representation.
@@ -48,12 +49,12 @@
 :- type threshold.
 
 :- func init_mode_constraint_info(bool) = mode_constraint_info.
-:- func 'pred_id :='(mode_constraint_info, pred_id) = mode_constraint_info.
+:- func mci_set_pred_id(mode_constraint_info, pred_id) = mode_constraint_info.
 
 :- type rep_var
     --->    in(prog_var)
-    ;   out(prog_var)
-    ;   prog_var `at` goal_path.
+    ;       out(prog_var)
+    ;       prog_var `at` goal_id.
 
     % Lookup a var in the mode_constraint_info. If the var is not found,
     % insert it.
@@ -69,29 +70,29 @@
 :- func mode_constraint_var(mode_constraint_info, rep_var) =
     mode_constraint_var.
 
-:- pred enter_lambda_goal(goal_path::in, mode_constraint_info::in,
+:- pred enter_lambda_goal(goal_id::in, mode_constraint_info::in,
     mode_constraint_info::out) is det.
 
 :- pred leave_lambda_goal(mode_constraint_info::in, mode_constraint_info::out)
     is det.
 
-    % lambda_path extends the idea of the goal_path to allow describing the
+    % lambda_path extends the idea of the goal_id to allow describing the
     % location of a goal within nested lambda goals.
-:- type lambda_path == stack(goal_path).
+:- type lambda_path == stack(goal_id).
 
     % Describes a var, its pred-id and lambda-nesting level.
     % XXX think up a better name for this.
 :- type prog_var_and_level.
 
-:- pred get_prog_var_level(prog_var::in, prog_var_and_level::out,
-    mode_constraint_info::in, mode_constraint_info::out) is det.
+:- pred get_prog_var_level(mode_constraint_info::in, prog_var::in,
+    prog_var_and_level::out) is det.
 
 :- pred set_level_from_var(prog_var_and_level::in,
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
     % Return the current max var for later use by restrict_threshold.
-:- pred save_threshold(threshold::out, mode_constraint_info::in,
-    mode_constraint_info::out) is det.
+    %
+:- pred save_threshold(mode_constraint_info::in, threshold::out) is det.
 
 :- func restrict_threshold(threshold, mode_constraint) = mode_constraint.
 
@@ -99,18 +100,18 @@
     mode_constraint) = mode_constraint.
 :- mode restrict_filter(pred(in) is semidet, in, in) = out is det.
 
-:- pred save_min_var_for_pred(pred_id::in, mode_constraint_info::in,
-    mode_constraint_info::out) is det.
+:- pred save_min_var_for_pred(pred_id::in,
+    mode_constraint_info::in, mode_constraint_info::out) is det.
 
 :- pred save_max_var_for_pred(pred_id::in, mode_constraint_info::in,
     mode_constraint_info::out) is det.
 
-:- pred get_interesting_vars_for_pred(pred_id::in,
-    set(mode_constraint_var)::out, mode_constraint_info::in,
-    mode_constraint_info::out) is det.
+:- pred get_interesting_vars_for_pred(mode_constraint_info::in, pred_id::in,
+    set(mode_constraint_var)::out) is det.
 
     % Set the input_nodes field of the mode_constraint_info and make sure
     % the zero_var is constrained to be zero in the mode_constraint.
+    %
 :- pred set_input_nodes(mode_constraint::in, mode_constraint::out,
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
@@ -120,8 +121,16 @@
 :- pred unset_simple_mode_constraints(mode_constraint_info::in,
     mode_constraint_info::out) is det.
 
-:- pred using_simple_mode_constraints(mode_constraint_info::in,
-    mode_constraint_info::out) is semidet.
+:- pred using_simple_mode_constraints(mode_constraint_info::in) is semidet.
+
+:- pred get_forward_goal_path_map(mode_constraint_info::in,
+    goal_forward_path_map::out) is det.
+
+:- pred get_forward_goal_path_map_for_pred(mode_constraint_info::in,
+    pred_id::in, goal_forward_path_map::out) is det.
+
+:- pred add_forward_goal_path_map(pred_id::in, goal_forward_path_map::in,
+    mode_constraint_info::in, mode_constraint_info::out) is det.
 
 % Remove the comments here and on the definition if you want to debug
 % the mode constraint system.
@@ -169,29 +178,34 @@
 
 :- type mode_constraint_info
     --->    mode_constraint_info(
-                varset              :: varset(mc_type),
-                varmap              :: mode_constraint_varmap,
-                pred_id             :: pred_id,
-                lambda_path         :: lambda_path,
-                min_vars            :: map(pred_id, mode_constraint_var),
-                max_vars            :: map(pred_id, mode_constraint_var),
-                input_nodes         :: sparse_bitset(prog_var),
-                zero_var            :: robdd_var,
-                                    % A var that is always zero.
-                simple_constraints  :: bool
-                                    % Are we using the simplified constraint
-                                    % model.
+                mci_varset              :: varset(mc_type),
+                mci_varmap              :: mode_constraint_varmap,
+                mci_pred_id             :: pred_id,
+                mci_lambda_path         :: lambda_path,
+                mci_min_vars            :: map(pred_id, mode_constraint_var),
+                mci_max_vars            :: map(pred_id, mode_constraint_var),
+                mci_input_nodes         :: sparse_bitset(prog_var),
+
+                % A var that is always zero.
+                mci_zero_var            :: robdd_var,
+
+                % Are we using the simplified constraint model.
+                mci_simple_constraints  :: bool,
+
+                mci_goal_path_map       :: map(pred_id, goal_forward_path_map)
             ).
 
+mci_set_pred_id(MCI, PredId) = MCI ^ mci_pred_id := PredId.
+
 :- type threshold
     --->    threshold(mode_constraint_var).
 
-init_mode_constraint_info(Simple) = Info :-
+init_mode_constraint_info(Simple) = MCI :-
     VarSet0 = varset.init,
     varset.new_var(VarSet0, ZeroVar, VarSet),
     PredId = hlds_pred.initial_pred_id,
-    Info = mode_constraint_info(VarSet, bimap.init, PredId, stack.init,
-        map.init, map.init, sparse_bitset.init, ZeroVar, Simple).
+    MCI = mode_constraint_info(VarSet, bimap.init, PredId, stack.init,
+        map.init, map.init, sparse_bitset.init, ZeroVar, Simple, map.init).
 
 :- type robdd_var == var(mc_type).
 
@@ -201,45 +215,50 @@
     % `pred_id' is the predicate the variable belongs to.
     % `lambda_path' describes the location of the lambda_goal
     % we are referring to.
-:- type varmap_key ---> key(rep_var, pred_id, lambda_path).
+:- type varmap_key
+    --->    key(
+                rep_var,
+                pred_id,
+                lambda_path
+            ).
 
-mode_constraint_var(RepVar0, RobddVar, Info0, Info) :-
-    mode_constraint_var(Info0 ^ pred_id, RepVar0, RobddVar, Info0, Info).
+mode_constraint_var(RepVar0, RobddVar, !MCI) :-
+    mode_constraint_var(!.MCI ^ mci_pred_id, RepVar0, RobddVar, !MCI).
 
-mode_constraint_var(PredId, RepVar0, RobddVar, Info0, Info) :-
+mode_constraint_var(PredId, RepVar0, RobddVar, !MCI) :-
     (
         RepVar0 = ProgVar `at` _,
-        Info0 ^ input_nodes `contains` ProgVar
+        !.MCI ^ mci_input_nodes `contains` ProgVar
     ->
         % This RepVar must be false since the corresponding input var
         % is true.  We can just return the zero var.
-        RobddVar = Info0 ^ zero_var,
-        Info = Info0
+        RobddVar = !.MCI ^ mci_zero_var
     ;
         RepVar = RepVar0,
-        LambdaPath = Info0 ^ lambda_path,
-        Key = key(RepVar, PredId, LambdaPath),
-        ( bimap.search(Info0 ^ varmap, Key, RobddVar0) ->
-            RobddVar = RobddVar0,
-            Info = Info0
+        LambdaId = !.MCI ^ mci_lambda_path,
+        Key = key(RepVar, PredId, LambdaId),
+        ( bimap.search(!.MCI ^ mci_varmap, Key, RobddVar0) ->
+            RobddVar = RobddVar0
         ;
-            varset.new_var(Info0 ^ varset, RobddVar, NewVarSet),
-            bimap.set(Info0 ^ varmap, Key, RobddVar, NewVarMap),
-            Info = (Info0 ^ varset := NewVarSet) ^ varmap := NewVarMap
+            varset.new_var(!.MCI ^ mci_varset, RobddVar, NewVarSet),
+            bimap.set(!.MCI ^ mci_varmap, Key, RobddVar, NewVarMap),
+            !MCI ^ mci_varset := NewVarSet,
+            !MCI ^ mci_varmap := NewVarMap
         )
     ).
 
-mode_constraint_var(Info, RepVar) = bimap.lookup(Info ^ varmap, Key) :-
-    Key = key(RepVar, Info ^ pred_id, Info ^ lambda_path).
-
-enter_lambda_goal(GoalPath, !Info) :-
-    LambdaPath0 = !.Info ^ lambda_path,
-    !:Info = !.Info ^ lambda_path := stack.push(LambdaPath0, GoalPath).
-
-leave_lambda_goal -->
-    LambdaPath0 =^ lambda_path,
-    { stack.pop_det(LambdaPath0, _GoalPath, LambdaPath) },
-    ^ lambda_path := LambdaPath.
+mode_constraint_var(MCI, RepVar) = Var :-
+    Key = key(RepVar, MCI ^ mci_pred_id, MCI ^ mci_lambda_path),
+    bimap.lookup(MCI ^ mci_varmap, Key, Var).
+
+enter_lambda_goal(GoalId, !MCI) :-
+    LambdaPath0 = !.MCI ^ mci_lambda_path,
+    !MCI ^ mci_lambda_path := stack.push(LambdaPath0, GoalId).
+
+leave_lambda_goal(!MCI) :-
+    LambdaPath0 = !.MCI ^ mci_lambda_path,
+    stack.pop_det(LambdaPath0, _GoalPath, LambdaPath),
+    !MCI ^ mci_lambda_path := LambdaPath.
 
 :- type prog_var_and_level
     --->    prog_var_and_level(
@@ -248,53 +267,57 @@
                 lambda_path
             ).
 
-get_prog_var_level(Var, prog_var_and_level(Var, PredId, LambdaPath)) -->
-    PredId =^ pred_id,
-    LambdaPath =^ lambda_path.
-
-set_level_from_var(prog_var_and_level(_Var, PredId, LambdaPath)) -->
-    ^ pred_id := PredId,
-    ^ lambda_path := LambdaPath.
+get_prog_var_level(MCI, Var, prog_var_and_level(Var, PredId, LambdaPath)) :-
+    PredId = MCI ^ mci_pred_id,
+    LambdaPath = MCI ^ mci_lambda_path.
+
+set_level_from_var(prog_var_and_level(_Var, PredId, LambdaPath), !MCI) :-
+    !MCI ^ mci_pred_id := PredId,
+    !MCI ^ mci_lambda_path := LambdaPath.
 
-save_threshold(threshold(varset.max_var(VarSet))) -->
-    VarSet =^ varset.
+save_threshold(MCI, threshold(varset.max_var(VarSet))) :-
+    VarSet = MCI ^ mci_varset.
 
 restrict_threshold(threshold(Threshold), Constraint) =
     restrict_threshold(Threshold, ensure_normalised(Constraint)).
 
-restrict_filter(P0, Info, M) = restrict_filter(P, ensure_normalised(M)) :-
+restrict_filter(P0, MCI, M) = restrict_filter(P, ensure_normalised(M)) :-
     P = (pred(MCV::in) is semidet :-
-        bimap.reverse_lookup(Info ^ varmap, key(RV, PredId, _), MCV),
-        ( PredId \= Info ^ pred_id ; P0(RV) )
+        bimap.reverse_lookup(MCI ^ mci_varmap, key(RV, PredId, _), MCV),
+        (
+            PredId \= MCI ^ mci_pred_id
+        ;
+            P0(RV)
+        )
     ).
 
-save_min_var_for_pred(PredId) -->
-    save_threshold(threshold(Threshold)),
-    MinVars0 =^ min_vars,
-    { map.set(MinVars0, PredId, Threshold, MinVars) },
-    ^ min_vars := MinVars.
-
-save_max_var_for_pred(PredId) -->
-    save_threshold(threshold(Threshold)),
-    MaxVars0 =^ max_vars,
-    { map.set(MaxVars0, PredId, Threshold, MaxVars) },
-    ^ max_vars := MaxVars.
-
-get_interesting_vars_for_pred(PredId, Vars) -->
-    MinVars =^ min_vars,
-    MaxVars =^ max_vars,
-    VarSet =^ varset,
-    { Vars = ( set.sorted_list_to_set `compose`
+save_min_var_for_pred(PredId, !MCI) :-
+    save_threshold(!.MCI, threshold(Threshold)),
+    MinVars0 = !.MCI ^ mci_min_vars,
+    map.set(MinVars0, PredId, Threshold, MinVars),
+    !MCI ^ mci_min_vars := MinVars.
+
+save_max_var_for_pred(PredId, !MCI) :-
+    save_threshold(!.MCI, threshold(Threshold)),
+    MaxVars0 = !.MCI ^ mci_max_vars,
+    map.set(MaxVars0, PredId, Threshold, MaxVars),
+    !MCI ^ mci_max_vars := MaxVars.
+
+get_interesting_vars_for_pred(MCI, PredId, Vars) :-
+    MinVars = MCI ^ mci_min_vars,
+    MaxVars = MCI ^ mci_max_vars,
+    VarSet = MCI ^ mci_varset,
+    Vars = ( set.sorted_list_to_set `compose`
         list.filter((pred(V::in) is semidet :-
-        compare(<, map.lookup(MinVars, PredId), V),
-        \+ compare(<, map.lookup(MaxVars, PredId), V))) `compose`
-        varset.vars
-    )(VarSet) }.
-
-set_input_nodes(Constraint0, Constraint, Info0, Info) :-
-    VarMap = Info0 ^ varmap,
-    LambdaPath = Info0 ^ lambda_path,
-    PredId = Info0 ^ pred_id,
+            compare(<, map.lookup(MinVars, PredId), V),
+            \+ compare(<, map.lookup(MaxVars, PredId), V)
+        )) `compose` varset.vars
+    )(VarSet).
+
+set_input_nodes(Constraint0, Constraint, !MCI) :-
+    VarMap = !.MCI ^ mci_varmap,
+    LambdaPath = !.MCI ^ mci_lambda_path,
+    PredId = !.MCI ^ mci_pred_id,
     bimap.ordinates(VarMap, Keys),
     Constraint1 = ensure_normalised(Constraint0),
     solutions.solutions((pred(ProgVar::out) is nondet :-
@@ -303,22 +326,34 @@
             bimap.lookup(VarMap, Key, RobddVar),
             var_entailed(Constraint1, RobddVar)
         ), InputNodes),
-    Info = Info0 ^ input_nodes := sorted_list_to_set(InputNodes),
-    Constraint = Constraint0 ^ not_var(Info ^ zero_var).
+    !MCI ^ mci_input_nodes := sorted_list_to_set(InputNodes),
+    Constraint = Constraint0 ^ not_var(!.MCI ^ mci_zero_var).
+
+set_simple_mode_constraints(!MCI) :-
+    !MCI ^ mci_simple_constraints := yes.
+
+unset_simple_mode_constraints(!MCI) :-
+    !MCI ^ mci_simple_constraints := no.
 
-set_simple_mode_constraints -->
-    ^ simple_constraints := yes.
+using_simple_mode_constraints(MCI) :-
+    MCI ^ mci_simple_constraints = yes.
 
-unset_simple_mode_constraints -->
-    ^ simple_constraints := no.
+get_forward_goal_path_map(MCI, ForwardGoalPathMap) :-
+    map.lookup(MCI ^ mci_goal_path_map, MCI ^ mci_pred_id, ForwardGoalPathMap).
 
-using_simple_mode_constraints -->
-    yes =^ simple_constraints.
+get_forward_goal_path_map_for_pred(MCI, PredId, ForwardGoalPathMap) :-
+    map.lookup(MCI ^ mci_goal_path_map, PredId, ForwardGoalPathMap).
 
-% dump_mode_constraints(_ModuleInfo, _PredInfo, _InstGraph, ROBDD, Info) -->
+add_forward_goal_path_map(PredId, ForwardGoalPathMap, !MCI) :-
+    ForwardGoalPathMapMap0 = !.MCI ^ mci_goal_path_map,
+    map.det_insert(ForwardGoalPathMapMap0, PredId, ForwardGoalPathMap,
+        ForwardGoalPathMapMap),
+    !MCI ^ mci_goal_path_map := ForwardGoalPathMapMap.
+
+% dump_mode_constraints(_ModuleInfo, _PredInfo, _InstGraph, ROBDD, MCI) -->
 %   { AL = (list.sort `compose`
 %       assoc_list.reverse_members `compose`
-%       bimap.to_assoc_list)(Info ^ varmap) },
+%       bimap.to_assoc_list)(MCI ^ mci_varmap) },
 %   list.foldl((pred((MCV - key(RV, _, _))::in, di, uo) is det -->
 %       print(MCV), write_string("\t"), print(RV), nl), AL),
 %
@@ -346,82 +381,50 @@
     varset.lookup_name(VarSet, V, Name),
     io.write_string(Name, !IO),
     io.write_string("_out", !IO).
-dump_mode_constraint_var(VarSet, V `at` Path, !IO) :-
+dump_mode_constraint_var(VarSet, V `at` Id, !IO) :-
     varset.lookup_name(VarSet, V, Name),
     io.write_string(Name, !IO),
     io.write_char('_', !IO),
-    PathSteps = goal_path_to_list(Path),
-    list.foldl(dump_goal_path_step, PathSteps, !IO).
-
-:- pred dump_goal_path_step(goal_path_step::in, io::di, io::uo) is det.
+    Id = goal_id(IdNum),
+    io.write_int(IdNum, !IO).
 
-dump_goal_path_step(step_conj(N), !IO) :-
-    io.write_char('c', !IO),
-    io.write_int(N, !IO).
-dump_goal_path_step(step_disj(N), !IO) :-
-    io.write_char('d', !IO),
-    io.write_int(N, !IO).
-dump_goal_path_step(step_switch(N, _), !IO) :-
-    io.write_char('s', !IO),
-    io.write_int(N, !IO).
-dump_goal_path_step(step_ite_cond, !IO) :-
-    io.write_char('c', !IO).
-dump_goal_path_step(step_ite_then, !IO) :-
-    io.write_char('t', !IO).
-dump_goal_path_step(step_ite_else, !IO) :-
-    io.write_char('e', !IO).
-dump_goal_path_step(step_neg, !IO) :-
-    io.write_char('n', !IO).
-dump_goal_path_step(step_scope(_), !IO) :-
-    io.write_char('q', !IO).
-dump_goal_path_step(step_first, !IO) :-
-    io.write_char('f', !IO).
-dump_goal_path_step(step_later, !IO) :-
-    io.write_char('l', !IO).
-dump_goal_path_step(step_atomic_main, !IO) :-
-    io.write_char('a', !IO).
-dump_goal_path_step(step_atomic_orelse(N), !IO) :-
-    io.write_char('o', !IO),
-    io.write_int(N, !IO).
-
-robdd_to_dot(Constraint, ProgVarSet, Info, FileName, !IO) :-
-    robdd_to_dot(Constraint ^ robdd, P, FileName, !IO),
-    VarMap = Info ^ varmap,
+robdd_to_dot(Constraint, ProgVarSet, MCI, FileName, !IO) :-
+    VarMap = MCI ^ mci_varmap,
     P = (pred(RobddVar::in, di, uo) is det -->
-        { bimap.reverse_lookup(VarMap, key(RepVar, PredId, LambdaPath),
+        { bimap.reverse_lookup(VarMap, key(RepVar, PredId, LambdaId),
             RobddVar) },
         dump_mode_constraint_var(ProgVarSet, RepVar),
         io.write_string(" "),
         { pred_id_to_int(PredId, PredIdNum) },
         io.write_int(PredIdNum),
         io.write_string(" "),
-        io.write_int(stack.depth(LambdaPath)),
+        io.write_int(stack.depth(LambdaId)),
         io.write_string(" ("),
         io.write_int(term.var_to_int(RobddVar)),
         io.write_string(")")
-    ).
+    ),
+    robdd_to_dot(Constraint ^ robdd, P, FileName, !IO).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-atomic_prodvars_map(Constraint, MCInfo) =
+atomic_prodvars_map(Constraint, MCI) =
     (
         some_vars(VarsEntailed) = vars_entailed(ensure_normalised(Constraint))
     ->
         list.foldl(
             (func(MCVar, PVM) =
                 (
-                    bimap.reverse_lookup(MCInfo ^ varmap, Key, MCVar),
-                    Key = key(RepVar, PredId, LambdaPath0),
-                    PredId = MCInfo ^ pred_id,
-                    RepVar = ProgVar `at` GoalPath,
-                    LambdaPath = stack.push(LambdaPath0, GoalPath)
+                    bimap.reverse_lookup(MCI ^ mci_varmap, Key, MCVar),
+                    Key = key(RepVar, PredId, LambdaId0),
+                    PredId = MCI ^ mci_pred_id,
+                    RepVar = ProgVar `at` GoalId,
+                    LambdaId = stack.push(LambdaId0, GoalId)
                 ->
-                    ( Vs = map.search(PVM, LambdaPath) ->
-                    map.det_update(PVM, LambdaPath,
-                        Vs `insert` ProgVar)
+                    ( Vs = map.search(PVM, LambdaId) ->
+                        map.det_update(PVM, LambdaId, Vs `insert` ProgVar)
                     ;
-                    map.det_insert(PVM, LambdaPath,
-                        make_singleton_set(ProgVar))
+                        map.det_insert(PVM, LambdaId,
+                            make_singleton_set(ProgVar))
                     )
                 ;
                     PVM
Index: compiler/mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_constraints.m,v
retrieving revision 1.56
diff -u -r1.56 mode_constraints.m
--- compiler/mode_constraints.m	15 Dec 2010 06:29:50 -0000	1.56
+++ compiler/mode_constraints.m	20 Dec 2010 07:34:36 -0000
@@ -28,7 +28,7 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred process_module(module_info::in, module_info::out,
+:- pred mc_process_module(module_info::in, module_info::out,
     io::di, io::uo) is det.
 
     % dump_abstract_constraints(ModuleInfo, Varset, PredConstraintsMap, !IO)
@@ -49,10 +49,10 @@
 :- import_module check_hlds.build_mode_constraints.
 :- import_module check_hlds.ordering_mode_constraints.
 
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.mode_constraint_robdd.
 :- import_module check_hlds.mode_ordering.
 :- import_module check_hlds.mode_util.
+:- import_module hlds.goal_path.
 :- import_module hlds.hhf.
 :- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_goal.
@@ -114,7 +114,7 @@
     func 'ho_modes :='(T, ho_modes) = T
 ].
 
-process_module(!ModuleInfo, !IO) :-
+mc_process_module(!ModuleInfo, !IO) :-
     module_info_get_valid_predids(PredIds, !ModuleInfo),
     module_info_get_globals(!.ModuleInfo, Globals),
     globals.lookup_bool_option(Globals, simple_mode_constraints, Simple),
@@ -122,21 +122,20 @@
 
     (
         New = no,
-        list__foldl2(hhf__process_pred(Simple), PredIds, !ModuleInfo, !IO),
+        list.foldl2(hhf.process_pred(Simple), PredIds, !ModuleInfo, !IO),
         get_predicate_sccs(!ModuleInfo, SCCs),
 
         % Stage 1: Process SCCs bottom-up to determine variable producers.
-        list.foldl3(process_scc(Simple), SCCs,
-            !ModuleInfo, map.init, PredConstraintMap, !IO),
+        list.foldl2(mc_process_scc(Simple), SCCs,
+            map.init, PredConstraintMap, !ModuleInfo),
 
         % Stage 2: Process SCCs top-down to determine execution order of
         % conjuctions and which modes are needed for each predicate.
-        mode_ordering(PredConstraintMap, list.reverse(SCCs),
-            !ModuleInfo, !IO),
+        mode_ordering(PredConstraintMap, list.reverse(SCCs), !ModuleInfo, !IO),
 
         % Stage 3, which would turn the results of the mode analysis
         % into goal annotations that the rest of the compiler can
-        % understand, doesn't exist yet. The whole point of this way of
+        % understand, doesn't exist yet.The whole point of this way of
         % doing mode analysis is to gain extra expressive power (e.g.
         % partially instantiated data structures), and the rest of the
         % compiler doesn't handle the extra expressive power yet.
@@ -147,16 +146,16 @@
         get_predicate_sccs(!ModuleInfo, SCCs),
 
         % Preprocess to accommodate implied modes.
-        % XXX The following transformation adds more unifications
-        % than is neccessary - eg, for arguments that will eventually
-        % be `in' modes anyway. The resulting loosening of constraints
-        % makes analysis take up to twice as long. Therefore, a more
-        % subtle approach would likely become a significant optimization.
+        % XXX The following transformation adds more unifications than is
+        % necessary; for example, for arguments that will eventually have `in'
+        % modes anyway. The resulting loosening of constraints makes analysis
+        % take up to twice as long. Therefore, a more subtle approach would
+        % likely be a significant optimization.
         list.foldl(ensure_unique_arguments, PredIds, !ModuleInfo),
 
-        % Requantify to avoid the appearance of variables in nonlocal
-        % sets that don't appear in the goal. (This makes it appear
-        % that the goal consumes the variable.)
+        % Requantify to avoid the appearance of variables in nonlocal sets
+        % that don't appear in the goal. (This makes it appear that the goal
+        % consumes the variable.)
         list.foldl(correct_nonlocals_in_pred, PredIds, !ModuleInfo),
 
         % Stage 1: Process SCCs bottom-up to determine constraints on
@@ -169,8 +168,10 @@
         (
             Debug = yes,
             ConstraintVarset = mc_varset(VarInfo),
-            pretty_print_pred_constraints_map(!.ModuleInfo, ConstraintVarset,
-                AbstractModeConstraints, !IO)
+            trace [io(!IO)] (
+                pretty_print_pred_constraints_map(!.ModuleInfo,
+                    ConstraintVarset, AbstractModeConstraints, !IO)
+            )
         ;
             Debug = no
         ),
@@ -183,8 +184,11 @@
 
         (
             Debug = yes,
-            list.foldl(ordering_mode_constraints.dump_goal_paths(!.ModuleInfo),
-                SCCs, !IO)
+            trace [io(!IO)] (
+                list.foldl(
+                    ordering_mode_constraints.dump_goal_paths(!.ModuleInfo),
+                    SCCs, !IO)
+            )
         ;
             Debug = no
         )
@@ -262,35 +266,31 @@
     (
         Warnings = []
     ;
-        Warnings = [_|_],
+        Warnings = [_ | _],
         unexpected(this_file, "Quantification error during constraints" ++
             " based mode analysis")
     ).
 
-:- pred process_scc(bool::in, list(pred_id)::in,
-    module_info::in, module_info::out,
-    pred_constraint_map::in, pred_constraint_map::out, io::di, io::uo) is det.
+:- pred mc_process_scc(bool::in, list(pred_id)::in,
+    pred_constraint_map::in, pred_constraint_map::out,
+    module_info::in, module_info::out) is det.
 
-process_scc(Simple, SCC, !ModuleInfo, !PredConstraintMap,
-        !IO) :-
-    some [!ModeConstraint, !ModeConstraintInfo] (
+mc_process_scc(Simple, SCC, !PredConstraintMap, !ModuleInfo) :-
+    some [!ModeConstraint, !MCI] (
         !:ModeConstraint = one,
-        !:ModeConstraintInfo = init_mode_constraint_info(Simple),
-        list.foldl2(number_robdd_variables_in_pred, SCC, !ModuleInfo,
-            !ModeConstraintInfo),
-
-        save_threshold(Threshold, !ModeConstraintInfo),
-        process_scc_pass_1(SCC, SCC, !ModuleInfo,
-            !ModeConstraint, !ModeConstraintInfo, !IO),
+        !:MCI = init_mode_constraint_info(Simple),
+        list.foldl2(number_robdd_variables_in_pred, SCC, !ModuleInfo, !MCI),
+
+        save_threshold(!.MCI, Threshold),
+        mc_process_scc_pass_1(SCC, SCC, !ModeConstraint, !MCI, !ModuleInfo),
 
         !:ModeConstraint = restrict_threshold(Threshold, !.ModeConstraint),
         !:ModeConstraint = ensure_normalised(!.ModeConstraint),
-        process_scc_pass_2(SCC, !.ModeConstraint,
-            !.ModeConstraintInfo, !ModuleInfo, !IO),
+        mc_process_scc_pass_2(SCC, !.ModeConstraint, !.MCI, !ModuleInfo),
 
         Insert = (pred(PredId::in, PCM0::in, PCM::out) is det :-
             NewPCI = pci(!.ModeConstraint,
-                !.ModeConstraintInfo ^ pred_id := PredId),
+                mci_set_pred_id(!.MCI, PredId)),
             map.det_insert(PCM0, PredId, NewPCI, PCM)
         ),
         list.foldl(Insert, SCC, !PredConstraintMap)
@@ -314,14 +314,14 @@
     func('module_info :='/2) is 'n_module_info :='
 ].
 
-:- pred update_mc_info(pred(T, mode_constraint_info, mode_constraint_info),
+:- pred update_mc_info_t(pred(T, mode_constraint_info, mode_constraint_info),
     T, C, C) <= has_mc_info(C).
-:- mode update_mc_info(pred(out, in, out) is det, out, in, out) is det.
+:- mode update_mc_info_t(pred(out, in, out) is det, out, in, out) is det.
 
-update_mc_info(P, R, !C) :-
+update_mc_info_t(P, R, !C) :-
     MCInfo0 = !.C ^ mc_info,
     P(R, MCInfo0, MCInfo),
-    !:C = !.C ^ mc_info := MCInfo.
+    !C ^ mc_info := MCInfo.
 
 :- pred update_mc_info(pred(mode_constraint_info, mode_constraint_info),
     C, C) <= has_mc_info(C).
@@ -331,7 +331,7 @@
 update_mc_info(P, !C) :-
     MCInfo0 = !.C ^ mc_info,
     P(MCInfo0, MCInfo),
-    !:C = !.C ^ mc_info := MCInfo.
+    !C ^ mc_info := MCInfo.
 
 :- pred update_md_info(pred(T, mode_decl_info, mode_decl_info), T, C, C)
     <= (has_mc_info(C), has_ho_modes(C)).
@@ -342,8 +342,8 @@
     HOModes0 = !.C ^ ho_modes,
     MDInfo0 = mode_decl_info(MCInfo0, HOModes0),
     P(R, MDInfo0, MDInfo),
-    !:C = !.C ^ mc_info := MDInfo ^ mc_info,
-    !:C = !.C ^ ho_modes := MDInfo ^ ho_modes.
+    !C ^ mc_info := MDInfo ^ mc_info,
+    !C ^ ho_modes := MDInfo ^ ho_modes.
 
     % Assign a number to all the ROBDD variables that we want to keep at
     % the end of the analysis.
@@ -357,9 +357,7 @@
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
 number_robdd_variables_in_pred(PredId, !ModuleInfo, !MCI) :-
-    !:MCI = !.MCI ^ pred_id := PredId,
-    module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
-
+    !:MCI = mci_set_pred_id(!.MCI, PredId),
     save_min_var_for_pred(PredId, !MCI),
 
     % Variables in each branch of a branched goal are always equivalent.
@@ -370,28 +368,36 @@
     % to the ROBDD. This is a good thing since equivalence constraints tend
     % to cause exponential explosions in ROBDDs. We achieve this by passing
     % `OmitModeEquivPrefix = yes' to `goal_path.fill_slots_in_clauses'.
+    % XXX We do not actually do that anymore, since this (a) that capability
+    % has not yet been implemented for the new goal_id system, and (b)
+    % this mode analysis system is obsolete.
 
-    OmitModeEquivPrefix = yes,
-    fill_goal_path_slots_in_clauses(!.ModuleInfo, OmitModeEquivPrefix,
-        PredInfo0, PredInfo1),
-
-    pred_info_get_clauses_info(PredInfo1, ClausesInfo0),
+    module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
     clauses_info_get_headvar_list(ClausesInfo0, HeadVars),
+    clauses_info_get_vartypes(ClausesInfo0, VarTypes),
+
+    pred_info_get_clauses_info(PredInfo0, ClausesInfo0),
+    fill_goal_id_slots_in_clauses(!.ModuleInfo, ContainingGoalMap,
+        ClausesInfo0, ClausesInfo1),
+    pred_info_set_clauses_info(ClausesInfo1, PredInfo0, PredInfo1),
+
+    ForwardGoalPathMap = create_forward_goal_path_map(ContainingGoalMap),
+    add_forward_goal_path_map(PredId, ForwardGoalPathMap, !MCI),
+
     pred_info_get_inst_graph_info(PredInfo1, InstGraphInfo),
     InstGraph = InstGraphInfo ^ implementation_inst_graph,
     inst_graph.foldl_reachable_from_list(
         ( pred(V::in, S0::in, S::out) is det :-
             mode_constraint_var(in(V), _, S0, S1),
             mode_constraint_var(out(V), _, S1, S2),
-            mode_constraint_var(V `at` empty_goal_path, _, S2, S)
+            mode_constraint_var(V `at` goal_id(0), _, S2, S)
         ), InstGraph, HeadVars, !MCI),
 
-    ( pred_info_is_imported(PredInfo0) ->
+    ( pred_info_is_imported(PredInfo1) ->
         true
     ;
-        clauses_info_clauses(Clauses0, ItemNumbers,
-            ClausesInfo0, ClausesInfo1),
-        clauses_info_get_vartypes(ClausesInfo0, VarTypes),
+        clauses_info_clauses(Clauses2, ItemNumbers,
+            ClausesInfo1, ClausesInfo2),
         NRInfo0 = number_robdd_info(!.MCI, !.ModuleInfo, VarTypes),
 
         list.map_foldl(
@@ -400,12 +406,12 @@
                 number_robdd_variables_in_goal(InstGraph,
                     set.init, _, Goal0, Goal, S0, S),
                 Clause = clause(A, Goal, C, D)
-        ), Clauses0, Clauses, NRInfo0, NRInfo),
+        ), Clauses2, Clauses, NRInfo0, NRInfo),
 
         !:MCI = NRInfo ^ mc_info,
         set_clause_list(Clauses, ClausesRep),
         clauses_info_set_clauses_rep(ClausesRep, ItemNumbers,
-            ClausesInfo1, ClausesInfo),
+            ClausesInfo2, ClausesInfo),
         pred_info_set_clauses_info(ClausesInfo, PredInfo1, PredInfo),
         module_info_set_pred_info(PredId, PredInfo, !ModuleInfo)
     ),
@@ -416,15 +422,16 @@
     number_robdd_info::in, number_robdd_info::out) is det.
 
 number_robdd_variables_in_goal(InstGraph, ParentNonLocals, Occurring,
-        hlds_goal(GoalExpr0, GoalInfo0), hlds_goal(GoalExpr, GoalInfo),
-        !RInfo) :-
+        Goal0, Goal, !RInfo) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
     NonLocals = goal_info_get_nonlocals(GoalInfo0),
-    GoalPath = goal_info_get_goal_path(GoalInfo0),
-    number_robdd_variables_in_goal_2(InstGraph, GoalPath, ParentNonLocals,
+    GoalId = goal_info_get_goal_id(GoalInfo0),
+    number_robdd_variables_in_goal_2(InstGraph, GoalId, ParentNonLocals,
         NonLocals, Occurring, GoalExpr0, GoalExpr, !RInfo),
-    goal_info_set_occurring_vars(Occurring, GoalInfo0, GoalInfo).
+    goal_info_set_occurring_vars(Occurring, GoalInfo0, GoalInfo),
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
-:- pred number_robdd_variables_in_goal_2(inst_graph::in, goal_path::in,
+:- pred number_robdd_variables_in_goal_2(inst_graph::in, goal_id::in,
     set(prog_var)::in, set(prog_var)::in, set(prog_var)::out,
     hlds_goal_expr::in, hlds_goal_expr::out,
     number_robdd_info::in, number_robdd_info::out) is det.
@@ -470,32 +477,32 @@
 %     number_robdd_variables_in_goals(InstGraph, NonLocals, OccOrElse,
 %         OrElseGoals0, OrElseGoals, !RInfo),
 %     Occurring = OccMain `set.union` OccOrElse.
-number_robdd_variables_in_goal_2(InstGraph, GoalPath, ParentNonLocals, _,
+number_robdd_variables_in_goal_2(InstGraph, GoalId, ParentNonLocals, _,
         Occurring, GoalExpr, GoalExpr, !RInfo) :-
     GoalExpr = plain_call(_, _, Args, _, _, _),
-    number_robdd_variables_at_goal_path(InstGraph, GoalPath,
+    number_robdd_variables_at_goal_path(InstGraph, GoalId,
         ParentNonLocals, Args, Occurring, !RInfo).
-number_robdd_variables_in_goal_2(InstGraph, GoalPath, ParentNonLocals, _,
+number_robdd_variables_in_goal_2(InstGraph, GoalId, ParentNonLocals, _,
         Occurring, GoalExpr, GoalExpr, !RInfo) :-
     GoalExpr = generic_call(_, Args, _, _),
-    number_robdd_variables_at_goal_path(InstGraph, GoalPath,
+    number_robdd_variables_at_goal_path(InstGraph, GoalId,
         ParentNonLocals, Args, Occurring, !RInfo).
-number_robdd_variables_in_goal_2(InstGraph, GoalPath, ParentNonLocals, _,
+number_robdd_variables_in_goal_2(InstGraph, GoalId, ParentNonLocals, _,
         Occurring, GoalExpr0, GoalExpr, !RInfo) :-
     GoalExpr0 = unify(VarL, RHS0, _, _, _),
-    number_robdd_variables_in_rhs(InstGraph, GoalPath, Vars, RHS0, RHS,
+    number_robdd_variables_in_rhs(InstGraph, GoalId, Vars, RHS0, RHS,
         !RInfo),
     GoalExpr = GoalExpr0 ^ unify_rhs := RHS,
-    number_robdd_variables_at_goal_path(InstGraph, GoalPath,
+    number_robdd_variables_at_goal_path(InstGraph, GoalId,
         ParentNonLocals, [VarL | Vars], Occurring, !RInfo).
-number_robdd_variables_in_goal_2(InstGraph, GoalPath, ParentNonLocals, _,
+number_robdd_variables_in_goal_2(InstGraph, GoalId, ParentNonLocals, _,
         Occurring, GoalExpr, GoalExpr, !RInfo) :-
     GoalExpr = call_foreign_proc(_, _, _, Args, _, _, _),
     ArgVars = list.map(foreign_arg_var, Args),
-    number_robdd_variables_at_goal_path(InstGraph, GoalPath,
+    number_robdd_variables_at_goal_path(InstGraph, GoalId,
         ParentNonLocals, ArgVars, Occurring, !RInfo).
 
-:- pred number_robdd_variables_in_rhs(inst_graph::in, goal_path::in,
+:- pred number_robdd_variables_in_rhs(inst_graph::in, goal_id::in,
     list(prog_var)::out, unify_rhs::in, unify_rhs::out,
     number_robdd_info::in, number_robdd_info::out) is det.
 
@@ -505,39 +512,35 @@
 number_robdd_variables_in_rhs(_, _, Vars, !RHS, !NRInfo) :-
     !.RHS = rhs_functor(_, _, Args),
     Vars = Args.
-number_robdd_variables_in_rhs(InstGraph, GoalPath, Vars, !RHS, !NRInfo) :-
+number_robdd_variables_in_rhs(InstGraph, GoalId, Vars, !RHS, !NRInfo) :-
     !.RHS = rhs_lambda_goal(_, _, _, _, LambdaNonLocals, LambdaVars, _, _,
         LambdaGoal0),
     Vars = LambdaNonLocals,
-    VarTypes = !.NRInfo ^ n_vartypes,
-    ModuleInfo = !.NRInfo ^ module_info,
-    fill_goal_path_slots_in_goal(LambdaGoal0, VarTypes, ModuleInfo,
-        LambdaGoal1),
-    update_mc_info(enter_lambda_goal(GoalPath), !NRInfo),
+    update_mc_info(enter_lambda_goal(GoalId), !NRInfo),
 
     % Number arguments to the lambda goal, i.e. the nonlocals and the
     % lambda-quantified variables.
-    LambdaHeadVars = LambdaNonLocals `list.append` LambdaVars,
+    LambdaHeadVars = LambdaNonLocals ++ LambdaVars,
     update_mc_info(pred(in, out) is det -->
         inst_graph.foldl_reachable_from_list(
             ( pred(V::in, in, out) is det -->
                 mode_constraint_var(in(V), _),
                 mode_constraint_var(out(V), _),
-                mode_constraint_var(V `at` empty_goal_path, _)
+                mode_constraint_var(V `at` whole_body_goal_id, _)
             ), InstGraph, LambdaHeadVars), !NRInfo),
 
     % Number variables within the lambda goal.
     number_robdd_variables_in_goal(InstGraph, set.init, _Occurring,
-        LambdaGoal1, LambdaGoal, !NRInfo),
+        LambdaGoal0, LambdaGoal, !NRInfo),
 
     update_mc_info(leave_lambda_goal, !NRInfo),
-    !:RHS = !.RHS ^ rhs_lambda_goal := LambdaGoal.
+    !RHS ^ rhs_lambda_goal := LambdaGoal.
 
-:- pred number_robdd_variables_at_goal_path(inst_graph::in, goal_path::in,
+:- pred number_robdd_variables_at_goal_path(inst_graph::in, goal_id::in,
     set(prog_var)::in, list(prog_var)::in, set(prog_var)::out,
     number_robdd_info::in, number_robdd_info::out) is det.
 
-number_robdd_variables_at_goal_path(InstGraph, GoalPath, ParentNonLocals,
+number_robdd_variables_at_goal_path(InstGraph, GoalId, ParentNonLocals,
         Vars0, Occurring, !NRInfo) :-
     solutions.solutions_set(inst_graph.reachable_from_list(InstGraph, Vars0),
         Occurring),
@@ -546,7 +549,7 @@
     % XXX We may be able to make this more efficient.
     inst_graph.foldl_reachable_from_list(
         (pred(V::in, S0::in, S::out) is det :-
-            update_mc_info(mode_constraint_var(V `at` GoalPath), _, S0, S)
+            update_mc_info_t(mode_constraint_var(V `at` GoalId), _, S0, S)
         ), InstGraph, Vars, !NRInfo).
 
 :- pred number_robdd_variables_in_goals(inst_graph::in, set(prog_var)::in,
@@ -579,45 +582,47 @@
         Cases0, Cases, !RInfo),
     Occurring = Occurring0 `set.union` Occurring1.
 
-:- pred process_scc_pass_1(list(pred_id)::in,
-    list(pred_id)::in, module_info::in,
-    module_info::out, mode_constraint::in, mode_constraint::out,
+%-----------------------------------------------------------------------------%
+
+:- pred mc_process_scc_pass_1(list(pred_id)::in,
+    list(pred_id)::in,
+    mode_constraint::in, mode_constraint::out,
     mode_constraint_info::in, mode_constraint_info::out,
-    io::di, io::uo) is det.
+    module_info::in, module_info::out) is det.
 
-process_scc_pass_1([], _, !ModuleInfo,
-        !ModeConstraint, !ModeConstraintInfo, !IO).
-process_scc_pass_1([PredId | PredIds], SCC,
-        !ModuleInfo, !ModeConstraint, !ModeConstraintInfo, !IO) :-
-    !:ModeConstraintInfo = !.ModeConstraintInfo ^ pred_id := PredId,
-    process_pred(PredId, SCC, !ModuleInfo,
-        !ModeConstraint, !ModeConstraintInfo, !IO),
-    process_scc_pass_1(PredIds, SCC, !ModuleInfo,
-        !ModeConstraint, !ModeConstraintInfo, !IO).
-
-:- pred process_scc_pass_2(list(pred_id)::in,
-    mode_constraint::in, mode_constraint_info::in, module_info::in,
-    module_info::out, io::di, io::uo) is det.
-
-process_scc_pass_2([], _, _, !ModuleInfo, !IO).
-process_scc_pass_2([PredId | PredIds], ModeConstraint,
-        ModeConstraintInfo, !ModuleInfo, !IO) :-
-    process_pred_2(PredId, ModeConstraint,
-        ModeConstraintInfo ^ pred_id := PredId, !ModuleInfo, !IO),
-    process_scc_pass_2(PredIds, ModeConstraint,
-        ModeConstraintInfo, !ModuleInfo, !IO).
-
-:- pred process_pred(pred_id::in, list(pred_id)::in,
-    module_info::in, module_info::out, mode_constraint::in,
-    mode_constraint::out, mode_constraint_info::in,
-    mode_constraint_info::out, io::di, io::uo) is det.
+mc_process_scc_pass_1([], _, !ModeConstraint, !MCI, !ModuleInfo).
+mc_process_scc_pass_1([PredId | PredIds], SCC,
+        !ModeConstraint, !MCI, !ModuleInfo) :-
+    !:MCI = mci_set_pred_id(!.MCI, PredId),
+    mc_process_pred(PredId, SCC, !ModeConstraint, !MCI, !ModuleInfo),
+    mc_process_scc_pass_1(PredIds, SCC, !ModeConstraint,
+        !MCI, !ModuleInfo).
+
+:- pred mc_process_scc_pass_2(list(pred_id)::in,
+    mode_constraint::in, mode_constraint_info::in,
+    module_info::in, module_info::out) is det.
+
+mc_process_scc_pass_2([], _, _, !ModuleInfo).
+mc_process_scc_pass_2([PredId | PredIds], ModeConstraint, MCI,
+        !ModuleInfo) :-
+    mc_process_pred_2(PredId, ModeConstraint,
+        mci_set_pred_id(MCI, PredId), !ModuleInfo),
+    mc_process_scc_pass_2(PredIds, ModeConstraint,
+        MCI, !ModuleInfo).
 
-process_pred(PredId, SCC, !ModuleInfo, !ModeConstraint,
-        !ModeConstraintInfo, !IO) :-
+:- pred mc_process_pred(pred_id::in, list(pred_id)::in,
+    mode_constraint::in, mode_constraint::out,
+    mode_constraint_info::in, mode_constraint_info::out,
+    module_info::in, module_info::out) is det.
+
+mc_process_pred(PredId, SCC, !ModeConstraint, !MCI,
+        !ModuleInfo) :-
     module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
-    write_pred_progress_message("% Calculating mode constraints for ",
-        PredId, !.ModuleInfo, !IO),
-    io.flush_output(!IO),
+    trace [io(!IO)] (
+        write_pred_progress_message("% Calculating mode constraints for ",
+            PredId, !.ModuleInfo, !IO),
+        io.flush_output(!IO)
+    ),
 
     pred_info_get_inst_graph_info(PredInfo0, InstGraphInfo),
     InstGraph = InstGraphInfo ^ implementation_inst_graph,
@@ -626,50 +631,49 @@
     clauses_info_get_headvar_list(ClausesInfo0, HeadVars),
 
     HOModes0 = map.init,
-    ( ( map.is_empty(ProcTable0) ; pred_info_infer_modes(PredInfo0) ) ->
+    (
+        ( map.is_empty(ProcTable0)
+        ; pred_info_infer_modes(PredInfo0)
+        )
+    ->
         DeclConstraint = one,
         HOModes = HOModes0,
         PredInfo1 = PredInfo0
     ;
-        ModeDeclInfo0 = mode_decl_info(!.ModeConstraintInfo, HOModes0),
+        ModeDeclInfo0 = mode_decl_info(!.MCI, HOModes0),
         map.map_foldl2(
-            mode_decl_to_constraint(!.ModuleInfo,
-                InstGraph, HeadVars, PredInfo0),
+            mode_decl_to_constraint(!.ModuleInfo, InstGraph, HeadVars,
+                PredInfo0),
             ProcTable0, ProcTable,
             zero, DeclConstraint, ModeDeclInfo0, ModeDeclInfo),
-        !:ModeConstraintInfo = ModeDeclInfo ^ mc_info,
+        !:MCI = ModeDeclInfo ^ mc_info,
         HOModes = ModeDeclInfo ^ ho_modes,
         pred_info_set_procedures(ProcTable, PredInfo0, PredInfo1)
     ),
     !:ModeConstraint = !.ModeConstraint * DeclConstraint,
-    set_input_nodes(!ModeConstraint, !ModeConstraintInfo),
+    set_input_nodes(!ModeConstraint, !MCI),
 
     % clauses_info_get_varset(ClausesInfo0, ProgVarSet),
     % pred_id_to_int(PredId, PredIdInt),
-    % robdd_to_dot(DeclConstraint, ProgVarSet, ModeConstraintInfo1,
+    % robdd_to_dot(DeclConstraint, ProgVarSet, MCI,
     %   format("mode_decl_%d.dot", [i(PredIdInt)]), !IO),
-    % robdd_to_dot(ModeConstraint1, ProgVarSet, ModeConstraintInfo1,
+    % robdd_to_dot(ModeConstraint1, ProgVarSet, MCI,
     %   format("mode_constraint1_%d.dot", [i(PredIdInt)]), !IO),
     % io.flush_output(!IO),
 
     ( pred_info_is_imported(PredInfo1) ->
         PredInfo = PredInfo1
     ;
-        process_clauses_info(!.ModuleInfo, SCC,
-            ClausesInfo0, ClausesInfo, InstGraph, HOModes,
-            !ModeConstraint, !ModeConstraintInfo, !IO),
-        pred_info_set_clauses_info(ClausesInfo,
-            PredInfo1, PredInfo)
+        process_clauses_info(!.ModuleInfo, SCC, ClausesInfo0, ClausesInfo,
+            InstGraph, HOModes, !ModeConstraint, !MCI),
+        pred_info_set_clauses_info(ClausesInfo, PredInfo1, PredInfo)
     ),
     module_info_set_pred_info(PredId, PredInfo, !ModuleInfo).
 
-:- pred process_pred_2(pred_id::in, mode_constraint::in,
-    mode_constraint_info::in, module_info::in, module_info::out,
-    io::di, io::uo) is det.
-
-process_pred_2(PredId, ModeConstraint, ModeConstraintInfo0,
-        !ModuleInfo, !IO) :-
+:- pred mc_process_pred_2(pred_id::in, mode_constraint::in,
+    mode_constraint_info::in, module_info::in, module_info::out) is det.
 
+mc_process_pred_2(PredId, ModeConstraint, MCI0, !ModuleInfo) :-
     module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
     pred_info_get_inst_graph_info(PredInfo0, InstGraphInfo),
     InstGraph = InstGraphInfo ^ implementation_inst_graph,
@@ -679,14 +683,13 @@
     % DMO document this better
     % XXX Needed for analysing calls. May want to store the constraint
     % as an ROBDD instead.
-    solutions(arg_modes_map(HeadVars, InstGraph, ModeConstraint,
-        ModeConstraintInfo0), Modes),
+    solutions(arg_modes_map(HeadVars, InstGraph, ModeConstraint, MCI0), Modes),
     pred_info_set_arg_modes_maps(Modes, PredInfo0, PredInfo),
     % PredInfo = PredInfo0,
 
     % DEBUGGING CODE
     % dump_mode_constraints(!.ModuleInfo, PredInfo0, InstGraph,
-    %   ModeConstraint, ModeConstraintInfo0),
+    %   ModeConstraint, MCI0),
     % io.flush_output(!IO),
     %
     % list.foldl((pred(M - _::in, di, uo) is det -->
@@ -702,11 +705,11 @@
     %   ReachVars),
     % list.map_foldl((pred(PV::in, MV::out, in, out) is det -->
     %   mode_constraint_var(in(PV), MV)
-    % ), ReachVars, InVars, ModeConstraintInfo0, ModeConstraintInfo),
+    % ), ReachVars, InVars, MCI0, MCI),
     %
     % InVarConstraint = restrict_filter((pred(in(V)::in) is semidet :-
     %       list.member(V, ReachVars)),
-    %   ModeConstraintInfo, ModeConstraint),
+    %   MCI, ModeConstraint),
     % aggregate(fundamental_mode(set.list_to_set(InVars), InVarConstraint),
     %   (pred(M::in, di, uo) is det -->
     %       map.foldl((pred(_MV::in, Val::in, di, uo) is det -->
@@ -717,14 +720,12 @@
 
     % DMO justify or delete
     % split_constraint_into_modes(PredId, HeadVars, InstGraph,
-    %   ModeConstraint, _ProcConstraints, ModeConstraintInfo0,
-    %   ModeConstraintInfo),
+    %   ModeConstraint, _ProcConstraints, MCI0, MCI),
 
     % DEBUGGING CODE
     % clauses_info_get_varset(ClausesInfo, ProgVarSet),
     % pred_info_name(PredInfo, Name),
-    % robdd_to_dot(ModeConstraint, ProgVarSet, ModeConstraintInfo,
-    %   Name `string.append` ".dot", !IO),
+    % robdd_to_dot(ModeConstraint, ProgVarSet, MCI, Name ++ ".dot", !IO),
     % io.flush_output(!IO),
 
     module_info_set_pred_info(PredId, PredInfo, !ModuleInfo).
@@ -736,7 +737,7 @@
                 inst_graph      :: inst_graph,
                 headvars        :: list(prog_var),
                 prog_varset     :: prog_varset,
-                atomic_goals    :: set(goal_path),
+                atomic_goals    :: set(goal_id),
                 g_mc_info       :: mode_constraint_info,
                 g_ho_modes      :: ho_modes,
                 ho_calls        :: ho_calls
@@ -761,32 +762,26 @@
     multi_map(prog_var_and_level, list(mer_mode)).
 
 :- type ho_calls ==
-    multi_map(prog_var_and_level, pair(goal_path, list(prog_var))).
+    multi_map(prog_var_and_level, pair(goal_id, list(prog_var))).
 
 :- pred get_var(rep_var::in, mode_constraint_var::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
 get_var(RepVar, MCVar, !GCInfo) :-
-    update_mc_info(mode_constraint_var(RepVar), MCVar, !GCInfo).
+    update_mc_info_t(mode_constraint_var(RepVar), MCVar, !GCInfo).
 
-:- pred get_var(pred_id::in, rep_var::in, mode_constraint_var::out,
+:- pred get_var_in_pred(pred_id::in, rep_var::in, mode_constraint_var::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-get_var(PredId, RepVar, MCVar, !GCInfo) :-
-    update_mc_info(mode_constraint_var(PredId, RepVar), MCVar, !GCInfo).
-
-:- pred save_thresh(threshold::out, goal_constraints_info::in,
-    goal_constraints_info::out) is det.
+get_var_in_pred(PredId, RepVar, MCVar, !GCInfo) :-
+    update_mc_info_t(mode_constraint_var(PredId, RepVar), MCVar, !GCInfo).
 
-save_thresh(Thresh, !GCInfo) :-
-    update_mc_info(save_threshold, Thresh, !GCInfo).
-
-:- pred add_atomic_goal(goal_path::in, goal_constraints_info::in,
-    goal_constraints_info::out) is det.
+:- pred add_atomic_goal(goal_id::in,
+    goal_constraints_info::in, goal_constraints_info::out) is det.
 
-add_atomic_goal(GoalPath, !GCInfo) :-
+add_atomic_goal(GoalId, !GCInfo) :-
     AtomicGoals = !.GCInfo ^ atomic_goals,
-    !:GCInfo = !.GCInfo ^ atomic_goals := AtomicGoals `set.insert` GoalPath.
+    !GCInfo ^ atomic_goals := AtomicGoals `set.insert` GoalId.
 
 :- type mode_decl_info
     --->    mode_decl_info(
@@ -813,19 +808,19 @@
     mode_decl_info::in, mode_decl_info::out) is det.
 
 mode_decl_to_constraint(ModuleInfo, InstGraph, HeadVars,
-        _PredInfo, _ProcId, !ProcInfo, !Constraint, !Info) :-
+        _PredInfo, _ProcId, !ProcInfo, !Constraint, !MDI) :-
     process_mode_decl_for_proc(ModuleInfo,
         InstGraph, HeadVars,
         false_var(initial), true_var(initial), yes,
         false_var(final), true_var(final), no,
-        !.ProcInfo, zero, DeclConstraint, !Info),
+        !.ProcInfo, zero, DeclConstraint, !MDI),
 
     % proc_id_to_int(ProcId, ProcIdInt),
     % pred_info_name(PredInfo, Name),
     % pred_info_clauses_info(PredInfo, ClausesInfo),
     % clauses_info_get_varset(ClausesInfo, ProgVarSet),
     % unsafe_perform_io(robdd_to_dot(DeclConstraint, ProgVarSet,
-    %   Info ^ mc_info, Name ++ int_to_string(ProcIdInt) ++ ".dot")),
+    %   !.MDI ^ mc_info, Name ++ int_to_string(ProcIdInt) ++ ".dot")),
 
     !:Constraint = !.Constraint + DeclConstraint,
     proc_info_set_head_modes_constraint(DeclConstraint, !ProcInfo).
@@ -893,21 +888,26 @@
 
 final(Var) = out(Var).
 
-:- func goal_path(goal_path, prog_var) = rep_var.
+:- func var_at_goal_id(goal_id, prog_var) = rep_var.
+
+var_at_goal_id(GoalId, Var) = Var `at` GoalId.
 
-goal_path(Path, Var) = Var `at` Path.
+:- func var_at_goal(hlds_goal, prog_var) = rep_var.
 
-:- pred true_var(func(prog_var) = rep_var, prog_var, mode_constraint,
-    mode_constraint, mode_constraint_info, mode_constraint_info).
-:- mode true_var(func(in) = out is det, in, in, out, in, out) is det.
+var_at_goal(Goal, Var) = Var `at` GoalId :-
+    Goal = hlds_goal(_, GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo).
+
+:- pred true_var((func(prog_var) = rep_var)::in(func(in) = out is det),
+    prog_var::in, mode_constraint::in, mode_constraint::out,
+    mode_constraint_info::in, mode_constraint_info::out) is det.
 
 true_var(F, V, !C, !MCI) :-
     mode_constraint_var(F(V), CV, !MCI),
     !:C = !.C ^ var(CV).
 
 :- pred false_var((func(prog_var) = rep_var)::in(func(in) = out is det),
-    prog_var::in,
-    mode_constraint::in, mode_constraint::out,
+    prog_var::in, mode_constraint::in, mode_constraint::out,
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
 false_var(F, V, !C, !MCI) :-
@@ -919,7 +919,7 @@
 
 ignore(_, !C, !MCI).
 
-:- pred call_in(goal_path::in, prog_var::in,
+:- pred call_in(goal_id::in, prog_var::in,
     mode_constraint::in, mode_constraint::out,
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
@@ -928,7 +928,7 @@
     mode_constraint_var(out(Var), VarOut, !MCI),
     !:C = !.C ^ not_var(VarGP) ^ var(VarOut).
 
-:- pred call_out(goal_path::in, prog_var::in,
+:- pred call_out(goal_id::in, prog_var::in,
     mode_constraint::in, mode_constraint::out,
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
@@ -974,7 +974,7 @@
 
 do_process_inst(ModuleInfo, InstGraph, Free, Bound, DoHO,
         Inst, Seen, Var, !Constraint, !MDI) :-
-    update_mc_info((pred(C::out, S0::in, S::out) is det :-
+    update_mc_info_t((pred(C::out, S0::in, S::out) is det :-
         (
             ( Inst = any(_, _)
             ; Inst = bound(_, _)
@@ -1022,9 +1022,10 @@
         Inst = ground(_, higher_order(pred_inst_info(_, ArgModes, _)))
     ->
         HoModes0 = !.MDI ^ ho_modes,
-        update_mc_info(get_prog_var_level(Var), VarLevel, !MDI),
+        MCI = !.MDI ^ mc_info,
+        get_prog_var_level(MCI, Var, VarLevel),
         multi_map.set(HoModes0, VarLevel, ArgModes, HoModes),
-        !:MDI = !.MDI ^ ho_modes := HoModes
+        !MDI ^ ho_modes := HoModes
     ;
         true
     ).
@@ -1032,56 +1033,56 @@
 :- pred process_clauses_info(module_info::in,
     list(pred_id)::in, clauses_info::in, clauses_info::out, inst_graph::in,
     ho_modes::in, mode_constraint::in, mode_constraint::out,
-    mode_constraint_info::in, mode_constraint_info::out,
-    io::di, io::uo) is det.
+    mode_constraint_info::in, mode_constraint_info::out) is det.
 
 process_clauses_info(ModuleInfo, SCC, !ClausesInfo,
-        InstGraph, HOModes0, !Constraint, !ConstraintInfo, !IO) :-
+        InstGraph, HOModes0, !Constraint, !MCI) :-
     clauses_info_get_varset(!.ClausesInfo, VarSet0),
     module_info_get_globals(ModuleInfo, Globals),
     globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
     (
         VeryVerbose = yes,
-        inst_graph.dump(InstGraph, VarSet0, !IO)
+        trace [io(!IO)] (
+            inst_graph.dump(InstGraph, VarSet0, !IO)
+        )
     ;
         VeryVerbose = no
     ),
 
     clauses_info_get_headvar_list(!.ClausesInfo, HeadVars),
     map.foldl2(input_output_constraints(HeadVars, InstGraph),
-        InstGraph, !Constraint, !ConstraintInfo),
+        InstGraph, !Constraint, !MCI),
 
     clauses_info_clauses(Clauses, _ItemNumbers, !ClausesInfo),
-    list.map(pred(clause(_, Goal, _, _)::in, Goal::out) is det, Clauses,
-        Goals),
+    list.map(pred(clause(_, Goal, _, _)::in, Goal::out) is det,
+        Clauses, Goals),
     DisjGoal = disj(Goals),
-    EmptyGoalPath = empty_goal_path,
     AtomicGoals0 = set.init,
-    Info0 = goal_constraints_info(ModuleInfo, SCC, InstGraph, HeadVars,
-        VarSet0, AtomicGoals0, !.ConstraintInfo, HOModes0, map.init),
+    GCInfo0 = goal_constraints_info(ModuleInfo, SCC, InstGraph, HeadVars,
+        VarSet0, AtomicGoals0, !.MCI, HOModes0, map.init),
     NonLocals = set.list_to_set(HeadVars),
     GoalVars = set.sorted_list_to_set(map.sorted_keys(InstGraph)),
 
-    goal_constraints_2(EmptyGoalPath, NonLocals, GoalVars, _CanSucceed,
-        DisjGoal, _, !Constraint, Info0, Info1),
+    goal_constraints_2(whole_body_goal_id, NonLocals, GoalVars, _CanSucceed,
+        DisjGoal, _, !Constraint, GCInfo0, GCInfo1),
 
     % DMO justify this or eliminate it
     % constrict_to_vars(HeadVars, GoalVars, [], !Constraint,
     %   Info1, Info2),
-    Info2 = Info1,
+    GCInfo2 = GCInfo1,
 
     % robdd_to_dot(!.Constraint, Info2 ^ prog_varset,
     %   Info2 ^ mc_info, "before_higher_order.dot, !IO"),
     % io.flush_output(!IO),
 
-    higher_order_call_constraints(!Constraint, Info2, Info),
+    higher_order_call_constraints(!Constraint, GCInfo2, GCInfo),
 
-    % robdd_to_dot(!.Constraint, Info ^ prog_varset,
-    %   Info ^ mc_info, "after_higher_order.dot", !IO),
+    % robdd_to_dot(!.Constraint, GCInfo ^ prog_varset,
+    %   GCInfo ^ mc_info, "after_higher_order.dot", !IO),
     % io.flush_output(!IO),
 
-    clauses_info_set_varset(Info ^ prog_varset, !ClausesInfo),
-    !:ConstraintInfo = Info ^ mc_info.
+    clauses_info_set_varset(GCInfo ^ prog_varset, !ClausesInfo),
+    !:MCI = GCInfo ^ mc_info.
 
     % 1.2.1 Input output constraints.
     % These constraints relate the relationships between the above
@@ -1097,7 +1098,7 @@
     inst_graph.top_level_node(InstGraph, V, TopLevel),
     mode_constraint_var(in(V), V_in, !MCI),
     mode_constraint_var(out(V), V_out, !MCI),
-    mode_constraint_var(V `at` empty_goal_path, V_, !MCI),
+    mode_constraint_var(V `at` whole_body_goal_id, V_, !MCI),
     ( TopLevel `list.member` HeadVars ->
         % For each variable V in the instantiation graph, add
         %   (Vout = Vin + V), ~(Vin * V).
@@ -1119,12 +1120,12 @@
     mode_constraint::in, mode_constraint::out,
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
-add_in_and_out_implications(V, V_in, V_out, W, !Cs, !Info) :-
+add_in_and_out_implications(V, V_in, V_out, W, !Cs, !MCI) :-
     ( W = V ->
         true
     ;
-        mode_constraint_var(in(W), W_in, !Info),
-        mode_constraint_var(out(W), W_out, !Info),
+        mode_constraint_var(in(W), W_in, !MCI),
+        mode_constraint_var(out(W), W_out, !MCI),
         !:Cs = !.Cs ^ imp_vars(W_out, V_out) ^ imp_vars(W_in, V_in)
     ).
 
@@ -1134,25 +1135,26 @@
     hlds_goal::out, mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-goal_constraints(ParentNonLocals, CanSucceed, hlds_goal(GoalExpr0, GoalInfo0),
-        hlds_goal(GoalExpr, GoalInfo), !Constraint, !GCInfo) :-
+goal_constraints(ParentNonLocals, CanSucceed, Goal0, Goal,
+        !Constraint, !GCInfo) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
     HasSubGoals = goal_expr_has_subgoals(GoalExpr0),
     (
         HasSubGoals = has_subgoals
     ;
         HasSubGoals = does_not_have_subgoals,
-        add_atomic_goal(GoalPath, !GCInfo)
+        add_atomic_goal(GoalId, !GCInfo)
     ),
 
-    GoalPath = goal_info_get_goal_path(GoalInfo0),
+    GoalId = goal_info_get_goal_id(GoalInfo0),
     goal_info_get_occurring_vars(GoalInfo0, Vars),
 
     % Number the vars we want to keep for this goal.
     % XXX
     list.foldl((pred(V::in, S0::in, S::out) is det :-
-            get_var(V `at` GoalPath, _, S0, S)
+            get_var(V `at` GoalId, _, S0, S)
         ), set.to_sorted_list(Vars), !GCInfo),
-    save_thresh(Threshold, !GCInfo),
+    save_threshold(!.GCInfo ^ mc_info, Threshold),
 
     NonLocals = goal_info_get_nonlocals(GoalInfo0),
 
@@ -1161,21 +1163,18 @@
         InstGraph, to_sorted_list(NonLocals))),
     LocalVars = Vars `difference` NonLocalReachable,
 
-    ( update_mc_info(using_simple_mode_constraints, !GCInfo) ->
+    ( using_simple_mode_constraints(!.GCInfo ^ g_mc_info) ->
         % With simple mode constraints, it is more efficient to do this
         % constraint before doing the goal constraints.
-        constrain_local_vars(LocalVars, GoalPath, !Constraint, !GCInfo)
-    ;
-        true
-    ),
-
-    goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed, GoalExpr0,
-        GoalExpr, !Constraint, !GCInfo),
-
-    ( update_mc_info(using_simple_mode_constraints, !GCInfo) ->
-        true
-    ;
-        constrain_local_vars(LocalVars, GoalPath, !Constraint, !GCInfo)
+        constrain_local_vars(LocalVars, GoalId, !Constraint, !GCInfo),
+        goal_constraints_2(GoalId, NonLocals, Vars, CanSucceed, GoalExpr0,
+            GoalExpr, !Constraint, !GCInfo)
+    ;
+        goal_constraints_2(GoalId, NonLocals, Vars, CanSucceed, GoalExpr0,
+            GoalExpr, !Constraint, !GCInfo),
+        % Without simple mode constraints, it is more efficient to do this
+        % constraint after doing the goal constraints.
+        constrain_local_vars(LocalVars, GoalId, !Constraint, !GCInfo)
     ),
 
     % DEBUGGING CODE
@@ -1188,7 +1187,7 @@
 
     % DMO document
     % constrict_to_vars(set.to_sorted_list(NonLocals), Vars,
-    %   GoalPath, !Constraint, !GCInfo)
+    %   GoalId, !Constraint, !GCInfo)
 
     % DEBUGGING CODE
     % size(Constraint1, NumNodes1, Depth1),
@@ -1207,262 +1206,259 @@
     % unsafe_perform_io(io.flush_output),
 
     constrain_non_occurring_vars(CanSucceed, ParentNonLocals, Vars,
-        GoalPath, !Constraint, !GCInfo),
+        GoalId, !Constraint, !GCInfo),
 
     % DEBUGGING CODE
     % unsafe_perform_io(dump_constraints(ModuleInfo, ProgVarset,
     %   !.Constraint)),
     % goal_info_set_mode_constraint(GoalInfo0, !.Constraint, GoalInfo).
 
-    GoalInfo = GoalInfo0.
-
-% :- pragma promise_pure(goal_constraints_2/9).
+    Goal = hlds_goal(GoalExpr, GoalInfo0).
 
-:- pred goal_constraints_2(goal_path::in, set(prog_var)::in,
+:- pred goal_constraints_2(goal_id::in, set(prog_var)::in,
     set(prog_var)::in, can_succeed::out, hlds_goal_expr::in,
     hlds_goal_expr::out, mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-goal_constraints_2(GoalPath, NonLocals, _, CanSucceed, conj(ConjType, Goals0),
-        conj(ConjType, Goals), !Constraint, !GCInfo) :-
+goal_constraints_2(GoalId, NonLocals, Vars, CanSucceed, GoalExpr0, GoalExpr,
+        !Constraint, !GCInfo) :-
     (
-        ConjType = plain_conj,
-        multi_map.init(Usage0),
-
-        Usage = list.foldl(func(G, U0) =
-            list.foldl((func(V, U1) = U :-
-                multi_map.set(U1, V, goal_path(G), U)),
-                set.to_sorted_list(vars(G)), U0),
-            Goals0, Usage0),
-
-        known_vars(ensure_normalised(!.Constraint), KnownTrue, KnownFalse),
-
-        % Generate conj constraints for known vars first since these should be
-        % more efficient and provide lots of useful information for the subgoal
-        % constraints.
-        conj_constraints(yes, KnownTrue, KnownFalse, GoalPath, Usage,
-            !Constraint, !GCInfo),
-
-        conj_subgoal_constraints(NonLocals, CanSucceed, !Constraint,
-            Goals0, Goals, !GCInfo),
+        GoalExpr0 = conj(ConjType, Goals0),
+        (
+            ConjType = plain_conj,
+            multi_map.init(Usage0),
 
-        % Generate the rest of the constraints.
-        conj_constraints(no, KnownTrue, KnownFalse, GoalPath, Usage,
-            !Constraint, !GCInfo)
+            Usage = list.foldl(func(G, U0) =
+                list.foldl((func(V, U1) = U :-
+                    multi_map.set(U1, V, get_goal_id(G), U)),
+                    set.to_sorted_list(vars(G)), U0),
+                Goals0, Usage0),
+
+            known_vars(ensure_normalised(!.Constraint), KnownTrue, KnownFalse),
+
+            % Generate conj constraints for known vars first since these
+            % should be more efficient and provide lots of useful information
+            % for the subgoal constraints.
+            conj_constraints(yes, KnownTrue, KnownFalse, GoalId, Usage,
+                !Constraint, !GCInfo),
+
+            conj_subgoal_constraints(NonLocals, CanSucceed, !Constraint,
+                Goals0, Goals, !GCInfo),
+
+            % Generate the rest of the constraints.
+            conj_constraints(no, KnownTrue, KnownFalse, GoalId, Usage,
+                !Constraint, !GCInfo)
+        ;
+            ConjType = parallel_conj,
+            sorry(this_file, "goal_constraints_2: par_conj NYI")
+        ),
+        GoalExpr = conj(ConjType, Goals)
     ;
-        ConjType = parallel_conj,
-        sorry(this_file, "goal_constraints_2: par_conj NYI")
-    ).
+        GoalExpr0 = disj(Goals0),
+        disj_constraints(NonLocals, CanSucceed, !Constraint, Goals0, Goals,
+            [], DisjunctPaths, !GCInfo),
+        list.foldl2((pred(V::in, Cons0::in, Cons::out, in, out) is det -->
+            get_var(V `at` GoalId, Vgp),
+            list.foldl2((pred(I::in, C0::in, C::out, in, out) is det -->
+                get_var(V `at` I, VI),
+                { C = C0 ^ eq_vars(Vgp, VI) }
+            ), DisjunctPaths, Cons0, Cons)
+        ), set.to_sorted_list(Vars), !Constraint, !GCInfo),
+        GoalExpr = disj(Goals)
+    ;
+        GoalExpr0 = unify(Var, RHS0, _, _, _),
+        unify_constraints(Var, GoalId, RHS0, RHS, !Constraint, !GCInfo),
+        GoalExpr = GoalExpr0 ^ unify_rhs := RHS,
+        CanSucceed = yes    % XXX Can we be more precise here?
+    ;
+        GoalExpr0 = plain_call(PredId, _, Args, _, _, _),
+        SCC = !.GCInfo ^ scc,
+        InstGraph = !.GCInfo ^ inst_graph,
+        ModuleInfo = !.GCInfo ^ module_info,
+        module_info_pred_info(ModuleInfo, PredId, PredInfo),
 
-goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed, disj(Goals0),
-        disj(Goals), !Constraint, !GCInfo) :-
-    disj_constraints(NonLocals, CanSucceed, !Constraint, Goals0, Goals,
-        [], DisjunctPaths, !GCInfo),
-    list.foldl2((pred(V::in, Cons0::in, Cons::out, in, out) is det -->
-        get_var(V `at` GoalPath, Vgp),
-        list.foldl2((pred(Path::in, C0::in, C::out, in, out) is det -->
-            get_var(V `at` Path, VPath),
-            { C = C0 ^ eq_vars(Vgp, VPath) }
-        ), DisjunctPaths, Cons0, Cons)
-    ), set.to_sorted_list(Vars), !Constraint, !GCInfo).
+        CanSucceed = ( pred_can_succeed(PredInfo) -> yes ; no ),
 
-goal_constraints_2(GoalPath, _NonLocals, _, CanSucceed, GoalExpr0, GoalExpr,
-        !Constraint, !GCInfo) :-
-    GoalExpr0 = unify(Var, RHS0, _, _, _),
-    unify_constraints(Var, GoalPath, RHS0, RHS, !Constraint, !GCInfo),
-    GoalExpr = GoalExpr0 ^ unify_rhs := RHS,
-    CanSucceed = yes.   % XXX Can we be more precise here?
-
-goal_constraints_2(GoalPath, _NonLocals, _, CanSucceed, GoalExpr, GoalExpr,
-        !Constraint, !GCInfo) :-
-    GoalExpr = plain_call(PredId, _, Args, _, _, _),
-    SCC = !.GCInfo ^ scc,
-    InstGraph = !.GCInfo ^ inst_graph,
-    ModuleInfo = !.GCInfo ^ module_info,
-    module_info_pred_info(ModuleInfo, PredId, PredInfo),
+        ( PredId `list.member` SCC ->
+            % This is a recursive call.
+            % XXX we currently assume that all recursive calls are to the
+            % same mode of the predicate.
+            pred_info_get_clauses_info(PredInfo, ClausesInfo),
+            clauses_info_get_headvar_list(ClausesInfo, HeadVars),
+            call_constraints(GoalId, PredId, HeadVars, Args,
+                !Constraint, !GCInfo)
+        ;
+            % This is a non-recursive call.
+            ( pred_has_mode_decl(ModuleInfo, PredId) ->
+                % The predicate has mode declarations so use them
+                % to obtain the constraints for the call.
+
+                pred_info_get_procedures(PredInfo, ProcTable),
+                map.values(ProcTable, ProcInfos),
+                update_md_info((pred(C::out, S0::in, S::out) is det :-
+                    list.foldl2(
+                        process_mode_decl_for_proc(ModuleInfo,
+                            InstGraph, Args, ignore, call_in(GoalId), no,
+                            false_var(var_at_goal_id(GoalId)),
+                            call_out(GoalId), yes),
+                        ProcInfos, zero, C, S0, S)),
+                    CallConstraint, !GCInfo)
 
-    CanSucceed = ( pred_can_succeed(PredInfo) -> yes ; no ),
+            ;
+                % The called predicate is from a lower (i.e. already
+                % mode-analysed) SCC, but does not have any mode declarations.
+                pred_info_get_arg_modes_maps(PredInfo, ArgModes),
+                pred_info_get_inst_graph_info(PredInfo, InstGraphInfo),
+                PredInstGraph = InstGraphInfo ^ interface_inst_graph,
+                pred_info_get_clauses_info(PredInfo, PredClausesInfo),
+                clauses_info_get_headvar_list(PredClausesInfo, PredHeadVars),
+                solutions((pred((V - W)::out) is nondet :-
+                    inst_graph.corresponding_nodes_from_lists(
+                        PredInstGraph, InstGraph, PredHeadVars, Args, V, W)
+                    ), CorrespondingNodes),
+                list.foldl2((pred(ArgMap::in, Cn0::in, Cn::out,
+                        S0::in, S::out) is det :-
+                    ArgMap = InArgs - OutArgs,
+                    list.foldl2((pred((V - W)::in, C0::in, C::out,
+                            T0::in, T::out) is det :-
+                        get_var(W `at` GoalId, Wgp, T0, T1),
+                        get_var(out(W), Wout, T1, T),
+                        ( map.lookup(InArgs, V, yes) ->
+                            C = C0 ^ var(Wout) ^ not_var(Wgp)
+                        ; map.lookup(OutArgs, V, yes) ->
+                            C = C0 ^ var(Wgp)
+                        ;
+                            C = C0 ^ not_var(Wgp)
+                        )
+                    ), CorrespondingNodes, one, Cn1, S0, S),
+                    Cn = Cn0 + Cn1
+                ), ArgModes, zero, CallConstraint, !GCInfo)
+                % XXX ArgModes is [] for `odd' - why?
+            ),
+            !:Constraint = !.Constraint * CallConstraint
+        ),
+        GoalExpr = GoalExpr0
+    ;
+        GoalExpr0 = generic_call(GenericCall, Args, _Modes, _Det),
+        % Note: `_Modes' is invalid for higher-order calls at this point.
+        (
+            GenericCall = higher_order(Var, _, _, _),
+            generic_call_constrain_var(Var, GoalId, !Constraint, !GCInfo),
 
-    ( PredId `list.member` SCC ->
-        % This is a recursive call.
-        % XXX we currently assume that all recursive calls are to the
-        % same mode of the predicate.
-        pred_info_get_clauses_info(PredInfo, ClausesInfo),
-        clauses_info_get_headvar_list(ClausesInfo, HeadVars),
-        call_constraints(GoalPath, PredId, HeadVars, Args,
-            !Constraint, !GCInfo)
-    ;
-        % This is a non-recursive call.
-        ( pred_has_mode_decl(ModuleInfo, PredId) ->
-            % The predicate has mode declarations so use them
-            % to obtain the constraints for the call.
-
-            pred_info_get_procedures(PredInfo, ProcTable),
-            map.values(ProcTable, ProcInfos),
-            update_md_info((pred(C::out, S0::in, S::out) is det :-
-                list.foldl2(
-                    process_mode_decl_for_proc(ModuleInfo,
-                        InstGraph, Args, ignore, call_in(GoalPath), no,
-                        false_var(goal_path(GoalPath)), call_out(GoalPath),
-                        yes),
-                    ProcInfos, zero, C, S0, S)),
-                CallConstraint, !GCInfo)
+            % Record that the argument vars need to be constrained
+            % once we know the higher order mode of the Var we are calling.
+            HoCalls0 = !.GCInfo ^ ho_calls,
+            get_prog_var_level(!.GCInfo ^ mc_info, Var, VarLevel),
+            multi_map.set(HoCalls0, VarLevel, GoalId - Args, HoCalls),
+            !GCInfo ^ ho_calls := HoCalls,
 
+            CanSucceed = yes % XXX should check this
         ;
-            % The called predicate is from a lower (i.e. already mode-analysed)
-            % SCC, but does not have any mode declarations.
-            pred_info_get_arg_modes_maps(PredInfo, ArgModes),
-            pred_info_get_inst_graph_info(PredInfo, InstGraphInfo),
-            PredInstGraph = InstGraphInfo ^ interface_inst_graph,
-            pred_info_get_clauses_info(PredInfo, PredClausesInfo),
-            clauses_info_get_headvar_list(PredClausesInfo, PredHeadVars),
-            solutions((pred((V - W)::out) is nondet :-
-                inst_graph.corresponding_nodes_from_lists(
-                    PredInstGraph, InstGraph, PredHeadVars, Args, V, W)
-                ), CorrespondingNodes),
-            list.foldl2((pred(ArgMap::in, Cn0::in, Cn::out,
-                    S0::in, S::out) is det :-
-                ArgMap = InArgs - OutArgs,
-                list.foldl2((pred((V - W)::in, C0::in, C::out,
-                        T0::in, T::out) is det :-
-                    get_var(W `at` GoalPath, Wgp, T0, T1),
-                    get_var(out(W), Wout, T1, T),
-                    ( map.lookup(InArgs, V, yes) ->
-                        C = C0 ^ var(Wout) ^ not_var(Wgp)
-                    ; map.lookup(OutArgs, V, yes) ->
-                        C = C0 ^ var(Wgp)
-                    ;
-                        C = C0 ^ not_var(Wgp)
-                    )
-                ), CorrespondingNodes, one, Cn1, S0, S),
-                Cn = Cn0 + Cn1
-            ), ArgModes, zero, CallConstraint, !GCInfo)
-            % XXX ArgModes is [] for `odd' - why?
+            GenericCall = class_method(Var, _, _, _),
+            generic_call_constrain_var(Var, GoalId, !Constraint, !GCInfo),
+            unexpected(this_file, "class_method call in clause")
+        ;
+            GenericCall = event_call(_),
+            sorry(this_file, "event_call NYI")
+        ;
+            GenericCall = cast(_),
+            sorry(this_file, "type/inst cast call NYI")
         ),
-        !:Constraint = !.Constraint * CallConstraint
-    ).
-
-goal_constraints_2(GoalPath, _NonLocals, _Vars, CanSucceed, GoalExpr, GoalExpr,
-        !Constraint, !GCInfo) :-
-    GoalExpr = generic_call(GenericCall, Args, _Modes, _Det),
-    % Note: `_Modes' is invalid for higher-order calls at this point.
-    (
-        GenericCall = higher_order(Var, _, _, _),
-        generic_call_constrain_var(Var, GoalPath, !Constraint, !GCInfo),
-
-        % Record that the argument vars need to be constrained
-        % once we know the higher order mode of the Var we are calling.
-        HoCalls0 = !.GCInfo ^ ho_calls,
-        update_mc_info(get_prog_var_level(Var), VarLevel, !GCInfo),
-        multi_map.set(HoCalls0, VarLevel, GoalPath - Args, HoCalls),
-        !:GCInfo = !.GCInfo ^ ho_calls := HoCalls,
-
-        CanSucceed = yes % XXX should check this
-    ;
-        GenericCall = class_method(Var, _, _, _),
-        generic_call_constrain_var(Var, GoalPath, !Constraint, !GCInfo),
-        unexpected(this_file, "class_method call in clause")
+        GoalExpr = GoalExpr0
     ;
-        GenericCall = event_call(_),
-        sorry(this_file, "event_call NYI")
+        GoalExpr0 = switch(_, _, _),
+        unexpected(this_file, "goal_constraints_2: switch (should be disj)")
     ;
-        GenericCall = cast(_),
-        sorry(this_file, "type/inst cast call NYI")
-    ).
-
-goal_constraints_2(_, _, _, _, switch(_, _, _), _, _, _, _, _) :-
-    unexpected(this_file, "goal_constraints_2: switch (should be disj)").
-
-goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed,
-        negation(Goal0), negation(Goal), !Constraint, !GCInfo) :-
-    goal_constraints(NonLocals, _, Goal0, Goal, !Constraint, !GCInfo),
-
-    CanSucceed = yes,
-
-    list.foldl2((pred(V::in, C0::in, C::out, in, out) is det -->
-            get_var(V `at` GoalPath, Vgp),
-            get_var(V `at` goal_path(Goal), Vneg),
-            { C = C0 ^ eq_vars(Vgp, Vneg) }
-        ), set.to_sorted_list(Vars), !Constraint, !GCInfo),
-
-    % Make sure the negation doesn't bind any nonlocal variables.
-    negation_constraints(GoalPath, NonLocals, !Constraint, !GCInfo).
+        GoalExpr0 = negation(SubGoal0),
+        goal_constraints(NonLocals, _, SubGoal0, SubGoal,
+            !Constraint, !GCInfo),
 
-goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed, scope(Reason, Goal0),
-        scope(Reason, Goal), !Constraint, !GCInfo) :-
-    goal_constraints(NonLocals, CanSucceed, Goal0, Goal, !Constraint,
-        !GCInfo),
+        CanSucceed = yes,
 
-    list.foldl2((pred(V::in, C0::in, C::out, in, out) is det -->
-            get_var(V `at` GoalPath, Vgp),
-            get_var(V `at` goal_path(Goal), Vexist),
-            { C = C0 ^ eq_vars(Vgp, Vexist) }
-        ), set.to_sorted_list(Vars), !Constraint, !GCInfo).
-
-goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed,
-        if_then_else(IteNonLocals, Cond0, Then0, Else0),
-        if_then_else(IteNonLocals, Cond, Then, Else),
-        !Constraint, !GCInfo) :-
+        list.foldl2((pred(V::in, C0::in, C::out, in, out) is det -->
+                get_var(V `at` GoalId, Vgp),
+                get_var(V `at` get_goal_id(SubGoal), Vneg),
+                { C = C0 ^ eq_vars(Vgp, Vneg) }
+            ), set.to_sorted_list(Vars), !Constraint, !GCInfo),
+
+        % Make sure the negation doesn't bind any nonlocal variables.
+        negation_constraints(GoalId, NonLocals, !Constraint, !GCInfo),
+        GoalExpr = negation(SubGoal)
+    ;
+        GoalExpr0 = scope(Reason, SubGoal0),
+        goal_constraints(NonLocals, CanSucceed, SubGoal0, SubGoal, !Constraint,
+            !GCInfo),
+
+        list.foldl2((pred(V::in, C0::in, C::out, in, out) is det -->
+                get_var(V `at` GoalId, Vgp),
+                get_var(V `at` get_goal_id(SubGoal), Vexist),
+                { C = C0 ^ eq_vars(Vgp, Vexist) }
+            ), set.to_sorted_list(Vars), !Constraint, !GCInfo),
+        GoalExpr = scope(Reason, SubGoal)
+    ;
+        GoalExpr0 = if_then_else(IteNonLocals, Cond0, Then0, Else0),
+
+        % Make sure that the condition doesn't bind any variables that are
+        % non-local to the if-then-else.
+        negation_constraints(get_goal_id(Cond0), NonLocals, !Constraint,
+            !GCInfo),
+
+        goal_constraints(NonLocals, CanSucceedC, Cond0, Cond, !Constraint,
+            !GCInfo),
+        goal_constraints(NonLocals, CanSucceedT, Then0, Then, !Constraint,
+            !GCInfo),
+        goal_constraints(NonLocals, CanSucceedE, Else0, Else, !Constraint,
+            !GCInfo),
 
-    % Make sure that the condition doesn't bind any variables that are
-    % non-local to the if-then-else.
-    negation_constraints(goal_path(Cond0), NonLocals,
-        !Constraint, !GCInfo),
+        CanSucceed = (CanSucceedC `and` CanSucceedT) `or` CanSucceedE,
 
-    goal_constraints(NonLocals, CanSucceedC, Cond0, Cond, !Constraint,
-        !GCInfo),
-    goal_constraints(NonLocals, CanSucceedT, Then0, Then, !Constraint,
-        !GCInfo),
-    goal_constraints(NonLocals, CanSucceedE, Else0, Else, !Constraint,
-        !GCInfo),
-
-    CanSucceed = (CanSucceedC `and` CanSucceedT) `or` CanSucceedE,
-
-    InstGraph = !.GCInfo ^ inst_graph,
-    NonLocalReachable = solutions.solutions(inst_graph.reachable_from_list(
-        InstGraph, to_sorted_list(NonLocals))),
+        InstGraph = !.GCInfo ^ inst_graph,
+        NonLocalReachable = solutions.solutions(inst_graph.reachable_from_list(
+            InstGraph, to_sorted_list(NonLocals))),
 
-    % Make sure variables have the same bindings in both the then and else
-    % branches.
-    list.foldl2((pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
-            get_var(V `at` GoalPath, Vgp, S0, S1),
-            get_var(V `at` goal_path(Then0), Vthen, S1, S2),
-            get_var(V `at` goal_path(Else0), Velse, S2, S),
-            C = C0 ^ eq_vars(Vgp, Vthen) ^ eq_vars(Vgp, Velse)
-        ), NonLocalReachable, !Constraint, !GCInfo),
-
-    % Make sure variables are bound in at most one of the cond and then
-    % goals.
-    list.foldl2((pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
-            get_var(V `at` goal_path(Cond0), Vcond, S0, S1),
-            get_var(V `at` goal_path(Then0), Vthen, S1, S),
-            C = C0 ^ not_both(Vcond, Vthen)
-        ), set.to_sorted_list(vars(Cond0) `set.union` vars(Then0)),
-        !Constraint, !GCInfo),
+        % Make sure variables have the same bindings in both the then and else
+        % branches.
+        list.foldl2((pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
+                get_var(V `at` GoalId, Vgp, S0, S1),
+                get_var(V `at` get_goal_id(Then0), Vthen, S1, S2),
+                get_var(V `at` get_goal_id(Else0), Velse, S2, S),
+                C = C0 ^ eq_vars(Vgp, Vthen) ^ eq_vars(Vgp, Velse)
+            ), NonLocalReachable, !Constraint, !GCInfo),
+
+        % Make sure variables are bound in at most one of the cond and then
+        % goals.
+        list.foldl2((pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
+                get_var(V `at` get_goal_id(Cond0), Vcond, S0, S1),
+                get_var(V `at` get_goal_id(Then0), Vthen, S1, S),
+                C = C0 ^ not_both(Vcond, Vthen)
+            ), set.to_sorted_list(vars(Cond0) `set.union` vars(Then0)),
+            !Constraint, !GCInfo),
 
-    % Local variables bound in cond, then or else should be treated as
-    % though they are bound in the ite as well. (Although all such
-    % variables will be local to the ite, the _out constraints still need to
-    % be satisfied.)
-    Locals = to_sorted_list(
-        Vars `difference` sorted_list_to_set(NonLocalReachable)),
-    list.foldl2((pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
-            get_var(V `at` goal_path(Cond), Vcond, S0, S1),
-            get_var(V `at` goal_path(Then), Vthen, S1, S2),
-            get_var(V `at` goal_path(Else), Velse, S2, S3),
-            get_var(V `at` GoalPath, Vgp, S3, S),
-            Vs = list_to_set([Vcond, Vthen, Velse]),
-            C = C0 ^ disj_vars_eq(Vs, Vgp)
-        ), Locals, !Constraint, !GCInfo).
-
-goal_constraints_2(_, _, _, _, call_foreign_proc(_, _, _, _, _, _, _),
-        _, _, _, _, _) :-
-    sorry(this_file, "goal_constraints_2: foreign_proc NYI").
+        % Local variables bound in cond, then or else should be treated as
+        % though they are bound in the ite as well. (Although all such
+        % variables will be local to the ite, the _out constraints still
+        % need to be satisfied.)
+        Locals = to_sorted_list(
+            Vars `difference` sorted_list_to_set(NonLocalReachable)),
+        list.foldl2((pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
+                get_var(V `at` get_goal_id(Cond), Vcond, S0, S1),
+                get_var(V `at` get_goal_id(Then), Vthen, S1, S2),
+                get_var(V `at` get_goal_id(Else), Velse, S2, S3),
+                get_var(V `at` GoalId, Vgp, S3, S),
+                Vs = list_to_set([Vcond, Vthen, Velse]),
+                C = C0 ^ disj_vars_eq(Vs, Vgp)
+            ), Locals, !Constraint, !GCInfo),
 
-goal_constraints_2(_, _, _, _, shorthand(_), _, _, _, _, _) :-
-    sorry(this_file, "goal_constraints_2: shorthand").
+        GoalExpr = if_then_else(IteNonLocals, Cond, Then, Else)
+    ;
+        GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _),
+        sorry(this_file, "goal_constraints_2: foreign_proc NYI")
+    ;
+        GoalExpr0 = shorthand(_),
+        sorry(this_file, "goal_constraints_2: shorthand")
+    ).
 
-% goal_constraints_2(GoalPath, NonLocals, Vars, CanSucceed,
+% goal_constraints_2(GoalId, NonLocals, Vars, CanSucceed,
 %         atomic_goal(GoalType, Outer, Inner, OutVars, MainGoal0, OrElseGoals0),
 %         atomic_goal(GoalType, Outer, Inner, OutVars, MainGoal, OrElseGoals),
 %         !Constraint, !GCInfo) :-
@@ -1470,7 +1466,7 @@
 %     disj_constraints(NonLocals, CanSucceed, !Constraint, Goals0, Goals,
 %         [], DisjunctPaths, !GCInfo),
 %     list.foldl2((pred(V::in, Cons0::in, Cons::out, in, out) is det -->
-%         get_var(V `at` GoalPath, Vgp),
+%         get_var(V `at` GoalId, Vgp),
 %         list.foldl2((pred(Path::in, C0::in, C::out, in, out) is det -->
 %             get_var(V `at` Path, VPath),
 %             { C = C0 ^ eq_vars(Vgp, VPath) }
@@ -1484,31 +1480,29 @@
     % constraints only for the vars _not_ is KnownVars.
     %
 :- pred conj_constraints(bool::in, mode_constraint_vars::in,
-    mode_constraint_vars::in, goal_path::in,
-    multi_map(prog_var, goal_path)::in,
+    mode_constraint_vars::in, goal_id::in, multi_map(prog_var, goal_id)::in,
     mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-conj_constraints(UseKnownVars, KnownTrue, KnownFalse, GoalPath, UsageMap,
+conj_constraints(UseKnownVars, KnownTrue, KnownFalse, GoalId, UsageMap,
         !Constraint, !GCInfo) :-
     UsageList = map.to_assoc_list(UsageMap), % XXX needed for deep profiler
     list.foldl2(
         conj_constraints_process_var(UseKnownVars, KnownTrue, KnownFalse,
-            GoalPath),
+            GoalId),
         UsageList, !Constraint, !GCInfo).
 
 :- pred conj_constraints_process_var(bool::in, mode_constraint_vars::in,
-    mode_constraint_vars::in, goal_path::in,
-    pair(prog_var, list(goal_path))::in,
+    mode_constraint_vars::in, goal_id::in, pair(prog_var, list(goal_id))::in,
     mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-conj_constraints_process_var(UseKnownVars, KnownTrue, KnownFalse, GoalPath,
-        Var - Paths, !Constraint, !GCInfo) :-
-    list.map_foldl((pred(P::in, CV::out, in, out) is det -->
-        get_var(Var `at` P, CV)
-    ), Paths, ConstraintVars, !GCInfo),
-    get_var(Var `at` GoalPath, VConj, !GCInfo),
+conj_constraints_process_var(UseKnownVars, KnownTrue, KnownFalse, GoalId,
+        Var - Ids, !Constraint, !GCInfo) :-
+    list.map_foldl((pred(I::in, CV::out, in, out) is det -->
+        get_var(Var `at` I, CV)
+    ), Ids, ConstraintVars, !GCInfo),
+    get_var(Var `at` GoalId, VConj, !GCInfo),
     ConstraintVarSet = list_to_set(ConstraintVars),
 
     % If UseKnownVars = yes we want to only generate the constraints
@@ -1577,162 +1571,169 @@
 :- pred disj_constraints(set(prog_var)::in, can_succeed::out,
     mode_constraint::in, mode_constraint::out,
     hlds_goals::in, hlds_goals::out,
-    list(goal_path)::in, list(goal_path)::out,
+    list(goal_id)::in, list(goal_id)::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-disj_constraints(_, no, !Constraint, [], [], Paths, Paths, !GCInfo).
+disj_constraints(_, no, !Constraint, [], [], Ids, Ids, !GCInfo).
 disj_constraints(NonLocals, CanSucceed, !Constraint,
-        [Goal0 | Goals0], [Goal | Goals], Paths0, Paths, !GCInfo) :-
+        [Goal0 | Goals0], [Goal | Goals], Ids0, Ids, !GCInfo) :-
     goal_constraints(NonLocals, CanSucceed0, Goal0, Goal,
         !Constraint, !GCInfo),
-    disj_constraints(NonLocals, CanSucceed1, !Constraint,
-        Goals0, Goals, [goal_path(Goal) | Paths0], Paths, !GCInfo),
+    disj_constraints(NonLocals, CanSucceed1, !Constraint, Goals0, Goals,
+        [get_goal_id(Goal) | Ids0], Ids, !GCInfo),
     CanSucceed = CanSucceed0 `bool.or` CanSucceed1.
 
     % See 1.2.3 The literals themselves
-:- pred unify_constraints(prog_var::in, goal_path::in, unify_rhs::in,
+    %
+:- pred unify_constraints(prog_var::in, goal_id::in, unify_rhs::in,
     unify_rhs::out, mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-unify_constraints(A, GoalPath, RHS, RHS, !Constraint, !GCInfo) :-
-    RHS = rhs_var(B),
-    InstGraph = !.GCInfo ^ inst_graph,
-    Generator =
-        (pred((V - W)::out) is multi :-
-            inst_graph.same_graph_corresponding_nodes(InstGraph, A, B, V, W)
-        ),
-    Accumulator =
-        (pred((V - W)::in, C0::in, C::out, S0::in, S::out) is det :-
-            get_var(out(V), Vout, S0, S1),
-            get_var(out(W), Wout, S1, S2),
-            get_var(V `at` GoalPath, Vgp, S2, S3),
-            get_var(W `at` GoalPath, Wgp, S3, S),
-            C = C0 ^ eq_vars(Vout, Wout) ^ not_both(Vgp, Wgp)
-        ),
-    solutions.aggregate2(Generator, Accumulator, !Constraint, !GCInfo),
-    get_var(out(A), Aout, !GCInfo),
-    !:Constraint = !.Constraint ^ var(Aout),
-
-    HoModes0 = !.GCInfo ^ ho_modes,
-    update_mc_info(share_ho_modes(A, B, HoModes0), HoModes, !GCInfo),
-    !:GCInfo = !.GCInfo ^ ho_modes := HoModes.
-
-unify_constraints(A, GoalPath, RHS, RHS, !Constraint, !GCInfo) :-
-    RHS = rhs_functor(_ConsId, _IsExistConstruct, Args),
-    get_var(out(A), Aout, !GCInfo),
-    !:Constraint = !.Constraint ^ var(Aout),
-    ( update_mc_info(using_simple_mode_constraints, !GCInfo) ->
-        % In the simple system a var-functor unification must be either
-        % a construction or a deconstruction.
-        list.map_foldl(
-            ( pred(ProgVar::in, RepVar::out, S0::in, S::out) is det :-
-                get_var(ProgVar `at` GoalPath, RepVar, S0, S)
-            ), Args, ArgsGp0, !GCInfo),
-        ArgsGp = list_to_set(ArgsGp0),
-        get_var(A `at` GoalPath, Agp, !GCInfo),
-        ( remove_least(ArgsGp, Arg1gp, ArgsGp1) ->
-            !:Constraint = !.Constraint
-                ^ neq_vars(Arg1gp, Agp)
-                ^ fold(eq_vars(Arg1gp), ArgsGp1)
+unify_constraints(LHSVar, GoalId, RHS0, RHS, !Constraint, !GCInfo) :-
+    (
+        RHS0 = rhs_var(RHSVar),
+        InstGraph = !.GCInfo ^ inst_graph,
+        Generator =
+            (pred((V - W)::out) is multi :-
+                inst_graph.same_graph_corresponding_nodes(InstGraph,
+                    LHSVar, RHSVar, V, W)
+            ),
+        Accumulator =
+            (pred((V - W)::in, C0::in, C::out, S0::in, S::out) is det :-
+                get_var(out(V), Vout, S0, S1),
+                get_var(out(W), Wout, S1, S2),
+                get_var(V `at` GoalId, Vgi, S2, S3),
+                get_var(W `at` GoalId, Wgi, S3, S),
+                C = C0 ^ eq_vars(Vout, Wout) ^ not_both(Vgi, Wgi)
+            ),
+        solutions.aggregate2(Generator, Accumulator, !Constraint, !GCInfo),
+        get_var(out(LHSVar), LHSVarOut, !GCInfo),
+        !:Constraint = !.Constraint ^ var(LHSVarOut),
+
+        HoModes0 = !.GCInfo ^ ho_modes,
+        update_mc_info_t(share_ho_modes(LHSVar, RHSVar, HoModes0), HoModes,
+            !GCInfo),
+        !GCInfo ^ ho_modes := HoModes,
+        RHS = RHS0
+    ;
+        RHS0 = rhs_functor(_ConsId, _IsExistConstruct, Args),
+        get_var(out(LHSVar), LHSVarOut, !GCInfo),
+        !:Constraint = !.Constraint ^ var(LHSVarOut),
+        ( using_simple_mode_constraints(!.GCInfo ^ g_mc_info) ->
+            % In the simple system a var-functor unification must be either
+            % a construction or a deconstruction.
+            list.map_foldl(
+                ( pred(ProgVar::in, RepVar::out, S0::in, S::out) is det :-
+                    get_var(ProgVar `at` GoalId, RepVar, S0, S)
+                ), Args, ArgsGi0, !GCInfo),
+            ArgsGi = list_to_set(ArgsGi0),
+            get_var(LHSVar `at` GoalId, LHSVargi, !GCInfo),
+            ( remove_least(ArgsGi, Arg1gi, ArgsGi1) ->
+                !:Constraint = !.Constraint
+                    ^ neq_vars(Arg1gi, LHSVargi)
+                    ^ fold(eq_vars(Arg1gi), ArgsGi1)
+            ;
+                !:Constraint = !.Constraint
+            )
+            % Constraint = Constraint1 *
+            %   ( one ^ var(Agp) ^ conj_not_vars(ArgsGp)
+            %   + one ^ not_var(Agp) ^ conj_vars(ArgsGp)
+            %   )
         ;
-            !:Constraint = !.Constraint
-        )
-        %{ Constraint = Constraint1 *
-        %   ( one ^ var(Agp) ^ conj_not_vars(ArgsGp)
-        %   + one ^ not_var(Agp) ^ conj_vars(ArgsGp)
-        %   ) }
+            InstGraph = !.GCInfo ^ inst_graph,
+            inst_graph.foldl_reachable_from_list2(
+                ( pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
+                    ( V \= LHSVar ->
+                        get_var(V `at` GoalId, Vgp, S0, S),
+                        C = C0 ^ not_var(Vgp)
+                    ;
+                        C = C0,
+                        S = S0
+                    )
+                ), InstGraph, Args, !Constraint, !GCInfo)
+        ),
+        RHS = RHS0
     ;
+        RHS0 = rhs_lambda_goal(_, _, _, _, NonLocals, LambdaVars, Modes,
+            _, Goal0),
         InstGraph = !.GCInfo ^ inst_graph,
-        inst_graph.foldl_reachable_from_list2(
-            ( pred(V::in, C0::in, C::out, S0::in, S::out) is det :-
-                ( V \= A ->
-                    get_var(V `at` GoalPath, Vgp, S0, S),
-                    C = C0 ^ not_var(Vgp)
-                ;
-                    C = C0,
-                    S = S0
-                )
-            ), InstGraph, Args, !Constraint, !GCInfo)
-    ).
-
-unify_constraints(Var, GoalPath, RHS0, RHS, !Constraint, !GCInfo) :-
-    RHS0 = rhs_lambda_goal(_, _, _, _, NonLocals, LambdaVars, Modes, _, Goal0),
-    InstGraph = !.GCInfo ^ inst_graph,
 
-    % Variable Var is made ground by this goal.
-    inst_graph.foldl_reachable2(
-        ( pred(V::in, Cn0::in, Cn::out, in, out) is det -->
-            get_var(V `at` GoalPath, Vgp),
-            { Cn = Cn0 ^ var(Vgp) }
-        ), InstGraph, Var, !Constraint, !GCInfo),
-
-    % The lambda NonLocals are not bound by this goal.
-    inst_graph.foldl_reachable_from_list2(
-        ( pred(V::in, Cn0::in, Cn::out, in, out) is det -->
-            get_var(V `at` GoalPath, Vgp),
-            { Cn = Cn0 ^ not_var(Vgp) }
-        ), InstGraph, NonLocals, !Constraint, !GCInfo),
-
-    % Record the higher-order mode of this lambda goal.
-    HoModes0 = !.GCInfo ^ ho_modes,
-    update_mc_info(get_prog_var_level(Var), VarLevel, !GCInfo),
-    multi_map.set(HoModes0, VarLevel, Modes, HoModes),
-    !:GCInfo = !.GCInfo ^ ho_modes := HoModes,
-
-    % Analyse the lambda goal.
-    update_mc_info(enter_lambda_goal(GoalPath), !GCInfo),
-
-    % XXX rather than adding `in' modes for lambda nonlocals we
-    % should just place a constraint `V_prod = 0' for all nodes
-    % reachable from these variables in the lambda goal.
-    ArgModes = list.duplicate(length(NonLocals), in_mode) ++ Modes,
-    LambdaHeadVars = NonLocals ++ LambdaVars,
-    ModuleInfo = !.GCInfo ^ module_info,
-    update_md_info(process_mode_decl(ModuleInfo,
-        InstGraph, LambdaHeadVars, false_var(initial),
-        true_var(initial), yes, false_var(final), true_var(final), no,
-        ArgModes, zero), DeclConstraint, !GCInfo),
-    !:Constraint = !.Constraint * DeclConstraint,
-
-    % XXX This will put constraints on variables that do not occur in
-    % the lambda goal. These constraints will be removed at the next
-    % restrict, but it would be more efficient not to put them in in the
-    % first place.
-
-    % DEBUGGING CODE
-    % size(!.Constraint, NumNodes3, Depth3, _),
-    % unsafe_perform_io(io.format(
-    %   "Pre lambda Size: %d, Depth: %d\n",
-    %   [i(NumNodes3), i(Depth3)])),
-
-    update_mc_info((pred(C::out, S0::in, S::out) is det :-
-            map.foldl2(input_output_constraints(LambdaHeadVars, InstGraph),
-                InstGraph, !.Constraint, C, S0, S)
-        ), !:Constraint, !GCInfo),
-
-    % DEBUGGING CODE
-    % size(!.Constraint, NumNodes5, Depth5, _),
-    % unsafe_perform_io(io.format(
-    %   "lambda io_constraints Size: %d, Depth: %d\n",
-    %   [i(NumNodes5), i(Depth5)])),
+        % Variable Var is made ground by this goal.
+        inst_graph.foldl_reachable2(
+            ( pred(V::in, Cn0::in, Cn::out, in, out) is det -->
+                get_var(V `at` GoalId, Vgp),
+                { Cn = Cn0 ^ var(Vgp) }
+            ), InstGraph, LHSVar, !Constraint, !GCInfo),
 
-    goal_constraints(set.init, _CanSucceed, Goal0, Goal, !Constraint,
-        !GCInfo),
-
-    % DEBUGGING CODE
-    % size(Constraint, NumNodes, Depth),
-    % unsafe_perform_io(io.format(
-    %   "post lambda Size: %d, Depth: %d\n",
-    %   [i(NumNodes), i(Depth)])),
+        % The lambda NonLocals are not bound by this goal.
+        inst_graph.foldl_reachable_from_list2(
+            ( pred(V::in, Cn0::in, Cn::out, in, out) is det -->
+                get_var(V `at` GoalId, Vgp),
+                { Cn = Cn0 ^ not_var(Vgp) }
+            ), InstGraph, NonLocals, !Constraint, !GCInfo),
+
+        % Record the higher-order mode of this lambda goal.
+        HoModes0 = !.GCInfo ^ ho_modes,
+        get_prog_var_level(!.GCInfo ^ mc_info, LHSVar, LHSVarLevel),
+        multi_map.set(HoModes0, LHSVarLevel, Modes, HoModes),
+        !GCInfo ^ ho_modes := HoModes,
+
+        % Analyse the lambda goal.
+        update_mc_info(enter_lambda_goal(GoalId), !GCInfo),
+
+        % XXX Rather than adding `in' modes for lambda nonlocals we should just
+        % place a constraint `V_prod = 0' for all nodes reachable from these
+        % variables in the lambda goal.
+        ArgModes = list.duplicate(length(NonLocals), in_mode) ++ Modes,
+        LambdaHeadVars = NonLocals ++ LambdaVars,
+        ModuleInfo = !.GCInfo ^ module_info,
+        update_md_info(process_mode_decl(ModuleInfo,
+            InstGraph, LambdaHeadVars, false_var(initial),
+            true_var(initial), yes, false_var(final), true_var(final), no,
+            ArgModes, zero), DeclConstraint, !GCInfo),
+        !:Constraint = !.Constraint * DeclConstraint,
+
+        % XXX This will put constraints on variables that do not occur in
+        % the lambda goal. These constraints will be removed at the next
+        % restrict, but it would be more efficient not to put them in in the
+        % first place.
+
+        % DEBUGGING CODE
+        % size(!.Constraint, NumNodes3, Depth3, _),
+        % unsafe_perform_io(io.format(
+        %   "Pre lambda Size: %d, Depth: %d\n",
+        %   [i(NumNodes3), i(Depth3)])),
+
+        update_mc_info_t((pred(C::out, S0::in, S::out) is det :-
+                map.foldl2(input_output_constraints(LambdaHeadVars, InstGraph),
+                    InstGraph, !.Constraint, C, S0, S)
+            ), !:Constraint, !GCInfo),
+
+        % DEBUGGING CODE
+        % size(!.Constraint, NumNodes5, Depth5, _),
+        % unsafe_perform_io(io.format(
+        %   "lambda io_constraints Size: %d, Depth: %d\n",
+        %   [i(NumNodes5), i(Depth5)])),
+
+        goal_constraints(set.init, _CanSucceed, Goal0, Goal, !Constraint,
+            !GCInfo),
+
+        % DEBUGGING CODE
+        % size(Constraint, NumNodes, Depth),
+        % unsafe_perform_io(io.format(
+        %   "post lambda Size: %d, Depth: %d\n",
+        %   [i(NumNodes), i(Depth)])),
 
-    update_mc_info(leave_lambda_goal, !GCInfo),
-    RHS = RHS0 ^ rhs_lambda_goal := Goal.
+        update_mc_info(leave_lambda_goal, !GCInfo),
+        RHS = RHS0 ^ rhs_lambda_goal := Goal
+    ).
 
-:- pred call_constraints(goal_path::in, pred_id::in, list(prog_var)::in,
-    list(prog_var)::in, mode_constraint::in, mode_constraint::out,
+:- pred call_constraints(goal_id::in, pred_id::in,
+    list(prog_var)::in, list(prog_var)::in,
+    mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-call_constraints(GoalPath, PredId, HeadVars, Args, !Constraint, !GCInfo) :-
+call_constraints(GoalId, PredId, HeadVars, Args, !Constraint, !GCInfo) :-
     InstGraph = !.GCInfo ^ inst_graph,
     Generator =
         (pred((V - W)::out) is nondet :-
@@ -1741,17 +1742,17 @@
         ),
     Accumulator =
         (pred((V - W)::in, C0::in, C::out, S0::in, S::out) is det :-
-            get_var(PredId, V `at` empty_goal_path, V_, S0, S1),
-            get_var(W `at` GoalPath, Wgp, S1, S2),
-            get_var(PredId, in(V), Vin, S2, S3),
+            get_var_in_pred(PredId, V `at` whole_body_goal_id, V_, S0, S1),
+            get_var(W `at` GoalId, Wgi, S1, S2),
+            get_var_in_pred(PredId, in(V), Vin, S2, S3),
             get_var(out(W), Wout, S3, S),
-            C = C0 ^ eq_vars(V_, Wgp) ^ imp_vars(Vin, Wout)
+            C = C0 ^ eq_vars(V_, Wgi) ^ imp_vars(Vin, Wout)
         ),
     solutions.aggregate2(Generator, Accumulator, !Constraint, !GCInfo).
 
-:- pred higher_order_call_constraints(mode_constraint::in,
-    mode_constraint::out, goal_constraints_info::in,
-    goal_constraints_info::out) is det.
+:- pred higher_order_call_constraints(
+    mode_constraint::in, mode_constraint::out,
+    goal_constraints_info::in, goal_constraints_info::out) is det.
 
 higher_order_call_constraints(Constraint0, Constraint, !GCInfo) :-
     HoModes = !.GCInfo ^ ho_modes,
@@ -1762,84 +1763,93 @@
         (pred(Constraint1::out, in, out) is det -->
         map.foldl2(
             (pred(HoVarLevel::in, Calls::in, Cons0::in, Cons::out,
-                in, out) is det -->
-            update_mc_info(set_level_from_var(HoVarLevel)),
-            ( { map.search(HoModes, HoVarLevel, ArgModesList) } ->
-                list.foldl2(
-                (pred((GoalPath - Args)::in, C0::in, C::out,
                     in, out) is det -->
+                update_mc_info(set_level_from_var(HoVarLevel)),
+                ( { map.search(HoModes, HoVarLevel, ArgModesList) } ->
                     list.foldl2(
-                    process_mode_decl(
-                        ModuleInfo, InstGraph, Args, ignore,
-                        call_in(GoalPath), no,
-                        false_var(goal_path(GoalPath)),
-                        call_out(GoalPath), no
-                    ), ArgModesList, zero, C1),
-                    { C = C0 * C1 } ),
-                Calls, Cons0, Cons)
-            ;
-                { Cons = Cons0 }
-            )
+                        (pred((GoalId - Args)::in, C0::in, C::out,
+                                in, out) is det -->
+                            list.foldl2(
+                                process_mode_decl(ModuleInfo, InstGraph,
+                                    Args, ignore, call_in(GoalId), no,
+                                    false_var(var_at_goal_id(GoalId)),
+                                    call_out(GoalId), no
+                                ), ArgModesList, zero, C1),
+                            { C = C0 * C1 } ),
+                        Calls, Cons0, Cons)
+                ;
+                    { Cons = Cons0 }
+                )
             ), HoCalls, Constraint0, Constraint1)),
         Constraint, !GCInfo).
 
-:- pred negation_constraints(goal_path::in, set(prog_var)::in,
+:- pred negation_constraints(goal_id::in, set(prog_var)::in,
     mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-negation_constraints(GoalPath, NonLocals, !Constraint, !GCInfo) :-
+negation_constraints(GoalId, NonLocals, !Constraint, !GCInfo) :-
     InstGraph = !.GCInfo ^ inst_graph,
     inst_graph.foldl_reachable_from_list2(
         (pred(V::in, C0::in, C::out, in, out) is det -->
-            get_var(V `at` GoalPath, Vgp),
+            get_var(V `at` GoalId, Vgp),
             { C = C0 ^ not_var(Vgp) }
         ), InstGraph, to_sorted_list(NonLocals),
         !Constraint, !GCInfo).
 
-:- pred generic_call_constrain_var(prog_var::in, goal_path::in,
+:- pred generic_call_constrain_var(prog_var::in, goal_id::in,
     mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-generic_call_constrain_var(Var, GoalPath, !Constraint, !GCInfo) :-
+generic_call_constrain_var(Var, GoalId, !Constraint, !GCInfo) :-
     InstGraph = !.GCInfo ^ inst_graph,
     inst_graph.foldl_reachable2(
         ( pred(V::in, C0::in, C::out, in, out) is det -->
             get_var(out(V), Vout),
-            get_var(V `at` GoalPath, Vgp),
+            get_var(V `at` GoalId, Vgp),
             { C = C0 ^ var(Vout) ^ not_var(Vgp) }
         ), InstGraph, Var, !Constraint, !GCInfo).
 
-:- pred constrict_to_vars(list(prog_var)::in, set(prog_var)::in, goal_path::in,
-    mode_constraint::in, mode_constraint::out, goal_constraints_info::in,
-    goal_constraints_info::out) is det.
-
-constrict_to_vars(NonLocals, GoalVars, GoalPath, !Constraint, !Info) :-
-    !:Constraint = restrict_filter(keep_var(NonLocals, GoalVars, GoalPath,
-        !.Info ^ atomic_goals, !.Info ^ inst_graph), !.Info ^ mc_info,
-        !.Constraint).
-
-:- pred keep_var(list(prog_var)::in, set(prog_var)::in, goal_path::in,
-    set(goal_path)::in, inst_graph::in, rep_var::in) is semidet.
-
-keep_var(_, _, _, AtomicGoals, _, _V `at` GoalPath) :-
-    set.member(GoalPath, AtomicGoals).
-keep_var(NonLocals, GoalVars, GoalPath, _AtomicGoals, InstGraph, RepVar) :-
-    (
-        ( RepVar = in(V)
-        ; RepVar = out(V)
-        ; RepVar = V `at` _
-        ),
-        set.member(V, GoalVars)
-    )
-    =>
+:- pred constrict_to_vars(list(prog_var)::in, set(prog_var)::in,
+    goal_id::in, mode_constraint::in, mode_constraint::out,
+    goal_constraints_info::in, goal_constraints_info::out) is det.
+
+constrict_to_vars(NonLocals, GoalVars, GoalId, !Constraint, !GCInfo) :-
+    get_forward_goal_path_map(!.GCInfo ^ mc_info, ForwardGoalPathMap),
+    !:Constraint = restrict_filter(
+        keep_var(ForwardGoalPathMap, NonLocals, GoalVars, GoalId,
+            !.GCInfo ^ atomic_goals, !.GCInfo ^ inst_graph),
+        !.GCInfo ^ mc_info, !.Constraint).
+
+:- pred keep_var(goal_forward_path_map::in, list(prog_var)::in,
+    set(prog_var)::in, goal_id::in, set(goal_id)::in, inst_graph::in,
+    rep_var::in) is semidet.
+
+keep_var(ForwardGoalPathMap, NonLocals, GoalVars, GoalId, AtomicGoals,
+        InstGraph, RepVar) :-
     (
-        list.member(NonLocal, NonLocals),
-        inst_graph.reachable(InstGraph, NonLocal, V),
-        \+ (
-            RepVar = _ `at` GoalPath1,
-            GoalPathSteps = goal_path_to_list(GoalPath),
-            GoalPathSteps1 = goal_path_to_list(GoalPath1),
-            list.remove_suffix(GoalPathSteps1, GoalPathSteps, [_ | _])
+        RepVar = _V `at` RepGoalId,
+        set.member(RepGoalId, AtomicGoals)
+    ;
+        (
+            ( RepVar = in(V)
+            ; RepVar = out(V)
+            ; RepVar = V `at` _
+            ),
+            set.member(V, GoalVars)
+        )
+        =>
+        (
+            list.member(NonLocal, NonLocals),
+            inst_graph.reachable(InstGraph, NonLocal, V),
+            \+ (
+                RepVar = _ `at` RepGoalId,
+                % XXX What higher level operation is being implemented here?
+                map.lookup(ForwardGoalPathMap, GoalId, GoalPath),
+                map.lookup(ForwardGoalPathMap, RepGoalId, RepGoalPath),
+                GoalPath = fgp(GoalPathSteps),
+                RepGoalPath = fgp(RepGoalPathSteps),
+                list.remove_suffix(RepGoalPathSteps, GoalPathSteps, [_ | _])
+            )
         )
     ).
 
@@ -1924,30 +1934,36 @@
 
 % For local variables, V_ must be equivalent to Vgp.
 
-:- pred constrain_local_vars(set(prog_var)::in, goal_path::in,
+:- pred constrain_local_vars(set(prog_var)::in, goal_id::in,
     mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
-constrain_local_vars(Locals, GoalPath, !Constraint, !GCInfo) :-
-    list.foldl2((pred(V::in, C0::in, C::out, in, out) is det -->
-        get_var(V `at` GoalPath, Vgp),
-        get_var(out(V), Vout),
-        ( update_mc_info(using_simple_mode_constraints) ->
-            % For simple_mode_constraints, local variables must all be
-            % bound within the goal.
-            { C = C0 ^ var(Vgp) ^ var(Vout) }
-        ;
-            { C = C0 ^ eq_vars(Vgp, Vout) }
-        )
-    ), to_sorted_list(Locals), !Constraint, !GCInfo).
+constrain_local_vars(Locals, GoalId, !Constraint, !GCInfo) :-
+    list.foldl2(do_constrain_local_vars(GoalId), to_sorted_list(Locals),
+        !Constraint, !GCInfo).
+
+:- pred do_constrain_local_vars(goal_id::in, prog_var::in,
+    mode_constraint::in, mode_constraint::out,
+    goal_constraints_info::in, goal_constraints_info::out) is det.
+
+do_constrain_local_vars(GoalId, Var, !Constraint, !GCInfo) :-
+    get_var(Var `at` GoalId, Vgp, !GCInfo),
+    get_var(out(Var), Vout, !GCInfo),
+    ( using_simple_mode_constraints(!.GCInfo ^ g_mc_info) ->
+        % For simple_mode_constraints, local variables must all be bound
+        % within the goal.
+        !:Constraint = !.Constraint ^ var(Vgp) ^ var(Vout)
+    ;
+        !:Constraint = !.Constraint ^ eq_vars(Vgp, Vout)
+    ).
 
 :- pred constrain_non_occurring_vars(can_succeed::in, set(prog_var)::in,
-    set(prog_var)::in, goal_path::in,
+    set(prog_var)::in, goal_id::in,
     mode_constraint::in, mode_constraint::out,
     goal_constraints_info::in, goal_constraints_info::out) is det.
 
 constrain_non_occurring_vars(no, _, _, _, !Constraint, !GCInfo).
-constrain_non_occurring_vars(yes, ParentNonLocals, OccurringVars, GoalPath,
+constrain_non_occurring_vars(yes, ParentNonLocals, OccurringVars, GoalId,
         !Constraint, !GCInfo) :-
     InstGraph = !.GCInfo ^ inst_graph,
     Generator =
@@ -1958,7 +1974,7 @@
         ),
     Accumulator =
         (pred(V::in, Vs0::in, Vs::out, in, out) is det -->
-            get_var(V `at` GoalPath, VGP),
+            get_var(V `at` GoalId, VGP),
             { Vs = Vs0 `insert` VGP }
         ),
     solutions.aggregate2(Generator, Accumulator, empty_vars_set,
@@ -1970,7 +1986,7 @@
 %       inst_graph.reachable(InstGraph, U, V),
 %       \+ set.member(V, OccurringVars)
 %       ), (pred(V::in, C0::in, C::out, in, out) is det -->
-%           get_var(V `at` GoalPath, VGP),
+%           get_var(V `at` GoalId, VGP),
 %           { C = C0 ^ not_var(VGP) }
 %       ), Constraint0, Constraint).
 
@@ -1980,11 +1996,11 @@
     mode_constraint_info::in, mode_constraint_info::out) is det.
 
 share_ho_modes(VarA, VarB, HoModes0, HoModes, !MCI) :-
-    get_prog_var_level(VarA, A, !MCI),
-    get_prog_var_level(VarB, B, !MCI),
+    get_prog_var_level(!.MCI, VarA, A),
+    get_prog_var_level(!.MCI, VarB, B),
     ( map.search(HoModes0, A, AModes) ->
         ( map.search(HoModes0, B, BModes) ->
-            Modes = list.sort_and_remove_dups(AModes `list.append` BModes),
+            Modes = list.sort_and_remove_dups(AModes ++ BModes),
             map.det_update(HoModes0, A, Modes, HoModes1),
             map.det_update(HoModes1, B, Modes, HoModes)
         ;
@@ -2009,7 +2025,7 @@
         mode_constraint_var(in(PV), MV)), Vars, InVars, Info0, Info1),
     list.map_foldl((pred(PV::in, (MV - out(PV))::out, in, out) is det -->
         mode_constraint_var(out(PV), MV)), Vars, OutVars, Info0, Info1),
-    MVars = list.sort_and_remove_dups(InVars `list.append` OutVars),
+    MVars = list.sort_and_remove_dups(InVars ++ OutVars),
     MVarKeys = assoc_list.keys(MVars),
     Constraint = restrict_filter(
         (pred(V::in) is semidet :- list.member(V, MVarKeys)),
@@ -2099,10 +2115,10 @@
 %------------------------------------------------------------------------%
 %------------------------------------------------------------------------%
 
-:- func goal_path(hlds_goal) = goal_path.
+:- func get_goal_id(hlds_goal) = goal_id.
 
-goal_path(hlds_goal(_, GoalInfo)) =
-    goal_info_get_goal_path(GoalInfo).
+get_goal_id(hlds_goal(_, GoalInfo)) =
+    goal_info_get_goal_id(GoalInfo).
 
 :- func vars(hlds_goal) = set(prog_var).
 
Index: compiler/mode_ordering.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_ordering.m,v
retrieving revision 1.31
diff -u -r1.31 mode_ordering.m
--- compiler/mode_ordering.m	15 Dec 2010 06:29:51 -0000	1.31
+++ compiler/mode_ordering.m	15 Dec 2010 06:33:21 -0000
@@ -25,8 +25,8 @@
 
 :- type pred_constraint_info
     --->    pci(
-                mode_constraint,
-                mode_constraint_info
+                pci_mode_constraint :: mode_constraint,
+                pci_mci             :: mode_constraint_info
             ).
 
 :- type pred_constraint_map == map(pred_id, pred_constraint_info).
@@ -45,6 +45,7 @@
 
 :- import_module check_hlds.clause_to_proc.
 :- import_module check_hlds.mode_constraint_robdd.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.inst_graph.
 :- import_module mode_robdd.
@@ -84,13 +85,12 @@
     RequestedProcsMap0 = map.init,
 
     module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
-    lookup_pred_constraint(PredConstraintMap, PredId,
-        ModeConstraint0, ModeConstraintInfo),
+    lookup_pred_constraint(PredConstraintMap, PredId, ModeConstraint0, MCI),
     ( pred_info_infer_modes(PredInfo0) ->
         ( map.search(RequestedProcsMap0, PredId, RequestedProcs) ->
             list.foldl(
-                mode_ordering_infer_proc(ModeConstraint0,
-                    ModeConstraintInfo, !.ModuleInfo, PredConstraintMap),
+                mode_ordering_infer_proc(!.ModuleInfo, PredConstraintMap,
+                    PredId, MCI, ModeConstraint0),
                 RequestedProcs, PredInfo0, PredInfo)
         ;
             % XXX Maybe we should remove the predicate from the
@@ -100,249 +100,250 @@
     ;
         ProcIds = pred_info_non_imported_procids(PredInfo0),
         list.foldl(
-            mode_ordering_check_proc(ModeConstraint0,
-                ModeConstraintInfo, !.ModuleInfo, PredConstraintMap),
+            mode_ordering_check_proc(!.ModuleInfo, PredConstraintMap,
+                PredId, MCI, ModeConstraint0),
             ProcIds, PredInfo0, PredInfo)
     ),
     module_info_set_pred_info(PredId, PredInfo, !ModuleInfo).
 
-:- pred mode_ordering_infer_proc(mode_constraint::in,
-    mode_constraint_info::in, module_info::in, pred_constraint_map::in,
-    mode_constraint::in, pred_info::in, pred_info::out) is det.
-
-mode_ordering_infer_proc(Constraint0, ModeConstraintInfo, ModuleInfo,
-        PredConstraintMap, ModeDeclConstraint, !PredInfo) :-
-    pred_info_create_proc_info_for_mode_decl_constraint(
-        ModeDeclConstraint, ProcId, !PredInfo),
-    mode_ordering_check_proc(Constraint0, ModeConstraintInfo, ModuleInfo,
-        PredConstraintMap, ProcId, !PredInfo).
-
-:- pred mode_ordering_check_proc(mode_constraint::in,
-    mode_constraint_info::in, module_info::in, pred_constraint_map::in,
-    proc_id::in, pred_info::in, pred_info::out) is det.
+:- pred mode_ordering_infer_proc(module_info::in, pred_constraint_map::in,
+    pred_id::in, mode_constraint_info::in,
+    mode_constraint::in, mode_constraint::in,
+    pred_info::in, pred_info::out) is det.
+
+mode_ordering_infer_proc(ModuleInfo, PredConstraintMap, PredId, MCI,
+        Constraint0, ModeDeclConstraint, !PredInfo) :-
+    pred_info_create_proc_info_for_mode_decl_constraint(ModeDeclConstraint,
+        ProcId, !PredInfo),
+    mode_ordering_check_proc(ModuleInfo, PredConstraintMap, PredId, MCI,
+        Constraint0, ProcId, !PredInfo).
+
+:- pred mode_ordering_check_proc(module_info::in, pred_constraint_map::in,
+    pred_id::in, mode_constraint_info::in, mode_constraint::in, proc_id::in,
+    pred_info::in, pred_info::out) is det.
 
-mode_ordering_check_proc(Constraint0, ModeConstraintInfo, ModuleInfo,
-        PredConstraintMap, ProcId, !PredInfo) :-
+mode_ordering_check_proc(ModuleInfo, PredConstraintMap, PredId, MCI,
+        Constraint0, ProcId, !PredInfo) :-
     pred_info_proc_info(!.PredInfo, ProcId, ProcInfo0),
     proc_info_head_modes_constraint(ProcInfo0, ModeDeclConstraint),
     Constraint = Constraint0 * ModeDeclConstraint,
     pred_info_get_inst_graph_info(!.PredInfo, InstGraphInfo),
     InstGraph = InstGraphInfo ^ implementation_inst_graph,
-    mode_ordering_proc(InstGraph, Constraint, ModeConstraintInfo,
-        ModuleInfo, PredConstraintMap, ProcInfo0, ProcInfo),
+    mode_ordering_proc(ModuleInfo, PredConstraintMap, PredId, MCI, InstGraph,
+        Constraint, ProcInfo0, ProcInfo),
     pred_info_set_proc_info(ProcId, ProcInfo, !PredInfo).
 
-:- pred mode_ordering_proc(inst_graph::in, mode_constraint::in,
-    mode_constraint_info::in, module_info::in, pred_constraint_map::in,
-    proc_info::in, proc_info::out) is det.
-
     % Perform mode ordering for a procedure. The ModeConstraint must be
     % constrained to contain just the mode information for this procedure.
     %
-mode_ordering_proc(InstGraph, ModeConstraint, ModeConstraintInfo, ModuleInfo,
-        PredConstraintMap, !ProcInfo) :-
-    MOI = mode_ordering_info(InstGraph,
-        atomic_prodvars_map(ModeConstraint, ModeConstraintInfo),
-        stack.init, ModuleInfo, PredConstraintMap),
+:- pred mode_ordering_proc(module_info::in, pred_constraint_map::in,
+    pred_id::in, mode_constraint_info::in, inst_graph::in,
+    mode_constraint::in, proc_info::in, proc_info::out) is det.
+
+mode_ordering_proc(ModuleInfo, PredConstraintMap, PredId, MCI, InstGraph,
+        ModeConstraint, !ProcInfo) :-
+    ProdVarsMap = atomic_prodvars_map(ModeConstraint, MCI),
+    LambdaNesting0 = stack.init,
+    get_forward_goal_path_map_for_pred(MCI, PredId, ForwardGoalPathMap),
+    MOI0 = mode_ordering_info(InstGraph, ProdVarsMap, LambdaNesting0,
+        ModuleInfo, PredConstraintMap, ForwardGoalPathMap),
+
     proc_info_get_goal(!.ProcInfo, Goal0),
-    mode_order_goal(Goal0, Goal, MOI, _MOI),
+    mode_order_goal(Goal0, Goal, MOI0, _MOI),
     proc_info_set_goal(Goal, !ProcInfo).
 
 :- type mode_ordering_info
     --->    mode_ordering_info(
-                inst_graph          :: inst_graph,
-                prodvars_map        :: prodvars_map,
-                lambda_nesting      :: lambda_path,
-                module_info         :: module_info,
-                pred_constraint_map :: pred_constraint_map
+                moi_inst_graph          :: inst_graph,
+                moi_prodvars_map        :: prodvars_map,
+                moi_lambda_nesting      :: lambda_path,
+                moi_module_info         :: module_info,
+                moi_pred_constraint_map :: pred_constraint_map,
+                moi_goal_path_map       :: goal_forward_path_map
             ).
 
-:- pred enter_lambda_goal(goal_path::in,
+:- pred enter_lambda_goal(goal_id::in,
     mode_ordering_info::in, mode_ordering_info::out) is det.
 
-enter_lambda_goal(GoalPath, !MOI) :-
-    LambdaNesting0 = !.MOI ^ lambda_nesting,
-    !:MOI = !.MOI ^ lambda_nesting := stack.push(LambdaNesting0, GoalPath).
+enter_lambda_goal(GoalId, !MOI) :-
+    LambdaNesting0 = !.MOI ^ moi_lambda_nesting,
+    !MOI ^ moi_lambda_nesting := stack.push(LambdaNesting0, GoalId).
 
 :- pred leave_lambda_goal(mode_ordering_info::in, mode_ordering_info::out)
     is det.
 
 leave_lambda_goal(!MOI) :-
-    LambdaNesting0 = !.MOI ^ lambda_nesting,
+    LambdaNesting0 = !.MOI ^ moi_lambda_nesting,
     stack.pop_det(LambdaNesting0, _, LambdaNesting),
-    !:MOI = !.MOI ^ lambda_nesting := LambdaNesting.
+    !MOI ^ moi_lambda_nesting := LambdaNesting.
 
 :- pred mode_order_goal(hlds_goal::in, hlds_goal::out,
     mode_ordering_info::in, mode_ordering_info::out) is det.
 
-mode_order_goal(hlds_goal(GoalExpr0, GoalInfo0),
-        hlds_goal(GoalExpr, GoalInfo), !MOI) :-
-    mode_order_goal_2(GoalExpr0, GoalExpr, GoalInfo0, GoalInfo, !MOI).
+mode_order_goal(Goal0, Goal, !MOI) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
+    mode_order_goal_2(GoalExpr0, GoalExpr, GoalInfo0, GoalInfo, !MOI),
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
 :- pred mode_order_goal_2(hlds_goal_expr::in, hlds_goal_expr::out,
     hlds_goal_info::in, hlds_goal_info::out,
     mode_ordering_info::in, mode_ordering_info::out) is det.
 
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    Goal0 = conj(ConjType, Goals0),
-    Goal = conj(ConjType, Goals),
+mode_order_goal_2(GoalExpr0, GoalExpr, !GoalInfo, !MOI) :-
     (
-        ConjType = plain_conj,
-        list.map_foldl(mode_order_goal, Goals0, Goals1, !MOI),
-        mode_order_conj(Goals1, Goals),
-        union_mode_vars_sets(Goals, !GoalInfo),
-        ConsVars = !.GoalInfo ^ consuming_vars,
-        !:GoalInfo = !.GoalInfo ^ consuming_vars :=
-            ConsVars `difference` !.GoalInfo ^ producing_vars,
-        NeedVars = !.GoalInfo ^ need_visible_vars,
-        !:GoalInfo = !.GoalInfo ^ need_visible_vars :=
-            NeedVars `difference` !.GoalInfo ^ make_visible_vars
-    ;
-        ConjType = parallel_conj,
-        list.map_foldl(mode_order_goal, Goals0, Goals, !MOI),
-        union_mode_vars_sets(Goals, !GoalInfo)
-    ).
-
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    Goal0 = plain_call(PredId, _, Args, _, _, _),
-    Goal = Goal0 ^ call_proc_id := ProcId,
-    set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI),
-    MakeVisibleVars = list_to_set(Args) `intersect` ProdVars,
-
-    find_matching_proc(PredId, Args, ProdVars, ProcId, ConsumingVars, !MOI),
-    NeedVisibleVars = list_to_set(Args) `intersect` ConsumingVars,
-
-    goal_info_set_consuming_vars(ConsumingVars, !GoalInfo),
-    goal_info_set_make_visible_vars(MakeVisibleVars, !GoalInfo),
-    goal_info_set_need_visible_vars(NeedVisibleVars, !GoalInfo).
-
-mode_order_goal_2(Goal0, _, !GoalInfo, !MOI) :-
-    Goal0 = generic_call(_GenericCall0, _Args, _Modes0, _Det),
-    unexpected(this_file, "mode_order_goal_2: generic_call NYI").
-
-mode_order_goal_2(Goal0, _, !GoalInfo, !MOI) :-
-    Goal0 = switch(_Var, _CanFail0, _Cases0),
-    unexpected(this_file, "mode_order_goal_2: switch").
-
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    Goal0 = unify(VarA, RHS0, UnifyMode, Unification0, Context),
-    Goal = unify(VarA, RHS, UnifyMode, Unification, Context),
-    set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI),
-    InstGraph = !.MOI ^ inst_graph,
-    (
-        RHS0 = rhs_var(VarB),
-        RHS = RHS0,
-        ( ProdVars `contains` VarA ->
-            Unification = assign(VarA, VarB),
-            MakeVisibleVars = make_singleton_set(VarA),
-            NeedVisibleVars = make_singleton_set(VarB)
-        ; ProdVars `contains` VarB ->
-            Unification = assign(VarB, VarA),
-            MakeVisibleVars = make_singleton_set(VarB),
-            NeedVisibleVars = make_singleton_set(VarA)
+        GoalExpr0 = conj(ConjType, Goals0),
+        (
+            ConjType = plain_conj,
+            list.map_foldl(mode_order_goal, Goals0, Goals1, !MOI),
+            ForwardGoalPathMap = !.MOI ^ moi_goal_path_map,
+            mode_order_conj(ForwardGoalPathMap, Goals1, Goals),
+            union_mode_vars_sets(Goals, !GoalInfo),
+            ConsVars = !.GoalInfo ^ consuming_vars,
+            !GoalInfo ^ consuming_vars :=
+                ConsVars `difference` !.GoalInfo ^ producing_vars,
+            NeedVars = !.GoalInfo ^ need_visible_vars,
+            !GoalInfo ^ need_visible_vars :=
+                NeedVars `difference` !.GoalInfo ^ make_visible_vars
         ;
-            Unification = simple_test(VarA, VarB),
-            % XXX may be complicated unify -- need to check.
-            MakeVisibleVars = set.init,
-            NeedVisibleVars = list_to_set([VarA, VarB])
+            ConjType = parallel_conj,
+            list.map_foldl(mode_order_goal, Goals0, Goals, !MOI),
+            union_mode_vars_sets(Goals, !GoalInfo)
         ),
-        ConsumingVars = solutions.solutions_set((pred(Var::out) is nondet :-
-            inst_graph.same_graph_corresponding_nodes(InstGraph,
-                VarA, VarB, VarC, VarD),
-            ( ProdVars `contains` VarC ->
-                Var = VarD
-            ; ProdVars `contains` VarD ->
-                Var = VarC
-            ;
-                fail
-            )))
+        GoalExpr = conj(ConjType, Goals)
     ;
-        RHS0 = rhs_functor(_ConsId, _IsExistConstruct, ArgVars),
-        RHS = RHS0,
-        ( ProdVars `contains` VarA ->
-            % Unification = construct(VarA, ConsId, ArgVars,
-            %   _UniModes, _HowTo, _CellUniq, _MaybeRLExprId),
-            Unification = Unification0, % XXX
-            ConsumingVars = set.init,
-            MakeVisibleVars = list_to_set([VarA | ArgVars]),
-            NeedVisibleVars = set.init
+        GoalExpr0 = plain_call(PredId, _, Args, _, _, _),
+        set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI),
+        MakeVisibleVars = list_to_set(Args) `intersect` ProdVars,
+
+        find_matching_proc(PredId, Args, ProdVars, ProcId, ConsumingVars,
+            !MOI),
+        NeedVisibleVars = list_to_set(Args) `intersect` ConsumingVars,
+
+        goal_info_set_consuming_vars(ConsumingVars, !GoalInfo),
+        goal_info_set_make_visible_vars(MakeVisibleVars, !GoalInfo),
+        goal_info_set_need_visible_vars(NeedVisibleVars, !GoalInfo),
+        GoalExpr = GoalExpr0 ^ call_proc_id := ProcId
+    ;
+        GoalExpr0 = generic_call(_GenericCall0, _Args, _Modes0, _Det),
+        unexpected(this_file, "mode_order_goal_2: generic_call NYI")
+    ;
+        GoalExpr0 = switch(_Var, _CanFail0, _Cases0),
+        unexpected(this_file, "mode_order_goal_2: switch")
+    ;
+        GoalExpr0 = unify(VarA, RHS0, UnifyMode, Unification0, Context),
+        set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI),
+        InstGraph = !.MOI ^ moi_inst_graph,
+        (
+            RHS0 = rhs_var(VarB),
+            RHS = RHS0,
+            ( ProdVars `contains` VarA ->
+                Unification = assign(VarA, VarB),
+                MakeVisibleVars = make_singleton_set(VarA),
+                NeedVisibleVars = make_singleton_set(VarB)
+            ; ProdVars `contains` VarB ->
+                Unification = assign(VarB, VarA),
+                MakeVisibleVars = make_singleton_set(VarB),
+                NeedVisibleVars = make_singleton_set(VarA)
+            ;
+                Unification = simple_test(VarA, VarB),
+                % XXX may be complicated unify -- need to check.
+                MakeVisibleVars = set.init,
+                NeedVisibleVars = list_to_set([VarA, VarB])
+            ),
+            ConsumingVars = solutions.solutions_set((pred(Var::out) is nondet :-
+                inst_graph.same_graph_corresponding_nodes(InstGraph,
+                    VarA, VarB, VarC, VarD),
+                ( ProdVars `contains` VarC ->
+                    Var = VarD
+                ; ProdVars `contains` VarD ->
+                    Var = VarC
+                ;
+                    fail
+                )))
+        ;
+            RHS0 = rhs_functor(_ConsId, _IsExistConstruct, ArgVars),
+            RHS = RHS0,
+            ( ProdVars `contains` VarA ->
+                % Unification = construct(VarA, ConsId, ArgVars,
+                %   _UniModes, _HowTo, _CellUniq, _MaybeRLExprId),
+                Unification = Unification0, % XXX
+                ConsumingVars = set.init,
+                MakeVisibleVars = list_to_set([VarA | ArgVars]),
+                NeedVisibleVars = set.init
+            ;
+                % Unification = deconstruct(VarA, ConsId, ArgVars,
+                %   _UniModes, _CanFail, _CanCGC),
+                Unification = Unification0, % XXX
+                ConsumingVars = make_singleton_set(VarA),
+                MakeVisibleVars = list_to_set(ArgVars),
+                NeedVisibleVars = make_singleton_set(VarA)
+            )
         ;
-            % Unification = deconstruct(VarA, ConsId, ArgVars,
-            %   _UniModes, _CanFail, _CanCGC),
+            % Unification = construct(VarA, _ConsId, _ArgVars,
+            %   _UniModes, _HowTo, _CellUniq, _MaybeRLExprId),
             Unification = Unification0, % XXX
-            ConsumingVars = make_singleton_set(VarA),
-            MakeVisibleVars = list_to_set(ArgVars),
-            NeedVisibleVars = make_singleton_set(VarA)
-        )
-    ;
-        % Unification = construct(VarA, _ConsId, _ArgVars,
-        %   _UniModes, _HowTo, _CellUniq, _MaybeRLExprId),
-        Unification = Unification0, % XXX
-        RHS0 = rhs_lambda_goal(A, B, C, D, NonLocals, LambdaVars, Modes0,
-            H, SubGoal0),
-        Modes = Modes0, % XXX
-        RHS = rhs_lambda_goal(A, B, C, D, NonLocals, LambdaVars, Modes,
-            H, SubGoal),
+            RHS0 = rhs_lambda_goal(A, B, C, D, NonLocals, LambdaVars, Modes0,
+                H, SubGoal0),
+            Modes = Modes0, % XXX
+            RHS = rhs_lambda_goal(A, B, C, D, NonLocals, LambdaVars, Modes,
+                H, SubGoal),
+
+            GoalId = goal_info_get_goal_id(!.GoalInfo),
+            enter_lambda_goal(GoalId, !MOI),
+            mode_order_goal(SubGoal0, SubGoal, !MOI),
+            leave_lambda_goal(!MOI),
 
-        GoalPath = goal_info_get_goal_path(!.GoalInfo),
-        enter_lambda_goal(GoalPath, !MOI),
+            ConsumingVars = solutions.solutions_set(
+                inst_graph.reachable_from_list(InstGraph, NonLocals)),
+            MakeVisibleVars = make_singleton_set(VarA),
+            NeedVisibleVars = list_to_set(NonLocals)
+        ),
+        goal_info_set_consuming_vars(ConsumingVars, !GoalInfo),
+        goal_info_set_make_visible_vars(MakeVisibleVars, !GoalInfo),
+        goal_info_set_need_visible_vars(NeedVisibleVars, !GoalInfo),
+
+        GoalExpr = unify(VarA, RHS, UnifyMode, Unification, Context)
+    ;
+        GoalExpr0 = disj(Goals0),
+        list.map_foldl(mode_order_goal, Goals0, Goals, !MOI),
+        mode_order_disj(Goals, !GoalInfo),
+        GoalExpr = disj(Goals)
+    ;
+        GoalExpr0 = negation(SubGoal0),
         mode_order_goal(SubGoal0, SubGoal, !MOI),
-        leave_lambda_goal(!MOI),
+        goal_info_copy_mode_var_sets(SubGoal ^ hlds_goal_info, !GoalInfo),
+        GoalExpr = negation(SubGoal)
+    ;
+        % XXX We should special-case the handling of from_ground_term_construct
+        % scopes.
+        GoalExpr0 = scope(Reason, SubGoal0),
+        mode_order_goal(SubGoal0, SubGoal, !MOI),
+        goal_info_copy_mode_var_sets(SubGoal ^ hlds_goal_info, !GoalInfo),
+        GoalExpr = scope(Reason, SubGoal)
+    ;
+        GoalExpr0 = if_then_else(Locals, Cond0, Then0, Else0),
+        mode_order_goal(Cond0, Cond, !MOI),
+        mode_order_goal(Then0, Then, !MOI),
+        mode_order_goal(Else0, Else, !MOI),
+        % XXX Ned to make sure that Cond can be scheduled before Then and Else.
 
-        ConsumingVars = solutions.solutions_set(
-            inst_graph.reachable_from_list(InstGraph, NonLocals)),
-        MakeVisibleVars = make_singleton_set(VarA),
-        NeedVisibleVars = list_to_set(NonLocals)
-    ),
-    goal_info_set_consuming_vars(ConsumingVars, !GoalInfo),
-    goal_info_set_make_visible_vars(MakeVisibleVars, !GoalInfo),
-    goal_info_set_need_visible_vars(NeedVisibleVars, !GoalInfo).
-
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    Goal0 = disj(Goals0),
-    Goal = disj(Goals),
-    list.map_foldl(mode_order_goal, Goals0, Goals, !MOI),
-    mode_order_disj(Goals, !GoalInfo).
-
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    Goal0 = negation(SubGoal0),
-    Goal = negation(SubGoal),
-    mode_order_goal(SubGoal0, SubGoal, !MOI),
-    goal_info_copy_mode_var_sets(SubGoal ^ hlds_goal_info, !GoalInfo).
-
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    % XXX We should special-case the handling of from_ground_term_construct
-    % scopes.
-    Goal0 = scope(Reason, SubGoal0),
-    Goal = scope(Reason, SubGoal),
-    mode_order_goal(SubGoal0, SubGoal, !MOI),
-    goal_info_copy_mode_var_sets(SubGoal ^ hlds_goal_info, !GoalInfo).
-
-mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
-    Goal0 = if_then_else(Locals, Cond0, Then0, Else0),
-    Goal = if_then_else(Locals, Cond, Then, Else),
-    mode_order_goal(Cond0, Cond, !MOI),
-    mode_order_goal(Then0, Then, !MOI),
-    mode_order_goal(Else0, Else, !MOI),
-    % XXX Ned to make sure that Cond can be scheduled before Then and Else.
-
-    union_mode_vars_sets([Cond, Then], !GoalInfo),
-    ConsVars = !.GoalInfo ^ consuming_vars,
-    !:GoalInfo = !.GoalInfo ^ consuming_vars :=
-        ConsVars `difference` !.GoalInfo ^ producing_vars,
-    NeedVars = !.GoalInfo ^ need_visible_vars,
-    !:GoalInfo = !.GoalInfo ^ need_visible_vars :=
-        NeedVars `difference` !.GoalInfo ^ make_visible_vars,
-
-    combine_mode_vars_sets(Else ^ hlds_goal_info, !GoalInfo).
-
-mode_order_goal_2(Goal0, _, !GoalInfo, !MOI) :-
-    Goal0 = call_foreign_proc(_, _, _, _, _, _, _),
-    unexpected(this_file, "mode_order_goal_2: pragma_foreign_code NYI").
-
-mode_order_goal_2(Goal0, _, !GoalInfo, !MOI) :-
-    Goal0 = shorthand(_),
-    unexpected(this_file, "mode_order_goal_2: shorthand").
+        union_mode_vars_sets([Cond, Then], !GoalInfo),
+        ConsVars = !.GoalInfo ^ consuming_vars,
+        !GoalInfo ^ consuming_vars :=
+            ConsVars `difference` !.GoalInfo ^ producing_vars,
+        NeedVars = !.GoalInfo ^ need_visible_vars,
+        !GoalInfo ^ need_visible_vars :=
+            NeedVars `difference` !.GoalInfo ^ make_visible_vars,
+
+        combine_mode_vars_sets(Else ^ hlds_goal_info, !GoalInfo),
+        GoalExpr = if_then_else(Locals, Cond, Then, Else)
+    ;
+        GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _),
+        unexpected(this_file, "mode_order_goal_2: pragma_foreign_code NYI")
+    ;
+        GoalExpr0 = shorthand(_),
+        unexpected(this_file, "mode_order_goal_2: shorthand")
+    ).
 % mode_order_goal_2(Goal0, Goal, !GoalInfo, !MOI) :-
 %     Goal0 = atomic_goal(GoalType, Outer, Inner, Vars, MainGoal0,
 %         OrElseGoals0),
@@ -374,13 +375,13 @@
     MakeVisibleVars0 = !.GoalInfo ^ make_visible_vars,
     NeedVisibleVars0 = !.GoalInfo ^ need_visible_vars,
 
-    !:GoalInfo = !.GoalInfo ^ producing_vars
+    !GoalInfo ^ producing_vars
         := ProdVars0 `intersect` GI ^ producing_vars,
-    !:GoalInfo = !.GoalInfo ^ consuming_vars
+    !GoalInfo ^ consuming_vars
         := ConsumVars0 `union` GI ^ consuming_vars,
-    !:GoalInfo = !.GoalInfo ^ make_visible_vars
+    !GoalInfo ^ make_visible_vars
         := MakeVisibleVars0 `intersect` GI ^ make_visible_vars,
-    !:GoalInfo = !.GoalInfo ^ need_visible_vars
+    !GoalInfo ^ need_visible_vars
         := NeedVisibleVars0 `union` GI ^ need_visible_vars.
 
 :- pred union_mode_vars_sets(hlds_goals::in,
@@ -399,32 +400,35 @@
     NeedVisibleVars0 = !.GoalInfo ^ need_visible_vars,
     Goal = hlds_goal(_, GI),
 
-    !:GoalInfo = !.GoalInfo ^ producing_vars
+    !GoalInfo ^ producing_vars
         := ProdVars0 `union` GI ^ producing_vars,
-    !:GoalInfo = !.GoalInfo ^ consuming_vars
+    !GoalInfo ^ consuming_vars
         := ConsumVars0 `union` GI ^ consuming_vars,
-    !:GoalInfo = !.GoalInfo ^ make_visible_vars
+    !GoalInfo ^ make_visible_vars
         := MakeVisibleVars0 `union` GI ^ make_visible_vars,
-    !:GoalInfo = !.GoalInfo ^ need_visible_vars
+    !GoalInfo ^ need_visible_vars
         := NeedVisibleVars0 `union` GI ^ need_visible_vars.
 
 :- pred goal_info_copy_mode_var_sets(hlds_goal_info::in,
     hlds_goal_info::in, hlds_goal_info::out) is det.
 
 goal_info_copy_mode_var_sets(GI, !GoalInfo) :-
-    !:GoalInfo = !.GoalInfo ^ producing_vars := GI ^ producing_vars,
-    !:GoalInfo = !.GoalInfo ^ consuming_vars := GI ^ consuming_vars,
-    !:GoalInfo = !.GoalInfo ^ make_visible_vars := GI ^ make_visible_vars,
-    !:GoalInfo = !.GoalInfo ^ need_visible_vars := GI ^ need_visible_vars.
+    !GoalInfo ^ producing_vars := GI ^ producing_vars,
+    !GoalInfo ^ consuming_vars := GI ^ consuming_vars,
+    !GoalInfo ^ make_visible_vars := GI ^ make_visible_vars,
+    !GoalInfo ^ need_visible_vars := GI ^ need_visible_vars.
 
-:- pred mode_order_conj(hlds_goals::in, hlds_goals::out) is det.
+:- pred mode_order_conj(goal_forward_path_map::in,
+    hlds_goals::in, hlds_goals::out) is det.
 
-mode_order_conj(Goals0, Goals) :-
+mode_order_conj(ForwardGoalPathMap, Goals0, Goals) :-
     GoalMap = list.foldl((func(G, GM) = map.det_insert(GM, Index, G) :-
+        G = hlds_goal(_, GI),
+        GoalId = goal_info_get_goal_id(GI),
+        map.lookup(ForwardGoalPathMap, GoalId, GoalPath),
+        GoalPath = fgp(GoalSteps),
         (
-            G = hlds_goal(_, GI),
-            GoalPath = goal_info_get_goal_path(GI),
-            LastStep = goal_path_get_last(GoalPath),
+            list.last(GoalSteps, LastStep),
             LastStep = step_conj(Index0)
         ->
             Index = Index0
@@ -441,7 +445,7 @@
     MakeVisMap =
         map.foldl((func(I, G, MVM0) =
             list.foldl((func(V, MVM1) = map.set(MVM1, V, I)),
-                            % XXX disjunction required!
+            % XXX disjunction required!
             set.to_sorted_list(G ^ hlds_goal_info ^ make_visible_vars), MVM0)
         ), GoalMap, map.init),
 
@@ -478,11 +482,11 @@
     mode_ordering_info::in, mode_ordering_info::out) is det.
 
 set_atomic_prod_vars(ProdVars, !GoalInfo, !MOI) :-
-    LambdaNesting = !.MOI ^ lambda_nesting,
-    AtomicProdVars = !.MOI ^ prodvars_map,
-    GoalPath = goal_info_get_goal_path(!.GoalInfo),
+    LambdaNesting = !.MOI ^ moi_lambda_nesting,
+    AtomicProdVars = !.MOI ^ moi_prodvars_map,
+    GoalId = goal_info_get_goal_id(!.GoalInfo),
     (
-        map.search(AtomicProdVars, stack.push(LambdaNesting, GoalPath),
+        map.search(AtomicProdVars, stack.push(LambdaNesting, GoalId),
             ProdVars0)
     ->
         ProdVars = ProdVars0
@@ -510,9 +514,9 @@
     mode_ordering_info::in, mode_ordering_info::out) is det.
 
 find_matching_proc(PredId, Args, ProdVars, ProcId, ConsumingVars, !MOI) :-
-    ModuleInfo = !.MOI ^ module_info,
-    CallerInstGraph = !.MOI ^ inst_graph,
-    PredConstraintMap = !.MOI ^ pred_constraint_map,
+    ModuleInfo = !.MOI ^ moi_module_info,
+    CallerInstGraph = !.MOI ^ moi_inst_graph,
+    PredConstraintMap = !.MOI ^ moi_pred_constraint_map,
     lookup_pred_constraint(PredConstraintMap, PredId, _, MCInfo),
 
     module_info_pred_info(ModuleInfo, PredId, PredInfo),
@@ -587,8 +591,8 @@
 :- pred lookup_pred_constraint(pred_constraint_map::in, pred_id::in,
     mode_constraint::out, mode_constraint_info::out) is det.
 
-lookup_pred_constraint(PCM, PredId, MC, MCInfo) :-
-    map.lookup(PCM, PredId, pci(MC, MCInfo)).
+lookup_pred_constraint(PCM, PredId, MC, MCI) :-
+    map.lookup(PCM, PredId, pci(MC, MCI)).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/mode_robdd.equiv_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_robdd.equiv_vars.m,v
retrieving revision 1.7
diff -u -r1.7 mode_robdd.equiv_vars.m
--- compiler/mode_robdd.equiv_vars.m	1 Dec 2006 15:04:11 -0000	1.7
+++ compiler/mode_robdd.equiv_vars.m	20 Mar 2010 04:59:47 -0000
@@ -79,7 +79,7 @@
 
 %---------------------------------------------------------------------------%
 
-init_equiv_vars = equiv_vars(map__init).
+init_equiv_vars = equiv_vars(map.init).
 
 add_equality(VarA, VarB, EQVars0) = EQVars :-
 	( LeaderA = EQVars0 ^ leader(VarA) ->
@@ -172,7 +172,7 @@
 empty(equiv_vars(LM)) :- is_empty(LM).
 
 equiv_vars(MA) * equiv_vars(MB) = equiv_vars(M) :-
-	M1 = map__foldl(func(Var, LeaderA, M0) =
+	M1 = map.foldl(func(Var, LeaderA, M0) =
 		( LeaderB = M0 ^ elem(Var) ->
 			( compare(<, LeaderA, LeaderB) ->
 				M0 ^ elem(LeaderB) := LeaderA
@@ -190,7 +190,7 @@
 :- func normalise_leader_map(leader_map(T)) = leader_map(T).
 
 normalise_leader_map(Map) =
-	map__foldl(func(Var, Leader, M0) =
+	map.foldl(func(Var, Leader, M0) =
 		( Leader = Var ->
 			M0
 		; LeaderLeader = M0 ^ elem(Leader) ->
@@ -198,12 +198,12 @@
 		;
 			( M0 ^ elem(Var) := Leader ) ^ elem(Leader) := Leader
 		),
-		Map, map__init).
+		Map, map.init).
 
 EA + EB = E :-
-	VarsA = set__sorted_list_to_set(map__sorted_keys(EA ^ leader_map)),
-	VarsB = set__sorted_list_to_set(map__sorted_keys(EB ^ leader_map)),
-	Vars = set__to_sorted_list(VarsA `intersect` VarsB),
+	VarsA = set.sorted_list_to_set(map.sorted_keys(EA ^ leader_map)),
+	VarsB = set.sorted_list_to_set(map.sorted_keys(EB ^ leader_map)),
+	Vars = set.to_sorted_list(VarsA `intersect` VarsB),
 	disj_2(Vars, EA, EB, init_equiv_vars, E).
 
 :- pred disj_2(list(var(T))::in, equiv_vars(T)::in, equiv_vars(T)::in,
@@ -242,7 +242,7 @@
 % work for the purpose we use it for in 'mode_robdd:+' since it never removes
 % any equivalences which it shouldn't.
 EA `difference` EB = E :-
-	Vars = map__sorted_keys(EA ^ leader_map),
+	Vars = map.sorted_keys(EA ^ leader_map),
 	diff_2(Vars, EA, EB, init_equiv_vars, E).
 
 :- pred diff_2(list(var(T))::in, equiv_vars(T)::in, equiv_vars(T)::in,
@@ -280,10 +280,10 @@
 delete(E0, V) = E :-
 	( L = E0 ^ leader(V) ->
 		( L = V ->
-			M0 = map__delete(E0 ^ leader_map, V),
+			M0 = map.delete(E0 ^ leader_map, V),
 			Vars = solutions.solutions(map.inverse_search(M0, V)),
 			( Vars = [NewLeader | _] ->
-				M = list__foldl(
+				M = list.foldl(
 					func(V1, M1) =
 						M1 ^ elem(V1) := NewLeader,
 					Vars, M0),
@@ -292,23 +292,23 @@
 				error("mode_robdd:equiv_vars:delete: malformed leader map")
 			)
 		;
-			E = equiv_vars(map__delete(E0 ^ leader_map, V))
+			E = equiv_vars(map.delete(E0 ^ leader_map, V))
 		)
 	;
 		E = E0
 	).
 
 restrict_threshold(Th, E) = equiv_vars(normalise_leader_map(LM)) :-
-	LL0 = map__to_assoc_list(E ^ leader_map),
-	list__takewhile((pred((V - _)::in) is semidet :-
+	LL0 = map.to_assoc_list(E ^ leader_map),
+	list.takewhile((pred((V - _)::in) is semidet :-
 		\+ compare(>, V, Th)
 		), LL0, LL, _),
-	LM = map__from_assoc_list(LL).
+	LM = map.from_assoc_list(LL).
 
 % XXX not terribly efficient.
 filter(P, equiv_vars(LM0)) = equiv_vars(LM) :-
-	list__filter(P, map__keys(LM0), _, Vars),
-	LM = list__foldl(func(V, M) = delete(M, V), Vars, LM0).
+	list.filter(P, map.keys(LM0), _, Vars),
+	LM = list.foldl(func(V, M) = delete(M, V), Vars, LM0).
 
 normalise_known_equivalent_vars(Changed, Vars0, Vars, EQVars0, EQVars) :-
 	( ( empty(Vars0) ; empty(EQVars0) ) ->
@@ -352,7 +352,7 @@
 	).
 
 label(E, True0, True, False0, False) :-
-	map__foldl2(
+	map.foldl2(
 		(pred(V::in, L::in, T0::in, T::out, F0::in, F::out) is det :-
 			( T0 `contains` L ->
 				T = T0 `insert` V,
@@ -367,7 +367,7 @@
 		), E ^ leader_map, True0, True, False0, False).
 
 equivalent_vars_in_robdd(Robdd) = LeaderMap :-
-	some_vars(LeaderMap) = robdd__equivalent_vars(Robdd).
+	some_vars(LeaderMap) = robdd.equivalent_vars(Robdd).
 
 remove_equiv(EQVars, Robdd) =
 	( is_empty(EQVars ^ leader_map) ->
Index: compiler/mode_robdd.implications.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_robdd.implications.m,v
retrieving revision 1.7
diff -u -r1.7 mode_robdd.implications.m
--- compiler/mode_robdd.implications.m	1 Dec 2006 15:04:11 -0000	1.7
+++ compiler/mode_robdd.implications.m	20 Mar 2010 05:00:36 -0000
@@ -3,10 +3,10 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %---------------------------------------------------------------------------%
-% 
+%
 % File: mode_robdd.implications.m.
 % Main author: dmo.
-% 
+%
 %---------------------------------------------------------------------------%
 
 :- module mode_robdd.implications.
@@ -118,7 +118,7 @@
 :- mode filter_imp_map(pred(in) is semidet, in) = out is det.
 
 filter_imp_map(P, IM) =
-	map__foldl(func(V, Vs, M) =
+	map.foldl(func(V, Vs, M) =
 		( P(V) ->
 		    M ^ entry(V) := filter(P, Vs)
 		;
@@ -195,7 +195,7 @@
 
 normalise_true_false_imp_map(IsDisImp, Changed, TrueVars0, TrueVars,
 		FalseVars0, FalseVars, ImpMap0, ImpMap) :-
-	{TrueVars, FalseVars, ImpMap, Changed} = map__foldl(
+	{TrueVars, FalseVars, ImpMap, Changed} = map.foldl(
 	    ( func(V, Vs, {Ts0, Fs0, IMs0, C0}) = {Ts, Fs, IMs, C} :-
 		(
 		    ( IsDisImp = yes -> Fs0 ; Ts0 ) `contains` V
@@ -258,12 +258,11 @@
 			Intersect ^ sorted_keys ^ sorted_list_to_set
 	    ;
 		Extract = values,
-		Values = list__foldl(union, Intersect ^ values, init),
+		Values = list.foldl(union, Intersect ^ values, init),
 		FalseVars = FalseVars0 `union` Values
 	    )
 	).
 
-
 %------------------------------------------------------------------------%
 
 propagate_equivalences_into_implications(EQVars, Changed, ImpVars0, ImpVars) :-
@@ -278,13 +277,13 @@
 	    RevImps0, RevImps),
 
 	ImpVars = imp_vars(Imps, RevImps, DisImps, RevDisImps),
-	Changed = Changed0 `bool__or` Changed1.
+	Changed = Changed0 `bool.or` Changed1.
 
 :- pred propagate_equivalences_into_implications_2(equiv_vars(T)::in,
 	bool::out, imp_map(T)::in, imp_map(T)::out) is det.
 
 propagate_equivalences_into_implications_2(EQVars, Changed, ImpMap0, ImpMap) :-
-	{ImpMap, Changed} = map__foldl((func(V, Vs0, {IM, C}) =
+	{ImpMap, Changed} = map.foldl((func(V, Vs0, {IM, C}) =
 		{ IM ^ entry(V) := Vs, ( Vs = Vs0 -> C ; yes ) } :-
 		Vs = filter(vars_are_not_equivalent(EQVars, V), Vs0)
 	    ), ImpMap0, {init, no}).
@@ -345,7 +344,7 @@
 
 	% XXX
 	% P = (pred(V::in, di, uo) is det -->
-	%	io__write_int(var_to_int(V))), % XXX
+	%	io.write_int(var_to_int(V))), % XXX
 	% impure unsafe_perform_io(robdd_to_dot(Robdd0, P,
 	%	"extract_impl_before.dot")), % XXX
 
@@ -359,7 +358,7 @@
 %------------------------------------------------------------------------%
 
 add_equalities_to_imp_vars(EQVars, ImpVars) =
-	map__foldl(func(VA, VB, IVs) =
+	map.foldl(func(VA, VB, IVs) =
 		IVs ^ imp_vars(VA, VB) ^ imp_vars(VB, VA),
 	    EQVars ^ leader_map, ImpVars).
 
@@ -451,7 +450,7 @@
 	( is_empty(IMA) ->
 	    IMA
 	;
-	    map__foldl(func(V, VsB, M) =
+	    map.foldl(func(V, VsB, M) =
 		    ( VsA = M ^ elem(V) ->
 			M ^ entry(V) := VsA `difference` VsB
 		    ;
@@ -463,7 +462,7 @@
 :- func remove_empty_sets(imp_map(T)) = imp_map(T).
 
 remove_empty_sets(IM) =
-	map__foldl(func(V, Vs, M) =
+	map.foldl(func(V, Vs, M) =
 		( empty(Vs) ->
 		    M `delete` V
 		;
@@ -474,7 +473,7 @@
 :- func delete_var_from_imp_map(var(T), imp_map(T)) = imp_map(T).
 
 delete_var_from_imp_map(Var, IM0) =
-	map__foldl(func(V, Vs, M) =
+	map.foldl(func(V, Vs, M) =
 		( Vs `contains` Var ->
 		    M ^ entry(V) := Vs `delete` Var
 		;
@@ -498,7 +497,7 @@
 :- func add_backwards_to_imp_map(imp_map(T), imp_map(T)) = imp_map(T).
 
 add_backwards_to_imp_map(IM, RIM) =
-	map__foldl(func(VA, Vs, M0) =
+	map.foldl(func(VA, Vs, M0) =
 		foldl(func(VB, M1) =
 			M1 ^ new_relation(VB) := VA,
 		    Vs, M0),
@@ -562,7 +561,7 @@
 
 get_resolvents_2(LitA, LitB, ImpVars) = Clauses :-
 	Literals = get_literals(LitA, ImpVars),
-	Clauses = list__map(func(NewLit) = {NewLit, LitB}, Literals).
+	Clauses = list.map(func(NewLit) = {NewLit, LitB}, Literals).
 
 :- func get_literals(literal(T), imp_vars(T)) = list(literal(T)).
 
@@ -583,7 +582,7 @@
 		imp_vars(T).
 
 add_imp_map_clauses(MkLitA, MkLitB, IM, ImpVars) =
-	map__foldl(func(VarA, Vars, IVs0) =
+	map.foldl(func(VarA, Vars, IVs0) =
 		foldl(func(VarB, IVs1) =
 			add_clause({MkLitA(VarA), MkLitB(VarB)}, IVs1),
 		    Vars, IVs0),
Index: compiler/mode_robdd.tfr.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_robdd.tfr.m,v
retrieving revision 1.3
diff -u -r1.3 mode_robdd.tfr.m
--- compiler/mode_robdd.tfr.m	31 Jul 2006 08:31:56 -0000	1.3
+++ compiler/mode_robdd.tfr.m	20 Mar 2010 05:01:17 -0000
@@ -3,14 +3,14 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %---------------------------------------------------------------------------%
-% 
+%
 % File: mode_robdd.tfr.m.
 % Main author: dmo
 % Stability: low
-% 
+%
 %-----------------------------------------------------------------------------%
 
-:- module mode_robdd__tfr.
+:- module mode_robdd.tfr.
 
 :- interface.
 
Index: compiler/ordering_mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ordering_mode_constraints.m,v
retrieving revision 1.26
diff -u -r1.26 ordering_mode_constraints.m
--- compiler/ordering_mode_constraints.m	15 Dec 2010 06:29:54 -0000	1.26
+++ compiler/ordering_mode_constraints.m	15 Dec 2010 06:33:22 -0000
@@ -21,6 +21,7 @@
 :- import_module check_hlds.build_mode_constraints.
 :- import_module check_hlds.prop_mode_constraints.
 :- import_module hlds.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_pred.
 :- import_module hlds.hlds_module.
 
@@ -46,14 +47,16 @@
 
     % Store for the ordering constraints for one conjunction.
     %
-:- type ordering_constraints_info --->
-    ordering_constraints_info(
-        num_conjuncts       :: int,
-                            % The number of conjucts in this conjunction
+:- type ordering_constraints_info
+    --->    ordering_constraints_info(
+                oci_containing_map      :: containing_goal_map,
 
-        constraints         :: set(mode_ordering_constraint)
-                            % Constraints on the conjuncts.
-    ).
+                % The number of conjucts in this conjunction
+                oci_num_conjuncts       :: int,
+
+                % Constraints on the conjuncts.
+                oci_constraints         :: set(mode_ordering_constraint)
+            ).
 
 %-----------------------------------------------------------------------------%
 
@@ -76,15 +79,15 @@
 
 %-----------------------------------------------------------------------------%
 
-    % ordering_init(N) creates a new ordering constraint system for
-    % a conjunction with N conjuncts.
-    %
-:- func ordering_init(int) = ordering_constraints_info.
-
     % add_ordering_constraint(Constraint, !OCI) adds Constraint
     % to the ordering constraints store. It fails if it immediately
     % detects a contradiction (at the moment, this means it has
-    % detected a loop in the producer/consumer dependency graph).
+    % detected a loop in the producer consumer dependency graph,
+    % such as in the conjunction:
+    % (p(A, B), p(B, C), p(C, A)) where p is pred(in, out)).
+    %
+    % NOTE: behaviour when constrained conjuncts are outside the
+    % possible range is undefined.
     %
 :- pred add_ordering_constraint(mode_ordering_constraint::in,
     ordering_constraints_info::in, ordering_constraints_info::out) is semidet.
@@ -219,8 +222,8 @@
     module_info_pred_info(!.ModuleInfo, PredId, PredInfo0),
 
     ( pred_info_infer_modes(PredInfo0) ->
-        % XXX GIVE UP FOR NOW!!!! In reality, execution shouldn't
-        % reach here if the pred is to be mode inferred, should it?
+        % XXX GIVE UP FOR NOW!!!! In reality, execution shouldn't reach here
+        % if the pred is to be mode inferred, should it?
         sorry(this_file, "mode inference constraints")
     ;
         % XXX Maybe move this outside of this predicate - then
@@ -230,10 +233,13 @@
 
         module_info_pred_info(!.ModuleInfo, PredId, PredInfo1),
 
-        PredConstraints = map.lookup(PredConstraintsMap, PredId),
+        map.lookup(PredConstraintsMap, PredId,
+            {ContainingGoalMap, PredConstraints}),
         ProcIds = pred_info_all_procids(PredInfo1),
-        list.foldl2(proc_reordering(PredConstraints, VarMap, PredId), ProcIds,
-            [], Errors, PredInfo1, PredInfo),
+        list.foldl2(
+            proc_reordering(ContainingGoalMap, PredConstraints, VarMap,
+                PredId),
+            ProcIds, [], Errors, PredInfo1, PredInfo),
 
         (
             Errors = [],
@@ -253,11 +259,13 @@
     % to the producer consumer constraints in PredConstraints. The procedure
     % with the modified body goal replaces its original in PredInfo.
     %
-:- pred proc_reordering(pred_p_c_constraints::in, mc_var_map::in, pred_id::in,
-    proc_id::in, mode_analysis_failures::in, mode_analysis_failures::out,
+:- pred proc_reordering(containing_goal_map::in, pred_p_c_constraints::in,
+    mc_var_map::in, pred_id::in, proc_id::in,
+    mode_analysis_failures::in, mode_analysis_failures::out,
     pred_info::in, pred_info::out) is det.
 
-proc_reordering(PredConstraints, VarMap, PredId, ProcId, !Errors, !PredInfo) :-
+proc_reordering(ContainingGoalMap, PredConstraints, VarMap, PredId, ProcId,
+        !Errors, !PredInfo) :-
     pred_info_proc_info(!.PredInfo, ProcId, ProcInfo0),
     proc_info_get_goal(ProcInfo0, Goal0),
 
@@ -275,8 +283,8 @@
     % variables.
     Errors0 = !.Errors,
     promise_equivalent_solutions [Errors1, Goal] (
-        solve_proc_reordering(VarMap, PredId, ProcId, SolverConstraints,
-            Errors0, Errors1, Goal0, Goal)
+        solve_proc_reordering(ContainingGoalMap, VarMap, PredId, ProcId,
+            SolverConstraints, Errors0, Errors1, Goal0, Goal)
     ),
     !:Errors = Errors1,
 
@@ -299,15 +307,16 @@
     % solution to the producing and consuming goals of program
     % variables.
     %
-:- pred solve_proc_reordering(mc_var_map::in, pred_id::in, proc_id::in,
-    solver_cstrts::in, mode_analysis_failures::in, mode_analysis_failures::out,
+:- pred solve_proc_reordering(containing_goal_map::in, mc_var_map::in,
+    pred_id::in, proc_id::in, solver_cstrts::in,
+    mode_analysis_failures::in, mode_analysis_failures::out,
     hlds_goal::in, hlds_goal::out) is cc_multi.
 
-solve_proc_reordering(VarMap, PredId, ProcId, SolverConstraints,
-        !Errors, !Goal) :-
+solve_proc_reordering(ContainingGoalMap, VarMap, PredId, ProcId,
+        SolverConstraints, !Errors, !Goal) :-
     (
         mcsolver.solve(SolverConstraints, Bindings),
-        goal_reordering(PredId, VarMap, Bindings, !Goal)
+        goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings, !Goal)
     ->
         true
     ;
@@ -320,33 +329,20 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Conjunction reordering
+% Conjunction reordering.
 %
 
-    % goal_reordering(PredId, VarMap, Bindings, !Goal) applies mode
-    % reordering to conjunctions in Goal (from predicate PredId) and its
-    % children. VarMap should contain all producer/consumer constraint
-    % variables relevant to said conjunctions, and Bindings should
-    % contain bindings for them.
-    %
-:- pred goal_reordering(pred_id::in, mc_var_map::in, mc_bindings::in,
-    hlds_goal::in, hlds_goal::out) is semidet.
-
-goal_reordering(PredId, VarMap, Bindings, Goal0, Goal) :-
-    Goal0 = hlds_goal(GoalExpr0, GoalInfo),
-    goal_expr_reordering(PredId, VarMap, Bindings, GoalExpr0, GoalExpr),
-    Goal = hlds_goal(GoalExpr, GoalInfo).
-
-    % goal_expr_reordering(PredId, VarMap, Bindings, !GoalExpr) applies
-    % mode reordering to conjunctions in GoalExpr (from predicate
-    % PredId) and its children. VarMap should contain all
-    % producer/consumer constraint variables relevant to said
+    % goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings, !Goal)
+    % applies mode reordering to conjunctions in Goal (from predicate PredId,
+    % which has the given ContainingGoalMap) and its children. VarMap should
+    % contain all producer/consumer constraint variables relevant to said
     % conjunctions, and Bindings should contain bindings for them.
     %
-:- pred goal_expr_reordering(pred_id::in, mc_var_map::in, mc_bindings::in,
-    hlds_goal_expr::in, hlds_goal_expr::out) is semidet.
+:- pred goal_reordering(containing_goal_map::in, pred_id::in,
+    mc_var_map::in, mc_bindings::in, hlds_goal::in, hlds_goal::out) is semidet.
 
-goal_expr_reordering(PredId, VarMap, Bindings, GoalExpr0, GoalExpr) :-
+goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings, Goal0, Goal) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo),
     (
         ( GoalExpr0 = plain_call(_, _, _, _, _, _)
         ; GoalExpr0 = generic_call(_, _, _, _)
@@ -361,23 +357,29 @@
             ConjType = plain_conj,
             % Build constraints for this conjunction.
             make_conjuncts_nonlocal_repvars(PredId, Goals0, RepVarMap),
+            OCInfo0 = ordering_init(ContainingGoalMap, list.length(Goals0)),
             conjunct_ordering_constraints(VarMap, Bindings, RepVarMap,
-                ordering_init(list.length(Goals0)), OrderingConstraintsInfo),
+                OCInfo0, OCInfo),
 
             % Then solve the constraints and reorder.
-            minimum_reordering(OrderingConstraintsInfo, Order),
+            minimum_reordering(OCInfo, Order),
             list.map(list.index1_det(Goals0), Order, Goals1),
 
             % Then recurse on the reordered goals
-            list.map(goal_reordering(PredId, VarMap, Bindings), Goals1, Goals)
+            list.map(
+                goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings),
+                Goals1, Goals)
         ;
             ConjType = parallel_conj,
-            list.map(goal_reordering(PredId, VarMap, Bindings), Goals0, Goals)
+            list.map(
+                goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings),
+                Goals0, Goals)
         ),
         GoalExpr = conj(ConjType, Goals)
     ;
         GoalExpr0 = disj(Goals0),
-        list.map(goal_reordering(PredId, VarMap, Bindings), Goals0, Goals),
+        list.map(goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings),
+            Goals0, Goals),
         GoalExpr = disj(Goals)
     ;
         GoalExpr0 = switch(_, _, _),
@@ -385,48 +387,47 @@
         unexpected(this_file, "goal_expr_reordering: switch")
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
-        goal_reordering(PredId, VarMap, Bindings, Cond0, Cond),
-        goal_reordering(PredId, VarMap, Bindings, Then0, Then),
-        goal_reordering(PredId, VarMap, Bindings, Else0, Else),
+        goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings,
+            Cond0, Cond),
+        goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings,
+            Then0, Then),
+        goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings,
+            Else0, Else),
         GoalExpr = if_then_else(Vars, Cond, Then, Else)
     ;
         GoalExpr0 = negation(SubGoal0),
-        goal_reordering(PredId, VarMap, Bindings, SubGoal0, SubGoal),
+        goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings,
+            SubGoal0, SubGoal),
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
         % Is it possible to special-case the handling of
         % from_ground_term_construct scopes?
-        goal_reordering(PredId, VarMap, Bindings, SubGoal0, SubGoal),
+        goal_reordering(ContainingGoalMap, PredId, VarMap, Bindings,
+            SubGoal0, SubGoal),
         GoalExpr = scope(Reason, SubGoal)
     ;
         GoalExpr0 = shorthand(_),
         % XXX We need to handle atomic goals.
         % XXX We need to handle try goals.
         unexpected(this_file, "goal_expr_reordering: NYI: shorthand")
-    ).
+    ),
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
 %-----------------------------------------------------------------------------%
 
     % ordering_init(N) creates a new ordering constraint system for
     % a conjunction with N conjuncts.
     %
-ordering_init(N) = ordering_constraints_info(N, set.init).
+:- func ordering_init(containing_goal_map, int) = ordering_constraints_info.
+
+ordering_init(ContainingGoalMap, N) =
+    ordering_constraints_info(ContainingGoalMap, N, set.init).
 
 %-----------------------------------------------------------------------------%
 
-    % add_ordering_constraint(Constraint, OCI0, OCI) adds Constraint
-    % to the ordering constraints store. It fails if it immediately
-    % detects a contradiction (at the moment, this means it has
-    % detected a loop in the producer consumer dependency graph - eg
-    % the conjunction:
-    % (p(A, B), p(B, C), p(C, A)) where p is pred(in, out)).
-    %
-    % NOTE: behaviour when constrained conjuncts are outside the
-    % possible range is undefined.
-    %
 add_ordering_constraint(Constraint, !OCI) :-
-    ( set.member(Constraint, !.OCI ^ constraints) ->
+    ( set.member(Constraint, !.OCI ^ oci_constraints) ->
         true
     ;
         constraint_transitive_closure(!.OCI, Constraint, NewConstraints),
@@ -434,8 +435,8 @@
         % No cycles. (lt(X, X) is a contradiction)
         set.empty(set.filter(pred(lt(X, X)::in) is semidet, NewConstraints)),
 
-        !:OCI = !.OCI ^ constraints :=
-            set.union(NewConstraints, !.OCI ^ constraints)
+        !OCI ^ oci_constraints :=
+            set.union(NewConstraints, !.OCI ^ oci_constraints)
     ).
 
     % constraint_transitive_closure(OCI, Constraint, NewConstraints)
@@ -448,7 +449,7 @@
     mode_ordering_constraint::in, set(mode_ordering_constraint)::out) is det.
 
 constraint_transitive_closure(OCI, Constraint, NewConstraints) :-
-    Constraints = OCI ^ constraints,
+    Constraints = OCI ^ oci_constraints,
     Constraint = lt(From, To),
     ComesBefore = set.filter_map(
         func(lt(B, F)::in) = (B::out) is semidet :- F = From, Constraints),
@@ -511,11 +512,11 @@
 make_conjunct_nonlocal_repvars(PredId, Goal, !RepvarMap) :-
     GoalInfo = Goal ^ hlds_goal_info,
     Nonlocals = goal_info_get_nonlocals(GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
 
     set.fold(
         (pred(NL::in, RMap0::in, RMap::out) is det :-
-            multi_map.set(RMap0, NL, NL `in` PredId `at` GoalPath, RMap)
+            multi_map.set(RMap0, NL, NL `in` PredId `at` GoalId, RMap)
         ),
         Nonlocals, !RepvarMap).
 
@@ -564,8 +565,10 @@
         % Variable not produced here - no constraints.
     ;
         ProgVarAtProducers = [RepVar],      % Should be only one producer
-        get_position_in_conj(RepVar, First),
-        list.map(get_position_in_conj, ProgVarAtConsumers, Laters),
+        ContainingGoalMap = !.OCInfo ^ oci_containing_map,
+        get_position_in_conj(ContainingGoalMap, RepVar, First),
+        list.map(get_position_in_conj(ContainingGoalMap), ProgVarAtConsumers,
+            Laters),
 
         list.foldl(add_lt_constraint(First), Laters, !OCInfo)
     ).
@@ -584,10 +587,12 @@
     % goalpath in RepVar is not a conjunction, otherwise it returns in N
     % the number of the conjunct the RepVar refers to.
     %
-:- pred get_position_in_conj(mc_rep_var::in, conjunct_id::out) is semidet.
+:- pred get_position_in_conj(containing_goal_map::in, mc_rep_var::in,
+    conjunct_id::out) is semidet.
 
-get_position_in_conj(_ProgVar `in` _PredId `at` GoalPath, N) :-
-    LastStep = goal_path_get_last(GoalPath),
+get_position_in_conj(ContainingGoalMap, _Var `in` _PredId `at` GoalId, N) :-
+    map.lookup(ContainingGoalMap, GoalId, ContainingGoal),
+    ContainingGoal = containing_goal(_, LastStep),
     LastStep = step_conj(N).
 
 %-----------------------------------------------------------------------------%
@@ -610,8 +615,8 @@
 %    original_order_constraints(OCI ^ num_conjuncts, OriginalOrderConstraints),
 %    constrain_if_possible(OriginalOrderConstraints, OCI0, OCI1),
 
-    Conjuncts = set.from_sorted_list(1 `..` OCI ^ num_conjuncts),
-    topological_sort_min_reordering(OCI ^ constraints, Conjuncts, Order).
+    Conjuncts = set.from_sorted_list(1 `..` OCI ^ oci_num_conjuncts),
+    topological_sort_min_reordering(OCI ^ oci_constraints, Conjuncts, Order).
 
     % original_order_constraints(N, MOCs) produces a list of constraints MOCs
     % that describe a complete order for N conjuncts, such that they are not
@@ -623,9 +628,8 @@
 original_order_constraints(N, MOCs) :-
     complete_order_constraints(1 `..` N, MOCs).
 
-    % complete_order_constraints(Xs) produces a list of constraints
-    % that describe a compete order for Xs such that it is not reordered
-    % at all.
+    % complete_order_constraints(Xs) produces a list of constraints that
+    % describe a compete order for Xs such that it is not reordered at all.
     %
 :- pred complete_order_constraints(list(conjunct_id)::in,
     mode_ordering_constraints::out) is det.
@@ -767,9 +771,10 @@
 
 dump_goal_goal_paths(Globals, Indent, Goal, !IO) :-
     Goal = hlds_goal(GoalExpr, GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
-    GoalPathFormat = [words(goal_path_to_string(GoalPath)), nl],
-    write_error_pieces_maybe_with_context(Globals, no, Indent, GoalPathFormat,
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    GoalId = goal_id(GoalIdNum),
+    GoalIdPieces = [words(string.int_to_string(GoalIdNum)), nl],
+    write_error_pieces_maybe_with_context(Globals, no, Indent, GoalIdPieces,
         !IO),
 
     % Dump the goal paths for each subgoal in GoalExpr at SubGoalIndent,
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.353
diff -u -r1.353 polymorphism.m
--- compiler/polymorphism.m	15 Dec 2010 06:29:55 -0000	1.353
+++ compiler/polymorphism.m	15 Dec 2010 06:33:23 -0000
@@ -1035,7 +1035,7 @@
         ActualExistConstraints) :-
     list.length(ExistConstraints, NumExistConstraints),
     (
-        search_hlds_constraint_list(ConstraintMap, unproven, empty_goal_path,
+        search_hlds_constraint_list(ConstraintMap, unproven, goal_id(0),
             NumExistConstraints, ActualExistConstraints0)
     ->
         ActualExistConstraints = ActualExistConstraints0
@@ -1606,19 +1606,19 @@
         yes(CallUnifyContext), QualifiedPName),
 
     % Construct a goal_info for the lambda goal, making sure to set up
-    % the nonlocals field in the goal_info correctly. The goal_path is needed
+    % the nonlocals field in the goal_info correctly. The goal_id is needed
     % to compute constraint_ids correctly.
 
     NonLocals = goal_info_get_nonlocals(GoalInfo0),
     set.insert_list(NonLocals, LambdaVars, OutsideVars),
     set.list_to_set(Args, InsideVars),
     set.intersect(OutsideVars, InsideVars, LambdaNonLocals),
-    GoalPath = goal_info_get_goal_path(GoalInfo0),
+    GoalId = goal_info_get_goal_id(GoalInfo0),
     goal_info_init(LambdaGoalInfo0),
     goal_info_set_context(Context, LambdaGoalInfo0, LambdaGoalInfo1),
     goal_info_set_nonlocals(LambdaNonLocals, LambdaGoalInfo1, LambdaGoalInfo2),
     goal_info_set_purity(Purity, LambdaGoalInfo2, LambdaGoalInfo3),
-    goal_info_set_goal_path(GoalPath, LambdaGoalInfo3, LambdaGoalInfo),
+    goal_info_set_goal_id(GoalId, LambdaGoalInfo3, LambdaGoalInfo),
     LambdaGoal = hlds_goal(LambdaGoalExpr, LambdaGoalInfo),
 
     % Work out the modes of the introduced lambda variables and the determinism
@@ -1742,20 +1742,20 @@
 
     % Create type_class_info variables for the type class constraints.
     poly_info_get_constraint_map(!.Info, ConstraintMap),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
     list.length(ParentExistentialConstraints, NumExistentialConstraints),
     Context = goal_info_get_context(GoalInfo),
     (
         IsConstruction = yes,
         % Assume it's a construction.
-        lookup_hlds_constraint_list(ConstraintMap, unproven, GoalPath,
+        lookup_hlds_constraint_list(ConstraintMap, unproven, GoalId,
             NumExistentialConstraints, ActualExistentialConstraints),
         make_typeclass_info_vars(ActualExistentialConstraints, [], Context,
             ExtraTypeClassVars, ExtraTypeClassGoals, !Info)
     ;
         IsConstruction = no,
         % Assume it's a deconstruction.
-        lookup_hlds_constraint_list(ConstraintMap, assumed, GoalPath,
+        lookup_hlds_constraint_list(ConstraintMap, assumed, GoalId,
             NumExistentialConstraints, ActualExistentialConstraints),
         make_existq_typeclass_info_vars(ActualExistentialConstraints,
             ExtraTypeClassVars, ExtraTypeClassGoals, !Info)
@@ -2083,9 +2083,9 @@
 
         % Make the universally quantified typeclass_infos for the call.
         poly_info_get_constraint_map(!.Info, ConstraintMap),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
         list.length(ParentUnivConstraints, NumUnivConstraints),
-        lookup_hlds_constraint_list(ConstraintMap, unproven, GoalPath,
+        lookup_hlds_constraint_list(ConstraintMap, unproven, GoalId,
             NumUnivConstraints, ActualUnivConstraints),
         apply_rec_subst_to_tvar_list(ParentKindMap, ParentToActualTypeSubst,
             ParentExistQVars, ActualExistQVarTypes),
@@ -2104,7 +2104,7 @@
         % Make variables to hold any existentially quantified typeclass_infos
         % in the call, insert them into the typeclass_info map.
         list.length(ParentExistConstraints, NumExistConstraints),
-        lookup_hlds_constraint_list(ConstraintMap, assumed, GoalPath,
+        lookup_hlds_constraint_list(ConstraintMap, assumed, GoalId,
             NumExistConstraints, ActualExistConstraints),
         make_existq_typeclass_info_vars(
             ActualExistConstraints, ExtraExistClassVars,
Index: compiler/post_typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/post_typecheck.m,v
retrieving revision 1.142
diff -u -r1.142 post_typecheck.m
--- compiler/post_typecheck.m	15 Dec 2010 06:29:55 -0000	1.142
+++ compiler/post_typecheck.m	15 Dec 2010 06:33:23 -0000
@@ -399,8 +399,8 @@
 
     % A prog_constraint cannot contain context information (see the comment on
     % the type definition). However, a constraint_id happens to contain a
-    % goal_path so we can look up a constraint_id for a prog_constraint, then
-    % use the goal_path to reach the goal.
+    % goal_id so we can look up a constraint_id for a prog_constraint, then
+    % use the goal_id to reach the goal.
     %
 :- func find_constrained_goals(pred_info, list(prog_constraint))
     = list(hlds_goal).
@@ -418,13 +418,13 @@
     % This could be more efficient.
     FindGoals = (pred(Goal::out) is nondet :-
         set.member(ConstraintId, ConstraintIds),
-        ConstraintId = constraint_id(_, ConstraintGoalPath, _),
+        ConstraintId = constraint_id(_, ConstraintGoalId, _),
         promise_equivalent_solutions [Goal] (
             list.member(Clause, Clauses),
             goal_contains_goal(Clause ^ clause_body, Goal),
             Goal = hlds_goal(_, GoalInfo),
-            GoalPath = goal_info_get_goal_path(GoalInfo),
-            GoalPath = ConstraintGoalPath
+            GoalId = goal_info_get_goal_id(GoalInfo),
+            GoalId = ConstraintGoalId
         )
     ),
     solutions(FindGoals, Goals).
@@ -1087,9 +1087,9 @@
         map.apply_to_list(ArgVars0, !.VarTypes, ArgTypes0),
         ArgTypes = ArgTypes0 ++ [TypeOfX],
         pred_info_get_constraint_map(!.PredInfo, ConstraintMap),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
         ConstraintSearch =
-            search_hlds_constraint_list(ConstraintMap, unproven, GoalPath),
+            search_hlds_constraint_list(ConstraintMap, unproven, GoalId),
         Context = goal_info_get_context(GoalInfo0),
         find_matching_pred_id(ModuleInfo, PredIds, TVarSet, ExistQTVars,
             ArgTypes, HeadTypeParams, yes(ConstraintSearch), Context,
@@ -1286,8 +1286,8 @@
     get_constructor_containing_field(ModuleInfo, TermType, FieldName,
         ConsId, FieldNumber),
 
-    GoalPath = goal_info_get_goal_path(OldGoalInfo),
-    get_cons_id_arg_types_adding_existq_tvars(ModuleInfo, GoalPath, ConsId,
+    GoalId = goal_info_get_goal_id(OldGoalInfo),
+    get_cons_id_arg_types_adding_existq_tvars(ModuleInfo, GoalId, ConsId,
         TermType, ArgTypes0, ExistQVars, !PredInfo),
 
     % If the type of the field we are extracting contains existentially
@@ -1340,8 +1340,8 @@
     get_constructor_containing_field(ModuleInfo, TermType, FieldName,
         ConsId0, FieldNumber),
 
-    GoalPath = goal_info_get_goal_path(OldGoalInfo),
-    get_cons_id_arg_types_adding_existq_tvars(ModuleInfo, GoalPath, ConsId0,
+    GoalId = goal_info_get_goal_id(OldGoalInfo),
+    get_cons_id_arg_types_adding_existq_tvars(ModuleInfo, GoalId, ConsId0,
         TermType, ArgTypes, ExistQVars, !PredInfo),
 
     split_list_at_index(FieldNumber, ArgTypes,
@@ -1394,10 +1394,10 @@
     Goal = scope(barrier(removable), Conj).
 
 :- pred get_cons_id_arg_types_adding_existq_tvars(module_info::in,
-    goal_path::in, cons_id::in, mer_type::in, list(mer_type)::out,
+    goal_id::in, cons_id::in, mer_type::in, list(mer_type)::out,
     list(tvar)::out, pred_info::in, pred_info::out) is det.
 
-get_cons_id_arg_types_adding_existq_tvars(ModuleInfo, GoalPath, ConsId,
+get_cons_id_arg_types_adding_existq_tvars(ModuleInfo, GoalId, ConsId,
         TermType, ActualArgTypes, ActualExistQVars, !PredInfo) :-
     % Split the list of argument types at the named field.
     type_to_ctor_det(TermType, TypeCtor),
@@ -1431,7 +1431,7 @@
 
         pred_info_get_constraint_map(!.PredInfo, ConstraintMap),
         list.length(ConsConstraints, NumConstraints),
-        lookup_hlds_constraint_list(ConstraintMap, assumed, GoalPath,
+        lookup_hlds_constraint_list(ConstraintMap, assumed, GoalId,
             NumConstraints, ActualConstraints),
         constraint_list_subsumes_det(ParentConstraints, ActualConstraints,
             ExistTSubst),
@@ -1572,7 +1572,7 @@
 create_pure_atomic_unification_with_nonlocals(Var, RHS, OldGoalInfo,
         RestrictNonLocals, VarsList, UnifyContext, Goal) :-
     Context = goal_info_get_context(OldGoalInfo),
-    GoalPath = goal_info_get_goal_path(OldGoalInfo),
+    GoalId = goal_info_get_goal_id(OldGoalInfo),
     UnifyContext = unify_context(UnifyMainContext, UnifySubContext),
     create_pure_atomic_complicated_unification(Var, RHS,
         Context, UnifyMainContext, UnifySubContext, Goal0),
@@ -1583,10 +1583,10 @@
     set.intersect(RestrictNonLocals, NonLocals1, NonLocals),
     goal_info_set_nonlocals(NonLocals, GoalInfo0, GoalInfo1),
 
-    % Use the goal path from the original goal, so that the constraint_ids
+    % Use the goal id from the original goal, so that the constraint_ids
     % will be as expected.  (See the XXX comment near the definition of
     % constraint_id in hlds_data.m for more info.)
-    goal_info_set_goal_path(GoalPath, GoalInfo1, GoalInfo),
+    goal_info_set_goal_id(GoalId, GoalInfo1, GoalInfo),
     Goal = hlds_goal(GoalExpr0, GoalInfo).
 
 :- pred make_new_vars(list(mer_type)::in, list(prog_var)::out,
Index: compiler/proc_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/proc_gen.m,v
retrieving revision 1.40
diff -u -r1.40 proc_gen.m
--- compiler/proc_gen.m	15 Dec 2010 06:29:56 -0000	1.40
+++ compiler/proc_gen.m	15 Dec 2010 06:33:23 -0000
@@ -75,6 +75,7 @@
 :- import_module backend_libs.proc_label.
 :- import_module backend_libs.rtti.
 :- import_module hlds.code_model.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_goal.
@@ -300,11 +301,23 @@
 %---------------------------------------------------------------------------%
 
 generate_proc_code(PredInfo, ProcInfo0, PredId, ProcId, ModuleInfo0,
-        !GlobalData, Proc) :-
+        !GlobalData, CProc) :-
     % The modified module_info and proc_info are both discarded
     % on return from generate_proc_code.
     maybe_set_trace_level(PredInfo, ModuleInfo0, ModuleInfo),
-    ensure_all_headvars_are_named(ProcInfo0, ProcInfo),
+    ensure_all_headvars_are_named(ProcInfo0, ProcInfo1),
+
+    % We use the globals from the original module info, so that
+    module_info_get_globals(ModuleInfo0, Globals0),
+    globals.get_trace_level(Globals0, TraceLevel0),
+    ( given_trace_level_is_none(TraceLevel0) = no ->
+        fill_goal_id_slots_in_proc(ModuleInfo, ContainingGoalMap,
+            ProcInfo1, ProcInfo),
+        MaybeContainingGoalMap = yes(ContainingGoalMap)
+    ;
+        MaybeContainingGoalMap = no,
+        ProcInfo = ProcInfo1
+    ),
 
     proc_info_interface_determinism(ProcInfo, Detism),
     CodeModel = proc_info_interface_code_model(ProcInfo),
@@ -319,8 +332,8 @@
         FollowVars = abs_follow_vars(FollowVarsMap, 1)
     ),
     module_info_get_globals(ModuleInfo, Globals),
-    continuation_info.basic_stack_layout_for_proc(PredInfo, Globals,
-        BasicStackLayout, ForceProcId),
+    basic_stack_layout_for_proc(PredInfo, Globals, BasicStackLayout,
+        ForceProcId),
     SaveSuccip = BasicStackLayout,
 
     % Initialise the code_info structure. Generate_category_code below will use
@@ -331,7 +344,7 @@
     global_data_get_static_cell_info(!.GlobalData, StaticCellInfo0),
     code_info_init(SaveSuccip, Globals, PredId, ProcId, PredInfo,
         ProcInfo, FollowVars, ModuleInfo, StaticCellInfo0,
-        OutsideResumePoint, TraceSlotInfo, CodeInfo0),
+        OutsideResumePoint, TraceSlotInfo, MaybeContainingGoalMap, CodeInfo0),
 
     % Find out the approriate context for the predicate's interface events.
     pred_info_get_clauses_info(PredInfo, ClausesInfo),
@@ -499,7 +512,7 @@
         ProcLabelCounter = LabelCounter
     ),
     get_used_env_vars(CodeInfo, UsedEnvVars),
-    Proc = c_procedure(Name, Arity, proc(PredId, ProcId), CodeModel,
+    CProc = c_procedure(Name, Arity, proc(PredId, ProcId), CodeModel,
         ProcInstructions, ProcLabel, ProcLabelCounter, MayAlterRtti,
         UsedEnvVars).
 
Index: compiler/prop_mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prop_mode_constraints.m,v
retrieving revision 1.27
diff -u -r1.27 prop_mode_constraints.m
--- compiler/prop_mode_constraints.m	15 Dec 2010 06:29:58 -0000	1.27
+++ compiler/prop_mode_constraints.m	15 Dec 2010 06:33:24 -0000
@@ -9,11 +9,10 @@
 % File: prop_mode_constraints.m.
 % Main author: richardf.
 %
-% XXX This module essentially serves as interface between the
-% pre-existing mode_constraints module and the new
-% abstract_mode_constraints and build_mode_constraints modules.
-% Ultimately its contents should probably be moved into those
-% modules respectively.
+% XXX This module essentially serves as interface between the old
+% mode_constraints module (by dmo) and the new abstract_mode_constraints
+% and build_mode_constraints modules (by richardf). Ultimately its contents
+% should probably be moved into those modules respectively.
 %
 %-----------------------------------------------------------------------------%
 
@@ -23,6 +22,7 @@
 :- import_module check_hlds.abstract_mode_constraints.
 :- import_module check_hlds.build_mode_constraints.
 :- import_module hlds.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
 
@@ -32,9 +32,10 @@
 
 %-----------------------------------------------------------------------------%
 
-    % Storing constraints by predicate.
-    %
-:- type pred_constraints_map == map(pred_id, mode_constraints).
+    % Maps each predicate to information about its goal ids and its mode
+    % constraint.
+:- type pred_constraints_map ==
+    map(pred_id, {containing_goal_map, mode_constraints}).
 
 %-----------------------------------------------------------------------------%
 
@@ -78,7 +79,6 @@
 
 :- implementation.
 
-:- import_module check_hlds.goal_path.
 :- import_module hlds.hlds_args.
 :- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_error_util.
@@ -119,7 +119,7 @@
     %   !Constraints):
     %
     % Performs a number of tasks for predicate PredId:
-    %   1) Fill out the goal_path information in the ModuleInfo structure.
+    %   1) Fill out the goal_id information in the ModuleInfo structure.
     %   2) Add producer/consumer constraint variables for program
     %      variables corresponding to any location at which they are
     %      nonlocal to Varset and VarMap. (Elsewhere is is clear as to
@@ -142,57 +142,61 @@
         !VarInfo, !Constraints),
     module_info_set_pred_info(PredId, PredInfo, !ModuleInfo).
 
-    % The working part of prop_mode_constraints_in_pred/8, with just
-    % the PredInfo unpacked from the ModuleInfo.
+    % The working part of prop_mode_constraints_in_pred/8, with the pred_info
+    % unpacked from the ModuleInfo.
     %
 :- pred do_prop_mode_constraints_in_pred(module_info::in, pred_id::in,
     pred_info::in, pred_info::out, mc_var_info::in, mc_var_info::out,
-    pred_constraints_map::in, pred_constraints_map::out)
-    is det.
+    pred_constraints_map::in, pred_constraints_map::out) is det.
 
 do_prop_mode_constraints_in_pred(ModuleInfo, PredId, !PredInfo, !VarInfo,
-        !Constraints) :-
-    fill_goal_path_slots_in_clauses(ModuleInfo, GoalPathOptimisation,
-        !PredInfo),
+        !PredConstraintsMap) :-
+    % XXX Currently the constraints simply say that if a variable is bound
+    % at a disjunct it is bound at the disjunction by making the relevant
+    % variables equivalent. Setting GoalPathOptimisation to yes will cause
+    % the disjucts to be given the same path as the disjunction, so that
+    % the relevant constraint variables will not need to be constrained
+    % equivalent - they will be the same variable. It will do the same
+    % for other path types with similar equivalence constraints -
+    % refer to the goal_path module for a more detailed description.
+    % GoalPathOptimisation = no.
+    %
+    % XXX The above comment is obsolete, in that the current version of the
+    % goal_path module leaves the task of making the relevant variables
+    % equivalent to THIS module.
+
+    pred_info_get_clauses_info(!.PredInfo, ClausesInfo0),
+    fill_goal_id_slots_in_clauses(ModuleInfo, ContainingGoalMap,
+        ClausesInfo0, ClausesInfo),
+    pred_info_set_clauses_info(ClausesInfo, !PredInfo),
 
     % If mode inference requested, just add constraints for the clause body,
     % otherwise, process the predicate for each of the procedures.
 
     ( pred_info_infer_modes(!.PredInfo) ->
         add_clauses_constraints(ModuleInfo, PredId, !.PredInfo, !VarInfo,
-            init_pred_p_c_constraints, BodyConstraints),
-        svmap.set(PredId, BodyConstraints, !Constraints)
+            init_pred_p_c_constraints, BodyConstraints)
     ;
         prop_mode_constraints_in_mode_declared_pred(ModuleInfo, PredId,
-            !.PredInfo, !VarInfo, !Constraints)
+            !.PredInfo, !VarInfo, BodyConstraints)
     ),
-
-    % XXX Currently the constraints simply say that if a variable is bound
-    % at a disjunct it is bound at the disjunction by making the relevant
-    % variables equivalent. Setting GoalPathOptimisation to yes will cause
-    % the disjucts to be given the same path as the disjunction, so that
-    % the relevant constraint variables will not need to be constrained
-    % equivalent - they will be the same variable. It will do the same
-    % for other path types with similar equivalence constraints -
-    % refer to the goal_path module for a more detailed description.
-    GoalPathOptimisation = no.
+    svmap.set(PredId, {ContainingGoalMap, BodyConstraints},
+        !PredConstraintsMap).
 
     % prop_mode_constraints_in_mode_declared_pred(ModuleInfo, PredId, PredInfo,
-    %   !VarInfo, !PredConstraintsMap):
+    %   !VarInfo, FullConstraints):
     %
-    % Uses the clauses and mode declarations in PredInfo (which should
-    % be for predicate PredId taken from ModuleInfo) to create
-    % producer/consumer constraints for program variables in predicate
-    % PredId and stores them in PredConstraintsMap. VarInfo is updated
+    % Uses the clauses and mode declarations in PredInfo (which should be
+    % for predicate PredId taken from ModuleInfo) to create producer/consumer
+    % constraints for program variables in predicate PredId. VarInfo is updated
     % with any constraint variables used.
     %
 :- pred prop_mode_constraints_in_mode_declared_pred(module_info::in,
     pred_id::in, pred_info::in, mc_var_info::in, mc_var_info::out,
-    pred_constraints_map::in, pred_constraints_map::out)
-    is det.
+    mode_constraints::out) is det.
 
 prop_mode_constraints_in_mode_declared_pred(ModuleInfo, PredId, PredInfo,
-        !VarInfo, !PredConstraintsMap) :-
+        !VarInfo, FullConstraints) :-
     ProcIds = pred_info_all_procids(PredInfo),
 
     add_clauses_constraints(ModuleInfo, PredId, PredInfo, !VarInfo,
@@ -202,9 +206,7 @@
     list.map(pred_info_proc_info(PredInfo), ProcIds, ProcInfos),
     list.foldl2_corresponding(
         prop_mode_constraints_in_mode_declared_proc(ModuleInfo, PredId),
-        ProcIds, ProcInfos, !VarInfo, BodyConstr, FullConstraints),
-
-    svmap.set(PredId, FullConstraints, !PredConstraintsMap).
+        ProcIds, ProcInfos, !VarInfo, BodyConstr, FullConstraints).
 
     % prop_mode_constraints_in_mode_declared_proc(ModuleInfo, PredId, ProcId,
     %   ProcInfo, !VarInfo, !PredConstraints):
@@ -218,8 +220,8 @@
     pred_id::in, proc_id::in, proc_info::in, mc_var_info::in,
     mc_var_info::out, mode_constraints::in, mode_constraints::out) is det.
 
-prop_mode_constraints_in_mode_declared_proc(ModuleInfo, PredId, ProcId, ProcInfo, !VarInfo,
-        !PredConstraints) :-
+prop_mode_constraints_in_mode_declared_proc(ModuleInfo, PredId, ProcId,
+        ProcInfo, !VarInfo, !PredConstraints) :-
     proc_info_get_argmodes(ProcInfo, ArgModes),
     proc_info_get_headvars(ProcInfo, Args),
     add_mode_decl_constraints(ModuleInfo, PredId, ProcId, ArgModes, Args,
@@ -382,23 +384,23 @@
     % flatten_conjunction(!Goals) flattens the conjunction Goals - that
     % is, moves the conjuncts from nested conjunctions into Goals.
     %
-:- pred flatten_conjunction(hlds_goals::in, hlds_goals::out) is det.
+:- pred flatten_conjunction(list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
 flatten_conjunction(!Goals) :-
-    list.foldr(add_to_conjunction, !.Goals, [], !:Goals).
+    list.foldr(add_to_before_conjunction, !.Goals, [], !:Goals).
 
-    % add_to_conjunction(Goal, !Goals) adds Goal to the front of the
+    % add_to_before_conjunction(Goal, !Goals) adds Goal to the front of the
     % conjunction Goals. It keeps the conjunction flat, so nested conjunctions
-    % are scrapped and their conjuncts prepended to Goals.
+    % are flattened and their conjuncts prepended to Goals.
     %
-:- pred add_to_conjunction(hlds_goal::in, hlds_goals::in, hlds_goals::out)
-    is det.
+:- pred add_to_before_conjunction(hlds_goal::in,
+    list(hlds_goal)::in, list(hlds_goal)::out) is det.
 
-add_to_conjunction(Goal, !Goals) :-
+add_to_before_conjunction(Goal, !Goals) :-
     ( Goal = hlds_goal(conj(plain_conj, SubGoals), _) ->
-        list.append(SubGoals, !Goals)
+        !:Goals = SubGoals ++ !.Goals
     ;
-        list.cons(Goal, !Goals)
+        !:Goals = [Goal | !.Goals]
     ).
 
     % make_unifications(Context, MaybeUnifications, Args0, Args, !SeenSoFar,
@@ -408,7 +410,7 @@
     % argument (in Varset and VarTypes) to replace it (in Args), and generates
     % a unification between new argument and old (with context Context).
     %
-:- pred make_unifications(prog_context::in, hlds_goals::out,
+:- pred make_unifications(prog_context::in, list(hlds_goal)::out,
     list(prog_var)::in, list(prog_var)::out,
     set(prog_var)::in, set(prog_var)::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
@@ -441,15 +443,15 @@
 
         % Make new unification.
         create_atomic_complicated_unification(Var0, rhs_var(Var), Context,
-            umc_implicit("Making call arguments unique for constraints" ++
-            " based mode analysis"), [], purity_pure, UnificationGoal0),
+            umc_implicit("Making call args unique for cbma"), [], purity_pure,
+            UnificationGoal0),
         UnificationGoal0 =
             hlds_goal(UnificationGoalExpr, UnificationGoalInfo0),
         goal_info_set_nonlocals(set.from_list([Var0, Var]),
             UnificationGoalInfo0, UnificationGoalInfo),
         UnificationGoal =
             hlds_goal(UnificationGoalExpr, UnificationGoalInfo),
-        list.cons(UnificationGoal, !Unifications)
+        !:Unifications = [UnificationGoal | !.Unifications]
     ;
         Var = Var0
     ),
@@ -466,7 +468,7 @@
     % (where Unifications contains unfications between old arguments
     % and their new replacements).
     %
-:- pred replace_call_with_conjunction(hlds_goal_expr::in, hlds_goals::in,
+:- pred replace_call_with_conjunction(hlds_goal_expr::in, list(hlds_goal)::in,
     list(prog_var)::in, hlds_goal_expr::out,
     hlds_goal_info::in, hlds_goal_info::out) is det.
 
@@ -477,7 +479,7 @@
     CallNonlocals0 = goal_info_get_nonlocals(CallGoalInfo0),
     CallNonlocals = set.insert_list(CallNonlocals0, NewArgs),
     goal_info_set_nonlocals(CallNonlocals, CallGoalInfo0, CallGoalInfo),
-    Goals = list.cons(hlds_goal(CallGoalExpr, CallGoalInfo), Unifications),
+    Goals = [hlds_goal(CallGoalExpr, CallGoalInfo) | Unifications],
 
     % Create the new conjunction
     GoalExpr = conj(plain_conj, Goals),
@@ -529,7 +531,7 @@
         describe_one_pred_info_name(should_module_qualify, PredInfo) ++
         [suffix(":")], !IO),
 
-    map.lookup(PredConstraintsMap, PredId, PredConstraints),
+    map.lookup(PredConstraintsMap, PredId, {_, PredConstraints}),
     AllProcAnnConstraints = allproc_annotated_constraints(PredConstraints),
     dump_constraints_and_annotations(Globals, ConstraintVarset,
         AllProcAnnConstraints, !IO),
Index: compiler/rbmm.add_rbmm_goal_infos.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.add_rbmm_goal_infos.m,v
retrieving revision 1.10
diff -u -r1.10 rbmm.add_rbmm_goal_infos.m
--- compiler/rbmm.add_rbmm_goal_infos.m	15 Dec 2010 06:29:59 -0000	1.10
+++ compiler/rbmm.add_rbmm_goal_infos.m	15 Dec 2010 06:33:24 -0000
@@ -57,8 +57,8 @@
 :- implementation.
 
 :- import_module check_hlds.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.type_util.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module libs.
Index: compiler/rbmm.condition_renaming.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.condition_renaming.m,v
retrieving revision 1.13
diff -u -r1.13 rbmm.condition_renaming.m
--- compiler/rbmm.condition_renaming.m	15 Dec 2010 06:29:59 -0000	1.13
+++ compiler/rbmm.condition_renaming.m	15 Dec 2010 06:33:24 -0000
@@ -27,6 +27,12 @@
 % when it introduces reverse renaming to a non-local variable inside the
 % condition goal of an if-then-else.
 %
+% XXX This approach is fundamentally misconceived. The right approach would be
+% for the analysis up to this point to work with identifiers representing
+% regions, and for another pass to map each region to one or more program
+% variables. This naturally allows N different lifetimes of a region inside a
+% procedure to be represented by N different program variables.
+%
 %-----------------------------------------------------------------------------%
 
 :- module transform_hlds.rbmm.condition_renaming.
@@ -49,7 +55,8 @@
 
 :- type proc_goal_path_regions_table ==
     map(pred_proc_id, goal_path_regions_table).
-:- type goal_path_regions_table == map(goal_path, set(string)).
+:- type goal_path_regions_table == map(reverse_goal_path, set(string)).
+% XXX The key type should be goal_id.
 
     % This predicate collects two pieces of information.
     %
@@ -110,27 +117,27 @@
     % it finds the first program point in the corresponding Then and
     % introduces the reverse renaming annotation before that ponit.
     % Note that that first program point must not be in the condition of
-    % an if-then-else. E.g., 
-    % if % a renaming exists here: R -> R_ite_1 
+    % an if-then-else. E.g.,
+    % if % a renaming exists here: R -> R_ite_1
     % then
     %    if % not add reverse renaming annotation at this point.
     %    then
     %       % but at here: R := R_ite_1
     %    else
-    %       $ and at here: R := R_ite_1
-    % else 
+    %       % and at here: R := R_ite_1
+    % else
     %    ...
 :- pred collect_ite_annotation(proc_goal_path_regions_table::in,
-    execution_path_table::in, rpta_info_table::in, renaming_table::in,
-    renaming_table::out, renaming_annotation_table::out) is det.
+    execution_path_table::in, rpta_info_table::in,
+    renaming_table::in, renaming_table::out,
+    renaming_annotation_table::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 
-:- import_module check_hlds.
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module transform_hlds.rbmm.points_to_graph.
 :- import_module transform_hlds.smm_common.
@@ -187,38 +194,40 @@
         ResurRenamingAnnoTable, ProcId,
         !NonLocalRegionsTable, !InCondRegionsTable) :-
     PPId = proc(PredId, ProcId),
-    ( if    some_are_special_preds([PPId], ModuleInfo)
-      then  true
-      else
-            module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
-            fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
-            proc_info_get_goal(ProcInfo, Goal),
-            map.lookup(RptaInfoTable, PPId, rpta_info(Graph, _)),
-            map.lookup(LRBeforeTable, PPId, LRBeforeProc),
-            map.lookup(LRAfterTable, PPId, LRAfterProc),
-            ( if    map.search(ResurRenamingTable, PPId,
-                        ResurRenamingProc0)
-              then  ResurRenamingProc = ResurRenamingProc0
-              else  ResurRenamingProc = map.init
-            ),
-            ( if    map.search(ResurRenamingAnnoTable, PPId,
-                        ResurRenamingAnnoProc0)
-              then  ResurRenamingAnnoProc = ResurRenamingAnnoProc0
-              else  ResurRenamingAnnoProc = map.init
-            ),
-            collect_non_local_and_in_cond_regions_goal(Graph,
-                LRBeforeProc, LRAfterProc, ResurRenamingProc,
-                ResurRenamingAnnoProc, Goal,
-                map.init, NonLocalRegionsProc,
-                map.init, InCondRegionsProc),
-            ( if    map.count(NonLocalRegionsProc) = 0
-              then  true
-              else  svmap.set(PPId, NonLocalRegionsProc, !NonLocalRegionsTable)
-            ),
-            ( if    map.count(InCondRegionsProc) = 0
-              then  true
-              else  svmap.set(PPId, InCondRegionsProc, !InCondRegionsTable)
-            )
+    ( some_are_special_preds([PPId], ModuleInfo) ->
+        true
+    ;
+        module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
+        fill_goal_path_slots_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
+        proc_info_get_goal(ProcInfo, Goal),
+        map.lookup(RptaInfoTable, PPId, rpta_info(Graph, _)),
+        map.lookup(LRBeforeTable, PPId, LRBeforeProc),
+        map.lookup(LRAfterTable, PPId, LRAfterProc),
+        ( map.search(ResurRenamingTable, PPId, ResurRenamingProc0) ->
+            ResurRenamingProc = ResurRenamingProc0
+        ;
+            ResurRenamingProc = map.init
+        ),
+        ( map.search(ResurRenamingAnnoTable, PPId, ResurRenamingAnnoProc0) ->
+            ResurRenamingAnnoProc = ResurRenamingAnnoProc0
+        ;
+            ResurRenamingAnnoProc = map.init
+        ),
+        collect_non_local_and_in_cond_regions_goal(Graph,
+            LRBeforeProc, LRAfterProc, ResurRenamingProc,
+            ResurRenamingAnnoProc, Goal,
+            map.init, NonLocalRegionsProc,
+            map.init, InCondRegionsProc),
+        ( map.count(NonLocalRegionsProc) = 0 ->
+            true
+        ;
+            svmap.set(PPId, NonLocalRegionsProc, !NonLocalRegionsTable)
+        ),
+        ( map.count(InCondRegionsProc) = 0 ->
+            true
+        ;
+            svmap.set(PPId, InCondRegionsProc, !InCondRegionsTable)
+        )
     ).
 
 :- pred collect_non_local_and_in_cond_regions_goal(rpt_graph::in,
@@ -249,7 +258,6 @@
             LRBeforeProc, LRAfterProc,
             ResurRenamingProc, ResurRenamingAnnoProc),
         Conjs, !NonLocalRegionsProc, !InCondRegionsProc).
-
 collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
         plain_call(_, _, _, _, _, _),
         !NonLocalRegionsProc, !InCondRegionsProc).
@@ -259,7 +267,6 @@
 collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
         call_foreign_proc(_, _, _, _, _, _, _),
         !NonLocalRegionsProc, !InCondRegionsProc).
-
 collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
         ResurRenamingProc, ResurRenamingAnnoProc, switch(_, _, Cases),
         !NonLocalRegionsProc, !InCondRegionsProc) :-
@@ -284,7 +291,6 @@
         !NonLocalRegionsProc, !InCondRegionsProc).
 collect_non_local_and_in_cond_regions_expr(_, _, _, _, _,
         unify(_, _, _, _, _), !NonLocalRegionsProc, !InCondRegionsProc).
-
 collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
         ResurRenamingProc, ResurRenamingAnnoProc, scope(_, Goal),
         !NonLocalRegionsProc, !InCondRegionsProc) :-
@@ -293,7 +299,6 @@
     collect_non_local_and_in_cond_regions_goal(Graph, LRBeforeProc,
         LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc, Goal,
         !NonLocalRegionsProc, !InCondRegionsProc).
-
 collect_non_local_and_in_cond_regions_expr(Graph, LRBeforeProc, LRAfterProc,
         ResurRenamingProc, ResurRenamingAnnoProc, Expr,
         !NonLocalRegionProc, !InCondRegionsProc) :-
@@ -316,7 +321,6 @@
     collect_non_local_regions_in_ite(Graph,
         LRBeforeProc, LRAfterProc, ResurRenamingProc, ResurRenamingAnnoProc,
         Else, !NonLocalRegionProc).
-
 collect_non_local_and_in_cond_regions_expr(_, _, _, _, _, shorthand(_),
         !NonLocalRegionProc, !InCondRegionsProc) :-
     % These should have been expanded out by now.
@@ -350,7 +354,7 @@
     (
         HasSubGoals = does_not_have_subgoals,
         ProgPoint = program_point_init(Info),
-        ProgPoint = pp(_, GoalPath),
+        ProgPoint = pp(_, RevGoalPath),
         map.lookup(LRBeforeProc, ProgPoint, LRBefore),
         map.lookup(LRAfterProc, ProgPoint, LRAfter),
 
@@ -361,9 +365,8 @@
         % Those sets need to subject to resurrection renaming
         % and annotations.
         % Apply resurrection renaming to those sets.
-        % For each renaming annotation, the left one is put
-        % into CreatedBefore, and the right one is put into
-        % RemovedAfter.
+        % For each renaming annotation, the left one is put into CreatedBefore,
+        % and the right one is put into RemovedAfter.
         ( map.search(ResurRenamingProc, ProgPoint, ResurRenaming0) ->
             ResurRenaming = ResurRenaming0
         ;
@@ -383,7 +386,7 @@
             ResurRenamingAnnos, set.init, LeftRegions, set.init, RightRegions),
         set.union(RemovedAfterRegions0, RightRegions, RemovedAfterRegions),
         set.union(CreatedBeforeRegions0, LeftRegions, CreatedBeforeRegions),
-        record_non_local_regions(GoalPath, CreatedBeforeRegions,
+        record_non_local_regions(RevGoalPath, CreatedBeforeRegions,
             RemovedAfterRegions, !NonLocalRegionProc)
     ;
         HasSubGoals = has_subgoals,
@@ -439,20 +442,23 @@
     % the non-local set of regions is updated by including the regions
     % created before or at that program point and excluding those removed
     % at or after the program point.
-    % Because if-then-else can be nestted, we need to update the
+    % Because if-then-else can be nested, we need to update the
     % non-local sets of all the surrounding if-then-elses of this
     % program point.
     %
-:- pred record_non_local_regions(goal_path::in, set(string)::in,
-    set(string)::in, goal_path_regions_table::in,
-    goal_path_regions_table::out) is det.
+:- pred record_non_local_regions(reverse_goal_path::in, set(string)::in,
+    set(string)::in,
+    goal_path_regions_table::in, goal_path_regions_table::out) is det.
 
 record_non_local_regions(Path, Created, Removed, !NonLocalRegionProc) :-
-    ( goal_path_remove_last(Path, InitialPath, LastStep) ->
+    Path = rgp(RevSteps),
+    (
+        RevSteps = [LastStep | RevInitialSteps],
+        InitialPath = rgp(RevInitialSteps),
         ( LastStep = step_ite_else ->
-            % The current NonLocalRegions are attached to the goal path to
-            % the corresponding condition.
-            PathToCond = goal_path_add_at_end(InitialPath, step_ite_cond),
+            % The current NonLocalRegions are attached to the goal path
+            % to the corresponding condition.
+            PathToCond = rgp([step_ite_cond | RevInitialSteps]),
             ( map.search(!.NonLocalRegionProc, PathToCond, NonLocalRegions0) ->
                 set.union(NonLocalRegions0, Created, NonLocalRegions1),
                 set.difference(NonLocalRegions1, Removed, NonLocalRegions)
@@ -474,7 +480,7 @@
         record_non_local_regions(InitialPath, Created, Removed,
             !NonLocalRegionProc)
     ;
-        true
+        RevSteps = []
     ).
 
 :- pred collect_non_local_regions_in_ite_compound_goal(rpt_graph::in,
@@ -585,7 +591,7 @@
     (
         HasSubGoals = does_not_have_subgoals,
         ProgPoint = program_point_init(CondInfo),
-        ProgPoint = pp(_, GoalPath),
+        ProgPoint = pp(_, RevGoalPath),
         map.lookup(LRBeforeProc, ProgPoint, LRBefore),
         map.lookup(LRAfterProc, ProgPoint, LRAfter),
 
@@ -611,7 +617,7 @@
             set.init, _RightRegions),
         set.union(CreatedRegions0, LeftRegions, CreatedRegions),
 
-        record_regions_created_in_condition(GoalPath,
+        record_regions_created_in_condition(RevGoalPath,
             CreatedRegions, !InCondRegionsProc)
     ;
         HasSubGoals = has_subgoals,
@@ -627,11 +633,15 @@
     % We need to update the sets of all the conditions surrounding this
     % program point.
     %
-:- pred record_regions_created_in_condition(goal_path::in, set(string)::in,
-    goal_path_regions_table::in, goal_path_regions_table::out) is det.
+:- pred record_regions_created_in_condition(reverse_goal_path::in,
+    set(string)::in, goal_path_regions_table::in,
+    goal_path_regions_table::out) is det.
 
 record_regions_created_in_condition(Path, Created, !InCondRegionsProc) :-
-    ( goal_path_remove_last(Path, InitialPath, LastStep) ->
+    Path = rgp(RevSteps),
+    (
+        RevSteps = [LastStep | RevInitialSteps],
+        InitialPath = rgp(RevInitialSteps),
         ( LastStep = step_ite_cond  ->
             ( map.search(!.InCondRegionsProc, Path, InCondRegions0) ->
                 set.union(InCondRegions0, Created, InCondRegions)
@@ -651,7 +661,7 @@
         record_regions_created_in_condition(InitialPath, Created,
             !InCondRegionsProc)
     ;
-        true
+        RevSteps = []
     ).
 
 :- pred collect_regions_created_in_condition_compound_goal(rpt_graph::in,
@@ -772,7 +782,7 @@
     ).
 
 :- pred collect_ite_renamed_regions_ite(goal_path_regions_table::in,
-    goal_path::in, set(string)::in,
+    reverse_goal_path::in, set(string)::in,
     goal_path_regions_table::in, goal_path_regions_table::out) is det.
 
 collect_ite_renamed_regions_ite(NonLocalRegionsProc, PathToCond,
@@ -805,93 +815,76 @@
 collect_ite_renaming_proc(ModuleInfo, RptaInfoTable,
         PPId, IteRenamedRegionProc, !IteRenamingTable) :-
     module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
-    fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+    fill_goal_path_slots_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
     proc_info_get_goal(ProcInfo, Goal),
     map.lookup(RptaInfoTable, PPId, RptaInfo),
     RptaInfo = rpta_info(Graph, _),
-    collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
-        map.init, IteRenamingProc),
+    collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
+        Goal, map.init, IteRenamingProc),
     svmap.set(PPId, IteRenamingProc, !IteRenamingTable).
 
-:- pred collect_ite_renaming_goal(goal_path_regions_table::in,
-    rpt_graph::in, hlds_goal::in, renaming_proc::in,
-    renaming_proc::out) is det.
+:- pred collect_ite_renaming_goal(goal_path_regions_table::in, rpt_graph::in,
+    hlds_goal::in, renaming_proc::in, renaming_proc::out) is det.
 
 collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
         !IteRenamingProc) :-
-    Goal = hlds_goal(Expr, _),
-    collect_ite_renaming_expr(Expr, IteRenamedRegionProc, Graph,
-        !IteRenamingProc).
-
-:- pred collect_ite_renaming_expr(hlds_goal_expr::in,
-    goal_path_regions_table::in, rpt_graph::in, renaming_proc::in,
-    renaming_proc::out) is det.
-
-collect_ite_renaming_expr(conj(_, Conjs), IteRenamedRegionProc,
-        Graph, !IteRenamingProc) :-
-    list.foldl(collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
-        Conjs, !IteRenamingProc).
-
-collect_ite_renaming_expr(plain_call(_, _, _, _, _, _), _, _,
-        !IteRenamingProc).
-collect_ite_renaming_expr(generic_call(_, _, _, _), _, _,
-        !IteRenamingProc).
-collect_ite_renaming_expr(call_foreign_proc(_, _, _, _, _, _, _),
-        _, _, !IteRenamingProc).
-
-collect_ite_renaming_expr(switch(_, _, Cases), IteRenamedRegionProc,
-        Graph, !IteRenamingProc) :-
-    list.foldl(
-        collect_ite_renaming_case(IteRenamedRegionProc, Graph),
-        Cases, !IteRenamingProc).
-collect_ite_renaming_expr(disj(Disjs), IteRenamedRegionProc, Graph,
-        !IteRenamingProc) :-
-    list.foldl(
-        collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
-        Disjs, !IteRenamingProc).
-collect_ite_renaming_expr(negation(Goal), IteRenamedRegionProc, Graph,
-        !IteRenamingProc) :-
-    collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
-        !IteRenamingProc).
-collect_ite_renaming_expr(unify(_, _, _, _, _), _, _, !IteRenamingProc).
-
-collect_ite_renaming_expr(scope(_, Goal), IteRenamedRegionProc,
-        Graph, !IteRenamingProc) :-
-    % XXX We should special-case the handling of from_ground_term_construct
-    % scopes.
-    collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
-        !IteRenamingProc).
-
-collect_ite_renaming_expr(shorthand(_), _, _, !IteRenamingProc) :-
-    unexpected(this_file, "collect_ite_renaming_expr: shorthand not handled").
-
-collect_ite_renaming_expr(Expr, IteRenamedRegionProc, Graph,
-        !IteRenamingProc) :-
-    Expr = if_then_else(_, Cond, Then, Else),
-
-    % Renaming for if-then-else only happens in condition goals.
-    collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Cond,
-        !IteRenamingProc),
-
-    collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Then,
-        !IteRenamingProc),
-    collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Else,
-        !IteRenamingProc).
+    Goal = hlds_goal(GoalExpr, _),
+    (
+        ( GoalExpr = unify(_, _, _, _, _)
+        ; GoalExpr = plain_call(_, _, _, _, _, _)
+        ; GoalExpr = generic_call(_, _, _, _)
+        ; GoalExpr = call_foreign_proc(_, _, _, _, _, _, _)
+        )
+    ;
+        GoalExpr = conj(_, Conjs),
+        list.foldl(collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
+            Conjs, !IteRenamingProc)
+    ;
+        GoalExpr = disj(Disjs),
+        list.foldl(collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
+            Disjs, !IteRenamingProc)
+    ;
+        GoalExpr = switch(_, _, Cases),
+        list.foldl(collect_ite_renaming_case(IteRenamedRegionProc, Graph),
+            Cases, !IteRenamingProc)
+    ;
+        GoalExpr = negation(SubGoal),
+        collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
+            SubGoal, !IteRenamingProc)
+    ;
+        GoalExpr = scope(_, SubGoal),
+        % XXX We should special-case the handling of from_ground_term_construct
+        % scopes.
+        collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
+            SubGoal, !IteRenamingProc)
+    ;
+        GoalExpr = if_then_else(_, Cond, Then, Else),
+        % Renaming for if-then-else only happens in condition goals.
+        collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
+            Cond, !IteRenamingProc),
+
+        collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
+            Then, !IteRenamingProc),
+        collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
+            Else, !IteRenamingProc)
+    ;
+        GoalExpr = shorthand(_),
+        unexpected(this_file, "collect_ite_renaming_goal: shorthand")
+    ).
 
-:- pred collect_ite_renaming_case(goal_path_regions_table::in,
-    rpt_graph::in, case::in, renaming_proc::in,
-    renaming_proc::out) is det.
+:- pred collect_ite_renaming_case(goal_path_regions_table::in, rpt_graph::in,
+    case::in, renaming_proc::in, renaming_proc::out) is det.
 
-collect_ite_renaming_case(IteRenamedRegionProc, Graph, Case,
-        !IteRenamingProc) :-
+collect_ite_renaming_case(IteRenamedRegionProc, Graph,
+        Case, !IteRenamingProc) :-
     Case = case(_, _, Goal),
-    collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
-        !IteRenamingProc).
+    collect_ite_renaming_goal(IteRenamedRegionProc, Graph,
+        Goal, !IteRenamingProc).
 
     % Introduce renaming for each program point in a condition goal.
     %
-:- pred collect_ite_renaming_in_condition(
-    goal_path_regions_table::in, rpt_graph::in, hlds_goal::in,
+:- pred collect_ite_renaming_in_condition(goal_path_regions_table::in,
+    rpt_graph::in, hlds_goal::in,
     renaming_proc::in, renaming_proc::out) is det.
 
 collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Cond,
@@ -905,11 +898,12 @@
         % condition because if a region is to be renamed for a compounding
         % if-then-else of the closest if-then-else then it also needs to be
         % renamed for the closest if-then-else.
-        ProgPoint = pp(_, GoalPath),
-        get_closest_condition_in_goal_path(GoalPath, PathToClosestCond,
+        ProgPoint = pp(_, RevGoalPath),
+        get_closest_condition_in_goal_path(RevGoalPath, RevPathToClosestCond,
             0, HowMany),
         (
-            map.search(IteRenamedRegionProc, PathToClosestCond, RenamedRegions)
+            map.search(IteRenamedRegionProc, RevPathToClosestCond,
+                RenamedRegions)
         ->
             set.fold(record_ite_renaming(ProgPoint, HowMany, Graph),
                 RenamedRegions, !IteRenamingProc)
@@ -920,7 +914,7 @@
         )
     ;
         HasSubGoals = has_subgoals,
-        collect_ite_renaming_in_condition_compound_goal(IteRenamedRegionProc,
+        collect_ite_renaming_in_condition_compound_goal( IteRenamedRegionProc,
             Graph, Cond, !IteRenamingProc)
     ).
 
@@ -939,8 +933,8 @@
     svmap.set(ProgPoint, IteRenaming, !IteRenamingProc).
 
 :- pred collect_ite_renaming_in_condition_compound_goal(
-    goal_path_regions_table::in, rpt_graph::in, hlds_goal::in,
-    renaming_proc::in, renaming_proc::out) is det.
+    goal_path_regions_table::in, rpt_graph::in,
+    hlds_goal::in, renaming_proc::in, renaming_proc::out) is det.
 
 collect_ite_renaming_in_condition_compound_goal(IteRenamedRegionProc,
         Graph, GoalInCond, !IteRenamingProc) :-
@@ -963,22 +957,22 @@
             Cases, !IteRenamingProc)
     ;
         Expr = negation(Goal),
-        collect_ite_renaming_in_condition(IteRenamedRegionProc,
-            Graph, Goal, !IteRenamingProc)
+        collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Goal,
+            !IteRenamingProc)
     ;
         Expr = scope(_, Goal),
         % XXX We should special-case the handling of from_ground_term_construct
         % scopes.
-        collect_ite_renaming_in_condition(IteRenamedRegionProc,
-            Graph, Goal, !IteRenamingProc)
+        collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Goal,
+            !IteRenamingProc)
     ;
         Expr = if_then_else(_, Cond, Then, Else),
-        collect_ite_renaming_in_condition(IteRenamedRegionProc,
-            Graph, Cond, !IteRenamingProc),
-        collect_ite_renaming_in_condition(IteRenamedRegionProc,
-            Graph, Then, !IteRenamingProc),
-        collect_ite_renaming_in_condition(IteRenamedRegionProc,
-            Graph, Else, !IteRenamingProc)
+        collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
+            Cond, !IteRenamingProc),
+        collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
+            Then, !IteRenamingProc),
+        collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph,
+            Else, !IteRenamingProc)
     ;
         ( Expr = unify(_, _, _, _, _)
         ; Expr = plain_call(_, _, _, _, _, _)
@@ -993,8 +987,8 @@
             ++ "encountered atomic or unsupported goal")
     ).
 
-:- pred collect_ite_renaming_in_condition_case(
-    goal_path_regions_table::in, rpt_graph::in, case::in,
+:- pred collect_ite_renaming_in_condition_case(goal_path_regions_table::in,
+    rpt_graph::in, case::in,
     renaming_proc::in, renaming_proc::out) is det.
 
 collect_ite_renaming_in_condition_case(IteRenamedRegionProc, Graph, Case,
@@ -1013,11 +1007,16 @@
     %               ...
     % then HowMany is 2.
     %
-:- pred get_closest_condition_in_goal_path(goal_path::in,
-    goal_path::out, int::in, int::out) is det.
+    % XXX should do this without goalpaths, with just goal parents.
+    %
+:- pred get_closest_condition_in_goal_path(reverse_goal_path::in,
+    reverse_goal_path::out, int::in, int::out) is det.
 
 get_closest_condition_in_goal_path(Path, PathToCond, !HowMany) :-
-    ( goal_path_remove_last(Path, InitialPath, LastStep) ->
+    Path = rgp(RevSteps),
+    (
+        RevSteps = [LastStep | RevInitialSteps],
+        InitialPath = rgp(RevInitialSteps),
         ( LastStep = step_ite_cond ->
             PathToCond = Path,
             get_closest_condition_in_goal_path(InitialPath, _, !HowMany),
@@ -1027,7 +1026,8 @@
                 !HowMany)
         )
     ;
-        PathToCond = empty_goal_path
+        RevSteps = [],
+        PathToCond = rgp([])
     ).
 
 %-----------------------------------------------------------------------------%
@@ -1035,16 +1035,15 @@
 % Derive necessary reverse renaming.
 %
 
-collect_ite_annotation(IteRenamedRegionTable, ExecPathTable,
-        RptaInfoTable, !IteRenamingTable, IteAnnotationTable) :-
-    map.foldl2(
-        collect_ite_annotation_proc(ExecPathTable, RptaInfoTable),
+collect_ite_annotation(IteRenamedRegionTable, ExecPathTable, RptaInfoTable,
+        !IteRenamingTable, IteAnnotationTable) :-
+    map.foldl2(collect_ite_annotation_proc(ExecPathTable, RptaInfoTable),
         IteRenamedRegionTable, !IteRenamingTable,
         map.init, IteAnnotationTable).
 
 :- pred collect_ite_annotation_proc(execution_path_table::in,
-    rpta_info_table::in, pred_proc_id::in,
-    goal_path_regions_table::in, renaming_table::in, renaming_table::out, 
+    rpta_info_table::in, pred_proc_id::in, goal_path_regions_table::in,
+    renaming_table::in, renaming_table::out,
     renaming_annotation_table::in, renaming_annotation_table::out) is det.
 
 collect_ite_annotation_proc(ExecPathTable, RptaInfoTable, PPId,
@@ -1053,64 +1052,69 @@
     map.lookup(RptaInfoTable, PPId, RptaInfo),
     map.lookup(!.IteRenamingTable, PPId, IteRenamingProc0),
     RptaInfo = rpta_info(Graph, _),
-    map.foldl2(
-        collect_ite_annotation_region_names(ExecPaths, Graph),
+    map.foldl2(collect_ite_annotation_region_names(ExecPaths, Graph),
         IteRenamedRegionProc, IteRenamingProc0, IteRenamingProc,
         map.init, IteAnnotationProc),
     svmap.set(PPId, IteAnnotationProc, !IteAnnotationTable),
     svmap.set(PPId, IteRenamingProc, !IteRenamingTable).
 
 :- pred collect_ite_annotation_region_names(list(execution_path)::in,
-    rpt_graph::in, goal_path::in, set(string)::in,
-    renaming_proc::in, renaming_proc::out, 
+    rpt_graph::in, reverse_goal_path::in, set(string)::in,
+    renaming_proc::in, renaming_proc::out,
     renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
 
 collect_ite_annotation_region_names(ExecPaths, Graph, PathToCond,
         RenamedRegions, !IteRenamingProc, !IteAnnotationProc) :-
-    ( goal_path_remove_last(PathToCond, InitialSteps, LastStep) ->
+    PathToCond = rgp(RevPathToCondSteps),
+    (
+        RevPathToCondSteps = [LastStep | RevInitialSteps],
         expect(unify(LastStep, step_ite_cond), this_file,
             "collect_ite_annotation_region_names: not step_ite_cond"),
-        PathToThen = goal_path_add_at_end(InitialSteps, step_ite_then),
+        PathToThen = rgp([step_ite_then | RevInitialSteps]),
         get_closest_condition_in_goal_path(PathToCond, _, 0, HowMany),
         list.foldl2(
-            collect_ite_annotation_exec_path(Graph, PathToThen,
-                RenamedRegions, HowMany),
+            collect_ite_annotation_exec_path(Graph, PathToThen, RenamedRegions,
+                HowMany),
             ExecPaths, !IteRenamingProc, !IteAnnotationProc)
     ;
+        RevPathToCondSteps = [],
         unexpected(this_file,
             "collect_ite_annotation_region_set: empty path to condition.")
     ).
 
-:- pred collect_ite_annotation_exec_path(rpt_graph::in, goal_path::in,
+:- pred collect_ite_annotation_exec_path(rpt_graph::in, reverse_goal_path::in,
     set(string)::in, int::in, execution_path::in,
-    renaming_proc::in, renaming_proc::out, 
+    renaming_proc::in, renaming_proc::out,
     renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
 
 collect_ite_annotation_exec_path(_, _, _, _, [], !IteRenamingProc,
         !IteAnnotationProc).
-collect_ite_annotation_exec_path(Graph, PathToThen, RenamedRegions,
-        HowMany, [ProgPoint - _ | ProgPoint_Goals],
+collect_ite_annotation_exec_path(Graph, PathToThen,
+        RenamedRegions, HowMany, [ProgPoint - _ | ProgPointGoals],
         !IteRenamingProc, !IteAnnotationProc) :-
     % This is the first program point of this execution path.
     % We never need to introduce reversed renaming at this point.
-    collect_ite_annotation_exec_path_2(Graph, PathToThen, RenamedRegions,
-        HowMany, ProgPoint, ProgPoint_Goals, !IteRenamingProc,
+    collect_ite_annotation_exec_path_2(Graph, PathToThen,
+        RenamedRegions, HowMany, ProgPoint, ProgPointGoals, !IteRenamingProc,
         !IteAnnotationProc).
 
     % Process from the 2nd program point onwards.
-:- pred collect_ite_annotation_exec_path_2(rpt_graph::in, goal_path::in,
-    set(string)::in, int::in, program_point::in, execution_path::in,
-    renaming_proc::in, renaming_proc::out, 
+    %
+:- pred collect_ite_annotation_exec_path_2(rpt_graph::in,
+    reverse_goal_path::in, set(string)::in, int::in, program_point::in,
+    execution_path::in, renaming_proc::in, renaming_proc::out,
     renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
 
 collect_ite_annotation_exec_path_2(_, _, _, _, _, [], !IteRenamingProc,
         !IteAnnotationProc).
-collect_ite_annotation_exec_path_2(Graph, PathToThen, RenamedRegions,
-        HowMany, PrevPoint, [ProgPoint - _ | ProgPoint_Goals],
+collect_ite_annotation_exec_path_2(Graph, PathToThen,
+        RenamedRegions, HowMany, PrevPoint, [ProgPoint - _ | ProgPointGoals],
         !IteRenamingProc, !IteAnnotationProc) :-
-    ProgPoint = pp(_, GoalPath),
-    PathToThenSteps = goal_path_to_list(PathToThen),
-    GoalPathSteps = goal_path_to_list(GoalPath),
+    ProgPoint = pp(_, RevGoalPath),
+    RevGoalPath = rgp(RevGoalPathSteps),
+    list.reverse(RevGoalPathSteps, GoalPathSteps),
+    PathToThen = rgp(RevPathToThenSteps),
+    list.reverse(RevPathToThenSteps, PathToThenSteps),
     ( list.append(PathToThenSteps, FromThenSteps, GoalPathSteps) ->
         ( list.member(step_ite_cond, FromThenSteps) ->
             % We cannot introduce reverse renaming in the condition of
@@ -1118,10 +1122,11 @@
             % from the previous point to this point.
             ( map.search(!.IteRenamingProc, PrevPoint, PrevIteRenaming) ->
                 svmap.set(ProgPoint, PrevIteRenaming, !IteRenamingProc)
-            ;   true
+            ;
+                true
             ),
             collect_ite_annotation_exec_path_2(Graph, PathToThen,
-                RenamedRegions, HowMany, ProgPoint, ProgPoint_Goals,
+                RenamedRegions, HowMany, ProgPoint, ProgPointGoals,
                 !IteRenamingProc, !IteAnnotationProc)
         ;
             % This is the first point in the corresponding then branch, which
@@ -1133,9 +1138,9 @@
                 RenamedRegions, !IteAnnotationProc)
         )
     ;
-        collect_ite_annotation_exec_path_2(Graph, PathToThen, RenamedRegions,
-            HowMany, ProgPoint, ProgPoint_Goals, !IteRenamingProc,
-            !IteAnnotationProc)
+        collect_ite_annotation_exec_path_2(Graph, PathToThen,
+            RenamedRegions, HowMany, ProgPoint, ProgPointGoals,
+            !IteRenamingProc, !IteAnnotationProc)
     ).
 
     % The reverse renaming annotation is in the form: R = R_ite_HowMany.
@@ -1158,7 +1163,7 @@
                 make_renaming_instruction(CurrentName, RenameTo, Annotation)
             ;
                 unexpected(this_file,
-                    "introduce_reverse_renaming: more than one renaming exist.")
+                    "introduce_reverse_renaming: more than one renaming")
             )
         ;
             make_renaming_instruction(CurrentName, RegName, Annotation)
@@ -1176,4 +1181,3 @@
 this_file = "rbmm.condition_renaming.m".
 
 %-----------------------------------------------------------------------------%
-
Index: compiler/rbmm.execution_path.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.execution_path.m,v
retrieving revision 1.12
diff -u -r1.12 rbmm.execution_path.m
--- compiler/rbmm.execution_path.m	15 Dec 2010 06:29:59 -0000	1.12
+++ compiler/rbmm.execution_path.m	20 Dec 2010 07:09:31 -0000
@@ -30,8 +30,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
@@ -86,8 +85,8 @@
     list(execution_path)::out) is det.
 
 compute_execution_paths(ProcInfo0, ModuleInfo, ExecPaths) :-
-    % Fill the goals with program point information
-    fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+    % Fill the goals with program point information.
+    fill_goal_path_slots_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
     proc_info_get_goal(ProcInfo, Goal),
     ExecPaths0 = [[]],
     execution_paths_covered_goal(ProcInfo, Goal, ExecPaths0, ExecPaths).
Index: compiler/rbmm.interproc_region_lifetime.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.interproc_region_lifetime.m,v
retrieving revision 1.6
diff -u -r1.6 rbmm.interproc_region_lifetime.m
--- compiler/rbmm.interproc_region_lifetime.m	15 Dec 2010 06:29:59 -0000	1.6
+++ compiler/rbmm.interproc_region_lifetime.m	15 Dec 2010 06:33:25 -0000
@@ -59,9 +59,9 @@
 :- implementation.
 
 :- import_module check_hlds.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.type_util.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module parse_tree.
Index: compiler/rbmm.live_region_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.live_region_analysis.m,v
retrieving revision 1.6
diff -u -r1.6 rbmm.live_region_analysis.m
--- compiler/rbmm.live_region_analysis.m	15 Dec 2010 06:29:59 -0000	1.6
+++ compiler/rbmm.live_region_analysis.m	15 Dec 2010 06:33:25 -0000
@@ -40,9 +40,9 @@
 :- implementation.
 
 :- import_module check_hlds.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.type_util.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module parse_tree.
Index: compiler/rbmm.live_variable_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.live_variable_analysis.m,v
retrieving revision 1.5
diff -u -r1.5 rbmm.live_variable_analysis.m
--- compiler/rbmm.live_variable_analysis.m	15 Dec 2010 06:29:59 -0000	1.5
+++ compiler/rbmm.live_variable_analysis.m	15 Dec 2010 06:33:25 -0000
@@ -32,9 +32,9 @@
 :- implementation.
 
 :- import_module check_hlds.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.type_util.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module parse_tree.
Index: compiler/rbmm.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
retrieving revision 1.10
diff -u -r1.10 rbmm.m
--- compiler/rbmm.m	28 Nov 2009 01:58:00 -0000	1.10
+++ compiler/rbmm.m	20 Dec 2010 07:06:43 -0000
@@ -5,7 +5,7 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-% 
+%
 % File: rbmm.m.
 % Main author: quan.
 %
@@ -63,9 +63,9 @@
 do_region_analysis(!ModuleInfo, !IO) :-
     region_points_to_analysis(RptaInfoTable, !ModuleInfo),
     execution_path_analysis(!.ModuleInfo, ExecPathTable),
-    live_variable_analysis(!.ModuleInfo, ExecPathTable, LVBeforeTable, 
+    live_variable_analysis(!.ModuleInfo, ExecPathTable, LVBeforeTable,
         LVAfterTable, VoidVarTable),
-    live_region_analysis(!.ModuleInfo, RptaInfoTable, 
+    live_region_analysis(!.ModuleInfo, RptaInfoTable,
         LVBeforeTable, LVAfterTable, VoidVarTable, LRBeforeTable0,
         LRAfterTable0, VoidVarRegionTable0, InputRTable, OutputRTable,
         BornRTable0, DeadRTable0, LocalRTable0),
@@ -73,7 +73,7 @@
         ExecPathTable, LRBeforeTable0, LRAfterTable0, InputRTable,
         OutputRTable, ConstantRTable0, BornRTable0, BornRTable1,
         DeadRTable0, DeadRTable1),
-    ignore_primitive_regions(!.ModuleInfo, RptaInfoTable, 
+    ignore_primitive_regions(!.ModuleInfo, RptaInfoTable,
         BornRTable1, BornRTable, DeadRTable1, DeadRTable,
         ConstantRTable0, ConstantRTable, LocalRTable0, LocalRTable,
         LRBeforeTable0, LRBeforeTable, LRAfterTable0, LRAfterTable,
@@ -92,9 +92,9 @@
     % imperative-style updatable variables. They may also have scopes
     % which are not valid in Mercury. In order for Mercury code to
     % manipulate regions we need to map these "region variables" on to
-    % Mercury variables. 
+    % Mercury variables.
     % The calls below derive the necessary mapping to resolve the problem.
-    compute_resurrection_paths(ExecPathTable, LRBeforeTable, LRAfterTable, 
+    compute_resurrection_paths(ExecPathTable, LRBeforeTable, LRAfterTable,
         BornRTable, DeadRTable, LocalRTable,
         BecomeLiveTable, BecomeDeadBeforeTable, BecomeDeadAfterTable,
         ResurrectionPathTable0),
@@ -115,19 +115,17 @@
         RenamedRegionsTable),
     collect_ite_renaming(!.ModuleInfo, RptaInfoTable, RenamedRegionsTable,
         IteRenamingTable0),
-    collect_ite_annotation(RenamedRegionsTable, ExecPathTable, 
+    collect_ite_annotation(RenamedRegionsTable, ExecPathTable,
         RptaInfoTable, IteRenamingTable0, IteRenamingTable,
         IteRenamingAnnoTable),
-
     region_transform(RptaInfoTable, FormalRegionArgTable,
         ActualRegionArgTable, ResurRenamingTable,
         IteRenamingTable, RegionInstructionTable, ResurRenamingAnnoTable,
         IteRenamingAnnoTable, map.init, NameToVarTable, !ModuleInfo),
-    
+
     collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgTable,
         ResurRenamingTable, IteRenamingTable, NameToVarTable, !ModuleInfo).
 
 %-----------------------------------------------------------------------------%
 :- end_module transform_hlds.rbmm.
 %-----------------------------------------------------------------------------%
-
Index: compiler/rbmm.points_to_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.points_to_analysis.m,v
retrieving revision 1.15
diff -u -r1.15 rbmm.points_to_analysis.m
--- compiler/rbmm.points_to_analysis.m	15 Dec 2010 06:30:00 -0000	1.15
+++ compiler/rbmm.points_to_analysis.m	20 Dec 2010 07:07:54 -0000
@@ -47,8 +47,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
@@ -335,7 +334,7 @@
     % XXX we should only fill goal path slots once, not once per iteration.
     %
     module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
-    fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+    fill_goal_path_slots_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
 
     proc_info_get_goal(ProcInfo, Goal),
     inter_analyse_goal(ModuleInfo, InfoTable, Goal, !FPTable,
Index: compiler/rbmm.region_arguments.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_arguments.m,v
retrieving revision 1.4
diff -u -r1.4 rbmm.region_arguments.m
--- compiler/rbmm.region_arguments.m	15 Dec 2010 06:30:00 -0000	1.4
+++ compiler/rbmm.region_arguments.m	20 Dec 2010 07:09:40 -0000
@@ -69,8 +69,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module libs.
 :- import_module libs.globals.
@@ -127,7 +126,7 @@
             !FormalRegionArgTable),
 
         module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
-        fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+        fill_goal_path_slots_in_proc(ModuleInfo, ProcInfo0, ProcInfo),
         proc_info_get_goal(ProcInfo, Body),
         record_actual_region_arguments_goal(ModuleInfo, PPId,
             RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Body,
Index: compiler/rbmm.region_instruction.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_instruction.m,v
retrieving revision 1.10
diff -u -r1.10 rbmm.region_instruction.m
--- compiler/rbmm.region_instruction.m	15 Dec 2010 06:30:00 -0000	1.10
+++ compiler/rbmm.region_instruction.m	15 Dec 2010 06:33:25 -0000
@@ -108,8 +108,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_llds.
Index: compiler/rbmm.region_transformation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_transformation.m,v
retrieving revision 1.14
diff -u -r1.14 rbmm.region_transformation.m
--- compiler/rbmm.region_transformation.m	15 Dec 2010 06:30:00 -0000	1.14
+++ compiler/rbmm.region_transformation.m	20 Dec 2010 07:09:51 -0000
@@ -73,10 +73,10 @@
 :- implementation.
 
 :- import_module check_hlds.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.mode_util.
 :- import_module check_hlds.purity.
 :- import_module check_hlds.type_util.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
@@ -217,7 +217,7 @@
         PredId, ProcId, !NameToVarTable, !ModuleInfo) :-
     PPId = proc(PredId, ProcId),
     module_info_pred_proc_info(!.ModuleInfo, PPId, PredInfo0, ProcInfo0),
-    fill_goal_path_slots(!.ModuleInfo, ProcInfo0, ProcInfo1),
+    fill_goal_path_slots_in_proc(!.ModuleInfo, ProcInfo0, ProcInfo1),
     proc_info_get_varset(ProcInfo1, VarSet0),
     proc_info_get_vartypes(ProcInfo1, VarTypes0),
     proc_info_get_headvars(ProcInfo1, HeadVars0),
Index: compiler/smm_common.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/smm_common.m,v
retrieving revision 1.6
diff -u -r1.6 smm_common.m
--- compiler/smm_common.m	4 Sep 2008 11:41:01 -0000	1.6
+++ compiler/smm_common.m	9 Dec 2010 05:19:28 -0000
@@ -10,7 +10,7 @@
 % Main author: Quan Phan.
 %
 % This module contains defines types and procedures that are common to
-% various static memory mangement analyses, e.g. CTGC, RBMM.
+% various static memory management analyses, e.g. CTGC, RBMM.
 %
 %-----------------------------------------------------------------------------%
 
@@ -24,7 +24,7 @@
 :- import_module mdbcomp.
 :- import_module mdbcomp.program_representation.
 :- import_module parse_tree.
-:- import_module parse_tree.prog_data. 
+:- import_module parse_tree.prog_data.
 
 :- import_module io.
 :- import_module list.
@@ -34,32 +34,32 @@
 
     % Succeeds if the selector selects the type node of the input type.
     %
-:- pred check_type_of_node(module_info::in, mer_type::in, selector::in) 
+:- pred check_type_of_node(module_info::in, mer_type::in, selector::in)
     is semidet.
 
     % Succeeds if some (or all) of the procedures in the list are special.
     %
-:- pred some_are_special_preds(list(pred_proc_id)::in, module_info::in) 
+:- pred some_are_special_preds(list(pred_proc_id)::in, module_info::in)
     is semidet.
 
 %-----------------------------------------------------------------------------%
 %
-% Definition of a program point
+% Definition of a program point.
 %
-    
-    % A program point records the place at which a data structure possibly
-    % becomes garbage. 
-    %
-:- type program_point 
-    ---> 	pp( 
-                pp_context	:: term.context, 
-                pp_path		:: goal_path
+
+    % A program point identifies a place at which a data structure possibly
+    % becomes garbage.
+    %
+:- type program_point
+    --->    pp(
+                pp_context  :: term.context,
+                pp_id       :: reverse_goal_path
             ).
-    
-    % Compute the program point from the given goal_info. 
+
+    % Compute the program point from the given goal_info.
     %
 :- func program_point_init(hlds_goal_info) = program_point.
-    
+
     % Dump the information contained in a program point.
     %
 :- pred dump_program_point(program_point::in, io::di, io::uo) is det.
@@ -70,7 +70,7 @@
 :- implementation.
 
 :- import_module check_hlds.
-:- import_module check_hlds.type_util. 
+:- import_module check_hlds.type_util.
 :- import_module ll_backend.
 :- import_module ll_backend.liveness.
 :- import_module parse_tree.prog_out.
@@ -82,105 +82,74 @@
 
 %-----------------------------------------------------------------------------%
 
-	% Check if the selector is valid w.r.t the type.
+    % Check if the selector is valid w.r.t the type.
     %
 check_type_of_node(ModuleInfo, StartType, Selector) :-
-	(
-		Selector = [Sel | Sels],
-		(
-			Sel = termsel(Cons_id, Choice),
-			select_subtype(ModuleInfo, StartType, Cons_id, Choice, SubType) 
-		; 
-			Sel = typesel(SubType)
-		),
-		check_type_of_node(ModuleInfo, SubType, Sels)
-	;
-		Selector = []
-	).
-
-	% Select the subtype of a type Type, selecting ConsId's position
-	% Position. Position counts starting from 1 (instead of 0). 
-	% Predicate aborts if the subtype cannot be determined. 
+    (
+        Selector = [Sel | Sels],
+        (
+            Sel = termsel(Cons_id, Choice),
+            select_subtype(ModuleInfo, StartType, Cons_id, Choice, SubType)
+        ;
+            Sel = typesel(SubType)
+        ),
+        check_type_of_node(ModuleInfo, SubType, Sels)
+    ;
+        Selector = []
+    ).
+
+    % Select the subtype of a type Type, selecting ConsId's position Position.
+    % Position counts starting from 1 (instead of 0).
+    % The predicate aborts if the subtype cannot be determined.
     %
-:- pred select_subtype(module_info::in, mer_type::in, cons_id::in, int::in, 
+:- pred select_subtype(module_info::in, mer_type::in, cons_id::in, int::in,
     mer_type::out) is semidet.
 
 select_subtype(ModuleInfo, Type, ConsId, Choice, SubType) :-
-	get_cons_id_non_existential_arg_types(ModuleInfo, Type, ConsId, ArgTypes),
-	list.index1(ArgTypes, Choice, SubType).
+    get_cons_id_non_existential_arg_types(ModuleInfo, Type, ConsId, ArgTypes),
+    list.index1(ArgTypes, Choice, SubType).
 
-    % Special predicates are either compiler-generated ones, such as 
-    % __Unify__ and others or ones that are not defined in the module. 
+    % Special predicates are either compiler-generated ones, such as
+    % __Unify__ and others or ones that are not defined in the module.
     %
-some_are_special_preds(PPIds, ModuleInfo) :- 
-	module_info_get_special_pred_map(ModuleInfo, SpecialPredMap), 
-	map.values(SpecialPredMap, SpecialPredIds), 
-	(
-		list.filter(pred(PPId::in) is semidet :- (
-                        PPId = proc(PredId, _),
-                        list.member(PredId, SpecialPredIds)
-                    ),
-                    PPIds, SpecialPPIds),
-		SpecialPPIds = [_ | _]
-	; 
-		list.filter(proc_not_defined_in_module(ModuleInfo),	PPIds,
-            FilteredPPIds), 
-		FilteredPPIds = [_ | _]
-	).
+some_are_special_preds(PPIds, ModuleInfo) :-
+    module_info_get_special_pred_map(ModuleInfo, SpecialPredMap),
+    map.values(SpecialPredMap, SpecialPredIds),
+    (
+        list.filter(
+            pred(PPId::in) is semidet :- (
+                PPId = proc(PredId, _),
+                list.member(PredId, SpecialPredIds)
+            ),
+            PPIds, SpecialPPIds),
+        SpecialPPIds = [_ | _]
+    ;
+        list.filter(proc_not_defined_in_module(ModuleInfo), PPIds,
+            FilteredPPIds),
+        FilteredPPIds = [_ | _]
+    ).
 
-:- pred proc_not_defined_in_module(module_info::in, pred_proc_id::in) 
+:- pred proc_not_defined_in_module(module_info::in, pred_proc_id::in)
     is semidet.
 
 proc_not_defined_in_module(ModuleInfo, proc(PredId, _)):-
-	module_info_pred_info(ModuleInfo, PredId, PredInfo),
-	pred_info_get_import_status(PredInfo, Status),
-	status_defined_in_this_module(Status) = no.
+    module_info_pred_info(ModuleInfo, PredId, PredInfo),
+    pred_info_get_import_status(PredInfo, Status),
+    status_defined_in_this_module(Status) = no.
 
-	% Note: for a meaningful use of this predicate the goal needs to be 
-    % filled with path information, i.e. call to fill_goal_path_slots(...).
+    % Note: for a meaningful use of this predicate the goal needs to be
+    % filled with goal id information, i.e. call to fill_goal_id_slots(...).
     %
 program_point_init(GoalInfo) = ProgPoint :-
-	Context = goal_info_get_context(GoalInfo),
-	GoalPath = goal_info_get_goal_path(GoalInfo),
-	ProgPoint = pp(Context, GoalPath).
+    Context = goal_info_get_context(GoalInfo),
+    RevGoalPath = goal_info_get_reverse_goal_path(GoalInfo),
+    ProgPoint = pp(Context, RevGoalPath).
 
-dump_program_point(pp(Context, GoalPath), !IO):- 
-    prog_out.write_context(Context, !IO), 
+dump_program_point(pp(Context, RevGoalPath), !IO):-
+    prog_out.write_context(Context, !IO),
     io.write_string("--", !IO),
-    GoalPathSteps = goal_path_to_list(GoalPath),
-    list.foldl(dump_goal_path_step, GoalPathSteps, !IO).
-
-:- pred dump_goal_path_step(goal_path_step::in, io::di, io::uo) is det.
+    io.write_string(rev_goal_path_to_string(RevGoalPath), !IO).
 
-dump_goal_path_step(step_conj(N)) -->
-    io.write_char('c'),
-    io.write_int(N).
-dump_goal_path_step(step_disj(N)) -->
-    io.write_char('d'),
-    io.write_int(N).
-dump_goal_path_step(step_switch(N, _)) -->
-    io.write_char('s'),
-    io.write_int(N).
-dump_goal_path_step(step_ite_cond) -->
-    io.write_char('c').
-dump_goal_path_step(step_ite_then) -->
-    io.write_char('t').
-dump_goal_path_step(step_ite_else) -->
-    io.write_char('e').
-dump_goal_path_step(step_neg) -->
-    io.write_char('n').
-dump_goal_path_step(step_scope(_)) -->
-    io.write_char('q').
-dump_goal_path_step(step_first) -->
-    io.write_char('f').
-dump_goal_path_step(step_later) -->
-    io.write_char('l').
-dump_goal_path_step(step_atomic_main) -->
-    io.write_char('a').
-dump_goal_path_step(step_atomic_orelse(N)) -->
-    io.write_char('o'),
-    io.write_int(N).
-	
 %-----------------------------------------------------------------------------%
 :- end_module smm_common.
 %-----------------------------------------------------------------------------%
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.152
diff -u -r1.152 stack_layout.m
--- compiler/stack_layout.m	15 Dec 2010 06:30:02 -0000	1.152
+++ compiler/stack_layout.m	15 Dec 2010 06:33:26 -0000
@@ -513,8 +513,8 @@
     ).
 
 :- pred find_valid_return_context(
-    assoc_list(code_addr, pair(prog_context, goal_path))::in,
-    code_addr::out, prog_context::out, goal_path::out) is semidet.
+    assoc_list(code_addr, pair(prog_context, forward_goal_path))::in,
+    code_addr::out, prog_context::out, forward_goal_path::out) is semidet.
 
 find_valid_return_context([TargetContext | TargetContexts],
         ValidTarget, ValidContext, ValidGoalPath) :-
Index: compiler/stack_opt.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/stack_opt.m,v
retrieving revision 1.45
diff -u -r1.45 stack_opt.m
--- compiler/stack_opt.m	15 Dec 2010 06:30:02 -0000	1.45
+++ compiler/stack_opt.m	15 Dec 2010 06:33:26 -0000
@@ -86,10 +86,10 @@
 
 :- import_module backend_libs.interval.
 :- import_module backend_libs.matching.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.mode_util.
 :- import_module check_hlds.simplify.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_llds.
@@ -150,7 +150,7 @@
                 cons_id,
                 list(prog_var),
                 set(prog_var),
-                goal_path,
+                goal_id,
                 set(interval_id),
                 set(interval_id),
                 set(anchor),
@@ -180,7 +180,7 @@
         OptNoReturnCalls),
     AllocData = alloc_data(!.ModuleInfo, !.ProcInfo, TypeInfoLiveness,
         OptNoReturnCalls),
-    fill_goal_path_slots(!.ModuleInfo, !ProcInfo),
+    fill_goal_id_slots_in_proc(!.ModuleInfo, _, !ProcInfo),
     proc_info_get_goal(!.ProcInfo, Goal2),
     OptStackAlloc0 = init_opt_stack_alloc,
     set.init(FailVars),
@@ -268,8 +268,7 @@
     globals.lookup_bool_option(Globals,
         optimize_saved_vars_cell_include_all_candidates, InclAllCand),
     MatchingParams = matching_params(CellVarStoreCost, CellVarLoadCost,
-        FieldVarStoreCost, FieldVarLoadCost, OpRatio, NodeRatio,
-        InclAllCand),
+        FieldVarStoreCost, FieldVarLoadCost, OpRatio, NodeRatio, InclAllCand),
     globals.lookup_int_option(Globals,
         optimize_saved_vars_cell_all_path_node_ratio,
         AllPathNodeRatio),
@@ -562,9 +561,9 @@
             PotentialAnchorList, !IntervalInfo, !StackOptInfo,
             set.init, InsertAnchors),
         Goal = hlds_goal(_, GoalInfo),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
+        GoalId = goal_info_get_goal_id(GoalInfo),
         MatchingResult = matching_result(CellVar, ConsId,
-            ArgVars, ViaCellVars, GoalPath,
+            ArgVars, ViaCellVars, GoalId,
             PotentialIntervals, InsertIntervals,
             PotentialAnchors, InsertAnchors),
         MatchingResults0 = !.StackOptInfo ^ soi_matching_results,
@@ -704,9 +703,9 @@
 
 anchor_requires_close(_, anchor_proc_start) = no.
 anchor_requires_close(_, anchor_proc_end) = yes.
-anchor_requires_close(IntervalInfo, anchor_branch_start(_, GoalPath)) =
+anchor_requires_close(IntervalInfo, anchor_branch_start(_, GoalId)) =
         resume_save_status_requires_close(ResumeSaveStatus) :-
-    map.lookup(IntervalInfo ^ ii_branch_resume_map, GoalPath,
+    map.lookup(IntervalInfo ^ ii_branch_resume_map, GoalId,
         ResumeSaveStatus).
 anchor_requires_close(_, anchor_cond_then(_)) = no.
 anchor_requires_close(_, anchor_branch_end(BranchType, _)) = NeedsClose :-
@@ -822,8 +821,8 @@
         ->
             !:AllPaths = !.AllPaths ^ used_after_scope := set.init
         ;
-            End = anchor_branch_end(_, EndGoalPath),
-            map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalPath,
+            End = anchor_branch_end(_, EndGoalId),
+            map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalId,
                 BranchEndInfo),
             OnStackAfterBranch = BranchEndInfo ^ flushed_after_branch,
             AccessedAfterBranch = BranchEndInfo ^ accessed_after_branch,
@@ -859,19 +858,19 @@
     FullPath = StackOptParams ^ sop_full_path,
     (
         FullPath = yes,
-        End = anchor_branch_start(branch_disj, EndGoalPath)
+        End = anchor_branch_start(branch_disj, EndGoalId)
     ->
-        MaybeSearchAnchor1 = yes(anchor_branch_end(branch_disj, EndGoalPath)),
+        MaybeSearchAnchor1 = yes(anchor_branch_end(branch_disj, EndGoalId)),
         one_after_another(RelevantVars, MaybeSearchAnchor1,
             IntervalInfo, StackOptInfo, SuccessorIds, !AllPaths),
-        map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalPath,
+        map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalId,
             BranchEndInfo),
         ContinueId = BranchEndInfo ^ interval_after_branch,
         apply_interval_find_all_branches(RelevantVars, MaybeSearchAnchor0,
             IntervalInfo, StackOptInfo, ContinueId, !AllPaths)
     ;
         FullPath = yes,
-        End = anchor_branch_start(branch_ite, EndGoalPath)
+        End = anchor_branch_start(branch_ite, EndGoalId)
     ->
         ( SuccessorIds = [ElseStartIdPrime, CondStartIdPrime] ->
             ElseStartId = ElseStartIdPrime,
@@ -880,29 +879,29 @@
             unexpected(this_file,
                 "find_all_branches_from: ite not else, cond")
         ),
-        MaybeSearchAnchorCond = yes(anchor_cond_then(EndGoalPath)),
+        MaybeSearchAnchorCond = yes(anchor_cond_then(EndGoalId)),
         apply_interval_find_all_branches(RelevantVars,
             MaybeSearchAnchorCond, IntervalInfo, StackOptInfo,
             CondStartId, !AllPaths),
-        MaybeSearchAnchorEnd = yes(anchor_branch_end(branch_ite, EndGoalPath)),
+        MaybeSearchAnchorEnd = yes(anchor_branch_end(branch_ite, EndGoalId)),
         CondEndMap = IntervalInfo ^ ii_cond_end_map,
-        map.lookup(CondEndMap, EndGoalPath, ThenStartId),
+        map.lookup(CondEndMap, EndGoalId, ThenStartId),
         one_after_another(RelevantVars, MaybeSearchAnchorEnd,
             IntervalInfo, StackOptInfo, [ThenStartId, ElseStartId], !AllPaths),
-        map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalPath,
+        map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalId,
             BranchEndInfo),
         ContinueId = BranchEndInfo ^ interval_after_branch,
         apply_interval_find_all_branches(RelevantVars, MaybeSearchAnchor0,
             IntervalInfo, StackOptInfo, ContinueId, !AllPaths)
     ;
-        End = anchor_branch_start(BranchType, EndGoalPath)
+        End = anchor_branch_start(BranchType, EndGoalId)
     ->
-        MaybeSearchAnchor1 = yes(anchor_branch_end(BranchType, EndGoalPath)),
+        MaybeSearchAnchor1 = yes(anchor_branch_end(BranchType, EndGoalId)),
         list.map(apply_interval_find_all_branches_map(RelevantVars,
             MaybeSearchAnchor1, IntervalInfo, StackOptInfo, !.AllPaths),
             SuccessorIds, AllPathsList),
         consolidate_after_join(AllPathsList, !:AllPaths),
-        map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalPath,
+        map.lookup(IntervalInfo ^ ii_branch_end_map, EndGoalId,
             BranchEndInfo),
         ContinueId = BranchEndInfo ^ interval_after_branch,
         apply_interval_find_all_branches(RelevantVars, MaybeSearchAnchor0,
@@ -1081,10 +1080,10 @@
 
 dump_matching_result(MatchingResult, !IO) :-
     MatchingResult = matching_result(CellVar, ConsId, ArgVars, ViaCellVars,
-        GoalPath, PotentialIntervals, InsertIntervals,
+        GoalId, PotentialIntervals, InsertIntervals,
         PotentialAnchors, InsertAnchors),
     io.write_string("\nmatching result at ", !IO),
-    io.write(GoalPath, !IO),
+    io.write(GoalId, !IO),
     io.write_string("\n", !IO),
     term.var_to_int(CellVar, CellVarNum),
     list.map(term.var_to_int, ArgVars, ArgVarNums),
Index: compiler/structure_reuse.analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.analysis.m,v
retrieving revision 1.26
diff -u -r1.26 structure_reuse.analysis.m
--- compiler/structure_reuse.analysis.m	15 Dec 2010 06:30:03 -0000	1.26
+++ compiler/structure_reuse.analysis.m	20 Dec 2010 04:40:11 -0000
@@ -63,7 +63,7 @@
     % Perform structure reuse analysis on the procedures defined in the
     % current module.
     %
-:- pred structure_reuse_analysis(module_info::in, module_info::out,
+:- pred perform_structure_reuse_analysis(module_info::in, module_info::out,
     io::di, io::uo) is det.
 
     % Write all the reuse information concerning the specified predicate as
@@ -97,7 +97,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_out.
 :- import_module hlds.hlds_out.hlds_out_util.
 :- import_module hlds.passes_aux.
@@ -125,6 +125,7 @@
 :- import_module bimap.
 :- import_module bool.
 :- import_module int.
+:- import_module io.
 :- import_module list.
 :- import_module map.
 :- import_module maybe.
@@ -136,7 +137,7 @@
 
 %-----------------------------------------------------------------------------%
 
-structure_reuse_analysis(!ModuleInfo, !IO):-
+perform_structure_reuse_analysis(!ModuleInfo, !IO):-
     module_info_get_globals(!.ModuleInfo, Globals),
     globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
 
@@ -172,7 +173,7 @@
         !:ReuseTable = ReuseTable0,
 
         % Pre-annotate each of the goals with "Local Forward Use" and
-        % "Local Backward Use" information, and fill in all the goal_path slots
+        % "Local Backward Use" information, and fill in all the goal_id slots
         % as well.
         trace [io(!IO)] (
             maybe_write_string(VeryVerbose,
@@ -181,9 +182,14 @@
         process_all_nonimported_procs(update_proc(annotate_in_use_information),
             !ModuleInfo),
         trace [io(!IO)] (
-            maybe_write_string(VeryVerbose, "done.\n", !IO)
+            maybe_write_string(VeryVerbose, "done.\n", !IO),
+            maybe_write_string(VeryVerbose,
+                "% Reuse table before intermediate reuse:\n", !IO),
+            reuse_as_table_maybe_dump(VeryVerbose, !.ModuleInfo, !.ReuseTable,
+                !IO)
         ),
 
+
         % Create copies of externally requested procedures.  This must be done
         % after the in-use annotations have been added to the procedures being
         % copied.
@@ -192,6 +198,10 @@
 
         % Determine information about possible direct reuses.
         trace [io(!IO)] (
+            maybe_write_string(VeryVerbose,
+                "% Reuse table after intermediate reuse:\n", !IO),
+            reuse_as_table_maybe_dump(VeryVerbose, !.ModuleInfo, !.ReuseTable,
+                !IO),
             maybe_write_string(VeryVerbose, "% Direct reuse...\n", !IO)
         ),
         direct_reuse_pass(SharingTable, !ModuleInfo, !ReuseTable),
@@ -220,8 +230,8 @@
             !ReuseTable, !ModuleInfo, DepProcs0, DepProcs,
             IntermodRequests0, IntermodRequests),
 
-        % Create reuse versions of procedures.  Update goals to reuse cells and
-        % call reuse versions of procedures.
+        % Create reuse versions of procedures.  Update goals to reuse cells
+        % and call reuse versions of procedures.
         create_reuse_procedures(!ReuseTable, !ModuleInfo),
 
         ReuseTable = !.ReuseTable
@@ -746,7 +756,7 @@
 annotate_in_use_information(ModuleInfo, !ProcInfo) :-
     forward_use_information(!ProcInfo),
     backward_use_information(ModuleInfo, !ProcInfo),
-    fill_goal_path_slots(ModuleInfo, !ProcInfo).
+    fill_goal_path_slots_in_proc(ModuleInfo, !ProcInfo).
 
 %-----------------------------------------------------------------------------%
 %
Index: compiler/structure_reuse.direct.detect_garbage.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.direct.detect_garbage.m,v
retrieving revision 1.23
diff -u -r1.23 structure_reuse.direct.detect_garbage.m
--- compiler/structure_reuse.direct.detect_garbage.m	15 Dec 2010 06:30:04 -0000	1.23
+++ compiler/structure_reuse.direct.detect_garbage.m	20 Dec 2010 03:35:29 -0000
@@ -74,8 +74,8 @@
     Background = detect_bg_info_init(ModuleInfo, PredInfo, ProcInfo,
         SharingTable),
     % In this process we need to know the sharing at each program point,
-    % which boils down to reconstructing that sharing information based on the
-    % sharing recorded in the sharing table.
+    % which boils down to reconstructing that sharing information based on
+    % the sharing recorded in the sharing table.
     determine_dead_deconstructions_2(Background, Goal,
         sharing_as_init, _, dead_cell_table_init, DeadCellTable),
 
@@ -90,8 +90,8 @@
         VeryVerbose = no
     ).
 
-    % Process a procedure goal, determining the sharing at each subgoal, as
-    % well as constructing the table of dead cells.
+    % Process a procedure goal, determining the sharing at each subgoal,
+    % as well as constructing the table of dead cells.
     %
     % This means:
     %   - at each program point: compute sharing
@@ -122,9 +122,8 @@
             GenDetails, CallArgs, Modes, GoalInfo, !SharingAs)
     ;
         GoalExpr = unify(_, _, _, Unification, _),
-        unification_verify_reuse(ModuleInfo, ProcInfo, GoalInfo,
-            Unification, program_point_init(GoalInfo), !.SharingAs,
-            !DeadCellTable),
+        unification_verify_reuse(ModuleInfo, ProcInfo, GoalInfo, Unification,
+            program_point_init(GoalInfo), !.SharingAs, !DeadCellTable),
         !:SharingAs = add_unify_sharing(ModuleInfo, ProcInfo, Unification,
             GoalInfo, !.SharingAs)
     ;
@@ -148,10 +147,10 @@
                 !DeadCellTable)
         )
     ;
-        GoalExpr = if_then_else(_, IfGoal, ThenGoal, ElseGoal),
-        determine_dead_deconstructions_2(Background, IfGoal, !.SharingAs,
-            IfSharingAs, !DeadCellTable),
-        determine_dead_deconstructions_2(Background, ThenGoal, IfSharingAs,
+        GoalExpr = if_then_else(_, CondGoal, ThenGoal, ElseGoal),
+        determine_dead_deconstructions_2(Background, CondGoal, !.SharingAs,
+            CondSharingAs, !DeadCellTable),
+        determine_dead_deconstructions_2(Background, ThenGoal, CondSharingAs,
             ThenSharingAs, !DeadCellTable),
         determine_dead_deconstructions_2(Background, ElseGoal, !.SharingAs,
             ElseSharingAs, !DeadCellTable),
@@ -264,8 +263,8 @@
         LFU = goal_info_get_lfu(GoalInfo),
         LBU = goal_info_get_lbu(GoalInfo),
         (
-            % Reuse is only relevant for real constructors, with
-            % arity different from 0.
+            % Reuse is only relevant for real constructors, with nonzero
+            % arities.
             ConsId = cons(_, Arity, _),
             Arity \= 0,
 
@@ -282,12 +281,11 @@
             % Check the live set of data structures at this program point.
             var_not_live(ModuleInfo, ProcInfo, GoalInfo, Sharing, Var)
         ->
-            % If all the above conditions are met, then the top
-            % cell data structure based on Var is dead right after
-            % this deconstruction, hence, may be involved with
-            % structure reuse.
-            NewCondition = reuse_condition_init(ModuleInfo,
-                ProcInfo, Var, LFU, LBU, Sharing),
+            % If all the above conditions are met, then the top cell
+            % data structure based on Var is dead right after this
+            % deconstruction, which means it may be reused.
+            NewCondition = reuse_condition_init(ModuleInfo, ProcInfo, Var,
+                LFU, LBU, Sharing),
             dead_cell_table_set(PP, NewCondition, !DeadCellTable)
         ;
             true
Index: compiler/structure_reuse.direct.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.direct.m,v
retrieving revision 1.15
diff -u -r1.15 structure_reuse.direct.m
--- compiler/structure_reuse.direct.m	30 Jul 2010 05:16:16 -0000	1.15
+++ compiler/structure_reuse.direct.m	20 Dec 2010 03:29:05 -0000
@@ -148,8 +148,8 @@
         !.ModuleInfo, Pred0, Proc0, Proc, ReuseAs),
     % XXX is this right?
     Status = optimal,
-    reuse_as_table_set(proc(PredId, ProcId),
-        reuse_as_and_status(ReuseAs, Status), !ReuseTable),
+    AsAndStatus = reuse_as_and_status(ReuseAs, Status),
+    reuse_as_table_set(proc(PredId, ProcId), AsAndStatus, !ReuseTable),
 
     map.det_update(Procs0, ProcId, Proc, Procs),
     pred_info_set_procedures(Procs, Pred0, Pred),
Index: compiler/structure_reuse.domain.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.domain.m,v
retrieving revision 1.23
diff -u -r1.23 structure_reuse.domain.m
--- compiler/structure_reuse.domain.m	15 Dec 2010 06:30:04 -0000	1.23
+++ compiler/structure_reuse.domain.m	20 Dec 2010 04:10:21 -0000
@@ -10,7 +10,7 @@
 % Main authors: nancy.
 %
 % Definition of the abstract domain for keeping track of opportunities for
-% structure reuse. 
+% structure reuse.
 %
 %-----------------------------------------------------------------------------%
 
@@ -25,24 +25,24 @@
 :- import_module transform_hlds.ctgc.structure_sharing.domain.
 
 :- import_module bimap.
-:- import_module bool. 
-:- import_module io. 
-:- import_module map. 
+:- import_module bool.
+:- import_module io.
+:- import_module map.
 :- import_module set.
 :- import_module list.
 
 %-----------------------------------------------------------------------------%
 
-    % A reuse condition stores all the necessary information to check if 
+    % A reuse condition stores all the necessary information to check if
     % a procedure call is safe w.r.t. a structure reuse opportunity within
-    % the body of the called procedure. 
+    % the body of the called procedure.
     %
-:- type reuse_condition. 
+:- type reuse_condition.
 :- type reuse_conditions == list(reuse_condition).
 
     % Abstract representation for a set of reuse conditions.
     %
-:- type reuse_as. 
+:- type reuse_as.
 
 %-----------------------------------------------------------------------------%
 %
@@ -56,14 +56,14 @@
     % local forward and backward use, as well as the local structure sharing.
     %
 :- func reuse_condition_init(module_info, proc_info, dead_var,
-    set(live_var), set(live_var), sharing_as) = reuse_condition. 
+    set(live_var), set(live_var), sharing_as) = reuse_condition.
 
 :- pred reuse_condition_is_conditional(reuse_condition::in) is semidet.
 
 :- pred reuse_condition_reusable_nodes(reuse_condition::in,
     dead_datastructs::out) is semidet.
 
-    % Renaming operation. 
+    % Renaming operation.
     % This operation renames all occurrences of program variables and
     % type variables according to a program and type variable mapping.
     %
@@ -71,8 +71,8 @@
     reuse_condition::in, reuse_condition::out) is det.
 
     % Succeeds if the first condition is subsumed by the second one, i.e.,
-    % if a procedure call verifies the second condition, then it also 
-    % verifies the first condition. 
+    % if a procedure call verifies the second condition, then it also
+    % verifies the first condition.
     %
 :- pred reuse_condition_subsumed_by(module_info::in, proc_info::in,
     reuse_condition::in, reuse_condition::in) is semidet.
@@ -82,10 +82,10 @@
 %
 % XXX The implementation of this type has changed wrt. its counterpart in the
 % reuse branch (called memo_reuse). While memo_reuse's didn't always keep a
-% minimal representation, reuse_as does. 
+% minimal representation, reuse_as does.
 %
 
-    % Create an initial set of reuse descriptions. 
+    % Create an initial set of reuse descriptions.
     %
 :- func reuse_as_init = reuse_as.
 :- func reuse_as_init_with_one_condition(reuse_condition) = reuse_as.
@@ -96,16 +96,16 @@
 
     % Succeeds if the first reuses description is subsumed by the second
     % description, i.e., if a procedure call satisfies all the conditions
-    % expressed by the second reuses description, then it also satisfies all 
-    % the conditions expressed by the first reuses description. 
+    % expressed by the second reuses description, then it also satisfies all
+    % the conditions expressed by the first reuses description.
     %
-:- pred reuse_as_subsumed_by(module_info::in, proc_info::in, reuse_as::in, 
+:- pred reuse_as_subsumed_by(module_info::in, proc_info::in, reuse_as::in,
     reuse_as::in) is semidet.
 
 :- pred reuse_as_and_status_subsumed_by(module_info::in, proc_info::in,
     reuse_as_and_status::in, reuse_as_and_status::in) is semidet.
 
-    % Tests to see whether the reuses description describes no reuses at all, 
+    % Tests to see whether the reuses description describes no reuses at all,
     % only unconditional reuses, or conditional reuses resp.
     %
 :- pred reuse_as_no_reuses(reuse_as::in) is semidet.
@@ -119,16 +119,16 @@
     %
     % Renaming of the formal description of structure reuse conditions to the
     % actual description of these conditions. The information about the formal
-    % variables needs to be extracted from the module information. 
-    % The actual names are determined by the actual variables names, the 
-    % actual types, and the type-variables occurring in those types. 
+    % variables needs to be extracted from the module information.
+    % The actual names are determined by the actual variables names, the
+    % actual types, and the type-variables occurring in those types.
     %
-:- pred reuse_as_rename_using_module_info(module_info::in, 
+:- pred reuse_as_rename_using_module_info(module_info::in,
     pred_proc_id::in, prog_vars::in, list(mer_type)::in, tvarset::in,
     head_type_params::in, reuse_as::in, reuse_as::out) is det.
 
-    % Given a variable and type variable mapping, rename the reuses 
-    % conditions accordingly. 
+    % Given a variable and type variable mapping, rename the reuses
+    % conditions accordingly.
     %
 :- pred reuse_as_rename(prog_var_renaming::in, tsubst::in, reuse_as::in,
     reuse_as::out) is det.
@@ -137,33 +137,33 @@
     % module_info and proc_info are needed to verify subsumption before adding
     % the new condition.
     %
-:- pred reuse_as_add_condition(module_info::in, proc_info::in, 
+:- pred reuse_as_add_condition(module_info::in, proc_info::in,
     reuse_condition::in, reuse_as::in, reuse_as::out) is det.
-    
+
     % A shortcut version of the above procedure when the additional condition
-    % is "unconditional". 
+    % is "unconditional".
     %
 :- pred reuse_as_add_unconditional(reuse_as::in, reuse_as::out) is det.
 
-    % Compute the least upper bound of two reuses descriptions. Module_info 
+    % Compute the least upper bound of two reuses descriptions. Module_info
     % and proc_info are needed for verifying subsumption.
     %
-:- pred reuse_as_least_upper_bound(module_info::in, proc_info::in, 
+:- pred reuse_as_least_upper_bound(module_info::in, proc_info::in,
     reuse_as::in, reuse_as::in, reuse_as::out) is det.
-:- func reuse_as_least_upper_bound(module_info, proc_info, reuse_as, 
+:- func reuse_as_least_upper_bound(module_info, proc_info, reuse_as,
     reuse_as) = reuse_as.
 
     % reuse_as_from_called_procedure_to_local_reuse_as(ModuleInfo,
-    %   ProcInfo, HeadVars, InUseData, SharingAs, CalledReuseAs) = 
+    %   ProcInfo, HeadVars, InUseData, SharingAs, CalledReuseAs) =
     %       LocalReuseAs.
     %
-    % Translate the reuse description of a called procedure to the 
+    % Translate the reuse description of a called procedure to the
     % environment of the caller. This means taking into account the local
-    % sets of in use variables, as well as the local sharing. 
+    % sets of in use variables, as well as the local sharing.
     %
     % Pre-condition: the reuse description of the called procedure is already
     % correctly renamed to the caller's environment.
-    % Pre-condition: the reuse_as from the called procedure contains at 
+    % Pre-condition: the reuse_as from the called procedure contains at
     % least one conditional reuse condition.
     %
 :- func reuse_as_from_called_procedure_to_local_reuse_as(module_info,
@@ -174,7 +174,7 @@
     % the associated memory reuses safe for that particular calling
     % environment. If the conditions are not satisfied, return the
     % variables which caused one of the conditions to be violated.
-    % 
+    %
 :- pred reuse_as_satisfied(module_info::in, proc_info::in, livedata::in,
     sharing_as::in, prog_vars::in, reuse_as::in, reuse_satisfied_result::out)
     is det.
@@ -198,8 +198,8 @@
             % arguments for reuse have sharing between them which would lead
             % to undefined behaviour in the reuse version of the procedure.
 
-    % Conversion procedures between the public (structure_reuse_domain) 
-    % and private (reuse_as) representation for structure reuse conditions. 
+    % Conversion procedures between the public (structure_reuse_domain)
+    % and private (reuse_as) representation for structure reuse conditions.
     %
 :- func from_structure_reuse_domain(structure_reuse_domain) = reuse_as.
 :- func to_structure_reuse_domain(reuse_as) = structure_reuse_domain.
@@ -239,7 +239,7 @@
 
 :- func reuse_as_table_init = reuse_as_table.
 
-:- pred reuse_as_table_search(reuse_as_table::in, pred_proc_id::in, 
+:- pred reuse_as_table_search(reuse_as_table::in, pred_proc_id::in,
     reuse_as_and_status::out) is semidet.
 
 :- pred reuse_as_table_search_reuse_version_proc(reuse_as_table::in,
@@ -248,7 +248,7 @@
 :- pred reuse_as_table_reverse_search_reuse_version_proc(reuse_as_table::in,
     pred_proc_id::in, pred_proc_id::out, list(int)::out) is det.
 
-:- pred reuse_as_table_set(pred_proc_id::in, reuse_as_and_status::in, 
+:- pred reuse_as_table_set(pred_proc_id::in, reuse_as_and_status::in,
     reuse_as_table::in, reuse_as_table::out) is det.
 
 :- pred reuse_as_table_insert_reuse_version_proc(pred_proc_id::in,
@@ -285,69 +285,74 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type reuse_condition 
-    --->    always      % The reuse is always safe and does not actually
-                        % have a condition.
+:- type reuse_condition
+    --->    always
+            % The reuse is always safe and does not actually have a condition.
+
     ;       condition(
+                % Description of the datastructures pointing to the memory
+                % that can be reused within a procedure.
                 reuseable_nodes     ::  dead_datastructs,
-                    % Description of the datastructures pointing to the 
-                    % memory that can be reused within a procedure. 
+
+                % Set of (headvar-related) datastructures that are
+                % inherently live at the place where the reuse is decided.
                 local_use_headvars  ::  live_datastructs,
-                    % Set of (headvar-related) datastructures that are 
-                    % inherently live at the place where the reuse is
-                    % decided. 
+
+                % Description of the (headvar-related) structure sharing
+                % that exists at the place where the reuse is decided.
                 local_sharing_headvars  ::  sharing_as
-                    % Description of the (headvar-related) structure sharing
-                    % that exists at the place where the reuse is decided.
             ).
 
 :- type reuse_as
-    --->    no_reuse 
-                % = fictive bottom element representing the fact that no
-                % reuse has been detected so far.
-    ;       unconditional  
-                % no_reuse < unconditional.
-                % = element representing the fact that all reuses detected
-                % so far are unconditional. 
-                % Semantically equivalent to "conditional(Cs)" where every C in
-                % Cs is "always".
+    --->    no_reuse
+            % = fictive bottom element representing the fact that no
+            % reuse has been detected so far.
+
+    ;       unconditional
+            % no_reuse < unconditional.
+            % = element representing the fact that all reuses detected
+            % so far are unconditional.
+            % Semantically equivalent to "conditional(Cs)" where every C in
+            % Cs is "always".
+
     ;       conditional(reuse_conditions).
-                % no_reuse < unconditional < conditional(List)
-                % = element representing the collection of reuse conditions
-                % collected for the reuses detected so far. 
+            % no_reuse < unconditional < conditional(List)
+            % = element representing the collection of reuse conditions
+            % collected for the reuses detected so far.
 
 %-----------------------------------------------------------------------------%
 %
-% reuse_condition
+% Reuse_condition.
 %
 
-reuse_condition_init(ModuleInfo, ProcInfo, DeadVar, LFU, LBU, 
-        Sharing) = Condition :- 
-    proc_info_get_headvars(ProcInfo, HeadVars), 
+reuse_condition_init(ModuleInfo, ProcInfo, DeadVar, LFU, LBU, Sharing)
+        = Condition :-
+    proc_info_get_headvars(ProcInfo, HeadVars),
 
-    % First determine the nodes to which the reuse is related. 
+    % First determine the nodes to which the reuse is related.
     % There are two cases:
-    % 1. Var is a headvar, then it is sufficient to keep the top cell of that
-    %    Var as only node. HeadVar-datastructures shared with that node will
-    %    still be retraceable at the moment of verifying the condition
-    % 2. Var is a local var, then we must compute all the headvar-
+    %
+    % 1 Var is a headvar, then it is sufficient to keep the top cell of that
+    %   Var as only node. HeadVar-datastructures shared with that node will
+    %   still be retraceable at the moment of verifying the condition.
+    %
+    % 2 Var is a local var, then we must compute all the headvar-
     %   datastructures sharing the same memory representation as the top cell
     %   of this var (note that the datastructures that share with some
     %   substructure of this var are not relevant for the nodes). All the
-    %   obtained datastructures are kept as the nodes for our condition. 
+    %   obtained datastructures are kept as the nodes for our condition.
+
     TopCell = ctgc.datastruct.datastruct_init(DeadVar),
-    (
-        list.member(DeadVar, HeadVars)
-    ->
+    ( list.member(DeadVar, HeadVars) ->
         Nodes = [TopCell]
     ;
-        SharedDatastructs = extend_datastruct(ModuleInfo, ProcInfo, 
-            Sharing, TopCell), 
+        SharedDatastructs = extend_datastruct(ModuleInfo, ProcInfo,
+            Sharing, TopCell),
         Nodes = datastructs_project(HeadVars, SharedDatastructs)
     ),
 
-    % It is possible that the obtained set of nodes is empty, in that
-    % case the condition is always satisfied, independent of any calling
+    % It is possible that the obtained set of nodes is empty. In that case
+    % the condition is always satisfied, independent of any calling
     % environment.
     (
         Nodes = [],
@@ -364,7 +369,7 @@
         SharedLU = list.condense(ExtendedLuData),
         HeadVarSharedLU = datastructs_project(HeadVars, SharedLU),
 
-        structure_sharing.domain.sharing_as_project(HeadVars, Sharing, 
+        structure_sharing.domain.sharing_as_project(HeadVars, Sharing,
             HeadVarSharing),
         Condition = condition(set.from_list(Nodes), HeadVarSharedLU,
             HeadVarSharing)
@@ -374,12 +379,12 @@
 
 reuse_condition_reusable_nodes(condition(Nodes, _, _), Nodes).
 
-reuse_condition_subsumed_by(ModuleInfo, ProcInfo, Cond1, Cond2) :- 
-    (   
+reuse_condition_subsumed_by(ModuleInfo, ProcInfo, Cond1, Cond2) :-
+    (
         Cond1 = always
     ;
         Cond1 = condition(Nodes1, LocalUse1, LocalSharing1),
-        Cond2 = condition(Nodes2, LocalUse2, LocalSharing2), 
+        Cond2 = condition(Nodes2, LocalUse2, LocalSharing2),
 
         % XXX this was Nancy's implementation, but bad_indirect_reuse.m is
         % broken when using this definition. --pw
@@ -408,14 +413,14 @@
     ;
         reuse_condition_subsumed_by_list(ModuleInfo, ProcInfo, Cond, Rest)
     ).
-        
+
 :- pred reuse_conditions_subsume_reuse_condition(module_info::in,
     proc_info::in, reuse_conditions::in, reuse_condition::in) is semidet.
 
 reuse_conditions_subsume_reuse_condition(ModuleInfo, ProcInfo, Conds, Cond):-
     reuse_condition_subsumed_by_list(ModuleInfo, ProcInfo, Cond, Conds).
 
-reuse_condition_rename(MapVar, TypeSubst, Condition, RenamedCondition):- 
+reuse_condition_rename(MapVar, TypeSubst, Condition, RenamedCondition):-
     (
         Condition = always,
         RenamedCondition = always
@@ -425,7 +430,7 @@
             DeadNodes),
         RenamedInUseNodes = list.map(rename_datastruct(MapVar, TypeSubst),
             InUseNodes),
-        sharing_as_rename(MapVar, TypeSubst, LocalSharing, 
+        sharing_as_rename(MapVar, TypeSubst, LocalSharing,
             RenamedLocalSharing),
         RenamedCondition = condition(RenamedDeadNodes, RenamedInUseNodes,
             RenamedLocalSharing)
@@ -437,10 +442,8 @@
 %
 
 reuse_as_init = no_reuse.
-reuse_as_init_with_one_condition(ReuseCondition) = ReuseAs :- 
-    (
-        reuse_condition_is_conditional(ReuseCondition)
-    ->
+reuse_as_init_with_one_condition(ReuseCondition) = ReuseAs :-
+    ( reuse_condition_is_conditional(ReuseCondition) ->
         ReuseAs = conditional([ReuseCondition])
     ;
         ReuseAs = unconditional
@@ -448,10 +451,10 @@
 
 reuse_as_short_description(no_reuse) = "no_reuse".
 reuse_as_short_description(unconditional) = "uncond".
-reuse_as_short_description(conditional(Conds)) = "cond(" ++ Size ++ ")" :- 
+reuse_as_short_description(conditional(Conds)) = "cond(" ++ Size ++ ")" :-
     Size = string.int_to_string(list.length(Conds)).
-      
-reuse_as_subsumed_by(ModuleInfo, ProcInfo, FirstReuseAs, SecondReuseAs) :- 
+
+reuse_as_subsumed_by(ModuleInfo, ProcInfo, FirstReuseAs, SecondReuseAs) :-
     (
         FirstReuseAs = no_reuse
     ;
@@ -467,7 +470,7 @@
         FirstReuseAs = conditional(ReuseConditionsFirst),
         SecondReuseAs = conditional(ReuseConditionsSecond),
         list.takewhile(reuse_conditions_subsume_reuse_condition(ModuleInfo,
-            ProcInfo, ReuseConditionsSecond), ReuseConditionsFirst, _, 
+            ProcInfo, ReuseConditionsSecond), ReuseConditionsFirst, _,
             NotSubsumed),
         NotSubsumed = []
     ).
@@ -488,13 +491,13 @@
 reuse_as_count_conditions(conditional(Conds)) = list.length(Conds).
 
 reuse_as_rename_using_module_info(ModuleInfo, PPId, ActualArgs, ActualTypes,
-        CallerTypeVarSet, CallerHeadTypeParams, FormalReuse, ActualReuse) :- 
+        CallerTypeVarSet, CallerHeadTypeParams, FormalReuse, ActualReuse) :-
     VarRenaming = get_variable_renaming(ModuleInfo, PPId, ActualArgs),
     TypeSubst = get_type_substitution(ModuleInfo, PPId, ActualTypes,
         CallerTypeVarSet, CallerHeadTypeParams),
     reuse_as_rename(VarRenaming, TypeSubst, FormalReuse, ActualReuse).
 
-reuse_as_rename(MapVar, TypeSubst, ReuseAs, RenamedReuseAs) :- 
+reuse_as_rename(MapVar, TypeSubst, ReuseAs, RenamedReuseAs) :-
     (
         ReuseAs = no_reuse,
         RenamedReuseAs = no_reuse
@@ -508,12 +511,10 @@
         RenamedReuseAs = conditional(RenamedReuseConditions)
     ).
 
-reuse_as_add_condition(ModuleInfo, ProcInfo, Condition, !ReuseAs) :- 
+reuse_as_add_condition(ModuleInfo, ProcInfo, Condition, !ReuseAs) :-
     (
         Condition = always,
-        (
-            !.ReuseAs = no_reuse
-        -> 
+        ( !.ReuseAs = no_reuse ->
             !:ReuseAs = unconditional
         ;
             true
@@ -528,13 +529,13 @@
             !:ReuseAs = conditional([Condition])
         ;
             !.ReuseAs = conditional(Conditions),
-            reuse_conditions_add_condition(ModuleInfo, ProcInfo, 
+            reuse_conditions_add_condition(ModuleInfo, ProcInfo,
                 Condition, Conditions, NewConditions),
             !:ReuseAs = conditional(NewConditions)
         )
     ).
 
-reuse_as_add_unconditional(!ReuseAs) :- 
+reuse_as_add_unconditional(!ReuseAs) :-
     (
         !.ReuseAs = no_reuse,
         !:ReuseAs = unconditional
@@ -547,11 +548,11 @@
 :- pred reuse_conditions_add_condition(module_info::in, proc_info::in,
     reuse_condition::in, reuse_conditions::in, reuse_conditions::out) is det.
 
-reuse_conditions_add_condition(ModuleInfo, ProcInfo, Condition, !Conds):- 
+reuse_conditions_add_condition(ModuleInfo, ProcInfo, Condition, !Conds):-
     (
-        reuse_condition_subsumed_by_list(ModuleInfo, ProcInfo, 
+        reuse_condition_subsumed_by_list(ModuleInfo, ProcInfo,
             Condition, !.Conds)
-    -> 
+    ->
         true
     ;
         !:Conds = [Condition | !.Conds]
@@ -560,24 +561,22 @@
 :- pred reuse_conditions_add_conditions(module_info::in, proc_info::in,
     reuse_conditions::in, reuse_conditions::in, reuse_conditions::out) is det.
 
-reuse_conditions_add_conditions(ModuleInfo, ProcInfo, NewConds, !Conds):- 
+reuse_conditions_add_conditions(ModuleInfo, ProcInfo, NewConds, !Conds):-
     (
         NewConds = [Cond | RemainingConds],
         reuse_conditions_add_condition(ModuleInfo, ProcInfo, Cond, !Conds),
-        reuse_conditions_add_conditions(ModuleInfo, ProcInfo, 
+        reuse_conditions_add_conditions(ModuleInfo, ProcInfo,
             RemainingConds, !Conds)
     ;
         NewConds = []
     ).
 
-reuse_as_least_upper_bound(ModuleInfo, ProcInfo, NewReuseAs, !ReuseAs) :- 
+reuse_as_least_upper_bound(ModuleInfo, ProcInfo, NewReuseAs, !ReuseAs) :-
     (
         NewReuseAs = no_reuse
     ;
         NewReuseAs = unconditional,
-        (
-            !.ReuseAs = no_reuse
-        ->
+        ( !.ReuseAs = no_reuse ->
             !:ReuseAs = unconditional
         ;
             true
@@ -592,55 +591,55 @@
             !:ReuseAs = NewReuseAs
         ;
             !.ReuseAs = conditional(Conditions),
-            reuse_conditions_add_conditions(ModuleInfo, ProcInfo, 
-                NewConditions, Conditions, AllConditions), 
+            reuse_conditions_add_conditions(ModuleInfo, ProcInfo,
+                NewConditions, Conditions, AllConditions),
             !:ReuseAs = conditional(AllConditions)
         )
-            
+
     ).
 
 reuse_as_least_upper_bound(ModuleInfo, ProcInfo, Reuse1, Reuse2) = Reuse :-
     reuse_as_least_upper_bound(ModuleInfo, ProcInfo, Reuse1, Reuse2, Reuse).
 
 reuse_as_from_called_procedure_to_local_reuse_as(ModuleInfo, ProcInfo,
-        HeadVars, LuData, SharingAs, CalledReuseAs) = LocalReuseAs :- 
+        HeadVars, LuData, SharingAs, CalledReuseAs) = LocalReuseAs :-
     (
         CalledReuseAs = no_reuse,
-        unexpected(this_file, 
-            "reuse_as_from_called_procedure_to_local_reuse_as: " ++ 
+        unexpected(this_file,
+            "reuse_as_from_called_procedure_to_local_reuse_as: " ++
             "reuse_as does not specify any reuses.")
-    ; 
+    ;
         CalledReuseAs = unconditional,
         unexpected(this_file,
             "reuse_as_from_called_procedure_to_local_reuse_as: " ++
             "reuse_as is unconditional.")
-    ; 
+    ;
         CalledReuseAs = conditional(ConditionsCaller),
-        ConditionsCallee = 
+        ConditionsCallee =
             list.map(reuse_condition_from_called_proc_to_local_condition(
-                ModuleInfo, ProcInfo, HeadVars, LuData, SharingAs), 
+                ModuleInfo, ProcInfo, HeadVars, LuData, SharingAs),
                 ConditionsCaller),
-        list.foldl(reuse_as_add_condition(ModuleInfo, ProcInfo), 
+        list.foldl(reuse_as_add_condition(ModuleInfo, ProcInfo),
             ConditionsCallee, reuse_as_init, LocalReuseAs)
     ).
-        
+
 :- func reuse_condition_from_called_proc_to_local_condition(module_info,
-    proc_info, prog_vars, live_datastructs, sharing_as, reuse_condition) = 
+    proc_info, prog_vars, live_datastructs, sharing_as, reuse_condition) =
     reuse_condition.
 
-reuse_condition_from_called_proc_to_local_condition(ModuleInfo, ProcInfo, 
-        HeadVars, LuData, SharingAs, CalledCondition) = LocalCondition :- 
+reuse_condition_from_called_proc_to_local_condition(ModuleInfo, ProcInfo,
+        HeadVars, LuData, SharingAs, CalledCondition) = LocalCondition :-
     (
-        CalledCondition = always, 
-        unexpected(this_file, 
+        CalledCondition = always,
+        unexpected(this_file,
             "reuse_condition_from_called_proc_to_local_condition: " ++
             "explicit condition expected.")
-    ; 
-        CalledCondition = condition(CalledDeadNodes, 
+    ;
+        CalledCondition = condition(CalledDeadNodes,
             CalledInUseNodes, CalledSharingAs),
 
-        % Translate the dead nodes: 
-        AllDeadNodes = extend_datastructs(ModuleInfo, ProcInfo, 
+        % Translate the dead nodes:
+        AllDeadNodes = extend_datastructs(ModuleInfo, ProcInfo,
             SharingAs, set.to_sorted_list(CalledDeadNodes)),
         AllDeadHeadVarNodes = datastructs_project(HeadVars, AllDeadNodes),
 
@@ -650,31 +649,31 @@
         ;
             AllDeadHeadVarNodes = [_ | _],
             % Translate the in use nodes:
-            AllInUseNodes = extend_datastructs(ModuleInfo, ProcInfo, 
+            AllInUseNodes = extend_datastructs(ModuleInfo, ProcInfo,
                 SharingAs, list.append(LuData, CalledInUseNodes)),
-            AllInUseHeadVarNodes = datastructs_project(HeadVars, 
+            AllInUseHeadVarNodes = datastructs_project(HeadVars,
                 AllInUseNodes),
 
-            % Translate the sharing information: 
-            AllLocalSharing = sharing_as_comb(ModuleInfo, ProcInfo, 
+            % Translate the sharing information:
+            AllLocalSharing = sharing_as_comb(ModuleInfo, ProcInfo,
                 CalledSharingAs, SharingAs),
-            AllHeadVarLocalSharing = sharing_as_project(HeadVars, 
+            AllHeadVarLocalSharing = sharing_as_project(HeadVars,
                 AllLocalSharing),
 
-            LocalCondition = condition(set.from_list(AllDeadHeadVarNodes), 
+            LocalCondition = condition(set.from_list(AllDeadHeadVarNodes),
                 AllInUseHeadVarNodes, AllHeadVarLocalSharing)
         )
-    ). 
+    ).
 
 reuse_as_satisfied(ModuleInfo, ProcInfo, LiveData, SharingAs, StaticVars,
-        ReuseAs, Result) :- 
+        ReuseAs, Result) :-
     (
         ReuseAs = no_reuse,
         Result = reuse_not_possible(no_reuse)
     ;
         ReuseAs = unconditional,
         Result = reuse_possible
-    ; 
+    ;
         ReuseAs = conditional(Conditions),
         reuse_as_satisfied_2(ModuleInfo, ProcInfo, LiveData, SharingAs,
             StaticVars, Conditions, Result0),
@@ -694,7 +693,7 @@
                 AliasedVars = [],
                 Result = reuse_possible
             ;
-                AliasedVars = [_ | _], 
+                AliasedVars = [_ | _],
                 Result = reuse_not_possible(reuse_nodes_have_sharing(
                     AliasedVars))
             )
@@ -710,8 +709,8 @@
 
 reuse_as_satisfied_2(_, _, _, _, _, [], reuse_possible).
 reuse_as_satisfied_2(ModuleInfo, ProcInfo, LiveData, SharingAs, StaticVars,
-        [Cond | Conds], Result) :- 
-    reuse_condition_satisfied(ModuleInfo, ProcInfo, 
+        [Cond | Conds], Result) :-
+    reuse_condition_satisfied(ModuleInfo, ProcInfo,
         LiveData, SharingAs, StaticVars, Cond, Result0),
     (
         Result0 = reuse_possible,
@@ -822,8 +821,8 @@
     livedata::in, sharing_as::in, prog_vars::in, reuse_condition::in,
     reuse_satisfied_result::out) is det.
 
-reuse_condition_satisfied(ModuleInfo, ProcInfo, LiveData, SharingAs, 
-        StaticVars, Condition, Result) :- 
+reuse_condition_satisfied(ModuleInfo, ProcInfo, LiveData, SharingAs,
+        StaticVars, Condition, Result) :-
     (
         Condition = always,
         Result = reuse_possible
@@ -836,14 +835,14 @@
         (
             StaticDeadNodes = [],
 
-            % Using the InUseNodes, and the sharing recorded by the condition, 
+            % Using the InUseNodes, and the sharing recorded by the condition,
             % compute a new set of livedata that (safely) approximates the
             % set of livedata that would have been obtained when looking at
             % the program point from where the reuse condition actually comes
             % from.
-            NewSharing = sharing_as_comb(ModuleInfo, ProcInfo, SharingNodes, 
+            NewSharing = sharing_as_comb(ModuleInfo, ProcInfo, SharingNodes,
                 SharingAs),
-            UpdatedLiveData = livedata_add_liveness(ModuleInfo, ProcInfo, 
+            UpdatedLiveData = livedata_add_liveness(ModuleInfo, ProcInfo,
                 InUseNodes, NewSharing, LiveData),
             nodes_are_not_live(ModuleInfo, ProcInfo, DeadNodes,
                 UpdatedLiveData, NotLiveResult),
@@ -870,58 +869,58 @@
 
 %-----------------------------------------------------------------------------%
 
-from_structure_reuse_domain(ReuseDomain) = ReuseAs :- 
+from_structure_reuse_domain(ReuseDomain) = ReuseAs :-
     (
         ReuseDomain = has_no_reuse,
         ReuseAs = no_reuse
     ;
         ReuseDomain = has_only_unconditional_reuse,
         ReuseAs = unconditional
-    ; 
+    ;
         ReuseDomain = has_conditional_reuse(PublicReuseConditions),
         ReuseAs = conditional(
             from_public_reuse_conditions(PublicReuseConditions))
     ).
 
-:- func from_public_reuse_conditions(structure_reuse_conditions) = 
+:- func from_public_reuse_conditions(structure_reuse_conditions) =
     reuse_conditions.
 
 from_public_reuse_conditions(PublicReuseConditions) =
     list.map(from_public_reuse_condition, PublicReuseConditions).
 
-:- func from_public_reuse_condition(structure_reuse_condition) = 
+:- func from_public_reuse_condition(structure_reuse_condition) =
     reuse_condition.
 
-from_public_reuse_condition(PublicReuseCondition) = ReuseCondition :- 
+from_public_reuse_condition(PublicReuseCondition) = ReuseCondition :-
     PublicReuseCondition = structure_reuse_condition(DeadNodes, LiveNodes,
         PublicSharing),
-    ReuseCondition = condition(DeadNodes, LiveNodes, 
+    ReuseCondition = condition(DeadNodes, LiveNodes,
         from_structure_sharing_domain(PublicSharing)).
-   
-to_structure_reuse_domain(ReuseAs) = ReuseDomain :- 
+
+to_structure_reuse_domain(ReuseAs) = ReuseDomain :-
     (
         ReuseAs = no_reuse,
         ReuseDomain = has_no_reuse
     ;
         ReuseAs = unconditional,
         ReuseDomain = has_only_unconditional_reuse
-    ; 
+    ;
         ReuseAs = conditional(ReuseConditions),
         ReuseDomain = has_conditional_reuse(
             to_structure_reuse_conditions(ReuseConditions))
     ).
 
-:- func to_structure_reuse_conditions(reuse_conditions) = 
+:- func to_structure_reuse_conditions(reuse_conditions) =
     structure_reuse_conditions.
 
-to_structure_reuse_conditions(ReuseConditions) = 
+to_structure_reuse_conditions(ReuseConditions) =
     list.filter_map(to_structure_reuse_condition, ReuseConditions).
 
-:- func to_structure_reuse_condition(reuse_condition) = 
+:- func to_structure_reuse_condition(reuse_condition) =
     structure_reuse_condition is semidet.
 
-to_structure_reuse_condition(Condition) = StructureReuseCondition :- 
-    Condition = condition(DeadNodes, LiveNodes, SharingAs), 
+to_structure_reuse_condition(Condition) = StructureReuseCondition :-
+    Condition = condition(DeadNodes, LiveNodes, SharingAs),
     StructureReuseCondition = structure_reuse_condition(DeadNodes, LiveNodes,
         to_structure_sharing_domain(SharingAs)).
 
@@ -948,12 +947,12 @@
             "reuse_as_table_reverse_search_reuse_version_proc")
     ).
 
-reuse_as_table_set(PPId, ReuseAs_Status, !Table) :- 
+reuse_as_table_set(PPId, ReuseAs_Status, !Table) :-
     T0 = !.Table ^ reuse_info_map,
     map.set(T0, PPId, ReuseAs_Status, T),
     !Table ^ reuse_info_map := T.
 
-reuse_as_table_insert_reuse_version_proc(PPId, NoClobbers, NewPPId, !Table) :- 
+reuse_as_table_insert_reuse_version_proc(PPId, NoClobbers, NewPPId, !Table) :-
     T0 = !.Table ^ reuse_version_map,
     bimap.det_insert(T0, ppid_no_clobbers(PPId, NoClobbers), NewPPId, T),
     !Table ^ reuse_version_map := T.
@@ -961,7 +960,7 @@
 reuse_as_table_maybe_dump(DoDump, ModuleInfo, Table, !IO) :-
     (
         DoDump = no
-    ;   
+    ;
         DoDump = yes,
         reuse_as_table_dump(ModuleInfo, Table, !IO)
     ).
@@ -972,9 +971,9 @@
 reuse_as_table_dump(ModuleInfo, Table, !IO) :-
     ReuseInfoMap = Table ^ reuse_info_map,
     ( map.is_empty(ReuseInfoMap) ->
-        io.write_string("% ReuseTable: Empty", !IO)
+        io.write_string("% ReuseTable: Empty\n", !IO)
     ;
-        io.write_string("% ReuseTable: PPId --> Reuse\n", !IO), 
+        io.write_string("% ReuseTable: PPId --> Reuse\n", !IO),
         map.foldl(dump_entries(ModuleInfo), ReuseInfoMap, !IO)
     ).
 
@@ -988,7 +987,7 @@
     io.write_string(reuse_as_short_description(ReuseAs), !IO),
     io.nl(!IO).
 
-load_structure_reuse_table(ModuleInfo) = ReuseTable :- 
+load_structure_reuse_table(ModuleInfo) = ReuseTable :-
     module_info_get_valid_predids(PredIds, ModuleInfo, _ModuleInfo),
     list.foldl(load_structure_reuse_table_2(ModuleInfo), PredIds,
         reuse_as_table_init, ReuseTable).
Index: compiler/trace_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/trace_gen.m,v
retrieving revision 1.30
diff -u -r1.30 trace_gen.m
--- compiler/trace_gen.m	15 Dec 2010 06:30:07 -0000	1.30
+++ compiler/trace_gen.m	15 Dec 2010 06:33:27 -0000
@@ -203,7 +203,7 @@
     llds_code::out, code_info::in, code_info::out) is det.
 
 :- pred generate_tailrec_event_code(trace_info::in,
-    assoc_list(prog_var, arg_info)::in, goal_path::in, prog_context::in,
+    assoc_list(prog_var, arg_info)::in, goal_id::in, prog_context::in,
     llds_code::out, label::out, code_info::in, code_info::out) is det.
 
 :- type external_event_info
@@ -246,6 +246,7 @@
 :- import_module check_hlds.inst_match.
 :- import_module check_hlds.mode_util.
 :- import_module check_hlds.type_util.
+:- import_module hlds.goal_path.
 :- import_module hlds.code_model.
 :- import_module hlds.hlds_llds.
 :- import_module hlds.instmap.
@@ -273,22 +274,25 @@
 :- type trace_port_info
     --->    port_info_external
     ;       port_info_tailrec_call(
-                goal_path,      % The path of the tail recursive call.
+                forward_goal_path,
+                % The id of the tail recursive call.
                 assoc_list(prog_var, arg_info)
-                                % The list of arguments of this call.
+                % The list of arguments of this call.
             )
     ;       port_info_internal(
-                goal_path,      % The path of the goal whose start
-                                % this port represents.
-                set(prog_var)   % The pre-death set of this goal.
+                forward_goal_path,
+                % The id of the goal whose start this port represents.
+                set(prog_var)
+                % The pre-death set of this goal.
             )
     ;       port_info_negation_end(
-                goal_path       % The path of the goal whose end
-                                % (one way or another) this port
-                                % represents.
+                forward_goal_path
+                % The id of the goal whose end (one way or another)
+                % this port represents.
             )
     ;       port_info_user(
-                goal_path       % The path of the goal.
+                forward_goal_path
+                % The id of the goal.
             )
     ;       port_info_nondet_foreign_proc.
 
@@ -607,13 +611,13 @@
 
 generate_slot_fill_code(CI, TraceInfo, TraceCode) :-
     CodeModel = get_proc_model(CI),
-    MaybeFromFullSlot  = TraceInfo ^ from_full_lval,
-    MaybeIoSeqSlot     = TraceInfo ^ io_seq_lval,
-    MaybeTrailLvals    = TraceInfo ^ trail_lvals,
-    MaybeMaxfrLval     = TraceInfo ^ maxfr_lval,
-    MaybeCallTableLval = TraceInfo ^ call_table_tip_lval,
-    MaybeTailRecInfo   = TraceInfo ^ tail_rec_info,
-    MaybeRedoLabel     = TraceInfo ^ redo_label,
+    MaybeFromFullSlot  = TraceInfo ^ ti_from_full_lval,
+    MaybeIoSeqSlot     = TraceInfo ^ ti_io_seq_lval,
+    MaybeTrailLvals    = TraceInfo ^ ti_trail_lvals,
+    MaybeMaxfrLval     = TraceInfo ^ ti_maxfr_lval,
+    MaybeCallTableLval = TraceInfo ^ ti_call_table_tip_lval,
+    MaybeTailRecInfo   = TraceInfo ^ ti_tail_rec_info,
+    MaybeRedoLabel     = TraceInfo ^ ti_redo_label,
     event_num_slot(CodeModel, EventNumLval),
     call_num_slot(CodeModel, CallNumLval),
     call_depth_slot(CodeModel, CallDepthLval),
@@ -745,7 +749,7 @@
     CodeModel = get_proc_model(CI),
     (
         MaybeTraceInfo = yes(TraceInfo),
-        MaybeFromFullSlot = TraceInfo ^ from_full_lval,
+        MaybeFromFullSlot = TraceInfo ^ ti_from_full_lval,
         call_depth_slot(CodeModel, CallDepthLval),
         stackref_to_string(CallDepthLval, CallDepthStr),
         (
@@ -770,9 +774,11 @@
     (
         MaybeTraceInfo = yes(TraceInfo),
         Goal = hlds_goal(_, GoalInfo),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        get_containing_goal_map_det(!.CI, ContainingGoalMap),
+        map.lookup(ContainingGoalMap, GoalId, ContainingGoal),
         (
-            LastStep = goal_path_get_last(GoalPath),
+            ContainingGoal = containing_goal(_, LastStep),
             (
                 LastStep = step_switch(_, _),
                 PortPrime = port_switch
@@ -806,8 +812,8 @@
             get_pred_info(!.CI, PredInfo),
             get_proc_info(!.CI, ProcInfo),
             eff_trace_needs_port(ModuleInfo, PredInfo, ProcInfo,
-                TraceInfo ^ trace_level,
-                TraceInfo ^ trace_suppress_items, Port) = yes
+                TraceInfo ^ ti_trace_level,
+                TraceInfo ^ ti_trace_suppress_items, Port) = yes
         ->
             goal_info_get_pre_deaths(GoalInfo, PreDeaths),
             Context = goal_info_get_context(GoalInfo),
@@ -819,6 +825,7 @@
             ;
                 HideEvent = no
             ),
+            GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
             generate_event_code(Port, port_info_internal(GoalPath, PreDeaths),
                 yes(TraceInfo), Context, HideEvent, no, _, _, Code, !CI)
         ;
@@ -844,19 +851,21 @@
         get_pred_info(!.CI, PredInfo),
         get_proc_info(!.CI, ProcInfo),
         eff_trace_needs_port(ModuleInfo, PredInfo, ProcInfo,
-            TraceInfo ^ trace_level,
-            TraceInfo ^ trace_suppress_items, Port) = yes
+            TraceInfo ^ ti_trace_level,
+            TraceInfo ^ ti_trace_suppress_items, Port) = yes
     ->
         Goal = hlds_goal(_, GoalInfo),
-        Path = goal_info_get_goal_path(GoalInfo),
+        GoalId = goal_info_get_goal_id(GoalInfo),
         Context = goal_info_get_context(GoalInfo),
         ( goal_info_has_feature(OutsideGoalInfo, feature_hide_debug_event) ->
             HideEvent = yes
         ;
             HideEvent = no
         ),
-        generate_event_code(Port, port_info_negation_end(Path), yes(TraceInfo),
-            Context, HideEvent, no, _, _, Code, !CI)
+        get_containing_goal_map_det(!.CI, ContainingGoalMap),
+        GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
+        generate_event_code(Port, port_info_negation_end(GoalPath),
+            yes(TraceInfo), Context, HideEvent, no, _, _, Code, !CI)
     ;
         Code = empty
     ).
@@ -870,8 +879,8 @@
         get_pred_info(!.CI, PredInfo),
         get_proc_info(!.CI, ProcInfo),
         eff_trace_needs_port(ModuleInfo, PredInfo, ProcInfo,
-            TraceInfo ^ trace_level,
-            TraceInfo ^ trace_suppress_items, Port) = yes
+            TraceInfo ^ ti_trace_level,
+            TraceInfo ^ ti_trace_suppress_items, Port) = yes
     ->
         generate_event_code(Port, port_info_nondet_foreign_proc,
             yes(TraceInfo), Context, no, no, _, _, Code, !CI)
@@ -880,10 +889,12 @@
     ).
 
 generate_user_event_code(UserInfo, GoalInfo, Code, !CI) :-
-    Path = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    get_containing_goal_map_det(!.CI, ContainingGoalMap),
+    GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
     Context = goal_info_get_context(GoalInfo),
     Port = port_user,
-    PortInfo = port_info_user(Path),
+    PortInfo = port_info_user(GoalPath),
     MaybeTraceInfo = no,
     HideEvent = no,
     generate_event_code(Port, PortInfo, MaybeTraceInfo, Context, HideEvent,
@@ -896,7 +907,7 @@
     get_pred_info(!.CI, PredInfo),
     get_proc_info(!.CI, ProcInfo),
     NeedPort = eff_trace_needs_port(ModuleInfo, PredInfo, ProcInfo,
-        TraceInfo ^ trace_level, TraceInfo ^ trace_suppress_items, Port),
+        TraceInfo ^ ti_trace_level, TraceInfo ^ ti_trace_suppress_items, Port),
     (
         NeedPort = yes,
         generate_event_code(Port, port_info_external, yes(TraceInfo), Context,
@@ -907,15 +918,17 @@
         MaybeExternalInfo = no
     ).
 
-generate_tailrec_event_code(TraceInfo, ArgsInfos, GoalPath, Context,
-        Code, TailRecLabel, !CI) :-
+generate_tailrec_event_code(TraceInfo, ArgsInfos, GoalId, Context, Code,
+        TailRecLabel, !CI) :-
     Port = port_tailrec_call,
+    get_containing_goal_map_det(!.CI, ContainingGoalMap),
+    GoalPath = goal_id_to_forward_path(ContainingGoalMap, GoalId),
     PortInfo = port_info_tailrec_call(GoalPath, ArgsInfos),
     HideEvent = no,
     MaybeUserInfo = no,
     generate_event_code(Port, PortInfo, yes(TraceInfo), Context, HideEvent,
         MaybeUserInfo, _Label, _TvarDataMap, Code, !CI),
-    MaybeTailRecInfo = TraceInfo ^ tail_rec_info,
+    MaybeTailRecInfo = TraceInfo ^ ti_tail_rec_info,
     (
         MaybeTailRecInfo = yes(_ - TailRecLabel)
     ;
@@ -942,17 +955,17 @@
     % Stage 2.
     % Tail recursion events cannot happen in model_non procedures, so stage 2
     % will not allocate any slots.
-    MaybeRedoLabelLval = TraceInfo ^ redo_label,
+    MaybeRedoLabelLval = TraceInfo ^ ti_redo_label,
     expect(unify(MaybeRedoLabelLval, no), this_file,
         "redo label in procedure with TAIL event"),
     % Stage 3.
     % Tail recursion events are disabled if the trace level is shallow tracing,
     % so stage 3 will not allocate any slots.
-    MaybeFromFullLval = TraceInfo ^ from_full_lval,
+    MaybeFromFullLval = TraceInfo ^ ti_from_full_lval,
     expect(unify(MaybeFromFullLval, no), this_file,
         "from_full slot in procedure with TAIL event"),
     % Stage 4.
-    MaybeIoSeqSlot = TraceInfo ^ io_seq_lval,
+    MaybeIoSeqSlot = TraceInfo ^ ti_io_seq_lval,
     (
         MaybeIoSeqSlot = yes(IoSeqLval),
         stackref_to_string(IoSeqLval, IoSeqStr),
@@ -962,7 +975,7 @@
         IoSeqCodeStr = ""
     ),
     % Stage 5.
-    MaybeTrailLvals = TraceInfo ^ trail_lvals,
+    MaybeTrailLvals = TraceInfo ^ ti_trail_lvals,
     (
         MaybeTrailLvals = yes(TrailLval - TicketLval),
         stackref_to_string(TrailLval, TrailLvalStr),
@@ -975,7 +988,7 @@
         TrailCodeStr = ""
     ),
     % Stage 6.
-    MaybeMaxfrLval = TraceInfo ^ maxfr_lval,
+    MaybeMaxfrLval = TraceInfo ^ ti_maxfr_lval,
     (
         MaybeMaxfrLval = yes(MaxfrLval),
         MaxfrCode = singleton(
@@ -986,7 +999,7 @@
         MaxfrCode = empty
     ),
     % Stage 7.
-    TailRecInfo = TraceInfo ^ tail_rec_info,
+    TailRecInfo = TraceInfo ^ ti_tail_rec_info,
     (
         TailRecInfo = yes(TailRecLval - _),
         TailRecLvalCode = singleton(
@@ -1000,7 +1013,7 @@
             "generate_tailrec_reset_slots_code: no tail rec lval")
     ),
     % Stage 8.
-    MaybeCallTableLval = TraceInfo ^ call_table_tip_lval,
+    MaybeCallTableLval = TraceInfo ^ ti_call_table_tip_lval,
     (
         MaybeCallTableLval = yes(CallTableLval),
         stackref_to_string(CallTableLval, CallTableLvalStr),
@@ -1034,7 +1047,7 @@
     (
         PortInfo = port_info_external,
         LiveVars = LiveVars0,
-        Path = empty_goal_path,
+        Path = fgp([]),
         TailRecResetCode = empty
     ;
         PortInfo = port_info_tailrec_call(Path, ArgsInfos),
@@ -1070,9 +1083,9 @@
         PortInfo = port_info_nondet_foreign_proc,
         LiveVars = [],
         ( Port = port_nondet_foreign_proc_first ->
-            Path = singleton_goal_path(step_first)
+            Path = fgp([step_first])
         ; Port = port_nondet_foreign_proc_later ->
-            Path = singleton_goal_path(step_later)
+            Path = fgp([step_later])
         ;
             unexpected(this_file,
                 "generate_event_code: bad nondet foreign_proc port")
@@ -1125,7 +1138,7 @@
     (
         Port = port_fail,
         MaybeTraceInfo = yes(TraceInfo),
-        TraceInfo ^ redo_label = yes(RedoLabel)
+        TraceInfo ^ ti_redo_label = yes(RedoLabel)
     ->
         % The layout information for the redo event is the same as for the
         % fail event; all the non-clobbered inputs in their stack slots.
@@ -1186,10 +1199,10 @@
 find_lval_in_layout_locn(locn_indirect(Lval, _)) = Lval.
 
 maybe_setup_redo_event(TraceInfo, Code) :-
-    TraceRedoLabel = TraceInfo ^ redo_label,
+    TraceRedoLabel = TraceInfo ^ ti_redo_label,
     (
         TraceRedoLabel = yes(_),
-        MaybeFromFullSlot = TraceInfo ^ from_full_lval,
+        MaybeFromFullSlot = TraceInfo ^ ti_from_full_lval,
         (
             MaybeFromFullSlot = yes(Lval),
             % The code in the runtime looks for the from-full flag in
@@ -1378,46 +1391,46 @@
     % of a procedure.
 :- type trace_info
     --->    trace_info(
-                trace_level             :: trace_level,
-                trace_suppress_items    :: trace_suppress_items,
+                ti_trace_level          :: trace_level,
+                ti_trace_suppress_items :: trace_suppress_items,
 
                 % If the trace level is shallow, the lval of the slot
                 % that holds the from-full flag.
-                from_full_lval          :: maybe(lval),
+                ti_from_full_lval       :: maybe(lval),
 
                 % If the procedure has I/O state arguments, the lval
                 % of the slot that holds the initial value of the
                 % I/O action counter.
-                io_seq_lval             :: maybe(lval),
+                ti_io_seq_lval          :: maybe(lval),
 
                 % If trailing is enabled, the lvals of the slots that hold
                 % the value of the trail pointer and the ticket counter
                 % at the time of the call.
-                trail_lvals             :: maybe(pair(lval)),
+                ti_trail_lvals          :: maybe(pair(lval)),
 
                 % If we reserve a slot for holding the value of maxfr
                 % at entry for use in implementing retry, the lval of the slot.
-                maxfr_lval              :: maybe(lval),
+                ti_maxfr_lval           :: maybe(lval),
 
                 % If we reserve a slot for holding the value of the call table
                 % tip variable, the lval of this variable.
-                call_table_tip_lval     :: maybe(lval),
+                ti_call_table_tip_lval  :: maybe(lval),
 
                 % If we reserve a slot for holding the number of times the
                 % stack frame was reused by tail recursive calls, the lval
                 % holding this counter, and the label that a tail recursive
                 % call should jump to.
-                tail_rec_info           :: maybe(pair(lval, label)),
+                ti_tail_rec_info        :: maybe(pair(lval, label)),
 
                 % If we are generating redo events, this has the label
                 % associated with the fail event, which we then reserve
                 % in advance, so we can put the address of its layout struct
                 % into the slot which holds the layout for the redo event
                 % (the two events have identical layouts).
-                redo_label              :: maybe(label)
+                ti_redo_label           :: maybe(label)
             ).
 
-get_trace_maybe_tail_rec_info(TraceInfo, TraceInfo ^ tail_rec_info).
+get_trace_maybe_tail_rec_info(TraceInfo, TraceInfo ^ ti_tail_rec_info).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/tupling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/tupling.m,v
retrieving revision 1.53
diff -u -r1.53 tupling.m
--- compiler/tupling.m	15 Dec 2010 06:30:07 -0000	1.53
+++ compiler/tupling.m	15 Dec 2010 06:33:28 -0000
@@ -10,19 +10,19 @@
 % Author: wangp.
 %
 % This module takes the HLDS and performs a tupling transformation on the
-% locally-defined procedures.  That is, instead of passing all of the
+% locally-defined procedures. That is, instead of passing all of the
 % procedure's arguments separately, it will try to bundle some of them up and
 % pass them together as a tuple.
 %
 % The idea is that some arguments passed to a procedure may not be needed
 % immediately: between the start of the procedure and the first use of a
 % given argument there may be a flush point, such as a call to another
-% procedure.  At these points all values residing in registers that will be
+% procedure. At these points, all values residing in registers that will be
 % needed later in the procedure will need to be flushed to the stack, to be
-% restored later.  In some cases, it may be beneficial to refer to some
-% arguments indirectly through a cell variable.  Flushing the (address of
-% the) cell variable to the stack is enough to save all the field variables
-% of the cell.  The downside is that accessing a field variable requires
+% restored later. In some cases, it may be beneficial to refer to some
+% arguments indirectly through a cell variable.  Flushing the (address of the)
+% cell variable to the stack is enough to save all the field variables
+% of the cell. The downside is that accessing a field variable requires
 % going through a cell variable (the cost of which may be amortised if
 % multiple field variables are needed in the same interval).
 %
@@ -32,16 +32,16 @@
 %
 % This implementation works as follows:
 %
-% 1. The module is divided up into its constituent SCCs.  We work our way
+% 1. We divide the module into its constituent SCCs. We work our way
 % through each SCC, starting from the bottommost SCC in the call graph.
 %
 % 2. For each SCC, we take guesses at a good tupling scheme for the
-% procedures in the SCC and count the average number of loads and stores
+% procedures in the SCC, and count the average number of loads and stores
 % between the registers and the stack for each given scheme.
 %
 % 3. If the best tupling scheme gives us an average number of loads/stores
-% that compares favourably against the original (untupled) scheme, we go
-% ahead and make the transformed versions of the procedures in the SCC and
+% that compares favourably against the original (untupled) scheme, we go ahead
+% and make the transformed versions of the procedures in the SCC and
 % add them to the HLDS.
 %
 % 4. After all the SCCs have been processed, we update all calls to the
@@ -51,20 +51,20 @@
 %
 % This implementation uses the names of input formal parameters to guess
 % which values are common between the procedures in an SCC (for SCCs with
-% more than one procedure).  i.e. if a variable name occurs as an input
-% argument to more than one procedure in the SCC, those variables
-% corresponding that name are candidates for tupling.  In the interest of
+% more than one procedure). This means that if a variable name occurs as
+% an input argument to more than one procedure in the SCC, those variables
+% corresponding that name are candidates for tupling. In the interest of
 % speeding up compilation times, the implementation only tries to tuple
-% contiguous runs of the candidate variables.
-% e.g. if the candidates are [A,B,C,D] these combinations would be tested in
-% turn, assuming a minimum run length of 3: {A,B,C,D}, {A,B,C}, {B,C,D}
+% contiguous runs of the candidate variables. For example, if the candidates
+% are [A,B,C,D], these combinations would be tested in turn, assuming a
+% minimum run length of 3: {A,B,C,D}, {A,B,C}, and {B,C,D}.
 %
-% To count the average number of loads and stores in a procedure we traverse
+% To count the average number of loads and stores in a procedure, we traverse
 % the procedure's body, remembering which values are available in registers
-% and the stack.  When we reach a branch point, we use the relative
-% frequencies that each branch was taken in a sample run to weight the costs
-% incurred in each branch.  The relative frequency data is gathered from the
-% trace count summary file that must be provided by the user.
+% and the stack. When we reach a branch point, we use the relative frequencies
+% that each branch was taken in a sample run to weight the costs incurred
+% in each branch. The relative frequency data is gathered from the trace count
+% summary file that must be provided by the user.
 %
 % Ideas for further work:
 %
@@ -74,10 +74,10 @@
 % - Proper weighting of calls to procedures from within and without the SCC
 %
 % This transformation is similar in spirit to the transformation in
-% stack_opt.m.  It also shares much code with it.
+% stack_opt.m. It also shares much code with it.
 %
-% XXX: we need to check that mprof can demangle the names of the transformed
-% procedures correctly
+% XXX We need to check that mprof can demangle the names of the transformed
+% procedures correctly.
 %
 %-----------------------------------------------------------------------------%
 
@@ -98,9 +98,9 @@
 
 :- import_module backend_libs.
 :- import_module backend_libs.interval.
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.mode_util.
 :- import_module hlds.arg_info.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_llds.
@@ -148,13 +148,16 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Top-level
+% The top level.
 %
 
 tuple_arguments(!ModuleInfo, !IO) :-
+    % XXX We should add a mechanism that would allow us to check whether
+    % we have already read in this file, and if we have, then avoid reading
+    % it in again.
     module_info_get_globals(!.ModuleInfo, Globals),
-    globals.lookup_string_option(Globals,
-        tuple_trace_counts_file, TraceCountsFile),
+    globals.lookup_string_option(Globals, tuple_trace_counts_file,
+        TraceCountsFile),
     ( TraceCountsFile = "" ->
         report_warning(Globals, "Warning: --tuple requires " ++
             "--tuple-trace-counts-file to work.\n", !IO)
@@ -162,17 +165,26 @@
         read_trace_counts_source(TraceCountsFile, Result, !IO),
         (
             Result = list_ok(_, TraceCounts),
-            tuple_arguments_2(!ModuleInfo, TraceCounts, !IO)
+            tuple_arguments_with_trace_counts(!ModuleInfo, TraceCounts)
         ;
             Result = list_error_message(Message),
             warn_trace_counts_error(Globals, TraceCountsFile, Message, !IO)
         )
     ).
 
-:- pred tuple_arguments_2(module_info::in, module_info::out, trace_counts::in,
+:- pred warn_trace_counts_error(globals::in, string::in, string::in,
     io::di, io::uo) is det.
 
-tuple_arguments_2(!ModuleInfo, TraceCounts0, !IO) :-
+warn_trace_counts_error(Globals, TraceCountsFile, Reason, !IO) :-
+    string.format(
+        "Warning: unable to read trace count summary from %s (%s)\n",
+        [s(TraceCountsFile), s(Reason)], Message),
+    report_warning(Globals, Message, !IO).
+
+:- pred tuple_arguments_with_trace_counts(module_info::in, module_info::out,
+    trace_counts::in) is det.
+
+tuple_arguments_with_trace_counts(!ModuleInfo, TraceCounts0) :-
     module_info_get_globals(!.ModuleInfo, Globals),
     % We use the same cost options as for the stack optimisation.
     globals.lookup_int_option(Globals,
@@ -206,25 +218,15 @@
 
     % Add transformed versions of procedures that we think would be
     % beneficial.
-    list.foldl4(maybe_tuple_scc(TraceCounts, TuningParams, DepGraph),
-        SCCs, !ModuleInfo, counter.init(0), _,
-        map.init, TransformMap, !IO),
+    list.foldl3(maybe_tuple_scc(TraceCounts, TuningParams, DepGraph),
+        SCCs, !ModuleInfo, counter.init(0), _, map.init, TransformMap),
 
     % Update the callers of the original procedures to call their
-    % transformed versions instead.  Do the same for the transformed
+    % transformed versions instead. Do the same for the transformed
     % procedures themselves.
     list.foldl(fix_calls_in_procs(TransformMap), SCCs, !ModuleInfo),
     fix_calls_in_transformed_procs(TransformMap, !ModuleInfo).
 
-:- pred warn_trace_counts_error(globals::in, string::in, string::in,
-    io::di, io::uo) is det.
-
-warn_trace_counts_error(Globals, TraceCountsFile, Reason, !IO) :-
-    string.format(
-        "Warning: unable to read trace count summary from %s (%s)\n",
-        [s(TraceCountsFile), s(Reason)], Message),
-    report_warning(Globals, Message, !IO).
-
 %-----------------------------------------------------------------------------%
 
     % This predicate can be used in place of maybe_tuple_scc to evaluate
@@ -235,33 +237,33 @@
 :- pred maybe_tuple_scc_individual_procs(trace_counts::in, tuning_params::in,
     dependency_graph::in, list(pred_proc_id)::in,
     module_info::in, module_info::out, counter::in, counter::out,
-    transform_map::in, transform_map::out, io::di, io::uo) is det.
+    transform_map::in, transform_map::out) is det.
 
 maybe_tuple_scc_individual_procs(_TraceCounts, _TuningParams, _DepGraph,
-        [], !ModuleInfo, !Counter, !TransformMap, !IO).
+        [], !ModuleInfo, !Counter, !TransformMap).
 maybe_tuple_scc_individual_procs(TraceCounts, TuningParams, DepGraph,
-        [Proc | Procs], !ModuleInfo, !Counter, !TransformMap, !IO) :-
+        [Proc | Procs], !ModuleInfo, !Counter, !TransformMap) :-
     maybe_tuple_scc(TraceCounts, TuningParams, DepGraph,
-        [Proc], !ModuleInfo, !Counter, !TransformMap, !IO),
+        [Proc], !ModuleInfo, !Counter, !TransformMap),
     maybe_tuple_scc_individual_procs(TraceCounts, TuningParams, DepGraph,
-        Procs, !ModuleInfo, !Counter, !TransformMap, !IO).
+        Procs, !ModuleInfo, !Counter, !TransformMap).
 
 :- pred maybe_tuple_scc(trace_counts::in, tuning_params::in,
     dependency_graph::in, list(pred_proc_id)::in(bound([ground | ground])),
     module_info::in, module_info::out, counter::in, counter::out,
-    transform_map::in, transform_map::out, io::di, io::uo) is det.
+    transform_map::in, transform_map::out) is det.
 
 maybe_tuple_scc(TraceCounts, TuningParams, DepGraph, SCC,
-        !ModuleInfo, !Counter, !TransformMap, !IO) :-
+        !ModuleInfo, !Counter, !TransformMap) :-
     module_info_get_globals(!.ModuleInfo, Globals),
     globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
     (
         VeryVerbose = yes,
-        io.write_string("% Considering tupling in ", !IO),
-        list.foldl((pred(PredProcId::in, IO0::di, IO::uo) is det :-
-            write_pred_proc_id(!.ModuleInfo, PredProcId, IO0, IO)),
-            SCC, !IO),
-        io.write_string("\n", !IO)
+        trace [io(!IO)] (
+            io.write_string("% Considering tupling in ", !IO),
+            list.foldl(write_pred_proc_id(!.ModuleInfo), SCC, !IO),
+            io.write_string("...\n", !IO)
+        )
     ;
         VeryVerbose = no
     ),
@@ -273,18 +275,20 @@
             common_candidate_headvars_of_procs(!.ModuleInfo, SCC,
                 CandidateHeadVars)
         ),
-        MinArgsToTuple = TuningParams ^ min_args_to_tuple,
+        MinArgsToTuple = TuningParams ^ tp_min_args_to_tuple,
         ( list.length(CandidateHeadVars) < MinArgsToTuple ->
             (
                 VeryVerbose = yes,
-                io.write_string("% Too few candidate headvars\n", !IO)
+                trace [io(!IO)] (
+                    io.write_string("% Too few candidate headvars.\n", !IO)
+                )
             ;
                 VeryVerbose = no
             )
         ;
             maybe_tuple_scc_2(TraceCounts, TuningParams,
                 SCC, CandidateHeadVars, !ModuleInfo,
-                !Counter, !TransformMap, !IO, VeryVerbose)
+                !Counter, !TransformMap, VeryVerbose)
         )
     ;
         % No need to work on this SCC if there are no callers to it
@@ -294,7 +298,9 @@
         % to look at it, for intermodule tupling.
         (
             VeryVerbose = yes,
-            io.write_string("% SCC has no local callers\n", !IO)
+            trace [io(!IO)] (
+                io.write_string("% SCC has no local callers.\n", !IO)
+            )
         ;
             VeryVerbose = no
         )
@@ -305,7 +311,7 @@
 
 scc_has_local_callers(CalleeProcs, DepGraph) :-
     some [CalleeProc] (
-        CalleeProc `list.member` CalleeProcs,
+        list.member(CalleeProc, CalleeProcs),
         proc_has_local_callers(CalleeProc, DepGraph)
     ).
 
@@ -322,19 +328,22 @@
 :- pred maybe_tuple_scc_2(trace_counts::in, tuning_params::in,
     list(pred_proc_id)::in, candidate_headvars::in,
     module_info::in, module_info::out, counter::in, counter::out,
-    transform_map::in, transform_map::out, io::di, io::uo, bool::in) is det.
+    transform_map::in, transform_map::out, bool::in) is det.
 
 maybe_tuple_scc_2(TraceCounts, TuningParams, PredProcIds, CandidateHeadVars,
-        !ModuleInfo, !Counter, !TransformMap, !IO, VeryVerbose) :-
-    list.foldl(prepare_proc_for_counting, PredProcIds, !ModuleInfo),
+        !ModuleInfo, !Counter, !TransformMap, VeryVerbose) :-
+    list.foldl2(prepare_proc_for_counting, PredProcIds,
+        map.init, ReverseGoalPathMapMap, !ModuleInfo),
     % Count the average number of loads/stores without any transformation.
     count_load_stores_for_scc(TraceCounts, TuningParams, !.ModuleInfo,
-        map.init, PredProcIds, CostsWithoutTupling),
+        map.init, ReverseGoalPathMapMap, PredProcIds, CostsWithoutTupling),
     (
         VeryVerbose = yes,
         CostsWithoutTupling = costs(LoadsWoTupling, StoresWoTupling),
-        io.format("%% SCC costs without tupling = {%g, %g}\n",
-            [f(LoadsWoTupling), f(StoresWoTupling)], !IO)
+        trace [io(!IO)] (
+            io.format("%% SCC costs without tupling = {%g, %g}\n",
+                [f(LoadsWoTupling), f(StoresWoTupling)], !IO)
+        )
     ;
         VeryVerbose = no
     ),
@@ -342,21 +351,23 @@
         % Don't bother continuing.
         true
     ;
-        maybe_tuple_scc_3(TraceCounts, TuningParams, PredProcIds,
-            CandidateHeadVars, CostsWithoutTupling,
-            !ModuleInfo, !Counter, !TransformMap, !IO, VeryVerbose)
+        maybe_tuple_scc_3(TraceCounts, TuningParams, ReverseGoalPathMapMap,
+            PredProcIds, CandidateHeadVars, CostsWithoutTupling,
+            !ModuleInfo, !Counter, !TransformMap, VeryVerbose)
     ).
 
 :- pred maybe_tuple_scc_3(trace_counts::in, tuning_params::in,
-    list(pred_proc_id)::in, candidate_headvars::in, costs::in,
-    module_info::in, module_info::out, counter::in, counter::out,
-    transform_map::in, transform_map::out, io::di, io::uo, bool::in) is det.
-
-maybe_tuple_scc_3(TraceCounts, TuningParams, PredProcIds, CandidateHeadVars,
-        CostsWithoutTupling,
-        !ModuleInfo, !Counter, !TransformMap, !IO, VeryVerbose) :-
+    map(pred_proc_id, goal_reverse_path_map)::in, list(pred_proc_id)::in,
+    candidate_headvars::in, costs::in, module_info::in, module_info::out,
+    counter::in, counter::out, transform_map::in, transform_map::out,
+    bool::in) is det.
+
+maybe_tuple_scc_3(TraceCounts, TuningParams, ReverseGoalPathMapMap,
+        PredProcIds, CandidateHeadVars, CostsWithoutTupling,
+        !ModuleInfo, !Counter, !TransformMap, VeryVerbose) :-
     find_best_tupling_scheme(TraceCounts, TuningParams, !.ModuleInfo,
-        PredProcIds, CandidateHeadVars, MaybeBestScheme),
+        ReverseGoalPathMapMap, PredProcIds, CandidateHeadVars,
+        MaybeBestScheme),
     (
         MaybeBestScheme = no
     ;
@@ -364,8 +375,10 @@
         CostsWithTupling = costs(LoadsWithTupling, StoresWithTupling),
         (
             VeryVerbose = yes,
-            io.format("%% SCC costs with tupling = {%g, %g}\n",
-                [f(LoadsWithTupling), f(StoresWithTupling)], !IO)
+            trace [io(!IO)] (
+                io.format("%% SCC costs with tupling = {%g, %g}\n",
+                    [f(LoadsWithTupling), f(StoresWithTupling)], !IO)
+            )
         ;
             VeryVerbose = no
         ),
@@ -375,7 +388,9 @@
         ->
             (
                 VeryVerbose = yes,
-                io.print("% Proceeding with tupling\n", !IO)
+                trace [io(!IO)] (
+                    io.print("% Proceeding with tupling\n", !IO)
+                )
             ;
                 VeryVerbose = no
             ),
@@ -392,7 +407,7 @@
 should_use_tupling_scheme(TuningParams,
         costs(LoadsWithoutTupling, StoresWithoutTupling),
         costs(LoadsWithTupling, StoresWithTupling)) :-
-    CostsRatio = float(TuningParams ^ costs_ratio),
+    CostsRatio = float(TuningParams ^ tp_costs_ratio),
     TotalWithoutTupling = LoadsWithoutTupling + StoresWithoutTupling,
     TotalWithTupling = LoadsWithTupling + StoresWithTupling,
     ( TotalWithTupling = 0.0 ->
@@ -494,34 +509,37 @@
             ).
 
 :- pred find_best_tupling_scheme(trace_counts::in, tuning_params::in,
-    module_info::in, list(pred_proc_id)::in, candidate_headvars::in,
+    module_info::in, map(pred_proc_id, goal_reverse_path_map)::in,
+    list(pred_proc_id)::in, candidate_headvars::in,
     maybe(pair(costs, tupling_scheme))::out) is det.
 
 find_best_tupling_scheme(TraceCounts, TuningParams, ModuleInfo,
-        PredProcIds, CandidateHeadVars, MaybeBestScheme) :-
-    MinArgsToTuple = TuningParams ^ min_args_to_tuple,
+        ReverseGoalPathMapMap, PredProcIds, CandidateHeadVars,
+        MaybeBestScheme) :-
+    MinArgsToTuple = TuningParams ^ tp_min_args_to_tuple,
     fold_over_list_runs(
         find_best_tupling_scheme_2(TraceCounts, TuningParams,
-            ModuleInfo, PredProcIds),
+            ModuleInfo, ReverseGoalPathMapMap, PredProcIds),
         CandidateHeadVars, MinArgsToTuple,
         no, MaybeBestScheme).
 
 :- pred find_best_tupling_scheme_2(trace_counts::in, tuning_params::in,
-    module_info::in, list(pred_proc_id)::in, candidate_headvars::in,
+    module_info::in, map(pred_proc_id, goal_reverse_path_map)::in,
+    list(pred_proc_id)::in, candidate_headvars::in,
     maybe(pair(costs, tupling_scheme))::in,
     maybe(pair(costs, tupling_scheme))::out) is det.
 
 find_best_tupling_scheme_2(TraceCounts, TuningParams, ModuleInfo,
-        PredProcIds, CandidateHeadVars,
+        ReverseGoalPathMapMap, PredProcIds, CandidateHeadVars,
         MaybeBestScheme0, MaybeBestScheme) :-
-    MinArgsToTuple = TuningParams ^ min_args_to_tuple,
+    MinArgsToTuple = TuningParams ^ tp_min_args_to_tuple,
     list.map(
         make_tupling_proposal(ModuleInfo, CandidateHeadVars, MinArgsToTuple),
         PredProcIds, TuplingProposals),
     map.from_corresponding_lists(PredProcIds, TuplingProposals,
         TuplingScheme),
     count_load_stores_for_scc(TraceCounts, TuningParams, ModuleInfo,
-        TuplingScheme, PredProcIds, Costs),
+        TuplingScheme, ReverseGoalPathMapMap, PredProcIds, Costs),
     (
         (
             MaybeBestScheme0 = no
@@ -610,6 +628,7 @@
     module_info::in, module_info::out, counter::in, counter::out,
     transform_map::in, transform_map::out) is det.
 
+add_transformed_proc(_, no_tupling, !ModuleInfo, !TransformMap, !Counter).
 add_transformed_proc(PredProcId, tupling(_, FieldVars, _),
         !ModuleInfo, !Counter, !TransformMap) :-
     PredProcId = proc(PredId, ProcId),
@@ -653,8 +672,6 @@
         svmap.det_insert(PredProcId, TransformedProc, !TransformMap)
     ).
 
-add_transformed_proc(_, no_tupling, !ModuleInfo, !TransformMap, !Counter).
-
 %-----------------------------------------------------------------------------%
 
 :- pred make_transformed_proc(prog_var::in, prog_vars::in, insert_map::in,
@@ -666,7 +683,7 @@
     proc_info_get_argmodes(!.ProcInfo, ArgModes0),
     HeadVarsAndModes = list.filter_map_corresponding(
         (func(Var, Mode) = (Var - Mode) is semidet :-
-            not Var `list.member` FieldVarsList),
+            not list.member(Var, FieldVarsList)),
         HeadVars0, ArgModes0),
     assoc_list.keys_and_values(HeadVarsAndModes, HeadVars, ArgModes),
     proc_info_set_headvars(HeadVars ++ [CellVar], !ProcInfo),
@@ -793,33 +810,34 @@
 
 :- type count_info
     --->    count_info(
-                count_info_pred_proc_id :: pred_proc_id,
-                                        % Which procedure is being counted.
-                count_info_proc         :: proc_info,
-                count_info_module       :: module_info,
-                count_info_proc_counts  :: proc_trace_counts,
-                count_info_params       :: tuning_params,
-                tupling_scheme          :: tupling_scheme
+                ci_pred_proc_id             :: pred_proc_id,
+                                            % Which procedure is being counted.
+                ci_proc                     :: proc_info,
+                ci_module                   :: module_info,
+                ci_proc_counts              :: proc_trace_counts,
+                ci_params                   :: tuning_params,
+                ci_tupling_scheme           :: tupling_scheme,
+                ci_rev_goal_path_map        :: goal_reverse_path_map
             ).
 
 :- type tuning_params
     --->    tuning_params(
-                normal_var_load_cost    :: int,
-                normal_var_store_cost   :: int,
-                cell_var_load_cost      :: int,
-                cell_var_store_cost     :: int,
-                field_var_load_cost     :: int,
-                field_var_store_cost    :: int,
-                costs_ratio             :: int,
-                min_args_to_tuple       :: int
+                tp_normal_var_load_cost     :: int,
+                tp_normal_var_store_cost    :: int,
+                tp_cell_var_load_cost       :: int,
+                tp_cell_var_store_cost      :: int,
+                tp_field_var_load_cost      :: int,
+                tp_field_var_store_cost     :: int,
+                tp_costs_ratio              :: int,
+                tp_min_args_to_tuple        :: int
             ).
 
 :- type count_state
     --->    count_state(
-                reg_vars                :: set(prog_var),
-                stack_vars              :: set(prog_var),
-                load_costs              :: float,
-                store_costs             :: float
+                cs_reg_vars             :: set(prog_var),
+                cs_stack_vars           :: set(prog_var),
+                cs_load_costs           :: float,
+                cs_store_costs          :: float
             ).
 
 :- type costs
@@ -832,7 +850,7 @@
     is det.
 
 get_tupling_proposal(CountInfo, PredProcId) = TuplingProposal :-
-    ( map.search(CountInfo ^ tupling_scheme, PredProcId, Probe) ->
+    ( map.search(CountInfo ^ ci_tupling_scheme, PredProcId, Probe) ->
         TuplingProposal = Probe
     ;
         TuplingProposal = no_tupling
@@ -841,7 +859,7 @@
 :- func get_own_tupling_proposal(count_info) = tupling_proposal is det.
 
 get_own_tupling_proposal(CountInfo) =
-    get_tupling_proposal(CountInfo, CountInfo ^ count_info_pred_proc_id).
+    get_tupling_proposal(CountInfo, CountInfo ^ ci_pred_proc_id).
 
 %-----------------------------------------------------------------------------%
 
@@ -849,9 +867,11 @@
     % the count_load_stores_in_proc predicate to work.
     %
 :- pred prepare_proc_for_counting(pred_proc_id::in,
+    map(pred_proc_id, goal_reverse_path_map)::in,
+    map(pred_proc_id, goal_reverse_path_map)::out,
     module_info::in, module_info::out) is det.
 
-prepare_proc_for_counting(PredProcId, !ModuleInfo) :-
+prepare_proc_for_counting(PredProcId, !ReverseGoalPathMapMap, !ModuleInfo) :-
     PredProcId = proc(PredId, ProcId),
     some [!ProcInfo] (
         module_info_pred_proc_info(!.ModuleInfo, PredId, ProcId,
@@ -867,7 +887,10 @@
             opt_no_return_calls, OptNoReturnCalls),
         AllocData = alloc_data(!.ModuleInfo, !.ProcInfo,
             TypeInfoLiveness, OptNoReturnCalls),
-        fill_goal_path_slots(!.ModuleInfo, !ProcInfo),
+        fill_goal_id_slots_in_proc(!.ModuleInfo, ContainingGoalMap, !ProcInfo),
+        ReverseGoalPathMap = create_reverse_goal_path_map(ContainingGoalMap),
+        svmap.det_insert(PredProcId, ReverseGoalPathMap,
+            !ReverseGoalPathMapMap),
         proc_info_get_goal(!.ProcInfo, Goal0),
         OptTupleAlloc0 = opt_tuple_alloc,
         set.init(FailVars),
@@ -913,22 +936,25 @@
 %-----------------------------------------------------------------------------%
 
 :- pred count_load_stores_for_scc(trace_counts::in, tuning_params::in,
-    module_info::in, tupling_scheme::in, list(pred_proc_id)::in, costs::out)
-    is det.
+    module_info::in, tupling_scheme::in,
+    map(pred_proc_id, goal_reverse_path_map)::in,
+    list(pred_proc_id)::in, costs::out) is det.
 
 count_load_stores_for_scc(TraceCounts, TuningParams, ModuleInfo,
-        TuplingScheme, PredProcIds, costs(Loads, Stores)) :-
+        TuplingScheme, ReverseGoalPathMapMap, PredProcIds, Costs) :-
     list.foldl2(
         count_load_stores_for_scc_2(TraceCounts, TuningParams, ModuleInfo,
-            TuplingScheme),
-        PredProcIds, 0.0, Loads, 0.0, Stores).
+            TuplingScheme, ReverseGoalPathMapMap),
+        PredProcIds, 0.0, Loads, 0.0, Stores),
+    Costs = costs(Loads, Stores).
 
 :- pred count_load_stores_for_scc_2(trace_counts::in, tuning_params::in,
-    module_info::in, tupling_scheme::in, pred_proc_id::in,
-    float::in, float::out, float::in, float::out) is det.
+    module_info::in, tupling_scheme::in,
+    map(pred_proc_id, goal_reverse_path_map)::in,
+    pred_proc_id::in, float::in, float::out, float::in, float::out) is det.
 
 count_load_stores_for_scc_2(TraceCounts, TuningParams, ModuleInfo,
-        TuplingScheme, PredProcId, !Loads, !Stores) :-
+        TuplingScheme, ReverseGoalPathMapMap, PredProcId, !Loads, !Stores) :-
     PredProcId = proc(PredId, ProcId),
     module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
         PredInfo, ProcInfo),
@@ -944,9 +970,10 @@
     ProcLabelInContext = proc_label_in_context(pred_info_module(PredInfo),
         FileName, ProcLabel),
     ( get_proc_counts(TraceCounts, ProcLabelInContext, yes(ProcCounts)) ->
-        count_load_stores_in_proc(count_info(PredProcId, ProcInfo,
-            ModuleInfo, ProcCounts, TuningParams, TuplingScheme),
-            ProcLoads, ProcStores),
+        map.lookup(ReverseGoalPathMapMap, PredProcId, ReverseGoalPathMap),
+        CountInfo = count_info(PredProcId, ProcInfo, ModuleInfo, ProcCounts,
+            TuningParams, TuplingScheme, ReverseGoalPathMap),
+        count_load_stores_in_proc(CountInfo, ProcLoads, ProcStores),
         % XXX: There is a problem somewhere causing CALL and EXIT
         % events not to show up for some procedures in trace count files.
         % The weighting of the procedure's costs is disabled.
@@ -967,9 +994,9 @@
     is det.
 
 count_load_stores_in_proc(CountInfo, Loads, Stores) :-
-    proc(PredId, _) = CountInfo ^ count_info_pred_proc_id,
-    ProcInfo = CountInfo ^ count_info_proc,
-    ModuleInfo = CountInfo ^ count_info_module,
+    proc(PredId, _) = CountInfo ^ ci_pred_proc_id,
+    ProcInfo = CountInfo ^ ci_proc,
+    ModuleInfo = CountInfo ^ ci_module,
     initial_liveness(ProcInfo, PredId, ModuleInfo, InitialLiveness),
     CountState0 = count_state(InitialLiveness, set.init, 0.0, 0.0),
     proc_info_get_goal(ProcInfo, Goal),
@@ -988,176 +1015,168 @@
 
 count_load_stores_in_goal(Goal, CountInfo, !CountState) :-
     Goal = hlds_goal(GoalExpr, GoalInfo),
-    count_load_stores_in_goal_expr(GoalExpr, GoalInfo, CountInfo, !CountState).
-
-:- pred count_load_stores_in_goal_expr(hlds_goal_expr::in, hlds_goal_info::in,
-    count_info::in, count_state::in, count_state::out) is det.
-
-count_load_stores_in_goal_expr(GoalExpr, GoalInfo, CountInfo, !CountState) :-
-    GoalExpr = call_foreign_proc(_Attributes, PredId, ProcId, Args, ExtraArgs,
-        _MaybeTraceRuntimeCond, _PragmaCode),
-    ModuleInfo = CountInfo ^ count_info_module,
-    module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
-        _PredInfo, ProcInfo),
-    ArgVars = list.map(foreign_arg_var, Args),
-    ExtraVars = list.map(foreign_arg_var, ExtraArgs),
-    CallingProcInfo = CountInfo ^ count_info_proc,
-    proc_info_get_vartypes(CallingProcInfo, VarTypes),
-    arg_info.partition_proc_call_args(ProcInfo, VarTypes,
-        ModuleInfo, ArgVars, InputArgVarSet, OutputArgVarSet, _),
-    set.to_sorted_list(InputArgVarSet, InputArgVars),
-    list.append(InputArgVars, ExtraVars, InputVars),
     (
-        goal_info_maybe_get_maybe_need_across_call(GoalInfo,
-            MaybeNeedAcrossCall),
-        MaybeNeedAcrossCall = yes(_)
-    ->
-        count_load_stores_for_call(CountInfo, InputVars, OutputArgVarSet,
-            MaybeNeedAcrossCall, GoalInfo, !CountState)
+        GoalExpr = unify(_, _, _, Unification, _),
+        (
+            Unification = construct(CellVar, _ConsId, ArgVars, _ArgModes,
+                _HowToConstruct, _, _),
+            cls_require_in_regs(CountInfo, ArgVars, !CountState),
+            cls_put_in_regs([CellVar], !CountState)
+        ;
+            Unification = deconstruct(CellVar, _ConsId, ArgVars, _ArgModes,
+                _, _),
+            cls_put_in_regs_via_deconstruct(CountInfo, CellVar, ArgVars,
+                !CountState)
+        ;
+            Unification = assign(ToVar, FromVar),
+            cls_require_in_reg(CountInfo, FromVar, !CountState),
+            cls_put_in_regs([ToVar], !CountState)
+        ;
+            Unification = simple_test(Var1, Var2),
+            cls_require_in_regs(CountInfo, [Var1, Var2], !CountState)
+        ;
+            Unification = complicated_unify(_, _, _),
+            unexpected(this_file,
+                "count_load_stores_in_goal: complicated_unify")
+        )
     ;
-        cls_require_in_regs(CountInfo, InputVars, !CountState),
-        cls_clobber_regs(OutputArgVarSet, !CountState)
-    ).
-
-count_load_stores_in_goal_expr(GoalExpr, GoalInfo, CountInfo, !CountState) :-
-    GoalExpr = generic_call(GenericCall, ArgVars, ArgModes, _Detism),
-    ProcInfo = CountInfo ^ count_info_proc,
-    ModuleInfo = CountInfo ^ count_info_module,
-    goal_info_get_maybe_need_across_call(GoalInfo, MaybeNeedAcrossCall),
-    proc_info_get_vartypes(ProcInfo, VarTypes),
-    list.map(map.lookup(VarTypes), ArgVars, ArgTypes),
-    arg_info.compute_in_and_out_vars(ModuleInfo, ArgVars,
-        ArgModes, ArgTypes, InputArgs, OutputArgs),
-
-    (
-        ( GenericCall = higher_order(_, _, _, _)
-        ; GenericCall = class_method(_, _, _, _)
-        ; GenericCall = event_call(_)
-        ),
-        module_info_get_globals(ModuleInfo, Globals),
-        call_gen.generic_call_info(Globals, GenericCall,
-            length(InputArgs), _, GenericVarsArgInfos, _, _),
-        assoc_list.keys(GenericVarsArgInfos, GenericVars),
-        list.append(GenericVars, InputArgs, Inputs),
-        set.list_to_set(OutputArgs, Outputs),
-        count_load_stores_for_call(CountInfo, Inputs, Outputs,
-            MaybeNeedAcrossCall, GoalInfo, !CountState)
+        GoalExpr = plain_call(PredId, ProcId, _, Builtin, _, _),
+        (
+            Builtin = not_builtin,
+            TuplingProposal = get_tupling_proposal(CountInfo,
+                proc(PredId, ProcId)),
+            TuplingProposal = tupling(_, _, _)
+        ->
+            count_load_stores_in_call_to_tupled(GoalExpr, GoalInfo,
+                CountInfo, TuplingProposal, !CountState)
+        ;
+            count_load_stores_in_call_to_not_tupled(GoalExpr, GoalInfo,
+                CountInfo, !CountState)
+        )
     ;
-        GenericCall = cast(_),
-        % Casts are generated inline.
-        cls_require_in_regs(CountInfo, InputArgs, !CountState),
-        cls_put_in_regs(OutputArgs, !CountState)
-    ).
+        GoalExpr = generic_call(GenericCall, ArgVars, ArgModes, _Detism),
+        ProcInfo = CountInfo ^ ci_proc,
+        ModuleInfo = CountInfo ^ ci_module,
+        goal_info_get_maybe_need_across_call(GoalInfo, MaybeNeedAcrossCall),
+        proc_info_get_vartypes(ProcInfo, VarTypes),
+        list.map(map.lookup(VarTypes), ArgVars, ArgTypes),
+        arg_info.compute_in_and_out_vars(ModuleInfo, ArgVars,
+            ArgModes, ArgTypes, InputArgs, OutputArgs),
 
-count_load_stores_in_goal_expr(GoalExpr, GoalInfo, CountInfo, !CountState) :-
-    GoalExpr = plain_call(PredId, ProcId, _, Builtin, _, _),
-    (
-        Builtin = not_builtin,
-        TuplingProposal = get_tupling_proposal(CountInfo,
-            proc(PredId, ProcId)),
-        TuplingProposal = tupling(_, _, _)
-    ->
-        count_load_stores_in_call_to_tupled(GoalExpr, GoalInfo,
-            CountInfo, TuplingProposal, !CountState)
+        (
+            ( GenericCall = higher_order(_, _, _, _)
+            ; GenericCall = class_method(_, _, _, _)
+            ; GenericCall = event_call(_)
+            ),
+            module_info_get_globals(ModuleInfo, Globals),
+            call_gen.generic_call_info(Globals, GenericCall,
+                length(InputArgs), _, GenericVarsArgInfos, _, _),
+            assoc_list.keys(GenericVarsArgInfos, GenericVars),
+            list.append(GenericVars, InputArgs, Inputs),
+            set.list_to_set(OutputArgs, Outputs),
+            count_load_stores_for_call(CountInfo, Inputs, Outputs,
+                MaybeNeedAcrossCall, GoalInfo, !CountState)
+        ;
+            GenericCall = cast(_),
+            % Casts are generated inline.
+            cls_require_in_regs(CountInfo, InputArgs, !CountState),
+            cls_put_in_regs(OutputArgs, !CountState)
+        )
     ;
-        count_load_stores_in_call_to_not_tupled(GoalExpr, GoalInfo,
-            CountInfo, !CountState)
-    ).
-
-count_load_stores_in_goal_expr(GoalExpr, _GoalInfo, CountInfo, !CountState) :-
-    GoalExpr = unify(_, _, _, Unification, _),
-    (
-        Unification = construct(CellVar, _ConsId, ArgVars, _ArgModes,
-            _HowToConstruct, _, _),
-        cls_require_in_regs(CountInfo, ArgVars, !CountState),
-        cls_put_in_regs([CellVar], !CountState)
+        GoalExpr = call_foreign_proc(_Attributes, PredId, ProcId,
+            Args, ExtraArgs, _MaybeTraceRuntimeCond, _PragmaCode),
+        ModuleInfo = CountInfo ^ ci_module,
+        module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
+            _PredInfo, ProcInfo),
+        ArgVars = list.map(foreign_arg_var, Args),
+        ExtraVars = list.map(foreign_arg_var, ExtraArgs),
+        CallingProcInfo = CountInfo ^ ci_proc,
+        proc_info_get_vartypes(CallingProcInfo, VarTypes),
+        arg_info.partition_proc_call_args(ProcInfo, VarTypes,
+            ModuleInfo, ArgVars, InputArgVarSet, OutputArgVarSet, _),
+        set.to_sorted_list(InputArgVarSet, InputArgVars),
+        list.append(InputArgVars, ExtraVars, InputVars),
+        (
+            goal_info_maybe_get_maybe_need_across_call(GoalInfo,
+                MaybeNeedAcrossCall),
+            MaybeNeedAcrossCall = yes(_)
+        ->
+            count_load_stores_for_call(CountInfo, InputVars, OutputArgVarSet,
+                MaybeNeedAcrossCall, GoalInfo, !CountState)
+        ;
+            cls_require_in_regs(CountInfo, InputVars, !CountState),
+            cls_clobber_regs(OutputArgVarSet, !CountState)
+        )
     ;
-        Unification = deconstruct(CellVar, _ConsId, ArgVars, _ArgModes, _, _),
-        cls_put_in_regs_via_deconstruct(CountInfo, CellVar, ArgVars,
-            !CountState)
+        GoalExpr = scope(Reason, SubGoal),
+        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+            % There are no loads or stored in these scopes.
+            true
+        ;
+            count_load_stores_in_goal(SubGoal, CountInfo, !CountState)
+        )
     ;
-        Unification = assign(ToVar, FromVar),
-        cls_require_in_reg(CountInfo, FromVar, !CountState),
-        cls_put_in_regs([ToVar], !CountState)
+        GoalExpr = conj(ConjType, Goals),
+        (
+            ConjType = plain_conj,
+            count_load_stores_in_conj(Goals, CountInfo, !CountState)
+        ;
+            ConjType = parallel_conj,
+            sorry(this_file, "tupling with parallel conjunctions")
+        )
     ;
-        Unification = simple_test(Var1, Var2),
-        cls_require_in_regs(CountInfo, [Var1, Var2], !CountState)
+        GoalExpr = disj(Goals),
+        count_load_stores_in_disj(Goals, CountInfo, !CountState)
     ;
-        Unification = complicated_unify(_, _, _),
-        unexpected(this_file, "count_load_stores_in_goal: complicated_unify")
-    ).
-
-count_load_stores_in_goal_expr(scope(_Reason, Goal), _GoalInfo, CountInfo,
-        !CountState) :-
-    % XXX We should special-case the handling of from_ground_term_construct
-    % scopes.
-    count_load_stores_in_goal(Goal, CountInfo, !CountState).
-
-count_load_stores_in_goal_expr(conj(ConjType, Goals), _GoalInfo, CountInfo,
-        !CountState) :-
-    (
-        ConjType = plain_conj,
-        count_load_stores_in_conj(Goals, CountInfo, !CountState)
+        GoalExpr = switch(_Var, _Det, Cases),
+        count_load_stores_in_cases(Cases, CountInfo, !CountState)
     ;
-        ConjType = parallel_conj,
-        sorry(this_file, "tupling with parallel conjunctions")
-    ).
-
-count_load_stores_in_goal_expr(disj(Goals), _GoalInfo, CountInfo,
-        !CountState) :-
-    count_load_stores_in_disj(Goals, CountInfo, !CountState).
-
-count_load_stores_in_goal_expr(switch(_Var, _Det, Cases), _GoalInfo, CountInfo,
-        !CountState) :-
-    count_load_stores_in_cases(Cases, CountInfo, !CountState).
-
-count_load_stores_in_goal_expr(negation(Goal), _GoalInfo, CountInfo,
-        !CountState) :-
-    goal_info_get_resume_point(Goal ^ hlds_goal_info, ResumePoint),
-    (
-        ResumePoint = resume_point(LiveVars, _ResumeLocs),
-        cls_require_flushed(CountInfo, LiveVars, !CountState)
+        GoalExpr = negation(SubGoal),
+        goal_info_get_resume_point(SubGoal ^ hlds_goal_info, ResumePoint),
+        (
+            ResumePoint = resume_point(LiveVars, _ResumeLocs),
+            cls_require_flushed(CountInfo, LiveVars, !CountState)
+        ;
+            ResumePoint = no_resume_point,
+            unexpected(this_file,
+                "count_load_stores_in_goal: no_resume_point for not")
+        ),
+        count_load_stores_in_goal(SubGoal, CountInfo, !CountState)
     ;
-        ResumePoint = no_resume_point,
-        unexpected(this_file,
-            "count_load_stores_in_goal: no_resume_point for not")
-    ),
-    count_load_stores_in_goal(Goal, CountInfo, !CountState).
-
-count_load_stores_in_goal_expr(if_then_else(_, Cond, Then, Else), _GoalInfo,
-        CountInfo, !CountState) :-
-    goal_info_get_resume_point(Cond ^ hlds_goal_info, ResumePoint),
-    (
-        ResumePoint = resume_point(LiveVars, _ResumeLocs),
-        cls_require_flushed(CountInfo, LiveVars, !CountState),
-        count_load_stores_in_goal(Cond, CountInfo, !CountState),
-
-        reset_count_state_counts(!.CountState, ResetCountInfo),
-        count_load_stores_in_goal(Then, CountInfo,
-            ResetCountInfo, ThenCountInfo),
-        count_load_stores_in_goal(Else, CountInfo,
-            ResetCountInfo, ElseCountInfo),
-
-        ProcCounts = CountInfo ^ count_info_proc_counts,
-        ThenGoalPath = goal_info_get_goal_path(Then ^ hlds_goal_info),
-        ElseGoalPath = goal_info_get_goal_path(Else ^ hlds_goal_info),
-        get_ite_relative_frequencies(ProcCounts,
-            ThenGoalPath, ElseGoalPath,
-            ThenRelFreq, ElseRelFreq),
+        GoalExpr = if_then_else(_, Cond, Then, Else),
+        goal_info_get_resume_point(Cond ^ hlds_goal_info, ResumePoint),
+        (
+            ResumePoint = resume_point(LiveVars, _ResumeLocs),
+            cls_require_flushed(CountInfo, LiveVars, !CountState),
+            count_load_stores_in_goal(Cond, CountInfo, !CountState),
+
+            reset_count_state_counts(!.CountState, ResetCountInfo),
+            count_load_stores_in_goal(Then, CountInfo,
+                ResetCountInfo, ThenCountInfo),
+            count_load_stores_in_goal(Else, CountInfo,
+                ResetCountInfo, ElseCountInfo),
+
+            ProcCounts = CountInfo ^ ci_proc_counts,
+            ThenGoalId = goal_info_get_goal_id(Then ^ hlds_goal_info),
+            ElseGoalId = goal_info_get_goal_id(Else ^ hlds_goal_info),
+            get_ite_relative_frequencies(ProcCounts,
+                CountInfo ^ ci_rev_goal_path_map,
+                ThenGoalId, ElseGoalId, ThenRelFreq, ElseRelFreq),
 
-        add_branch_costs(ThenCountInfo, ThenRelFreq, !CountState),
-        add_branch_costs(ElseCountInfo, ElseRelFreq, !CountState)
+            add_branch_costs(ThenCountInfo, ThenRelFreq, !CountState),
+            add_branch_costs(ElseCountInfo, ElseRelFreq, !CountState)
+        ;
+            ResumePoint = no_resume_point,
+            unexpected(this_file,
+                "count_load_stores_in_goal: no_resume_point for if_then_else")
+        )
     ;
-        ResumePoint = no_resume_point,
+        GoalExpr = shorthand(_),
+        % These should have been expanded out by now.
         unexpected(this_file,
-            "count_load_stores_in_goal: no_resume_point for if_then_else")
+            "count_load_stores_in_goal: shorthand")
     ).
 
-count_load_stores_in_goal_expr(shorthand(_), _, _, !_) :-
-    % These should have been expanded out by now.
-    unexpected(this_file,
-        "count_load_stores_in_goal_expr: shorthand").
-
 %-----------------------------------------------------------------------------%
 
 :- inst call_goal_expr
@@ -1174,10 +1193,10 @@
         CalleeTuplingProposal, !CountState) :-
     GoalExpr = plain_call(CalleePredId, CalleeProcId, ArgVars, _, _, _),
     CalleeTuplingProposal = tupling(CellVar, FieldVars, FieldVarArgPos),
-    ModuleInfo = CountInfo ^ count_info_module,
+    ModuleInfo = CountInfo ^ ci_module,
     module_info_pred_proc_info(ModuleInfo, CalleePredId, CalleeProcId,
         _, CalleeProcInfo),
-    CallingProcInfo = CountInfo ^ count_info_proc,
+    CallingProcInfo = CountInfo ^ ci_proc,
     proc_info_get_vartypes(CallingProcInfo, VarTypes),
     arg_info.partition_proc_call_args(CalleeProcInfo, VarTypes,
         ModuleInfo, ArgVars, InputArgs0, Outputs, _),
@@ -1192,9 +1211,9 @@
         % then they could be checked also.
         get_own_tupling_proposal(CountInfo) = tupling(_, _, _),
         all [Var] (
-            Var `list.member` FieldVars
+            list.member(Var, FieldVars)
         => (
-            Var `set.member` InputArgs0,
+            set.member(Var, InputArgs0),
             assoc_list.search(FieldVarArgPos, Var, Pos),
             list.nth_member_search(ArgVars, Var, Pos)
         ))
@@ -1206,10 +1225,10 @@
     ;
         % The cell var cannot be used for the callee, so we must add
         % the cost of constructing a new tuple.
-        TuplingParams = CountInfo ^ count_info_params,
-        CellVarStoreCost = float(TuplingParams ^ cell_var_store_cost),
-        !:CountState = (!.CountState ^ store_costs :=
-            (!.CountState ^ store_costs + CellVarStoreCost)),
+        TuplingParams = CountInfo ^ ci_params,
+        CellVarStoreCost = float(TuplingParams ^ tp_cell_var_store_cost),
+        !CountState ^ cs_store_costs :=
+            !.CountState ^ cs_store_costs + CellVarStoreCost,
         InputArgs = InputArgs0
     ),
     set.to_sorted_list(InputArgs, Inputs),
@@ -1224,10 +1243,10 @@
 count_load_stores_in_call_to_not_tupled(GoalExpr, GoalInfo, CountInfo,
         !CountState) :-
     GoalExpr = plain_call(PredId, ProcId, ArgVars, Builtin, _, _),
-    ModuleInfo = CountInfo ^ count_info_module,
+    ModuleInfo = CountInfo ^ ci_module,
     module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
         _PredInfo, CalleeProcInfo),
-    ProcInfo = CountInfo ^ count_info_proc,
+    ProcInfo = CountInfo ^ ci_proc,
     proc_info_get_vartypes(ProcInfo, VarTypes),
     arg_info.partition_proc_call_args(CalleeProcInfo, VarTypes,
         ModuleInfo, ArgVars, InputArgs, Outputs, _),
@@ -1292,9 +1311,10 @@
     reset_count_state_counts(!.CountState, BranchCountState0),
     count_load_stores_in_goal(Goal, CountInfo,
         BranchCountState0, BranchCountState),
-    ProcCounts = CountInfo ^ count_info_proc_counts,
-    GoalPath = goal_info_get_goal_path(GoalInfo),
-    get_disjunct_relative_frequency(ProcCounts, GoalPath, RelFreq),
+    ProcCounts = CountInfo ^ ci_proc_counts,
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    get_disjunct_relative_frequency(ProcCounts,
+        CountInfo ^ ci_rev_goal_path_map, GoalId, RelFreq),
     add_branch_costs(BranchCountState, RelFreq, !CountState),
     count_load_stores_in_disj(Goals, CountInfo, !CountState).
 
@@ -1315,9 +1335,10 @@
     reset_count_state_counts(!.CountState, BranchCountState0),
     count_load_stores_in_goal(Goal, CountInfo, BranchCountState0,
         BranchCountState),
-    ProcCounts = CountInfo ^ count_info_proc_counts,
-    GoalPath = goal_info_get_goal_path(GoalInfo),
-    get_case_relative_frequency(ProcCounts, GoalPath, RelFreq),
+    ProcCounts = CountInfo ^ ci_proc_counts,
+    GoalId = goal_info_get_goal_id(GoalInfo),
+    get_case_relative_frequency(ProcCounts,
+        CountInfo ^ ci_rev_goal_path_map, GoalId, RelFreq),
     add_branch_costs(BranchCountState, RelFreq, !CountState),
     count_load_stores_in_cases(Cases, CountInfo, !CountState).
 
@@ -1338,7 +1359,7 @@
     (
         TuplingProposal = get_own_tupling_proposal(CountInfo),
         TuplingProposal = tupling(_, FieldVars, _),
-        Var `list.member` FieldVars
+        list.member(Var, FieldVars)
     ->
         cls_require_field_var_in_reg(CountInfo, TuplingProposal,
             Var, !CountState)
@@ -1350,8 +1371,8 @@
     count_state::in, count_state::out) is det.
 
 cls_require_normal_var_in_reg(CountInfo, Var, !CountState) :-
-    TuningParams = CountInfo ^ count_info_params,
-    NormalLoadCost = TuningParams ^ normal_var_load_cost,
+    TuningParams = CountInfo ^ ci_params,
+    NormalLoadCost = TuningParams ^ tp_normal_var_load_cost,
     cls_require_var_in_reg_with_cost(NormalLoadCost, Var, !CountState).
 
 :- pred cls_require_field_var_in_reg(count_info::in,
@@ -1361,18 +1382,18 @@
 cls_require_field_var_in_reg(CountInfo, TuplingProposal, FieldVar,
         CountState0, CountState) :-
     CountState0 = count_state(RegVars0, StackVars, Loads0, Stores),
-    ( FieldVar `set.member` RegVars0 ->
+    ( set.member(FieldVar, RegVars0) ->
         CountState = CountState0
     ;
         TuplingProposal = tupling(CellVar, _, _),
-        TuningParams = CountInfo ^ count_info_params,
-        CvLoadCost = float(TuningParams ^ cell_var_load_cost),
-        FvLoadCost = float(TuningParams ^ field_var_load_cost),
-        ( CellVar `set.member` RegVars0 ->
-            RegVars = RegVars0 `insert` FieldVar,
+        TuningParams = CountInfo ^ ci_params,
+        CvLoadCost = float(TuningParams ^ tp_cell_var_load_cost),
+        FvLoadCost = float(TuningParams ^ tp_field_var_load_cost),
+        ( set.member(CellVar, RegVars0) ->
+            set.insert(RegVars0, FieldVar, RegVars),
             Loads = Loads0 + FvLoadCost
         ;
-            RegVars = RegVars0 `insert_list` [CellVar, FieldVar],
+            set.insert_list(RegVars0, [CellVar, FieldVar], RegVars),
             Loads = Loads0 + CvLoadCost + FvLoadCost
         ),
         CountState = count_state(RegVars, StackVars, Loads, Stores)
@@ -1383,10 +1404,10 @@
 
 cls_require_var_in_reg_with_cost(LoadCost, Var, CountState0, CountState) :-
     CountState0 = count_state(RegVars0, StackVars, Loads0, Stores),
-    ( Var `set.member` RegVars0 ->
+    ( set.member(Var, RegVars0) ->
         CountState = CountState0
     ;
-        RegVars = RegVars0 `insert` Var,
+        set.insert(RegVars0, Var, RegVars),
         Loads = Loads0 + float(LoadCost),
         CountState = count_state(RegVars, StackVars, Loads, Stores)
     ).
@@ -1396,18 +1417,19 @@
 :- pred cls_put_in_regs(prog_vars::in, count_state::in, count_state::out)
     is det.
 
-cls_put_in_regs(Vars, State0, State) :-
-    RegVars0 = (State0 ^ reg_vars),
-    State = (State0 ^ reg_vars := RegVars0 `insert_list` Vars).
+cls_put_in_regs(Vars, !CountState) :-
+    RegVars0 = !.CountState ^ cs_reg_vars,
+    set.insert_list(RegVars0, Vars, RegVars),
+    !CountState ^ cs_reg_vars := RegVars.
 
 :- pred cls_put_in_regs_via_deconstruct(count_info::in, prog_var::in,
     prog_vars::in, count_state::in, count_state::out) is det.
 
 cls_put_in_regs_via_deconstruct(CountInfo,
         DeconstructCellVar, DeconstructFieldVars, !State) :-
-    TuningParams = CountInfo ^ count_info_params,
-    CvLoadCost = TuningParams ^ cell_var_load_cost,
-    FvLoadCost = TuningParams ^ field_var_load_cost,
+    TuningParams = CountInfo ^ ci_params,
+    CvLoadCost = TuningParams ^ tp_cell_var_load_cost,
+    FvLoadCost = TuningParams ^ tp_field_var_load_cost,
     TuplingProposal = get_own_tupling_proposal(CountInfo),
     (
         TuplingProposal = no_tupling,
@@ -1444,7 +1466,7 @@
 
 cls_require_flushed(CountInfo, Vars, !CountState) :-
     TuplingProposal = get_own_tupling_proposal(CountInfo),
-    TuningParams = CountInfo ^ count_info_params,
+    TuningParams = CountInfo ^ ci_params,
     set.fold(cls_require_flushed_2(TuplingProposal, TuningParams),
         Vars, !CountState).
 
@@ -1452,16 +1474,16 @@
     prog_var::in, count_state::in, count_state::out) is det.
 
 cls_require_flushed_2(no_tupling, TuningParams, Var, !CountState) :-
-    StoreCost = TuningParams ^ normal_var_store_cost,
+    StoreCost = TuningParams ^ tp_normal_var_store_cost,
     cls_require_flushed_with_cost(StoreCost, Var, !CountState).
 
 cls_require_flushed_2(tupling(CellVar, FieldVars, _), TuningParams, Var,
         !CountState) :-
     ( list.member(Var, FieldVars) ->
-        FvStoreCost = TuningParams ^ field_var_store_cost,
+        FvStoreCost = TuningParams ^ tp_field_var_store_cost,
         cls_require_flushed_with_cost(FvStoreCost, CellVar, !CountState)
     ;
-        StoreCost = TuningParams ^ normal_var_store_cost,
+        StoreCost = TuningParams ^ tp_normal_var_store_cost,
         cls_require_flushed_with_cost(StoreCost, Var, !CountState)
     ).
 
@@ -1487,15 +1509,16 @@
 :- pred cls_clobber_regs(set(prog_var)::in, count_state::in, count_state::out)
     is det.
 
-cls_clobber_regs(NewVars, CountState0, CountState0 ^ reg_vars := NewVars).
+cls_clobber_regs(NewVars, !CountState) :-
+    !CountState ^ cs_reg_vars := NewVars.
 
 %-----------------------------------------------------------------------------%
 
 :- pred reset_count_state_counts(count_state::in, count_state::out) is det.
 
 reset_count_state_counts(!CountState) :-
-    !:CountState = !.CountState ^ load_costs := 0.0,
-    !:CountState = !.CountState ^ store_costs := 0.0.
+    !CountState ^ cs_load_costs := 0.0,
+    !CountState ^ cs_store_costs := 0.0.
 
 :- pred add_branch_costs(count_state::in, float::in,
     count_state::in, count_state::out) is det.
@@ -1503,10 +1526,8 @@
 add_branch_costs(BranchState, Weight, !CountState) :-
     BranchState = count_state(_, _, BranchLoads, BranchStores),
     !.CountState = count_state(_, _, Loads0, Stores0),
-    !:CountState = !.CountState ^ load_costs
-        := Loads0 + Weight * BranchLoads,
-    !:CountState = !.CountState ^ store_costs
-        := Stores0 + Weight * BranchStores.
+    !CountState ^ cs_load_costs := Loads0 + Weight * BranchLoads,
+    !CountState ^ cs_store_costs := Stores0 + Weight * BranchStores.
 
 %-----------------------------------------------------------------------------%
 %
@@ -1897,8 +1918,8 @@
     map.lookup(ProcCounts, port_only(port_call), ContextCount),
     Count = ContextCount ^ exec_count.
 
-:- pred get_path_only_count(proc_trace_counts::in, goal_path::in, int::out)
-    is det.
+:- pred get_path_only_count(proc_trace_counts::in, reverse_goal_path::in,
+    int::out) is det.
 
 get_path_only_count(ProcCounts, GoalPath, Count) :-
     PathPort = path_only(GoalPath),
@@ -1909,10 +1930,13 @@
     ).
 
 :- pred get_ite_relative_frequencies(proc_trace_counts::in,
-    goal_path::in, goal_path::in, float::out, float::out) is det.
+    goal_reverse_path_map::in, goal_id::in, goal_id::in,
+    float::out, float::out) is det.
 
-get_ite_relative_frequencies(ProcCounts, ThenGoalPath, ElseGoalPath,
-        ThenRelFreq, ElseRelFreq) :-
+get_ite_relative_frequencies(ProcCounts, ReverseGoalPathMap,
+        ThenGoalId, ElseGoalId, ThenRelFreq, ElseRelFreq) :-
+    map.lookup(ReverseGoalPathMap, ThenGoalId, ThenGoalPath),
+    map.lookup(ReverseGoalPathMap, ElseGoalId, ElseGoalPath),
     get_path_only_count(ProcCounts, ThenGoalPath, ThenCounts),
     get_path_only_count(ProcCounts, ElseGoalPath, ElseCounts),
     Total = ThenCounts + ElseCounts,
@@ -1924,18 +1948,20 @@
         ElseRelFreq = 0.5
     ).
 
-:- pred get_disjunct_relative_frequency(proc_trace_counts::in, goal_path::in,
-    float::out) is det.
+:- pred get_disjunct_relative_frequency(proc_trace_counts::in,
+    goal_reverse_path_map::in, goal_id::in, float::out) is det.
 
-get_disjunct_relative_frequency(ProcCounts, GoalPath, RelFreq) :-
+get_disjunct_relative_frequency(ProcCounts, ReverseGoalPathMap,
+        GoalId, RelFreq) :-
+    map.lookup(ReverseGoalPathMap, GoalId, GoalPath),
+    GoalPath = rgp(RevGoalSteps),
     (
-        goal_path_remove_last(GoalPath, InitialSteps, LastStep),
-        LastStep = step_disj(Num)
+        RevGoalSteps = [LastStep | PrevSteps],
+        LastStep = step_disj(_)
     ->
-        get_path_only_count(ProcCounts,
-            goal_path_add_at_end(InitialSteps, step_disj(Num)), DisjCount),
-        get_path_only_count(ProcCounts,
-            goal_path_add_at_end(InitialSteps, step_disj(1)), FirstDisjCount),
+        FirstDisjGoalPath = rgp([step_disj(1) | PrevSteps]),
+        get_path_only_count(ProcCounts, GoalPath, DisjCount),
+        get_path_only_count(ProcCounts, FirstDisjGoalPath, FirstDisjCount),
         ( FirstDisjCount = 0 ->
             RelFreq = 0.0
         ;
@@ -1947,10 +1973,11 @@
             "did not see disj(N) at head of goal path")
     ).
 
-:- pred get_case_relative_frequency(proc_trace_counts::in, goal_path::in,
-    float::out) is det.
+:- pred get_case_relative_frequency(proc_trace_counts::in,
+    goal_reverse_path_map::in, goal_id::in, float::out) is det.
 
-get_case_relative_frequency(ProcCounts, GoalPath, RelFreq) :-
+get_case_relative_frequency(ProcCounts, ReverseGoalPathMap, GoalId, RelFreq) :-
+    map.lookup(ReverseGoalPathMap, GoalId, GoalPath),
     get_path_only_count(ProcCounts, GoalPath, CaseTotal),
     get_switch_total_count(ProcCounts, GoalPath, SwitchTotal),
     ( SwitchTotal = 0 ->
@@ -1959,13 +1986,14 @@
         RelFreq = float(CaseTotal) / float(SwitchTotal)
     ).
 
-:- pred get_switch_total_count(proc_trace_counts::in, goal_path::in,
+:- pred get_switch_total_count(proc_trace_counts::in, reverse_goal_path::in,
     int::out) is det.
 
 get_switch_total_count(ProcCounts, GoalPath, Total) :-
+    % XXX This is very inefficient.
     map.foldl(get_switch_total_count_2(GoalPath), ProcCounts, 0, Total).
 
-:- pred get_switch_total_count_2(goal_path::in, path_port::in,
+:- pred get_switch_total_count_2(reverse_goal_path::in, path_port::in,
     line_no_and_count::in, int::in, int::out) is det.
 
 get_switch_total_count_2(SwitchGoalPath, PathPort, LineNoAndCount,
@@ -1976,10 +2004,10 @@
         true
     ).
 
-:- pred case_in_switch(goal_path::in, path_port::in) is semidet.
+:- pred case_in_switch(reverse_goal_path::in, path_port::in) is semidet.
 
 case_in_switch(GoalPath, path_only(GoalPath)) :-
-    LastStep = goal_path_get_last(GoalPath),
+    GoalPath = rgp([LastStep | _]),
     LastStep = step_switch(_, _).
 
 %-----------------------------------------------------------------------------%
Index: compiler/type_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/type_constraints.m,v
retrieving revision 1.10
diff -u -r1.10 type_constraints.m
--- compiler/type_constraints.m	30 Jul 2010 05:16:18 -0000	1.10
+++ compiler/type_constraints.m	23 Aug 2010 12:18:26 -0000
@@ -32,7 +32,7 @@
 
 :- implementation.
 
-:- import_module check_hlds.goal_path.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_data.
@@ -102,9 +102,9 @@
                 % The context of the goal that creates the conjunction.
                 tconstr_context     :: prog_context,
 
-                % The goal path of the goal which created the constraint,
+                % The id of the goal which created the constraint,
                 % if it is relevant.
-                tconstr_goal_path   :: maybe(goal_path),
+                tconstr_goal_id     :: maybe(goal_id),
 
                 % The predicate id of the predicate call, if this is a
                 % predicate call constraint.
@@ -286,8 +286,6 @@
         pred_info_get_context(!.PredInfo, Context),
         pred_info_get_clauses_info(!.PredInfo, !:ClausesInfo),
         clauses_info_get_varset(!.ClausesInfo, ProgVarSet),
-        clauses_info_get_clauses_rep(!.ClausesInfo, ClausesRep0, ItemNumbers),
-        get_clause_list(ClausesRep0, !:Clauses),
 
         trace [compile_time(flag("type_error_diagnosis")), io(!IO)] (
             LineNumber = string.int_to_string(term.context_line(Context)),
@@ -310,8 +308,13 @@
         ),
 
         % Generate constraints for each clause of the predicate.
+        fill_goal_id_slots_in_clauses(!.HLDS, ContainingGoalMap,
+            !ClausesInfo),
+        ForwardGoalPathMap =
+            create_forward_goal_path_map(ContainingGoalMap),
+        clauses_info_get_clauses_rep(!.ClausesInfo, ClausesRep0, ItemNumbers),
+        get_clause_list(ClausesRep0, !:Clauses),
         list.map(get_clause_body, !.Clauses, !:Goals),
-        list.map(fill_goal_path_slots_in_goal_2(map.init, !.HLDS), !Goals),
         list.foldl(goal_to_constraint(!.Environment), !.Goals, !TCInfo),
         trace [compile_time(flag("type_error_diagnosis")), io(!IO)] (
             print_pred_constraint(!.TCInfo, ProgVarSet, !IO)
@@ -319,7 +322,7 @@
 
         % Solve all the constraints.
         find_type_constraint_solutions(Context, ProgVarSet, DomainMap0,
-                !TCInfo),
+            !TCInfo),
         list.foldl2_corresponding(unify_equal_tvars(!.TCInfo, set.init),
             HeadTVars, HeadTVars,
             map.init, ReplacementMap, DomainMap0, DomainMap),
@@ -329,7 +332,9 @@
 
         % Update the HLDS with the results of the solving and report any
         % ambiguity errors found in this process.
-        list.map2(update_goal(!.PredEnv, !.TCInfo ^ tconstr_constraint_map),
+        list.map2(
+            update_goal(!.PredEnv, !.TCInfo ^ tconstr_constraint_map,
+                ForwardGoalPathMap),
             !Goals, PredErrors),
         create_vartypes_map(Context, ProgVarSet, !.TCInfo ^ tconstr_tvarset,
             !.TCInfo ^ tconstr_var_map, DomainMap, ReplacementMap, !:Vartypes,
@@ -387,10 +392,11 @@
     % If there is an ambiguous predicate call, chooses one predicate to be
     % the "correct" one and returns an error message describing the problem.
     %
-:- pred update_goal(pred_env::in, type_constraint_map::in, hlds_goal::in,
-    hlds_goal::out, list(error_msg)::out) is det.
+:- pred update_goal(pred_env::in, type_constraint_map::in,
+    goal_forward_path_map::in, hlds_goal::in, hlds_goal::out,
+    list(error_msg)::out) is det.
 
-update_goal(PredEnv, ConstraintMap, !Goal, Errors) :-
+update_goal(PredEnv, ConstraintMap, ForwardGoalPathMap, !Goal, Errors) :-
     Disjunctions = map.values(ConstraintMap),
     list.filter_map(has_one_disjunct, Disjunctions, Conjunctions),
     list.filter_map(pred_constraint_info, Conjunctions, DefinitePredData),
@@ -402,38 +408,43 @@
         AmbigPredDatas),
     AmbigPredData = list.filter_map(list.head, AmbigPredDatas),
     PredData = DefinitePredData ++ AmbigPredData,
-    list.foldl(apply_pred_data_to_goal, PredData, !Goal).
+    list.foldl(apply_pred_data_to_goal(ForwardGoalPathMap), PredData, !Goal).
 
-:- pred apply_pred_data_to_goal(pair(goal_path, pred_id)::in,
-    hlds_goal::in, hlds_goal::out) is det.
+:- pred apply_pred_data_to_goal(goal_forward_path_map::in,
+    pair(goal_id, pred_id)::in, hlds_goal::in, hlds_goal::out) is det.
 
-apply_pred_data_to_goal((GoalPath0 - PredId), !Goal) :-
-    program_representation.goal_path_consable(GoalPath0, GoalPath),
+apply_pred_data_to_goal(ForwardGoalPathMap, GoalId - PredId, !Goal) :-
+    map.lookup(ForwardGoalPathMap, GoalId, GoalPath),
+    maybe_transform_goal_at_goal_path(set_goal_pred_id(PredId), GoalPath,
+        !.Goal, Result),
     (
-        goal_util.maybe_transform_goal_at_goal_path(set_goal_pred_id(PredId),
-            GoalPath, !.Goal, ok(GoalPrime))
-    ->
-        !:Goal = GoalPrime
+        Result = ok(!:Goal)
     ;
-        true
+        ( Result = error(_)
+        ; Result = goal_not_found
+        ),
+        unexpected(this_file, "apply_pred_data_to_goal: not ok")
     ).
 
-:- pred set_goal_pred_id(pred_id::in, hlds_goal::in, 
+:- 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(_, _, _, _, _, _) ->
+set_goal_pred_id(PredId, Goal0, MaybeGoal) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo),
+    ( GoalExpr0 = plain_call(_, _, _, _, _, _) ->
         trace [compile_time(flag("type_error_diagnosis")), io(!IO)] (
-            Context = goal_info_get_context(Info),
-            LineNumber = string.int_to_string(term.context_line(Context)),
+            Context = goal_info_get_context(GoalInfo),
+            LineNumber = term.context_line(Context),
             FileName = term.context_file(Context),
-            PredName = sym_name_to_string(Expression0 ^ call_sym_name),
-            io.print("  Predicate " ++ PredName ++ " (" ++ FileName ++ ": " ++
-                LineNumber ++ ") has id " ++
-                int_to_string(pred_id_to_int(PredId)) ++ "\n", !IO)
+            PredName = sym_name_to_string(GoalExpr0 ^ call_sym_name),
+            io.format("  Predicate %s PredName (%s:%d) has id %d\n",
+                [s(PredName), s(FileName), i(LineNumber),
+                    i(pred_id_to_int(PredId))],
+                !IO)
         ),
-        NewCall = Expression0 ^ call_pred_id := PredId,
-        MaybeGoal = ok(hlds_goal(NewCall, Info))
+        GoalExpr = GoalExpr0 ^ call_pred_id := PredId,
+        Goal = hlds_goal(GoalExpr, GoalInfo),
+        MaybeGoal = ok(Goal)
     ;
         MaybeGoal = error("Goal was not a plain call") 
     ).
@@ -529,12 +540,6 @@
         Error = no
     ).
 
-:- pred fill_goal_path_slots_in_goal_2(vartypes::in, module_info::in,
-    hlds_goal::in, hlds_goal::out) is det.
-
-fill_goal_path_slots_in_goal_2(V, M, !G) :-
-    fill_goal_path_slots_in_goal(!.G, V, M, !:G).
-
 :- pred get_clause_body(clause::in, hlds_goal::out) is det.
 
 get_clause_body(Clause, Clause ^ clause_body).
@@ -828,7 +833,7 @@
         DomainMap = DomainMap0
     ;
         !.ConjTypeConstraint = ctconstr(Constraints, tconstr_active, Context,
-            GoalPath, PredId),
+            GoalId, PredId),
         list.foldl(simple_find_domain, Constraints, DomainMap0, DomainMap1),
         ( constraint_is_satisfiable(DomainMap1, Constraints) ->
             map.to_assoc_list(DomainMap1, AssocDomain1),
@@ -839,7 +844,7 @@
             )
         ;
             !:ConjTypeConstraint = ctconstr(Constraints, tconstr_unsatisfiable,
-                Context, GoalPath, PredId),
+                Context, GoalId, PredId),
             DomainMap = DomainMap1
         )
     ).
@@ -1475,7 +1480,7 @@
         | Components],
     Msg = simple_msg(Context, Pieces).
 
-:- pred ambig_pred_error_message(pred_env::in, pair(goal_path, pred_id)::in,
+:- pred ambig_pred_error_message(pred_env::in, pair(goal_id, pred_id)::in,
     error_msg_component::out) is det.
 
 ambig_pred_error_message(PredEnv, (_ - PredId), Component) :-
@@ -1492,7 +1497,7 @@
         suffix(")")]).
 
 :- pred pred_constraint_info(conj_type_constraint::in,
-    pair(goal_path, pred_id)::out) is semidet.
+    pair(goal_id, pred_id)::out) is semidet.
 
 pred_constraint_info(Constraint, Path - PredId) :-
     Constraint = ctconstr(_, tconstr_active, _, yes(Path), yes(PredId)).
@@ -1970,9 +1975,9 @@
 pred_call_constraint(PredTable, Info, ArgTVars, PredId, Constraint, TVars,
         !TCInfo) :-
     Constraint = ctconstr(Constraints, tconstr_active, Context,
-        yes(GoalPath), yes(PredId)),
+        yes(GoalId), yes(PredId)),
     Context = goal_info_get_context(Info),
-    GoalPath = goal_info_get_goal_path(Info),
+    GoalId = goal_info_get_goal_id(Info),
     ( map.search(PredTable, PredId, PredInfo) ->
         pred_info_get_arg_types(PredInfo, PredArgTypes0),
         pred_info_get_typevarset(PredInfo, PredTVarSet),
@@ -2007,9 +2012,9 @@
 ho_pred_unif_constraint(PredTable, Info, LHSTVar, ArgTVars, PredId, Constraint,
         !TCInfo) :-
     Constraint = ctconstr(Constraints, tconstr_active, Context,
-        yes(GoalPath), yes(PredId)),
+        yes(GoalId), yes(PredId)),
     Context = goal_info_get_context(Info),
-    GoalPath = goal_info_get_goal_path(Info),
+    GoalId = goal_info_get_goal_id(Info),
     ( map.search(PredTable, PredId, PredInfo) ->
         pred_info_get_arg_types(PredInfo, PredArgTypes0),
         pred_info_get_typevarset(PredInfo, PredTVarSet),
@@ -2083,7 +2088,7 @@
     ConsDefn = hlds_cons_defn(TypeCtor, FunctorTVarSet, TypeParams0, _, _, _,
         FuncArgs, _),
     Context = goal_info_get_context(Info),
-    GoalPath = goal_info_get_goal_path(Info),
+    GoalId = goal_info_get_goal_id(Info),
     % Find the types of each argument and the result type, given a renaming
     % of type variables.
     list.map(get_ctor_arg_type, FuncArgs, FuncArgTypes0),
@@ -2100,7 +2105,7 @@
     RHS_Constraints = list.map_corresponding(create_stconstr,
         ArgTVars, FuncArgTypes),
     Constraints = ctconstr([LHS_Constraint | RHS_Constraints],
-        tconstr_active, Context, yes(GoalPath), no).
+        tconstr_active, Context, yes(GoalId), no).
 
 %-----------------------------------------------------------------------------%
 %
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.449
diff -u -r1.449 typecheck.m
--- compiler/typecheck.m	15 Dec 2010 06:30:08 -0000	1.449
+++ compiler/typecheck.m	15 Dec 2010 06:33:29 -0000
@@ -97,11 +97,11 @@
 
 :- implementation.
 
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.type_util.
 :- import_module check_hlds.typecheck_errors.
 :- import_module check_hlds.typecheck_info.
 :- import_module check_hlds.typeclasses.
+:- import_module hlds.goal_path.
 :- import_module hlds.goal_util.
 :- import_module hlds.headvar_names.
 :- import_module hlds.hlds_args.
@@ -195,9 +195,14 @@
     some [!PredInfo] (
         PredIdInfo0 = PredId - !:PredInfo,
         ( set_tree234.contains(ValidPredIdSet, PredId) ->
-            % Goal paths are used to identify typeclass constraints.
-            fill_goal_path_slots_in_clauses(ModuleInfo, no, !PredInfo),
+            % Goal ids are used to identify typeclass constraints.
+            pred_info_get_clauses_info(!.PredInfo, GoalIdClausesInfo0),
+            fill_goal_id_slots_in_clauses(ModuleInfo, _ContainingGoalMap,
+                GoalIdClausesInfo0, GoalIdClausesInfo),
+            pred_info_set_clauses_info(GoalIdClausesInfo, !PredInfo),
+
             maybe_add_field_access_function_clause(ModuleInfo, !PredInfo),
+
             module_info_get_globals(ModuleInfo, Globals),
             maybe_improve_headvar_names(Globals, !PredInfo),
             PredIdInfo = PredId - !.PredInfo
@@ -1297,8 +1302,8 @@
         list.length(Args, Arity),
         CurCall = simple_call_id(pf_predicate, Name, Arity),
         typecheck_info_set_called_predid(plain_call_id(CurCall), !Info),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
-        typecheck_call_pred(CurCall, Args, GoalPath, PredId, !Info),
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        typecheck_call_pred(CurCall, Args, GoalId, PredId, !Info),
         GoalExpr = plain_call(PredId, ProcId, Args, BI, UC, Name)
     ;
         GoalExpr0 = generic_call(GenericCall0, Args, Modes, Detism),
@@ -1336,8 +1341,8 @@
         ),
         !:Info = !.Info ^ tc_info_arg_num := 0,
         !:Info = !.Info ^ tc_info_unify_context := UnifyContext,
-        GoalPath = goal_info_get_goal_path(GoalInfo),
-        typecheck_unification(LHS, RHS0, RHS, GoalPath, !Info),
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        typecheck_unification(LHS, RHS0, RHS, GoalId, !Info),
         GoalExpr = unify(LHS, RHS, UnifyMode, Unification, UnifyContext)
     ;
         GoalExpr0 = switch(_, _, _),
@@ -1350,8 +1355,8 @@
         % typed foreign_procs. (We could probably do that more efficiently
         % than the way it is done below, though.)
         ArgVars = list.map(foreign_arg_var, Args),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
-        typecheck_call_pred_id(PredId, ArgVars, GoalPath, !Info),
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        typecheck_call_pred_id(PredId, ArgVars, GoalId, !Info),
         perform_context_reduction(!Info),
         GoalExpr = GoalExpr0
     ;
@@ -1563,10 +1568,9 @@
 %-----------------------------------------------------------------------------%
 
 :- pred typecheck_call_pred(simple_call_id::in, list(prog_var)::in,
-    goal_path::in, pred_id::out, typecheck_info::in, typecheck_info::out)
-    is det.
+    goal_id::in, pred_id::out, typecheck_info::in, typecheck_info::out) is det.
 
-typecheck_call_pred(CallId, Args, GoalPath, PredId, !Info) :-
+typecheck_call_pred(CallId, Args, GoalId, PredId, !Info) :-
     % Look up the called predicate's arg types.
     ModuleInfo = !.Info ^ tc_info_module_info,
     module_info_get_predicate_table(ModuleInfo, PredicateTable),
@@ -1582,10 +1586,10 @@
         % non-polymorphic predicate).
         ( PredIdList = [PredId0] ->
             PredId = PredId0,
-            typecheck_call_pred_id(PredId, Args, GoalPath, !Info)
+            typecheck_call_pred_id(PredId, Args, GoalId, !Info)
         ;
             typecheck_call_overloaded_pred(CallId, PredIdList, Args,
-                GoalPath, !Info),
+                GoalId, !Info),
 
             % In general, we can't figure out which predicate it is until
             % after we have resolved any overloading, which may require
@@ -1609,10 +1613,10 @@
 
     % Typecheck a call to a specific predicate.
     %
-:- pred typecheck_call_pred_id(pred_id::in, list(prog_var)::in, goal_path::in,
+:- pred typecheck_call_pred_id(pred_id::in, list(prog_var)::in, goal_id::in,
     typecheck_info::in, typecheck_info::out) is det.
 
-typecheck_call_pred_id(PredId, Args, GoalPath, !Info) :-
+typecheck_call_pred_id(PredId, Args, GoalId, !Info) :-
     ModuleInfo = !.Info ^ tc_info_module_info,
     module_info_get_predicate_table(ModuleInfo, PredicateTable),
     predicate_table_get_preds(PredicateTable, Preds),
@@ -1633,16 +1637,16 @@
     ;
         module_info_get_class_table(ModuleInfo, ClassTable),
         make_body_hlds_constraints(ClassTable, PredTypeVarSet,
-            GoalPath, PredClassContext, PredConstraints),
+            GoalId, PredClassContext, PredConstraints),
         typecheck_var_has_polymorphic_type_list(Args, PredTypeVarSet,
             PredExistQVars, PredArgTypes, PredConstraints, !Info)
     ).
 
 :- pred typecheck_call_overloaded_pred(simple_call_id::in, list(pred_id)::in,
-    list(prog_var)::in, goal_path::in, typecheck_info::in, typecheck_info::out)
+    list(prog_var)::in, goal_id::in, typecheck_info::in, typecheck_info::out)
     is det.
 
-typecheck_call_overloaded_pred(CallId, PredIdList, Args, GoalPath, !Info) :-
+typecheck_call_overloaded_pred(CallId, PredIdList, Args, GoalId, !Info) :-
     Context = !.Info ^ tc_info_context,
     Symbol = overloaded_pred(CallId, PredIdList),
     typecheck_info_add_overloaded_symbol(Symbol, Context, !Info),
@@ -1655,7 +1659,7 @@
     module_info_get_predicate_table(ModuleInfo, PredicateTable),
     predicate_table_get_preds(PredicateTable, Preds),
     TypeAssignSet0 = !.Info ^ tc_info_type_assign_set,
-    get_overloaded_pred_arg_types(PredIdList, Preds, ClassTable, GoalPath,
+    get_overloaded_pred_arg_types(PredIdList, Preds, ClassTable, GoalId,
         TypeAssignSet0, [], ArgsTypeAssignSet),
 
     % Then unify the types of the call arguments with the
@@ -1663,23 +1667,23 @@
     typecheck_var_has_arg_type_list(Args, 1, ArgsTypeAssignSet, !Info).
 
 :- pred get_overloaded_pred_arg_types(list(pred_id)::in, pred_table::in,
-    class_table::in, goal_path::in, type_assign_set::in,
+    class_table::in, goal_id::in, type_assign_set::in,
     args_type_assign_set::in, args_type_assign_set::out) is det.
 
-get_overloaded_pred_arg_types([], _Preds, _ClassTable, _GoalPath,
+get_overloaded_pred_arg_types([], _Preds, _ClassTable, _GoalId,
         _TypeAssignSet0, !ArgsTypeAssignSet).
-get_overloaded_pred_arg_types([PredId | PredIds], Preds, ClassTable, GoalPath,
+get_overloaded_pred_arg_types([PredId | PredIds], Preds, ClassTable, GoalId,
         TypeAssignSet0, !ArgsTypeAssignSet) :-
     map.lookup(Preds, PredId, PredInfo),
     pred_info_get_arg_types(PredInfo, PredTypeVarSet, PredExistQVars,
         PredArgTypes),
     pred_info_get_class_context(PredInfo, PredClassContext),
     pred_info_get_typevarset(PredInfo, TVarSet),
-    make_body_hlds_constraints(ClassTable, TVarSet, GoalPath,
+    make_body_hlds_constraints(ClassTable, TVarSet, GoalId,
         PredClassContext, PredConstraints),
     rename_apart(TypeAssignSet0, PredTypeVarSet, PredExistQVars,
         PredArgTypes, PredConstraints, !ArgsTypeAssignSet),
-    get_overloaded_pred_arg_types(PredIds, Preds, ClassTable, GoalPath,
+    get_overloaded_pred_arg_types(PredIds, Preds, ClassTable, GoalId,
         TypeAssignSet0, !ArgsTypeAssignSet).
 
 %-----------------------------------------------------------------------------%
@@ -1976,13 +1980,13 @@
     % iterate over all the possible type assignments.
     %
 :- pred typecheck_unification(prog_var::in, unify_rhs::in, unify_rhs::out,
-    goal_path::in, typecheck_info::in, typecheck_info::out) is det.
+    goal_id::in, typecheck_info::in, typecheck_info::out) is det.
 
 typecheck_unification(X, rhs_var(Y), rhs_var(Y), _, !Info) :-
     typecheck_unify_var_var(X, Y, !Info).
 typecheck_unification(X, rhs_functor(Functor, ExistConstraints, Args),
-        rhs_functor(Functor, ExistConstraints, Args), GoalPath, !Info) :-
-    typecheck_unify_var_functor(X, Functor, Args, GoalPath, !Info),
+        rhs_functor(Functor, ExistConstraints, Args), GoalId, !Info) :-
+    typecheck_unify_var_functor(X, Functor, Args, GoalId, !Info),
     perform_context_reduction(!Info).
 typecheck_unification(X,
         rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
@@ -2029,10 +2033,10 @@
     ConsType = builtin_type(BuiltinType).
 
 :- pred typecheck_unify_var_functor(prog_var::in, cons_id::in,
-    list(prog_var)::in, goal_path::in,
+    list(prog_var)::in, goal_id::in,
     typecheck_info::in, typecheck_info::out) is det.
 
-typecheck_unify_var_functor(Var, ConsId, Args, GoalPath, !Info) :-
+typecheck_unify_var_functor(Var, ConsId, Args, GoalId, !Info) :-
     ( cons_id_must_be_builtin_type(ConsId, ConsType, BuiltinTypeName) ->
         TypeAssignSet0 = !.Info ^ tc_info_type_assign_set,
         list.foldl(
@@ -2065,7 +2069,7 @@
         % Get the list of possible constructors that match this functor/arity.
         % If there aren't any, report an undefined constructor error.
         list.length(Args, Arity),
-        typecheck_info_get_ctor_list(!.Info, ConsId, Arity, GoalPath,
+        typecheck_info_get_ctor_list(!.Info, ConsId, Arity, GoalId,
             ConsDefns, ConsErrors),
         (
             ConsDefns = [],
@@ -2541,22 +2545,22 @@
         Type = "int"
     ).
 
-    % builtin_pred_type(Info, ConsId, Arity, GoalPath, PredConsInfoList):
+    % builtin_pred_type(Info, ConsId, Arity, GoalId, PredConsInfoList):
     %
     % If ConsId/Arity is a constant of a pred type, instantiates
     % the output parameters, otherwise fails.
     %
     % Instantiates PredConsInfoList to the set of cons_type_info structures
     % for each predicate with name `ConsId' and arity greater than or equal to
-    % Arity. GoalPath is used to identify any constraints introduced.
+    % Arity. GoalId is used to identify any constraints introduced.
     %
     % For example, functor `map.search/1' has type `pred(K, V)'
     % (hence PredTypeParams = [K, V]) and argument types [map(K, V)].
     %
 :- pred builtin_pred_type(typecheck_info::in, cons_id::in, int::in,
-    goal_path::in, list(cons_type_info)::out) is semidet.
+    goal_id::in, list(cons_type_info)::out) is semidet.
 
-builtin_pred_type(Info, ConsId, Arity, GoalPath, PredConsInfoList) :-
+builtin_pred_type(Info, ConsId, Arity, GoalId, PredConsInfoList) :-
     ConsId = cons(SymName, _, _),
     ModuleInfo = Info ^ tc_info_module_info,
     module_info_get_predicate_table(ModuleInfo, PredicateTable),
@@ -2567,28 +2571,28 @@
     ->
         predicate_table_get_preds(PredicateTable, Preds),
         make_pred_cons_info_list(Info, PredIdList, Preds, Arity,
-            GoalPath, [], PredConsInfoList)
+            GoalId, [], PredConsInfoList)
     ;
         PredConsInfoList = []
     ).
 
 :- pred make_pred_cons_info_list(typecheck_info::in, list(pred_id)::in,
-    pred_table::in, int::in, goal_path::in,
+    pred_table::in, int::in, goal_id::in,
     list(cons_type_info)::in, list(cons_type_info)::out) is det.
 
 make_pred_cons_info_list(_, [], _, _, _, !ConsTypeInfos).
 make_pred_cons_info_list(Info, [PredId | PredIds], PredTable, Arity,
-        GoalPath, !ConsTypeInfos) :-
+        GoalId, !ConsTypeInfos) :-
     make_pred_cons_info(Info, PredId, PredTable, Arity,
-        GoalPath, !ConsTypeInfos),
+        GoalId, !ConsTypeInfos),
     make_pred_cons_info_list(Info, PredIds, PredTable, Arity,
-        GoalPath, !ConsTypeInfos).
+        GoalId, !ConsTypeInfos).
 
 :- pred make_pred_cons_info(typecheck_info::in, pred_id::in, pred_table::in,
-    int::in, goal_path::in,
+    int::in, goal_id::in,
     list(cons_type_info)::in, list(cons_type_info)::out) is det.
 
-make_pred_cons_info(Info, PredId, PredTable, FuncArity, GoalPath,
+make_pred_cons_info(Info, PredId, PredTable, FuncArity, GoalId,
         !ConsInfos) :-
     ModuleInfo = Info ^ tc_info_module_info,
     module_info_get_class_table(ModuleInfo, ClassTable),
@@ -2613,7 +2617,7 @@
             construct_higher_order_pred_type(Purity, lambda_normal,
                 PredTypeParams, PredType),
             make_body_hlds_constraints(ClassTable, PredTypeVarSet,
-                GoalPath, PredClassContext, PredConstraints),
+                GoalId, PredClassContext, PredConstraints),
             ConsInfo = cons_type_info(PredTypeVarSet, PredExistQVars,
                 PredType, ArgTypes, PredConstraints, source_pred(PredId)),
             !:ConsInfos = [ConsInfo | !.ConsInfos]
@@ -2646,7 +2650,7 @@
                     FuncArgTypeParams, FuncReturnTypeParam, FuncType)
             ),
             make_body_hlds_constraints(ClassTable, PredTypeVarSet,
-                GoalPath, PredClassContext, PredConstraints),
+                GoalId, PredClassContext, PredConstraints),
             ConsInfo = cons_type_info(PredTypeVarSet,
                 PredExistQVars, FuncType, FuncArgTypes, PredConstraints,
                 source_pred(PredId)),
@@ -2698,16 +2702,16 @@
         [FuncType | ArgTypes], EmptyConstraints,
         source_apply(ApplyNameToUse))].
 
-    % builtin_field_access_function_type(Info, GoalPath, ConsId,
+    % builtin_field_access_function_type(Info, GoalId, ConsId,
     %   Arity, ConsTypeInfos):
     %
     % Succeed if ConsId is the name of one the automatically
     % generated field access functions (fieldname, '<fieldname> :=').
     %
-:- pred builtin_field_access_function_type(typecheck_info::in, goal_path::in,
+:- pred builtin_field_access_function_type(typecheck_info::in, goal_id::in,
     cons_id::in, arity::in, list(maybe_cons_type_info)::out) is semidet.
 
-builtin_field_access_function_type(Info, GoalPath, ConsId, Arity,
+builtin_field_access_function_type(Info, GoalId, ConsId, Arity,
         MaybeConsTypeInfos) :-
     % Taking the address of automatically generated field access functions
     % is not allowed, so currying does have to be considered here.
@@ -2720,18 +2724,18 @@
     map.search(CtorFieldTable, FieldName, FieldDefns),
 
     list.filter_map(
-        make_field_access_function_cons_type_info(Info, GoalPath, Name,
+        make_field_access_function_cons_type_info(Info, GoalId, Name,
             Arity, AccessType, FieldName),
         FieldDefns, MaybeConsTypeInfos).
 
 :- pred make_field_access_function_cons_type_info(typecheck_info::in,
-    goal_path::in, sym_name::in, arity::in, field_access_type::in,
+    goal_id::in, sym_name::in, arity::in, field_access_type::in,
     ctor_field_name::in, hlds_ctor_field_defn::in,
     maybe_cons_type_info::out) is semidet.
 
-make_field_access_function_cons_type_info(Info, GoalPath, FuncName, Arity,
+make_field_access_function_cons_type_info(Info, GoalId, FuncName, Arity,
         AccessType, FieldName, FieldDefn, ConsTypeInfo) :-
-    get_field_access_constructor(Info, GoalPath, FuncName, Arity,
+    get_field_access_constructor(Info, GoalId, FuncName, Arity,
         AccessType, FieldDefn, OrigExistTVars,
         MaybeFunctorConsTypeInfo),
     (
@@ -2746,11 +2750,11 @@
         ConsTypeInfo = MaybeFunctorConsTypeInfo
     ).
 
-:- pred get_field_access_constructor(typecheck_info::in, goal_path::in,
+:- pred get_field_access_constructor(typecheck_info::in, goal_id::in,
     sym_name::in, arity::in, field_access_type::in, hlds_ctor_field_defn::in,
     existq_tvars::out, maybe_cons_type_info::out) is semidet.
 
-get_field_access_constructor(Info, GoalPath, FuncName, Arity, AccessType,
+get_field_access_constructor(Info, GoalId, FuncName, Arity, AccessType,
         FieldDefn, OrigExistTVars, FunctorConsTypeInfo) :-
     FieldDefn = hlds_ctor_field_defn(_, _, TypeCtor, ConsId, _),
     TypeCtor = type_ctor(qualified(TypeModule, _), _),
@@ -2786,7 +2790,7 @@
         ConsAction = flip_constraints_for_field_set
     ),
     OrigExistTVars = ConsDefn ^ cons_exist_tvars,
-    convert_cons_defn(Info, GoalPath, ConsAction, ConsDefn,
+    convert_cons_defn(Info, GoalId, ConsAction, ConsDefn,
         FunctorConsTypeInfo).
 
 :- type maybe_cons_type_info
@@ -2974,9 +2978,9 @@
     % and recompilation.check.check_functor_ambiguities.
     %
 :- pred typecheck_info_get_ctor_list(typecheck_info::in, cons_id::in, int::in,
-    goal_path::in, list(cons_type_info)::out, list(cons_error)::out) is det.
+    goal_id::in, list(cons_type_info)::out, list(cons_error)::out) is det.
 
-typecheck_info_get_ctor_list(Info, Functor, Arity, GoalPath, ConsInfos,
+typecheck_info_get_ctor_list(Info, Functor, Arity, GoalId, ConsInfos,
         ConsErrors) :-
     typecheck_info_get_is_field_access_function(Info, IsFieldAccessFunc),
     (
@@ -2990,7 +2994,7 @@
         ImportStatus \= status_opt_imported
     ->
         (
-            builtin_field_access_function_type(Info, GoalPath,
+            builtin_field_access_function_type(Info, GoalId,
                 Functor, Arity, FieldAccessConsInfos)
         ->
             split_cons_errors(FieldAccessConsInfos, ConsInfos, ConsErrors)
@@ -2999,15 +3003,15 @@
             ConsErrors = []
         )
     ;
-        typecheck_info_get_ctor_list_2(Info, Functor, Arity, GoalPath,
+        typecheck_info_get_ctor_list_2(Info, Functor, Arity, GoalId,
             ConsInfos, ConsErrors)
     ).
 
 :- pred typecheck_info_get_ctor_list_2(typecheck_info::in, cons_id::in,
-    int::in, goal_path::in, list(cons_type_info)::out, list(cons_error)::out)
+    int::in, goal_id::in, list(cons_type_info)::out, list(cons_error)::out)
     is det.
 
-typecheck_info_get_ctor_list_2(Info, Functor, Arity, GoalPath, ConsInfos,
+typecheck_info_get_ctor_list_2(Info, Functor, Arity, GoalId, ConsInfos,
         DataConsErrors) :-
     empty_hlds_constraints(EmptyConstraints),
 
@@ -3019,7 +3023,7 @@
         Functor = cons(_, _, _),
         map.search(Ctors, Functor, HLDS_ConsDefns)
     ->
-        convert_cons_defn_list(Info, GoalPath, do_not_flip_constraints,
+        convert_cons_defn_list(Info, GoalId, do_not_flip_constraints,
             HLDS_ConsDefns, PlainMaybeConsInfos)
     ;
         PlainMaybeConsInfos = []
@@ -3047,7 +3051,7 @@
         OrigFunctor = cons(OrigName, Arity, FunctorTypeCtor),
         map.search(Ctors, OrigFunctor, HLDS_ExistQConsDefns)
     ->
-        convert_cons_defn_list(Info, GoalPath, flip_constraints_for_new,
+        convert_cons_defn_list(Info, GoalId, flip_constraints_for_new,
             HLDS_ExistQConsDefns, UnivQuantifiedMaybeConsInfos)
     ;
         UnivQuantifiedMaybeConsInfos = []
@@ -3056,7 +3060,7 @@
     % Check if Functor is a field access function for which the user
     % has not supplied a declaration.
     (
-        builtin_field_access_function_type(Info, GoalPath, Functor,
+        builtin_field_access_function_type(Info, GoalId, Functor,
             Arity, FieldAccessMaybeConsInfosPrime)
     ->
         FieldAccessMaybeConsInfos = FieldAccessMaybeConsInfosPrime
@@ -3117,7 +3121,7 @@
     % Check if Functor is the name of a predicate which takes at least
     % Arity arguments. If so, insert the resulting cons_type_info
     % at the start of the list.
-    ( builtin_pred_type(Info, Functor, Arity, GoalPath, PredConsInfosPrime) ->
+    ( builtin_pred_type(Info, Functor, Arity, GoalId, PredConsInfosPrime) ->
         PredConsInfos = PredConsInfosPrime
     ;
         PredConsInfos = []
@@ -3160,22 +3164,22 @@
     ;       flip_constraints_for_field_set
     ;       do_not_flip_constraints.
 
-:- pred convert_cons_defn_list(typecheck_info::in, goal_path::in,
+:- pred convert_cons_defn_list(typecheck_info::in, goal_id::in,
     cons_constraints_action::in, list(hlds_cons_defn)::in,
     list(maybe_cons_type_info)::out) is det.
 
-convert_cons_defn_list(_Info, _GoalPath, _Action, [], []).
-convert_cons_defn_list(Info, GoalPath, Action, [X | Xs], [Y | Ys]) :-
-    convert_cons_defn(Info, GoalPath, Action, X, Y),
-    convert_cons_defn_list(Info, GoalPath, Action, Xs, Ys).
+convert_cons_defn_list(_Info, _GoalId, _Action, [], []).
+convert_cons_defn_list(Info, GoalId, Action, [X | Xs], [Y | Ys]) :-
+    convert_cons_defn(Info, GoalId, Action, X, Y),
+    convert_cons_defn_list(Info, GoalId, Action, Xs, Ys).
 
-:- pred convert_cons_defn(typecheck_info, goal_path,
+:- pred convert_cons_defn(typecheck_info, goal_id,
     cons_constraints_action, hlds_cons_defn, maybe_cons_type_info).
 :- mode convert_cons_defn(in, in, in(bound(do_not_flip_constraints)), in, out)
     is det.
 :- mode convert_cons_defn(in, in, in, in, out) is det.
 
-convert_cons_defn(Info, GoalPath, Action, HLDS_ConsDefn, ConsTypeInfo) :-
+convert_cons_defn(Info, GoalId, Action, HLDS_ConsDefn, ConsTypeInfo) :-
     % XXX We should investigate whether the job done by this predicate
     % on demand and therefore possibly lots of times for the same type,
     % would be better done just once, either by invoking it (at least with
@@ -3266,7 +3270,7 @@
             ExistQVars = ExistQVars0
         ),
         make_body_hlds_constraints(ClassTable, ConsTypeVarSet,
-            GoalPath, ProgConstraints, Constraints),
+            GoalId, ProgConstraints, Constraints),
         ConsTypeInfo = ok(cons_type_info(ConsTypeVarSet, ExistQVars,
             ConsType, ArgTypes, Constraints, source_type(TypeCtor)))
     ).
Index: compiler/unify_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unify_gen.m,v
retrieving revision 1.199
diff -u -r1.199 unify_gen.m
--- compiler/unify_gen.m	15 Dec 2010 06:30:09 -0000	1.199
+++ compiler/unify_gen.m	15 Dec 2010 06:33:29 -0000
@@ -756,15 +756,16 @@
         Context = goal_info_get_context(GoalInfo),
         term.context_file(Context, FileName),
         term.context_line(Context, LineNumber),
-        GoalPath = goal_info_get_goal_path(GoalInfo),
-        GoalPathStr = goal_path_to_string(GoalPath),
+        GoalId = goal_info_get_goal_id(GoalInfo),
+        GoalId = goal_id(GoalIdNum),
+        GoalIdStr = string.int_to_string(GoalIdNum),
         get_cur_proc_label(!.CI, CallerProcLabel),
         get_next_closure_seq_no(SeqNo, !CI),
         get_static_cell_info(!.CI, StaticCellInfo0),
         hlds.hlds_pred.pred_info_get_origin(PredInfo, PredOrigin),
         stack_layout.construct_closure_layout(CallerProcLabel,
             SeqNo, ClosureInfo, ProcLabel, ModuleName, FileName, LineNumber,
-            PredOrigin, GoalPathStr, StaticCellInfo0, StaticCellInfo,
+            PredOrigin, GoalIdStr, StaticCellInfo0, StaticCellInfo,
             ClosureLayoutRvalsTypes, Data),
         set_static_cell_info(StaticCellInfo, !CI),
         add_closure_layout(Data, !CI),
Index: compiler/unneeded_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unneeded_code.m,v
retrieving revision 1.55
diff -u -r1.55 unneeded_code.m
--- compiler/unneeded_code.m	15 Dec 2010 06:30:10 -0000	1.55
+++ compiler/unneeded_code.m	15 Dec 2010 06:33:29 -0000
@@ -72,10 +72,10 @@
 
 :- implementation.
 
-:- import_module check_hlds.goal_path.
 :- import_module check_hlds.inst_match.
 :- import_module check_hlds.mode_util.
 :- import_module hlds.goal_form.
+:- import_module hlds.goal_path.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_out.
 :- import_module hlds.hlds_out.hlds_out_goal.
@@ -111,29 +111,29 @@
     %
 :- type branch_point
     --->    branch_point(
-                goal_path,  % The position of the branch point.
-                branch_alts % What kind of goal the branch point
-                            % is, and many branches it has.
-                            % Note that the second argument is a
-                            % function of the first.
+                % The id of the branch point.
+                goal_id,
+
+                % What kind of goal the branch point is, and many branches
+                % it has. Note that the second argument is a function of
+                % the first.
+                branch_alts
             ).
 
 :- type branch_alts
-    --->    alt_ite         % If-then-elses always have two alternatives:
-                            % the then branch (numbered 1) and the else branch
-                            % (numbered 2).
+    --->    alt_ite
+            % If-then-elses always have two alternatives: the then branch
+            % (numbered 1) and the else branch (numbered 2).
 
     ;       alt_switch(maybe(int)).
-                            % The number of alternatives in a switch is equal
-                            % to the number of function symbols in the type of
-                            % the switched-on variable. This number is given by
-                            % the argument integer, if present; if the argument
-                            % is "no", then the number of function symbols in
-                            % the type is effectively infinite (this can happen
-                            % for builtin types such as "int"). If the switch
-                            % cannot_fail, then this will be equal to the
-                            % number of cases; if the switch can_fail, there
-                            % will be strictly fewer cases than this.
+            % The number of alternatives in a switch is equal to the number of
+            % function symbols in the type of the switched-on variable. This
+            % number is given by the argument integer, if present; if the
+            % argument is "no", then the number of function symbols in the type
+            % is effectively infinite (this can happen for builtin types
+            % such as "int"). If the switch cannot_fail, then this will be
+            % equal to the number of cases; if the switch can_fail, there
+            % will be strictly fewer cases than this.
 
     % The location type identifies one arm of a branched control structure.
     % The branched control structure id is a branch_point instead of a
@@ -153,7 +153,9 @@
     % everywhere, then the computation producing it cannot be eliminated
     % or moved. If it is not needed at all, its producer can be eliminated.
     % If it is needed on some but not all branches, then the producer
-    % can be moved to the starts of those branches.
+    % can be moved to the starts of those branches (or, preferably,
+    % to the first point in those branches that need them, but we do not do
+    % that yet).
     %
     % The set of branches to whose starts the producer can be moved
     % is represented as a map from the id of the branched control
@@ -210,8 +212,8 @@
     % The order is important, since some of the producers in such a list
     % may depend on variables produced by other goals that precede them
     % in the list.
-
-:- type refined_goal_map == map(pair(goal_path, int), list(hlds_goal)).
+    %
+:- type refined_goal_map == map(pair(goal_id, int), list(hlds_goal)).
 
 %-----------------------------------------------------------------------------%
 
@@ -284,19 +286,27 @@
 % of the procedure body is executed. Since both the number of subgoals and
 % computation paths are finite, the recursion must end.
 
-:- type option_values
-    --->    option_values(
-                fully_strict    :: bool,
-                reorder_conj    :: bool,
-                copy_limit      :: int,
-                debug           :: bool
+:- type uc_option_values
+    --->    uc_option_values(
+                uc_fully_strict         :: bool,
+                uc_reorder_conj         :: bool,
+                uc_copy_limit           :: int,
+                uc_debug                :: bool
+            ).
+
+:- type unneeded_code_info
+    --->    unneeded_code_info(
+                uci_module_info         :: module_info,
+                uci_vartypes            :: vartypes,
+                uci_options             :: uc_option_values,
+                uci_containing_goal_map :: containing_goal_map
             ).
 
 :- pred unneeded_process_proc(proc_info::in, proc_info::out,
     module_info::in, module_info::out, pred_id::in, int::in, bool::out) is det.
 
 unneeded_process_proc(!ProcInfo, !ModuleInfo, PredId, Pass, Successful) :-
-    fill_goal_path_slots(!.ModuleInfo, !ProcInfo),
+    fill_goal_id_slots_in_proc(!.ModuleInfo, ContainingGoalMap, !ProcInfo),
     proc_info_get_goal(!.ProcInfo, Goal0),
     proc_info_get_varset(!.ProcInfo, VarSet0),
     proc_info_get_vartypes(!.ProcInfo, VarTypes0),
@@ -316,7 +326,7 @@
     globals.lookup_bool_option(Globals, fully_strict, FullyStrict),
     globals.lookup_int_option(Globals, unneeded_code_copy_limit, Limit),
     globals.lookup_bool_option(Globals, unneeded_code_debug, Debug),
-    Options = option_values(FullyStrict, ReorderConj, Limit, Debug),
+    Options = uc_option_values(FullyStrict, ReorderConj, Limit, Debug),
     (
         Debug = no
     ;
@@ -345,9 +355,11 @@
             )
         )
     ),
-    unneeded_process_goal(Goal0, Goal1, InitInstMap, FinalInstMap, VarTypes0,
-        !.ModuleInfo, Options, WhereNeededMap1, _, map.init, RefinedGoals1,
-        no, Changed),
+    UnneededInfo = unneeded_code_info(!.ModuleInfo, VarTypes0, Options,
+        ContainingGoalMap),
+    unneeded_process_goal(UnneededInfo, Goal0, Goal1,
+        InitInstMap, FinalInstMap, WhereNeededMap1, _,
+        map.init, RefinedGoals1, no, Changed),
     unneeded_refine_goal(Goal1, Goal2, RefinedGoals1, RefinedGoals),
     expect(map.is_empty(RefinedGoals),
         this_file, "unneeded_process_proc: goal reattachment unsuccessful"),
@@ -379,23 +391,23 @@
         Successful = no
     ).
 
-:- pred unneeded_process_goal(hlds_goal::in, hlds_goal::out,
-    instmap::in, instmap::in, vartypes::in, module_info::in, option_values::in,
+:- pred unneeded_process_goal(unneeded_code_info::in,
+    hlds_goal::in, hlds_goal::out, instmap::in, instmap::in,
     where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out, bool::in, bool::out) is det.
 
-unneeded_process_goal(Goal0, Goal, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, !WhereNeededMap, !RefinedGoals, !Changed) :-
-    can_eliminate_or_move(Goal0, InitInstMap, FinalInstMap,
-        VarTypes, ModuleInfo, Options, !.WhereNeededMap, WhereInfo),
+unneeded_process_goal(UnneededInfo, Goal0, Goal, InitInstMap, FinalInstMap,
+        !WhereNeededMap, !RefinedGoals, !Changed) :-
+    can_eliminate_or_move(UnneededInfo, Goal0, InitInstMap, FinalInstMap,
+        !.WhereNeededMap, WhereInfo),
     (
         WhereInfo = everywhere,
-        unneeded_process_goal_internal(Goal0, Goal, InitInstMap, FinalInstMap,
-            VarTypes, ModuleInfo, Options, !WhereNeededMap, !RefinedGoals,
-            !Changed)
+        unneeded_process_goal_internal(UnneededInfo, Goal0, Goal,
+            InitInstMap, FinalInstMap,
+            !WhereNeededMap, !RefinedGoals, !Changed)
     ;
         WhereInfo = branches(Branches),
-        demand_inputs(Goal0, ModuleInfo, InitInstMap, WhereInfo,
+        demand_inputs(UnneededInfo, Goal0, InitInstMap, WhereInfo,
             !WhereNeededMap),
         map.to_assoc_list(Branches, BranchList),
         list.foldl(insert_branch_into_refined_goals(Goal0), BranchList,
@@ -403,20 +415,21 @@
         Goal = true_goal,
         !:Changed = yes,
 
-        Debug = Options ^ debug,
+        Options = UnneededInfo ^ uci_options,
+        Debug = Options ^ uc_debug,
         (
             Debug = no
         ;
             Debug = yes,
             Goal0 = hlds_goal(_GoalExpr0, GoalInfo0),
-            GoalPath0 = goal_info_get_goal_path(GoalInfo0),
-            GoalPathStr0 = goal_path_to_string(GoalPath0),
+            goal_info_get_goal_id(GoalInfo0) = goal_id(GoalIdNum0),
             trace [io(!IO)] (
-                io.format("unneeded code at goal path %s\n", [s(GoalPathStr0)],
+                io.format("unneeded code at goal id %d\n", [i(GoalIdNum0)],
                     !IO)
             )
         )
     ),
+    ModuleInfo = UnneededInfo ^ uci_module_info,
     undemand_virgin_outputs(Goal0, ModuleInfo, InitInstMap, !WhereNeededMap),
     ( goal_get_purity(Goal) = purity_impure ->
         % By saying that all vars that are live before the impure goal are
@@ -441,7 +454,7 @@
     list.foldl(insert_branch_arm_into_refined_goals(Goal, GoalPath),
         BranchNums, !RefinedGoals).
 
-:- pred insert_branch_arm_into_refined_goals(hlds_goal::in, goal_path::in,
+:- pred insert_branch_arm_into_refined_goals(hlds_goal::in, goal_id::in,
     int::in, refined_goal_map::in, refined_goal_map::out) is det.
 
 insert_branch_arm_into_refined_goals(Goal, GoalPath, BranchNum,
@@ -456,29 +469,37 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred can_eliminate_or_move(hlds_goal::in, instmap::in,
-    instmap::in, vartypes::in, module_info::in, option_values::in,
+:- pred can_eliminate_or_move(unneeded_code_info::in, hlds_goal::in,
+    instmap::in, instmap::in,
     where_needed_map::in, where_needed::out) is det.
 
-can_eliminate_or_move(Goal, InitInstMap, FinalInstMap, VarTypes, ModuleInfo,
-        Options, WhereNeededMap, !:WhereInfo) :-
+can_eliminate_or_move(UnneededInfo, Goal, InitInstMap, FinalInstMap,
+        WhereNeededMap, !:WhereInfo) :-
+    ModuleInfo = UnneededInfo ^ uci_module_info,
+    VarTypes = UnneededInfo ^ uci_vartypes,
     instmap_changed_vars(InitInstMap, FinalInstMap, VarTypes, ModuleInfo,
         ChangedVarSet),
     set.to_sorted_list(ChangedVarSet, ChangedVars),
     map.init(Empty),
     !:WhereInfo = branches(Empty),
     Goal = hlds_goal(_, GoalInfo),
-    CurrentPath = goal_info_get_goal_path(GoalInfo),
-    list.foldl(collect_where_needed(CurrentPath, WhereNeededMap), ChangedVars,
-        !WhereInfo),
+    CurrentId = goal_info_get_goal_id(GoalInfo),
+    ContainingGoalMap = UnneededInfo ^ uci_containing_goal_map,
+    list.foldl(
+        collect_where_needed(ContainingGoalMap, CurrentId, WhereNeededMap),
+        ChangedVars, !WhereInfo),
+    Options = UnneededInfo ^ uci_options,
     adjust_where_needed(Goal, Options, !WhereInfo).
 
-:- pred collect_where_needed(goal_path::in, where_needed_map::in, prog_var::in,
-    where_needed::in, where_needed::out) is det.
+:- pred collect_where_needed(containing_goal_map::in, goal_id::in,
+    where_needed_map::in, prog_var::in, where_needed::in, where_needed::out)
+    is det.
 
-collect_where_needed(CurrentPath, WhereNeededMap, ChangedVar, !WhereInfo) :-
+collect_where_needed(ContainingGoalMap, CurrentId, WhereNeededMap, ChangedVar,
+        !WhereInfo) :-
     ( map.search(WhereNeededMap, ChangedVar, Where) ->
-        where_needed_upper_bound(CurrentPath, Where, !WhereInfo)
+        where_needed_upper_bound(ContainingGoalMap, CurrentId, Where,
+            !WhereInfo)
     ;
         true
     ).
@@ -488,7 +509,7 @@
     % operational semantics only in ways that are explicitly permitted by the
     % programmer.
     %
-:- pred adjust_where_needed(hlds_goal::in, option_values::in,
+:- pred adjust_where_needed(hlds_goal::in, uc_option_values::in,
     where_needed::in, where_needed::out) is det.
 
 adjust_where_needed(Goal, Options, !WhereInfo) :-
@@ -507,12 +528,12 @@
         ;
             % With --fully-strict, we cannot optimize away infinite loops
             % or exceptions.
-            Options ^ fully_strict = yes,
+            Options ^ uc_fully_strict = yes,
             goal_can_loop_or_throw(Goal)
         ;
             % With --no-reorder-conj, we cannot move infinite loops or
             % exceptions, but we can delete them.
-            Options ^ reorder_conj = no,
+            Options ^ uc_reorder_conj = no,
             goal_can_loop_or_throw(Goal),
             !.WhereInfo = branches(BranchMap),
             \+ map.is_empty(BranchMap)
@@ -526,7 +547,7 @@
             map.values(BranchMap, BranchArms),
             list.map(set.count, BranchArms, BranchArmCounts),
             BranchArmCount = list.foldl(int.plus, BranchArmCounts, 0),
-            BranchArmCount > Options ^ copy_limit
+            BranchArmCount > Options ^ uc_copy_limit
 
             % We may also want to add other space time tradeoffs. E.g. if
             % profiling shows that Goal is required in 10 branches that
@@ -556,18 +577,20 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred demand_inputs(hlds_goal::in, module_info::in,
-    instmap::in, where_needed::in,
-    where_needed_map::in, where_needed_map::out) is det.
+:- pred demand_inputs(unneeded_code_info::in, hlds_goal::in, instmap::in,
+    where_needed::in, where_needed_map::in, where_needed_map::out) is det.
 
-demand_inputs(Goal, ModuleInfo, InitInstMap, WhereNeeded, !WhereNeededMap) :-
+demand_inputs(UnneededInfo, Goal, InitInstMap, WhereNeeded, !WhereNeededMap) :-
     Goal = hlds_goal(_, GoalInfo),
     NonLocalSet = goal_info_get_nonlocals(GoalInfo),
-    GoalPath = goal_info_get_goal_path(GoalInfo),
+    GoalId = goal_info_get_goal_id(GoalInfo),
     set.to_sorted_list(NonLocalSet, NonLocals),
+    ModuleInfo = UnneededInfo ^ uci_module_info,
     list.filter(nonlocal_may_be_input(ModuleInfo, InitInstMap), NonLocals,
         Inputs),
-    list.foldl(demand_var(GoalPath, WhereNeeded), Inputs, !WhereNeededMap).
+    ContainingGoalMap = UnneededInfo ^ uci_containing_goal_map,
+    list.foldl(demand_var(ContainingGoalMap, GoalId, WhereNeeded), Inputs,
+        !WhereNeededMap).
 
 :- pred nonlocal_may_be_input(module_info::in, instmap::in,
     prog_var::in) is semidet.
@@ -598,12 +621,14 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred demand_var(goal_path::in, where_needed::in,
-    prog_var::in, where_needed_map::in, where_needed_map::out) is det.
+:- pred demand_var(containing_goal_map::in, goal_id::in,
+    where_needed::in, prog_var::in,
+    where_needed_map::in, where_needed_map::out) is det.
 
-demand_var(CurrentPath, WhereNeeded, Var, !WhereNeededMap) :-
+demand_var(ContainingGoalMap, CurrentId, WhereNeeded, Var, !WhereNeededMap) :-
     ( map.search(!.WhereNeededMap, Var, Where0) ->
-        where_needed_upper_bound(CurrentPath, WhereNeeded, Where0, Where),
+        where_needed_upper_bound(ContainingGoalMap, CurrentId,
+            WhereNeeded, Where0, Where),
         svmap.det_update(Var, Where, !WhereNeededMap)
     ;
         svmap.det_insert(Var, WhereNeeded, !WhereNeededMap)
@@ -623,56 +648,49 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred unneeded_process_goal_internal(hlds_goal::in, hlds_goal::out,
-    instmap::in, instmap::in, vartypes::in, module_info::in,
-    option_values::in, where_needed_map::in, where_needed_map::out,
+:- pred unneeded_process_goal_internal(unneeded_code_info::in,
+    hlds_goal::in, hlds_goal::out, instmap::in, instmap::in,
+    where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out, bool::in, bool::out) is det.
 
-unneeded_process_goal_internal(Goal0, Goal, InitInstMap, FinalInstMap,
-        VarTypes, ModuleInfo, Options, !WhereNeededMap, !RefinedGoals,
-        !Changed) :-
+unneeded_process_goal_internal(UnneededInfo, Goal0, Goal,
+        InitInstMap, FinalInstMap, !WhereNeededMap, !RefinedGoals, !Changed) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
     (
-        GoalExpr0 = unify(_, _, _, _, _),
-        Goal = Goal0,
-        demand_inputs(Goal, ModuleInfo, InitInstMap, everywhere,
-            !WhereNeededMap)
-    ;
-        GoalExpr0 = plain_call(_, _, _, _, _, _),
-        Goal = Goal0,
-        demand_inputs(Goal, ModuleInfo, InitInstMap, everywhere,
-            !WhereNeededMap)
-    ;
-        GoalExpr0 = generic_call(_, _, _, _),
-        Goal = Goal0,
-        demand_inputs(Goal, ModuleInfo, InitInstMap, everywhere,
-            !WhereNeededMap)
-    ;
-        GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _),
+        ( GoalExpr0 = unify(_, _, _, _, _)
+        ; GoalExpr0 = plain_call(_, _, _, _, _, _)
+        ; GoalExpr0 = generic_call(_, _, _, _)
+        ; GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
+        ),
         Goal = Goal0,
-        demand_inputs(Goal, ModuleInfo, InitInstMap, everywhere,
+        demand_inputs(UnneededInfo, Goal, InitInstMap, everywhere,
             !WhereNeededMap)
     ;
         GoalExpr0 = conj(ConjType, Conjuncts0),
         (
             ConjType = plain_conj,
-            unneeded_process_conj(Conjuncts0, Conjuncts,
-                InitInstMap, FinalInstMap, VarTypes, ModuleInfo, Options,
+            unneeded_process_conj(UnneededInfo, Conjuncts0, Conjuncts,
+                InitInstMap, FinalInstMap,
                 !WhereNeededMap, !RefinedGoals, !Changed),
             GoalExpr = conj(plain_conj, Conjuncts),
             Goal = hlds_goal(GoalExpr, GoalInfo0)
         ;
             ConjType = parallel_conj,
             Goal = Goal0,
-            demand_inputs(Goal, ModuleInfo, InitInstMap, everywhere,
+            demand_inputs(UnneededInfo, Goal, InitInstMap, everywhere,
                 !WhereNeededMap)
         )
     ;
         GoalExpr0 = switch(SwitchVar, CanFail, Cases0),
+        ContainingGoalMap = UnneededInfo ^ uci_containing_goal_map,
         (
-            Cases0 = [case(_, _, hlds_goal(_, FirstCaseGoalInfo)) | _],
-            FirstCaseGoalPath = goal_info_get_goal_path(FirstCaseGoalInfo),
-            FirstCaseLastStep = goal_path_get_last(FirstCaseGoalPath),
+            Cases0 = [FirstCase0 | _],
+            FirstCase0 = case(_, _, FirstCaseGoal0),
+            FirstCaseGoal0 = hlds_goal(_, FirstCaseGoalInfo0),
+            FirstCaseGoalId0 = goal_info_get_goal_id(FirstCaseGoalInfo0),
+            map.lookup(ContainingGoalMap, FirstCaseGoalId0, GoalContaining0),
+            GoalContaining0 = containing_goal(_ContainingGoalId,
+                FirstCaseLastStep),
             FirstCaseLastStep = step_switch(_, MaybeNumAltPrime)
         ->
             MaybeNumAlt = MaybeNumAltPrime
@@ -680,43 +698,44 @@
             unexpected(this_file,
                 "unneeded_process_goal_internal: switch count")
         ),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
-        BranchPoint = branch_point(GoalPath, alt_switch(MaybeNumAlt)),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
+        BranchPoint = branch_point(GoalId, alt_switch(MaybeNumAlt)),
         map.map_values_only(demand_var_everywhere, !WhereNeededMap),
         map.init(BranchNeededMap0),
-        unneeded_process_cases(Cases0, Cases, BranchPoint, 1,
-            InitInstMap, FinalInstMap, VarTypes, ModuleInfo, Options, GoalPath,
-            !.WhereNeededMap, BranchNeededMap0, BranchNeededMap, !RefinedGoals,
-            !Changed),
-        merge_where_needed_maps(GoalPath, !.WhereNeededMap,
+        unneeded_process_cases(UnneededInfo, Cases0, Cases, BranchPoint, 1,
+            InitInstMap, FinalInstMap, GoalId,
+            !.WhereNeededMap, BranchNeededMap0, BranchNeededMap,
+            !RefinedGoals, !Changed),
+        merge_where_needed_maps(ContainingGoalMap, GoalId, !.WhereNeededMap,
             BranchNeededMap, !:WhereNeededMap),
-        demand_var(GoalPath, everywhere, SwitchVar, !WhereNeededMap),
+        demand_var(ContainingGoalMap, GoalId, everywhere, SwitchVar,
+            !WhereNeededMap),
         GoalExpr = switch(SwitchVar, CanFail, Cases),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = disj(Disjuncts0),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
         map.map_values_only(demand_var_everywhere, !WhereNeededMap),
-        unneeded_process_disj(Disjuncts0, Disjuncts, InitInstMap, FinalInstMap,
-            VarTypes, ModuleInfo, Options, GoalPath,
+        unneeded_process_disj(UnneededInfo, Disjuncts0, Disjuncts,
+            InitInstMap, FinalInstMap, GoalId,
             !.WhereNeededMap, !.WhereNeededMap, !:WhereNeededMap,
             !RefinedGoals, !Changed),
         GoalExpr = disj(Disjuncts),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = if_then_else(Quant, Cond0, Then0, Else0),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
-        BranchPoint = branch_point(GoalPath, alt_ite),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
+        BranchPoint = branch_point(GoalId, alt_ite),
         map.map_values_only(demand_var_everywhere, !WhereNeededMap),
-        unneeded_process_ite(Cond0, Cond, Then0, Then, Else0, Else,
-            BranchPoint, InitInstMap, FinalInstMap, VarTypes, ModuleInfo,
-            Options, GoalPath, !WhereNeededMap, !RefinedGoals, !Changed),
+        unneeded_process_ite(UnneededInfo, Cond0, Cond,
+            Then0, Then, Else0, Else, BranchPoint, InitInstMap, FinalInstMap,
+            GoalId, !WhereNeededMap, !RefinedGoals, !Changed),
         GoalExpr = if_then_else(Quant, Cond, Then, Else),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = negation(NegGoal0),
-        unneeded_process_goal(NegGoal0, NegGoal, InitInstMap, FinalInstMap,
-            VarTypes, ModuleInfo, Options,
+        unneeded_process_goal(UnneededInfo, NegGoal0, NegGoal,
+            InitInstMap, FinalInstMap,
             !WhereNeededMap, !RefinedGoals, !Changed),
         GoalExpr = negation(NegGoal),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
@@ -725,8 +744,8 @@
         ( Reason = from_ground_term(_, from_ground_term_construct) ->
             Goal = Goal0
         ;
-            unneeded_process_goal(SomeGoal0, SomeGoal,
-                InitInstMap, FinalInstMap, VarTypes, ModuleInfo, Options,
+            unneeded_process_goal(UnneededInfo, SomeGoal0, SomeGoal,
+                InitInstMap, FinalInstMap,
                 !WhereNeededMap, !RefinedGoals, !Changed),
             GoalExpr = scope(Reason, SomeGoal),
             Goal = hlds_goal(GoalExpr, GoalInfo0)
@@ -742,17 +761,17 @@
 :- type bracketed_goal
     --->    bracketed_goal(hlds_goal, instmap, instmap).
 
-:- pred unneeded_process_conj(list(hlds_goal)::in, list(hlds_goal)::out,
-    instmap::in, instmap::in, vartypes::in, module_info::in,
-    option_values::in, where_needed_map::in, where_needed_map::out,
+:- pred unneeded_process_conj(unneeded_code_info::in,
+    list(hlds_goal)::in, list(hlds_goal)::out, instmap::in, instmap::in,
+    where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out, bool::in, bool::out) is det.
 
-unneeded_process_conj(Goals0, Goals, InitInstMap, _FinalInstMap, VarTypes,
-        ModuleInfo, Options, !WhereNeededMap, !RefinedGoals, !Changed) :-
+unneeded_process_conj(UnneededInfo, Goals0, Goals, InitInstMap, _FinalInstMap,
+        !WhereNeededMap, !RefinedGoals, !Changed) :-
     build_bracketed_conj(Goals0, InitInstMap, BracketedGoals),
     list.reverse(BracketedGoals, RevBracketedGoals),
-    unneeded_process_rev_bracketed_conj(RevBracketedGoals, RevGoals, VarTypes,
-        ModuleInfo, Options, !WhereNeededMap, !RefinedGoals, !Changed),
+    unneeded_process_rev_bracketed_conj(UnneededInfo,
+        RevBracketedGoals, RevGoals, !WhereNeededMap, !RefinedGoals, !Changed),
     list.reverse(RevGoals, Goals).
 
 :- pred build_bracketed_conj(list(hlds_goal)::in, instmap::in,
@@ -771,21 +790,21 @@
         BracketedGoals = [BracketedGoal | BracketedTail]
     ).
 
-:- pred unneeded_process_rev_bracketed_conj(list(bracketed_goal)::in,
-    list(hlds_goal)::out, vartypes::in, module_info::in, option_values::in,
+:- pred unneeded_process_rev_bracketed_conj(unneeded_code_info::in,
+    list(bracketed_goal)::in, list(hlds_goal)::out,
     where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out, bool::in, bool::out) is det.
 
-unneeded_process_rev_bracketed_conj([], [], _, _, _,
+unneeded_process_rev_bracketed_conj(_, [], [],
         !WhereNeededMap, !RefinedGoals, !Changed).
-unneeded_process_rev_bracketed_conj([BracketedGoal | BracketedGoals], Goals,
-        VarTypes, ModuleInfo, Options, !WhereNeededMap, !RefinedGoals,
-        !Changed) :-
+unneeded_process_rev_bracketed_conj(UnneededInfo,
+        [BracketedGoal | BracketedGoals], Goals,
+        !WhereNeededMap, !RefinedGoals, !Changed) :-
     BracketedGoal = bracketed_goal(Goal0, InitInstMap, FinalInstMap),
-    unneeded_process_goal(Goal0, Goal1, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, !WhereNeededMap, !RefinedGoals, !Changed),
-    unneeded_process_rev_bracketed_conj(BracketedGoals, Goals1, VarTypes,
-        ModuleInfo, Options, !WhereNeededMap, !RefinedGoals, !Changed),
+    unneeded_process_goal(UnneededInfo, Goal0, Goal1,
+        InitInstMap, FinalInstMap, !WhereNeededMap, !RefinedGoals, !Changed),
+    unneeded_process_rev_bracketed_conj(UnneededInfo, BracketedGoals, Goals1,
+        !WhereNeededMap, !RefinedGoals, !Changed),
     ( Goal1 = hlds_goal(true_goal_expr, _) ->
         Goals = Goals1
     ;
@@ -794,89 +813,87 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred unneeded_process_disj(list(hlds_goal)::in, list(hlds_goal)::out,
-    instmap::in, instmap::in, vartypes::in, module_info::in,
-    option_values::in, goal_path::in,
+:- pred unneeded_process_disj(unneeded_code_info::in,
+    list(hlds_goal)::in, list(hlds_goal)::out,
+    instmap::in, instmap::in, goal_id::in,
     where_needed_map::in, where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out, bool::in, bool::out) is det.
 
-unneeded_process_disj([], [], _, _, _, _, _, _, _,
+unneeded_process_disj(_, [], [], _, _, _, _,
         !WhereNeededMap, !RefinedGoals, !Changed).
-unneeded_process_disj([Goal0 | Goals0], [Goal | Goals],
-        InitInstMap, FinalInstMap, VarTypes, ModuleInfo, Options, CurrentPath,
+unneeded_process_disj(UnneededInfo, [Goal0 | Goals0], [Goal | Goals],
+        InitInstMap, FinalInstMap, CurrentId,
         StartWhereNeededMap, !WhereNeededMap, !RefinedGoals, !Changed) :-
-    unneeded_process_goal(Goal0, Goal, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, StartWhereNeededMap, WhereNeededMapFirst,
-        !RefinedGoals, !Changed),
+    unneeded_process_goal(UnneededInfo, Goal0, Goal, InitInstMap, FinalInstMap,
+        StartWhereNeededMap, WhereNeededMapFirst, !RefinedGoals, !Changed),
     map.to_assoc_list(WhereNeededMapFirst, WhereNeededList),
-    add_where_needed_list(WhereNeededList, CurrentPath, !WhereNeededMap),
-    unneeded_process_disj(Goals0, Goals, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, CurrentPath, StartWhereNeededMap,
+    ContainingGoalMap = UnneededInfo ^ uci_containing_goal_map,
+    add_where_needed_list(ContainingGoalMap, WhereNeededList, CurrentId,
+        !WhereNeededMap),
+    unneeded_process_disj(UnneededInfo, Goals0, Goals,
+        InitInstMap, FinalInstMap, CurrentId, StartWhereNeededMap,
         !WhereNeededMap, !RefinedGoals, !Changed).
 
 %---------------------------------------------------------------------------%
 
-:- pred unneeded_process_cases(list(case)::in, list(case)::out,
-    branch_point::in, int::in, instmap::in, instmap::in, vartypes::in,
-    module_info::in, option_values::in, goal_path::in, where_needed_map::in,
-    where_needed_map::in, where_needed_map::out,
+:- pred unneeded_process_cases(unneeded_code_info::in,
+    list(case)::in, list(case)::out, branch_point::in, int::in,
+    instmap::in, instmap::in, goal_id::in,
+    where_needed_map::in, where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out,
     bool::in, bool::out) is det.
 
-unneeded_process_cases([], [], _, _, _, _, _, _, _, _, _,
+unneeded_process_cases(_, [], [], _, _, _, _, _, _,
         !WhereNeededMap, !RefinedGoals, !Changed).
-unneeded_process_cases([Case0 | Cases0], [Case | Cases],
-        BranchPoint, BranchNum, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, CurrentPath, StartWhereNeededMap,
-        !WhereNeededMap, !RefinedGoals, !Changed) :-
+unneeded_process_cases(UnneededInfo, [Case0 | Cases0], [Case | Cases],
+        BranchPoint, BranchNum, InitInstMap, FinalInstMap, CurrentId,
+        StartWhereNeededMap, !WhereNeededMap, !RefinedGoals, !Changed) :-
     Case0 = case(MainConsId, OtherConsIds, Goal0),
-    unneeded_process_goal(Goal0, Goal, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, StartWhereNeededMap, WhereNeededMapFirst,
-        !RefinedGoals, !Changed),
+    unneeded_process_goal(UnneededInfo, Goal0, Goal, InitInstMap, FinalInstMap,
+        StartWhereNeededMap, WhereNeededMapFirst, !RefinedGoals, !Changed),
     Case = case(MainConsId, OtherConsIds, Goal),
     map.to_assoc_list(WhereNeededMapFirst, WhereNeededList),
-    add_alt_start(WhereNeededList, BranchPoint, BranchNum, CurrentPath,
-        !WhereNeededMap),
-    unneeded_process_cases(Cases0, Cases, BranchPoint, BranchNum + 1,
-        InitInstMap, FinalInstMap, VarTypes, ModuleInfo, Options, CurrentPath,
+    ContainingGoalMap = UnneededInfo ^ uci_containing_goal_map,
+    add_alt_start(ContainingGoalMap, WhereNeededList, BranchPoint, BranchNum,
+        CurrentId, !WhereNeededMap),
+    unneeded_process_cases(UnneededInfo, Cases0, Cases,
+        BranchPoint, BranchNum + 1, InitInstMap, FinalInstMap, CurrentId,
         StartWhereNeededMap, !WhereNeededMap, !RefinedGoals, !Changed).
 
 %---------------------------------------------------------------------------%
 
-:- pred unneeded_process_ite(hlds_goal::in, hlds_goal::out,
+:- pred unneeded_process_ite(unneeded_code_info::in,
+    hlds_goal::in, hlds_goal::out,
     hlds_goal::in, hlds_goal::out, hlds_goal::in, hlds_goal::out,
-    branch_point::in, instmap::in, instmap::in, vartypes::in,
-    module_info::in, option_values::in, goal_path::in,
+    branch_point::in, instmap::in, instmap::in, goal_id::in,
     where_needed_map::in, where_needed_map::out,
     refined_goal_map::in, refined_goal_map::out, bool::in, bool::out) is det.
 
-unneeded_process_ite(Cond0, Cond, Then0, Then, Else0, Else, BranchPoint,
-        InitInstMap, FinalInstMap, VarTypes, ModuleInfo, Options,
-        CurrentPath, !WhereNeededMap, !RefinedGoals, !Changed) :-
+unneeded_process_ite(UnneededInfo, Cond0, Cond, Then0, Then, Else0, Else,
+        BranchPoint, InitInstMap, FinalInstMap, CurrentId,
+        !WhereNeededMap, !RefinedGoals, !Changed) :-
     Cond0 = hlds_goal(_, CondInfo0),
     InstMapDelta = goal_info_get_instmap_delta(CondInfo0),
     instmap.apply_instmap_delta(InitInstMap, InstMapDelta, InstMapCond),
 
-    unneeded_process_goal(Else0, Else, InitInstMap, FinalInstMap, VarTypes,
-        ModuleInfo, Options, !.WhereNeededMap, WhereNeededMapElse,
-        !RefinedGoals, !Changed),
-    unneeded_process_goal(Then0, Then, InstMapCond, FinalInstMap, VarTypes,
-        ModuleInfo, Options, !.WhereNeededMap, WhereNeededMapThen,
-        !RefinedGoals, !Changed),
+    unneeded_process_goal(UnneededInfo, Else0, Else, InitInstMap, FinalInstMap,
+        !.WhereNeededMap, WhereNeededMapElse, !RefinedGoals, !Changed),
+    unneeded_process_goal(UnneededInfo, Then0, Then, InstMapCond, FinalInstMap,
+        !.WhereNeededMap, WhereNeededMapThen, !RefinedGoals, !Changed),
 
+    ContainingGoalMap = UnneededInfo ^ uci_containing_goal_map,
     map.init(BranchNeededMap0),
     map.to_assoc_list(WhereNeededMapElse, WhereNeededListElse),
-    add_alt_start(WhereNeededListElse, BranchPoint, 2,
-        CurrentPath, BranchNeededMap0, BranchNeededMap1),
+    add_alt_start(ContainingGoalMap, WhereNeededListElse, BranchPoint, 2,
+        CurrentId, BranchNeededMap0, BranchNeededMap1),
     map.to_assoc_list(WhereNeededMapThen, WhereNeededListThen),
-    add_alt_start(WhereNeededListThen, BranchPoint, 1,
-        CurrentPath, BranchNeededMap1, BranchNeededMap),
-    merge_where_needed_maps(CurrentPath,
+    add_alt_start(ContainingGoalMap, WhereNeededListThen, BranchPoint, 1,
+        CurrentId, BranchNeededMap1, BranchNeededMap),
+    merge_where_needed_maps(ContainingGoalMap, CurrentId,
         !.WhereNeededMap, BranchNeededMap, WhereNeededMapCond),
 
-    unneeded_process_goal(Cond0, Cond, InitInstMap, InstMapCond,
-        VarTypes, ModuleInfo, Options, WhereNeededMapCond,
-        !:WhereNeededMap, !RefinedGoals, !Changed).
+    unneeded_process_goal(UnneededInfo, Cond0, Cond, InitInstMap, InstMapCond,
+        WhereNeededMapCond, !:WhereNeededMap, !RefinedGoals, !Changed).
 
 %---------------------------------------------------------------------------%
 
@@ -884,30 +901,30 @@
     % in the resulting where_needed_map iff it is needed there in one of
     % the input maps.
     %
-:- pred merge_where_needed_maps(goal_path::in,
-    where_needed_map::in, where_needed_map::in, where_needed_map::out)
-    is det.
+:- pred merge_where_needed_maps(containing_goal_map::in, goal_id::in,
+    where_needed_map::in, where_needed_map::in, where_needed_map::out) is det.
 
-merge_where_needed_maps(CurrentPath,
+merge_where_needed_maps(ContainingGoalMap, CurrentId,
         WhereNeededMap1, WhereNeededMap2, WhereNeededMap) :-
     map.to_assoc_list(WhereNeededMap1, WhereNeededList1),
-    add_where_needed_list(WhereNeededList1, CurrentPath,
+    add_where_needed_list(ContainingGoalMap, WhereNeededList1, CurrentId,
         WhereNeededMap2, WhereNeededMap).
 
-:- pred add_where_needed_list(assoc_list(prog_var, where_needed)::in,
-    goal_path::in, where_needed_map::in, where_needed_map::out) is det.
+:- pred add_where_needed_list(containing_goal_map::in,
+    assoc_list(prog_var, where_needed)::in, goal_id::in,
+    where_needed_map::in, where_needed_map::out) is det.
 
-add_where_needed_list([], _, !WhereNeededMap).
-add_where_needed_list([Var - BranchWhere | WhereNeededList],
-        CurrentPath, !WhereNeededMap) :-
+add_where_needed_list(_, [], _, !WhereNeededMap).
+add_where_needed_list(ContainingGoalMap, [Var - BranchWhere | WhereNeededList],
+        CurrentId, !WhereNeededMap) :-
     ( map.search(!.WhereNeededMap, Var, OldWhere) ->
-        where_needed_upper_bound(CurrentPath, BranchWhere, OldWhere,
-            CombinedWhere),
+        where_needed_upper_bound(ContainingGoalMap, CurrentId,
+            BranchWhere, OldWhere, CombinedWhere),
         svmap.det_update(Var, CombinedWhere, !WhereNeededMap)
     ;
         svmap.det_insert(Var, BranchWhere, !WhereNeededMap)
     ),
-    add_where_needed_list(WhereNeededList, CurrentPath,
+    add_where_needed_list(ContainingGoalMap, WhereNeededList, CurrentId,
         !WhereNeededMap).
 
     % Given a where_needed_map, add to it the where_needed information for the
@@ -916,13 +933,13 @@
     % variable is needed everywhere, the scope of this "everywhere" is only
     % that alternative.
     %
-:- pred add_alt_start(assoc_list(prog_var, where_needed)::in,
-    branch_point::in, int::in, goal_path::in,
-    where_needed_map::in, where_needed_map::out) is det.
-
-add_alt_start([], _, _, _, !WhereNeededMap).
-add_alt_start([Var - BranchWhere0 | WhereNeededList],
-        BranchPoint, BranchNum, CurrentPath, !WhereNeededMap) :-
+:- pred add_alt_start(containing_goal_map::in,
+    assoc_list(prog_var, where_needed)::in, branch_point::in,
+    int::in, goal_id::in, where_needed_map::in, where_needed_map::out) is det.
+
+add_alt_start(_, [], _, _, _, !WhereNeededMap).
+add_alt_start(ContainingGoalMap, [Var - BranchWhere0 | WhereNeededList],
+        BranchPoint, BranchNum, CurrentId, !WhereNeededMap) :-
     (
         BranchWhere0 = everywhere,
         map.init(Empty),
@@ -934,14 +951,14 @@
         BranchWhere = BranchWhere0
     ),
     ( map.search(!.WhereNeededMap, Var, OldWhere) ->
-        where_needed_upper_bound(CurrentPath, BranchWhere, OldWhere,
-            CombinedWhere),
+        where_needed_upper_bound(ContainingGoalMap, CurrentId,
+            BranchWhere, OldWhere, CombinedWhere),
         svmap.det_update(Var, CombinedWhere, !WhereNeededMap)
     ;
         svmap.det_insert(Var, BranchWhere, !WhereNeededMap)
     ),
-    add_alt_start(WhereNeededList, BranchPoint, BranchNum,
-        CurrentPath, !WhereNeededMap).
+    add_alt_start(ContainingGoalMap, WhereNeededList, BranchPoint, BranchNum,
+        CurrentId, !WhereNeededMap).
 
 %---------------------------------------------------------------------------%
 
@@ -970,22 +987,22 @@
         )
     ;
         GoalExpr0 = switch(SwitchVar, CanFail, Cases0),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
-        unneeded_refine_cases(Cases0, Cases, !RefinedGoals, GoalPath, 1),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
+        unneeded_refine_cases(Cases0, Cases, !RefinedGoals, GoalId, 1),
         GoalExpr = switch(SwitchVar, CanFail, Cases),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = disj(Disjuncts0),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
         unneeded_refine_disj(Disjuncts0, Disjuncts, !RefinedGoals,
-            GoalPath, 1),
+            GoalId, 1),
         GoalExpr = disj(Disjuncts),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = if_then_else(Quant, Cond0, Then0, Else0),
-        GoalPath = goal_info_get_goal_path(GoalInfo0),
+        GoalId = goal_info_get_goal_id(GoalInfo0),
         unneeded_refine_ite(Cond0, Cond, Then0, Then, Else0, Else,
-            !RefinedGoals, GoalPath),
+            !RefinedGoals, GoalId),
         GoalExpr = if_then_else(Quant, Cond, Then, Else),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
@@ -1022,59 +1039,59 @@
 
 :- pred unneeded_refine_cases(list(case)::in, list(case)::out,
     refined_goal_map::in, refined_goal_map::out,
-    goal_path::in, int::in) is det.
+    goal_id::in, int::in) is det.
 
 unneeded_refine_cases([], [], !RefinedGoals, _, _).
 unneeded_refine_cases([Case0 | Cases0], [Case | Cases], !RefinedGoals,
-        GoalPath, BranchNum) :-
+        GoalId, BranchNum) :-
     Case0 = case(MainConsId, OtherConsIds, Goal0),
     unneeded_refine_goal(Goal0, Goal1, !RefinedGoals),
-    ( map.search(!.RefinedGoals, GoalPath - BranchNum, ToInsertGoals) ->
+    ( map.search(!.RefinedGoals, GoalId - BranchNum, ToInsertGoals) ->
         insert_refine_goals(ToInsertGoals, Goal1, Goal),
-        svmap.delete(GoalPath - BranchNum, !RefinedGoals)
+        svmap.delete(GoalId - BranchNum, !RefinedGoals)
     ;
         Goal = Goal1
     ),
     Case = case(MainConsId, OtherConsIds, Goal),
     unneeded_refine_cases(Cases0, Cases, !RefinedGoals,
-        GoalPath, BranchNum + 1).
+        GoalId, BranchNum + 1).
 
 :- pred unneeded_refine_disj(list(hlds_goal)::in, list(hlds_goal)::out,
     refined_goal_map::in, refined_goal_map::out,
-    goal_path::in, int::in) is det.
+    goal_id::in, int::in) is det.
 
 unneeded_refine_disj([], [], !RefinedGoals, _, _).
 unneeded_refine_disj([Goal0 | Goals0], [Goal | Goals], !RefinedGoals,
-        GoalPath, BranchNum) :-
+        GoalId, BranchNum) :-
     unneeded_refine_goal(Goal0, Goal1, !RefinedGoals),
-    ( map.search(!.RefinedGoals, GoalPath - BranchNum, ToInsertGoals) ->
+    ( map.search(!.RefinedGoals, GoalId - BranchNum, ToInsertGoals) ->
         insert_refine_goals(ToInsertGoals, Goal1, Goal),
-        svmap.delete(GoalPath - BranchNum, !RefinedGoals)
+        svmap.delete(GoalId - BranchNum, !RefinedGoals)
     ;
         Goal = Goal1
     ),
-    unneeded_refine_disj(Goals0, Goals, !RefinedGoals, GoalPath,
-        BranchNum + 1).
+    unneeded_refine_disj(Goals0, Goals, !RefinedGoals,
+        GoalId, BranchNum + 1).
 
 :- pred unneeded_refine_ite(hlds_goal::in, hlds_goal::out,
     hlds_goal::in, hlds_goal::out, hlds_goal::in, hlds_goal::out,
-    refined_goal_map::in, refined_goal_map::out, goal_path::in) is det.
+    refined_goal_map::in, refined_goal_map::out, goal_id::in) is det.
 
 unneeded_refine_ite(Cond0, Cond, Then0, Then, Else0, Else,
-        !RefinedGoals, GoalPath) :-
+        !RefinedGoals, GoalId) :-
     unneeded_refine_goal(Cond0, Cond, !RefinedGoals),
     unneeded_refine_goal(Then0, Then1, !RefinedGoals),
     unneeded_refine_goal(Else0, Else1, !RefinedGoals),
 
-    ( map.search(!.RefinedGoals, GoalPath - 1, ToInsertGoalsThen) ->
+    ( map.search(!.RefinedGoals, GoalId - 1, ToInsertGoalsThen) ->
         insert_refine_goals(ToInsertGoalsThen, Then1, Then),
-        svmap.delete(GoalPath - 1, !RefinedGoals)
+        svmap.delete(GoalId - 1, !RefinedGoals)
     ;
         Then = Then1
     ),
-    ( map.search(!.RefinedGoals, GoalPath - 2, ToInsertGoalsElse) ->
+    ( map.search(!.RefinedGoals, GoalId - 2, ToInsertGoalsElse) ->
         insert_refine_goals(ToInsertGoalsElse, Else1, Else),
-        svmap.delete(GoalPath - 2, !RefinedGoals)
+        svmap.delete(GoalId - 2, !RefinedGoals)
     ;
         Else = Else1
     ).
@@ -1096,10 +1113,10 @@
     % requirements (e.g. branch sets {b1,b2} and {b3} covers all
     % computation paths.
     %
-:- pred where_needed_upper_bound(goal_path::in,
+:- pred where_needed_upper_bound(containing_goal_map::in, goal_id::in,
     where_needed::in, where_needed::in, where_needed::out) is det.
 
-where_needed_upper_bound(CurrentPath,
+where_needed_upper_bound(ContainingGoalMap, CurrentId,
         WhereNeededA, WhereNeededB, WhereNeeded) :-
     (
         WhereNeededA = everywhere,
@@ -1111,86 +1128,86 @@
             WhereNeeded = everywhere
         ;
             WhereNeededB = branches(BranchesB),
-            where_needed_branches_upper_bound(CurrentPath,
+            where_needed_branches_upper_bound(ContainingGoalMap, CurrentId,
                 BranchesA, BranchesB, WhereNeeded)
         )
     ).
 
-:- pred where_needed_branches_upper_bound(goal_path::in,
+:- pred where_needed_branches_upper_bound(containing_goal_map::in, goal_id::in,
     where_needed_branches::in, where_needed_branches::in, where_needed::out)
     is det.
 
-where_needed_branches_upper_bound(CurrentPath, BranchesA, BranchesB,
-        WhereNeeded) :-
-    % Should select smaller map to convert to list.
+where_needed_branches_upper_bound(ContainingGoalMap, CurrentId,
+        BranchesA, BranchesB, WhereNeeded) :-
+    % We should select the smaller map to convert to list.
     map.to_assoc_list(BranchesA, BranchesList),
-    where_needed_branches_upper_bound_2(CurrentPath,
+    where_needed_branches_upper_bound_2(ContainingGoalMap, CurrentId,
         BranchesList, BranchesB, WhereNeeded).
 
-:- pred where_needed_branches_upper_bound_2(goal_path::in,
-    assoc_list(branch_point, set(int))::in, where_needed_branches::in,
-    where_needed::out) is det.
+:- pred where_needed_branches_upper_bound_2(containing_goal_map::in,
+    goal_id::in, assoc_list(branch_point, set(int))::in,
+    where_needed_branches::in, where_needed::out) is det.
 
-where_needed_branches_upper_bound_2(_, [],
+where_needed_branches_upper_bound_2(_, _, [],
         Branches, branches(Branches)).
-where_needed_branches_upper_bound_2(CurrentPath, [First | Rest],
-        Branches0, WhereNeeded) :-
+where_needed_branches_upper_bound_2(ContainingGoalMap, CurrentId,
+        [First | Rest], Branches0, WhereNeeded) :-
     First = BranchPoint - NewAlts,
     ( map.search(Branches0, BranchPoint, OldAlts) ->
         set.union(OldAlts, NewAlts, Alts),
-        BranchPoint = branch_point(GoalPath, BranchAlts),
+        BranchPoint = branch_point(BranchGoalId, BranchAlts),
         ( branch_point_is_complete(BranchAlts, Alts) ->
             (
-                get_parent_branch_point(GoalPath,
-                    ParentGoalInitialPath, ParentGoalPathStep,
+                get_parent_branch_point(ContainingGoalMap, BranchGoalId,
+                    ParentBranchGoalId, ParentBranchArmGoalId,
                     ParentBranchAlt, ParentBranchNum),
-                ParentGoalPath = goal_path_add_at_end(ParentGoalInitialPath,
-                    ParentGoalPathStep),
-                \+ goal_path_inside(ParentGoalPath, CurrentPath)
+                \+ goal_id_inside(ContainingGoalMap, ParentBranchArmGoalId,
+                    CurrentId)
             ->
                 map.delete(Branches0, BranchPoint, Branches1),
-                ParentBranchPoint = branch_point(ParentGoalInitialPath,
+                ParentBranchPoint = branch_point(ParentBranchGoalId,
                     ParentBranchAlt),
                 set.singleton_set(ParentAlts, ParentBranchNum),
-                where_needed_branches_upper_bound_2(CurrentPath,
-                    [ParentBranchPoint - ParentAlts | Rest], Branches1,
-                    WhereNeeded)
+                where_needed_branches_upper_bound_2(ContainingGoalMap,
+                    CurrentId, [ParentBranchPoint - ParentAlts | Rest],
+                    Branches1, WhereNeeded)
             ;
                 WhereNeeded = everywhere
             )
         ;
             map.det_update(Branches0, BranchPoint, Alts, Branches1),
-            where_needed_branches_upper_bound_2(CurrentPath,
+            where_needed_branches_upper_bound_2(ContainingGoalMap, CurrentId,
                 Rest, Branches1, WhereNeeded)
         )
     ;
         map.det_insert(Branches0, BranchPoint, NewAlts, Branches1),
-        where_needed_branches_upper_bound_2(CurrentPath, Rest,
-            Branches1, WhereNeeded)
+        where_needed_branches_upper_bound_2(ContainingGoalMap, CurrentId,
+            Rest, Branches1, WhereNeeded)
     ).
 
-:- pred get_parent_branch_point(goal_path::in, goal_path::out,
-    goal_path_step::out, branch_alts::out, int::out) is semidet.
+:- pred get_parent_branch_point(containing_goal_map::in, goal_id::in,
+    goal_id::out, goal_id::out, branch_alts::out, int::out) is semidet.
 
-get_parent_branch_point(GoalPath, ParentPath, ParentStep,
-        BranchAlt, BranchNum) :-
-    goal_path_remove_last(GoalPath, InitialPath, LastStep),
+get_parent_branch_point(ContainingGoalMap, GoalId, BranchGoalId,
+        BranchArmGoalId, BranchAlt, BranchNum) :-
+    map.lookup(ContainingGoalMap, GoalId, GoalContaining),
+    GoalContaining = containing_goal(ContainingGoalId, LastStep),
     (
         LastStep = step_switch(Arm, MaybeNumAlts),
-        ParentPath = InitialPath,
-        ParentStep = LastStep,
+        BranchGoalId = ContainingGoalId,
+        BranchArmGoalId = GoalId,
         BranchAlt = alt_switch(MaybeNumAlts),
         BranchNum = Arm
     ;
         LastStep = step_ite_then,
-        ParentPath = InitialPath,
-        ParentStep = LastStep,
+        BranchGoalId = ContainingGoalId,
+        BranchArmGoalId = GoalId,
         BranchAlt = alt_ite,
         BranchNum = 1
     ;
         LastStep = step_ite_else,
-        ParentPath = InitialPath,
-        ParentStep = LastStep,
+        BranchGoalId = ContainingGoalId,
+        BranchArmGoalId = GoalId,
         BranchAlt = alt_ite,
         BranchNum = 2
     ;
@@ -1202,8 +1219,8 @@
         ; LastStep = step_first
         ; LastStep = step_later
         ),
-        get_parent_branch_point(InitialPath, ParentPath, ParentStep,
-            BranchAlt, BranchNum)
+        get_parent_branch_point(ContainingGoalMap, ContainingGoalId,
+            BranchGoalId, BranchArmGoalId, BranchAlt, BranchNum)
     ).
 
 :- pred branch_point_is_complete(branch_alts::in, set(int)::in) is semidet.
cvs diff: Diffing compiler/notes
cvs diff: Diffing deep_profiler
Index: deep_profiler/analysis_utils.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/analysis_utils.m,v
retrieving revision 1.3
diff -u -r1.3 analysis_utils.m
--- deep_profiler/analysis_utils.m	15 Dec 2010 06:30:32 -0000	1.3
+++ deep_profiler/analysis_utils.m	17 Dec 2010 03:03:26 -0000
@@ -68,8 +68,8 @@
 
 :- pred build_call_site_cost_and_callee_map(deep::in,
     pair(call_site_static_ptr, call_site_array_slot)::in,
-    map(goal_path, cost_and_callees)::in, map(goal_path, cost_and_callees)::out)
-    is det.
+    map(reverse_goal_path, cost_and_callees)::in,
+    map(reverse_goal_path, cost_and_callees)::out) is det.
 
 %----------------------------------------------------------------------------%
 
@@ -78,7 +78,7 @@
     %
 :- pred build_recursive_call_site_cost_map(deep, clique_ptr,
     proc_dynamic_ptr, recursion_type, maybe(recursion_depth),
-    maybe_error(map(goal_path, cs_cost_csq))) is det.
+    maybe_error(map(reverse_goal_path, cs_cost_csq))) is det.
 :- mode build_recursive_call_site_cost_map(in, in, in,
     in(recursion_type_known_costs), in(maybe_yes(ground)),
     out(maybe_error_ok(ground))) is det.
@@ -176,8 +176,8 @@
     CostAndCallees = cost_and_callees(CostCsq, set(Callees), HigherOrder),
     lookup_call_site_statics(Deep ^ call_site_statics, CSSPtr, CSS),
     call_site_kind_to_higher_order(CSS ^ css_kind, HigherOrder),
-    goal_path_from_string_det(CSS ^ css_goal_path, GoalPath),
-    svmap.det_insert(GoalPath, CostAndCallees, !CallSitesMap).
+    rev_goal_path_from_string_det(CSS ^ css_goal_path, RevGoalPath),
+    svmap.det_insert(RevGoalPath, CostAndCallees, !CallSitesMap).
 
 :- pred call_site_dynamic_get_callee_and_costs(deep::in,
     call_site_dynamic_ptr::in, callee::out, own_prof_info::out,
@@ -265,7 +265,7 @@
     ).
 
 :- pred get_recursive_calls_and_counts(deep::in, clique_ptr::in,
-    proc_dynamic_ptr::in, map(goal_path, int)::out) is det.
+    proc_dynamic_ptr::in, map(reverse_goal_path, int)::out) is det.
 
 get_recursive_calls_and_counts(Deep, CliquePtr, PDPtr, CallCountsMap) :-
     proc_dynamic_paired_call_site_slots(Deep, PDPtr, SiteSlots),
@@ -274,7 +274,7 @@
 
 :- pred build_recursive_call_site_counts_map(deep::in, clique_ptr::in,
     pair(call_site_static_ptr, call_site_array_slot)::in,
-    map(goal_path, int)::in, map(goal_path, int)::out) is det.
+    map(reverse_goal_path, int)::in, map(reverse_goal_path, int)::out) is det.
 
 build_recursive_call_site_counts_map(Deep, CliquePtr, CSSPtr - CSDSlot,
         !Map) :-
@@ -309,8 +309,8 @@
     (
         Recursive = yes,
         deep_lookup_call_site_statics(Deep, CSSPtr, CSS),
-        goal_path_from_string_det(CSS ^ css_goal_path, GoalPath),
-        svmap.det_insert(GoalPath, Count, !Map)
+        rev_goal_path_from_string_det(CSS ^ css_goal_path, RevGoalPath),
+        svmap.det_insert(RevGoalPath, Count, !Map)
     ;
         Recursive = no
     ).
@@ -333,20 +333,20 @@
         MaybeCallee = no
     ).
 
-:- pred format_recursive_call_site_cost_map(map(goal_path, cs_cost_csq)::in,
-    cord(string)::out) is det.
+:- pred format_recursive_call_site_cost_map(
+    map(reverse_goal_path, cs_cost_csq)::in, cord(string)::out) is det.
 
 format_recursive_call_site_cost_map(Map, Result) :-
     map.foldl(format_recursive_call_site_cost, Map, cord.empty, Result).
 
-:- pred format_recursive_call_site_cost(goal_path::in, cs_cost_csq::in,
+:- pred format_recursive_call_site_cost(reverse_goal_path::in, cs_cost_csq::in,
     cord(string)::in, cord(string)::out) is det.
 
-format_recursive_call_site_cost(GoalPath, Cost, !Result) :-
+format_recursive_call_site_cost(RevGoalPath, Cost, !Result) :-
     !:Result = cord.snoc(!.Result ++ indent(1), String),
     String = format("%s -> Percall cost: %f Calls: %f\n",
         [s(GoalPathString), f(PerCallCost), f(Calls)]),
-    GoalPathString = goal_path_to_string(GoalPath),
+    GoalPathString = rev_goal_path_to_string(RevGoalPath),
     PerCallCost = cs_cost_get_percall(Cost),
     Calls = cs_cost_get_calls(Cost).
 
Index: deep_profiler/coverage.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/coverage.m,v
retrieving revision 1.10
diff -u -r1.10 coverage.m
--- deep_profiler/coverage.m	15 Dec 2010 06:30:33 -0000	1.10
+++ deep_profiler/coverage.m	17 Dec 2010 02:41:26 -0000
@@ -67,7 +67,7 @@
                 % immediately before this goal, otherwise it is immediately
                 % after.
 
-                goal_path,
+                reverse_goal_path,
 
                 % The type of this coverage point.
                 cp_type
@@ -93,9 +93,10 @@
     % Annotate the program representation structure with coverage information.
     %
 :- pred procrep_annotate_with_coverage(own_prof_info::in,
-    map(goal_path, calls_and_exits)::in, map(goal_path, coverage_point)::in,
-    map(goal_path, coverage_point)::in, proc_rep::in,
-    maybe_error(proc_rep(coverage_info))::out) is det.
+    map(reverse_goal_path, calls_and_exits)::in,
+    map(reverse_goal_path, coverage_point)::in,
+    map(reverse_goal_path, coverage_point)::in,
+    proc_rep::in, maybe_error(proc_rep(coverage_info))::out) is det.
 
 %-----------------------------------------------------------------------------%
 
@@ -224,7 +225,7 @@
         Before = before_coverage(Calls),
         CoverageReference = coverage_reference_info(ProcLabel, CallSites,
             SolnsCoveragePoints, BranchCoveragePoints),
-        goal_annotate_coverage(CoverageReference, empty_goal_path,
+        goal_annotate_coverage(CoverageReference, [],
             Before, After, !GoalRep),
         require(unify(After, after_coverage(Exits)),
             "Coverage after procedure not equal with exit count of" ++
@@ -234,59 +235,61 @@
         MaybeProcRep = ok(!.ProcRep)
     ).
 
-    % These maps are keyed by goal_path, comparing these structures is less
-    % efficient than comparing simple structures like the alternative
+    % These maps are keyed by reverse_goal_path, comparing these structures
+    % is less efficient than comparing simple structures like the alternative
     % goal_path_string, however, that involves frequently constructing strings
-    % from goal paths.  Using goal_path_string may be faster but I'd rather not
-    % make this optimisation without first testing it.
+    % from goal paths.  Using reverse_goal_path_string may be faster but
+    % I'd rather not make this optimisation without first testing it.
     %
 :- type coverage_reference_info
     --->    coverage_reference_info(
-                cri_proc                    :: string_proc_label,
-                cri_call_sites              :: map(goal_path, calls_and_exits),
-                cri_solns_coverage_points   :: map(goal_path, coverage_point),
-                cri_branch_coverage_points  :: map(goal_path, coverage_point)
+                cri_proc        :: string_proc_label,
+                cri_call_sites  :: map(reverse_goal_path, calls_and_exits),
+                cri_solns_coverage_points 
+                                :: map(reverse_goal_path, coverage_point),
+                cri_branch_coverage_points
+                                :: map(reverse_goal_path, coverage_point)
             ).
 
     % Annotate a goal and its children with coverage information.
     %
-:- pred goal_annotate_coverage(coverage_reference_info::in, goal_path::in,
-    coverage_before::in, coverage_after::out,
+:- pred goal_annotate_coverage(coverage_reference_info::in,
+    list(goal_path_step)::in, coverage_before::in, coverage_after::out,
     goal_rep(unit)::in, goal_rep(coverage_info)::out) is det.
 
-goal_annotate_coverage(Info, GoalPath, Before, After, Goal0, Goal) :-
+goal_annotate_coverage(Info, RevGoalPathSteps, Before, After, Goal0, Goal) :-
     Goal0 = goal_rep(GoalExpr0, Detism, _),
 
     % Calculate coverage of any inner goals.
     (
         GoalExpr0 = conj_rep(Conjuncts0),
-        conj_annotate_coverage(Info, GoalPath, Before, After0,
-            Conjuncts0, Conjuncts),
+        conj_annotate_coverage(Info, RevGoalPathSteps,
+            Before, After0, Conjuncts0, Conjuncts),
         GoalExpr = conj_rep(Conjuncts)
     ;
         GoalExpr0 = disj_rep(Disjuncts0),
-        disj_annotate_coverage(Info, Detism, GoalPath, Before, After0,
-            Disjuncts0, Disjuncts),
+        disj_annotate_coverage(Info, Detism, RevGoalPathSteps,
+            Before, After0, Disjuncts0, Disjuncts),
         GoalExpr = disj_rep(Disjuncts)
     ;
         GoalExpr0 = switch_rep(Var, CanFail, Cases0),
-        switch_annotate_coverage(Info, CanFail, GoalPath, Before, After0,
-            Cases0, Cases),
+        switch_annotate_coverage(Info, CanFail, RevGoalPathSteps,
+            Before, After0, Cases0, Cases),
         GoalExpr = switch_rep(Var, CanFail, Cases)
     ;
         GoalExpr0 = ite_rep(Cond0, Then0, Else0),
-        ite_annotate_coverage(Info, GoalPath, Before, After0, Cond0, Cond,
-            Then0, Then, Else0, Else),
+        ite_annotate_coverage(Info, RevGoalPathSteps,
+            Before, After0, Cond0, Cond, Then0, Then, Else0, Else),
         GoalExpr = ite_rep(Cond, Then, Else)
     ;
         GoalExpr0 = negation_rep(NegGoal0),
-        negation_annotate_coverage(Info, GoalPath, Before, After0,
-            NegGoal0, NegGoal),
+        negation_annotate_coverage(Info, RevGoalPathSteps,
+            Before, After0, NegGoal0, NegGoal),
         GoalExpr = negation_rep(NegGoal)
     ;
         GoalExpr0 = scope_rep(ScopedGoal0, MaybeCut),
-        scope_annotate_coverage(Info, GoalPath, MaybeCut, Before, After0,
-            ScopedGoal0, ScopedGoal),
+        scope_annotate_coverage(Info, RevGoalPathSteps, MaybeCut,
+            Before, After0, ScopedGoal0, ScopedGoal),
         GoalExpr = scope_rep(ScopedGoal, MaybeCut)
     ;
         GoalExpr0 = atomic_goal_rep(Filename, Line, Vars, AtomicGoal),
@@ -297,7 +300,10 @@
             ; AtomicGoal = higher_order_call_rep(_, _)
             ; AtomicGoal = method_call_rep(_, _, _)
             ),
-            ( map.search(Info ^ cri_call_sites, GoalPath, CallsAndExits) ->
+            (
+                map.search(Info ^ cri_call_sites, rgp(RevGoalPathSteps),
+                    CallsAndExits)
+            ->
                 % Entry due to redo is not counted at the point before the
                 % goal, it is represented when the number of exists is greater
                 % than the number of calls. XXX This won't work with nondet
@@ -309,7 +315,7 @@
             ;
                 unexpected($module, $pred,
                     "Couldn't look up call site for port counts GP: " ++
-                    goal_path_to_string(GoalPath))
+                    rev_goal_path_to_string(rgp(RevGoalPathSteps)))
             )
         ;
             ( AtomicGoal = builtin_call_rep(_, _, _)
@@ -331,7 +337,10 @@
     % even when the coverage has been calculated from inner goals, since this
     % is used to perform an assertion that these two sources agree about the
     % coverage after this goal.
-    ( map.search(Info ^ cri_solns_coverage_points, GoalPath, CoveragePoint) ->
+    (
+        map.search(Info ^ cri_solns_coverage_points, rgp(RevGoalPathSteps),
+            CoveragePoint)
+    ->
         CoveragePoint = coverage_point(CoverageAfterCount, _, _),
         after_count_from_either_source(after_coverage(CoverageAfterCount),
             After0, After)
@@ -344,7 +353,7 @@
     trace [compile_time(flag("debug_coverage_propagation")), io(!IO)] (
         io.write_string("goal_annotate_coverage: done\n", !IO),
         io.format("\tGoalPath: %s\n\tDetism %s\n\tCoverage; %s\n",
-            [s(goal_path_to_string(GoalPath)),
+            [s(rev_goal_path_to_string(rgp(RevGoalPathSteps))),
              s(string(Detism)),
              s(string(GoalCoverage))], !IO)
     ),
@@ -352,17 +361,17 @@
         ( check_coverage_complete(GoalCoverage, GoalExpr) ->
             true
         ;
-            error(
+            unexpected($module, $pred,
                 string.format("check_coverage_complete failed\n" ++
                     "\tCoverage: %s\n\tGoalPath: %s\n\tProc: %s\n",
                     [s(string(GoalCoverage)), 
-                     s(goal_path_to_string(GoalPath)),
+                     s(rev_goal_path_to_string(rgp(RevGoalPathSteps))),
                      s(string(Info ^ cri_proc))]))
         ),
         ( check_coverage_regarding_detism(GoalCoverage, Detism) ->
             true
         ;
-            error(
+            unexpected($module, $pred,
                 string.format("check_coverage_regarding_detism failed: %s %s",
                     [s(string(GoalCoverage)), s(string(Detism))]))
         )
@@ -416,12 +425,12 @@
 
     % Annotate a conjunction with coverage information.
     %
-:- pred conj_annotate_coverage(coverage_reference_info::in, goal_path::in,
-    coverage_before::in, coverage_after::out,
+:- pred conj_annotate_coverage(coverage_reference_info::in,
+    list(goal_path_step)::in, coverage_before::in, coverage_after::out,
     list(goal_rep(unit))::in, list(goal_rep(coverage_info))::out) is det.
 
-conj_annotate_coverage(Info, GoalPath, Before, After, Conjs0, Conjs) :-
-    conj_annotate_coverage_2(Info, GoalPath, 1, Before, After,
+conj_annotate_coverage(Info, RevGoalPathSteps, Before, After, Conjs0, Conjs) :-
+    conj_annotate_coverage_2(Info, RevGoalPathSteps, 1, Before, After,
         Conjs0, Conjs).
 
     % Annotate a conjunction with coverage information.
@@ -431,19 +440,20 @@
     % conjunction.  Each goal also has it's own coverage.
     %
 :- pred conj_annotate_coverage_2(coverage_reference_info::in,
-    goal_path::in, int::in, coverage_before::in, coverage_after::out,
+    list(goal_path_step)::in, int::in,
+    coverage_before::in, coverage_after::out,
     list(goal_rep(unit))::in, list(goal_rep(coverage_info))::out) is det.
 
 conj_annotate_coverage_2(_, _, _, Before, After, [], []) :-
     % The empty conjunction is equivalent to 'true' which is deterministic,
     propagate_det_coverage(Before, After).
-conj_annotate_coverage_2(Info, GoalPath, ConjunctNum, Before, After,
+conj_annotate_coverage_2(Info, RevGoalPathSteps, ConjunctNum, Before, After,
         [Conj0 | Conjs0], [Conj | Conjs]) :-
-    HeadGoalPath = goal_path_add_at_end(GoalPath, step_conj(ConjunctNum)),
-    goal_annotate_coverage(Info, HeadGoalPath,
+    RevSubGoalPathStep = [step_conj(ConjunctNum) | RevGoalPathSteps],
+    goal_annotate_coverage(Info, RevSubGoalPathStep,
         Before, CoverageAfterHead, Conj0, Conj),
     after_to_before_coverage(CoverageAfterHead, CoverageBeforeTail),
-    conj_annotate_coverage_2(Info, GoalPath, ConjunctNum + 1,
+    conj_annotate_coverage_2(Info, RevGoalPathSteps, ConjunctNum + 1,
         CoverageBeforeTail, After, Conjs0, Conjs).
 
     % Compute the coverage information for a disjunction.
@@ -454,30 +464,30 @@
     %   - The coverage after a disjunction is equal to the sum of coverages
     %     after each disjunct.
     %
-:- pred disj_annotate_coverage(coverage_reference_info::in,
-    detism_rep::in, goal_path::in, coverage_before::in, coverage_after::out,
+:- pred disj_annotate_coverage(coverage_reference_info::in, detism_rep::in,
+    list(goal_path_step)::in, coverage_before::in, coverage_after::out,
     list(goal_rep(unit))::in, list(goal_rep(coverage_info))::out) is det.
 
-disj_annotate_coverage(Info, Detism, GoalPath, Before, After,
+disj_annotate_coverage(Info, Detism, RevGoalPathSteps, Before, After,
         Disjs0, Disjs) :-
     % XXX In theory, we could update Before using information from any counter
     % at the start of the first disjunct, but we don't do that (yet).  This may
     % not be useful for some disjunctions, for example those called from a
     % single solution context or committed-choice.
     Solutions = detism_get_solutions(Detism),
-    disj_annotate_coverage_2(Info, GoalPath, 1, Solutions,
+    disj_annotate_coverage_2(Info, RevGoalPathSteps, 1, Solutions,
         Before, sum_after_zero, SumAfterDisjuncts, Disjs0, Disjs),
     after_count_sum_after_count(SumAfterDisjuncts, After).
 
 :- pred disj_annotate_coverage_2(coverage_reference_info::in,
-    goal_path::in, int::in, solution_count_rep::in, coverage_before::in,
-    sum_coverage_after::in, sum_coverage_after::out,
+    list(goal_path_step)::in, int::in, solution_count_rep::in,
+    coverage_before::in, sum_coverage_after::in, sum_coverage_after::out,
     list(goal_rep)::in, list(goal_rep(coverage_info))::out) is det.
 
 disj_annotate_coverage_2(_, _, _, _, _, !SumAfter, [], []).
-disj_annotate_coverage_2(Info, GoalPath, DisjNum, Solutions,
+disj_annotate_coverage_2(Info, RevGoalPathSteps, DisjNum, Solutions,
         Before0, !SumAfter, [Disj0 | Disjs0], [Disj | Disjs]) :-
-    DisjGoalPath = goal_path_add_at_end(GoalPath, step_disj(DisjNum)),
+    RevSubGoalPathSteps = [step_disj(DisjNum) | RevGoalPathSteps],
     (
         ( Before0 = before_known(_)
         ; Before0 = before_zero
@@ -485,28 +495,28 @@
         Before = Before0
     ;
         Before0 = before_unknown,
-        get_branch_start_coverage(Info, DisjGoalPath, Before)
+        get_branch_start_coverage(Info, rgp(RevSubGoalPathSteps), Before)
     ),
-    goal_annotate_coverage(Info, DisjGoalPath,
+    goal_annotate_coverage(Info, RevSubGoalPathSteps,
         Before, After, Disj0, Disj),
     sum_after_coverage(After, !SumAfter),
     % We don't know how many times the start of the next disjunct is executed
     % unless we have a counter there.
-    disj_annotate_coverage_2(Info, GoalPath, DisjNum + 1, Solutions,
+    disj_annotate_coverage_2(Info, RevGoalPathSteps, DisjNum + 1, Solutions,
         before_unknown, !SumAfter, Disjs0, Disjs).
 
 :- pred switch_annotate_coverage(coverage_reference_info::in,
-    switch_can_fail_rep::in, goal_path::in,
+    switch_can_fail_rep::in, list(goal_path_step)::in,
     coverage_before::in, coverage_after::out,
     list(case_rep(unit))::in, list(case_rep(coverage_info))::out) is det.
 
-switch_annotate_coverage(Info, CanFail, GoalPath, Before, After,
+switch_annotate_coverage(Info, CanFail, RevGoalPathSteps, Before, After,
         Cases0, Cases) :-
     trace [compile_time(flag("debug_coverage_propagation")), io(!IO)] (
         io.format("Switch: Before0: %s\n", [s(string(Before))], !IO)
     ),
 
-    switch_annotate_coverage_2(Info, CanFail, GoalPath, 1,
+    switch_annotate_coverage_2(Info, CanFail, RevGoalPathSteps, 1,
         sum_before_zero, _SumBefore, sum_after_zero, SumAfter,
         Before, Cases0, Cases),
     % For can_fail switches, the sum of the exec counts at the starts of the
@@ -536,7 +546,7 @@
         )
     ).
 
-    % switch_annotate_coverage_2(Info, Detism, GoalPath, CaseNum,
+    % switch_annotate_coverage_2(Info, Detism, RevGoalPathSteps, CaseNum,
     %   !CoverageSum, CoverageBeforeSwitch, !Cases),
     %
     % Perform coverage annotation on cases from the left to the right.
@@ -550,17 +560,17 @@
     % each of the other goals.
     %
 :- pred switch_annotate_coverage_2(coverage_reference_info::in,
-    switch_can_fail_rep::in, goal_path::in, int::in,
+    switch_can_fail_rep::in, list(goal_path_step)::in, int::in,
     sum_coverage_before::in, sum_coverage_before::out,
     sum_coverage_after::in, sum_coverage_after::out,
     coverage_before::in,
     list(case_rep(unit))::in, list(case_rep(coverage_info))::out) is det.
 
 switch_annotate_coverage_2(_, _, _, _, !SumBefore, !SumAfter, _, [], []).
-switch_annotate_coverage_2(Info, CanFail, GoalPath, CaseNum,
+switch_annotate_coverage_2(Info, CanFail, RevGoalPathSteps, CaseNum,
         !SumBefore, !SumAfter, SwitchBefore,
         [Case0 | Cases0], [Case | Cases]) :-
-    CaseGoalPath = goal_path_add_at_end(GoalPath, step_switch(CaseNum, no)),
+    RevSubGoalPathSteps = [step_switch(CaseNum, no) | RevGoalPathSteps],
 
     % If this is the last case in the switch, then its coverage information
     % may be computed from the coverage of other cases and the coverage of the
@@ -588,12 +598,12 @@
         BeforeCase = before_coverage(SwitchBeforeExecCount - SumBeforeExecCount)
     ;
         % Search for a coverage point for this case.
-        get_branch_start_coverage(Info, CaseGoalPath, BeforeCase)
+        get_branch_start_coverage(Info, rgp(RevSubGoalPathSteps), BeforeCase)
     ),
 
     % Calculate and annotate the coverage for the case itself.
     Case0 = case_rep(ConsID, OtherConsIDs, Goal0),
-    goal_annotate_coverage(Info, CaseGoalPath,
+    goal_annotate_coverage(Info, RevSubGoalPathSteps,
         BeforeCase, AfterCase, Goal0, Goal),
     Case = case_rep(ConsID, OtherConsIDs, Goal),
 
@@ -601,27 +611,27 @@
     sum_before_coverage(BeforeCase, !SumBefore),
     sum_after_coverage(AfterCase, !SumAfter),
 
-    switch_annotate_coverage_2(Info, CanFail, GoalPath, CaseNum + 1,
+    switch_annotate_coverage_2(Info, CanFail, RevGoalPathSteps, CaseNum + 1,
         !SumBefore, !SumAfter, SwitchBefore, Cases0, Cases).
 
     % Propagate coverage information for if-then-else goals.
     %
-:- pred ite_annotate_coverage(coverage_reference_info::in, goal_path::in,
-    coverage_before::in, coverage_after::out,
+:- pred ite_annotate_coverage(coverage_reference_info::in,
+    list(goal_path_step)::in, coverage_before::in, coverage_after::out,
     goal_rep::in, goal_rep(coverage_info)::out,
     goal_rep::in, goal_rep(coverage_info)::out,
     goal_rep::in, goal_rep(coverage_info)::out) is det.
 
-ite_annotate_coverage(Info, GoalPath, Before, After,
+ite_annotate_coverage(Info, RevGoalPathSteps, Before, After,
         Cond0, Cond, Then0, Then, Else0, Else) :-
-    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),
+    RevCondGoalPathSteps = [step_ite_cond | RevGoalPathSteps],
+    RevThenGoalPathSteps = [step_ite_then | RevGoalPathSteps],
+    RevElseGoalPathSteps = [step_ite_else | RevGoalPathSteps],
     CondDetism = Cond0 ^ goal_detism_rep,
 
     % Step 1:
     %   Call goal_annotate_coverage for the condition goal.
-    goal_annotate_coverage(Info, CondGoalPath,
+    goal_annotate_coverage(Info, RevCondGoalPathSteps,
         Before, AfterCond, Cond0, Cond),
     after_to_before_coverage(AfterCond, BeforeThen0),
 
@@ -634,7 +644,7 @@
         BeforeThen = BeforeThen0
     ;
         BeforeThen0 = before_unknown,
-        get_branch_start_coverage(Info, ThenGoalPath, BeforeThen)
+        get_branch_start_coverage(Info, rgp(RevThenGoalPathSteps), BeforeThen)
     ),
     % XXX It should be possible, if the condition is not at_most_many and does
     % not throw exceptions, to compute BeforeElse as the difference between the
@@ -642,21 +652,21 @@
     % check_ite_coverage already knows the relationship.  Using exception
     % counts on call goals and propagating them through the coverage annotation
     % algorithms can solve this.
-    get_branch_start_coverage(Info, ElseGoalPath, BeforeElse),
+    get_branch_start_coverage(Info, rgp(RevElseGoalPathSteps), BeforeElse),
 
     trace [compile_time(flag("debug_coverage_propagation")), io(!IO)] (
         io.format("ITE Coverage inferred before then and else branches:\n" ++
             "\tWhole: %s \n\tThen: %s\n\tElse: %s\n" ++
             "\tGoalPath %s\n",
             [s(string(Before)), s(string(BeforeThen)), s(string(BeforeElse)),
-            s(goal_path_to_string(GoalPath))], !IO)
+            s(rev_goal_path_to_string(rgp(RevGoalPathSteps)))], !IO)
     ),
 
     % Step 3:
     %   Call goal_annotate_coverage for the then and else goals.
-    goal_annotate_coverage(Info, ThenGoalPath,
+    goal_annotate_coverage(Info, RevThenGoalPathSteps,
         BeforeThen, AfterThen, Then0, Then),
-    goal_annotate_coverage(Info, ElseGoalPath,
+    goal_annotate_coverage(Info, RevElseGoalPathSteps,
         BeforeElse, AfterElse, Else0, Else),
 
     % Step 4:
@@ -705,32 +715,32 @@
                 s(string(Before)), s(string(AfterCond)),
                 s(string(BeforeThen)), s(string(AfterThen)),
                 s(string(BeforeElse)), s(string(AfterElse)),
-                s(goal_path_to_string(GoalPath))]))
+                s(rev_goal_path_to_string(rgp(RevGoalPathSteps)))]))
         )
     ).
 
     % Get the coverage information from a coverage point about the branch
     % referenced by the given goal path.
     %
-:- pred get_branch_start_coverage(coverage_reference_info::in, goal_path::in,
-    coverage_before::out) is det.
+:- pred get_branch_start_coverage(coverage_reference_info::in,
+    reverse_goal_path::in, coverage_before::out) is det.
 
-get_branch_start_coverage(Info, GoalPath, Before) :-
-    ( map.search(Info ^ cri_branch_coverage_points, GoalPath, CP) ->
+get_branch_start_coverage(Info, RevGoalPath, Before) :-
+    ( map.search(Info ^ cri_branch_coverage_points, RevGoalPath, CP) ->
         CP = coverage_point(ExecCount, _, _),
         Before = before_coverage(ExecCount)
     ;
         Before = before_unknown
     ).
 
-:- pred negation_annotate_coverage(coverage_reference_info::in, goal_path::in,
-    coverage_before::in, coverage_after::out,
+:- pred negation_annotate_coverage(coverage_reference_info::in,
+    list(goal_path_step)::in, coverage_before::in, coverage_after::out,
     goal_rep::in, goal_rep(coverage_info)::out) is det.
 
-negation_annotate_coverage(Info, GoalPath, Before, After,
+negation_annotate_coverage(Info, RevGoalPathSteps, Before, After,
         NegGoal0, NegGoal) :-
-    NegGoalPath = goal_path_add_at_end(GoalPath, step_neg),
-    goal_annotate_coverage(Info, NegGoalPath,
+    RevSubGoalPathSteps = [step_neg | RevGoalPathSteps],
+    goal_annotate_coverage(Info, RevSubGoalPathSteps,
         Before, _CoverageAfter, NegGoal0, NegGoal),
     % The coverage after a negation is always unknown.
     After = after_unknown,
@@ -740,13 +750,14 @@
     ).
 
 :- pred scope_annotate_coverage(coverage_reference_info::in,
-    goal_path::in, maybe_cut::in, coverage_before::in, coverage_after::out,
+    list(goal_path_step)::in, maybe_cut::in,
+    coverage_before::in, coverage_after::out,
     goal_rep::in, goal_rep(coverage_info)::out) is det.
 
-scope_annotate_coverage(Info, GoalPath, MaybeCut, Before, After,
+scope_annotate_coverage(Info, RevGoalPathSteps, MaybeCut, Before, After,
         ScopedGoal0, ScopedGoal) :-
-    ScopeGoalPath = goal_path_add_at_end(GoalPath, step_scope(MaybeCut)),
-    goal_annotate_coverage(Info, ScopeGoalPath,
+    RevSubGoalPathSteps = [step_scope(MaybeCut) | RevGoalPathSteps],
+    goal_annotate_coverage(Info, RevSubGoalPathSteps,
         Before, AfterScopedGoal, ScopedGoal0, ScopedGoal),
     (
         MaybeCut = scope_is_cut,
Index: deep_profiler/create_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/create_report.m,v
retrieving revision 1.29
diff -u -r1.29 create_report.m
--- deep_profiler/create_report.m	15 Dec 2010 06:30:33 -0000	1.29
+++ deep_profiler/create_report.m	17 Dec 2010 03:03:02 -0000
@@ -1152,7 +1152,7 @@
 
 :- pred maybe_create_procrep_coverage_report(deep::in, proc_static_ptr::in,
     own_prof_info::in, maybe(array(int))::in,
-    map(goal_path, calls_and_exits)::in,
+    map(reverse_goal_path, calls_and_exits)::in,
     maybe_error(procrep_coverage_info)::out) is det.
 
 maybe_create_procrep_coverage_report(_, _, _, no, _, error(Error)) :-
@@ -1186,18 +1186,20 @@
     ).
 
 :- func add_ps_calls_and_exits_to_map(deep, call_site_static_ptr,
-    map(goal_path, calls_and_exits)) = map(goal_path, calls_and_exits).
+    map(reverse_goal_path, calls_and_exits)) =
+    map(reverse_goal_path, calls_and_exits).
 
 add_ps_calls_and_exits_to_map(Deep, CSSPtr, !.Map) = !:Map :-
     lookup_call_site_statics(Deep ^ call_site_statics, CSSPtr, CSS),
-    goal_path_from_string_det(CSS ^ css_goal_path, GoalPath),
+    rev_goal_path_from_string_det(CSS ^ css_goal_path, RevGoalPath),
     lookup_css_own(Deep ^ css_own, CSSPtr, Own),
-    svmap.det_insert(GoalPath, calls_and_exits(calls(Own), exits(Own)), !Map).
+    svmap.det_insert(RevGoalPath, calls_and_exits(calls(Own), exits(Own)),
+        !Map).
 
 :- pred add_pd_calls_and_exits_to_map(deep::in, call_site_static_ptr::in,
     call_site_array_slot::in,
-    map(goal_path, calls_and_exits)::in, map(goal_path, calls_and_exits)::out)
-    is det.
+    map(reverse_goal_path, calls_and_exits)::in,
+    map(reverse_goal_path, calls_and_exits)::out) is det.
 
 add_pd_calls_and_exits_to_map(Deep, CSSPtr, Slot, !Map) :-
     (
@@ -1209,8 +1211,8 @@
             0, Calls, 0, Exits)
     ),
     deep_lookup_call_site_statics(Deep, CSSPtr, CSS),
-    goal_path_from_string_det(CSS ^ css_goal_path, GoalPath),
-    svmap.det_insert(GoalPath, calls_and_exits(Calls, Exits), !Map).
+    rev_goal_path_from_string_det(CSS ^ css_goal_path, RevGoalPath),
+    svmap.det_insert(RevGoalPath, calls_and_exits(Calls, Exits), !Map).
 
 :- pred csd_get_calls_and_exits(deep::in, call_site_dynamic_ptr::in,
     int::out, int::out) is det.
@@ -1235,9 +1237,10 @@
     csd_get_calls_and_exits(Deep, CSDPtr, NewCalls, NewExits).
 
 :- pred add_coverage_point_to_map(coverage_point::in,
-    map(goal_path, coverage_point)::in, map(goal_path, coverage_point)::out,
-    map(goal_path, coverage_point)::in, map(goal_path, coverage_point)::out)
-    is det.
+    map(reverse_goal_path, coverage_point)::in,
+    map(reverse_goal_path, coverage_point)::out,
+    map(reverse_goal_path, coverage_point)::in,
+    map(reverse_goal_path, coverage_point)::out) is det.
 
 add_coverage_point_to_map(CoveragePoint, !SolnsMap, !BranchMap) :-
     CoveragePoint = coverage_point(_, GoalPath, CPType),
@@ -1650,7 +1653,7 @@
         ModuleName = ContainingPS ^ ps_decl_module,
         UnQualRefinedName = ContainingPS ^ ps_uq_refined_id,
         QualRefinedName = ContainingPS ^ ps_q_refined_id,
-        goal_path_from_string_det(GoalPathString, GoalPath),
+        rev_goal_path_from_string_det(GoalPathString, RevGoalPath),
         (
             Kind = normal_call_and_callee(CalleePSPtr, _TypeSubst),
             CalleeDesc = describe_proc(Deep, CalleePSPtr),
@@ -1671,12 +1674,12 @@
         UnQualRefinedName = "mercury_runtime",
         QualRefinedName = "mercury_runtime",
         SlotNumber = -1,
-        GoalPath = empty_goal_path,
+        RevGoalPath = rgp([]),
         MaybeCalleeDesc = no
     ),
     CallSiteDesc = call_site_desc(CSSPtr, ContainingPSPtr,
         FileName, LineNumber, ModuleName, UnQualRefinedName, QualRefinedName,
-        SlotNumber, GoalPath, MaybeCalleeDesc).
+        SlotNumber, RevGoalPath, MaybeCalleeDesc).
 
     % describe_clique(Deep, CliquePtr, MaybeEntryPDPtr) = CliqueDesc
     %
Index: deep_profiler/display_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/display_report.m,v
retrieving revision 1.32
diff -u -r1.32 display_report.m
--- deep_profiler/display_report.m	15 Dec 2010 06:30:33 -0000	1.32
+++ deep_profiler/display_report.m	17 Dec 2010 03:03:39 -0000
@@ -2212,8 +2212,8 @@
 :- pred format_coverage_point_row(coverage_point::in, table_row::out) is det.
 
 format_coverage_point_row(CoveragePoint, Row) :-
-    CoveragePoint = coverage_point(Count, GoalPath, CPType),
-    GoalPathString = goal_path_to_string(GoalPath),
+    CoveragePoint = coverage_point(Count, RevGoalPath, CPType),
+    GoalPathString = rev_goal_path_to_string(RevGoalPath),
     GoalPathCell = table_cell(td_s(GoalPathString)),
     TypeCell = table_cell(td_s(string(CPType))),
     CountCell = table_cell(td_i(Count)),
@@ -4272,10 +4272,10 @@
     CallSiteDesc = call_site_desc(CSSPtr, _ContainerPSPtr,
         _FileName, _LineNumber, _ModuleName,
         _UnQualRefinedName, _QualRefinedName,
-        SlotNumber, GoalPath, _MaybeCallee),
+        SlotNumber, RevGoalPath, _MaybeCallee),
     RefinedName = call_site_desc_get_caller_refined_id(MaybeCurModuleName,
         ModuleQual, CallSiteDesc),
-    GoalPathStr = goal_path_to_string(GoalPath),
+    GoalPathStr = rev_goal_path_to_string(RevGoalPath),
     string.format("%s @ %s #%d",
         [s(RefinedName), s(GoalPathStr), i(SlotNumber)], Name),
     Cmd = deep_cmd_dump_call_site_static(CSSPtr),
Index: deep_profiler/dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/dump.m,v
retrieving revision 1.20
diff -u -r1.20 dump.m
--- deep_profiler/dump.m	15 Dec 2010 06:30:33 -0000	1.20
+++ deep_profiler/dump.m	17 Dec 2010 02:42:32 -0000
@@ -620,8 +620,8 @@
 
 :- pred format_cp_info(int::in, coverage_point_info::in, string::out) is det.
 
-format_cp_info(Num, coverage_point_info(Path, CPType), String) :-
-    goal_path_to_string(Path) = PathString,
+format_cp_info(Num, coverage_point_info(RevPath, CPType), String) :-
+    rev_goal_path_to_string(RevPath) = PathString,
     format("coverage_point[%d]: %s, %s",
         [i(Num), s(string(CPType)), s(PathString)], String).
 
Index: deep_profiler/mdprof_fb.automatic_parallelism.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_fb.automatic_parallelism.m,v
retrieving revision 1.22
diff -u -r1.22 mdprof_fb.automatic_parallelism.m
--- deep_profiler/mdprof_fb.automatic_parallelism.m	15 Dec 2010 06:30:33 -0000	1.22
+++ deep_profiler/mdprof_fb.automatic_parallelism.m	17 Dec 2010 04:04:22 -0000
@@ -183,8 +183,8 @@
                 ipi_progrep         :: prog_rep,
                 ipi_opts            :: candidate_par_conjunctions_params,
                 ipi_clique          :: clique_ptr,
-                ipi_call_sites      :: map(goal_path, cost_and_callees),
-                ipi_rec_call_sites  :: map(goal_path, cs_cost_csq),
+                ipi_call_sites      :: map(reverse_goal_path, cost_and_callees),
+                ipi_rec_call_sites  :: map(reverse_goal_path, cs_cost_csq),
                 ipi_recursion_type  :: recursion_type,
                 ipi_var_table       :: var_table,
                 ipi_proc_label      :: string_proc_label
@@ -207,7 +207,7 @@
                 pgd_inst_map_info           :: inst_map_info,
 
                 % The original goal path of this goal.
-                pgd_original_path           :: goal_path,
+                pgd_original_path           :: reverse_goal_path,
 
                 % Coverage data for this goal.
                 pgd_coverage                :: coverage_info,
@@ -328,7 +328,7 @@
 
                 % The context of the call site that calls this clique.
                 ccc_proc                :: string_proc_label,
-                ccc_goal_path           :: goal_path,
+                ccc_goal_path           :: reverse_goal_path,
 
                 % The amount of parallelism already used during the call due to
                 % parallelisations in the parents.
@@ -355,24 +355,25 @@
 
 pd_slot_callees(Deep, Parallelism, ProcLabel, CSSPtr - Slot, ChildCliques) :-
     deep_lookup_call_site_statics(Deep, CSSPtr, CSS),
-    goal_path_from_string_det(CSS ^ css_goal_path, GoalPath),
+    rev_goal_path_from_string_det(CSS ^ css_goal_path, RevGoalPath),
     (
         Slot = slot_normal(CSDPtr),
-        call_site_dynamic_callees(Deep, Parallelism, ProcLabel, GoalPath,
+        call_site_dynamic_callees(Deep, Parallelism, ProcLabel, RevGoalPath,
             CSDPtr, ChildCliques)
     ;
         Slot = slot_multi(_, CSDPtrs),
         list.map(
-            call_site_dynamic_callees(Deep, Parallelism, ProcLabel, GoalPath),
+            call_site_dynamic_callees(Deep, Parallelism, ProcLabel,
+                RevGoalPath),
             to_list(CSDPtrs), ChildCliqueCords),
         ChildCliques = cord_list_to_cord(ChildCliqueCords)
     ).
 
 :- pred call_site_dynamic_callees(deep::in, parallelism_amount::in,
-    string_proc_label::in, goal_path::in, call_site_dynamic_ptr::in,
+    string_proc_label::in, reverse_goal_path::in, call_site_dynamic_ptr::in,
     cord(candidate_child_clique)::out) is det.
 
-call_site_dynamic_callees(Deep, Parallelism, ProcLabel, GoalPath, CSDPtr,
+call_site_dynamic_callees(Deep, Parallelism, ProcLabel, RevGoalPath, CSDPtr,
         ChildCliques) :-
     ( valid_call_site_dynamic_ptr(Deep, CSDPtr) ->
         deep_lookup_clique_maybe_child(Deep, CSDPtr, MaybeClique),
@@ -383,7 +384,7 @@
             Cost = build_cs_cost_csq(calls(Own),
                 float(callseqs(Own) + inherit_callseqs(Desc))),
             ChildCliques = singleton(
-                candidate_child_clique(CliquePtr, Cost, ProcLabel, GoalPath,
+                candidate_child_clique(CliquePtr, Cost, ProcLabel, RevGoalPath,
                     Parallelism))
         ;
             MaybeClique = no,
@@ -471,8 +472,8 @@
     candidate_child_clique::in, candidate_child_clique::out) is det.
 
 update_parallelism_available_conj(Conj, !ChildClique) :-
-    GoalPath = !.ChildClique ^ ccc_goal_path,
-    goal_path_from_string_det(Conj ^ cpc_goal_path, ConjGoalPath),
+    RevGoalPath = !.ChildClique ^ ccc_goal_path,
+    rev_goal_path_from_string_det(Conj ^ cpc_goal_path, RevConjGoalPath),
     % XXX: This needs revisiting if we allow parallelised conjuncts to be
     % re-ordered.
     FirstConjunct = Conj ^ cpc_first_conj_num +
@@ -480,10 +481,12 @@
     Length = list.foldl((func(seq_conj(ConjsI), Acc) = Acc + length(ConjsI)),
         Conj ^ cpc_conjs, 0),
     (
-        GoalPath \= ConjGoalPath,
-        goal_path_inside(ConjGoalPath, GoalPath, RelativePath),
-        goal_path_consable(RelativePath, RelativePathCons),
-        goal_path_consable_remove_first(RelativePathCons, Step, _),
+        % XXX zs: I am not confident of the update for goal path
+        % representations.
+        RevGoalPath \= RevConjGoalPath,
+        rev_goal_path_inside(RevConjGoalPath, RevGoalPath, RevRelativePath),
+        RevRelativePath = rgp(RevRelativePathSteps),
+        list.last(RevRelativePathSteps, Step),
         Step = step_conj(ConjNum),
         ConjNum > FirstConjunct,
         ConjNum =< FirstConjunct + Length
@@ -535,7 +538,7 @@
             MaybeRecursiveCallSiteCostMap = ok(RecursiveCallSiteCostMap)
         ;
             MaybeRecursiveCallSiteCostMap = error(Error),
-            append_message(clique(CliquePtr),
+            append_message(pl_clique(CliquePtr),
                 warning_cannot_compute_cost_of_recursive_calls(Error),
                 !Messages),
             RecursiveCallSiteCostMap = map.init
@@ -573,7 +576,7 @@
     %
 :- pred candidate_parallel_conjunctions_proc(
     candidate_par_conjunctions_params::in, deep::in, proc_dynamic_ptr::in,
-    recursion_type::in, map(goal_path, cs_cost_csq)::in,
+    recursion_type::in, map(reverse_goal_path, cs_cost_csq)::in,
     candidate_par_conjunctions::out, cord(message)::out) is det.
 
 candidate_parallel_conjunctions_proc(Opts, Deep, PDPtr, RecursionType,
@@ -621,9 +624,9 @@
                     goal_annotate_with_instmap(!Goal,
                         initial_inst_map(ProcDefnRep), _FinalInstMap,
                         SeenDuplicateInstantiation, _ConsumedVars, _BoundVars),
-                    goal_to_pard_goal(Info, empty_goal_path, !Goal, !Messages),
+                    goal_to_pard_goal(Info, [], !Goal, !Messages),
                     goal_get_conjunctions_worth_parallelising(Info,
-                        empty_goal_path, !.Goal, _, Candidates0, MessagesA),
+                        [], !.Goal, _, Candidates0, MessagesA),
                     !:Messages = !.Messages ++ MessagesA
                 ),
                 (
@@ -636,14 +639,14 @@
                 ;
                     SeenDuplicateInstantiation = seen_duplicate_instantiation,
                     Candidates = map.init,
-                    append_message(proc(ProcLabel),
+                    append_message(pl_proc(ProcLabel),
                         notice_duplicate_instantiation(length(Candidates0)),
                         !Messages)
                 )
             ;
                 MaybeCoverageReport = error(Error),
                 Candidates = map.init,
-                append_message(proc(ProcLabel),
+                append_message(pl_proc(ProcLabel),
                     error_coverage_procrep_error(Error), !Messages)
             )
         ),
@@ -683,13 +686,13 @@
     svmap.set(ProcLabel, CandidateProc, !Map).
 
 :- pred goal_get_conjunctions_worth_parallelising(
-    implicit_parallelism_info::in, goal_path::in,
+    implicit_parallelism_info::in, list(goal_path_step)::in,
     pard_goal_detail::in, pard_goal_detail::out,
     list(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::out) is det.
 
-goal_get_conjunctions_worth_parallelising(Info, GoalPath, !Goal, Candidates,
-        Messages) :-
+goal_get_conjunctions_worth_parallelising(Info, RevGoalPathSteps,
+        !Goal, Candidates, Messages) :-
     GoalExpr0 = !.Goal ^ goal_expr_rep,
     Coverage = !.Goal ^ goal_annotation ^ pgd_coverage,
     get_coverage_before_det(Coverage, Calls),
@@ -697,9 +700,10 @@
         (
             GoalExpr0 = conj_rep(Conjs0),
             list.map3_foldl(
-                conj_get_conjunctions_worth_parallelising(Info, GoalPath),
+                conj_get_conjunctions_worth_parallelising(Info,
+                    RevGoalPathSteps),
                 Conjs0, Conjs, Candidatess, Messagess, 1, _),
-            conj_build_candidate_conjunctions(Info, GoalPath, Conjs,
+            conj_build_candidate_conjunctions(Info, RevGoalPathSteps, Conjs,
                 MaybeCost, MessagesB, MaybeCandidate),
             (
                 MaybeCost = yes(Cost)
@@ -719,7 +723,8 @@
         ;
             GoalExpr0 = disj_rep(Disjs0),
             list.map3_foldl(
-                disj_get_conjunctions_worth_parallelising(Info, GoalPath),
+                disj_get_conjunctions_worth_parallelising(Info,
+                    RevGoalPathSteps),
                 Disjs0, Disjs, Candidatess, Messagess, 1, _),
             disj_calc_cost(Disjs, Calls, Cost),
             GoalExpr = disj_rep(Disjs),
@@ -729,7 +734,7 @@
             GoalExpr0 = switch_rep(Var, CanFail, Cases0),
             list.map3_foldl(
                 switch_case_get_conjunctions_worth_parallelising(Info,
-                    GoalPath),
+                    RevGoalPathSteps),
                 Cases0, Cases, Candidatess, Messagess, 1, _),
             switch_calc_cost(Cases, Calls, Cost),
             GoalExpr = switch_rep(Var, CanFail, Cases),
@@ -737,23 +742,22 @@
             Candidates = condense(Candidatess)
         ;
             GoalExpr0 = ite_rep(Cond0, Then0, Else0),
-            ite_get_conjunctions_worth_parallelising(Info, GoalPath,
+            ite_get_conjunctions_worth_parallelising(Info, RevGoalPathSteps,
                 Cond0, Cond, Then0, Then, Else0, Else, Candidates, Messages),
             ite_calc_cost(Cond, Then, Else, Cost),
             GoalExpr = ite_rep(Cond, Then, Else)
         ;
             GoalExpr0 = scope_rep(SubGoal0, MaybeCut),
-            ScopeGoalPath =
-                goal_path_add_at_end(GoalPath, step_scope(MaybeCut)),
-            goal_get_conjunctions_worth_parallelising(Info, ScopeGoalPath,
-                SubGoal0, SubGoal, Candidates, Messages),
+            RevSubGoalPathSteps = [step_scope(MaybeCut) | RevGoalPathSteps],
+            goal_get_conjunctions_worth_parallelising(Info,
+                RevSubGoalPathSteps, SubGoal0, SubGoal, Candidates, Messages),
             Cost = SubGoal ^ goal_annotation ^ pgd_cost,
             GoalExpr = scope_rep(SubGoal, MaybeCut)
         ;
             GoalExpr0 = negation_rep(SubGoal0),
-            NegGoalPath = goal_path_add_at_end(GoalPath, step_neg),
-            goal_get_conjunctions_worth_parallelising(Info, NegGoalPath,
-                SubGoal0, SubGoal, Candidates, Messages),
+            RevSubGoalPathSteps = [step_neg | RevGoalPathSteps],
+            goal_get_conjunctions_worth_parallelising(Info,
+                RevSubGoalPathSteps, SubGoal0, SubGoal, Candidates, Messages),
             Cost = SubGoal ^ goal_annotation ^ pgd_cost,
             GoalExpr = negation_rep(SubGoal)
         ),
@@ -767,66 +771,66 @@
     !Goal ^ goal_expr_rep := GoalExpr.
 
 :- pred conj_get_conjunctions_worth_parallelising(
-    implicit_parallelism_info::in, goal_path::in,
+    implicit_parallelism_info::in, list(goal_path_step)::in,
     pard_goal_detail::in, pard_goal_detail::out,
     list(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::out, int::in, int::out) is det.
 
-conj_get_conjunctions_worth_parallelising(Info, GoalPath, !Conj, Candidates,
-        Messages, !ConjNum) :-
-    ConjGoalPath = goal_path_add_at_end(GoalPath, step_conj(!.ConjNum)),
-    goal_get_conjunctions_worth_parallelising(Info, ConjGoalPath, !Conj,
-        Candidates, Messages),
+conj_get_conjunctions_worth_parallelising(Info, RevGoalPathSteps,
+        !Conj, Candidates, Messages, !ConjNum) :-
+    RevConjGoalPathSteps = [step_disj(!.ConjNum) | RevGoalPathSteps],
+    goal_get_conjunctions_worth_parallelising(Info, RevConjGoalPathSteps,
+        !Conj, Candidates, Messages),
     !:ConjNum = !.ConjNum + 1.
 
 :- pred disj_get_conjunctions_worth_parallelising(
-    implicit_parallelism_info::in, goal_path::in,
+    implicit_parallelism_info::in, list(goal_path_step)::in,
     pard_goal_detail::in, pard_goal_detail::out,
     list(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::out, int::in, int::out) is det.
 
-disj_get_conjunctions_worth_parallelising(Info, GoalPath, !Disj, Candidates,
-        Messages, !DisjNum) :-
-    DisjGoalPath = goal_path_add_at_end(GoalPath, step_disj(!.DisjNum)),
-    goal_get_conjunctions_worth_parallelising(Info, DisjGoalPath, !Disj,
-        Candidates, Messages),
+disj_get_conjunctions_worth_parallelising(Info, RevGoalPathSteps,
+        !Disj, Candidates, Messages, !DisjNum) :-
+    RevDisjGoalPathSteps = [step_disj(!.DisjNum) | RevGoalPathSteps],
+    goal_get_conjunctions_worth_parallelising(Info, RevDisjGoalPathSteps,
+        !Disj, Candidates, Messages),
     !:DisjNum = !.DisjNum + 1.
 
 :- pred switch_case_get_conjunctions_worth_parallelising(
-    implicit_parallelism_info::in, goal_path::in,
+    implicit_parallelism_info::in, list(goal_path_step)::in,
     case_rep(pard_goal_detail_annotation)::in,
     case_rep(pard_goal_detail_annotation)::out,
     list(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::out, int::in, int::out) is det.
 
-switch_case_get_conjunctions_worth_parallelising(Info, GoalPath, !Case,
+switch_case_get_conjunctions_worth_parallelising(Info, RevGoalPathSteps, !Case,
         Candidates, Messages, !CaseNum) :-
     Goal0 = !.Case ^ cr_case_goal,
-    CaseGoalPath = goal_path_add_at_end(GoalPath, step_switch(!.CaseNum, no)),
-    goal_get_conjunctions_worth_parallelising(Info, CaseGoalPath, Goal0, Goal,
-        Candidates, Messages),
+    RevCaseGoalPathSteps = [step_switch(!.CaseNum, no) | RevGoalPathSteps],
+    goal_get_conjunctions_worth_parallelising(Info, RevCaseGoalPathSteps,
+        Goal0, Goal, Candidates, Messages),
     !Case ^ cr_case_goal := Goal,
     !:CaseNum = !.CaseNum + 1.
 
 :- pred ite_get_conjunctions_worth_parallelising(
-    implicit_parallelism_info::in,  goal_path::in,
+    implicit_parallelism_info::in,  list(goal_path_step)::in,
     pard_goal_detail::in, pard_goal_detail::out,
     pard_goal_detail::in, pard_goal_detail::out,
     pard_goal_detail::in, pard_goal_detail::out,
     list(candidate_par_conjunction(pard_goal_detail))::out, cord(message)::out)
     is det.
 
-ite_get_conjunctions_worth_parallelising(Info, GoalPath, !Cond, !Then, !Else,
-        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(Info, CondGoalPath, !Cond,
-        CondCandidates, CondMessages),
-    goal_get_conjunctions_worth_parallelising(Info, ThenGoalPath, !Then,
-        ThenCandidates, ThenMessages),
-    goal_get_conjunctions_worth_parallelising(Info, ElseGoalPath, !Else,
-        ElseCandidates, ElseMessages),
+ite_get_conjunctions_worth_parallelising(Info, RevGoalPathSteps,
+        !Cond, !Then, !Else, Candidates, Messages) :-
+    RevCondGoalPathSteps = [step_ite_cond | RevGoalPathSteps],
+    RevThenGoalPathSteps = [step_ite_then | RevGoalPathSteps],
+    RevElseGoalPathSteps = [step_ite_else | RevGoalPathSteps],
+    goal_get_conjunctions_worth_parallelising(Info, RevCondGoalPathSteps,
+        !Cond, CondCandidates, CondMessages),
+    goal_get_conjunctions_worth_parallelising(Info, RevThenGoalPathSteps,
+        !Then, ThenCandidates, ThenMessages),
+    goal_get_conjunctions_worth_parallelising(Info, RevElseGoalPathSteps,
+        !Else, ElseCandidates, ElseMessages),
     Candidates = CondCandidates ++ ThenCandidates ++ ElseCandidates,
     Messages = CondMessages ++ ThenMessages ++ ElseMessages.
 
@@ -834,14 +838,13 @@
     % the list of calls we have found and make any parallelisation decisions.
     %
 :- pred conj_build_candidate_conjunctions(implicit_parallelism_info::in,
-    goal_path::in, list(pard_goal_detail)::in, maybe(goal_cost_csq)::out,
-    cord(message)::out,
+    list(goal_path_step)::in, list(pard_goal_detail)::in,
+    maybe(goal_cost_csq)::out, cord(message)::out,
     maybe(candidate_par_conjunction(pard_goal_detail))::out) is det.
 
-conj_build_candidate_conjunctions(Info, GoalPath, Conjs, MaybeCost, Messages,
-        MaybeCandidate) :-
+conj_build_candidate_conjunctions(Info, RevGoalPathSteps, Conjs, MaybeCost,
+        Messages, MaybeCandidate) :-
     ProcLabel = Info ^ ipi_proc_label,
-    Location = goal(ProcLabel, GoalPath),
     some [!Messages]
     (
         !:Messages = cord.empty,
@@ -854,12 +857,13 @@
             MaybeCost = no,
             MaybeCandidate = no
         ;
+            Location = pl_goal(ProcLabel, rgp(RevGoalPathSteps)),
             append_message(Location,
                 info_found_conjs_above_callsite_threshold(NumCostlyGoals),
                 !Messages),
 
-            pardgoals_build_candidate_conjunction(Info, Location, GoalPath,
-                Conjs, MaybeCandidate, !Messages),
+            pardgoals_build_candidate_conjunction(Info, Location,
+                RevGoalPathSteps, Conjs, MaybeCandidate, !Messages),
             (
                 MaybeCandidate = yes(Candidate),
                 append_message(Location,
@@ -894,11 +898,11 @@
     ).
 
 :- pred pardgoals_build_candidate_conjunction(implicit_parallelism_info::in,
-    program_location::in, goal_path::in, list(pard_goal_detail)::in,
+    program_location::in, list(goal_path_step)::in, list(pard_goal_detail)::in,
     maybe(candidate_par_conjunction(pard_goal_detail))::out,
     cord(message)::in, cord(message)::out) is det.
 
-pardgoals_build_candidate_conjunction(Info, Location, GoalPath, Goals,
+pardgoals_build_candidate_conjunction(Info, Location, RevGoalPathSteps, Goals,
         MaybeCandidate, !Messages) :-
     % 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
@@ -921,7 +925,8 @@
         GoalsBeforeCost = goal_cost_get_percall(GoalsBeforeCost0),
         conj_calc_cost(GoalsAfter, Calls, GoalsAfterCost0),
         GoalsAfterCost = goal_cost_get_percall(GoalsAfterCost0),
-        Candidate = candidate_par_conjunction(goal_path_to_string(GoalPath),
+        RevGoalPathString = rev_goal_path_to_string(rgp(RevGoalPathSteps)),
+        Candidate = candidate_par_conjunction(RevGoalPathString,
             FirstConjNum, IsDependent, GoalsBefore, GoalsBeforeCost, ParConjs,
             GoalsAfter, GoalsAfterCost, Metrics),
         (
@@ -935,19 +940,21 @@
             MaybeCandidate = yes(Candidate)
         ;
             MaybeCandidate = no,
-            trace [compile_time(flag("debug_parallel_conjunction_speedup")),
-                    io(!IO)]
+            trace [
+                compile_time(flag("debug_parallel_conjunction_speedup")),
+                io(!IO)
+            ]
             (
                 (
-                    ( Location = proc(ProcLabel)
-                    ; Location = goal(ProcLabel, _)
+                    ( Location = pl_proc(ProcLabel)
+                    ; Location = pl_goal(ProcLabel, _)
                     )
                 ;
-                    ( Location = clique(_)
-                    ; Location = call_site_dynamic(_)
+                    ( Location = pl_clique(_)
+                    ; Location = pl_csd(_)
                     ),
-                    error("Location is a clique or CSD when it should be a "
-                        ++ "proc or goal")
+                    unexpected($module, $pred, "Location is a clique or CSD "
+                        ++ "when it should be a proc or a goal")
                 ),
 
                 convert_candidate_par_conjunction(
@@ -2331,12 +2338,12 @@
     PercallCost = goal_cost_get_percall(Cost),
     PercallCost > float(Info ^ ipi_opts ^ cpcp_call_site_threshold).
 
-:- pred atomic_pard_goal_type(implicit_parallelism_info::in, goal_path::in,
-    atomic_goal_rep::in, inst_map_info::in, pard_goal_type::out,
-    cord(message)::out) is det.
+:- pred atomic_pard_goal_type(implicit_parallelism_info::in,
+    list(goal_path_step)::in, atomic_goal_rep::in, inst_map_info::in,
+    pard_goal_type::out, cord(message)::out) is det.
 
-atomic_pard_goal_type(Info, GoalPath, AtomicGoal, InstMapInfo, GoalType,
-        !:Messages) :-
+atomic_pard_goal_type(Info, RevGoalPathSteps, AtomicGoal, InstMapInfo,
+        GoalType, !:Messages) :-
     !:Messages = cord.empty,
     InstMapBefore = InstMapInfo ^ im_before,
     InstMapAfter = InstMapInfo ^ im_after,
@@ -2347,16 +2354,17 @@
     ;
         IsCall = atomic_goal_is_call(Args),
         % Lookup var use information.
-        map.lookup(Info ^ ipi_call_sites, GoalPath, CallSite),
+        map.lookup(Info ^ ipi_call_sites, rgp(RevGoalPathSteps), CallSite),
         map_foldl(compute_var_modes(InstMapBefore, InstMapAfter),
             Args, VarsAndModes, 0, _),
         GoalType = pgt_call(VarsAndModes, CallSite)
     ).
 
-:- pred atomic_pard_goal_cost(implicit_parallelism_info::in, goal_path::in,
-    coverage_info::in, atomic_goal_rep::in, goal_cost_csq::out) is det.
+:- pred atomic_pard_goal_cost(implicit_parallelism_info::in,
+    list(goal_path_step)::in, coverage_info::in, atomic_goal_rep::in,
+    goal_cost_csq::out) is det.
 
-atomic_pard_goal_cost(Info, GoalPath, Coverage, AtomicGoal, Cost) :-
+atomic_pard_goal_cost(Info, RevGoalPathSteps, Coverage, AtomicGoal, Cost) :-
     atomic_goal_is_call(AtomicGoal, IsCall),
     (
         IsCall = atomic_goal_is_trivial,
@@ -2364,10 +2372,11 @@
         Cost = atomic_goal_cost(Calls)
     ;
         IsCall = atomic_goal_is_call(_),
-        map.lookup(Info ^ ipi_call_sites, GoalPath, CallSite),
+        RevGoalPath = rgp(RevGoalPathSteps),
+        map.lookup(Info ^ ipi_call_sites, RevGoalPath, CallSite),
         (
             cost_and_callees_is_recursive(Info ^ ipi_clique, CallSite),
-            map.search(Info ^ ipi_rec_call_sites, GoalPath, RecCost)
+            map.search(Info ^ ipi_rec_call_sites, RevGoalPath, RecCost)
         ->
             CSCost = RecCost
         ;
@@ -2384,12 +2393,13 @@
     VarAndMode = var_and_mode(Arg, Mode),
     !:ArgNum = !.ArgNum + 1.
 
-:- pred atomic_goal_build_use_map(atomic_goal_rep::in, goal_path::in,
-    implicit_parallelism_info::in, var_use_type::in, var_rep::in,
+:- pred atomic_goal_build_use_map(atomic_goal_rep::in,
+    list(goal_path_step)::in, implicit_parallelism_info::in,
+    var_use_type::in, var_rep::in,
     map(var_rep, lazy(var_use_info))::in,
     map(var_rep, lazy(var_use_info))::out) is det.
 
-atomic_goal_build_use_map(AtomicGoal, GoalPath, Info, VarUseType, Var,
+atomic_goal_build_use_map(AtomicGoal, RevGoalPathSteps, Info, VarUseType, Var,
         !Map) :-
     atomic_goal_is_call(AtomicGoal, IsCall),
     (
@@ -2406,27 +2416,30 @@
         LazyUse = val(var_use_info(CostUntilUse, 1.0, VarUseType))
     ;
         IsCall = atomic_goal_is_call(Args),
-        LazyUse = delay((func) = compute_var_use_lazy(Info, GoalPath, Var,
-            Args, VarUseType))
+        LazyUse = delay(
+            (func) = compute_var_use_lazy(Info, RevGoalPathSteps, Var,
+                Args, VarUseType))
     ),
     svmap.det_insert(Var, LazyUse, !Map).
 
-:- func compute_var_use_lazy(implicit_parallelism_info, goal_path,
+:- func compute_var_use_lazy(implicit_parallelism_info, list(goal_path_step),
     var_rep, list(var_rep), var_use_type) = var_use_info.
 
-compute_var_use_lazy(Info, GoalPath, Var, Args, VarUseType) = Use :-
+compute_var_use_lazy(Info, RevGoalPathSteps, Var, Args, VarUseType) = Use :-
     CliquePtr = Info ^ ipi_clique,
-    map.lookup(Info ^ ipi_call_sites, GoalPath, CostAndCallee),
+    RevGoalPath = rgp(RevGoalPathSteps),
+    map.lookup(Info ^ ipi_call_sites, RevGoalPath, CostAndCallee),
     (
         cost_and_callees_is_recursive(CliquePtr, CostAndCallee),
-        map.search(Info ^ ipi_rec_call_sites, GoalPath, RecCost)
+        map.search(Info ^ ipi_rec_call_sites, RevGoalPath, RecCost)
     ->
         Cost = RecCost
     ;
         Cost = CostAndCallee ^ cac_cost
     ),
 
-    solutions(compute_var_use_lazy_arg(Info, Var, Args, CostAndCallee,
+    solutions(
+        compute_var_use_lazy_arg(Info, Var, Args, CostAndCallee,
             Cost, VarUseType),
         Uses),
     (
@@ -2525,27 +2538,28 @@
     ;
         MaybeUse = error(Error),
         pessimistic_var_use_info(VarUseType, Cost, Use),
-        append_message(call_site_dynamic(CSDPtr),
+        append_message(pl_csd(CSDPtr),
             warning_cannot_compute_first_use_time(Error),
             !Messages)
     ).
 
 :- pred goal_build_use_map(goal_rep(coverage_and_instmap_info)::in,
-    goal_path::in, goal_cost_csq::in, implicit_parallelism_info::in,
+    list(goal_path_step)::in, goal_cost_csq::in, implicit_parallelism_info::in,
     var_use_type::in, var_rep::in,
     map(var_rep, lazy(var_use_info))::in,
     map(var_rep, lazy(var_use_info))::out) is det.
 
-goal_build_use_map(Goal, GoalPath, Cost, Info, VarUseType, Var, !Map) :-
-    LazyUse = delay((func) = compute_goal_var_use_lazy(Goal, GoalPath, Cost,
-        Info, VarUseType, Var)),
+goal_build_use_map(Goal, RevGoalPathSteps, Cost, Info, VarUseType, Var, !Map) :-
+    LazyUse = delay((func) = compute_goal_var_use_lazy(Goal, RevGoalPathSteps,
+        Cost, Info, VarUseType, Var)),
     svmap.det_insert(Var, LazyUse, !Map).
 
 :- func compute_goal_var_use_lazy(goal_rep(coverage_and_instmap_info),
-    goal_path, goal_cost_csq, implicit_parallelism_info, var_use_type,
-    var_rep) = var_use_info.
+    list(goal_path_step), goal_cost_csq, implicit_parallelism_info,
+    var_use_type, var_rep) = var_use_info.
 
-compute_goal_var_use_lazy(Goal, GoalPath, Cost, Info, VarUseType, Var) = Use :-
+compute_goal_var_use_lazy(Goal, RevGoalPathSteps, Cost, Info, VarUseType, Var)
+        = Use :-
     Info = implicit_parallelism_info(Deep, _ProgRep, _Params, CliquePtr,
         CallSiteMap, RecursiveCallSiteMap, RecursionType, _VarTable,
         _ProcLabel),
@@ -2560,8 +2574,8 @@
         VarUseOptions = var_use_options(Deep, FollowCallsAcrossModules,
             VarUseType),
         var_first_use(CliquePtr, CallSiteMap, RecursiveCallSiteMap,
-            RecursionType, RecDepth, Goal, GoalPath, CostPercall, Var,
-            VarUseOptions, Use)
+            RecursionType, RecDepth, Goal, rgp(RevGoalPathSteps),
+            CostPercall, Var, VarUseOptions, Use)
     ;
         ( RecursionType = rt_divide_and_conquer(_, _)
         ; RecursionType = rt_mutual_recursion(_)
@@ -2570,8 +2584,9 @@
         ),
         % var_first_use doesn't work for these recursion types.
         pessimistic_var_use_info(VarUseType, CostPercall, Use),
-        append_message(clique(CliquePtr), warning_cannot_compute_first_use_time(
-            "Recursion type unknown for var_first_use/12"),
+        append_message(pl_clique(CliquePtr),
+            warning_cannot_compute_first_use_time(
+                "Recursion type unknown for var_first_use/12"),
             empty, Messages),
         trace [io(!IO)] (
             io.stderr_stream(Stderr, !IO),
@@ -2580,8 +2595,8 @@
     ).
 
 :- instance goal_annotation_with_coverage(coverage_and_instmap_info) where [
-        (get_coverage(Goal) = Goal ^ goal_annotation ^ cai_coverage)
-    ].
+    (get_coverage(Goal) = Goal ^ goal_annotation ^ cai_coverage)
+].
 
 :- pred implicit_par_info_intermodule_var_use(implicit_parallelism_info::in,
     intermodule_var_use::out) is det.
@@ -2666,11 +2681,11 @@
 
     % Transform a goal in a conjunction into a pard_goal.
     %
-:- pred goal_to_pard_goal(implicit_parallelism_info::in, goal_path::in,
-    goal_rep(coverage_and_instmap_info)::in, pard_goal_detail::out,
-    cord(message)::in, cord(message)::out) is det.
+:- pred goal_to_pard_goal(implicit_parallelism_info::in,
+    list(goal_path_step)::in, goal_rep(coverage_and_instmap_info)::in,
+    pard_goal_detail::out, cord(message)::in, cord(message)::out) is det.
 
-goal_to_pard_goal(Info, GoalPath, !Goal, !Messages) :-
+goal_to_pard_goal(Info, RevGoalPathSteps, !Goal, !Messages) :-
     !.Goal = goal_rep(GoalExpr0, Detism, CoverageAndInstMapInfo),
     InstMapInfo = CoverageAndInstMapInfo ^ cai_inst_map_info,
     Coverage = CoverageAndInstMapInfo ^ cai_coverage,
@@ -2678,45 +2693,41 @@
     (
         (
             GoalExpr0 = conj_rep(Conjs0),
-            list.map_foldl2(conj_to_pard_goals(Info, GoalPath), Conjs0, Conjs,
-                1, _, !Messages),
+            list.map_foldl2(conj_to_pard_goals(Info, RevGoalPathSteps),
+                Conjs0, Conjs, 1, _, !Messages),
             conj_calc_cost(Conjs, Before, Cost),
             GoalExpr = conj_rep(Conjs)
         ;
             GoalExpr0 = disj_rep(Disjs0),
-            list.map_foldl2(disj_to_pard_goals(Info, GoalPath), Disjs0, Disjs,
-                1, _, !Messages),
+            list.map_foldl2(disj_to_pard_goals(Info, RevGoalPathSteps),
+                Disjs0, Disjs, 1, _, !Messages),
             disj_calc_cost(Disjs, Before, Cost),
             GoalExpr = disj_rep(Disjs)
         ;
             GoalExpr0 = switch_rep(Var, CanFail, Cases0),
-            list.map_foldl2(case_to_pard_goal(Info, GoalPath), Cases0, Cases,
-                1, _, !Messages),
+            list.map_foldl2(case_to_pard_goal(Info, RevGoalPathSteps),
+                Cases0, Cases, 1, _, !Messages),
             switch_calc_cost(Cases, Before, Cost),
             GoalExpr = switch_rep(Var, CanFail, Cases)
         ;
             GoalExpr0 = ite_rep(Cond0, Then0, Else0),
-            goal_to_pard_goal(Info,
-                goal_path_add_at_end(GoalPath, step_ite_cond), Cond0, Cond,
-                !Messages),
-            goal_to_pard_goal(Info,
-                goal_path_add_at_end(GoalPath, step_ite_then), Then0, Then,
-                !Messages),
-            goal_to_pard_goal(Info,
-                goal_path_add_at_end(GoalPath, step_ite_else), Else0, Else,
-                !Messages),
+            goal_to_pard_goal(Info, [step_ite_cond | RevGoalPathSteps],
+                Cond0, Cond, !Messages),
+            goal_to_pard_goal(Info, [step_ite_then | RevGoalPathSteps],
+                Then0, Then, !Messages),
+            goal_to_pard_goal(Info, [step_ite_else | RevGoalPathSteps],
+                Else0, Else, !Messages),
             ite_calc_cost(Cond, Then, Else, Cost),
             GoalExpr = ite_rep(Cond, Then, Else)
         ;
             GoalExpr0 = negation_rep(SubGoal0),
-            goal_to_pard_goal(Info, goal_path_add_at_end(GoalPath, step_neg),
+            goal_to_pard_goal(Info, [step_neg | RevGoalPathSteps],
                 SubGoal0, SubGoal, !Messages),
             Cost = SubGoal ^ goal_annotation ^ pgd_cost,
             GoalExpr = negation_rep(SubGoal)
         ;
             GoalExpr0 = scope_rep(SubGoal0, MaybeCut),
-            goal_to_pard_goal(Info,
-                goal_path_add_at_end(GoalPath, step_scope(MaybeCut)),
+            goal_to_pard_goal(Info, [step_scope(MaybeCut) | RevGoalPathSteps],
                 SubGoal0, SubGoal, !Messages),
             Cost = SubGoal ^ goal_annotation ^ pgd_cost,
             GoalExpr = scope_rep(SubGoal, MaybeCut)
@@ -2725,29 +2736,30 @@
 
         BoundVars = to_sorted_list(InstMapInfo ^ im_bound_vars),
         list.foldl(
-            goal_build_use_map(!.Goal, GoalPath, Cost, Info,
+            goal_build_use_map(!.Goal, RevGoalPathSteps, Cost, Info,
                 var_use_production),
             BoundVars, map.init, ProductionUseMap),
         ConsumedVars = to_sorted_list(InstMapInfo ^ im_consumed_vars),
-        foldl(goal_build_use_map(!.Goal, GoalPath, Cost, Info,
+        list.foldl(goal_build_use_map(!.Goal, RevGoalPathSteps, Cost, Info,
                 var_use_consumption),
             ConsumedVars, map.init, ConsumptionUseMap)
     ;
         GoalExpr0 = atomic_goal_rep(Context, Line, BoundVars, AtomicGoal),
         GoalExpr = atomic_goal_rep(Context, Line, BoundVars, AtomicGoal),
-        atomic_pard_goal_type(Info, GoalPath, AtomicGoal, InstMapInfo,
+        atomic_pard_goal_type(Info, RevGoalPathSteps, AtomicGoal, InstMapInfo,
             PardGoalType, Messages),
-        atomic_pard_goal_cost(Info, GoalPath, Coverage, AtomicGoal, Cost),
+        atomic_pard_goal_cost(Info, RevGoalPathSteps, Coverage, AtomicGoal,
+            Cost),
 
         list.foldl(
-            atomic_goal_build_use_map(AtomicGoal, GoalPath, Info,
+            atomic_goal_build_use_map(AtomicGoal, RevGoalPathSteps, Info,
                 var_use_production),
             BoundVars, map.init, ProductionUseMap),
-        ConsumedVars = InstMapInfo ^ im_consumed_vars,
+        ConsumedVars = to_sorted_list(InstMapInfo ^ im_consumed_vars),
         list.foldl(
-            atomic_goal_build_use_map(AtomicGoal, GoalPath, Info,
+            atomic_goal_build_use_map(AtomicGoal, RevGoalPathSteps, Info,
                 var_use_consumption),
-            to_sorted_list(ConsumedVars), map.init, ConsumptionUseMap),
+            ConsumedVars, map.init, ConsumptionUseMap),
 
         !:Messages = !.Messages ++ Messages
     ),
@@ -2762,38 +2774,40 @@
     ;
         CostAboveThreshold = cost_not_above_par_threshold
     ),
-    PardGoalAnnotation = pard_goal_detail(PardGoalType, InstMapInfo, GoalPath,
-        Coverage, Cost, CostAboveThreshold, ProductionUseMap,
-        ConsumptionUseMap),
+    PardGoalAnnotation = pard_goal_detail(PardGoalType, InstMapInfo,
+        rgp(RevGoalPathSteps), Coverage, Cost, CostAboveThreshold,
+        ProductionUseMap, ConsumptionUseMap),
     !:Goal = goal_rep(GoalExpr, Detism, PardGoalAnnotation).
 
-:- pred conj_to_pard_goals(implicit_parallelism_info::in, goal_path::in,
-    goal_rep(coverage_and_instmap_info)::in, pard_goal_detail::out,
-    int::in, int::out, cord(message)::in, cord(message)::out) is det.
-
-conj_to_pard_goals(Info, GoalPath0, !Goal, !ConjNum, !Messages) :-
-    GoalPath = goal_path_add_at_end(GoalPath0, step_conj(!.ConjNum)),
-    goal_to_pard_goal(Info, GoalPath, !Goal, !Messages),
+:- pred conj_to_pard_goals(implicit_parallelism_info::in,
+    list(goal_path_step)::in, goal_rep(coverage_and_instmap_info)::in,
+    pard_goal_detail::out, int::in, int::out,
+    cord(message)::in, cord(message)::out) is det.
+
+conj_to_pard_goals(Info, RevGoalPathSteps, !Goal, !ConjNum, !Messages) :-
+    goal_to_pard_goal(Info, [step_conj(!.ConjNum) | RevGoalPathSteps],
+        !Goal, !Messages),
     !:ConjNum = !.ConjNum + 1.
 
-:- pred disj_to_pard_goals(implicit_parallelism_info::in, goal_path::in,
-    goal_rep(coverage_and_instmap_info)::in, pard_goal_detail::out,
-    int::in, int::out, cord(message)::in, cord(message)::out) is det.
-
-disj_to_pard_goals(Info, GoalPath0, !Goal, !DisjNum, !Messages) :-
-    GoalPath = goal_path_add_at_end(GoalPath0, step_disj(!.DisjNum)),
-    goal_to_pard_goal(Info, GoalPath, !Goal, !Messages),
+:- pred disj_to_pard_goals(implicit_parallelism_info::in,
+    list(goal_path_step)::in, goal_rep(coverage_and_instmap_info)::in,
+    pard_goal_detail::out, int::in, int::out,
+    cord(message)::in, cord(message)::out) is det.
+
+disj_to_pard_goals(Info, RevGoalPathSteps, !Goal, !DisjNum, !Messages) :-
+    goal_to_pard_goal(Info, [step_disj(!.DisjNum) | RevGoalPathSteps],
+        !Goal, !Messages),
     !:DisjNum = !.DisjNum + 1.
 
-:- pred case_to_pard_goal(implicit_parallelism_info::in, goal_path::in,
-    case_rep(coverage_and_instmap_info)::in,
+:- pred case_to_pard_goal(implicit_parallelism_info::in,
+    list(goal_path_step)::in, case_rep(coverage_and_instmap_info)::in,
     case_rep(pard_goal_detail_annotation)::out, int::in, int::out,
     cord(message)::in, cord(message)::out) is det.
 
-case_to_pard_goal(Info, GoalPath0, !Case, !CaseNum, !Messages) :-
+case_to_pard_goal(Info, RevGoalPathSteps, !Case, !CaseNum, !Messages) :-
     !.Case = case_rep(ConsId, OtherConsId, Goal0),
-    GoalPath = goal_path_add_at_end(GoalPath0, step_switch(!.CaseNum, no)),
-    goal_to_pard_goal(Info, GoalPath, Goal0, Goal, !Messages),
+    goal_to_pard_goal(Info, [step_switch(!.CaseNum, no) | RevGoalPathSteps],
+        Goal0, Goal, !Messages),
     !:CaseNum = !.CaseNum + 1,
     !:Case = case_rep(ConsId, OtherConsId, Goal).
 
@@ -3280,27 +3294,27 @@
         ReportHeaderStr),
     ReportHeader = singleton(ReportHeaderStr),
 
-    ( goal_path_from_string(GoalPathString, GoalPathPrime) ->
-        GoalPath = GoalPathPrime
+    ( rev_goal_path_from_string(GoalPathString, RevGoalPath) ->
+        RevGoalPath = rgp(RevGoalPathSteps)
     ;
         unexpected($module, $pred, "couldn't parse goal path")
     ),
     some [!ConjNum] (
         !:ConjNum = FirstConjNum,
-        format_sequential_conjunction(VarTable, 4, GoalPath, GoalsBefore,
-            GoalsBeforeCost, !.ConjNum, ReportGoalsBefore0),
+        format_sequential_conjunction(VarTable, 4, RevGoalPathSteps,
+            GoalsBefore, GoalsBeforeCost, !.ConjNum, ReportGoalsBefore0),
         ReportGoalsBefore = indent(3) ++ singleton("Goals before:\n") ++
             ReportGoalsBefore0,
 
         !:ConjNum = !.ConjNum + length(GoalsBefore),
-        format_parallel_conjunction(VarTable, 4, GoalPath, !.ConjNum, Conjs,
-            ReportParConj0),
+        format_parallel_conjunction(VarTable, 4, RevGoalPathSteps,
+            !.ConjNum, Conjs, ReportParConj0),
         ReportParConj = indent(3) ++ singleton("Parallel conjunction:\n") ++
             ReportParConj0,
 
         !:ConjNum = !.ConjNum + 1,
-        format_sequential_conjunction(VarTable, 4, GoalPath, GoalsAfter,
-            GoalsAfterCost, !.ConjNum, ReportGoalsAfter0),
+        format_sequential_conjunction(VarTable, 4, RevGoalPathSteps,
+            GoalsAfter, GoalsAfterCost, !.ConjNum, ReportGoalsAfter0),
         ReportGoalsAfter = indent(3) ++ singleton("Goals after:\n") ++
             ReportGoalsAfter0
     ),
@@ -3308,25 +3322,25 @@
         ReportGoalsAfter ++ nl.
 
 :- pred format_parallel_conjunction(var_table::in, int::in,
-    goal_path::in, int::in,
+    list(goal_path_step)::in, int::in,
     list(seq_conj(pard_goal))::in, cord(string)::out) is det.
 
-format_parallel_conjunction(VarTable, Indent, GoalPath0, ConjNum, Conjs,
+format_parallel_conjunction(VarTable, Indent, RevGoalPathSteps, ConjNum, Conjs,
         !:Report) :-
     IndentStr = indent(Indent),
     !:Report = IndentStr ++ singleton("(\n"),
-    GoalPath = goal_path_add_at_end(GoalPath0, step_conj(ConjNum)),
-    format_parallel_conjuncts(VarTable, Indent, GoalPath, 1, Conjs, !Report).
+    format_parallel_conjuncts(VarTable, Indent,
+        [step_conj(ConjNum) | RevGoalPathSteps], 1, Conjs, !Report).
 
-:- pred format_parallel_conjuncts(var_table::in, int::in, goal_path::in,
-    int::in, list(seq_conj(pard_goal))::in,
+:- pred format_parallel_conjuncts(var_table::in, int::in,
+    list(goal_path_step)::in, int::in, list(seq_conj(pard_goal))::in,
     cord(string)::in, cord(string)::out) is det.
 
-format_parallel_conjuncts(_VarTable, Indent, _GoalPath, _ConjNum0,
+format_parallel_conjuncts(_VarTable, Indent, _RevGoalPathSteps, _ConjNum0,
         [], !Report) :-
     IndentStr = indent(Indent),
     !:Report = snoc(!.Report ++ IndentStr, ")\n").
-format_parallel_conjuncts(VarTable, Indent, GoalPath0, ConjNum0,
+format_parallel_conjuncts(VarTable, Indent, RevGoalPathSteps, ConjNum0,
         [Conj | Conjs], !Report) :-
     Conj = seq_conj(Goals),
     (
@@ -3334,20 +3348,20 @@
         unexpected($module, $pred, "empty conjunct in parallel conjunction")
     ;
         Goals = [Goal | GoalsTail],
-        GoalPath = goal_path_add_at_end(GoalPath0, step_conj(ConjNum0)),
+        RevInnerGoalPathSteps = [step_conj(ConjNum0) | RevGoalPathSteps],
         (
             GoalsTail = [],
             % A singleton conjunction gets printed as a single goal.
-            print_goal_to_strings(VarTable, Indent + 1, GoalPath, Goal,
-                ConjReport)
+            print_goal_to_strings(VarTable, Indent + 1, RevInnerGoalPathSteps,
+                Goal, ConjReport)
         ;
             GoalsTail = [_ | _],
             Cost = foldl(
                 (func(GoalI, Acc) =
                     Acc + GoalI ^ goal_annotation ^ pga_cost_percall),
                 Goals, 0.0),
-            format_sequential_conjunction(VarTable, Indent + 1, GoalPath,
-                Goals, Cost, 1, ConjReport)
+            format_sequential_conjunction(VarTable, Indent + 1,
+                RevInnerGoalPathSteps, Goals, Cost, 1, ConjReport)
         )
     ),
     !:Report = !.Report ++ ConjReport,
@@ -3358,20 +3372,21 @@
         !:Report = snoc(!.Report ++ indent(Indent), "&\n")
     ),
     ConjNum = ConjNum0 + 1,
-    format_parallel_conjuncts(VarTable, Indent, GoalPath0, ConjNum, Conjs,
-        !Report).
+    format_parallel_conjuncts(VarTable, Indent, RevGoalPathSteps, ConjNum,
+        Conjs, !Report).
 
-:- pred format_sequential_conjunction(var_table::in, int::in, goal_path::in,
-    list(pard_goal)::in, float::in, int::in, cord(string)::out) is det.
+:- pred format_sequential_conjunction(var_table::in, int::in,
+    list(goal_path_step)::in, list(pard_goal)::in, float::in, int::in,
+    cord(string)::out) is det.
 
-format_sequential_conjunction(VarTable, Indent, GoalPath, Goals, Cost,
+format_sequential_conjunction(VarTable, Indent, RevGoalPathSteps, Goals, Cost,
         FirstConjNum, !:Report) :-
     !:Report = empty,
     ( FirstConjNum = 1 ->
         !:Report = !.Report ++
             indent(Indent) ++
             singleton(format("%% conjunction: %s",
-                [s(goal_path_to_string(GoalPath))])) ++
+                [s(rev_goal_path_to_string(rgp(RevGoalPathSteps)))])) ++
             nl_indent(Indent) ++
             singleton(format("%% Cost: %s",
                 [s(two_decimal_fraction(Cost))])) ++
@@ -3379,18 +3394,18 @@
     ;
         true
     ),
-    format_sequential_conjuncts(VarTable, Indent, GoalPath, Goals,
+    format_sequential_conjuncts(VarTable, Indent, RevGoalPathSteps, Goals,
         FirstConjNum, _, !Report).
 
-:- pred format_sequential_conjuncts(var_table::in, int::in, goal_path::in,
-    list(pard_goal)::in, int::in, int::out,
+:- pred format_sequential_conjuncts(var_table::in, int::in,
+    list(goal_path_step)::in, list(pard_goal)::in, int::in, int::out,
     cord(string)::in, cord(string)::out) is det.
 
 format_sequential_conjuncts(_, _, _, [], !ConjNum, !Report).
-format_sequential_conjuncts(VarTable, Indent, GoalPath0, [Conj | Conjs],
+format_sequential_conjuncts(VarTable, Indent, RevGoalPathSteps, [Conj | Conjs],
         !ConjNum, !Report) :-
-    GoalPath = goal_path_add_at_end(GoalPath0, step_conj(!.ConjNum)),
-    print_goal_to_strings(VarTable, Indent, GoalPath, Conj, ConjReport),
+    print_goal_to_strings(VarTable, Indent,
+        [step_conj(!.ConjNum) | RevGoalPathSteps], Conj, ConjReport),
     !:Report = !.Report ++ ConjReport,
     !:ConjNum = !.ConjNum + 1,
     (
@@ -3398,7 +3413,7 @@
     ;
         Conjs = [_ | _],
         !:Report = !.Report ++ indent(Indent) ++ singleton(",\n"),
-        format_sequential_conjuncts(VarTable, Indent, GoalPath0, Conjs,
+        format_sequential_conjuncts(VarTable, Indent, RevGoalPathSteps, Conjs,
             !ConjNum, !Report)
     ).
 
Index: deep_profiler/message.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/message.m,v
retrieving revision 1.11
diff -u -r1.11 message.m
--- deep_profiler/message.m	15 Dec 2010 06:30:34 -0000	1.11
+++ deep_profiler/message.m	17 Dec 2010 02:50:58 -0000
@@ -37,8 +37,8 @@
                 message_type        :: message_type
             ).
 
-    % The 'importance' of a message,  Debug messages are not covered here since
-    % they should be implemented via trace goals. neither are critical messages
+    % The 'importance' of a message. Debug messages are not covered here since
+    % they should be implemented via trace goals. Neither are critical messages
     % since we use exceptions in that case.
     %
 :- type message_level
@@ -48,10 +48,10 @@
     ;       message_error.
 
 :- type program_location
-    --->    proc(string_proc_label)
-    ;       goal(string_proc_label, goal_path)
-    ;       clique(clique_ptr)
-    ;       call_site_dynamic(call_site_dynamic_ptr).
+    --->    pl_proc(string_proc_label)
+    ;       pl_goal(string_proc_label, reverse_goal_path)
+    ;       pl_clique(clique_ptr)
+    ;       pl_csd(call_site_dynamic_ptr).
 
 %-----------------------------------------------------------------------------%
 
@@ -77,7 +77,6 @@
     % type 'message_type'.
     %
 :- type message_type
-
     --->    info_found_candidate_conjunction
             % A candidate parallel conjunction has been found.
 
@@ -212,27 +211,36 @@
         indent(1) ++ MessageStr ++ singleton("\n"),
     append_list(cord.list(Cord), String).
 
-location_to_string(Level, proc(ProcLabel), String) :-
-    print_proc_label_to_string(ProcLabel, ProcLabelString),
-    String = indent(Level) ++ singleton("Proc: ") ++
-        singleton(ProcLabelString) ++ singleton("\n").
-location_to_string(Level, goal(ProcLabel, GoalPath), String) :-
-    ( empty_goal_path(GoalPath) ->
-        GoalPathString = singleton("Root goal")
+location_to_string(Level, Location, String) :-
+    (
+        Location = pl_proc(ProcLabel),
+        print_proc_label_to_string(ProcLabel, ProcLabelString),
+        String = indent(Level) ++ singleton("Proc: ") ++
+            singleton(ProcLabelString) ++ singleton("\n")
+    ;
+        Location = pl_goal(ProcLabel, RevGoalPath),
+        location_to_string(Level, pl_proc(ProcLabel), FirstLine),
+        RevGoalPath = rgp(RevGoalSteps),
+        (
+            RevGoalSteps = [],
+            GoalPathString = singleton("Root goal")
+        ;
+            RevGoalSteps = [_ | _],
+            GoalPathString = singleton("Goal: ") ++
+                singleton(rev_goal_path_to_string(RevGoalPath))
+        ),
+        SecondLine = indent(Level) ++ GoalPathString ++ singleton("\n"),
+        String = FirstLine ++ SecondLine
     ;
-        GoalPathString =
-            singleton("Goal: ") ++ singleton(goal_path_to_string(GoalPath))
-    ),
-    location_to_string(Level, proc(ProcLabel), FirstLine),
-    SecondLine = indent(Level) ++ GoalPathString ++ singleton("\n"),
-    String = FirstLine ++ SecondLine.
-location_to_string(Level, clique(clique_ptr(Id)), String) :-
-    format("clique %d", [i(Id)], String0),
-    String = indent(Level) ++ singleton(String0).
-location_to_string(Level, call_site_dynamic(CSDPtr), String) :-
-    CSDPtr = call_site_dynamic_ptr(CSDNum),
-    format("call site dynamic %d", [i(CSDNum)], String0),
-    String = indent(Level) ++ singleton(String0).
+        Location = pl_clique(clique_ptr(Id)),
+        format("clique %d", [i(Id)], String0),
+        String = indent(Level) ++ singleton(String0)
+    ;
+        Location = pl_csd(CSDPtr),
+        CSDPtr = call_site_dynamic_ptr(CSDNum),
+        format("call site dynamic %d", [i(CSDNum)], String0),
+        String = indent(Level) ++ singleton(String0)
+    ).
 
 %-----------------------------------------------------------------------------%
 
@@ -260,32 +268,35 @@
 
 :- func message_type_to_level(message_type) = message_level.
 
-message_type_to_level(info_found_candidate_conjunction) =
-    message_info.
-message_type_to_level(info_found_conjs_above_callsite_threshold(_)) =
-    message_info.
-message_type_to_level(info_found_n_conjunctions_with_positive_speedup(_)) =
-    message_info.
-message_type_to_level(info_split_conjunction_into_partitions(_)) = message_info.
-message_type_to_level(notice_duplicate_instantiation(_)) = message_notice.
-message_type_to_level(notice_callpair_has_more_than_one_dependant_var) =
-    message_notice.
-message_type_to_level(notice_partition_does_not_have_costly_calls(_, _)) =
-    message_notice.
-message_type_to_level(notice_candidate_conjunction_not_det(_)) =
-    message_notice.
-message_type_to_level(warning_cannot_lookup_proc_defn) = message_warning.
-message_type_to_level(warning_cannot_compute_procrep_coverage_fallback(_)) =
-    message_warning.
-message_type_to_level(warning_cannot_compute_cost_of_recursive_calls(_)) =
-    message_warning.
-message_type_to_level(warning_cannot_compute_first_use_time(_)) =
-    message_warning.
-message_type_to_level(error_extra_proc_dynamics_in_clique_proc) =
-    message_error.
-message_type_to_level(error_coverage_procrep_error(_)) =
-    message_error.
-message_type_to_level(error_exception_thrown(_)) = message_error.
+message_type_to_level(MsgType) = MsgLevel :-
+    (
+        ( MsgType = info_found_candidate_conjunction
+        ; MsgType = info_found_conjs_above_callsite_threshold(_)
+        ; MsgType = info_found_n_conjunctions_with_positive_speedup(_)
+        ; MsgType = info_split_conjunction_into_partitions(_)
+        ),
+        MsgLevel = message_info
+    ;
+        ( MsgType = notice_duplicate_instantiation(_)
+        ; MsgType = notice_callpair_has_more_than_one_dependant_var
+        ; MsgType = notice_partition_does_not_have_costly_calls(_, _)
+        ; MsgType = notice_candidate_conjunction_not_det(_)
+        ),
+        MsgLevel = message_notice
+    ;
+        ( MsgType = warning_cannot_lookup_proc_defn
+        ; MsgType = warning_cannot_compute_procrep_coverage_fallback(_)
+        ; MsgType = warning_cannot_compute_cost_of_recursive_calls(_)
+        ; MsgType = warning_cannot_compute_first_use_time(_)
+        ),
+        MsgLevel = message_warning
+    ;
+        ( MsgType = error_extra_proc_dynamics_in_clique_proc
+        ; MsgType = error_coverage_procrep_error(_)
+        ; MsgType = error_exception_thrown(_)
+        ),
+        MsgLevel = message_error
+    ).
 
 %-----------------------------------------------------------------------------%
 
Index: deep_profiler/program_representation_utils.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/program_representation_utils.m,v
retrieving revision 1.28
diff -u -r1.28 program_representation_utils.m
--- deep_profiler/program_representation_utils.m	15 Dec 2010 06:30:34 -0000	1.28
+++ deep_profiler/program_representation_utils.m	17 Dec 2010 02:25:19 -0000
@@ -46,22 +46,21 @@
     %
 :- pred print_proc_label_to_string(string_proc_label::in, string::out) is det.
 
-    % print_goal_to_strings(VarTable, Indent, Goal, Strings).
+    % print_goal_to_strings(VarTable, Indent, RevGoalPathSteps, Goal, Strings):
     %
     % Print a goal (recursively) to a string representation.
     %
-:- pred print_goal_to_strings(var_table::in, int::in, goal_path::in, 
-        goal_rep(GoalAnn)::in, cord(string)::out) is det 
+:- pred print_goal_to_strings(var_table::in, int::in, list(goal_path_step)::in,
+    goal_rep(GoalAnn)::in, cord(string)::out) is det
     <= goal_annotation(GoalAnn).
 
-
 %----------------------------------------------------------------------------%
 
 :- typeclass goal_annotation(T) where [
     % Print the goal annotation for inclusion by print_proc_to_strings
     % above.
     %
-    pred print_goal_annotation_to_strings(var_table::in, T::in, 
+    pred print_goal_annotation_to_strings(var_table::in, T::in,
         cord(cord(string))::out) is det
 ].
 
@@ -157,7 +156,7 @@
     % InstMapAfter is InstMapBefore after the variables in InstMapDelta have
     % been instantiated.
     %
-:- pred calc_inst_map_delta(inst_map::in, inst_map::in, inst_map_delta::out) 
+:- pred calc_inst_map_delta(inst_map::in, inst_map::in, inst_map_delta::out)
     is det.
 
 %----------------------------------------------------------------------------%
@@ -172,7 +171,7 @@
     --->    atomic_goal_is_call(list(var_rep))
     ;       atomic_goal_is_trivial.
 
-:- pred atomic_goal_is_call(atomic_goal_rep::in, atomic_goal_is_call::out) 
+:- pred atomic_goal_is_call(atomic_goal_rep::in, atomic_goal_is_call::out)
     is det.
 
 %----------------------------------------------------------------------------%
@@ -214,10 +213,10 @@
     ProcDefnRep = proc_defn_rep(ArgVarReps, GoalRep, VarTable, Detism),
     print_proc_label_to_string(ProcLabel, ProcLabelString0),
     detism_to_string(Detism, DetismString),
-    ProcLabelString = DetismString ++ cord.singleton(" ") ++ 
+    ProcLabelString = DetismString ++ cord.singleton(" ") ++
         cord.singleton(ProcLabelString0),
     print_args_to_strings(print_head_var, VarTable, ArgVarReps, ArgsString),
-    print_goal_to_strings(VarTable, 1, empty_goal_path, GoalRep, GoalString),
+    print_goal_to_strings(VarTable, 1, [], GoalRep, GoalString),
     Strings = ProcLabelString ++ ArgsString ++ cord.singleton(" :-\n") ++
         GoalString ++ nl.
 
@@ -243,17 +242,17 @@
 
 %-----------------------------------------------------------------------------%
 
-print_goal_to_strings(VarTable, Indent, GoalPath, GoalRep, Strings) :-
+print_goal_to_strings(VarTable, Indent, RevGoalPathSteps, GoalRep, Strings) :-
     GoalRep = goal_rep(GoalExprRep, DetismRep, GoalAnnotation),
     (
         GoalExprRep = conj_rep(ConjGoalReps),
-        print_conj_to_strings(VarTable, Indent, GoalPath, ConjGoalReps, 
-            ExprString)
+        print_conj_to_strings(VarTable, Indent, RevGoalPathSteps,
+            ConjGoalReps, ExprString)
     ;
         GoalExprRep = disj_rep(DisjGoalReps),
-        print_disj_to_strings(VarTable, Indent, GoalPath, 1, DisjGoalReps, 
-            no, DisjString),
-        ExprString = indent(Indent) ++ 
+        print_disj_to_strings(VarTable, Indent, RevGoalPathSteps, 1,
+            DisjGoalReps, no, DisjString),
+        ExprString = indent(Indent) ++
             cord.singleton("(\n") ++ DisjString ++ indent(Indent) ++
             cord.singleton(")\n")
     ;
@@ -261,33 +260,33 @@
         lookup_var_name(VarTable, SwitchVarRep, SwitchVarName),
         string.format("%s switch on %s\n",
             [s(string(CanFail)), s(SwitchVarName)], SwitchOnString),
-        print_switch_to_strings(VarTable, Indent, GoalPath, 1, CasesRep, 
-            no, SwitchString),
-        ExprString = indent(Indent) ++ cord.singleton(SwitchOnString) ++ 
-            indent(Indent) ++ cord.singleton("(\n") ++ SwitchString ++ 
+        print_switch_to_strings(VarTable, Indent, RevGoalPathSteps, 1,
+            CasesRep, no, SwitchString),
+        ExprString = indent(Indent) ++ cord.singleton(SwitchOnString) ++
+            indent(Indent) ++ cord.singleton("(\n") ++ SwitchString ++
             indent(Indent) ++ cord.singleton(")\n")
     ;
         GoalExprRep = ite_rep(CondRep, ThenRep, ElseRep),
-        GoalPathCond = goal_path_add_at_end(GoalPath, step_ite_cond),
-        GoalPathThen = goal_path_add_at_end(GoalPath, step_ite_then),
-        GoalPathElse = goal_path_add_at_end(GoalPath, step_ite_else),
-        print_goal_to_strings(VarTable, Indent + 1, GoalPathCond, CondRep, 
-            CondString),
-        print_goal_to_strings(VarTable, Indent + 1, GoalPathThen, ThenRep, 
-            ThenString),
-        print_goal_to_strings(VarTable, Indent + 1, GoalPathElse, ElseRep, 
-            ElseString),
+        RevGoalPathStepsCond = [step_ite_cond | RevGoalPathSteps],
+        RevGoalPathStepsThen = [step_ite_then | RevGoalPathSteps],
+        RevGoalPathStepsElse = [step_ite_else | RevGoalPathSteps],
+        print_goal_to_strings(VarTable, Indent + 1, RevGoalPathStepsCond,
+            CondRep, CondString),
+        print_goal_to_strings(VarTable, Indent + 1, RevGoalPathStepsThen,
+            ThenRep, ThenString),
+        print_goal_to_strings(VarTable, Indent + 1, RevGoalPathStepsElse,
+            ElseRep, ElseString),
         IndentString = indent(Indent),
-        ExprString = IndentString ++ cord.singleton("(\n") ++ CondString ++ 
-            IndentString ++ cord.singleton("->\n") ++ ThenString ++ 
-            IndentString ++ cord.singleton(";\n") ++ ElseString ++ 
+        ExprString = IndentString ++ cord.singleton("(\n") ++ CondString ++
+            IndentString ++ cord.singleton("->\n") ++ ThenString ++
+            IndentString ++ cord.singleton(";\n") ++ ElseString ++
             IndentString ++ cord.singleton(")\n")
     ;
         GoalExprRep = negation_rep(SubGoalRep),
-        SubGoalPath = goal_path_add_at_end(GoalPath, step_neg),
-        print_goal_to_strings(VarTable, Indent + 1, SubGoalPath, SubGoalRep,
-            SubGoalString),
-        ExprString = indent(Indent) ++ cord.singleton("not (\n") ++ 
+        RevSubGoalPathSteps = [step_neg | RevGoalPathSteps],
+        print_goal_to_strings(VarTable, Indent + 1, RevSubGoalPathSteps,
+            SubGoalRep, SubGoalString),
+        ExprString = indent(Indent) ++ cord.singleton("not (\n") ++
             SubGoalString ++ indent(Indent) ++ cord.singleton(")\n")
     ;
         GoalExprRep = scope_rep(SubGoalRep, MaybeCut),
@@ -298,10 +297,10 @@
             MaybeCut = scope_is_no_cut,
             CutString = cord.empty
         ),
-        SubGoalPath = goal_path_add_at_end(GoalPath, step_scope(MaybeCut)),
-        print_goal_to_strings(VarTable, Indent + 1, SubGoalPath, SubGoalRep,
-            SubGoalString),
-        ExprString = indent(Indent) ++ cord.singleton("scope") ++ CutString ++ 
+        RevSubGoalPathSteps = [step_scope(MaybeCut) | RevGoalPathSteps],
+        print_goal_to_strings(VarTable, Indent + 1, RevSubGoalPathSteps,
+            SubGoalRep, SubGoalString),
+        ExprString = indent(Indent) ++ cord.singleton("scope") ++ CutString ++
             cord.singleton(" (\n") ++
             SubGoalString ++ indent(Indent) ++ cord.singleton(")\n")
     ;
@@ -310,7 +309,7 @@
         print_atomic_goal_to_strings(VarTable, AtomicGoalRep, ExprString0),
         ExprString = indent(Indent) ++ ExprString0
     ),
-    
+
     ( GoalExprRep = conj_rep(_) ->
         LinePrefix = indent(Indent) ++ singleton("% conjunction: "),
         ExtraLineForConjunctions = nl
@@ -330,7 +329,7 @@
         GoalAnnotationLines = foldr(++, GoalAnnotationLines1, empty)
     ),
 
-    GoalPathString0 = goal_path_to_string(GoalPath),
+    GoalPathString0 = rev_goal_path_to_string(rgp(RevGoalPathSteps)),
     ( GoalPathString0 = "" ->
         GoalPathString = "root goal"
     ;
@@ -345,50 +344,54 @@
         ++ ExprString.
 
 :- pred print_conj_to_strings(var_table::in, int::in,
-    goal_path::in, list(goal_rep(GoalAnn))::in, cord(string)::out) is det
+    list(goal_path_step)::in, list(goal_rep(GoalAnn))::in,
+    cord(string)::out) is det
     <= goal_annotation(GoalAnn).
 
-print_conj_to_strings(VarTable, Indent, GoalPath, GoalReps, Strings) :-
+print_conj_to_strings(VarTable, Indent, RevGoalPathSteps, GoalReps, Strings) :-
     (
         GoalReps = [],
         Strings = cord.snoc(indent(Indent), "true\n")
     ;
         GoalReps = [_ | _],
-        print_conj_2_to_strings(VarTable, Indent, GoalPath, 1, GoalReps, 
-            Strings)
+        print_conj_to_strings_2(VarTable, Indent, RevGoalPathSteps, 1,
+            GoalReps, Strings)
     ).
 
-:- pred print_conj_2_to_strings(var_table::in, int::in,
-    goal_path::in, int::in, list(goal_rep(GoalAnn))::in, cord(string)::out)
+:- pred print_conj_to_strings_2(var_table::in, int::in,
+    list(goal_path_step)::in, int::in, list(goal_rep(GoalAnn))::in,
+    cord(string)::out)
     is det <= goal_annotation(GoalAnn).
 
-print_conj_2_to_strings(_, _Indent, _, _, [], cord.empty).
-print_conj_2_to_strings(VarTable, Indent, GoalPath0, ConjNum, 
+print_conj_to_strings_2(_, _Indent, _, _, [], cord.empty).
+print_conj_to_strings_2(VarTable, Indent, RevGoalPathSteps, ConjNum,
         [GoalRep | GoalReps], Strings) :-
     % We use the absence of a separator to denote conjunction.
     %
     % We could try to append the comma at the end of each goal that is
     % not last in a conjunction, but that would be significant work,
     % and (at least for now) there is no real need for it.
-    GoalPath = goal_path_add_at_end(GoalPath0, step_conj(ConjNum)),
-    print_goal_to_strings(VarTable, Indent, GoalPath, GoalRep, GoalString),
-    print_conj_2_to_strings(VarTable, Indent, GoalPath0, ConjNum+1, 
-        GoalReps, ConjString),
+    RevSubGoalPathSteps = [step_conj(ConjNum) | RevGoalPathSteps],
+    print_goal_to_strings(VarTable, Indent, RevSubGoalPathSteps,
+        GoalRep, HeadGoalString),
+    print_conj_to_strings_2(VarTable, Indent, RevGoalPathSteps, ConjNum + 1,
+        GoalReps, TailGoalsString),
     (
         GoalReps = [],
-        Seperator = empty
+        Separator = empty
     ;
         GoalReps = [_ | _],
-        Seperator = indent(Indent) ++ singleton(",\n")
+        Separator = indent(Indent) ++ singleton(",\n")
     ),
-    Strings = GoalString ++ Seperator ++ ConjString.
+    Strings = HeadGoalString ++ Separator ++ TailGoalsString.
 
-:- pred print_disj_to_strings(var_table::in, int::in, goal_path::in, 
-    int::in, list(goal_rep(GoalAnn))::in, bool::in, cord(string)::out) 
+:- pred print_disj_to_strings(var_table::in, int::in,
+    list(goal_path_step)::in, int::in, list(goal_rep(GoalAnn))::in, bool::in,
+    cord(string)::out)
     is det <= goal_annotation(GoalAnn).
 
 print_disj_to_strings(_, _Indent, _, _, [], _PrintSemi, cord.empty).
-print_disj_to_strings(VarTable, Indent, GoalPath0, DisjNum,
+print_disj_to_strings(VarTable, Indent, RevGoalPathSteps, DisjNum,
         [GoalRep | GoalReps], PrintSemi, Strings) :-
     (
         PrintSemi = no,
@@ -397,18 +400,20 @@
         PrintSemi = yes,
         DelimString = indent(Indent) ++ cord.singleton(";\n")
     ),
-    GoalPath = goal_path_add_at_end(GoalPath0, step_disj(DisjNum)),
-    print_goal_to_strings(VarTable, Indent + 1, GoalPath, GoalRep, GoalString),
-    print_disj_to_strings(VarTable, Indent, GoalPath0, DisjNum+1, GoalReps,
-        yes, DisjString),
-    Strings = DelimString ++ GoalString ++ DisjString.
-
-:- pred print_switch_to_strings(var_table::in, int::in, goal_path::in, 
-    int::in, list(case_rep(GoalAnn))::in, bool::in, cord(string)::out) is det
+    RevSubGoalPathSteps = [step_disj(DisjNum) | RevGoalPathSteps],
+    print_goal_to_strings(VarTable, Indent + 1, RevSubGoalPathSteps,
+        GoalRep, HeadGoalString),
+    print_disj_to_strings(VarTable, Indent, RevGoalPathSteps, DisjNum + 1,
+        GoalReps, yes, TailGoalsString),
+    Strings = DelimString ++ HeadGoalString ++ TailGoalsString.
+
+:- pred print_switch_to_strings(var_table::in, int::in,
+    list(goal_path_step)::in, int::in, list(case_rep(GoalAnn))::in, bool::in,
+    cord(string)::out) is det
     <= goal_annotation(GoalAnn).
 
 print_switch_to_strings(_, _Indent, _, _, [], _PrintSemi, cord.empty).
-print_switch_to_strings(VarTable, Indent, GoalPath0, CaseNum, 
+print_switch_to_strings(VarTable, Indent, RevGoalPathSteps, CaseNum,
         [CaseRep | CaseReps], PrintSemi, Strings) :-
     (
         PrintSemi = no,
@@ -422,13 +427,14 @@
         ConsIdArityString),
     list.map(print_cons_id_and_arity_to_strings(Indent + 1),
         OtherConsIdArityRep, OtherConsIdArityStrings),
-    GoalPath = goal_path_add_at_end(GoalPath0, step_switch(CaseNum, no)),
-    print_goal_to_strings(VarTable, Indent + 1, GoalPath, GoalRep, GoalString),
-    print_switch_to_strings(VarTable, Indent, GoalPath0, CaseNum+1, CaseReps,
-        yes, CaseStrings),
+    RevSubGoalPathSteps = [step_switch(CaseNum, no) | RevGoalPathSteps],
+    print_goal_to_strings(VarTable, Indent + 1, RevSubGoalPathSteps,
+        GoalRep, HeadGoalString),
+    print_switch_to_strings(VarTable, Indent, RevGoalPathSteps, CaseNum + 1,
+        CaseReps, yes, TailCasesStrings),
     Strings = DelimString ++ ConsIdArityString ++
-        cord_list_to_cord(OtherConsIdArityStrings) ++ GoalString ++
-        CaseStrings.
+        cord_list_to_cord(OtherConsIdArityStrings) ++ HeadGoalString ++
+        TailCasesStrings.
 
 :- pred print_cons_id_and_arity_to_strings(int::in, cons_id_arity_rep::in,
     cord(string)::out) is det.
@@ -440,7 +446,7 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred print_atomic_goal_to_strings(var_table::in, atomic_goal_rep::in, 
+:- pred print_atomic_goal_to_strings(var_table::in, atomic_goal_rep::in,
     cord(string)::out) is det.
 
 print_atomic_goal_to_strings(VarTable, AtomicGoalRep, Strings) :-
@@ -827,7 +833,7 @@
             ->
                 (
                     BeforeInst = ir_free_rep,
-                    ( 
+                    (
                         Inst = ir_free_rep,
                         Set = Set0
                     ;
@@ -841,7 +847,7 @@
                     BeforeInst = ir_ground_rep,
                     (
                         Inst = ir_free_rep,
-                        error("calc_inst_map_delta: " ++ 
+                        error("calc_inst_map_delta: " ++
                             "Variables cannot become less instantiated.")
                     ;
                         ( Inst = ir_ground_rep
@@ -853,7 +859,7 @@
                     BeforeInst = ir_other_rep,
                     (
                         Inst = ir_free_rep,
-                        error("calc_inst_map_delta: " ++ 
+                        error("calc_inst_map_delta: " ++
                             "Variables cannot become less instantiated.")
                     ;
                         ( Inst = ir_ground_rep
@@ -952,4 +958,3 @@
     ).
 
 %----------------------------------------------------------------------------%
-
Index: deep_profiler/read_profile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/read_profile.m,v
retrieving revision 1.31
diff -u -r1.31 read_profile.m
--- deep_profiler/read_profile.m	15 Dec 2010 06:30:34 -0000	1.31
+++ deep_profiler/read_profile.m	17 Dec 2010 02:51:53 -0000
@@ -703,8 +703,8 @@
         read_string,
         read_cp_type,
         (pred(GoalPathString::in, CPType::in, MaybeCPI::out) is det :-
-            goal_path_from_string_det(GoalPathString, GoalPath),
-            MaybeCPI = ok(coverage_point_info(GoalPath, CPType))
+            rev_goal_path_from_string_det(GoalPathString, RevGoalPath),
+            MaybeCPI = ok(coverage_point_info(RevGoalPath, CPType))
         ), MaybeCP, !IO).
 
 :- func raw_proc_id_to_string(string_proc_label) = string.
Index: deep_profiler/recursion_patterns.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/recursion_patterns.m,v
retrieving revision 1.9
diff -u -r1.9 recursion_patterns.m
--- deep_profiler/recursion_patterns.m	15 Dec 2010 06:30:34 -0000	1.9
+++ deep_profiler/recursion_patterns.m	17 Dec 2010 03:32:31 -0000
@@ -128,7 +128,7 @@
         proc_dynamic_paired_call_site_slots(Deep, PDPtr, Slots),
         foldl(build_call_site_cost_and_callee_map(Deep),
             Slots, map.init, CallSitesMap),
-        goal_recursion_data(ThisClique, CallSitesMap, empty_goal_path,
+        goal_recursion_data(ThisClique, CallSitesMap, [],
             Goal, RecursionData),
         recursion_data_to_recursion_type(ParentCalls, TotalCalls,
             RecursionData, RecursionType),
@@ -287,10 +287,10 @@
     % that may eventually lead to Goal.
     %
 :- pred goal_recursion_data(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, goal_path::in,
+    map(reverse_goal_path, cost_and_callees)::in, list(goal_path_step)::in,
     goal_rep(coverage_info)::in, recursion_data::out) is det.
 
-goal_recursion_data(ThisClique, CallSiteMap, GoalPath, GoalRep,
+goal_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps, GoalRep,
         !:RecursionData) :-
     GoalRep = goal_rep(GoalExpr, Detism, CoverageInfo),
     ( get_coverage_before(CoverageInfo, CallsPrime) ->
@@ -303,19 +303,19 @@
     ;
         (
             GoalExpr = conj_rep(Conjs),
-            conj_recursion_data(ThisClique, CallSiteMap, GoalPath, 1, Conjs,
-                !:RecursionData)
+            conj_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
+                1, Conjs, !:RecursionData)
         ;
             GoalExpr = disj_rep(Disjs),
-            disj_recursion_data(ThisClique, CallSiteMap, GoalPath, 1, Disjs,
-                !:RecursionData)
+            disj_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
+                1, Disjs, !:RecursionData)
         ;
             GoalExpr = switch_rep(_, _, Cases),
-            switch_recursion_data(ThisClique, CallSiteMap, GoalPath, 1, Cases,
-                float(Calls), Calls, !:RecursionData)
+            switch_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
+                1, Cases, float(Calls), Calls, !:RecursionData)
         ;
             GoalExpr = ite_rep(Cond, Then, Else),
-            ite_recursion_data(ThisClique, CallSiteMap, GoalPath,
+            ite_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
                 Cond, Then, Else, Calls, !:RecursionData)
         ;
             (
@@ -326,12 +326,12 @@
                 GoalPathStep = step_scope(MaybeCut)
             ),
             goal_recursion_data(ThisClique, CallSiteMap,
-                goal_path_add_at_end(GoalPath, GoalPathStep), SubGoal,
+                [GoalPathStep | RevGoalPathSteps], SubGoal,
                 !:RecursionData)
         ;
             GoalExpr = atomic_goal_rep(_, _, _, AtomicGoalRep),
-            atomic_goal_recursion_data(ThisClique, CallSiteMap, GoalPath,
-                AtomicGoalRep, !:RecursionData)
+            atomic_goal_recursion_data(ThisClique, CallSiteMap,
+                RevGoalPathSteps, AtomicGoalRep, !:RecursionData)
         )
     ),
     (
@@ -351,17 +351,16 @@
     ).
 
 :- pred conj_recursion_data(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, goal_path::in, int::in,
-    list(goal_rep(coverage_info))::in, recursion_data::out) is det.
+    map(reverse_goal_path, cost_and_callees)::in, list(goal_path_step)::in,
+    int::in, list(goal_rep(coverage_info))::in, recursion_data::out) is det.
 
 conj_recursion_data(_, _, _, _, [], simple_recursion_data(0.0, 0)).
     % An empty conjunction is true, there is exactly one trivial path
     % through it with 0 recursive calls.
-conj_recursion_data(ThisClique, CallSiteMap, GoalPath, ConjNum,
+conj_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps, ConjNum,
         [Conj | Conjs], RecursionData) :-
     goal_recursion_data(ThisClique, CallSiteMap,
-        goal_path_add_at_end(GoalPath, step_conj(ConjNum)), Conj,
-        ConjRecursionData),
+        [step_conj(ConjNum) | RevGoalPathSteps], Conj, ConjRecursionData),
     (
         ConjRecursionData = proc_dead_code,
         % If the first conjunct is dead then the remaining ones will
@@ -371,8 +370,8 @@
     ;
         ConjRecursionData = recursion_data(_, _, _),
 
-        conj_recursion_data(ThisClique, CallSiteMap, GoalPath, ConjNum + 1,
-            Conjs, ConjsRecursionData0),
+        conj_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
+            ConjNum + 1, Conjs, ConjsRecursionData0),
         CanFail = detism_get_can_fail(Conj ^ goal_detism_rep),
         (
             CanFail = cannot_fail_rep,
@@ -400,17 +399,16 @@
     ).
 
 :- pred disj_recursion_data(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, goal_path::in, int::in,
-    list(goal_rep(coverage_info))::in, recursion_data::out) is det.
+    map(reverse_goal_path, cost_and_callees)::in, list(goal_path_step)::in,
+    int::in, list(goal_rep(coverage_info))::in, recursion_data::out) is det.
 
 disj_recursion_data(_, _, _, _, [], simple_recursion_data(0.0, 0)).
-disj_recursion_data(ThisClique, CallSiteMap, GoalPath, DisjNum,
+disj_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps, DisjNum,
         [Disj | Disjs], RecursionData) :-
     % Handle only semidet and committed-choice disjunctions, which cannot be
     % re-entered once a disjunct succeeds.
     goal_recursion_data(ThisClique, CallSiteMap,
-        goal_path_add_at_end(GoalPath, step_disj(DisjNum)), Disj,
-        DisjRecursionData),
+        [step_disj(DisjNum) | RevGoalPathSteps], Disj, DisjRecursionData),
     (
         DisjRecursionData = proc_dead_code,
         % If the first disjunct was never tried, then no other disjuncts will
@@ -424,8 +422,8 @@
 
         % The code can branch here, either it tries the next disjuct, which we
         % represent as DisjsRecursionData, ...
-        disj_recursion_data(ThisClique, CallSiteMap, GoalPath, DisjNum + 1,
-            Disjs, DisjsRecursionData0),
+        disj_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
+            DisjNum + 1, Disjs, DisjsRecursionData0),
         recursion_data_and_probability(DisjFailureProb, DisjsRecursionData0,
             DisjsRecursionData),
 
@@ -459,21 +457,18 @@
     ).
 
 :- pred ite_recursion_data(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, goal_path::in,
+    map(reverse_goal_path, cost_and_callees)::in, list(goal_path_step)::in,
     goal_rep(coverage_info)::in, goal_rep(coverage_info)::in,
     goal_rep(coverage_info)::in, int::in, recursion_data::out) is det.
 
-ite_recursion_data(ThisClique, CallSiteMap, GoalPath, Cond, Then, Else,
+ite_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps, Cond, Then, Else,
         Calls, !:RecursionData) :-
     goal_recursion_data(ThisClique, CallSiteMap,
-        goal_path_add_at_end(GoalPath, step_ite_cond), Cond,
-        CondRecursionData),
+        [step_ite_cond | RevGoalPathSteps], Cond, CondRecursionData),
     goal_recursion_data(ThisClique, CallSiteMap,
-        goal_path_add_at_end(GoalPath, step_ite_then), Then,
-        ThenRecursionData0),
+        [step_ite_then | RevGoalPathSteps], Then, ThenRecursionData0),
     goal_recursion_data(ThisClique, CallSiteMap,
-        goal_path_add_at_end(GoalPath, step_ite_else), Else,
-        ElseRecursionData0),
+        [step_ite_else | RevGoalPathSteps], Else, ElseRecursionData0),
 
     % Adjust the probabilities of executing the then and else branches.
     (
@@ -500,8 +495,8 @@
     merge_recursion_data_sequence(CondRecursionData, !RecursionData).
 
 :- pred switch_recursion_data(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, goal_path::in, int::in,
-    list(case_rep(coverage_info))::in, float::in, int::in,
+    map(reverse_goal_path, cost_and_callees)::in, list(goal_path_step)::in,
+    int::in, list(case_rep(coverage_info))::in, float::in, int::in,
     recursion_data::out) is det.
 
 switch_recursion_data(_, _, _, _, [], TotalCalls, CallsRemaining,
@@ -510,11 +505,11 @@
     FailProb = probable(float(CallsRemaining) / TotalCalls),
     RecursionData0 = simple_recursion_data(0.0, 0),
     recursion_data_and_probability(FailProb, RecursionData0, RecursionData).
-switch_recursion_data(ThisClique, CallSiteMap, GoalPath, CaseNum,
+switch_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps, CaseNum,
         [Case | Cases], TotalCalls, CallsRemaining, RecursionData) :-
     Case = case_rep(_, _, Goal),
     goal_recursion_data(ThisClique, CallSiteMap,
-        goal_path_add_at_end(GoalPath, step_switch(CaseNum, no)), Goal,
+        [step_switch(CaseNum, no) | RevGoalPathSteps], Goal,
         CaseRecursionData0),
     ( get_coverage_before(Goal ^ goal_annotation, CallsPrime) ->
         Calls = CallsPrime
@@ -524,17 +519,17 @@
     CaseProb = probable(float(Calls) / TotalCalls),
     recursion_data_and_probability(CaseProb, CaseRecursionData0,
         CaseRecursionData),
-    switch_recursion_data(ThisClique, CallSiteMap, GoalPath, CaseNum+1,
+    switch_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps, CaseNum+1,
         Cases, TotalCalls, CallsRemaining - Calls, CasesRecursionData),
     merge_recursion_data_after_branch(CaseRecursionData, CasesRecursionData,
         RecursionData).
 
 :- pred atomic_goal_recursion_data(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, goal_path::in,
+    map(reverse_goal_path, cost_and_callees)::in, list(goal_path_step)::in,
     atomic_goal_rep::in, recursion_data::out) is det.
 
-atomic_goal_recursion_data(ThisClique, CallSiteMap, GoalPath, AtomicGoal,
-        RecursionData) :-
+atomic_goal_recursion_data(ThisClique, CallSiteMap, RevGoalPathSteps,
+        AtomicGoal, RecursionData) :-
     (
         % All these things have trivial cost except for foreign code whose cost
         % is unknown (which because it doesn't contribute to the cost of the
@@ -558,7 +553,7 @@
         ),
 
         % Get the cost of the call.
-        map.lookup(CallSiteMap, GoalPath, CostAndCallees),
+        map.lookup(CallSiteMap, rgp(RevGoalPathSteps), CostAndCallees),
         ( cost_and_callees_is_recursive(ThisClique, CostAndCallees) ->
             % Cost will be 1.0 for for each call to recursive calls but we
             % calculate this later.
Index: deep_profiler/report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/report.m,v
retrieving revision 1.27
diff -u -r1.27 report.m
--- deep_profiler/report.m	15 Dec 2010 06:30:34 -0000	1.27
+++ deep_profiler/report.m	17 Dec 2010 02:58:28 -0000
@@ -642,7 +642,7 @@
                 csdesc_caller_uq_refined_name   :: string,
                 csdesc_caller_q_refined_name    :: string,
                 csdesc_slot_number              :: int,
-                csdesc_goal_path                :: goal_path,
+                csdesc_goal_path                :: reverse_goal_path,
                 csdesc_maybe_callee             :: maybe(proc_desc)
             ).
 
@@ -683,8 +683,8 @@
     % Build a map from goal paths to call site reports.
     %
 :- pred add_call_site_report_to_map(clique_call_site_report::in,
-    map(goal_path, clique_call_site_report)::in,
-    map(goal_path, clique_call_site_report)::out) is det.
+    map(reverse_goal_path, clique_call_site_report)::in,
+    map(reverse_goal_path, clique_call_site_report)::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: deep_profiler/var_use_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/var_use_analysis.m,v
retrieving revision 1.9
diff -u -r1.9 var_use_analysis.m
--- deep_profiler/var_use_analysis.m	15 Dec 2010 06:30:35 -0000	1.9
+++ deep_profiler/var_use_analysis.m	17 Dec 2010 03:41:34 -0000
@@ -132,9 +132,10 @@
     % Find the first use of a variable in an arbitrary goal.
     %
 :- pred var_first_use(clique_ptr::in,
-    map(goal_path, cost_and_callees)::in, map(goal_path, cs_cost_csq)::in,
+    map(reverse_goal_path, cost_and_callees)::in,
+    map(reverse_goal_path, cs_cost_csq)::in,
     recursion_type::in(recursion_type_known_costs), recursion_depth::in,
-    goal_rep(T)::in, goal_path::in, float::in, var_rep::in,
+    goal_rep(T)::in, reverse_goal_path::in, float::in, var_rep::in,
     var_use_options::in, var_use_info::out) is det
     <= goal_annotation_with_coverage(T).
 
@@ -402,8 +403,10 @@
 :- type var_first_use_static_info
     --->    var_first_use_static_info(
                 fui_clique              :: clique_ptr,
-                fui_call_site_map       :: map(goal_path, cost_and_callees),
-                fui_rec_call_site_map   :: map(goal_path, cs_cost_csq),
+                fui_call_site_map       :: map(reverse_goal_path,
+                                                cost_and_callees),
+                fui_rec_call_site_map   :: map(reverse_goal_path,
+                                                cs_cost_csq),
                 fui_var                 :: var_rep,
                 fui_var_use_opts        :: var_use_options,
 
@@ -432,12 +435,13 @@
     % follow call the calls seen during profiling and aggregate their variable
     % use information based on how often they are called from that call site.
     %
-:- pred goal_var_first_use(goal_path::in, goal_rep(T)::in,
+:- pred goal_var_first_use(list(goal_path_step)::in, goal_rep(T)::in,
     var_first_use_static_info::in(var_first_use_static_info), float::in,
     float::out, found_first_use::out) is det
     <= goal_annotation_with_coverage(T).
 
-goal_var_first_use(GoalPath, Goal, StaticInfo, !CostSoFar, FoundFirstUse) :-
+goal_var_first_use(RevGoalPathSteps, Goal, StaticInfo, !CostSoFar,
+        FoundFirstUse) :-
     Goal = goal_rep(GoalExpr, Detism, _),
     Coverage = get_coverage(Goal),
     (
@@ -461,31 +465,31 @@
     ;
         (
             GoalExpr = conj_rep(Conjuncts),
-            conj_var_first_use(GoalPath, 1, Conjuncts, StaticInfo, !CostSoFar,
-                FoundFirstUse)
+            conj_var_first_use(RevGoalPathSteps, 1, Conjuncts, StaticInfo,
+                !CostSoFar, FoundFirstUse)
         ;
             GoalExpr = disj_rep(Disjuncts),
-            disj_var_first_use(GoalPath, Disjuncts, Detism, StaticInfo,
+            disj_var_first_use(RevGoalPathSteps, Disjuncts, Detism, StaticInfo,
                 !CostSoFar, FoundFirstUse)
         ;
             GoalExpr = switch_rep(SwitchedOnVar, _CanFail, Cases),
-            switch_var_first_use(GoalPath, SwitchedOnVar, Cases,
+            switch_var_first_use(RevGoalPathSteps, SwitchedOnVar, Cases,
                 StaticInfo, !CostSoFar, FoundFirstUse)
         ;
             GoalExpr = ite_rep(Cond, Then, Else),
-            ite_var_first_use(GoalPath, Cond, Then, Else, StaticInfo,
+            ite_var_first_use(RevGoalPathSteps, Cond, Then, Else, StaticInfo,
                 !CostSoFar, FoundFirstUse)
         ;
             (
                 GoalExpr = negation_rep(SubGoal),
-                SubGoalPath = goal_path_add_at_end(GoalPath, step_neg)
+                GoalPathStep = step_neg
             ;
                 GoalExpr = scope_rep(SubGoal, ScopeIsCut),
-                SubGoalPath = goal_path_add_at_end(GoalPath,
-                    step_scope(ScopeIsCut))
+                GoalPathStep = step_scope(ScopeIsCut)
             ),
-            goal_var_first_use(SubGoalPath, SubGoal, StaticInfo, !CostSoFar,
-                FoundFirstUse)
+            RevSubGoalPathSteps = [GoalPathStep | RevGoalPathSteps],
+            goal_var_first_use(RevSubGoalPathSteps, SubGoal, StaticInfo,
+                !CostSoFar, FoundFirstUse)
         ;
             GoalExpr = atomic_goal_rep(_, _, BoundVars, AtomicGoal),
             (
@@ -493,8 +497,8 @@
                 ; AtomicGoal = higher_order_call_rep(_, _)
                 ; AtomicGoal = method_call_rep(_, _, _)
                 ),
-                call_var_first_use(AtomicGoal, BoundVars, GoalPath, StaticInfo,
-                    !CostSoFar, FoundFirstUse)
+                call_var_first_use(AtomicGoal, BoundVars, RevGoalPathSteps,
+                    StaticInfo, !CostSoFar, FoundFirstUse)
             ;
                 ( AtomicGoal = unify_construct_rep(_, _, _)
                 ; AtomicGoal = unify_deconstruct_rep(_, _, _)
@@ -515,7 +519,7 @@
     ),
     trace [compile_time(flag("debug_first_var_use")), io(!IO)] (
         io.format("Trace: goal_var_first_use: %s\n",
-            [s(goal_path_to_string(GoalPath))], !IO)
+            [s(rev_goal_path_to_string(rgp(RevGoalPathSteps)))], !IO)
     ).
 
 :- inst atomic_goal_rep_call
@@ -524,21 +528,22 @@
     ;       method_call_rep(ground, ground, ground).
 
 :- pred call_var_first_use(atomic_goal_rep::in(atomic_goal_rep_call),
-    list(var_rep)::in, goal_path::in,
+    list(var_rep)::in, list(goal_path_step)::in,
     var_first_use_static_info::in(var_first_use_static_info),
     float::in, float::out, found_first_use::out) is det.
 
-call_var_first_use(AtomicGoal, BoundVars, GoalPath, StaticInfo,
+call_var_first_use(AtomicGoal, BoundVars, RevGoalPathSteps, StaticInfo,
         CostSoFar, NextCostSoFar, FoundFirstUse) :-
     StaticInfo = var_first_use_static_info(CliquePtr, CostMap,
         RecCostMap, Var, VarUseOptions, _CallStack, _RecursionType,
         _MaybeCurDepth),
     VarUseType = VarUseOptions ^ vuo_var_use_type,
-    map.lookup(CostMap, GoalPath, CostAndCallees),
+    RevGoalPath = rgp(RevGoalPathSteps),
+    map.lookup(CostMap, RevGoalPath, CostAndCallees),
 
     % Get the cost of the call.
     ( cost_and_callees_is_recursive(CliquePtr, CostAndCallees) ->
-        map.lookup(RecCostMap, GoalPath, Cost0)
+        map.lookup(RecCostMap, RevGoalPath, Cost0)
     ;
         Cost0 = CostAndCallees ^ cac_cost
     ),
@@ -714,18 +719,17 @@
     % time from the end of the goal. Similarly with other goal types that have
     % an execution order, namely disjunctions and if-then-elses.
     %
-:- pred conj_var_first_use(goal_path::in, int::in,
+:- pred conj_var_first_use(list(goal_path_step)::in, int::in,
     list(goal_rep(T))::in,
     var_first_use_static_info::in(var_first_use_static_info),
     float::in, float::out, found_first_use::out) is det
     <= goal_annotation_with_coverage(T).
 
 conj_var_first_use(_, _, [], _, !Cost, have_not_found_first_use).
-conj_var_first_use(GoalPath, ConjNum, [Conj | Conjs], StaticInfo, !CostSoFar,
-        FoundFirstUse) :-
-    ConjGoalPath = goal_path_add_at_end(GoalPath, step_conj(ConjNum)),
-    goal_var_first_use(ConjGoalPath, Conj, StaticInfo, !CostSoFar,
-        HeadFoundFirstUse),
+conj_var_first_use(RevGoalPathSteps, ConjNum, [Conj | Conjs], StaticInfo,
+        !CostSoFar, FoundFirstUse) :-
+    goal_var_first_use([step_conj(ConjNum) | RevGoalPathSteps], Conj,
+        StaticInfo, !CostSoFar, HeadFoundFirstUse),
     (
         % XXX: if a variable is bound more than once, because it's used with
         % partial instantiation then we want to use the last time it is bound.
@@ -735,17 +739,17 @@
         FoundFirstUse = HeadFoundFirstUse
     ;
         HeadFoundFirstUse = have_not_found_first_use,
-        conj_var_first_use(GoalPath, ConjNum + 1, Conjs, StaticInfo,
+        conj_var_first_use(RevGoalPathSteps, ConjNum + 1, Conjs, StaticInfo,
             !CostSoFar, TailFoundFirstUse),
         FoundFirstUse = TailFoundFirstUse
     ).
 
-:- pred disj_var_first_use(goal_path::in, list(goal_rep(T))::in,
+:- pred disj_var_first_use(list(goal_path_step)::in, list(goal_rep(T))::in,
     detism_rep::in, var_first_use_static_info::in(var_first_use_static_info),
     float::in, float::out, found_first_use::out) is det
     <= goal_annotation_with_coverage(T).
 
-disj_var_first_use(GoalPath, Disjuncts, Detism, StaticInfo,
+disj_var_first_use(RevGoalPathSteps, Disjuncts, Detism, StaticInfo,
         !CostSoFar, FoundFirstUse) :-
     % We cannot handle nondet/multi disjunctions. So we use pessimistic
     % defaults for FoundFirstUse if this disjunction is nondet or multi.
@@ -755,7 +759,7 @@
     % drametically effect anything.
     CostBeforeConsumption = !.CostSoFar,
     CostAfterProduction = !.CostSoFar,
-    disj_var_first_use_2(GoalPath, 1, Disjuncts, StaticInfo,
+    disj_var_first_use_2(RevGoalPathSteps, 1, Disjuncts, StaticInfo,
         !CostSoFar, FoundFirstUse0),
     (
         detism_get_solutions(Detism) = at_most_many_rep,
@@ -775,20 +779,19 @@
         FoundFirstUse = FoundFirstUse0
     ).
 
-:- pred disj_var_first_use_2(goal_path::in, int::in,
+:- pred disj_var_first_use_2(list(goal_path_step)::in, int::in,
     list(goal_rep(T))::in,
     var_first_use_static_info::in(var_first_use_static_info),
     float::in, float::out, found_first_use::out) is det
     <= goal_annotation_with_coverage(T).
 
 disj_var_first_use_2(_, _, [], _, !CostSoFar, have_not_found_first_use).
-disj_var_first_use_2(GoalPath, DisjNum, [Disj | Disjs], StaticInfo, !CostSoFar,
-        FoundFirstUse) :-
-    DisjGoalPath = goal_path_add_at_end(GoalPath, step_disj(DisjNum)),
+disj_var_first_use_2(RevGoalPathSteps, DisjNum, [Disj | Disjs], StaticInfo,
+        !CostSoFar, FoundFirstUse) :-
     VarUseType = StaticInfo ^ fui_var_use_opts ^ vuo_var_use_type,
-    goal_var_first_use(DisjGoalPath, Disj, StaticInfo, !CostSoFar,
-        HeadFoundFirstUse),
-    disj_var_first_use_2(GoalPath, DisjNum + 1, Disjs, StaticInfo,
+    goal_var_first_use([step_disj(DisjNum) | RevGoalPathSteps], Disj,
+        StaticInfo, !CostSoFar, HeadFoundFirstUse),
+    disj_var_first_use_2(RevGoalPathSteps, DisjNum + 1, Disjs, StaticInfo,
         !CostSoFar, TailFoundFirstUse),
     (
         HeadFoundFirstUse = have_not_found_first_use,
@@ -841,15 +844,15 @@
         FoundFirstUse = found_first_use(Cost)
     ).
 
-:- pred switch_var_first_use(goal_path::in, var_rep::in,
+:- pred switch_var_first_use(list(goal_path_step)::in, var_rep::in,
     list(case_rep(T))::in,
     var_first_use_static_info::in(var_first_use_static_info),
     float::in, float::out, found_first_use::out) is det
     <= goal_annotation_with_coverage(T).
 
-switch_var_first_use(GoalPath, SwitchedOnVar, Cases, StaticInfo,
+switch_var_first_use(RevGoalPathSteps, SwitchedOnVar, Cases, StaticInfo,
         CostBeforeSwitch, CostAfterSwitch, FoundFirstUse) :-
-    switch_var_first_use_2(GoalPath, 1, StaticInfo, Cases, CaseWeights,
+    switch_var_first_use_2(RevGoalPathSteps, 1, StaticInfo, Cases, CaseWeights,
         CostBeforeSwitch, CostCases, FoundFirstUseCases),
     weighted_average(CaseWeights, CostCases, CostAfterSwitch),
     Var = StaticInfo ^ fui_var,
@@ -878,36 +881,34 @@
         )
     ).
 
-:- pred switch_var_first_use_2(goal_path::in, int::in,
+:- pred switch_var_first_use_2(list(goal_path_step)::in, int::in,
     var_first_use_static_info::in(var_first_use_static_info),
     list(case_rep(T))::in, list(float)::out, float::in,
     list(float)::out, list(found_first_use)::out)
     is det <= goal_annotation_with_coverage(T).
 
 switch_var_first_use_2(_, _, _, [], [], _, [], []).
-switch_var_first_use_2(GoalPath, CaseNum, StaticInfo, [Case | Cases],
+switch_var_first_use_2(RevGoalPathSteps, CaseNum, StaticInfo, [Case | Cases],
         [Weight | Weights], Cost0, [Cost | Costs],
         [FoundFirstUse | FoundFirstUses]) :-
-    switch_var_first_use_2(GoalPath, CaseNum + 1, StaticInfo, Cases, Weights,
-        Cost0, Costs, FoundFirstUses),
-    CaseGoalPath = goal_path_add_at_end(GoalPath, step_switch(CaseNum, no)),
+    switch_var_first_use_2(RevGoalPathSteps, CaseNum + 1, StaticInfo,
+        Cases, Weights, Cost0, Costs, FoundFirstUses),
     Case = case_rep(_, _, Goal),
-    goal_var_first_use(CaseGoalPath, Goal, StaticInfo, Cost0, Cost,
-        FoundFirstUse),
+    goal_var_first_use([step_switch(CaseNum, no) | RevGoalPathSteps],
+        Goal, StaticInfo, Cost0, Cost, FoundFirstUse),
     ( get_coverage_before(get_coverage(Goal), BeforeCount) ->
         Weight = float(BeforeCount)
     ;
         unexpected($module, $pred, "unknown coverage before switch case")
     ).
 
-/* ###  Error: no clauses for predicate `ite_var_first_use'/8. */
-:- pred ite_var_first_use(goal_path::in,
+:- pred ite_var_first_use(list(goal_path_step)::in,
     goal_rep(T)::in, goal_rep(T)::in, goal_rep(T)::in,
     var_first_use_static_info::in(var_first_use_static_info),
     float::in, float::out, found_first_use::out)
     is det <= goal_annotation_with_coverage(T).
 
-ite_var_first_use(GoalPath, Cond, Then, Else, StaticInfo,
+ite_var_first_use(RevGoalPathSteps, Cond, Then, Else, StaticInfo,
         !CostSoFar, FoundFirstUse) :-
     (
         get_coverage_before(get_coverage(Then), CountBeforeThen),
@@ -918,19 +919,18 @@
         unexpected($module, $pred,
             "incomplete coverage information for if-then-else branches")
     ),
-    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),
+    RevCondGoalPathSteps = [step_ite_cond | RevGoalPathSteps],
+    RevThenGoalPathSteps = [step_ite_then | RevGoalPathSteps],
+    RevElseGoalPathSteps = [step_ite_else | RevGoalPathSteps],
     VarUseType = StaticInfo ^ fui_var_use_opts ^ vuo_var_use_type,
     CostBeforeITE = !.CostSoFar,
-    goal_var_first_use(CondGoalPath, Cond, StaticInfo,
+    goal_var_first_use(RevCondGoalPathSteps, Cond, StaticInfo,
         CostBeforeITE, CostAfterCond, CondFoundFirstUse),
-    goal_var_first_use(ThenGoalPath, Then, StaticInfo,
+    goal_var_first_use(RevThenGoalPathSteps, Then, StaticInfo,
         CostAfterCond, CostAfterThen, ThenFoundFirstUse),
-    goal_var_first_use(ElseGoalPath, Else, StaticInfo,
+    goal_var_first_use(RevElseGoalPathSteps, Else, StaticInfo,
         CostAfterCond, CostAfterElse, ElseFoundFirstUse),
-    weighted_average(Weights, [CostAfterThen, CostAfterElse],
-        CostAfterITE),
+    weighted_average(Weights, [CostAfterThen, CostAfterElse], CostAfterITE),
     !:CostSoFar = CostAfterITE,
     (
         CondFoundFirstUse = found_first_use(_),
@@ -976,7 +976,8 @@
 %----------------------------------------------------------------------------%
 
 :- pred goal_var_first_use_wrapper(clique_ptr::in, set(proc_dynamic_ptr)::in,
-    map(goal_path, cost_and_callees)::in, map(goal_path, cs_cost_csq)::in,
+    map(reverse_goal_path, cost_and_callees)::in,
+    map(reverse_goal_path, cs_cost_csq)::in,
     recursion_type::in(recursion_type_known_costs), recursion_depth::in,
     goal_rep(coverage_info)::in, float::in, var_rep::in,
     var_use_options::in, var_use_info::out) is det.
@@ -984,7 +985,7 @@
 goal_var_first_use_wrapper(CliquePtr, CallStack, CallSiteMap,
         RecursiveCallSiteMap, RT, CurDepth, Goal, ProcCost, Var,
         VarUseOptions, VarUseInfo) :-
-    goal_var_first_use(empty_goal_path, Goal,
+    goal_var_first_use([], Goal,
         var_first_use_static_info(CliquePtr, CallSiteMap, RecursiveCallSiteMap,
             Var, VarUseOptions, CallStack, RT, CurDepth),
         0.0, _Cost, FoundFirstUse),
@@ -997,8 +998,9 @@
 ].
 
 var_first_use(CliquePtr, CallSiteMap, RecursiveCallSiteMap, RT, CurDepth,
-        Goal, GoalPath, Cost, Var, VarUseOptions, VarUseInfo) :-
-    goal_var_first_use(GoalPath, Goal,
+        Goal, RevGoalPath, Cost, Var, VarUseOptions, VarUseInfo) :-
+    RevGoalPath = rgp(RevGoalPathSteps),
+    goal_var_first_use(RevGoalPathSteps, Goal,
         var_first_use_static_info(CliquePtr, CallSiteMap, RecursiveCallSiteMap,
             Var, VarUseOptions, set.init, RT, CurDepth),
         0.0, _, FoundFirstUse),
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_cairo
cvs diff: Diffing extras/graphics/mercury_cairo/samples
cvs diff: Diffing extras/graphics/mercury_cairo/samples/data
cvs diff: Diffing extras/graphics/mercury_cairo/tutorial
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/monte
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
Index: library/digraph.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/digraph.m,v
retrieving revision 1.1
diff -u -r1.1 digraph.m
--- library/digraph.m	7 Sep 2007 15:08:20 -0000	1.1
+++ library/digraph.m	5 Nov 2009 23:07:03 -0000
@@ -5,16 +5,16 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %------------------------------------------------------------------------------%
-% 
+%
 % File: digraph.m
 % Main author: bromage, petdr
 % Stability: medium
-% 
+%
 % This module defines a data type representing directed graphs.  A directed
 % graph of type digraph(T) is logically equivalent to a set of vertices of
 % type T, and a set of edges of type pair(T).  The endpoints of each edge
 % must be included in the set of vertices; cycles and loops are allowed.
-% 
+%
 %------------------------------------------------------------------------------%
 %------------------------------------------------------------------------------%
 
@@ -352,19 +352,17 @@
 
 :- type digraph(T)
     --->    digraph(
+                % Next unallocated key number.
                 next_key            :: int,
-                                        % Next unallocated key number.
 
+                % Maps vertices to their keys.
                 vertex_map          :: bimap(T, digraph_key(T)),
-                                        % Maps vertices to their keys.
 
+                % Maps each vertex to its direct successors.
                 fwd_map             :: key_set_map(T),
-                                        % Maps each vertex to its direct
-                                        % successors.
 
+                % Maps each vertex to its direct predecessors.
                 bwd_map             :: key_set_map(T)
-                                        % Maps each vertex to its direct
-                                        % predecessors.
             ).
 
 %-----------------------------------------------------------------------------%
@@ -462,8 +460,8 @@
 digraph.add_edge(X, Y, !G) :-
     X = digraph_key(XI),
     Y = digraph_key(YI),
-    !:G = !.G ^ fwd_map := key_set_map_add(!.G ^ fwd_map, XI, Y),
-    !:G = !.G ^ bwd_map := key_set_map_add(!.G ^ bwd_map, YI, X).
+    !G ^ fwd_map := key_set_map_add(!.G ^ fwd_map, XI, Y),
+    !G ^ bwd_map := key_set_map_add(!.G ^ bwd_map, YI, X).
 
 digraph.add_vertices_and_edge(VX, VY, !.G) = !:G :-
     digraph.add_vertices_and_edge(VX, VY, !G).
@@ -495,8 +493,8 @@
 digraph.delete_edge(X, Y, !G) :-
     X = digraph_key(XI),
     Y = digraph_key(YI),
-    !:G = !.G ^ fwd_map := key_set_map_delete(!.G ^ fwd_map, XI, Y),
-    !:G = !.G ^ bwd_map := key_set_map_delete(!.G ^ bwd_map, YI, X).
+    !G ^ fwd_map := key_set_map_delete(!.G ^ fwd_map, XI, Y),
+    !G ^ bwd_map := key_set_map_delete(!.G ^ bwd_map, YI, X).
 
 digraph.delete_assoc_list(Edges, !.G) = !:G :-
     digraph.delete_assoc_list(Edges, !G).
@@ -763,6 +761,7 @@
 
 %-----------------------------------------------------------------------------%
 
+digraph.is_dag(G) :-
     % Traverses the digraph depth-first, keeping track of all ancestors.
     % Fails if we encounter an ancestor during the traversal, otherwise
     % succeeds.
@@ -779,7 +778,6 @@
     %
     % (<=) If we encounter an ancestor in any traversal, then we have a cycle.
     %
-digraph.is_dag(G) :-
     digraph.keys(G, Keys),
     foldl(digraph.is_dag_2(G, []), Keys, init, _).
 
@@ -842,22 +840,21 @@
 
 %-----------------------------------------------------------------------------%
 
-    % digraph cliques
-    %   take a digraph and return the set of strongly connected
-    %   components
-    %
-    %   Works using the following algorithm:
-    %       1. Reverse the digraph ie G'
-    %       2. Traverse G in reverse depth-first order.  From the first vertex
-    %          do a DFS on G'; all vertices visited are a member of the clique.
-    %       3. From the next non-visited vertex do a DFS on G', not including
-    %          visited vertices.  This is the next clique.
-    %       4. Repeat step 3 until all vertices visited.
-
 digraph.cliques(G) = Cliques :-
     digraph.cliques(G, Cliques).
 
 digraph.cliques(G, Cliques) :-
+    % Take a digraph and return the set of strongly connected components.
+    %
+    % Works using the following algorithm:
+    % 1. Reverse the digraph.
+    % 2. Traverse G in reverse depth-first order. From the first vertex
+    %    do a DFS on the reversed G; all vertices visited are a member
+    %    of the clique.
+    % 3. From the next non-visited vertex do a DFS on the reversed G,
+    %    not including visited vertices. This is the next clique.
+    % 4. Repeat step 3 until all vertices visited.
+
     digraph.dfsrev(G, DfsRev),
     digraph.inverse(G, GInv),
     set.init(Cliques0),
@@ -870,7 +867,7 @@
 
 digraph.cliques_2([], _, _, !Cliques).
 digraph.cliques_2([X | Xs0], GInv, !.Visited, !Cliques) :-
-    % Do a DFS on G', starting from X, but not including visited vertices.
+    % Do a DFS on GInv, starting from X, but not including visited vertices.
     digraph.dfs_2(GInv, X, !Visited, [], CliqueList),
 
     % Insert the cycle into the clique set.
@@ -956,18 +953,15 @@
 
 %-----------------------------------------------------------------------------%
 
-    % digraph.atsort returns a topological sorting of the cliques in a digraph.
-    %
-    % The algorithm used is described in:
-    %
-    %   R. E. Tarjan, "Depth-first search and
-    %   linear graph algorithms,"  SIAM Journal
-    %   on Computing, 1, 2 (1972).
-
 digraph.atsort(G) = ATsort :-
     digraph.atsort(G, ATsort).
 
 digraph.atsort(G, ATsort) :-
+    % digraph.atsort returns a topological sorting of the cliques in a digraph.
+    %
+    % The algorithm used is described in R. E. Tarjan, "Depth-first search
+    % and linear graph algorithms,"  SIAM Journal on Computing, 1, 2 (1972).
+
     digraph.dfsrev(G, DfsRev),
     digraph.inverse(G, GInv),
     init(Vis),
@@ -1001,22 +995,21 @@
 
 %-----------------------------------------------------------------------------%
 
-    % digraph.tc returns the transitive closure of a digraph.
-    % We use this procedure:
-    %
-    %   - Compute the reflexive transitive closure.
-    %   - Find the "fake reflexives", that is, the set of vertices x for
-    %     which (x,x) is not an edge in G+.  This is done by noting that
-    %     G+ = G . G* (where '.' denotes composition).  Therefore x is a
-    %     fake reflexive iff there is no y such that (x,y) is an edge in G
-    %     and (y,x) is an edge in G*.
-    %   - Remove those edges from the reflexive transitive closure
-    %     computed above.
-
 digraph.tc(G) = Tc :-
     digraph.tc(G, Tc).
 
 digraph.tc(G, Tc) :-
+    % digraph.tc returns the transitive closure of a digraph.
+    % We use this procedure:
+    %
+    % - Compute the reflexive transitive closure.
+    % - Find the "fake reflexives", that is, the set of vertices x for which
+    %   (x,x) is not an edge in G+. This is done by noting that G+ = G . G*
+    %   (where '.' denotes composition). Therefore x is a fake reflexive
+    %   iff there is no y such that (x,y) is an edge in G and (y,x) is an edge
+    %   in G*.
+    % - Remove those edges from the reflexive transitive closure
+    %   computed above.
     digraph.rtc(G, Rtc),
 
     % Find the fake reflexives.
@@ -1044,6 +1037,10 @@
 
 %-----------------------------------------------------------------------------%
 
+digraph.rtc(G) = Rtc :-
+    digraph.rtc(G, Rtc).
+
+digraph.rtc(G, !:Rtc) :-
     % digraph.rtc returns the reflexive transitive closure of a digraph.
     %
     % Note: This is not the most efficient algorithm (in the sense of minimal
@@ -1056,10 +1053,6 @@
     % sorted order, compute the RTC for each element in the clique and then
     % add the appropriate edges.
 
-digraph.rtc(G) = Rtc :-
-    digraph.rtc(G, Rtc).
-
-digraph.rtc(G, !:Rtc) :-
     digraph.dfs(G, Dfs),
     init(Vis),
 
Index: library/group.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/group.m,v
retrieving revision 1.29
diff -u -r1.29 group.m
--- library/group.m	23 Nov 2007 07:35:56 -0000	1.29
+++ library/group.m	5 Nov 2009 23:53:52 -0000
@@ -5,11 +5,11 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-% 
+%
 % File: group.m.
 % Main author: conway.
 % Stability: low (obsolete).
-% 
+%
 % This module is probably not terribly useful, and it may not be supported
 % in future releases.
 %
@@ -17,7 +17,7 @@
 % A group is a set of sets of elements, where each element is unique within
 % the scope of the group. The module provides moderately efficient ways for
 % manipulating groups and elements.
-% 
+%
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -152,8 +152,8 @@
     ),
     set.to_sorted_list(S, SL),
     group.remove_elements(SL, Es0, Es),
-    !:G = !.G ^ sets := Ss,
-    !:G = !.G ^ elements := Es.
+    !G ^ sets := Ss,
+    !G ^ elements := Es.
 
 :- pred group.remove_elements(list(T)::in,
     map(T, group.key)::in, map(T, group.key)::out) is det.
Index: library/injection.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/injection.m,v
retrieving revision 1.7
diff -u -r1.7 injection.m
--- library/injection.m	23 Oct 2006 00:32:57 -0000	1.7
+++ library/injection.m	5 Nov 2009 23:23:33 -0000
@@ -5,11 +5,11 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-% 
+%
 % File: injection.m.
 % Author: mark.
 % Stability: low.
-% 
+%
 % This module provides the `injection' ADT.  An injection is like a `map'
 % (see map.m) but it allows efficient reverse lookups, similarly to `bimap'.
 % This time efficiency comes at the expense of using twice as much space
@@ -25,7 +25,7 @@
 %
 % 2) For any value V, if a reverse lookup succeeds with key K then a forward
 % lookup of key K will succeed with some value (not necessarily V).
-% 
+%
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -63,8 +63,8 @@
 :- pred injection.reverse_search(injection(K, V)::in, K::out, V::in)
     is semidet.
 
-    % Combined forward/reverse search.  (Declaratively equivalent to
-    % reverse_search.)
+    % Combined forward/reverse search.
+    % (Declaratively equivalent to reverse_search.)
     %
 :- pred injection.search(injection(K, V), K, V).
 :- mode injection.search(in, in, out) is cc_nondet.
@@ -122,8 +122,8 @@
 :- pred injection.update(injection(K, V)::in, K::in, V::in,
     injection(K, V)::out) is semidet.
 
-    % As above, but throws an exception if the key does not already
-    % exist, or if the value is already associated with a key.
+    % As above, but throws an exception if the key does not already exist,
+    % or if the value is already associated with a key.
     %
 :- func injection.det_update(injection(K, V), K, V) = injection(K, V).
 :- pred injection.det_update(injection(K, V)::in, K::in, V::in,
Index: library/pprint.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/pprint.m,v
retrieving revision 1.28
diff -u -r1.28 pprint.m
--- library/pprint.m	3 Aug 2007 05:18:38 -0000	1.28
+++ library/pprint.m	5 Nov 2009 23:34:50 -0000
@@ -5,37 +5,33 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-% 
+%
 % File: pprint.m
 % Main author: rafe
 % Stability: medium
 %
-% NOTE: this module has now been superceded by pretty_printer.m
-% which is more economical, produces better output, has better
-% control over the amount of output produced, and supports user-
-% specifiable formatting for arbitrary types.
-% 
+% NOTE: this module has now been superceded by pretty_printer.m which is
+% more economical, produces better output, has better control over
+% the amount of output produced, and supports user-specifiable formatting
+% for arbitrary types.
+%
 % ABOUT
 % -----
 %
-% This started off as pretty much a direct transliteration of Philip
-% Wadler's Haskell pretty printer described in "A Prettier Printer",
-% available at
+% This started off as pretty much a direct transliteration of Philip Wadler's
+% Haskell pretty printer described in "A Prettier Printer", available at
 % http://cm.bell-labs.com/cm/cs/who/wadler/topics/recent.html
 %
-% Several changes have been made to the algorithm to preserve linear
-% running time under a strict language and to ensure scalability to
-% extremely large terms without thrashing the VM system.
+% Several changes have been made to the algorithm to preserve linear running
+% time under a strict language and to ensure scalability to extremely large
+% terms without thrashing the VM system.
 %
 % Wadler's approach has three main advantages:
-% 1. the layout algebra is small and quite intuitive (more
-%    so than Hughes');
-% 2. the pretty printer is optimal in the sense that it will
-%    never generate output that over-runs the specified width
-%    unless that is unavoidable; and
-% 3. the pretty printer is bounded in that it never needs to
-%    look more than k characters ahead to make a formatting
-%    decision.
+% 1. the layout algebra is small and quite intuitive (more so than Hughes');
+% 2. the pretty printer is optimal in the sense that it will never generate
+%    output that over-runs the specified width unless that is unavoidable; and
+% 3. the pretty printer is bounded in that it never needs to look more than
+%    k characters ahead to make a formatting decision.
 %
 % I have made the following changes:
 %
@@ -80,26 +76,23 @@
 % USAGE
 % -----
 %
-% There are two stages in pretty printing an object of some
-% type T:
-% 1. convert the object to a pprint.doc using the
-%    constructor functions described below or by simply
-%    calling pprint.to_doc/[1,2];
-% 2. call pprint.write/[4,5] or pprint.to_string/2
-%    passing the display width and the doc.
+% There are two stages in pretty printing an object of some type T:
+% 1. convert the object to a pprint.doc using the constructor functions
+%    described below or by simply calling pprint.to_doc/[1,2];
+% 2. call pprint.write/[4,5] or pprint.to_string/2 passing the display width
+%    and the doc.
 %
 %
 % EXAMPLES
 % --------
 %
-% The doc/1 type class has types string, char, int, float and doc as
-% instances.  Hence these types can all be converted to docs by
-% applying doc/1.  This happens automatically to the arguments of ++/2.
-% Users may find it convenient to add other types as instances of the
-% doc/1 type class.
+% The doc/1 type class has types string, char, int, float and doc as instances.
+% Hence these types can all be converted to docs by applying doc/1.
+% This happens automatically to the arguments of ++/2. Users may find it
+% convenient to add other types as instances of the doc/1 type class.
 %
-% Below are some docs followed by the ways they might be
-% displayed by the pretty printer given various line widths.
+% Below are some docs followed by the ways they might be displayed by the
+% pretty printer given various line widths.
 %
 % 1. "Hello " ++ line ++ "world"
 %
@@ -151,7 +144,7 @@
 %   Look! Goodbye
 %   Look!    cruel
 %   Look!    world
-% 
+%
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -175,19 +168,18 @@
     % This typeclass can be used to simplify the construction of docs.
     %
 :- typeclass doc(T) where [
-
-        % Convert a T to a doc, placing a limit on how much of the
-        % term will be fully converted as follows:
-        %
-        % doc(_, f         ) = f
-        % doc(N, f(A, B, C)) = f/3 if N =< 0
-        % doc(N, f(A, B, C)) = some representation of the term whereby
-        %   A is converted as doc(N - 1, A),
-        %   B is converted as doc(N - 2, B), and
-        %   C is converted as doc(N - 3, C)
-        %   - if there are more than N arguments, the N+1th and subsequent
-        %     arguments should be replaced with a single ellipsis.
-        %
+    % Convert a T to a doc, placing a limit on how much of the term
+    % will be fully converted as follows:
+    %
+    % doc(_, f         ) = f
+    % doc(N, f(A, B, C)) = f/3 if N =< 0
+    % doc(N, f(A, B, C)) = some representation of the term whereby
+    %   A is converted as doc(N - 1, A),
+    %   B is converted as doc(N - 2, B), and
+    %   C is converted as doc(N - 3, C)
+    %   - if there are more than N arguments, the N+1th and subsequent
+    %     arguments should be replaced with a single ellipsis.
+    %
     func doc(int, T) = doc
 ].
 
@@ -225,40 +217,36 @@
     %
 :- func doc `<>` doc        = doc.
 
-    % The new-line document.  In a group doc (see below) the
-    % pretty printer may choose to instead `flatten' all
-    % line docs into nil docs in order to fit a doc on a
-    % single line.
+    % The newline document. In a group doc (see below) the pretty printer
+    % may choose to instead `flatten' all line docs into nil docs in order
+    % to fit a doc on a single line.
     %
 :- func line                = doc.
 
-    % Any `line' docs in the body that are not flattened out
-    % by the pretty printer are followed by the given number
-    % of spaces (nested `nest's add up).
+    % Any `line' docs in the body that are not flattened out by the
+    % pretty printer are followed by the given number of spaces
+    % (nested `nest's add up).
     %
 :- func nest(int, T)        = doc <= (doc(T)).
 
-    % Identical to a nest doc except that indentation is
-    % extended with a string label rather than some number
-    % of spaces.
+    % Identical to a nest doc except that indentation is extended with
+    % a string label rather than some number of spaces.
     %
 :- func label(string, T)    = doc <= (doc(T)).
 
-    % A group doc gives the pretty printer a choice: if
-    % the doc can be printed without line wrapping then
-    % it does so (all line, label, nest and group
-    % directives within the group are ignored); otherwise
-    % the pretty printer treats the group body literally,
-    % although nested group docs remain as choice points.
+    % A group doc gives the pretty printer a choice: if the doc can be printed
+    % without line wrapping then it does so (all line, label, nest and group
+    % directives within the group are ignored); otherwise the pretty printer
+    % treats the group body literally, although nested group docs remain as
+    % choice points.
     %
 :- func group(T)            = doc <= (doc(T)).
 
-    % This function can be used to convert strings, chars,
-    % ints and floats to their text doc equivalents.
+    % This function can be used to convert strings, chars, ints and floats
+    % to their text doc equivalents.
     %
-    % NOTE: since these types are now instances of the doc/1
-    % type class, it is simpler to just apply the doc/1
-    % method to these types.
+    % NOTE: since these types are now instances of the doc/1 type class,
+    % it is simpler to just apply the doc/1 method to these types.
     %
 :- func poly(string.poly_type) = doc.
 
@@ -284,39 +272,35 @@
     %
     % For the singleton list case, packed(Sep, [X]) = group(line `<>` X).
     %
-    % The resulting doc tries to pack as many items on a line as
-    % possible.
+    % The resulting doc tries to pack as many items on a line as possible.
     %
 :- func packed(T1, list(T2)) = doc <= (doc(T1), doc(T2)).
 
-    % A variant of the above whereby only the first N elements of
-    % the list are formatted and the rest are replaced by a single
-    % ellipsis.
+    % A variant of the above whereby only the first N elements of the list
+    % are formatted and the rest are replaced by a single ellipsis.
     %
 :- func packed(int, T1, list(T2)) = doc <= (doc(T1), doc(T2)).
 
     % packed_cs(Xs) = packed(comma_space, Xs).
     %
-    % For example, to pretty print a Mercury list of docs
-    % one might use
+    % For example, to pretty print a Mercury list of docs one might use
     %
     %   brackets(nest(2, packed_cs(Xs)))
     %
 :- func packed_cs(list(T)) = doc <= (doc(T)).
 
-    % A variant of the above whereby only the first N elements of
-    % the list are formatted and the rest are replaced by a single
-    % ellipsis.
+    % A variant of the above whereby only the first N elements of the list
+    % are formatted and the rest are replaced by a single ellipsis.
     %
 :- func packed_cs(int, list(T)) = doc <= (doc(T)).
 
-    % This is like a depth-limited version of packed_cs/1 that first
-    % calls to_doc/2 on each member of the argument list.
+    % This is like a depth-limited version of packed_cs/1 that first calls
+    % to_doc/2 on each member of the argument list.
     %
 :- func packed_cs_to_depth(int, list(T)) = doc.
 
-    % This is like a version of packed_cs_to_depth/1 that first
-    % calls univ_value/1 for each member of the argument list.
+    % This is like a version of packed_cs_to_depth/1 that first calls
+    % univ_value/1 for each member of the argument list.
     %
 :- func packed_cs_univ_args(int, list(univ)) = doc.
 
@@ -344,36 +328,35 @@
 :- func colon_space_line    = doc.
 :- func ellipsis            = doc.      % "...".
 
-    % Performs word wrapping at the end of line, taking
-    % whitespace sequences as delimiters separating words.
+    % Performs word wrapping at the end of line, taking whitespace sequences
+    % as delimiters separating words.
     %
 :- func word_wrapped(string) = doc.
 
-    % Convert arbitrary terms to docs.  This requires
-    % std_util.functor/3 to work on all components of the
-    % object being converted.  The second version places a
-    % maximum depth on terms which are otherwise truncated
-    % in the manner described in the documentation for the
-    % doc/2 method of the doc/1 type class.
+    % Convert arbitrary terms to docs. This requires std_util.functor/3 to work
+    % on all components of the object being converted. The second version
+    % places a maximum depth on terms which are otherwise truncated in the
+    % manner described in the documentation for the doc/2 method of the doc/1
+    % type class.
     %
-    % This may throw an exception or cause a runtime abort
-    % if the term in question has user-defined equality.
+    % This may throw an exception or cause a runtime abort if the term
+    % in question has user-defined equality.
     %
 :- func to_doc(T)           = doc.
 :- func to_doc(int, T)      = doc.
 
-    % Convert docs to pretty printed strings.  The int
-    % argument specifies a line width in characters.
+    % Convert docs to pretty printed strings. The int argument specifies
+    % a line width in characters.
     %
 :- func to_string(int, doc) = string.
 
-    % Write docs out in pretty printed format.  The int
-    % argument specifies a page width in characters.
+    % Write docs out in pretty printed format. The int argument specifies
+    % a page width in characters.
     %
 :- pred write(int::in, T::in, io::di, io::uo) is det <= doc(T).
 
     % Write docs to the specified string writer stream in pretty printed
-    % format.  The int argument specifies a page width in characters.
+    % format. The int argument specifies a page width in characters.
     %
 :- pred write(Stream::in, int::in, T::in, State::di, State::uo) is det
     <= ( doc(T), stream.writer(Stream, string, State) ).
@@ -406,11 +389,11 @@
     ;       'LINE'
     ;       'GROUP'(doc)
     ;       'DOC'(int, univ).
-                %
-                % 'DOC'(MaxDepth, Univ)
-                % - Univ is the object to be converted to a doc via to_doc/3,
-                %   represented as a univ.
-                % - MaxDepth is the depth limit before using ellipsis.
+            %
+            % 'DOC'(MaxDepth, Univ)
+            % - Univ is the object to be converted to a doc via to_doc/3,
+            %   represented as a univ.
+            % - MaxDepth is the depth limit before using ellipsis.
 
     % This type is used to format key-value pairs in maps when
     % using the generic to_doc/[1,2] functions.
@@ -722,56 +705,39 @@
 :- func generic_term_to_doc(depth, priority, T) = doc.
 
 generic_term_to_doc(Depth, Priority, X) = Doc :-
-
     ( if
-
     	Depth =< 0
-
       then
-
         functor(X, canonicalize, Name, Arity),
         Doc = ( if Arity = 0 then text(Name) else Name ++ "/" ++ Arity )
-
       else
-
         deconstruct(X, canonicalize, Name, _Arity, UnivArgs),
         Table = init_mercury_op_table,
         Doc =
             ( if
-
                 UnivArgs = [UnivArg],
                 lookup_prefix_op(Table, Name, OpPri, Assoc)
-
               then
-
                 maybe_parens(Priority, OpPri,
                     Name ++
                     space ++
                     univ_to_doc(Depth - 1, OpPri `adjusted_by` Assoc,
                         UnivArg)
                 )
-
               else if
-
                 UnivArgs = [UnivArg],
                 lookup_postfix_op(Table, Name, OpPri, Assoc)
-
               then
-
                 maybe_parens(Priority, OpPri,
                     univ_to_doc(Depth - 1, OpPri `adjusted_by` Assoc,
                         UnivArg) ++
                     space ++
                     Name
                 )
-
               else if
-
                 UnivArgs = [UnivArgL, UnivArgR],
                 lookup_infix_op(Table, Name, OpPri, AssocL, AssocR)
-
               then
-
                 maybe_parens(Priority, OpPri,
                     univ_to_doc(Depth - 1, OpPri `adjusted_by` AssocL,
                         UnivArgL) ++
@@ -785,14 +751,10 @@
                         )
                     )
                 )
-
               else if
-
                 UnivArgs = [UnivArgR1, UnivArgR2],
                 lookup_binary_prefix_op(Table, Name, OpPri, AssocR1, AssocR2)
-
               then
-
                 maybe_parens(Priority, OpPri,
                     Name ++
                     space ++
@@ -806,17 +768,11 @@
                         )
                     )
                 )
-
               else if
-
                 UnivArgs = []
-
               then
-
                 text(Name)
-
               else
-
                 group(
                     Name ++ parentheses(
                         nest(2, packed_cs_univ_args(Depth - 1, UnivArgs))
@@ -858,18 +814,13 @@
 :- some [T2] pred dynamic_cast_to_var(T1::in, var(T2)::out) is semidet.
 
 dynamic_cast_to_var(X, V) :-
-
-        % If X is a var then it has a type with one type argument.
-        %
+    % If X is a var then it has a type with one type argument.
     [ArgTypeDesc] = type_args(type_of(X)),
 
-        % Convert ArgTypeDesc to a type variable ArgType.
-        %
+    % Convert ArgTypeDesc to a type variable ArgType.
     (_ `with_type` ArgType) `has_type` ArgTypeDesc,
 
-        % Constrain the type of V to be var(ArgType) and do the
-        % cast.
-        %
+    % Constrain the type of V to be var(ArgType) and do the cast.
     dynamic_cast(X, V `with_type` var(ArgType)).
 
 %-----------------------------------------------------------------------------%
@@ -891,18 +842,13 @@
 :- some [T2] pred dynamic_cast_to_array(T1::in, array(T2)::out) is semidet.
 
 dynamic_cast_to_array(X, A) :-
-
-        % If X is an array then it has a type with one type argument.
-        %
+    % If X is an array then it has a type with one type argument.
     [ArgTypeDesc] = type_args(type_of(X)),
 
-        % Convert ArgTypeDesc to a type variable ArgType.
-        %
+    % Convert ArgTypeDesc to a type variable ArgType.
     (_ `with_type` ArgType) `has_type` ArgTypeDesc,
 
-        % Constrain the type of A to be array(ArgType) and do the
-        % cast.
-        %
+    % Constrain the type of A to be array(ArgType) and do the cast.
     dynamic_cast(X, A `with_type` array(ArgType)).
 
 %-----------------------------------------------------------------------------%
@@ -910,18 +856,13 @@
 :- some [T2] pred dynamic_cast_to_list(T1::in, list(T2)::out) is semidet.
 
 dynamic_cast_to_list(X, L) :-
-
-        % If X is a list then it has a type with one type argument.
-        %
+    % If X is a list then it has a type with one type argument.
     [ArgTypeDesc] = type_args(type_of(X)),
 
-        % Convert ArgTypeDesc to a type variable ArgType.
-        %
+    % Convert ArgTypeDesc to a type variable ArgType.
     (_ `with_type` ArgType) `has_type` ArgTypeDesc,
 
-        % Constrain the type of L to be list(ArgType) and do the
-        % cast.
-        %
+    % Constrain the type of L to be list(ArgType) and do the cast.
     dynamic_cast(X, L `with_type` list(ArgType)).
 
 %-----------------------------------------------------------------------------%
@@ -929,19 +870,14 @@
 :- some [T2, T3] pred dynamic_cast_to_map(T1::in, map(T2, T3)::out) is semidet.
 
 dynamic_cast_to_map(X, M) :-
-
-        % If X is a map then it has a type with two type arguments.
-        %
+    % If X is a map then it has a type with two type arguments.
     [KeyTypeDesc, ValueTypeDesc] = type_args(type_of(X)),
 
-        % Convert the TypeDescs to type variables.
-        %
+    % Convert the TypeDescs to type variables.
     (_ `with_type` KeyType) `has_type` KeyTypeDesc,
     (_ `with_type` ValueType) `has_type` ValueTypeDesc,
 
-        % Constrain the type of M to be map(KeyType, ValueType)
-        % and do the cast.
-        %
+    % Constrain the type of M to be map(KeyType, ValueType) and do the cast.
     dynamic_cast(X, M `with_type` map(KeyType, ValueType)).
 
 %-----------------------------------------------------------------------------%
@@ -950,19 +886,15 @@
     is semidet.
 
 dynamic_cast_to_map_pair(X, MP) :-
-
-        % If X is a map_pair then it has a type with two type arguments.
-        %
+    % If X is a map_pair then it has a type with two type arguments.
     [KeyTypeDesc, ValueTypeDesc] = type_args(type_of(X)),
 
-        % Convert the TypeDescs to type variables.
-        %
+    % Convert the TypeDescs to type variables.
     (_ `with_type` KeyType) `has_type` KeyTypeDesc,
     (_ `with_type` ValueType) `has_type` ValueTypeDesc,
 
-        % Constrain the type of MP to be map_pair(KeyType, ValueType)
-        % and do the cast.
-        %
+    % Constrain the type of MP to be map_pair(KeyType, ValueType)
+    % and do the cast.
     dynamic_cast(X, MP `with_type` map_pair(KeyType, ValueType)).
 
 %-----------------------------------------------------------------------------%
@@ -970,8 +902,7 @@
 :- pred dynamic_cast_to_tuple(T::in, T::out) is semidet.
 
 dynamic_cast_to_tuple(X, X) :-
-        % If X is a tuple then it's functor name is {}.
-        %
+    % If X is a tuple then it's functor name is {}.
     functor(X, canonicalize, "{}", _Arity).
 
 %-----------------------------------------------------------------------------%
@@ -980,18 +911,13 @@
 :-           mode dynamic_cast_to_robdd(in, out) is semidet.
 
 dynamic_cast_to_robdd(X, R) :-
-
-        % If X is a robdd then it has a type with one type argument.
-        %
+    % If X is a robdd then it has a type with one type argument.
     [ArgTypeDesc] = type_args(type_of(X)),
 
-        % Convert ArgTypeDesc to a type variable ArgType.
-        %
+    % Convert ArgTypeDesc to a type variable ArgType.
     (_ `with_type` ArgType) `has_type` ArgTypeDesc,
 
-        % Constrain the type of R to be robdd(ArgType) and do the
-        % cast.
-        %
+    % Constrain the type of R to be robdd(ArgType) and do the cast.
     dynamic_cast(X, R `with_type` robdd(ArgType)).
 
 %-----------------------------------------------------------------------------%
@@ -1003,7 +929,7 @@
 
 %-----------------------------------------------------------------------------%
 
-    % XXX Ideally we'd just walk the sparse bitset.  But that's an optimization
+    % XXX Ideally we'd just walk the sparse bitset. But that is an optimization
     % for another day.
     %
 :- func sparse_bitset_to_doc(int, sparse_bitset(T)) = doc <= enum(T).
Index: library/pretty_printer.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/pretty_printer.m,v
retrieving revision 1.15
diff -u -r1.15 pretty_printer.m
--- library/pretty_printer.m	23 Sep 2010 05:31:59 -0000	1.15
+++ library/pretty_printer.m	27 Sep 2010 06:20:37 -0000
@@ -5,7 +5,7 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-% 
+%
 % File: pretty_printer.m
 % Main author: rafe
 % Stability: medium
@@ -56,7 +56,7 @@
 
 :- type doc
     --->    str(string)
-            % Output a literal string.  Strings containing newlines, hard tabs,
+            % Output a literal string. Strings containing newlines, hard tabs,
             % etc. will lead to strange output.
 
     ;       nl
@@ -79,17 +79,17 @@
             % between items.
 
     ;       format_term(string, list(univ))
-            % Pretty print a term with zero or more arguments.  If the term
+            % Pretty print a term with zero or more arguments. If the term
             % corresponds to a Mercury operator it will be printed with
-            % appropriate fixity and, if necessary, in parentheses.  The term
+            % appropriate fixity and, if necessary, in parentheses. The term
             % name will be quoted and escaped if necessary.
 
     ;       format_susp((func) = doc)
             % The argument is a suspended computation used to lazily produce a
-            % doc.  If the formatting limit has been reached then just "..." is
+            % doc. If the formatting limit has been reached then just "..." is
             % output, otherwise the suspension is evaluated and the resulting
-            % doc is used.  This is useful for formatting large structures
-            % without using more resources than required.  Expanding a
+            % doc is used. This is useful for formatting large structures
+            % without using more resources than required. Expanding a
             % suspended computation reduces the formatting limit by one.
 
     ;       pp_internal(pp_internal).
@@ -98,33 +98,34 @@
 
 :- type docs == list(doc).
 
-    % This type is private to the implementation.  It cannot be exploited by
+    % This type is private to the implementation. It cannot be exploited by
     % user code.
     %
 :- type pp_internal.
 
-    % indent(IndentString, Docs)
-    %   Append IndentString to the current indentation while
-    %   printing Docs.  Indentation is printed after each newline that is
-    %   output.
+    % indent(IndentString, Docs):
+    %
+    % Append IndentString to the current indentation while printing Docs.
+    % Indentation is printed after each newline that is output.
     %
 :- func indent(string, docs) = doc.
 
     % indent(Docs) = indent("  ", Docs).
     %   A convenient abbreviation.
-    %   
+    %
 :- func indent(docs) = doc.
 
-    % group(Docs)
-    %   If Docs can be output on the remainder of the current line
-    %   by ignoring any nls in Docs, then do so.  Otherwise
-    %   nls in Docs are printed (followed by any indentation).
-    %   The formatting test is applied recursively for any subgroups in Docs.
+    % group(Docs):
+    %
+    % If Docs can be output on the remainder of the current line by ignoring
+    % any nls in Docs, then do so. Otherwise nls in Docs are printed
+    % (followed by any indentation). The formatting test is applied recursively
+    % for any subgroups in Docs.
     %
 :- func group(docs) = doc.
 
-    % format(X) = format_univ(univ(X)).
-    %   A convenient abbreviation.
+    % format(X) = format_univ(univ(X)):
+    % A convenient abbreviation.
     %
 :- func format(T) = doc.
 
@@ -169,27 +170,29 @@
     %
 :- func new_formatter_map = formatter_map.
 
-    % set_formatter(ModuleName, TypeName, TypeArity, Formatter, FMap)
-    %   Update FMap to use Formatter to format the type
-    %   ModuleName.TypeName/TypeArity.
+    % set_formatter(ModuleName, TypeName, TypeArity, Formatter, FMap):
+    %
+    % Update FMap to use Formatter to format the type
+    % ModuleName.TypeName/TypeArity.
     %
 :- func set_formatter(string, string, int, formatter, formatter_map) =
-        formatter_map.
+    formatter_map.
 
 
 
-    % format(Stream, FMap, LineWidth, MaxLines, Limit, Doc, !State).
-    %   Format Doc to fit on lines of LineWidth chars, truncating after
-    %   MaxLines lines, fomatting format_univ(_) docs using specialised
-    %   formatters Formatters starting with pretty-printer limits Limit.
+    % format(Stream, FMap, LineWidth, MaxLines, Limit, Doc, !State):
+    %
+    % Format Doc to fit on lines of LineWidth chars, truncating after
+    % MaxLines lines, fomatting format_univ(_) docs using specialised
+    % formatters Formatters starting with pretty-printer limits Limit.
     %
 :- pred write_doc_to_stream(Stream, noncanon_handling, formatter_map, int, int,
-        formatting_limit, doc, State, State)
-        <= stream.writer(Stream, string, State).
+    formatting_limit, doc, State, State)
+    <= stream.writer(Stream, string, State).
 :- mode write_doc_to_stream(in, in(canonicalize), in, in, in, in, in,
-        di, uo) is det.
+    di, uo) is det.
 :- mode write_doc_to_stream(in, in(include_details_cc), in, in, in, in, in,
-        di, uo) is cc_multi.
+    di, uo) is cc_multi.
 
     % Convenience predicates.  A user-configurable set of type-specific
     % formatters and formatting parameters are attached to the I/O state.
@@ -206,8 +209,8 @@
     % used types in the Mercury standard library (array, char, float,
     % int, map, string, etc.)
     %
-    % The default formatter_map may also be updated by 
-    % users' modules (e.g., in initialisation goals).
+    % The default formatter_map may also be updated by users' modules
+    % (e.g., in initialisation goals).
     %
     % These defaults are thread local (i.e., changes made by one thread to
     % the default formatter_map will not be visible in another thread).
@@ -215,7 +218,7 @@
 :- pred get_default_formatter_map(formatter_map::out, io::di, io::uo) is det.
 :- pred set_default_formatter_map(formatter_map::in, io::di, io::uo) is det.
 :- pred set_default_formatter(string::in, string::in, int::in, formatter::in,
-        io::di, io::uo) is det.
+    io::di, io::uo) is det.
 
     % The initial default pp_params are pp_params(78, 100, triangular(100)).
     % These defaults are thread local (i.e., changes made by one thread to
@@ -224,11 +227,12 @@
 :- pred get_default_params(pp_params::out, io::di, io::uo) is det.
 :- pred set_default_params(pp_params::in, io::di, io::uo) is det.
 
-    % write_doc(Doc, !IO)
-    % write_doc(FileStream, Doc, !IO)
-    %   Format Doc to io.stdout_stream or FileStream respectively, using
-    %   write_doc_to stream, with include_details_cc, the default
-    %   formatter_map, and the default pp_params.
+    % write_doc(Doc, !IO):
+    % write_doc(FileStream, Doc, !IO):
+    %
+    % Format Doc to io.stdout_stream or FileStream respectively, using
+    % write_doc_to stream, with include_details_cc, the default formatter_map,
+    % and the default pp_params.
     %
 :- pred write_doc(doc::in, io::di, io::uo) is det.
 :- pred write_doc(io.output_stream::in, doc::in, io::di, io::uo) is det.
@@ -300,7 +304,7 @@
 %-----------------------------------------------------------------------------%
 
 :- pred get_formatter(formatter_map::in, string::in, string::in, int::in,
-        formatter::out) is semidet.
+    formatter::out) is semidet.
 
 get_formatter(FMap, ModuleName, TypeName, Arity, Formatter) :-
     Formatter = FMap ^ elem(ModuleName) ^ elem(TypeName) ^ elem(Arity).
@@ -346,28 +350,28 @@
 %-----------------------------------------------------------------------------%
 
     % format(FMap, LineWidth, Docs, !RemainingWidth, !Indents,
-    %       !RemainingLines, !Limit, !Pri, !IO)
-    %   Format Docs to fit on LineWidth chars per line,
-    %   - tracking !RemainingWidth chars left on the current line,
-    %   - indenting by !Indents after newlines,
-    %   - truncating output after !RemainingLines,
-    %   - expanding terms to at most !Limit depth before truncating,
-    %   - tracking current operator priority !Pri.
-    %   Assumes that Docs is the output of expand.
+    %   !RemainingLines, !Limit, !Pri, !IO):
+    %
+    % Format Docs to fit on LineWidth chars per line,
+    % - tracking !RemainingWidth chars left on the current line,
+    % - indenting by !Indents after newlines,
+    % - truncating output after !RemainingLines,
+    % - expanding terms to at most !Limit depth before truncating,
+    % - tracking current operator priority !Pri.
+    % Assumes that Docs is the output of expand.
     %
 :- pred write_doc_to_stream(Stream, noncanon_handling, formatter_map, int,
-        docs, int, int, indents, indents, int, int,
-        formatting_limit, formatting_limit,
-        ops.priority, ops.priority, State, State)
-        <= stream.writer(Stream, string, State).
+    docs, int, int, indents, indents, int, int,
+    formatting_limit, formatting_limit,
+    ops.priority, ops.priority, State, State)
+    <= stream.writer(Stream, string, State).
 :- mode write_doc_to_stream(in, in(canonicalize), in, in, in,
-        in, out, in, out, in, out, in, out, in, out, di, uo) is det.
+    in, out, in, out, in, out, in, out, in, out, di, uo) is det.
 :- mode write_doc_to_stream(in, in(include_details_cc), in, in, in,
-        in, out, in, out, in, out, in, out, in, out, di, uo) is cc_multi.
+    in, out, in, out, in, out, in, out, in, out, di, uo) is cc_multi.
 
 write_doc_to_stream(_Stream, _Canonicalize, _FMap, _LineWidth, [],
         !RemainingWidth, !Indents, !RemainingLines, !Limit, !Pri, !IO).
-
 write_doc_to_stream(Stream, Canonicalize, FMap, LineWidth, [Doc | Docs0],
         !RemainingWidth, !Indents, !RemainingLines, !Limit, !Pri, !IO) :-
     ( if !.RemainingLines =< 0 then
@@ -467,26 +471,19 @@
 %-----------------------------------------------------------------------------%
 
 :- pred output_current_group(Stream::in, int::in, indents::in, int::in,
-        docs::in, docs::out, int::in, int::out, int::in, int::out,
-        State::di, State::uo)
-        is det
-        <= stream.writer(Stream, string, State).
+    docs::in, docs::out, int::in, int::out, int::in, int::out,
+    State::di, State::uo) is det <= stream.writer(Stream, string, State).
 
 output_current_group(_Stream, _LineWidth, _Indents, _OpenGroups,
         [], [], !RemainingWidth, !RemainingLines, !IO).
-
 output_current_group(Stream, LineWidth, Indents, OpenGroups,
         [Doc | Docs0], Docs, !RemainingWidth, !RemainingLines, !IO) :-
-
     ( if Doc = str(String) then
-
         stream.put(Stream, String, !IO),
         !:RemainingWidth = !.RemainingWidth - string.length(String),
         output_current_group(Stream, LineWidth, Indents, OpenGroups,
             Docs0, Docs, !RemainingWidth, !RemainingLines, !IO)
-
       else if Doc = hard_nl then
-
         format_nl(Stream, LineWidth, Indents, !:RemainingWidth,
             !RemainingLines, !IO),
         ( if !.RemainingLines =< 0 then
@@ -495,26 +492,19 @@
             output_current_group(Stream, LineWidth, Indents, OpenGroups,
                 Docs0, Docs, !RemainingWidth, !RemainingLines, !IO)
         )
-
       else if Doc = pp_internal(open_group) then
-
         output_current_group(Stream, LineWidth, Indents, OpenGroups + 1,
             Docs0, Docs, !RemainingWidth, !RemainingLines, !IO)
-
       else if Doc = pp_internal(close_group) then
-
         ( if OpenGroups = 1 then
             Docs = Docs0
           else
             output_current_group(Stream, LineWidth, Indents, OpenGroups - 1,
                 Docs0, Docs, !RemainingWidth, !RemainingLines, !IO)
         )
-
       else
-
         output_current_group(Stream, LineWidth, Indents, OpenGroups,
             Docs0, Docs, !RemainingWidth, !RemainingLines, !IO)
-
     ).
 
 %-----------------------------------------------------------------------------%
@@ -530,16 +520,15 @@
     % !R tracks the remaining line width after accounting for expansion.
     %
 :- pred expand_docs(noncanon_handling, formatter_map, docs, docs, int,
-        formatting_limit, formatting_limit, ops.priority, ops.priority,
-        int, int) is cc_multi.
+    formatting_limit, formatting_limit, ops.priority, ops.priority,
+    int, int) is cc_multi.
 :- mode expand_docs(in(canonicalize), in, in, out, in, in, out,
-        in, out, in, out) is det.
+    in, out, in, out) is det.
 :- mode expand_docs(in(include_details_cc), in, in, out, in, in, out,
-        in, out, in, out) is cc_multi.
+    in, out, in, out) is cc_multi.
 
 expand_docs(_Canonicalize, _FMap, [], [], _OpenGroups,
         !Limit, !Pri, !RemainingWidth).
-
 expand_docs(Canonicalize, FMap, [Doc | Docs0], Docs, OpenGroups,
         !Limit, !Pri, !RemainingWidth) :-
     ( if
@@ -634,9 +623,8 @@
     % Output a newline followed by indentation.
     %
 :- pred format_nl(Stream::in, int::in, indents::in, int::out,
-        int::in, int::out, State::di, State::uo)
-        is det
-        <= stream.writer(Stream, string, State).
+    int::in, int::out, State::di, State::uo) is det
+    <= stream.writer(Stream, string, State).
 
 format_nl(Stream, LineWidth, Indents, RemainingWidth, !RemainingLines, !IO) :-
     stream.put(Stream, "\n", !IO),
@@ -645,12 +633,9 @@
 
 
 :- pred output_indentation(Stream::in, indents::in, int::in, int::out,
-        State::di, State::uo)
-        is det
-        <= stream.writer(Stream, string, State).
+    State::di, State::uo) is det <= stream.writer(Stream, string, State).
 
 output_indentation(_Stream, [], !RemainingWidth, !IO).
-
 output_indentation(Stream, [Indent | Indents], !RemainingWidth, !IO) :-
     output_indentation(Stream, Indents, !RemainingWidth, !IO),
     stream.put(Stream, Indent, !IO),
@@ -659,15 +644,15 @@
 %-----------------------------------------------------------------------------%
 
     % Expand a univ into docs using the first pretty-printer in the given list
-    % that succeeds, otherwise use the generic pretty- printer.  If the
-    % pretty-printer limit has been exhausted then only "..." is produced.
+    % that succeeds, otherwise use the generic pretty- printer. If the
+    % pretty-printer limit has been exhausted, then only "..." is produced.
     %
 :- pred expand_pp(noncanon_handling, formatter_map, univ, doc,
-        formatting_limit, formatting_limit, ops.priority).
+    formatting_limit, formatting_limit, ops.priority).
 :- mode expand_pp(in(canonicalize), in, in, out, in, out, in)
-        is det.
+    is det.
 :- mode expand_pp(in(include_details_cc), in, in, out, in, out, in)
-        is cc_multi.
+    is cc_multi.
 
 expand_pp(Canonicalize, FMap, Univ, Doc, !Limit, CurrentPri) :-
     ( if
@@ -695,7 +680,7 @@
     % Expand a list of univs into docs using the given separator.
     %
 :- pred expand_format_list(list(univ)::in, doc::in, doc::out,
-        formatting_limit::in, formatting_limit::out) is det.
+    formatting_limit::in, formatting_limit::out) is det.
 
 expand_format_list([], _Sep, docs([]), !Limit).
 
@@ -748,7 +733,7 @@
 %-----------------------------------------------------------------------------%
 
 :- pred expand_format_susp(((func) = doc)::in, doc::out,
-        formatting_limit::in, formatting_limit::out) is det.
+    formatting_limit::in, formatting_limit::out) is det.
 
 expand_format_susp(Susp, Doc, !Limit) :-
     ( if limit_overrun(!.Limit) then
@@ -764,7 +749,7 @@
     % operator syntax.
     %
 :- pred expand_format_op(string::in, list(univ)::in, ops.priority::in,
-        doc::out) is semidet.
+    doc::out) is semidet.
 
 expand_format_op(Op, [Arg], CurrentPri, Docs) :-
     ( if ops.lookup_prefix_op(ops.init_mercury_op_table, Op, OpPri, Assoc) then
@@ -834,7 +819,6 @@
 
 set_formatting_limit_correctly(linear(_), Doc) =
     Doc.
-
 set_formatting_limit_correctly(Limit @ triangular(_), Doc0) =
     docs([Doc0, pp_internal(set_limit(Limit))]).
 
@@ -866,7 +850,6 @@
 
 limit_overrun(linear(N)) :-
     N =< 0.
-
 limit_overrun(triangular(N)) :-
     N =< 0.
 
@@ -877,12 +860,13 @@
 :- pred decrement_limit(formatting_limit::in, formatting_limit::out) is det.
 
 decrement_limit(linear(N), linear(N - 1)).
-
 decrement_limit(triangular(N), triangular(N - 1)).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
+%
 % Convenience predicates.
+%
 
     % This is where we keep the display parameters (line width etc.).
     % The formatter map is handled separately because it *has* to
@@ -1085,7 +1069,7 @@
 
 %-----------------------------------------------------------------------------%
 
-    % Construct the initial default formatter map.  This function
+    % Construct the initial default formatter map. This function
     % should be extended as more specialised formatters are added
     % to the standard library modules.
     %
@@ -1104,7 +1088,7 @@
 %-----------------------------------------------------------------------------%
 
 :- pred set_formatter_sv(string::in, string::in, int::in, formatter::in,
-        formatter_map::in, formatter_map::out) is det.
+    formatter_map::in, formatter_map::out) is det.
 
 set_formatter_sv(ModuleName, TypeName, Arity, Formatter, FMap0, FMap) :-
     FMap = set_formatter(ModuleName, TypeName, Arity, Formatter, FMap0).
Index: library/relation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/relation.m,v
retrieving revision 1.46
diff -u -r1.46 relation.m
--- library/relation.m	5 Aug 2010 06:55:45 -0000	1.46
+++ library/relation.m	23 Aug 2010 08:38:56 -0000
@@ -145,6 +145,9 @@
 :- pred relation.lookup_to(relation(T)::in, relation_key::in,
     set(relation_key)::out) is det.
 
+    % relation.lookup_to returns the set of elements x such that xRy,
+    % given some y.
+    %
 :- func relation.lookup_key_set_to(relation(T), relation_key)
     = relation_key_set.
 :- pred relation.lookup_key_set_to(relation(T)::in,
@@ -498,8 +501,6 @@
 relation.lookup_to(R, U, to_set(Vs)) :-
     relation.lookup_key_set_to(R, U, Vs).
 
-    % relation.lookup_to returns the set of elements
-    % x such that xRy, given some y.
 relation.lookup_key_set_to(Rel, relation_key(V), Us) :-
     Rel = relation(_Key, _ElMap, _Fwd, Bwd),
     ( map.search(Bwd, V, Us0) ->
@@ -560,8 +561,6 @@
 
 %------------------------------------------------------------------------------%
 
-    % relation.from_assoc_list turns a list of pairs of
-    % elements into a relation.
 relation.from_assoc_list(AL, Rel) :-
     relation.init_internal(Rel0),
     Rel = list.foldl(
@@ -715,10 +714,10 @@
     foldl(relation.is_dag_2(R, Visit), DomList, AllVisit, _).
 
 :- pred relation.is_dag_2(relation(T)::in, relation_key_set::in,
-    relation_key::in, relation_key_set::in, relation_key_set::out)
-    is semidet.
+    relation_key::in, relation_key_set::in, relation_key_set::out) is semidet.
 
-    % Provided that we never encounter a node that we've visited before
+relation.is_dag_2(Rel, Visit, Node, !AllVisited) :-
+    % Provided that we never encounter a node that we have visited before
     % during the current DFS, the graph isn't cyclic.
     % NB It is possible that we have visited a node before while doing a
     % DFS from another node.
@@ -729,8 +728,7 @@
     %          1
     %
     % 1 will be visited by a DFS from both 2 and 3.
-    %
-relation.is_dag_2(Rel, Visit, Node, !AllVisited) :-
+
     ( contains(Visit, Node) ->
         fail
     ; contains(!.AllVisited, Node) ->
@@ -787,18 +785,18 @@
 %------------------------------------------------------------------------------%
 
 relation.cliques(Rel, Cliques) :-
-    % Relation cliques takes a relation and returns the set of strongly
-    % connected components.
+    % relation.cliques takes a relation and returns the set of strongly
+    % connected components of that relation.
     %
     % It works using the following algorith.
-    % 1. Topologically sort the nodes.  Then number the nodes so the
-    %    highest num is the first node in the topological sort.
-    % 2. Reverse the relation, i.e. generate Rel'.
-    % 3. Starting from the highest numbered node do a DFS on Rel'.
-    %    All the nodes visited are a member of the cycle.
-    % 4. From the next highest non-visited node do a DFS on Rel'
+    % 1. Topologically sort the nodes. Then number the nodes so that
+    %    the highest number is the first node in the topological sort.
+    % 2. Compute the inverse of the relation, i.e. generate RelInv.
+    % 3. Starting from the highest numbered node, do a depth first search (DFS)
+    %    on Rel'. All the nodes visited are a member of the cycle.
+    % 4. From the next highest non-visited node do a DFS on RelInv
     %    (not including visited nodes). This is the next cycle.
-    % 5. Repeat step 4 until all nodes visited.
+    % 5. Repeat step 4 until all nodes have been visited.
 
     % Effectively assigns a numbering to the nodes.
     relation.dfsrev(Rel, DfsRev),
@@ -814,7 +812,7 @@
 
 relation.cliques_2([], _, _, !Cliques).
 relation.cliques_2([H | T0], RelInv, Visit0, !Cliques) :-
-    % Do a DFS on R'
+    % Do a DFS on RelInv.
     relation.dfs_2(RelInv, H, Visit0, Visit, [], StrongComponent),
 
     % Insert the cycle into the clique set.
@@ -896,8 +894,8 @@
 %------------------------------------------------------------------------------%
 
 relation.atsort(Rel, ATsort) :-
-    % relation.atsort returns a topological sorting
-    % of the cliques in a relation.
+    % relation.atsort returns a topological sorting of the cliques
+    % in the given relation.
     %
     % The algorithm used is described in:
     %
Index: library/term_to_xml.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/term_to_xml.m,v
retrieving revision 1.20
diff -u -r1.20 term_to_xml.m
--- library/term_to_xml.m	30 Jul 2010 13:16:47 -0000	1.20
+++ library/term_to_xml.m	23 Aug 2010 08:39:11 -0000
@@ -26,7 +26,7 @@
 % The second method is less flexible than the first, but it allows for the
 % automatic generation of a DTD.
 % Each functor in a term is given a corresponding well-formed element name in
-% the XML document according to a mapping.  Some predefined mappings are
+% the XML document according to a mapping. Some predefined mappings are
 % provided, but user defined mappings may also be used.
 %
 % Method 1 vs. Method 2
@@ -36,7 +36,7 @@
 % elements with arbitrary children and arbitrary attributes.
 % In method 2 each functor in a term can be mapped to only one XML element.
 % Method 2 also only allows a selected set of attributes.
-% In method 2 a DTD can be automatically generated.  In method 1 DTDs cannot
+% In method 2 a DTD can be automatically generated. In method 1 DTDs cannot
 % be automatically generated.
 %
 % Method 1 is useful for mapping a specific type to XML,
@@ -83,7 +83,7 @@
             )
 
     ;       data(string)
-            % Textual data.  `<', `>', `&', `'' and `"' characters
+            % Textual data. `<', `>', `&', `'' and `"' characters
             % will be replaced by `<', `>', `&', `''
             % and `"' respectively.
 
@@ -93,18 +93,18 @@
             % If it does then invalid XML will be generated.
 
     ;       comment(string)
-            % An XML comment.  The comment should not
-            % include the `<!--' and `-->'.  Any occurrences of
+            % An XML comment. The comment should not
+            % include the `<!--' and `-->'. Any occurrences of
             % the substring "--" will be replaced by " - ",
             % since "--" is not allowed in XML comments.
 
     ;       entity(string)
-            % An entity reference.  The string will
+            % An entity reference. The string will
             % have `&' prepended and `;' appended before being
             % output.
 
     ;       raw(string).
-            % Raw XML data.  The data will be written out verbatim.
+            % Raw XML data. The data will be written out verbatim.
 
     % An XML document must have an element at the top-level.
     % The following inst is used to enforce this restriction.
@@ -207,7 +207,7 @@
 %
 
     % Values of this type specify which mapping from functors to elements
-    % to use when generating XML.  The role of a mapping is twofold:
+    % to use when generating XML. The role of a mapping is twofold:
     %   1. To map functors to elements, and
     %   2. To map functors to a set of attributes that should be
     %      generated for the corresponding element.
@@ -215,17 +215,17 @@
     % We provide two predefined mappings:
     %
     %   1. simple: The functors `[]', `[|]' and `{}' are mapped to the
-    %   elements `List', `Nil' and `Tuple' respectively.  Arrays are
-    %   assigned the `Array' element.  The builtin types are assigned
-    %   the elements `Int', `String', `Float' and `Char'.  All other
+    %   elements `List', `Nil' and `Tuple' respectively. Arrays are
+    %   assigned the `Array' element. The builtin types are assigned
+    %   the elements `Int', `String', `Float' and `Char'. All other
     %   functors are assigned elements with the same name as the
     %   functor provided the functor name is well formed and does
-    %   not start with a capital letter.  Otherwise a mangled
+    %   not start with a capital letter. Otherwise a mangled
     %   version of the functor name is used.
     %
     %   All elements except `Int', `String', `Float' and `Char'
     %   will have their `functor', `arity', `type' and `field' (if
-    %   there is a field name) attributes set.  `Int', `String',
+    %   there is a field name) attributes set. `Int', `String',
     %   `Float' and `Char' elements will just have their `type' and
     %   possibly their `field' attributes set.
     %
@@ -235,15 +235,15 @@
     %
     %   2. unique: Here we use the same mapping as `simple' except
     %   we append the functor arity for discriminated unions and
-    %   a mangled version of the type name for every element.  The same
-    %   attributes as the `simple' scheme are provided.  The advantage
+    %   a mangled version of the type name for every element. The same
+    %   attributes as the `simple' scheme are provided. The advantage
     %   of this scheme is that it maps each functor to a unique
-    %   element.  This means that it will always be possible to
+    %   element. This means that it will always be possible to
     %   generate a DTD using this mapping so long as there is only
     %   one top level functor and no unsupported types can appear in
     %   terms of the type.
     %
-    % A custom mapping can be provided using the `custom' functor.  See the
+    % A custom mapping can be provided using the `custom' functor. See the
     % documentation for the element_pred type below for more information.
     %
 :- type element_mapping
@@ -257,11 +257,11 @@
     ;       custom(element_pred).
 
     % Deterministic procedures with the following signature can be used as
-    % custom functor to element mappings.  The inputs to the procedure are
+    % custom functor to element mappings. The inputs to the procedure are
     % a type and some information about a functor for that type
-    % if the type is a discriminated union.  The output should be a well
+    % if the type is a discriminated union. The output should be a well
     % formed XML element name and a list of attributes that should be set
-    % for that element.  See the types `maybe_functor_info' and
+    % for that element. See the types `maybe_functor_info' and
     % `attr_from_source' below.
     %
 :- type element_pred == (pred(type_desc, maybe_functor_info, string,
@@ -271,7 +271,7 @@
 
     % Values of this type are passed to custom functor-to-element
     % mapping predicates to tell the predicate which functor to generate
-    % an element name for if the type is a discriminated union.  If the
+    % an element name for if the type is a discriminated union. If the
     % type is not a discriminated union, then non_du is passed to
     % the predicate when requesting an element for the type.
     %
@@ -286,7 +286,7 @@
             % The type is not a discriminated union.
 
     % Values of this type specify attributes that should be set from
-    % a particular source.  The attribute_name field specifies the name
+    % a particular source. The attribute_name field specifies the name
     % of the attribute in the generated XML and the attribute_source
     % field indicates where the attribute's value should come from.
     %
@@ -317,11 +317,11 @@
 
     % To support third parties generating XML which is compatible with the
     % XML generated using method 2, a DTD for a Mercury type can also be
-    % generated.  A DTD for a given type and functor-to-element mapping may
+    % generated. A DTD for a given type and functor-to-element mapping may
     % be generated provided the following conditions hold:
     %
     %   1. If the type is a discriminated union then there must be only
-    %   one top-level functor for the type.  This is because the top
+    %   one top-level functor for the type. This is because the top
     %   level functor will be used to generate the document type name.
     %
     %   2. The functor to element mapping must map each functor to a
@@ -349,7 +349,7 @@
 
     ;       duplicate_elements(
                 % The functor-to-element mapping maps different
-                % functors to the same element.  The duplicate element
+                % functors to the same element. The duplicate element
                 % and a list of types whose functors map to that
                 % element is given.
                 duplicate_element   :: string,
@@ -377,11 +377,11 @@
     % Write Term to the given stream as an XML document using
     % ElementMapping as the scheme to map functors to elements.
     % MaybeStyleSheet and MaybeDTD specify whether or not a stylesheet
-    % reference and/or a DTD should be included.  Any non-canonical terms
-    % will be canonicalized.  If an embedded DTD is requested, but it is
+    % reference and/or a DTD should be included. Any non-canonical terms
+    % will be canonicalized. If an embedded DTD is requested, but it is
     % not possible to generate a DTD for Term using ElementMapping, then a
     % value other than `ok' is returned in DTDResult and nothing is written
-    % out.  See the dtd_generation_result type for a list of the other
+    % out. See the dtd_generation_result type for a list of the other
     % possible values of DTDResult and their meanings.
     %
 :- pred write_xml_doc_general(Stream::in, T::in,
@@ -395,11 +395,11 @@
     % Write Term to the current file output stream as an XML document using
     % ElementMapping as the scheme to map functors to elements.
     % MaybeStyleSheet and MaybeDTD specify whether or not a stylesheet
-    % reference and/or a DTD should be included.  Any non-canonical terms
-    % will be written out in full.  If an embedded DTD is requested, but
+    % reference and/or a DTD should be included. Any non-canonical terms
+    % will be written out in full. If an embedded DTD is requested, but
     % it is not possible to generate a DTD for Term using ElementMapping,
     % then a value other than `ok' is returned in DTDResult and nothing is
-    % written out.  See the dtd_generation_result type for a list of the
+    % written out. See the dtd_generation_result type for a list of the
     % other possible values of DTDResult and their meanings.
     %
 :- pred write_xml_doc_general_cc(Stream::in, T::in,
@@ -410,8 +410,8 @@
     % can_generate_dtd(ElementMapping, Type) = Result:
     %
     % Check if a DTD can be generated for the given Type using the
-    % functor-to-element mapping scheme ElementMapping.  Return `ok' if it
-    % is possible to generate a DTD.  See the documentation of the
+    % functor-to-element mapping scheme ElementMapping. Return `ok' if it
+    % is possible to generate a DTD. See the documentation of the
     % dtd_generation_result type for the meaning of the return value when
     % it is not `ok'.
     %
@@ -421,7 +421,7 @@
     % write_dtd(Stream, Term, ElementMapping, DTDResult, !State):
     %
     % Write a DTD for the given term to the current file output stream using
-    % ElementMapping to map functors to elements.  If a DTD
+    % ElementMapping to map functors to elements. If a DTD
     % cannot be generated for Term using ElementMapping then a value
     % other than `ok' is returned in DTDResult and nothing is written.
     % See the dtd_generation_result type for a list of the other
@@ -432,8 +432,7 @@
     State::di, State::uo) is det
     <= stream.writer(Stream, string, State).
 
-    % write_dtd_for_type(Stream, Type, ElementMapping, DTDResult,
-    %   !State):
+    % write_dtd_for_type(Stream, Type, ElementMapping, DTDResult, !State):
     %
     % Write a DTD for the given type to the given stream. If a
     % DTD cannot be generated for Type using ElementMapping then a value
@@ -443,8 +442,7 @@
     %
 :- pred write_dtd_from_type(Stream::in, type_desc::in,
     element_mapping::in(element_mapping), dtd_generation_result::out,
-    State::di, State::uo) is det
-    <= stream.writer(Stream, string, State).
+    State::di, State::uo) is det <= stream.writer(Stream, string, State).
 
     % write_xml_element_general(Stream, NonCanon, MakeElement, IndentLevel,
     %   Term, !State):
@@ -452,9 +450,9 @@
     % Write XML elements for the given term and all its descendents,
     % using IndentLevel as the initial indentation level (each
     % indentation level is one tab character) and using the MakeElement
-    % predicate to map functors to elements.  No <?xml ... ?>
-    % header will be written.  Non-canonical terms will be handled
-    % according to the value of NonCanon.  See the deconstruct
+    % predicate to map functors to elements. No <?xml ... ?>
+    % header will be written. Non-canonical terms will be handled
+    % according to the value of NonCanon. See the deconstruct
     % module in the standard library for more information on this argument.
     %
 :- pred write_xml_element_general(Stream, deconstruct.noncanon_handling,
@@ -710,7 +708,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Some reserved element names for the predefined mapping schemes.  Reserved
+% Some reserved element names for the predefined mapping schemes. Reserved
 % element names all start with a capital letter so as not to conflict with a
 % mangled element name.
 %
@@ -758,7 +756,7 @@
 % elements).
 %
 % If the string to be mangled begins with a capital letter then we prefix it
-% with another string reserved for this purpose.  Then we replace all
+% with another string reserved for this purpose. Then we replace all
 % characters which aren't alpha numeric or underscores with '-' followed by
 % the character code.
 %
@@ -786,9 +784,8 @@
 
 :- pred mangle_char(char::in, list(char)::in, list(char)::out) is det.
 
-    % XXX This is system dependent since char.to_int is system dependent.
-    %
 mangle_char(Chr, PrevChrs, list.append(PrevChrs, Chrs)) :-
+    % XXX This is system dependent since char.to_int is system dependent.
     (
         char.is_alnum_or_underscore(Chr)
     ->
@@ -976,10 +973,10 @@
 :- mode write_xml_element_univ(in, in, in(element_pred), in, in, in, out, di,
     uo) is cc_multi.
 
-    % Write an element and all its descendents to the current output
-    % stream.  If MaybeFields isn't empty then its head is used for the
-    % `field' attribute and the Tail is returned in
-    % RemainingMaybeFieldNames.  This is so it can be called using foldl2.
+    % Write an element and all its descendents to the current output stream.
+    % If MaybeFields isn't empty then its head is used for the `field'
+    % attribute and the Tail is returned in RemainingMaybeFieldNames.
+    % This is so it can be called using foldl2.
     %
 write_xml_element_univ(Stream, NonCanon, MakeElement, IndentLevel, Univ,
         MaybeFieldNames, RemainingMaybeFieldNames, !State) :-
@@ -1073,11 +1070,6 @@
     ).
 
 %-----------------------------------------------------------------------------%
-%
-% XXX The following is done to get around an unimplemented feature where higher
-% order terms with more than one mode can't be passed as arguments (so we can't
-% just pass write_xml_element_univ to foldl).
-%
 
 :- pred write_child_xml_elements(Stream, deconstruct.noncanon_handling,
     element_pred, int, list(univ), list(maybe(string)), State, State)
@@ -1093,6 +1085,9 @@
 
 write_child_xml_elements(Stream, NonCanon, MakeElement, IndentLevel, Args,
         MaybeFieldNames, !State) :-
+    % The switch is needed because we can't pass write_xml_element_univ
+    % to foldl, since higher order terms with more than one mode can't be
+    % passed as arguments.
     (
         NonCanon = do_not_allow,
         list.foldl2(
@@ -1145,7 +1140,7 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Predicates for writing elements
+% Predicates for writing elements.
 %
 
 :- pred indent(Stream::in, int::in, State::di, State::uo) is det
@@ -1427,8 +1422,8 @@
     ).
 
     % Write out the DTD entries for all the given types and add the written
-    % types to AlreadyDone.  Children types found along the way are added
-    % to the first argument.  We stop when all the types have had their DTD
+    % types to AlreadyDone. Children types found along the way are added
+    % to the first argument. We stop when all the types have had their DTD
     % entry written.
     %
 :- pred write_dtd_types(Stream::in, element_pred::in(element_pred),
@@ -1600,8 +1595,10 @@
                 Braces = no
             ),
 
-            AllowedFunctorsRegexs = list.map(dtd_allowed_functors_regex(MakeElement), ArgTypeList),
-            AllowedFunctorsRegex = string.join_list(",", AllowedFunctorsRegexs),
+            AllowedFunctorsRegexs = list.map(
+                dtd_allowed_functors_regex(MakeElement), ArgTypeList),
+            AllowedFunctorsRegex =
+                string.join_list(",", AllowedFunctorsRegexs),
             put(Stream, AllowedFunctorsRegex, !State),
 
             (
cvs diff: Diffing mdbcomp
Index: mdbcomp/feedback.automatic_parallelism.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/feedback.automatic_parallelism.m,v
retrieving revision 1.7
diff -u -r1.7 feedback.automatic_parallelism.m
--- mdbcomp/feedback.automatic_parallelism.m	15 Dec 2010 06:30:36 -0000	1.7
+++ mdbcomp/feedback.automatic_parallelism.m	17 Dec 2010 03:27:23 -0000
@@ -150,7 +150,7 @@
     %
 :- type candidate_par_conjunction(GoalType)
     --->    candidate_par_conjunction(
-                % The path within the procedure to this conjunuction.
+                % The path within the procedure to this conjunction.
                 cpc_goal_path           :: goal_path_string,
 
                 % The position within the original conjunction that this
Index: mdbcomp/program_representation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/program_representation.m,v
retrieving revision 1.54
diff -u -r1.54 program_representation.m
--- mdbcomp/program_representation.m	13 Dec 2010 04:31:46 -0000	1.54
+++ mdbcomp/program_representation.m	20 Dec 2010 07:20:32 -0000
@@ -457,22 +457,48 @@
 %-----------------------------------------------------------------------------%
 
 % We can think of the goal that defines a procedure to be a tree, whose leaves
-% are primitive goals and whose interior nodes are compound goals. These two
-% types describe the position of a goal in this tree. A goal_path_step type
-% says which branch to take at an interior node; the integer counts start
-% at one. (For switches, the second int, if present, gives the total number
-% of function symbols in the type of the switched-on var; for builtin types
-% such as integer and string, for which this number is effectively infinite,
-% the second number won't be present.)
+% are primitive goals and whose interior nodes are compound goals. The goal_id,
+% forward_goal_path and reverse_goal_path types describe the position of a goal
+% in this tree. Therefore value of three types can uniquely identify a goal
+% within its defining procedure.
 %
-% The goal_path type gives the sequence of steps from the root to the given
-% goal. We use a cord instead of a list because most operations on goal paths
-% focus on the last element, not the first.
+% Goal ids are allocated in a depth-first manner that guarantees the following
+% invariants:
+%
+% - the goal id of a goal representing the procedure body will be 0, and
+% - the goal id of a goal will be greater than the goal ids of all the goals
+%   that contain it.
+%
+% A goal_path_step type says which branch to take at an interior node;
+% the integer counts inside steps start at one. For switches, the second int,
+% if present, gives the total number of function symbols in the type of the
+% switched-on var. For builtin types such as integer and string, for which
+% this number is effectively infinite, the second number won't be present.
+%
+% A forward goal path lists the step from the root of the tree to the goal
+% being identified.
+%
+% A reverse goal path lists the step from to the goal being identified to
+% the root of the tree.
+%
+% The code in the compiler that allocates goal ids also returns a containing
+% goal map, which maps each goal id to the id of its innermost containing goal
+% (if there is one). When possible, new code should use this data structure,
+% though code that needs to identify goals in files outside the compiler
+% will probably continue to need to use goal paths. The string representations
+% of goal paths always list the steps in the forward order, even though
+% most operations inside the compiler use reverse goal paths, because most
+% operations on goal paths focus on the last element, not the first.
 %
-% The goal_path type is safe for use in maps and sets. However compare/3 and
-% unify/2 are faster for goal_path_string.
 
-:- type goal_path.
+:- type goal_id
+    --->    goal_id(int).
+
+:- type forward_goal_path
+    --->    fgp(list(goal_path_step)).
+
+:- type reverse_goal_path
+    --->    rgp(list(goal_path_step)).
 
 :- type goal_path_string == string.
 
@@ -485,6 +511,8 @@
     ;       step_ite_else
     ;       step_neg
     ;       step_scope(maybe_cut)
+    ;       step_lambda
+    ;       step_try
     ;       step_atomic_main
     ;       step_atomic_orelse(int)
     ;       step_first
@@ -495,71 +523,63 @@
     --->    scope_is_cut
     ;       scope_is_no_cut.
 
-    % The empty goal path.
-    %
-:- func empty_goal_path = goal_path.
-:- pred empty_goal_path(goal_path).
-:- mode empty_goal_path(out) is det.
-:- mode empty_goal_path(in) is semidet.
-
-    % A singleton goal path.
-    %
-:- func singleton_goal_path(goal_path_step) = goal_path.
+:- func whole_body_goal_id = goal_id.
 
     % Append a goal path step onto the end of a goal path.
     %
-:- func goal_path_add_at_end(goal_path, goal_path_step) = goal_path.
+:- func goal_path_add_at_end(forward_goal_path, goal_path_step) =
+    forward_goal_path.
 
-    % Remove the last item from the goal path.  This fails if the goal path is
-    % empty.
+    % Append a goal path step onto the end of a reverse goal path.
     %
-:- func goal_path_remove_last(goal_path) = goal_path is semidet.
+:- func rev_goal_path_add_at_end(reverse_goal_path, goal_path_step) =
+    reverse_goal_path.
 
     % Remove the last item from the goal path, returning it and the new
     % goal path.
     %
-:- pred goal_path_remove_last(goal_path::in, goal_path::out,
+:- pred goal_path_remove_last(forward_goal_path::in, forward_goal_path::out,
     goal_path_step::out) is semidet.
 
-    % Get the last item from the goal path.  This fails if the goal path is
-    % empty
+    % Get the last item from the goal path. This fails if the goal path is
+    % empty.
     %
-:- func goal_path_get_last(goal_path) = goal_path_step is semidet.
+:- pred goal_path_get_last(forward_goal_path::in, goal_path_step::out)
+    is semidet.
 
-    % Return the goal path represented as a list, with the outer most goal path
-    % step at the head of the list.
+    % Remove the last item from the goal path, returning it and the new
+    % goal path.
     %
-:- func goal_path_to_list(goal_path) = list(goal_path_step).
+:- pred rev_goal_path_remove_last(reverse_goal_path::in,
+    reverse_goal_path::out, goal_path_step::out) is semidet.
 
-    % Build a goal path from the given list of goal steps.  The outer most goal
-    % step should be at the head of the list.
+    % Get the last item from the goal path. This fails if the goal path is
+    % empty.
     %
-:- func list_to_goal_path(list(goal_path_step)) = goal_path.
+:- pred rev_goal_path_get_last(reverse_goal_path::in, goal_path_step::out)
+    is semidet.
 
-    % goal_path_inside(PathA, PathB):
+    % Converts a string to a forward goal path, failing if the string
+    % is not a valid goal path.
     %
-    % Succeed if PathB denotes a goal *inside* the goal denoted by PathA.
-    % (It considers a goal to be inside itself.)
-    %
-:- pred goal_path_inside(goal_path::in, goal_path::in) is semidet.
+:- pred goal_path_from_string(string::in, forward_goal_path::out) is semidet.
 
-    % goal_path_inside(PathA, PathB, Relative):
-    %
-    % As above, except that Releative denotes the same goal that PathB denotes,
-    % only from GoalA's perspective.
+    % Converts a string to a forward goal path, aborting if the string
+    % is not a valid goal path.
     %
-:- pred goal_path_inside(goal_path::in, goal_path::in, goal_path::out)
-    is semidet.
+:- pred goal_path_from_string_det(string::in, forward_goal_path::out) is det.
 
-    % Converts a string to a goal path, failing if the string is not a valid
-    % goal path.
+    % Converts a string to a reverse goal path, failing if the string
+    % is not a valid goal path.
     %
-:- pred goal_path_from_string(string::in, goal_path::out) is semidet.
+:- pred rev_goal_path_from_string(string::in, reverse_goal_path::out)
+    is semidet.
 
-    % Converts a string to a goal path, aborting if the string is not a valid
-    % goal path.
+    % Converts a string to a reverse goal path, aborting if the string
+    % is not a valid goal path.
     %
-:- pred goal_path_from_string_det(string::in, goal_path::out) is det.
+:- pred rev_goal_path_from_string_det(string::in, reverse_goal_path::out)
+    is det.
 
     % Converts a string to a goal path step, failing if the string is not
     % a valid goal path step.
@@ -569,33 +589,36 @@
     % Convert the goal path to its string representation. The resulting string
     % is guaranteed to be acceptable to path_from_string_det.
     %
-:- func goal_path_to_string(goal_path) = string.
+:- func goal_path_to_string(forward_goal_path) = string.
+
+    % Convert the goal path to its string representation. The resulting string
+    % is guaranteed to be acceptable to rev_path_from_string_det.
+    %
+:- func rev_goal_path_to_string(reverse_goal_path) = string.
 
     % Is this character the one that ends each goal path step?
     %
 :- pred is_goal_path_separator(char::in) is semidet.
 
-    % A goal path stored in order for constant time access to elements at the
-    % start of the goal path.  Recall that the start of a goal path is the root
-    % of the tree of goals.
-    %
-    % XXX: Review the name of this type and related predicates.
+    % goal_path_inside(PathA, PathB):
     %
-:- type goal_path_consable.
-
-    % Convert between a goal_path and a goal_path_consable.
+    % Succeed if PathB denotes a goal *inside* the goal denoted by PathA.
+    % (It considers a goal to be inside itself.)
     %
-:- pred goal_path_consable(goal_path, goal_path_consable).
-:- mode goal_path_consable(in, out) is det.
-:- mode goal_path_consable(out, in) is det.
+:- pred goal_path_inside(forward_goal_path::in, forward_goal_path::in)
+    is semidet.
+:- pred rev_goal_path_inside(reverse_goal_path::in, reverse_goal_path::in)
+    is semidet.
 
-    % goal_path_consable_remove_first(GP, GPHead, GPTail).
+    % goal_path_inside(PathA, PathB, RelativePath):
     %
-    % GPHead is the first goal path step in the GP, GPTail is the tail (the
-    % goals other than the first).  This predicate is false if GP is empty.
+    % As above, except that it also return RelativePath, which denotes
+    % the same goal that PathB denotes, only from GoalA's perspective.
     %
-:- pred goal_path_consable_remove_first(goal_path_consable::in,
-    goal_path_step::out, goal_path_consable::out) is semidet.
+:- pred goal_path_inside(forward_goal_path::in, forward_goal_path::in,
+    forward_goal_path::out) is semidet.
+:- pred rev_goal_path_inside(reverse_goal_path::in, reverse_goal_path::in,
+    reverse_goal_path::out) is semidet.
 
 %----------------------------------------------------------------------------%
 
@@ -743,15 +766,16 @@
                 % If cp_type is cp_type_branch_arm, the coverage point is
                 % immediately before this goal, otherwise it is immediately
                 % after.
-                goal_path,
+                reverse_goal_path,
 
                 % The type of this coverage point.
                 cp_type
             ).
 
-% This enumeration specifies the type of coverage point. A branch arm is an
-% arm of an if-then-else, switch or disj goal. The coverage_after type is used
-% to measure the coverage after the goal it's coverage point referrs to.
+    % This enumeration specifies the type of coverage point. A branch arm
+    % is an arm of an if-then-else, switch or disj goal. The coverage_after
+    % type is used to measure the coverage after the goal its coverage point
+    % refers to.
 :- type cp_type
     --->    cp_type_coverage_after
     ;       cp_type_branch_arm.
@@ -918,77 +942,76 @@
 
 %-----------------------------------------------------------------------------%
 
-    % Goal paths are stored as a list in reverse order, that is the inner most
-    % goal path step is at the head of the list.
-    %
-:- type goal_path
-    --->    goal_path(
-                gp_steps    :: list(goal_path_step)
-            ).
-
-empty_goal_path = Empty :-
-    empty_goal_path(Empty).
+whole_body_goal_id = goal_id(0).
 
-empty_goal_path(goal_path([])).
-
-singleton_goal_path(Step) = goal_path([Step]).
-
-goal_path_inside(PathA, PathB, Relative) :-
-    list.remove_suffix(PathB ^ gp_steps, PathA ^ gp_steps, RelativeSteps),
-    Relative = goal_path(RelativeSteps).
+goal_path_add_at_end(GoalPath0, GoalPathStep) = GoalPath :-
+    GoalPath0 = fgp(Steps0),
+    Steps = Steps0 ++ [GoalPathStep],
+    GoalPath = fgp(Steps).
+
+rev_goal_path_add_at_end(GoalPath0, GoalPathStep) = GoalPath :-
+    GoalPath0 = rgp(Steps0),
+    Steps = [GoalPathStep | Steps0],
+    GoalPath = rgp(Steps).
+
+goal_path_remove_last(GoalPath0, GoalPath, LastStep) :-
+    GoalPath0 = fgp(Steps0),
+    list.split_last(Steps0, Steps, LastStep),
+    GoalPath = fgp(Steps).
+
+goal_path_get_last(GoalPath, LastStep) :-
+    goal_path_remove_last(GoalPath, _, LastStep).
+
+rev_goal_path_remove_last(GoalPath0, GoalPath, LastStep) :-
+    GoalPath0 = rgp(Steps0),
+    Steps0 = [LastStep | Steps],
+    GoalPath = rgp(Steps).
+
+rev_goal_path_get_last(GoalPath, LastStep) :-
+    rev_goal_path_remove_last(GoalPath, _, LastStep).
+
+goal_path_inside(PathA, PathB, RelativePath) :-
+    PathA = fgp(StepsA),
+    PathB = fgp(StepsB),
+    list.append(StepsA, RelativeSteps, StepsB),
+    RelativePath = fgp(RelativeSteps).
+
+rev_goal_path_inside(PathA, PathB, Relative) :-
+    PathA = rgp(StepsA),
+    PathB = rgp(StepsB),
+    list.remove_suffix(StepsB, StepsA, RelativeSteps),
+    Relative = rgp(RelativeSteps).
 
 goal_path_inside(PathA, PathB) :-
     goal_path_inside(PathA, PathB, _).
 
-goal_path_add_at_end(GoalPath0, GoalPathStep) = GoalPath :-
-    goal_path_snoc(GoalPath, GoalPath0, GoalPathStep).
-
-goal_path_remove_last(GoalPath0) = GoalPath :-
-    goal_path_snoc(GoalPath0, GoalPath, _).
-
-goal_path_remove_last(GoalPath0, GoalPath, GoalPathStep) :-
-    goal_path_snoc(GoalPath0, GoalPath, GoalPathStep).
-
-goal_path_get_last(GoalPath) = Step :-
-    goal_path_snoc(GoalPath, _, Step).
-
-    % goal_path_snoc(GP, GP0, GPS) <=> GP = GP0 ++ [GPS].
-    %
-:- pred goal_path_snoc(goal_path, goal_path, goal_path_step).
-:- mode goal_path_snoc(in, out, out) is semidet.
-:- mode goal_path_snoc(out, in, in) is det.
-
-goal_path_snoc(GoalPath, GoalPath0, GoalPathStep) :-
-    GoalPath0 = goal_path(Steps0),
-    Steps = [ GoalPathStep | Steps0 ],
-    GoalPath = goal_path(Steps).
-
-goal_path_to_list(GoalPath) = List :-
-    goal_path_list(GoalPath, List).
-
-list_to_goal_path(List) = GoalPath :-
-    goal_path_list(GoalPath, List).
+rev_goal_path_inside(PathA, PathB) :-
+    rev_goal_path_inside(PathA, PathB, _).
 
-:- pred goal_path_list(goal_path, list(goal_path_step)).
-:- mode goal_path_list(in, out) is det.
-:- mode goal_path_list(out, in) is det.
-
-goal_path_list(GoalPath, StepsList) :-
-    GoalPath = goal_path(RevSteps),
-    reverse(RevSteps, StepsList).
+goal_path_from_string(GoalPathStr, GoalPath) :-
+    StepStrs = string.words_separator(is_goal_path_separator, GoalPathStr),
+    list.map(goal_path_step_from_string, StepStrs, Steps),
+    GoalPath = fgp(Steps).
 
 goal_path_from_string_det(GoalPathStr, GoalPath) :-
     ( goal_path_from_string(GoalPathStr, GoalPathPrime) ->
         GoalPath = GoalPathPrime
     ;
-        error("path_from_string_det: path_from_string failed")
+        error("path_from_string_det: goal_path_from_string failed")
     ).
 
-goal_path_from_string(GoalPathStr, GoalPath) :-
+rev_goal_path_from_string(GoalPathStr, GoalPath) :-
     StepStrs = string.words_separator(is_goal_path_separator, GoalPathStr),
-    list.map(goal_path_step_from_string, StepStrs, Steps0),
-    list.reverse(Steps0, Steps),
-    GoalPath = goal_path(Steps).
+    list.map(goal_path_step_from_string, StepStrs, Steps),
+    list.reverse(Steps, RevSteps),
+    GoalPath = rgp(RevSteps).
+
+rev_goal_path_from_string_det(GoalPathStr, GoalPath) :-
+    ( rev_goal_path_from_string(GoalPathStr, GoalPathPrime) ->
+        GoalPath = GoalPathPrime
+    ;
+        error("rev_path_from_string_det: rev_goal_path_from_string failed")
+    ).
 
 goal_path_step_from_string(String, Step) :-
     string.first_char(String, First, Rest),
@@ -1017,6 +1040,8 @@
 goal_path_step_from_string_2('~', "", step_neg).
 goal_path_step_from_string_2('q', "!", step_scope(scope_is_cut)).
 goal_path_step_from_string_2('q', "", step_scope(scope_is_no_cut)).
+goal_path_step_from_string_2('r', "", step_try).
+goal_path_step_from_string_2('=', "", step_lambda).
 goal_path_step_from_string_2('a', "", step_atomic_main).
 goal_path_step_from_string_2('o', NStr, step_atomic_orelse(N)) :-
     string.to_int(NStr, N).
@@ -1026,8 +1051,13 @@
 is_goal_path_separator(';').
 
 goal_path_to_string(GoalPath) = GoalPathStr :-
-    Steps0 = GoalPath ^ gp_steps,
-    list.reverse(Steps0, Steps),
+    GoalPath = fgp(Steps),
+    StepStrs = list.map(goal_path_step_to_string, Steps),
+    string.append_list(StepStrs, GoalPathStr).
+
+rev_goal_path_to_string(GoalPath) = GoalPathStr :-
+    GoalPath = rgp(RevSteps),
+    list.reverse(RevSteps, Steps),
     StepStrs = list.map(goal_path_step_to_string, Steps),
     string.append_list(StepStrs, GoalPathStr).
 
@@ -1045,24 +1075,14 @@
 goal_path_step_to_string(step_neg) = "~;".
 goal_path_step_to_string(step_scope(scope_is_cut)) = "q!;".
 goal_path_step_to_string(step_scope(scope_is_no_cut)) = "q;".
+goal_path_step_to_string(step_try) = "r;".
+goal_path_step_to_string(step_lambda) = "=;".
 goal_path_step_to_string(step_atomic_main) = "a;".
 goal_path_step_to_string(step_atomic_orelse(N)) =
     "o" ++ int_to_string(N) ++ ";".
 goal_path_step_to_string(step_first) = "f;".
 goal_path_step_to_string(step_later) = "l;".
 
-:- type goal_path_consable
-    --->    goal_path_consable(
-                list(goal_path_step)
-                    % The list of goal path steps is stored in-order.
-            ).
-
-goal_path_consable(goal_path(ListRev), goal_path_consable(List)) :-
-    reverse(List, ListRev).
-
-goal_path_consable_remove_first(goal_path_consable([H | T]), H,
-    goal_path_consable(T)).
-
 %-----------------------------------------------------------------------------%
 
 detism_rep(Detism) = Rep :-
@@ -1957,7 +1977,6 @@
 ").
 
 %-----------------------------------------------------------------------------%
-
 %
 % Please keep runtime/mercury_deep_profiling.h updated when modifing this
 % section.
Index: mdbcomp/rtti_access.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/rtti_access.m,v
retrieving revision 1.15
diff -u -r1.15 rtti_access.m
--- mdbcomp/rtti_access.m	30 Sep 2010 07:23:33 -0000	1.15
+++ mdbcomp/rtti_access.m	1 Oct 2010 04:02:04 -0000
@@ -225,7 +225,7 @@
 get_path_port_from_label_layout(Label) = PathPort :-
     Port = get_port_from_label_layout(Label),
     GoalPathStr = get_goal_path_from_label_layout(Label),
-    goal_path_from_string_det(GoalPathStr, GoalPath),
+    rev_goal_path_from_string_det(GoalPathStr, GoalPath),
     PathPort = make_path_port(GoalPath, Port).
 
 %-----------------------------------------------------------------------------%
Index: mdbcomp/slice_and_dice.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/slice_and_dice.m,v
retrieving revision 1.16
diff -u -r1.16 slice_and_dice.m
--- mdbcomp/slice_and_dice.m	12 Nov 2007 03:52:48 -0000	1.16
+++ mdbcomp/slice_and_dice.m	21 Mar 2010 05:13:33 -0000
@@ -906,7 +906,8 @@
 
 format_path_port(port_only(Port)) = Str :-
     mdbcomp.trace_counts.string_to_trace_port(Str, Port).
-format_path_port(path_only(Path)) = "<" ++ goal_path_to_string(Path) ++ ">".
+format_path_port(path_only(Path)) =
+    "<" ++ rev_goal_path_to_string(Path) ++ ">".
 format_path_port(port_and_path(Port, Path)) =
     format_path_port(port_only(Port)) ++ " " ++
         format_path_port(path_only(Path)).
Index: mdbcomp/trace_counts.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/trace_counts.m,v
retrieving revision 1.25
diff -u -r1.25 trace_counts.m
--- mdbcomp/trace_counts.m	15 Dec 2010 06:30:36 -0000	1.25
+++ mdbcomp/trace_counts.m	15 Dec 2010 06:33:38 -0000
@@ -75,8 +75,8 @@
 
 :- type path_port
     --->    port_only(trace_port)
-    ;       path_only(goal_path)
-    ;       port_and_path(trace_port, goal_path).
+    ;       path_only(reverse_goal_path)
+    ;       port_and_path(trace_port, reverse_goal_path).
 
 :- type line_no_and_count
     --->    line_no_and_count(
@@ -85,7 +85,7 @@
                 num_tests               :: int
             ).
 
-:- func make_path_port(goal_path, trace_port) = path_port.
+:- func make_path_port(reverse_goal_path, trace_port) = path_port.
 
 :- pred summarize_trace_counts_list(list(trace_counts)::in, trace_counts::out)
     is det.
@@ -705,14 +705,14 @@
 string_to_trace_port("LATR", port_nondet_foreign_proc_later).
 string_to_trace_port("USER", port_user).
 
-:- func string_to_goal_path(string) = goal_path is semidet.
+:- func string_to_goal_path(string) = reverse_goal_path is semidet.
 
 string_to_goal_path(String) = Path :-
     string.prefix(String, "<"),
     string.suffix(String, ">"),
     string.length(String, Length),
     string.substring(String, 1, Length-2, SubString),
-    goal_path_from_string(SubString, Path).
+    rev_goal_path_from_string(SubString, Path).
 
     % This function should be kept in sync with the MR_named_count_port array
     % in runtime/mercury_trace_base.c.
@@ -904,7 +904,7 @@
 write_path_port_count(path_only(Path),
         line_no_and_count(LineNo, ExecCount, NumTests), !IO) :-
     io.write_strings([
-        "<", goal_path_to_string(Path), "> ",
+        "<", rev_goal_path_to_string(Path), "> ",
         int_to_string(LineNo), " ",
         int_to_string(ExecCount), " ",
         int_to_string(NumTests), "\n"], !IO).
@@ -912,7 +912,7 @@
         line_no_and_count(LineNo, ExecCount, NumTests), !IO) :-
     string_to_trace_port(PortStr, Port),
     io.write_strings([
-        PortStr, " <", goal_path_to_string(Path), "> ",
+        PortStr, " <", rev_goal_path_to_string(Path), "> ",
         int_to_string(LineNo), " ",
         int_to_string(ExecCount), " ",
         int_to_string(NumTests), "\n"], !IO).
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/concurrency
cvs diff: Diffing samples/concurrency/dining_philosophers
cvs diff: Diffing samples/concurrency/midimon
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/java_interface
cvs diff: Diffing samples/java_interface/java_calls_mercury
cvs diff: Diffing samples/java_interface/mercury_calls_java
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
Index: slice/mcov.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/slice/mcov.m,v
retrieving revision 1.6
diff -u -r1.6 mcov.m
--- slice/mcov.m	12 Nov 2007 03:52:49 -0000	1.6
+++ slice/mcov.m	21 Mar 2010 05:16:05 -0000
@@ -338,10 +338,10 @@
     string_to_trace_port(PortStr, Port),
     io.write_string(PortStr, !IO).
 write_path_port_for_user(path_only(Path), !IO) :-
-    io.write_strings(["<", goal_path_to_string(Path), ">"], !IO).
+    io.write_strings(["<", rev_goal_path_to_string(Path), ">"], !IO).
 write_path_port_for_user(port_and_path(Port, Path), !IO) :-
     string_to_trace_port(PortStr, Port),
-    io.write_strings([PortStr, " <", goal_path_to_string(Path), ">"], !IO).
+    io.write_strings([PortStr, " <", rev_goal_path_to_string(Path), ">"], !IO).
 
 %-----------------------------------------------------------------------------%
 
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list