[m-rev.] for post-commit review: from_ground_term_initial

Zoltan Somogyi zs at csse.unimelb.edu.au
Wed Aug 31 17:57:32 AEST 2011


Fix a problem with from_ground_term scopes. When they are built, the scopes
are tentantively marked as from_ground_term_construct scopes, and the
unifications inside them are in a top down order. Mode analysis therefore
expected the unifications inside from_ground_term_construct scopes to have
that order.

The problem was that mode analysis, when it confirmed that a
from_ground_term scope is indeed a from_ground_term_construct scope,
itself reversed the order of the unifications, putting them in a bottom up
order. When mode analysis is reinvoked, either for unique mode checking, or
after cse_detection finds common subexpressions, this meant that
mode analysis found the unifications in the "wrong" order, and therefore
disregarded the scope, discarding all its performance benefits.

This diff separates out the two notions that we previously conflated.
The scope kind from_ground_term_construct now refers only to scopes
which are definitely known to construct ground terms. We can know that
only after mode analysis. Until then, from_ground_term scopes are now marked
as from_ground_term_initial. The two kinds have different though overlapping
sets of invariants; in particular, they promise different orderings of the
unifications in the scope.

This diff reduces the time needed to compile mas_objects.data.m
from about 221 seconds to about 8.

compiler/hlds_goal.m:
	Add the from_ground_term_initial kind. Document the invariants
	that each kind of from_ground_term scope promises.

compiler/superhomogeneous.m:
	Mark from_ground_term scopes initially as from_ground_term_initial,
	not from_ground_term_construct.

compiler/post_typecheck.m:
	Make the predicate that converts function calls that look like
	unifications (such as X = int.min) into actual function calls
	say whether it performed such a conversion.

compiler/purity.m:
	Use the new functionality in post_typecheck.m to convert
	from_ground_term_initial scopes into from_ground_term_other scopes
	if the conversion of a unification into a call means that we have to
	break an invariant expected of from_ground_term_initial scopes.

compiler/cse_detection.m:
compiler/switch_detection.m:
	Maintain the invariants we now expect of from_ground_term_deconstruct
	scopes.

compiler/modecheck_goal.m:
	Maintain the invariants we now expect of the different
	from_ground_term scopes.

	Avoid traversing such scopes if a previous invocation of mode analysis
	says we can.

	Optimize away from_ground_term_construct scopes if the variable being
	constructed is not needed later.

compiler/quantification.m:
	If the variable named in a from_ground_term_initial or
	from_ground_term_construct scope is not referred to outside the scope,
	set the nonlocals set of the scope to empty, which allows later
	compiler passes to optimize it away.

	Avoid some unnecessary work by the compiler.

compiler/add_trail_ops.m:
compiler/closure_analysis.m:
compiler/constraint.m:
compiler/dead_proc_elim.m:
compiler/deep_profile.m:
compiler/deforest.m:
compiler/delay_construct.m:
compiler/delay_partial_inst.m:
compiler/dep_par_conj.m:
compiler/dependency_graph.m:
compiler/exception_analysis.m:
compiler/follow_code.m:
compiler/follow_vars.m:
compiler/goal_form.m:
compiler/goal_util.m:
compiler/granularity.m:
compiler/inlining.m:
compiler/interval.m:
compiler/lambda.m:
compiler/lco.m:
compiler/middle_rec.m:
compiler/mode_util.m:
compiler/parallel_to_plain.m:
compiler/simplify.m:
compiler/stm_expand.m:
compiler/stratify.m:
compiler/tabling_analysis.m:
compiler/term_pass1.m:
compiler/try_expand.m:
compiler/tupling.m:
compiler/untupling.m:
compiler/unused_args.m:
	Avoid traversing from_ground_term_deconstruct scopes in cases
	where the invariants that now hold (mainly the absence of anything
	but deconstruct unifications) make such traversals unnecessary.

compiler/live_vars.m:
compiler/liveness.m:
compiler/structure_reuse.lbu.m:
	Add comments about exploiting from_ground_term_deconstruct scopes.

compiler/det_analysis.m:
compiler/hlds_out_goal.m:
compiler/polymorphism.m:
compiler/saved_vars.m:
compiler/unique_modes.m:
	Handle from_ground_term_initial scopes.

compiler/handle_options.m:
	Add a dump verbosity option that is useful for comparing HLDS dumps
	created by two different compilers.

compiler/type_util.m:
	Minor speedup.

compiler/mode_info.m:
compiler/modecheck_conj.m:
compiler/prog_data.m:
compiler/rbmm.region_transformation.m:
compiler/typecheck.m:
	Improve documentation.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/extra
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/extra
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/doc
cvs diff: Diffing boehm_gc/libatomic_ops/src
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/armcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops/tests
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/m4
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_trail_ops.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_trail_ops.m,v
retrieving revision 1.60
diff -u -b -r1.60 add_trail_ops.m
--- compiler/add_trail_ops.m	23 May 2011 05:08:00 -0000	1.60
+++ compiler/add_trail_ops.m	29 Aug 2011 15:54:50 -0000
@@ -262,7 +262,10 @@
             GoalExpr =
                 conj(plain_conj, [MarkTicketStackGoal, StoreTicketGoal, Goal3])
         ;
-            Reason = from_ground_term(_, from_ground_term_construct)
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
         ->
             % The scope has no goals that either create choice points
             % or allocate dynamic terms.
Index: compiler/closure_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/closure_analysis.m,v
retrieving revision 1.25
diff -u -b -r1.25 closure_analysis.m
--- compiler/closure_analysis.m	16 Aug 2011 03:26:29 -0000	1.25
+++ compiler/closure_analysis.m	29 Aug 2011 15:54:50 -0000
@@ -342,7 +342,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             SubGoal = SubGoal0
         ;
             process_goal(VarTypes, ModuleInfo, SubGoal0, SubGoal, !ClosureInfo)
Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.102
diff -u -b -r1.102 constraint.m
--- compiler/constraint.m	16 Aug 2011 03:26:29 -0000	1.102
+++ compiler/constraint.m	30 Aug 2011 14:37:56 -0000
@@ -184,8 +184,9 @@
         ;
             ( Reason = require_detism(_)
             ; Reason = require_complete_switch(_)
+            ; Reason = from_ground_term(_, from_ground_term_initial)
             ),
-            % These scopes should have been deleted by now.
+            % These scopes should have been deleted or converted by now.
             unexpected($module, $pred, "unexpected scope")
         ;
             Reason = from_ground_term(_, from_ground_term_construct),
@@ -730,10 +731,20 @@
     (
         goal_expr_has_subgoals(GoalExpr) = does_not_have_subgoals
     ;
-        ( GoalExpr = scope(_, SubGoal)
-        ; GoalExpr = negation(SubGoal)
-        ),
+        GoalExpr = negation(SubGoal),
+        goal_is_simple(SubGoal)
+    ;
+        GoalExpr = scope(Reason, SubGoal),
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
+            true
+        ;
         goal_is_simple(SubGoal)
+        )
     ).
 
 %-----------------------------------------------------------------------------%
Index: compiler/cse_detection.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/cse_detection.m,v
retrieving revision 1.133
diff -u -b -r1.133 cse_detection.m
--- compiler/cse_detection.m	16 Aug 2011 03:26:29 -0000	1.133
+++ compiler/cse_detection.m	30 Aug 2011 17:19:33 -0000
@@ -315,14 +315,23 @@
         detect_cse_in_goal(SubGoal0, SubGoal, !CseInfo, InstMap0, Redo),
         GoalExpr = negation(SubGoal)
     ;
-        GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        GoalExpr0 = scope(Reason0, SubGoal0),
+        ( Reason0 = from_ground_term(_, from_ground_term_construct) ->
             % There are no deconstructions at all inside these scopes.
             GoalExpr = GoalExpr0,
             Redo = no
         ;
             detect_cse_in_goal(SubGoal0, SubGoal, !CseInfo, InstMap0, Redo),
-            GoalExpr = scope(Reason, SubGoal)
+            (
+                Redo = yes,
+                Reason0 = from_ground_term(_, from_ground_term_deconstruct)
+            ->
+                % If we remove a goal from such a scope, what is left
+                % may no longer satisfy the invariants we expect it to satisfy.
+                SubGoal = hlds_goal(GoalExpr, _)
+            ;
+                GoalExpr = scope(Reason0, SubGoal)
+            )
         )
     ;
         GoalExpr0 = conj(ConjType, Goals0),
Index: compiler/dead_proc_elim.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dead_proc_elim.m,v
retrieving revision 1.141
diff -u -b -r1.141 dead_proc_elim.m
--- compiler/dead_proc_elim.m	3 May 2011 05:12:03 -0000	1.141
+++ compiler/dead_proc_elim.m	29 Aug 2011 15:54:50 -0000
@@ -480,7 +480,12 @@
         dead_proc_examine_goal(SubGoal, CurrProc, !Queue, !Needed)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % The scope has no references to procedures at all.
             true
         ;
Index: compiler/deep_profiling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/deep_profiling.m,v
retrieving revision 1.115
diff -u -b -r1.115 deep_profiling.m
--- compiler/deep_profiling.m	16 Aug 2011 03:26:30 -0000	1.115
+++ compiler/deep_profiling.m	29 Aug 2011 15:54:50 -0000
@@ -541,7 +541,12 @@
         figure_out_rec_call_numbers(SubGoal, !N, !TailCallSites)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             true
         ;
             figure_out_rec_call_numbers(SubGoal, !N, !TailCallSites)
@@ -1137,7 +1142,12 @@
                 AddForceCommit = yes
             )
         ),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % We must annotate the scope goal and its children with a default
             % deep profiling information structure, this is required by the
             % coverage profiling transformation.
Index: compiler/deforest.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/deforest.m,v
retrieving revision 1.104
diff -u -b -r1.104 deforest.m
--- compiler/deforest.m	16 Aug 2011 03:26:30 -0000	1.104
+++ compiler/deforest.m	30 Aug 2011 16:33:57 -0000
@@ -152,8 +152,7 @@
     module_info::in, module_info::out) is det.
 
 reset_inferred_proc_determinism(PredProcId, !ModuleInfo) :-
-    module_info_pred_proc_info(!.ModuleInfo, PredProcId,
-        PredInfo, ProcInfo0),
+    module_info_pred_proc_info(!.ModuleInfo, PredProcId, PredInfo, ProcInfo0),
     proc_info_get_inferred_determinism(ProcInfo0, Detism0),
     ( determinism_components(Detism0, _, at_most_many_cc) ->
         % `cc_multi' or `cc_nondet' determinisms are never inferred,
@@ -207,14 +206,11 @@
         module_info_get_globals(!.ModuleInfo, Globals),
         simplify.find_simplifications(no, Globals, Simplifications),
         pd_util.pd_simplify_goal(Simplifications, !Goal, !PDInfo),
-
         pd_util.propagate_constraints(!Goal, !PDInfo),
-
         trace [io(!IO)] (
             pd_debug_output_goal(!.PDInfo, "after constraints\n", !.Goal, !IO)
         ),
         deforest_goal(!Goal, !PDInfo),
-
         pd_info_get_proc_info(!.PDInfo, !:ProcInfo),
         proc_info_set_goal(!.Goal, !ProcInfo),
         pd_info_get_changed(!.PDInfo, Changed),
@@ -230,12 +226,10 @@
             recompute_instmap_delta(recompute_atomic_instmap_deltas, !Goal,
                 VarTypes, InstVarSet, InstMap0, !ModuleInfo),
             pd_info_set_module_info(!.ModuleInfo, !PDInfo),
-
             pd_info_get_pred_info(!.PDInfo, !:PredInfo),
             proc_info_set_goal(!.Goal, !ProcInfo),
             module_info_set_pred_proc_info(PredId, ProcId,
                 !.PredInfo, !.ProcInfo, !ModuleInfo),
-
             pd_info_get_rerun_det(!.PDInfo, RerunDet),
 
             (
@@ -349,7 +343,12 @@
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             SubGoal = SubGoal0
         ;
             deforest_goal(SubGoal0, SubGoal, !PDInfo)
Index: compiler/delay_construct.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/delay_construct.m,v
retrieving revision 1.36
diff -u -b -r1.36 delay_construct.m
--- compiler/delay_construct.m	16 Aug 2011 03:26:30 -0000	1.36
+++ compiler/delay_construct.m	29 Aug 2011 15:54:50 -0000
@@ -145,7 +145,12 @@
         Goal = hlds_goal(if_then_else(Vars, Cond, Then, Else), GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Goal = Goal0
         ;
             delay_construct_in_goal(SubGoal0, InstMap0, DelayInfo, SubGoal),
Index: compiler/delay_partial_inst.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/delay_partial_inst.m,v
retrieving revision 1.20
diff -u -b -r1.20 delay_partial_inst.m
--- compiler/delay_partial_inst.m	23 May 2011 05:08:01 -0000	1.20
+++ compiler/delay_partial_inst.m	29 Aug 2011 15:54:50 -0000
@@ -281,7 +281,12 @@
         Goal = hlds_goal(if_then_else(Vars, Cond, Then, Else), GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Goal = Goal0
         ;
             delay_partial_inst_in_goal(InstMap0, SubGoal0, SubGoal,
Index: compiler/dep_par_conj.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dep_par_conj.m,v
retrieving revision 1.57
diff -u -b -r1.57 dep_par_conj.m
--- compiler/dep_par_conj.m	16 Aug 2011 03:26:30 -0000	1.57
+++ compiler/dep_par_conj.m	29 Aug 2011 15:54:50 -0000
@@ -400,7 +400,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Goal = Goal0
         ;
             sync_dep_par_conjs_in_goal(SubGoal0, SubGoal, InstMap0, _,
@@ -829,6 +834,10 @@
                 % These scopes do not consume anything.
                 unexpected($module, $pred, "from_ground_term_construct")
             ;
+                % XXX If Reason = from_ground_term(X,
+                % from_ground_term_deconstruct), then the only variable
+                % that we can wait for is X. We should be able to use that fact
+                % to avoid processing SubGoal0.
                 insert_wait_in_goal(ModuleInfo, AllowSomePathsOnly,
                     FutureMap, ConsumedVar, WaitedOnAllSuccessPaths0,
                     SubGoal0, SubGoal, !VarSet, !VarTypes),
@@ -2575,6 +2584,10 @@
             % static data structure, its cost in execution time is negligible.
             Wait = not_seen_wait_negligible_cost_so_far
         ;
+            % XXX If Reason = from_ground_term(X,
+            % from_ground_term_deconstruct), then the only variable
+            % that we can wait for is X. We should be able to use that fact
+            % to avoid processing SubGoal.
             should_we_push_wait(Var, SubGoal, Wait)
         )
     ;
Index: compiler/dependency_graph.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dependency_graph.m,v
retrieving revision 1.109
diff -u -b -r1.109 dependency_graph.m
--- compiler/dependency_graph.m	23 May 2011 05:08:01 -0000	1.109
+++ compiler/dependency_graph.m	29 Aug 2011 15:54:50 -0000
@@ -374,7 +374,12 @@
         add_dependency_arcs_in_goal(Caller, SubGoal, !DepGraph)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % The scope references no predicates or procedures.
             true
         ;
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.233
diff -u -b -r1.233 det_analysis.m
--- compiler/det_analysis.m	17 Aug 2011 03:28:13 -0000	1.233
+++ compiler/det_analysis.m	29 Aug 2011 15:54:50 -0000
@@ -1792,6 +1792,9 @@
             det_infer_goal(Goal0, Goal, InstMap0, SolnContext,
                 RightFailingContexts, MaybePromiseEqvSolutionSets0,
                 Detism, GoalFailingContexts, !DetInfo)
+        ;
+            FromGroundTermKind = from_ground_term_initial,
+            unexpected($module, $pred, "from_ground_term_initial")
         )
     ).
 
Index: compiler/exception_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/exception_analysis.m,v
retrieving revision 1.57
diff -u -b -r1.57 exception_analysis.m
--- compiler/exception_analysis.m	23 May 2011 05:08:02 -0000	1.57
+++ compiler/exception_analysis.m	29 Aug 2011 15:54:50 -0000
@@ -434,7 +434,12 @@
         check_goal_for_exceptions(SCC, VarTypes, SubGoal, !Result, !ModuleInfo)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             true
         ;
             check_goal_for_exceptions(SCC, VarTypes, SubGoal, !Result,
Index: compiler/follow_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/follow_code.m,v
retrieving revision 1.105
diff -u -b -r1.105 follow_code.m
--- compiler/follow_code.m	16 Aug 2011 03:26:30 -0000	1.105
+++ compiler/follow_code.m	29 Aug 2011 15:54:50 -0000
@@ -136,7 +136,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             SubGoal = SubGoal0
         ;
             move_follow_code_in_goal(SubGoal0, SubGoal, RttiVarMaps, !Changed)
Index: compiler/follow_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/follow_vars.m,v
retrieving revision 1.95
diff -u -b -r1.95 follow_vars.m
--- compiler/follow_vars.m	23 May 2011 05:08:02 -0000	1.95
+++ compiler/follow_vars.m	29 Aug 2011 15:54:50 -0000
@@ -196,7 +196,12 @@
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             SubGoal = SubGoal0
         ;
             find_follow_vars_in_goal(SubGoal0, SubGoal, VarTypes, ModuleInfo,
Index: compiler/goal_form.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_form.m,v
retrieving revision 1.54
diff -u -b -r1.54 goal_form.m
--- compiler/goal_form.m	16 Aug 2011 03:26:30 -0000	1.54
+++ compiler/goal_form.m	29 Aug 2011 15:54:50 -0000
@@ -296,8 +296,14 @@
         goal_can_throw(SubGoal, Result, !ModuleInfo)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
-            % These scopes contain only construction unifications.
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
+            % These scopes contain only construction/deconstruction
+            % unifications.
             Result = cannot_throw
         ;
             goal_can_throw(SubGoal, Result, !ModuleInfo)
@@ -493,8 +499,14 @@
         CanLoop = goal_can_loop_func(MaybeModuleInfo, SubGoal)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
-            % These scopes contain only construction unifications.
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
+            % These scopes contain only construction/deconstruction
+            % unifications.
             CanLoop = no
         ;
             CanLoop = goal_can_loop_func(MaybeModuleInfo, SubGoal)
@@ -620,8 +632,14 @@
         CanThrow = goal_can_throw_func(MaybeModuleInfo, SubGoal)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
-            % These scopes contain only construction unifications.
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
+            % These scopes contain only construction/deconstruction
+            % unifications.
             CanThrow = no
         ;
             CanThrow = goal_can_throw_func(MaybeModuleInfo, SubGoal)
@@ -695,7 +713,12 @@
         IsFlat = goal_is_flat(SubGoal)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             IsFlat = yes
         ;
             IsFlat = goal_is_flat(SubGoal)
@@ -789,11 +812,17 @@
         goal_may_allocate_heap(SubGoal, May)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
-            % These scopes construct ground terms, but they construct them
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
+            % Construct scopes construct ground terms, but they construct them
             % statically, so if we modify the code above to check the
             % construct_how field of construction unifications, we could
-            % return May = no here.
+            % return May = no for them.
+            % Deconstruct scopes do not construct new ground terms.
             May = yes
         ;
             goal_may_allocate_heap(SubGoal, May)
@@ -955,8 +984,14 @@
         count_recursive_calls(SubGoal, PredId, ProcId, Min, Max)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
-            % These scopes contain only construction unifications.
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
+            % These scopes contain only construction/deconstruction
+            % unifications.
             Min = 0,
             Max = 0
         ;
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.187
diff -u -b -r1.187 goal_util.m
--- compiler/goal_util.m	16 Aug 2011 03:26:30 -0000	1.187
+++ compiler/goal_util.m	29 Aug 2011 15:54:50 -0000
@@ -880,7 +880,12 @@
         IsLeaf = proc_body_is_leaf(SubGoal)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             IsLeaf = is_leaf
         ;
             IsLeaf = proc_body_is_leaf(SubGoal)
@@ -1113,8 +1118,13 @@
 goal_expr_calls(negation(Goal), PredProcId) :-
     goal_calls(Goal, PredProcId).
 goal_expr_calls(scope(Reason, Goal), PredProcId) :-
-    ( Reason = from_ground_term(_, from_ground_term_construct) ->
-        % These goals contain only construction unifications.
+    (
+        Reason = from_ground_term(_, FGT),
+        ( FGT = from_ground_term_construct
+        ; FGT = from_ground_term_deconstruct
+        )
+    ->
+        % These goals contain only construction/deconstruction unifications.
         fail
     ;
         goal_calls(Goal, PredProcId)
@@ -1176,8 +1186,13 @@
 goal_expr_calls_pred_id(negation(Goal), PredId) :-
     goal_calls_pred_id(Goal, PredId).
 goal_expr_calls_pred_id(scope(Reason, Goal), PredId) :-
-    ( Reason = from_ground_term(_, from_ground_term_construct) ->
-        % These goals contain only construction unifications.
+    (
+        Reason = from_ground_term(_, FGT),
+        ( FGT = from_ground_term_construct
+        ; FGT = from_ground_term_deconstruct
+        )
+    ->
+        % These goals contain only construction/deconstruction unifications.
         fail
     ;
         goal_calls_pred_id(Goal, PredId)
@@ -1231,7 +1246,12 @@
         goal_calls_proc_in_list_2(Goal, PredProcIds, !CalledSet)
     ;
         GoalExpr = scope(Reason, Goal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % These goals contain only construction unifications.
             true
         ;
@@ -1291,9 +1311,15 @@
 goal_expr_contains_reconstruction(negation(Goal)) :-
     goal_contains_reconstruction(Goal).
 goal_expr_contains_reconstruction(scope(Reason, Goal)) :-
-    ( Reason = from_ground_term(_, from_ground_term_construct) ->
-        % These goals contain only construction unifications
-        % that do no reuse.
+    (
+        Reason = from_ground_term(_, FGT),
+        ( FGT = from_ground_term_construct
+        ; FGT = from_ground_term_deconstruct
+        )
+    ->
+        % Construct scopes contain only construction unifications
+        % that do no reuse. Deconstruct scopes do not contain any constructions
+        % at all.
         fail
     ;
         goal_contains_reconstruction(Goal)
@@ -1812,7 +1838,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Goal = Goal0
         ;
             SubGoal = maybe_strip_equality_pretest(SubGoal0),
Index: compiler/granularity.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/granularity.m,v
retrieving revision 1.23
diff -u -b -r1.23 granularity.m
--- compiler/granularity.m	23 May 2011 05:08:03 -0000	1.23
+++ compiler/granularity.m	29 Aug 2011 15:54:50 -0000
@@ -186,7 +186,12 @@
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             GoalExpr = GoalExpr0
         ;
             runtime_granularity_test_in_goal(SubGoal0, SubGoal, !Changed, SCC,
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.366
diff -u -b -r1.366 handle_options.m
--- compiler/handle_options.m	18 Aug 2011 06:36:16 -0000	1.366
+++ compiler/handle_options.m	30 Aug 2011 14:37:56 -0000
@@ -3060,6 +3060,7 @@
 convert_dump_alias("allD", "abcdEfgilmnprstuvzBCDMPT").
 convert_dump_alias("all", "abcdEfgilmnprstuvzBCMPSTZ").
 convert_dump_alias("most", "bcdfgilmnprstuvzP").
+convert_dump_alias("cmp", "bdfgilmnprstuvzP").
 convert_dump_alias("trans", "bcdglmnstuvz").
 convert_dump_alias("mintrans", "bcdglmnstvz").
 convert_dump_alias("codegen", "dfnprsu").
Index: compiler/higher_order.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/higher_order.m,v
retrieving revision 1.196
diff -u -b -r1.196 higher_order.m
--- compiler/higher_order.m	16 Aug 2011 03:26:30 -0000	1.196
+++ compiler/higher_order.m	29 Aug 2011 15:54:50 -0000
@@ -601,7 +601,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Goal = Goal0
         ;
             ho_traverse_goal(SubGoal0, SubGoal, !Info),
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.227
diff -u -b -r1.227 hlds_goal.m
--- compiler/hlds_goal.m	16 Aug 2011 03:26:31 -0000	1.227
+++ compiler/hlds_goal.m	30 Aug 2011 14:37:13 -0000
@@ -59,28 +59,24 @@
                 % A unification. Initially only the terms and the context
                 % are known. Mode analysis fills in the missing information.
 
+                % The variable on the left hand side of the unification.
+                % NOTE: for convenience this field is duplicated in the
+                % unification structure below.
                 unify_lhs           :: prog_var,
-                                    % The variable on the left hand side
-                                    % of the unification.  NOTE: for
-                                    % convenience this field is duplicated
-                                    % in the unification structure below.
 
+                % Whatever is on the right hand side of the unification.
                 unify_rhs           :: unify_rhs,
-                                    % Whatever is on the right hand side
-                                    % of the unification.
 
+                % The mode of the unification.
                 unify_mode          :: unify_mode,
-                                    % the mode of the unification.
 
+                % This field says what category of unification it is,
+                % and contains information specific to each category.
                 unify_kind          :: unification,
-                                    % This field says what category of
-                                    % unification it is, and contains
-                                    % information specific to each category.
 
-                unify_context       :: unify_context
-                                    % The location of the unification
-                                    % in the original source code
+                % The location of the unification in the original source code
                                     % (for use in error messages).
+                unify_context       :: unify_context
             )
 
     ;       plain_call(
@@ -89,26 +85,25 @@
                 % pred_id. Mode analysis fills in the proc_id and
                 % builtin_state fields.
 
-                call_pred_id        :: pred_id,
                                     % Which predicate are we calling?
+                call_pred_id        :: pred_id,
 
-                call_proc_id        :: proc_id,
                                     % Which mode of the predicate?
+                call_proc_id        :: proc_id,
 
-                call_args           :: list(prog_var),
                                     % The list of argument variables.
+                call_args           :: list(prog_var),
 
-                call_builtin        :: builtin_state,
                                     % Is the predicate builtin, and if yes,
                                     % do we generate inline code for it?
+                call_builtin        :: builtin_state,
 
+                % Was this predicate call originally a unification? If so,
+                % we store the context of the unification.
                 call_unify_context  :: maybe(call_unify_context),
-                                    % Was this predicate call originally
-                                    % a unification? If so, we store the
-                                    % context of the unification.
 
-                call_sym_name       :: sym_name
                                     % The name of the predicate.
+                call_sym_name       :: sym_name
             )
 
     ;       generic_call(
@@ -118,19 +113,18 @@
                 % variable, or they take higher-order arguments of variable
                 % arity. This currently includes higher-order calls and
                 % class-method calls.
-                %
+
                 gcall_details       :: generic_call,
 
-                gcall_args          :: list(prog_var),
                                     % The list of argument variables.
+                gcall_args          :: list(prog_var),
 
+                % The modes of the argument variables. For higher_order calls,
+                % this field is junk until after mode analysis.
                 gcall_modes         :: list(mer_mode),
-                                    % The modes of the argument variables.
-                                    % For higher_order calls, this field
-                                    % is junk until after mode analysis.
 
-                gcall_detism        :: determinism
                                     % The determinism of the call.
+                gcall_detism        :: determinism
             )
 
     ;       call_foreign_proc(
@@ -138,32 +132,26 @@
 
                 foreign_attr        :: pragma_foreign_proc_attributes,
 
+                % The called predicate and its mode.
                 foreign_pred_id     :: pred_id,
-                                    % The called predicate.
-
                 foreign_proc_id     :: proc_id,
-                                    % The mode of the predicate.
 
                 foreign_args        :: list(foreign_arg),
+
+                % Extra arguments added when compiler passes such as tabling
+                % stuff more code into a foreign proc than the declared
+                % interface of the called Mercury procedure would allow.
                 foreign_extra_args  :: list(foreign_arg),
-                                    % Extra arguments added when compiler
-                                    % passes such as tabling stuff more
-                                    % code into a foreign proc than the
-                                    % declared interface of the called
-                                    % Mercury procedure would allow.
 
-                foreign_trace_cond  :: maybe(trace_expr(trace_runtime)),
-                                    % If set to yes(Cond), then this goal
-                                    % represents the evaluation of the runtime
-                                    % condition of a trace goal. In that case,
-                                    % the goal must be semidet, and the
-                                    % argument lists empty; the actual code
-                                    % in pragma_foreign_code_impl is ignored
+                % If set to yes(Cond), then this goal represents the evaluation
+                % of the runtime condition of a trace goal. In that case,
+                % the goal must be semidet, and the argument lists empty;
+                % the actual code in pragma_foreign_code_impl is ignored
                                     % and replaced by the evaluation of Cond.
+                foreign_trace_cond  :: maybe(trace_expr(trace_runtime)),
 
+                % The actual code of the foreign_proc.
                 foreign_impl        :: pragma_foreign_code_impl
-                                    % Extra information for model_non
-                                    % pragma_foreign_codes; none for others.
             )
 
     ;       conj(conj_type, list(hlds_goal))
@@ -179,13 +167,12 @@
                 % Deterministic disjunctions are converted into switches
                 % by the switch detection pass.
 
-                switch_var          :: prog_var,
                                     % The variable we are switching on.
+                switch_var          :: prog_var,
 
+                % Whether or not the switch test itself can fail (i.e. whether
+                % or not it covers all the possible cases).
                 switch_canfail      :: can_fail,
-                                    % Whether or not the switch test itself
-                                    % can fail (i.e. whether or not it
-                                    % covers all the possible cases).
 
                 switch_cases        :: list(case)
             )
@@ -210,9 +197,8 @@
                 % <Vars> is over the <Condition> and the <Then> part,
                 % but not the <Else> part.
 
+                % The locally existentially quantified variables <Vars>.
                 ite_exist_vars      :: list(prog_var),
-                                    % The locally existentially quantified
-                                    % variables <Vars>.
 
                 ite_cond            :: hlds_goal,   % The <Condition>
                 ite_then            :: hlds_goal,   % The <Then> part
@@ -364,11 +350,13 @@
             ).
 
     % Each scope that is created from the expansion of a ground term above
-    % a certain size is classified into one of these three categories.
+    % a certain size is classified into one of these four categories.
     % The categories are for scopes that (a) construct a ground term, (b)
     % take an existing ground term and test whether it has a given shape, and
     % (c) everything else (perhaps some parts of the term are matched and some
-    % parts are bound, or some invariant listed below is not guaranteed).
+    % parts are bound, or some invariant listed below is not guaranteed), and
+    % (d) scopes that have not yet been classified into one of these three
+    % categories.
     %
     % Many parts of the compiler have special code for handling
     % from_ground_term_construct scopes, code that avoids scanning the code
@@ -389,34 +377,42 @@
     %    determinism says that the goal is det. The goal_info of the
     %    conjunction will be filled in similarly.
     % 4. None of the these unifications constructs a higher order value.
-    %
-    % Invariants 3 and 4 are established during mode checking, so code executed
-    % before then cannot rely on them.
-    %
-    % If any compiler pass modifies a from_ground_term_construct scope in a way
-    % that invalidates these invariants, it must set the kind field of the
-    % scope to from_ground_term_other (or from_ground_term_deconstruct).
+    % 5. The unifications are ordered such that a variable constructed by
+    %    all unifications except the last occurs exactly once, as a functor
+    %    argument of a later unification (bottom up order).
+    %
+    % From_ground_term_deconstruct scopes obey invariants 1 and 2, and they
+    % also obey invariant 6:
+    %
+    % 6. The unifications are ordered such that a variable on the LHS of
+    %    all unifications except the first occurs exactly once, as a functor
+    %    argument on the RHS of an *earlier* unification (top down order).
+    %
+    % From_ground_term_initial scopes obey invariant 1, and they obey weak
+    % forms of invariants 2 and 6. The difference is that some of the
+    % "unifications" may include things that look like function symbols
+    % but are in fact function calls. When typecheck.m discovers that this
+    % applies to a unification, it does not remove the scope or change its
+    % kind. The mode analysis pass will eventually change the kind to
+    % from_ground_term_other.
+    %
+    % Up to the first invocation of mode analysis, all from_ground_term scopes
+    % will have kind from_ground_term_initial. After that, they will have
+    % one of the three other kinds.
+    %
+    % If any later compiler pass modifies a from_ground_term_construct scope
+    % in a way that invalidates these invariants, it must set the kind field
+    % of the scope to from_ground_term_other (or from_ground_term_deconstruct).
     % If the original scope had the from_head feature, the code that does this
     % must also attach that feature to all the subgoals of the modified scope,
     % unless we can  be sure that it is executed *after* switch detection,
     % which is the only pass that looks for from_head features, and which looks
     % in all scopes *except* from_ground_term_construct scopes.
     %
-    % For now, we don't optimize from_ground_term_deconstruct and
-    % from_ground_term_other scopes, so there are no invariants required
-    % of them.
-    %
-    % There are several possible alternative designs that could allow the
-    % special-casing of from_ground_term_construct scopes. Here are two
-    % of them.
-    %
-    % One alternative is to have fourth kind, from_ground_term_initial,
-    % which would promise only the first two invariants, so compiler writers
-    % wouldn't have to worry about when a piece of code is executed if they
-    % need to depend on invariants 3 and/or 4. This works, but it leads to
-    % a slight slowdown normal code (code without big ground terms).
+    % For now, we don't optimize from_ground_term_other scopes, so there are
+    % no invariants required of them.
     %
-    % A second alternative is to have the mode checker turn any scope
+    % An alternative design would be to have the mode checker turn any scope
     % that it currently keeps as from_ground_term_construct into a new kind
     % of generic call, one which basically says "this goal binds this variable
     % to this ground term", with the ground term represented as a ground term,
@@ -432,7 +428,8 @@
     % generator.
     %
 :- type from_ground_term_kind
-    --->    from_ground_term_construct
+    --->    from_ground_term_initial
+    ;       from_ground_term_construct
     ;       from_ground_term_deconstruct
     ;       from_ground_term_other.
 
@@ -3245,7 +3242,12 @@
         HasForeign = goal_has_foreign(SubGoal)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             HasForeign = no
         ;
             HasForeign = goal_has_foreign(SubGoal)
Index: compiler/hlds_out_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out_goal.m,v
retrieving revision 1.9
diff -u -b -r1.9 hlds_out_goal.m
--- compiler/hlds_out_goal.m	16 Aug 2011 03:26:31 -0000	1.9
+++ compiler/hlds_out_goal.m	29 Aug 2011 15:54:50 -0000
@@ -1912,6 +1912,9 @@
         mercury_output_var(VarSet, AppendVarNums, Var, !IO),
         io.write_string(", ", !IO),
         (
+            Kind = from_ground_term_initial,
+            io.write_string("initial", !IO)
+        ;
             Kind = from_ground_term_construct,
             io.write_string("construct", !IO)
         ;
Index: compiler/inlining.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/inlining.m,v
retrieving revision 1.174
diff -u -b -r1.174 inlining.m
--- compiler/inlining.m	16 Aug 2011 03:26:31 -0000	1.174
+++ compiler/inlining.m	29 Aug 2011 15:54:50 -0000
@@ -353,7 +353,12 @@
         is_flat_simple_goal(Goal)
     ;
         GoalExpr = scope(Reason, Goal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % These scopes are flat and simple by construction.
             true
         ;
@@ -601,7 +606,12 @@
         GoalInfo = GoalInfo0
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % The scope has no calls to inline.
             GoalExpr = GoalExpr0,
             GoalInfo = GoalInfo0
Index: compiler/interval.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/interval.m,v
retrieving revision 1.52
diff -u -b -r1.52 interval.m
--- compiler/interval.m	21 Jul 2011 06:58:25 -0000	1.52
+++ compiler/interval.m	29 Aug 2011 15:54:50 -0000
@@ -280,6 +280,8 @@
             % the generated code will do.
             require_access([TermVar], !IntervalInfo)
         ;
+            % XXX We could treat from_ground_term_deconstruct scopes specially
+            % as well.
             build_interval_info_in_goal(SubGoal, !IntervalInfo, !Acc)
         )
     ;
@@ -967,6 +969,8 @@
             % There won't be any decisions to record.
             Goal = Goal0
         ;
+            % XXX We could treat from_ground_term_deconstruct scopes specially
+            % as well.
             record_decisions_in_goal(SubGoal0, SubGoal, !VarInfo, !VarRename,
                 InsertMap, MaybeFeature),
             GoalExpr = scope(Reason, SubGoal),
Index: compiler/lambda.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/lambda.m,v
retrieving revision 1.152
diff -u -b -r1.152 lambda.m
--- compiler/lambda.m	16 Aug 2011 03:26:31 -0000	1.152
+++ compiler/lambda.m	29 Aug 2011 15:54:50 -0000
@@ -259,9 +259,14 @@
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % If the scope had any rhs_lambda_goals, modes.m wouldn't have
-            % left its kind field as from_ground_term_construct.
+            % left its kind field as from_ground_term_(de)construct.
             GoalExpr = GoalExpr0
         ;
             expand_lambdas_in_goal(SubGoal0, SubGoal, !Info),
Index: compiler/lco.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/lco.m,v
retrieving revision 1.70
diff -u -b -r1.70 lco.m
--- compiler/lco.m	19 May 2011 16:49:10 -0000	1.70
+++ compiler/lco.m	29 Aug 2011 15:54:50 -0000
@@ -535,7 +535,12 @@
         GoalExpr = if_then_else(Vars, Cond, Then, Else)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             GoalExpr = GoalExpr0
         ;
             lco_in_goal(SubGoal0, SubGoal, !Info, ConstInfo),
@@ -1288,7 +1293,12 @@
         GoalInfo = GoalInfo0
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             GoalExpr = GoalExpr0,
             Changed = no
         ;
Index: compiler/live_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/live_vars.m,v
retrieving revision 1.148
diff -u -b -r1.148 live_vars.m
--- compiler/live_vars.m	16 Aug 2011 03:26:31 -0000	1.148
+++ compiler/live_vars.m	29 Aug 2011 15:54:50 -0000
@@ -405,6 +405,8 @@
             % !NondetLiveness, or !ParStackVars.
             set_of_var.insert(TermVar, !Liveness)
         ;
+            % XXX We could treat from_ground_term_deconstruct scopes specially
+            % as well.
             NondetLiveness0 = !.NondetLiveness,
             build_live_sets_in_goal(SubGoal0, SubGoal, ResumeVars0, AllocData,
                 !StackAlloc, !Liveness, !NondetLiveness, !ParStackVars),
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.183
diff -u -b -r1.183 liveness.m
--- compiler/liveness.m	16 Aug 2011 03:26:31 -0000	1.183
+++ compiler/liveness.m	29 Aug 2011 15:54:50 -0000
@@ -475,6 +475,8 @@
                 detect_liveness_in_construct(SubGoal0, SubGoal,
                     Liveness0, Liveness, LiveInfo, TermVar)
             ;
+                % XXX We could treat from_ground_term_deconstruct specially
+                % as well.
                 detect_liveness_in_goal(SubGoal0, SubGoal, Liveness0, Liveness,
                     LiveInfo)
             ),
@@ -802,6 +804,8 @@
             % The job on SubGoal0 was done by detect_liveness_in_goal.
             SubGoal = SubGoal0
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well.
             detect_deadness_in_goal(SubGoal0, SubGoal, !Deadness,
                 !.Liveness, LiveInfo)
         ),
@@ -1070,6 +1074,8 @@
                 set_of_var.make_singleton(TermVar), CompletedTermVars),
             set_of_var.union(CompletedTermVars, !Liveness)
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well.
             update_liveness_goal(SubGoal, LiveInfo, !Liveness)
         )
     ;
@@ -1259,6 +1265,8 @@
             % be no point in delaying their death.
             Goal = Goal0
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well.
             delay_death_goal(Goal0, Goal, !.BornVars, _, !DelayedDead, VarSet)
         ),
         !:GoalExpr = scope(Reason, Goal)
@@ -1508,6 +1516,8 @@
             % There are no resume points in these scopes.
             SubGoal = SubGoal0
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well.
             detect_resume_points_in_goal(SubGoal0, SubGoal, !Liveness,
                 LiveInfo, ResumeVars0)
         ),
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.145
diff -u -b -r1.145 middle_rec.m
--- compiler/middle_rec.m	23 May 2011 05:08:05 -0000	1.145
+++ compiler/middle_rec.m	29 Aug 2011 15:54:50 -0000
@@ -143,7 +143,12 @@
         OnlyBuiltins = contains_only_builtins(SubGoal)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             OnlyBuiltins = yes
         ;
             OnlyBuiltins = contains_only_builtins(SubGoal)
Index: compiler/mode_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_info.m,v
retrieving revision 1.105
diff -u -b -r1.105 mode_info.m
--- compiler/mode_info.m	16 Aug 2011 03:26:32 -0000	1.105
+++ compiler/mode_info.m	30 Aug 2011 16:36:19 -0000
@@ -700,8 +700,7 @@
 %-----------------------------------------------------------------------------%
 
     % We keep track of the live variables and the nondet-live variables
-    % a bag, represented as a list of sets of vars.
-    % This allows us to easily add and remove sets of variables.
+    % as two bags. This allows us to easily add and remove sets of variables.
     % It is probably not maximally efficient.
 
     % Add a set of vars to the bag of live vars and the bag of
@@ -709,7 +708,6 @@
 
 mode_info_add_live_vars(NewLiveVars, !MI) :-
     set_of_var.to_sorted_list(NewLiveVars, NewLiveVarsList),
-
     mode_info_get_live_vars(!.MI, LiveVars0),
     mode_info_get_nondet_live_vars(!.MI, NondetLiveVars0),
     bag.insert_list(NewLiveVarsList, LiveVars0, LiveVars),
@@ -722,7 +720,6 @@
 
 mode_info_remove_live_vars(OldLiveVars, !MI) :-
     set_of_var.to_sorted_list(OldLiveVars, OldLiveVarsList),
-
     mode_info_get_live_vars(!.MI, LiveVars0),
     mode_info_get_nondet_live_vars(!.MI, NondetLiveVars0),
     bag.det_remove_list(OldLiveVarsList, LiveVars0, LiveVars),
@@ -773,11 +770,11 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-    % The locked variables are stored as a stack
-    % of sets of variables.  A variable is locked if it is
-    % a member of any of the sets.  To lock a set of vars, we just
-    % push them on the stack, and to unlock a set of vars, we just
-    % pop them off the stack.  The stack is implemented as a list.
+    % The locked variables are stored as a stack of sets of variables.
+    % A variable is locked if it is a member of any of the sets.
+    % To lock a set of vars, we just push them on the stack,
+    % and to unlock a set of vars, we just pop them off the stack.
+    % The stack is implemented as a list.
 
 mode_info_lock_vars(Reason, Vars, !ModeInfo) :-
     mode_info_get_locked_vars(!.ModeInfo, LockedVars),
Index: compiler/mode_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_util.m,v
retrieving revision 1.219
diff -u -b -r1.219 mode_util.m
--- compiler/mode_util.m	16 Aug 2011 03:26:32 -0000	1.219
+++ compiler/mode_util.m	30 Aug 2011 14:37:13 -0000
@@ -1188,11 +1188,23 @@
         GoalExpr = if_then_else(Vars, Cond, Then, Else)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        ( Reason = from_ground_term(_, FGT) ->
+            (
+                ( FGT = from_ground_term_construct
+                ; FGT = from_ground_term_deconstruct
+                ),
             SubGoal = SubGoal0,
             SubGoal = hlds_goal(_, SubGoalInfo),
             InstMapDelta = goal_info_get_instmap_delta(SubGoalInfo)
         ;
+                FGT = from_ground_term_initial,
+                unexpected($module, $pred, "from_ground_term_initial")
+            ;
+                FGT = from_ground_term_other,
+                recompute_instmap_delta_1(RecomputeAtomic, SubGoal0, SubGoal,
+                    VarTypes, InstMap0, InstMapDelta, !RI)
+            )
+        ;
             recompute_instmap_delta_1(RecomputeAtomic, SubGoal0, SubGoal,
                 VarTypes, InstMap0, InstMapDelta, !RI)
         ),
Index: compiler/modecheck_conj.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modecheck_conj.m,v
retrieving revision 1.5
diff -u -b -r1.5 modecheck_conj.m
--- compiler/modecheck_conj.m	16 Aug 2011 03:26:32 -0000	1.5
+++ compiler/modecheck_conj.m	30 Aug 2011 14:37:13 -0000
@@ -522,9 +522,6 @@
         GoalExpr = conj(_ConjType, Goals),
         candidate_init_vars_2(ModeInfo, Goals, !NonFree, !CandidateVars)
     ;
-        % XXX Is the determinism field of a generic_call valid at this point?
-        % Determinism analysis is run after mode analysis.
-        %
         % We assume that generic calls are deterministic. The modes field of
         % higher_order calls is junk until *after* mode analysis, hence we
         % can't handle them here.
Index: compiler/modecheck_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modecheck_goal.m,v
retrieving revision 1.11
diff -u -b -r1.11 modecheck_goal.m
--- compiler/modecheck_goal.m	25 Aug 2011 09:49:41 -0000	1.11
+++ compiler/modecheck_goal.m	30 Aug 2011 15:42:11 -0000
@@ -518,7 +518,8 @@
             Reason = from_ground_term(TermVar, from_ground_term_construct),
             LargeFlatConstructs = set_of_var.make_singleton(TermVar)
         ;
-            ( Reason = from_ground_term(_, from_ground_term_deconstruct)
+            ( Reason = from_ground_term(_, from_ground_term_initial)
+            ; Reason = from_ground_term(_, from_ground_term_deconstruct)
             ; Reason = from_ground_term(_, from_ground_term_other)
             ; Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
@@ -593,7 +594,8 @@
                 Goal = Goal0
             )
         ;
-            ( Reason = from_ground_term(_, from_ground_term_deconstruct)
+            ( Reason = from_ground_term(_, from_ground_term_initial)
+            ; Reason = from_ground_term(_, from_ground_term_deconstruct)
             ; Reason = from_ground_term(_, from_ground_term_other)
             ; Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
@@ -810,13 +812,53 @@
         GoalExpr = scope(Reason, SubGoal),
         mode_checkpoint(exit, "scope", !ModeInfo)
     ;
-        Reason = from_ground_term(TermVar, _),
+        Reason = from_ground_term(TermVar, OldKind),
+        (
+            OldKind = from_ground_term_construct,
+            mode_info_var_is_live(!.ModeInfo, TermVar, IsLive),
+            (
+                IsLive = is_live,
+                % We have already modechecked the subgoal. If we had done
+                % anything to it that could invalidate its invariants,
+                % the part of the compiler that did this should have also
+                % updated the scope reason.
+                GoalExpr = scope(Reason, SubGoal0),
+
+                InstMapDelta0 = goal_info_get_instmap_delta(GoalInfo0),
+                instmap_delta_lookup_var(InstMapDelta0, TermVar, TermVarInst),
+                mode_info_get_instmap(!.ModeInfo, InstMap0),
+                instmap_set_var(TermVar, TermVarInst, InstMap0, InstMap),
+                mode_info_set_instmap(InstMap, !ModeInfo)
+            ;
+                IsLive = is_dead,
+                % We delete construction unifications that construct dead
+                % variables; do the same with construct scopes.
+                GoalExpr = conj(plain_conj, [])
+            )
+        ;
+            ( OldKind = from_ground_term_initial
+            ; OldKind = from_ground_term_deconstruct
+            ; OldKind = from_ground_term_other
+            ),
         mode_checkpoint(enter, "from_ground_term scope", !ModeInfo),
         modecheck_goal_from_ground_term_scope(TermVar, SubGoal0, GoalInfo0,
             MaybeKind1AndSubGoal1, !ModeInfo),
         mode_checkpoint(exit, "from_ground_term scope", !ModeInfo),
         (
             MaybeKind1AndSubGoal1 = yes(Kind1 - SubGoal1),
+                (
+                    Kind1 = from_ground_term_initial,
+                    unexpected($module, $pred, "from_ground_term_initial")
+                ;
+                    Kind1 = from_ground_term_construct,
+                    Kind2 = from_ground_term_construct
+                ;
+                    Kind1 = from_ground_term_deconstruct,
+                    Kind2 = from_ground_term_deconstruct
+                ;
+                    Kind1 = from_ground_term_other,
+                    Kind2 = from_ground_term_other
+                ),
             mode_info_set_had_from_ground_term(had_from_ground_term_scope,
                 !ModeInfo),
 
@@ -824,27 +866,27 @@
                 MakeGroundTermsUnique),
             (
                 MakeGroundTermsUnique = do_not_make_ground_terms_unique,
-                UpdatedReason1 = from_ground_term(TermVar, Kind1),
-                GoalExpr = scope(UpdatedReason1, SubGoal1)
+                    UpdatedReason2 = from_ground_term(TermVar, Kind2),
+                    GoalExpr = scope(UpdatedReason2, SubGoal1)
             ;
                 MakeGroundTermsUnique = make_ground_terms_unique,
                 (
-                    Kind1 = from_ground_term_construct,
+                        Kind2 = from_ground_term_construct,
                     modecheck_goal_make_ground_term_unique(TermVar,
                         SubGoal1, GoalInfo0, GoalExpr, !ModeInfo)
                 ;
-                    ( Kind1 = from_ground_term_deconstruct
-                    ; Kind1 = from_ground_term_other
+                        ( Kind2 = from_ground_term_deconstruct
+                        ; Kind2 = from_ground_term_other
                     ),
-                    % Do not wrap the subgoal up in a scope, since these scopes
-                    % do not get useful any special treatment.
-                    SubGoal1 = hlds_goal(GoalExpr, _)
+                        UpdatedReason2 = from_ground_term(TermVar, Kind2),
+                        GoalExpr = scope(UpdatedReason2, SubGoal1)
                 )
             )
         ;
             MaybeKind1AndSubGoal1 = no,
             GoalExpr = conj(plain_conj, [])
         )
+        )
     ;
         Reason = promise_purity(_Purity),
         mode_info_get_in_promise_purity_scope(!.ModeInfo, InPPScope),
Index: compiler/parallel_to_plain_conj.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/parallel_to_plain_conj.m,v
retrieving revision 1.4
diff -u -b -r1.4 parallel_to_plain_conj.m
--- compiler/parallel_to_plain_conj.m	23 May 2011 05:08:09 -0000	1.4
+++ compiler/parallel_to_plain_conj.m	29 Aug 2011 15:54:50 -0000
@@ -79,7 +79,12 @@
         GoalExpr = negation(SubGoal)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % There cannot be parallel conjunctions inside these scopes.
             SubGoal = SubGoal0
         ;
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.368
diff -u -b -r1.368 polymorphism.m
--- compiler/polymorphism.m	16 Aug 2011 03:26:32 -0000	1.368
+++ compiler/polymorphism.m	30 Aug 2011 16:37:49 -0000
@@ -1148,11 +1148,12 @@
             (
                 Reason0 = from_ground_term(TermVar, Kind),
                 (
-                    Kind = from_ground_term_construct,
+                    Kind = from_ground_term_initial,
                     polymorphism_process_from_ground_term(TermVar, Reason,
                         GoalInfo0, SubGoal0, SubGoal, !Info)
                 ;
-                    ( Kind = from_ground_term_deconstruct
+                    ( Kind = from_ground_term_construct
+                    ; Kind = from_ground_term_deconstruct
                     ; Kind = from_ground_term_other
                     ),
                     polymorphism_process_goal(SubGoal0, SubGoal, !Info),
@@ -1292,14 +1293,14 @@
             % If it turns out to be wrong, we would have to add a flag to
             % poly_infos that is set whenever this pass modifies a goal,
             % at least in ways that would invalidate the
-            % from_ground_term_construct invariant.
-            Reason = from_ground_term(TermVar, from_ground_term_construct),
+            % from_ground_term_initial invariant.
+            Reason = from_ground_term(TermVar, from_ground_term_initial),
             SubGoal = SubGoal1
         )
     ;
         % We did introduce some variables into the scope, so we cannot
         % guarantee that the scope still satisfies the invariants of
-        % from_ground_term_construct scopes.
+        % from_ground_term_initial scopes.
         Reason = from_ground_term(TermVar, from_ground_term_other),
         ( goal_info_has_feature(GoalInfo0, feature_from_head) ->
             attach_features_to_all_goals([feature_from_head],
Index: compiler/post_typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/post_typecheck.m,v
retrieving revision 1.153
diff -u -b -r1.153 post_typecheck.m
--- compiler/post_typecheck.m	22 Aug 2011 04:23:13 -0000	1.153
+++ compiler/post_typecheck.m	30 Aug 2011 14:37:13 -0000
@@ -107,6 +107,10 @@
     pred_info::in, module_info::in, prog_context::in,
     sym_name::in, sym_name::out, pred_id::in, pred_id::out) is det.
 
+:- type is_plain_unify
+    --->    is_not_plain_unify
+    ;       is_plain_unify.
+
     % Work out whether a var-functor unification is actually a function call.
     % If so, replace the unification goal with a call.
     %
@@ -114,7 +118,7 @@
     list(prog_var)::in, unify_mode::in, unification::in, unify_context::in,
     hlds_goal_info::in, module_info::in, pred_info::in, pred_info::out,
     vartypes::in, vartypes::out, prog_varset::in, prog_varset::out,
-    hlds_goal::out) is det.
+    hlds_goal::out, is_plain_unify::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -1023,7 +1027,8 @@
 %-----------------------------------------------------------------------------%
 
 resolve_unify_functor(X0, ConsId0, ArgVars0, Mode0, Unification0, UnifyContext,
-        GoalInfo0, ModuleInfo, !PredInfo, !VarTypes, !VarSet, Goal) :-
+        GoalInfo0, ModuleInfo, !PredInfo, !VarTypes, !VarSet,
+        Goal, IsPlainUnify) :-
     map.lookup(!.VarTypes, X0, TypeOfX),
     list.length(ArgVars0, Arity),
     (
@@ -1050,7 +1055,8 @@
         HOCall = generic_call(
             higher_order(FuncVar, Purity, pf_function, FullArity),
             ArgVars, Modes, Det),
-        Goal = hlds_goal(HOCall, GoalInfo0)
+        Goal = hlds_goal(HOCall, GoalInfo0),
+        IsPlainUnify = is_not_plain_unify
     ;
         % Is the function symbol a user-defined function, rather than
         % a functor which represents a data constructor?
@@ -1104,7 +1110,8 @@
             rhs_functor(ConsId0, no, ArgVars0), UnifyContext),
         FuncCall = plain_call(PredId, ProcId, ArgVars, not_builtin,
             yes(FuncCallUnifyContext), QualifiedFuncName),
-        Goal = hlds_goal(FuncCall, GoalInfo0)
+        Goal = hlds_goal(FuncCall, GoalInfo0),
+        IsPlainUnify = is_not_plain_unify
     ;
         % Is the function symbol a higher-order predicate or function constant?
         ConsId0 = cons(Name, _, _),
@@ -1146,7 +1153,8 @@
         ConsId = closure_cons(ShroudedPredProcId, EvalMethod),
         GoalExpr = unify(X0, rhs_functor(ConsId, no, ArgVars0), Mode0,
             Unification0, UnifyContext),
-        Goal = hlds_goal(GoalExpr, GoalInfo0)
+        Goal = hlds_goal(GoalExpr, GoalInfo0),
+        IsPlainUnify = is_not_plain_unify
     ;
         % Is it a call to an automatically generated field access function.
         % This test must come after the tests for function calls and
@@ -1171,7 +1179,9 @@
             TypeOfX, ArgTypes0)
     ->
         finish_field_access_function(ModuleInfo, !PredInfo, !VarTypes, !VarSet,
-            AccessType, FieldName, UnifyContext, X0, ArgVars0, GoalInfo0, Goal)
+            AccessType, FieldName, UnifyContext, X0, ArgVars0, GoalInfo0,
+            Goal),
+        IsPlainUnify = is_not_plain_unify
     ;
         % Module qualify ordinary construction/deconstruction unifications.
         type_to_ctor_det(TypeOfX, TypeCtorOfX),
@@ -1207,7 +1217,8 @@
         ),
         GoalExpr = unify(X0, rhs_functor(ConsId, no, ArgVars0), Mode0,
             Unification0, UnifyContext),
-        Goal = hlds_goal(GoalExpr, GoalInfo0)
+        Goal = hlds_goal(GoalExpr, GoalInfo0),
+        IsPlainUnify = is_plain_unify
     ).
 
 %-----------------------------------------------------------------------------%
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.233
diff -u -b -r1.233 prog_data.m
--- compiler/prog_data.m	16 Aug 2011 03:26:33 -0000	1.233
+++ compiler/prog_data.m	30 Aug 2011 14:38:25 -0000
@@ -824,9 +824,8 @@
 :- type pragma_foreign_code_impl
     --->    fc_impl_ordinary(
                 % This is a foreign language definition of a model_det or
-                % model_semi procedure. (We also allow model_non, until
-                % everyone has had time to adapt to the new way of handling
-                % model_non pragmas.)
+                % model_semi procedure. (We used to allow model_non, but
+                % do not any more.)
 
                 string,             % The code of the procedure.
                 maybe(prog_context)
Index: compiler/purity.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/purity.m,v
retrieving revision 1.147
diff -u -b -r1.147 purity.m
--- compiler/purity.m	16 Aug 2011 03:26:33 -0000	1.147
+++ compiler/purity.m	30 Aug 2011 14:37:13 -0000
@@ -270,11 +270,12 @@
         clauses_info_get_vartypes(!.ClausesInfo, VarTypes0),
         clauses_info_get_varset(!.ClausesInfo, VarSet0),
         PurityInfo0 = purity_info(ModuleInfo, run_post_typecheck,
-            !.PredInfo, VarTypes0, VarSet0, [], do_not_need_to_requantify),
+            !.PredInfo, VarTypes0, VarSet0, [], do_not_need_to_requantify,
+            have_not_converted_unify),
         compute_purity_for_clauses(Clauses0, Clauses, !.PredInfo,
             purity_pure, Purity, PurityInfo0, PurityInfo),
         PurityInfo = purity_info(_, _, !:PredInfo,
-            VarTypes, VarSet, GoalSpecs, _),
+            VarTypes, VarSet, GoalSpecs, _, _),
         clauses_info_set_vartypes(VarTypes, !ClausesInfo),
         clauses_info_set_varset(VarSet, !ClausesInfo),
         set_clause_list(Clauses, ClausesRep),
@@ -325,10 +326,11 @@
     proc_info_get_vartypes(ProcInfo0, VarTypes0),
     proc_info_get_varset(ProcInfo0, VarSet0),
     PurityInfo0 = purity_info(ModuleInfo, do_not_run_post_typecheck,
-        !.PredInfo, VarTypes0, VarSet0, [], do_not_need_to_requantify),
+        !.PredInfo, VarTypes0, VarSet0, [], do_not_need_to_requantify,
+        have_not_converted_unify),
     compute_goal_purity(Goal0, Goal, Bodypurity, _, PurityInfo0, PurityInfo),
     PurityInfo = purity_info(_, _, !:PredInfo, VarTypes, VarSet, _,
-        NeedToRequantify),
+        NeedToRequantify, _),
     proc_info_set_goal(Goal, ProcInfo0, ProcInfo1),
     proc_info_set_vartypes(VarTypes, ProcInfo1, ProcInfo2),
     proc_info_set_varset(VarSet, ProcInfo2, ProcInfo3),
@@ -592,10 +594,16 @@
                 post_typecheck.resolve_unify_functor(LHS, ConsId, Args, Mode,
                     Unification, UnifyContext, GoalInfo, ModuleInfo,
                     PredInfo0, PredInfo, VarTypes0, VarTypes, VarSet0, VarSet,
-                    Goal1),
+                    Goal1, IsPlainUnify),
                 !Info ^ pi_vartypes := VarTypes,
                 !Info ^ pi_varset := VarSet,
-                !Info ^ pi_pred_info := PredInfo
+                !Info ^ pi_pred_info := PredInfo,
+                (
+                    IsPlainUnify = is_plain_unify
+                ;
+                    IsPlainUnify = is_not_plain_unify,
+                    !Info ^ pi_converted_unify := have_converted_unify
+                )
             ;
                 RunPostTypecheck = do_not_run_post_typecheck,
                 Goal1 = hlds_goal(GoalExpr0, GoalInfo)
@@ -635,14 +643,17 @@
             NotGoal1 = hlds_goal(GoalExpr, _)
         )
     ;
-        GoalExpr0 = scope(Reason, Goal0),
+        GoalExpr0 = scope(Reason0, SubGoal0),
         (
-            Reason = exist_quant(_),
-            compute_goal_purity(Goal0, Goal, Purity, ContainsTrace, !Info)
+            Reason0 = exist_quant(_),
+            compute_goal_purity(SubGoal0, SubGoal, Purity, ContainsTrace,
+                !Info),
+            Reason = Reason0
         ;
-            Reason = promise_purity(PromisedPurity),
-            compute_goal_purity(Goal0, Goal, _, ContainsTrace, !Info),
-            Purity = PromisedPurity
+            Reason0 = promise_purity(PromisedPurity),
+            compute_goal_purity(SubGoal0, SubGoal, _, ContainsTrace, !Info),
+            Purity = PromisedPurity,
+            Reason = Reason0
         ;
             % We haven't yet classified from_ground_term scopes into
             % from_ground_term_construct and other kinds, which is a pity,
@@ -652,21 +663,37 @@
             % conjunctions of unifications, and we could take advantage of
             % that, e.g. by avoiding repeatedly taking the varset and vartypes
             % out of !Info and just as repeatedly putting it back again.
-            ( Reason = promise_solutions(_, _)
-            ; Reason = require_detism(_)
-            ; Reason = require_complete_switch(_)
-            ; Reason = commit(_)
-            ; Reason = barrier(_)
-            ; Reason = from_ground_term(_, _)
+            Reason0 = from_ground_term(TermVar, Kind0),
+            !Info ^ pi_converted_unify := have_not_converted_unify,
+            compute_goal_purity(SubGoal0, SubGoal, Purity, ContainsTrace,
+                !Info),
+            HaveConvertedUnify = !.Info ^ pi_converted_unify,
+            (
+                HaveConvertedUnify = have_not_converted_unify,
+                Kind = Kind0
+            ;
+                HaveConvertedUnify = have_converted_unify,
+                Kind = from_ground_term_other
+            ),
+            Reason = from_ground_term(TermVar, Kind)
+        ;
+            ( Reason0 = promise_solutions(_, _)
+            ; Reason0 = require_detism(_)
+            ; Reason0 = require_complete_switch(_)
+            ; Reason0 = commit(_)
+            ; Reason0 = barrier(_)
             ),
-            compute_goal_purity(Goal0, Goal, Purity, ContainsTrace, !Info)
+            compute_goal_purity(SubGoal0, SubGoal, Purity, ContainsTrace,
+                !Info),
+            Reason = Reason0
         ;
-            Reason = trace_goal(_, _, _, _, _),
-            compute_goal_purity(Goal0, Goal, _SubPurity, _, !Info),
+            Reason0 = trace_goal(_, _, _, _, _),
+            compute_goal_purity(SubGoal0, SubGoal, _SubPurity, _, !Info),
             Purity = purity_pure,
-            ContainsTrace = contains_trace_goal
+            ContainsTrace = contains_trace_goal,
+            Reason = Reason0
         ),
-        GoalExpr = scope(Reason, Goal)
+        GoalExpr = scope(Reason, SubGoal)
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
         compute_goal_purity(Cond0, Cond, Purity1, ContainsTrace1, !Info),
@@ -1326,6 +1353,10 @@
     --->    run_post_typecheck
     ;       do_not_run_post_typecheck.
 
+:- type converted_unify
+    --->    have_not_converted_unify
+    ;       have_converted_unify.
+
 :- type purity_info
     --->    purity_info(
                 % Fields not changed by purity checking.
@@ -1337,7 +1368,8 @@
                 pi_vartypes             :: vartypes,
                 pi_varset               :: prog_varset,
                 pi_messages             :: list(error_spec),
-                pi_requant              :: need_to_requantify
+                pi_requant              :: need_to_requantify,
+                pi_converted_unify      :: converted_unify
             ).
 
 :- pred purity_info_add_message(error_spec::in,
Index: compiler/quantification.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/quantification.m,v
retrieving revision 1.146
diff -u -b -r1.146 quantification.m
--- compiler/quantification.m	16 Aug 2011 03:26:33 -0000	1.146
+++ compiler/quantification.m	30 Aug 2011 16:38:07 -0000
@@ -147,10 +147,10 @@
     %   OutsideVars will be [X] and QuantifiedVars will be [],
     %   since the quantification can't be pushed inside the negation.
     %
-    % The `outside vars', `lambda outside vars', and `quant vars'
-    % fields are inputs; the `nonlocals' field is output; and
-    % the `seen so far', the varset, the types, rtti_varmaps, and the
-    % warnings fields are threaded (i.e. both input and output).
+    % The `outside vars', `lambda outside vars', and `quant vars' fields
+    % are inputs; the `nonlocals' field is output; and the `seen so far',
+    % the varset, the types, rtti_varmaps, and the warnings fields are
+    % threaded (i.e. both input and output).
     % We use the convention that the input fields are callee save,
     % and the outputs are caller save.
     %
@@ -256,21 +256,23 @@
 
 implicitly_quantify_goal_quant_info(Goal0, Goal, NonLocalsToRecompute,
         !Info) :-
-    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
+    some [!GoalExpr, !GoalInfo] (
+        Goal0 = hlds_goal(!:GoalExpr, !:GoalInfo),
     get_seen(!.Info, SeenVars),
-    implicitly_quantify_goal_quant_info_2(GoalExpr0, GoalExpr1, GoalInfo0,
+        implicitly_quantify_goal_quant_info_2(!GoalExpr, !.GoalInfo,
         NonLocalsToRecompute, PossiblyNonLocalGoalVars0, !Info),
     get_nonlocals(!.Info, NonLocalVars),
-    difference(PossiblyNonLocalGoalVars0, NonLocalVars, LocalVars),
-    intersect(SeenVars, LocalVars, RenameVars),
+        set_of_var.difference(PossiblyNonLocalGoalVars0, NonLocalVars,
+            LocalVars),
+        set_of_var.intersect(SeenVars, LocalVars, RenameVars),
     % If there are any variables that are local to the goal
     % which we have come across before, then we rename them apart.
     ( set_of_var.is_empty(RenameVars) ->
-        GoalExpr = GoalExpr1,
-        GoalInfo1 = GoalInfo0
+            true
     ;
         rename_apart(RenameVars, RenameMap, NonLocalsToRecompute,
-            hlds_goal(GoalExpr1, GoalInfo0), hlds_goal(GoalExpr, GoalInfo1),
+                hlds_goal(!.GoalExpr, !.GoalInfo),
+                hlds_goal(!:GoalExpr, !:GoalInfo),
             !Info),
 
         % Make sure that the information in the RTTI varmaps is updated
@@ -282,18 +284,19 @@
             set_rtti_varmaps(!.RttiVarMaps, !Info)
         )
     ),
-    set_goal_nonlocals_translate(NonLocalVars, NonLocals, NonLocalsToRecompute,
-        GoalInfo1, GoalInfo2, !Info),
+        set_goal_nonlocals(NonLocalVars, NonLocalsToRecompute,
+            !GoalInfo, !Info),
 
     % If the nonlocals set has shrunk (e.g. because some optimization
     % optimizes away the other occurrences of a variable, causing it
     % to become local when previously it was nonlocal),
     % then we may need to likewise shrink the instmap delta.
 
-    InstMapDelta0 = goal_info_get_instmap_delta(GoalInfo2),
-    instmap_delta_restrict(NonLocals, InstMapDelta0, InstMapDelta),
-    goal_info_set_instmap_delta(InstMapDelta, GoalInfo2, GoalInfo),
-    Goal = hlds_goal(GoalExpr, GoalInfo).
+        InstMapDelta0 = goal_info_get_instmap_delta(!.GoalInfo),
+        instmap_delta_restrict(NonLocalVars, InstMapDelta0, InstMapDelta),
+        goal_info_set_instmap_delta(InstMapDelta, !GoalInfo),
+        Goal = hlds_goal(!.GoalExpr, !.GoalInfo)
+    ).
 
     % After this pass, explicit quantifiers are redundant, since all variables
     % which were explicitly quantified have been renamed apart. So we don't
@@ -422,7 +425,8 @@
             LambdaVarsThen = set_of_var.init
         ),
         set_of_var.union(OutsideVars, VarsThen, OutsideVars1),
-        set_of_var.union(LambdaOutsideVars, LambdaVarsThen, LambdaOutsideVars1),
+        set_of_var.union(LambdaOutsideVars, LambdaVarsThen,
+            LambdaOutsideVars1),
         set_quant_vars(QuantVars1, !Info),
         set_outside(OutsideVars1, !Info),
         set_lambda_outside(LambdaOutsideVars1, !Info),
@@ -512,37 +516,39 @@
         ),
         implicitly_quantify_unify_rhs(MaybeSetArgs, GoalInfo0,
             UnifyRHS0, UnifyRHS, Unification0, Unification,
-            NonLocalsToRecompute, !Info),
+            NonLocalsToRecompute, RHSGoalVars, !Info),
         GoalExpr = unify(Var, UnifyRHS, Mode, Unification, UnifyContext),
-        get_nonlocals(!.Info, VarsUnifyRHS),
-        set_of_var.insert(Var, VarsUnifyRHS, GoalVars0),
-        set_of_var.insert_list(TypeInfoVars, GoalVars0, GoalVars1),
+
+        some [!GoalVars] (
+            !:GoalVars = RHSGoalVars,
+            set_of_var.insert(Var, !GoalVars),
+            set_of_var.insert_list(TypeInfoVars, !GoalVars),
         (
             MaybeReuseVar = yes(ReuseVar),
-            set_of_var.insert(ReuseVar, GoalVars1, GoalVars2)
+                set_of_var.insert(ReuseVar, !GoalVars)
         ;
-            MaybeReuseVar = no,
-            GoalVars2 = GoalVars1
+                MaybeReuseVar = no
         ),
         (
             MaybeSizeVar = yes(SizeVar),
-            set_of_var.insert(SizeVar, GoalVars2, GoalVars3)
+                set_of_var.insert(SizeVar, !GoalVars)
         ;
-            MaybeSizeVar = no,
-            GoalVars3 = GoalVars2
+                MaybeSizeVar = no
         ),
         (
             MaybeRegionVar = yes(RegionVar),
-            set_of_var.insert(RegionVar, GoalVars3, GoalVars)
+                set_of_var.insert(RegionVar, !GoalVars)
         ;
-            MaybeRegionVar = no,
-            GoalVars = GoalVars3
+                MaybeRegionVar = no
         ),
-        update_seen_vars(GoalVars, !Info),
-        set_of_var.intersect(GoalVars, OutsideVars, NonLocalVars1),
-        set_of_var.intersect(GoalVars, LambdaOutsideVars, NonLocalVars2),
+            update_seen_vars(!.GoalVars, !Info),
+            set_of_var.intersect(!.GoalVars, OutsideVars,
+                NonLocalVars1),
+            set_of_var.intersect(!.GoalVars, LambdaOutsideVars,
+                NonLocalVars2),
         set_of_var.union(NonLocalVars1, NonLocalVars2, NonLocalVars),
-        set_nonlocals(NonLocalVars, !Info),
+            set_nonlocals(NonLocalVars, !Info)
+        ),
         goal_expr_vars_bitset(NonLocalsToRecompute, GoalExpr0,
             PossiblyNonLocalGoalVars0)
     ;
@@ -682,27 +688,49 @@
         set_of_var.delete_list(Vars, NonLocals0, NonLocals),
         set_nonlocals(NonLocals, !Info)
     ;
-        Reason0 = from_ground_term(TermVar, from_ground_term_construct),
+        Reason0 = from_ground_term(TermVar, FGT),
+        (
+            ( FGT = from_ground_term_initial
+            ; FGT = from_ground_term_construct
+            ),
         Reason = Reason0,
         % Not quantifying the subgoal is a substantial speedup. It is ok
         % because superhomogeneous.m sets up the nonlocal sets of the
         % unifications, their conjunction, and the scope goal itself,
-        % and every later compiler pass than can invalidate those nonlocal sets
-        % will either set the kind to from_ground_term_other (or to
-        % from_ground_term_deconstruct) or remove the scope altogether.
+            % and the mode analysis pass that converted the kind from
+            % from_ground_term_initial to from_ground_term_construct
+            % has checked that the invariants we need do indeed apply.
         SubGoal = SubGoal0,
-        NonLocals = set_of_var.make_singleton(TermVar),
+            get_outside(!.Info, OutsideVars),
+            get_lambda_outside(!.Info, LambdaOutsideVars),
+            (
+                ( set_of_var.contains(OutsideVars, TermVar)
+                ; set_of_var.contains(LambdaOutsideVars, TermVar)
+                )
+            ->
+                NonLocals = set_of_var.make_singleton(TermVar)
+            ;
+                NonLocals = set_of_var.init
+            ),
         set_nonlocals(NonLocals, !Info),
         PossiblyNonLocalGoalVars0 = NonLocals
     ;
+            ( FGT = from_ground_term_deconstruct
+            ; FGT = from_ground_term_other
+            ),
+            Reason = Reason0,
+            goal_expr_vars_bitset(NonLocalsToRecompute, GoalExpr0,
+                PossiblyNonLocalGoalVars0),
+            implicitly_quantify_goal_quant_info(SubGoal0, SubGoal,
+                NonLocalsToRecompute, !Info)
+        )
+    ;
         ( Reason0 = promise_purity(_)
         ; Reason0 = promise_solutions(_, _)
         ; Reason0 = require_detism(_)
         ; Reason0 = require_complete_switch(_)
         ; Reason0 = commit(_)
         ; Reason0 = barrier(_)
-        ; Reason0 = from_ground_term(_, from_ground_term_deconstruct)
-        ; Reason0 = from_ground_term(_, from_ground_term_other)
         ),
         Reason = Reason0,
         goal_expr_vars_bitset(NonLocalsToRecompute, GoalExpr0,
@@ -808,7 +836,8 @@
     % outside vars and the outside lambda vars sets.
     goal_vars_both_maybe_lambda_and_bi_impl(RHS0, RHS_Vars, RHS_LambdaVars),
     set_of_var.union(OutsideVars1, RHS_Vars, LHS_OutsideVars),
-    set_of_var.union(LambdaOutsideVars1, RHS_LambdaVars, LHS_LambdaOutsideVars),
+    set_of_var.union(LambdaOutsideVars1, RHS_LambdaVars,
+        LHS_LambdaOutsideVars),
 
     % Quantify the LHS.
     set_outside(LHS_OutsideVars, !Info),
@@ -892,20 +921,20 @@
 
 :- pred implicitly_quantify_unify_rhs(maybe(list(needs_update)),
     hlds_goal_info, unify_rhs, unify_rhs,
-    unification, unification, nonlocals_to_recompute, quant_info, quant_info).
+    unification, unification, nonlocals_to_recompute, set_of_progvar,
+    quant_info, quant_info).
 :- mode implicitly_quantify_unify_rhs(in, in, in, out, in, out,
-    in(ordinary_nonlocals_maybe_lambda), in, out) is det.
+    in(ordinary_nonlocals_maybe_lambda), out, in, out) is det.
 :- mode implicitly_quantify_unify_rhs(in, in, in, out, in, out,
-    in(ordinary_nonlocals_no_lambda), in, out) is det.
+    in(ordinary_nonlocals_no_lambda), out, in, out) is det.
 :- mode implicitly_quantify_unify_rhs(in, in, in, out, in, out,
-    in(code_gen_nonlocals_no_lambda), in, out) is det.
+    in(code_gen_nonlocals_no_lambda), out, in, out) is det.
 
 implicitly_quantify_unify_rhs(ReuseArgs, GoalInfo0, !RHS, !Unification,
-        NonLocalsToRecompute, !Info) :-
+        NonLocalsToRecompute, RHSNonLocals, !Info) :-
     (
         !.RHS = rhs_var(X),
-        Vars = set_of_var.make_singleton(X),
-        set_nonlocals(Vars, !Info)
+        RHSNonLocals = set_of_var.make_singleton(X)
     ;
         !.RHS = rhs_functor(_, _, ArgVars),
         (
@@ -915,11 +944,10 @@
             % The fields taken from the reused cell aren't counted
             % as code-gen nonlocals.
             get_updated_fields(SetArgs, ArgVars, Vars0),
-            Vars = list_to_set(Vars0)
+            RHSNonLocals = set_of_var.list_to_set(Vars0)
         ;
-            Vars = list_to_set(ArgVars)
-        ),
-        set_nonlocals(Vars, !Info)
+            RHSNonLocals = set_of_var.list_to_set(ArgVars)
+        )
     ;
         !.RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
             LambdaNonLocals0, LambdaVars0, Modes, Det, Goal0),
@@ -973,13 +1001,12 @@
         !:RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
             LambdaNonLocals, LambdaVars, Modes, Det, Goal),
 
-        get_nonlocals(!.Info, NonLocals0),
+        get_nonlocals(!.Info, RHSNonLocals0),
         % Lambda-quantified variables are local.
-        set_of_var.delete_list(LambdaVars, NonLocals0, NonLocals),
+        set_of_var.delete_list(LambdaVars, RHSNonLocals0, RHSNonLocals),
         set_quant_vars(QuantVars0, !Info),
         set_outside(OutsideVars0, !Info),
         set_lambda_outside(LambdaOutsideVars0, !Info),
-        set_nonlocals(NonLocals, !Info),
 
         % Work out the list of nonlocal curried arguments to the lambda
         % expression. This set must only ever decrease, since the first
@@ -1011,7 +1038,7 @@
                     "lambda term has size info")
             ),
             map.from_corresponding_lists(Args0, ArgModes0, ArgModesMap),
-            Args = set_of_var.to_sorted_list(NonLocals),
+            Args = set_of_var.to_sorted_list(RHSNonLocals),
             map.apply_to_list(Args, ArgModesMap, ArgModes),
             !:Unification = construct(ConstructVar, ConsId, Args,
                 ArgModes, HowToConstruct, Uniq, SubInfo)
@@ -1247,7 +1274,8 @@
     set_of_var.union(GoalSet, Set, PossiblyNonLocalGoalVars).
 
 :- pred get_following_vars_maybe_lambda_2(nonlocals_to_recompute,
-    list(hlds_goal), set_of_progvar, set_of_progvar, list(pair(set_of_progvar))).
+    list(hlds_goal), set_of_progvar, set_of_progvar,
+    list(pair(set_of_progvar))).
 :- mode get_following_vars_maybe_lambda_2(in(ordinary_nonlocals_maybe_lambda),
     in, out, out, out) is det.
 
@@ -1274,7 +1302,8 @@
     Set = set_of_var.init.
 get_following_vars_no_lambda_2(NonLocalsToRecompute, [Goal | Goals],
         Set, SetList) :-
-    get_following_vars_no_lambda_2(NonLocalsToRecompute, Goals, Set0, SetList0),
+    get_following_vars_no_lambda_2(NonLocalsToRecompute, Goals,
+        Set0, SetList0),
     goal_vars_both_no_lambda(NonLocalsToRecompute, Goal, Set1),
     set_of_var.union(Set0, Set1, Set),
     SetList = [Set0 | SetList0].
@@ -1705,8 +1734,8 @@
     Goal = hlds_goal(GoalExpr, _),
     goal_expr_vars_both_no_lambda(NonLocalsToRecompute, GoalExpr, Set).
 
-:- pred goal_expr_vars_both_maybe_lambda(nonlocals_to_recompute, hlds_goal_expr,
-    set_of_progvar, set_of_progvar).
+:- pred goal_expr_vars_both_maybe_lambda(nonlocals_to_recompute,
+    hlds_goal_expr, set_of_progvar, set_of_progvar).
 :- mode goal_expr_vars_both_maybe_lambda(in(ordinary_nonlocals_maybe_lambda),
     in, out, out) is det.
 
@@ -1771,7 +1800,7 @@
             )
         ;
             Unification = complicated_unify(_, _, TypeInfoVars),
-            insert_list(TypeInfoVars, !Set)
+            set_of_var.insert_list(TypeInfoVars, !Set)
         ;
             ( Unification = deconstruct(_, _, _, _, _, _)
             ; Unification = assign(_, _)
@@ -1865,7 +1894,9 @@
         ;
             Reason = from_ground_term(TermVar, Kind),
             (
-                Kind = from_ground_term_construct,
+                ( Kind = from_ground_term_initial
+                ; Kind = from_ground_term_construct
+                ),
                 !:Set = set_of_var.init,
                 set_of_var.insert(TermVar, !Set),
                 !:LambdaSet = set_of_var.init
@@ -1874,7 +1905,7 @@
                 ; Kind = from_ground_term_other
                 ),
                 % Unfortunately, while there will never by any lambda goals
-                % inside such SubGoal when the scope is built, there may be
+                % inside such a SubGoal when the scope is built, there may be
                 % lambda goals inside SubGoal after typechecking.
                 goal_vars_both_maybe_lambda(NonLocalsToRecompute, SubGoal,
                     !:Set, !:LambdaSet)
@@ -1982,12 +2013,9 @@
         % This code does the following:
         %     !:Set = !.Set + ( (vars(Cond) + vars(Then)) \ Vars ) + vars(Else)
         % where `+' is set union and `\' is relative complement.
-        goal_vars_both_maybe_lambda_and_bi_impl(Cond,
-            CondSet, CondLambdaSet),
-        goal_vars_both_maybe_lambda_and_bi_impl(Then,
-            ThenSet, ThenLambdaSet),
-        goal_vars_both_maybe_lambda_and_bi_impl(Else,
-            ElseSet, ElseLambdaSet),
+        goal_vars_both_maybe_lambda_and_bi_impl(Cond, CondSet, CondLambdaSet),
+        goal_vars_both_maybe_lambda_and_bi_impl(Then, ThenSet, ThenLambdaSet),
+        goal_vars_both_maybe_lambda_and_bi_impl(Else, ElseSet, ElseLambdaSet),
         set_of_var.union(CondSet, ThenSet, CondThenSet),
         set_of_var.union(CondLambdaSet, ThenLambdaSet, CondThenLambdaSet),
         set_of_var.delete_list(Vars, CondThenSet, SomeCondThenSet),
@@ -2379,7 +2407,7 @@
         % of the seen var set down.
         % get_seen(!.Info, SeenVars0),
         % map.values(RenameMap, NewVarsList),
-        % insert_list(SeenVars0, NewVarsList, SeenVars),
+        % set_of_var.insert_list(NewVarsList, SeenVars0, SeenVars),
         % set_seen(SeenVars, !Info)
     ).
 
@@ -2395,21 +2423,6 @@
     in, out, in, out) is det.
 
 set_goal_nonlocals(NonLocals, NonLocalsToRecompute, !GoalInfo, !Info) :-
-    set_goal_nonlocals_translate(NonLocals, _, NonLocalsToRecompute,
-        !GoalInfo, !Info).
-
-:- pred set_goal_nonlocals_translate(set_of_progvar, set_of_progvar,
-    nonlocals_to_recompute, hlds_goal_info, hlds_goal_info,
-    quant_info, quant_info).
-:- mode set_goal_nonlocals_translate(in, out,
-    in(ordinary_nonlocals_maybe_lambda), in, out, in, out) is det.
-:- mode set_goal_nonlocals_translate(in, out,
-    in(ordinary_nonlocals_no_lambda), in, out, in, out) is det.
-:- mode set_goal_nonlocals_translate(in, out,
-    in(code_gen_nonlocals_no_lambda), in, out, in, out) is det.
-
-set_goal_nonlocals_translate(NonLocals, NonLocals, NonLocalsToRecompute,
-        !GoalInfo, !Info) :-
     (
         ( NonLocalsToRecompute = ordinary_nonlocals_maybe_lambda
         ; NonLocalsToRecompute = ordinary_nonlocals_no_lambda
Index: compiler/rbmm.region_transformation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_transformation.m,v
retrieving revision 1.20
diff -u -b -r1.20 rbmm.region_transformation.m
--- compiler/rbmm.region_transformation.m	16 Aug 2011 03:26:33 -0000	1.20
+++ compiler/rbmm.region_transformation.m	29 Aug 2011 15:54:50 -0000
@@ -541,9 +541,14 @@
         % instructions are added in these scopes. This expectation seems
         % reasonable because a region is often created before a heap
         % allocation.
+        % zs: This is very inefficient. Scopes that construct ground terms
+        % construct STATIC ground terms. Since these are not created
+        % dynamically, they cannot possibly refer to any dynamically created
+        % region, so RBMM transformations should ignore them.
         ( Reason0 = from_ground_term(Var, _Kind) ->
             Reason = from_ground_term(Var, from_ground_term_other)
-        ;   Reason = Reason0
+        ;
+            Reason = Reason0
         ),
         region_transform_goal(ModuleInfo, Graph, ResurRenamingProc,
             IteRenamingProc, ActualRegionArgProc, RegionInstructionProc,
Index: compiler/saved_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/saved_vars.m,v
retrieving revision 1.92
diff -u -b -r1.92 saved_vars.m
--- compiler/saved_vars.m	16 Aug 2011 03:26:33 -0000	1.92
+++ compiler/saved_vars.m	29 Aug 2011 15:54:50 -0000
@@ -319,6 +319,7 @@
             ;
                 ( Reason = require_detism(_)
                 ; Reason = require_complete_switch(_)
+                ; Reason = from_ground_term(_, from_ground_term_initial)
                 ),
                 % These scopes should have been deleted by now.
                 unexpected($module, $pred, "unexpected scope")
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.269
diff -u -b -r1.269 simplify.m
--- compiler/simplify.m	17 Aug 2011 07:30:24 -0000	1.269
+++ compiler/simplify.m	30 Aug 2011 14:38:25 -0000
@@ -752,7 +752,7 @@
 :- pred simplify_goal(hlds_goal::in, hlds_goal::out,
     simplify_info::in, simplify_info::out) is det.
 
-simplify_goal(Goal0, hlds_goal(GoalExpr, GoalInfo), !Info) :-
+simplify_goal(Goal0, Goal, !Info) :-
     Goal0 = hlds_goal(_, GoalInfo0),
     simplify_info_get_inside_duplicated_for_switch(!.Info,
         InsideDuplForSwitch),
@@ -900,8 +900,8 @@
         Goal1 = Goal0
     ),
 
-    % Remove unnecessary explicit quantifications before working
-    % out whether the goal can cause a stack flush.
+    % Remove unnecessary explicit quantifications before working out
+    % whether the goal can cause a stack flush.
 
     ( Goal1 = hlds_goal(scope(Reason1, SomeGoal1), GoalInfo1) ->
         nested_scopes(Reason1, SomeGoal1, GoalInfo1, Goal2)
@@ -915,9 +915,7 @@
             Reason2 = barrier(removable)
         ;
             Reason2 = from_ground_term(_, Kind),
-            ( Kind = from_ground_term_deconstruct
-            ; Kind = from_ground_term_other
-            )
+            Kind = from_ground_term_other
         )
     ->
         Goal3 = SomeGoal2
@@ -926,14 +924,15 @@
     ),
     simplify_info_maybe_clear_structs(before, Goal3, !Info),
     Goal3 = hlds_goal(GoalExpr3, GoalInfo3),
-    simplify_goal_expr(GoalExpr3, GoalExpr, GoalInfo3, GoalInfo4, !Info),
-    simplify_info_maybe_clear_structs(after, hlds_goal(GoalExpr, GoalInfo4),
-        !Info),
+    simplify_goal_expr(GoalExpr3, GoalExpr4, GoalInfo3, GoalInfo4, !Info),
+    Goal4 = hlds_goal(GoalExpr4, GoalInfo4),
+    simplify_info_maybe_clear_structs(after, Goal4, !Info),
     simplify_info_set_inside_duplicated_for_switch(InsideDuplForSwitch, !Info),
-    enforce_unreachability_invariant(GoalInfo4, GoalInfo, !Info).
+    enforce_unreachability_invariant(GoalInfo4, GoalInfo, !Info),
+    Goal = hlds_goal(GoalExpr4, GoalInfo).
 
-    % Ensure that the mode information and the determinism
-    % information say consistent things about unreachability.
+    % Ensure that the mode information and the determinism information
+    % say consistent things about unreachability.
     %
 :- pred enforce_unreachability_invariant(
     hlds_goal_info::in, hlds_goal_info::out,
@@ -3755,10 +3754,20 @@
             SubGoal = SubGoal0,
             ContainsTrace = contains_trace_goal
         ;
-            Reason = from_ground_term(_, from_ground_term_construct),
+            Reason = from_ground_term(_, FGT),
+            (
+                ( FGT = from_ground_term_construct
+                ; FGT = from_ground_term_deconstruct
+                ),
             SubGoal = SubGoal0,
             ContainsTrace = contains_no_trace_goal
         ;
+                ( FGT = from_ground_term_initial
+                ; FGT = from_ground_term_other
+                ),
+                goal_contains_trace(SubGoal0, SubGoal, ContainsTrace)
+            )
+        ;
             ( Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
             ; Reason = promise_purity(_)
@@ -3766,8 +3775,6 @@
             ; Reason = require_complete_switch(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
-            ; Reason = from_ground_term(_, from_ground_term_deconstruct)
-            ; Reason = from_ground_term(_, from_ground_term_other)
             ),
             goal_contains_trace(SubGoal0, SubGoal, ContainsTrace)
         ),
Index: compiler/stm_expand.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/stm_expand.m,v
retrieving revision 1.23
diff -u -b -r1.23 stm_expand.m
--- compiler/stm_expand.m	16 Aug 2011 03:26:33 -0000	1.23
+++ compiler/stm_expand.m	29 Aug 2011 15:54:50 -0000
@@ -330,17 +330,29 @@
     ;
         GoalExpr0 = scope(Reason, InnerGoal0),
         (
-            Reason = from_ground_term(_, from_ground_term_construct),
+            Reason = from_ground_term(_, FGT),
+            (
+                ( FGT = from_ground_term_construct
+                ; FGT = from_ground_term_deconstruct
+                ),
             % There can be no atomic goals inside this scope.
             Goal = Goal0
         ;
+                FGT = from_ground_term_other,
+                stm_process_goal(Instmap, InnerGoal0, InnerGoal, !Info),
+                GoalExpr = scope(Reason, InnerGoal),
+                Goal = hlds_goal(GoalExpr, GoalInfo0)
+            ;
+                FGT = from_ground_term_initial,
+                % These scopes should have been deleted by now.
+                unexpected($module, $pred, "unexpected scope")
+            )
+        ;
             ( Reason = exist_quant(_)
             ; Reason = promise_solutions(_, _)
             ; Reason = promise_purity(_)
             ; Reason = commit(_)
             ; Reason = barrier(_)
-            ; Reason = from_ground_term(_, from_ground_term_deconstruct)
-            ; Reason = from_ground_term(_, from_ground_term_other)
             ; Reason = trace_goal(_, _, _, _, _)
             ),
             stm_process_goal(Instmap, InnerGoal0, InnerGoal, !Info),
@@ -355,8 +367,8 @@
         )
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
-        stm_process_if_then_else(Instmap, Cond0, Then0, Else0, Cond, Then,
-            Else, !Info),
+        stm_process_if_then_else(Instmap, Cond0, Then0, Else0,
+            Cond, Then, Else, !Info),
         GoalExpr = if_then_else(Vars, Cond, Then, Else),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
Index: compiler/stratify.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/stratify.m,v
retrieving revision 1.79
diff -u -b -r1.79 stratify.m
--- compiler/stratify.m	23 May 2011 05:08:12 -0000	1.79
+++ compiler/stratify.m	29 Aug 2011 15:54:50 -0000
@@ -196,7 +196,12 @@
             ThisPredProcId, ErrorOrWarning, ModuleInfo, !Specs)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % These scopes cannot contain any calls.
             true
         ;
@@ -349,7 +354,12 @@
             HighOrderLoops, ErrorOrWarning, ModuleInfo, !Specs)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % These scopes cannot contain any calls.
             true
         ;
@@ -829,7 +839,12 @@
         stratify_analyze_goal(SubGoal, !Calls, !HasAT, !CallsHO)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % The code in these scopes does not make calls (either first order
             % or higher order), and it does not take addresses.
             true
@@ -948,7 +963,12 @@
         get_called_procs(SubGoal, !Calls)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % The code in these scopes does not make calls.
             true
         ;
Index: compiler/structure_reuse.lbu.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.lbu.m,v
retrieving revision 1.17
diff -u -b -r1.17 structure_reuse.lbu.m
--- compiler/structure_reuse.lbu.m	16 Aug 2011 03:26:34 -0000	1.17
+++ compiler/structure_reuse.lbu.m	29 Aug 2011 15:54:50 -0000
@@ -134,6 +134,8 @@
         ( Reason = from_ground_term(_, from_ground_term_construct) ->
             SubGoal = SubGoal0
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well.
             backward_use_in_goal(VarTypes, SubGoal0, SubGoal, !LBU)
         ),
         !:Expr = scope(Reason, SubGoal)
Index: compiler/superhomogeneous.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/superhomogeneous.m,v
retrieving revision 1.47
diff -u -b -r1.47 superhomogeneous.m
--- compiler/superhomogeneous.m	16 Aug 2011 03:26:34 -0000	1.47
+++ compiler/superhomogeneous.m	29 Aug 2011 11:11:38 -0000
@@ -413,12 +413,7 @@
         ground_term(RHS)
     ->
         Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
-        % We don't yet know whether this scope is actually be a construction;
-        % that is decided during mode analysis. However, the code inside the
-        % scope actually maintains the invariants we expect from
-        % from_ground_term_construct scopes, and quantification can
-        % exploit this knowledge.
-        Kind = from_ground_term_construct,
+        Kind = from_ground_term_initial,
         goal_info_set_nonlocals(set_of_var.make_singleton(LHSVar),
             GoalInfo0, GoalInfo),
         ( GoalExpr0 = conj(plain_conj, Conjuncts0) ->
Index: compiler/switch_detection.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/switch_detection.m,v
retrieving revision 1.157
diff -u -b -r1.157 switch_detection.m
--- compiler/switch_detection.m	16 Aug 2011 03:26:34 -0000	1.157
+++ compiler/switch_detection.m	29 Aug 2011 15:54:50 -0000
@@ -306,6 +306,9 @@
             % inside these scopes.
             SubGoal = SubGoal0
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well, since the only variable whose deconstruction could be of
+            % interest here is the one named in Reason.
             detect_switches_in_goal(InstMap0, SubGoal0, SubGoal, !LocalInfo)
         ),
         GoalExpr = scope(Reason, SubGoal)
@@ -913,8 +916,8 @@
         FoundDeconstruct) :-
     Goal0 = hlds_goal(GoalExpr0, GoalInfo),
     (
-        GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        GoalExpr0 = scope(Reason0, SubGoal0),
+        ( Reason0 = from_ground_term(_, from_ground_term_construct) ->
             % There are no deconstruction unifications inside these scopes.
             Goal = Goal0,
             % Whether we want to keep looking at the code that follows them
@@ -925,7 +928,16 @@
         ;
             find_bind_var_2(Var, ProcessUnify, SubGoal0, SubGoal, !Subst,
                 !Result, !Info, FoundDeconstruct),
-            Goal = hlds_goal(scope(Reason, SubGoal), GoalInfo)
+            (
+                FoundDeconstruct = found_deconstruct,
+                Reason0 = from_ground_term(_, from_ground_term_deconstruct)
+            ->
+                % If we remove a goal from such a scope, what is left
+                % may no longer satisfy the invariants we expect it to satisfy.
+                Goal = SubGoal
+            ;
+                Goal = hlds_goal(scope(Reason0, SubGoal), GoalInfo)
+            )
         )
     ;
         GoalExpr0 = conj(ConjType, SubGoals0),
Index: compiler/tabling_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/tabling_analysis.m,v
retrieving revision 1.24
diff -u -b -r1.24 tabling_analysis.m
--- compiler/tabling_analysis.m	23 May 2011 05:08:13 -0000	1.24
+++ compiler/tabling_analysis.m	29 Aug 2011 15:54:50 -0000
@@ -362,7 +362,12 @@
             MaybeAnalysisStatus, !ModuleInfo)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Result = mm_tabled_will_not_call,
             MaybeAnalysisStatus = yes(optimal)
         ;
@@ -678,7 +683,12 @@
         !:GoalExpr = negation(SubGoal)
     ;
         !.GoalExpr = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Status = mm_tabled_will_not_call
         ;
             annotate_goal(VarTypes, SubGoal0, SubGoal, Status, !ModuleInfo),
Index: compiler/term_pass1.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/term_pass1.m,v
retrieving revision 1.46
diff -u -b -r1.46 term_pass1.m
--- compiler/term_pass1.m	23 May 2011 05:08:14 -0000	1.46
+++ compiler/term_pass1.m	29 Aug 2011 15:54:50 -0000
@@ -372,7 +372,12 @@
             !Errors, !ModuleInfo, !IO)
     ;
         GoalExpr = scope(Reason, SubGoal),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % The scope has no calls, let alone nonterminating calls.
             true
         ;
Index: compiler/try_expand.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/try_expand.m,v
retrieving revision 1.18
diff -u -b -r1.18 try_expand.m
--- compiler/try_expand.m	16 Aug 2011 03:26:34 -0000	1.18
+++ compiler/try_expand.m	29 Aug 2011 15:54:50 -0000
@@ -390,6 +390,9 @@
             expand_try_goals_in_goal(Instmap, InnerGoal0, InnerGoal, !Info),
             GoalExpr = scope(Reason, InnerGoal),
             Goal = hlds_goal(GoalExpr, GoalInfo0)
+        ;
+            Reason = from_ground_term(_, from_ground_term_initial),
+            unexpected($module, $pred, "from_ground_term_initial")
         )
     ;
         GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
Index: compiler/tupling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/tupling.m,v
retrieving revision 1.64
diff -u -b -r1.64 tupling.m
--- compiler/tupling.m	22 Jul 2011 03:31:41 -0000	1.64
+++ compiler/tupling.m	29 Aug 2011 15:54:50 -0000
@@ -1760,7 +1760,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             Goal = Goal0
         ;
             fix_calls_in_goal(SubGoal0, SubGoal, !VarSet, !VarTypes,
Index: compiler/type_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.210
diff -u -b -r1.210 type_util.m
--- compiler/type_util.m	22 Aug 2011 04:23:14 -0000	1.210
+++ compiler/type_util.m	29 Aug 2011 11:11:38 -0000
@@ -406,7 +406,7 @@
 
 type_to_type_defn(ModuleInfo, Type, TypeDefn) :-
     module_info_get_type_table(ModuleInfo, TypeTable),
-    type_to_ctor_and_args(Type, TypeCtor, _TypeArgs),
+    type_to_ctor(Type, TypeCtor),
     search_type_ctor_defn(TypeTable, TypeCtor, TypeDefn).
 
 type_to_type_defn_body(ModuleInfo, Type, TypeBody) :-
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.461
diff -u -b -r1.461 typecheck.m
--- compiler/typecheck.m	22 Aug 2011 04:23:14 -0000	1.461
+++ compiler/typecheck.m	30 Aug 2011 14:37:13 -0000
@@ -1174,9 +1174,6 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred typecheck_goal(hlds_goal::in, hlds_goal::out,
-    typecheck_info::in, typecheck_info::out) is det.
-
     % Typecheck a goal.
     % Note that we save the context of the goal in the typecheck_info for
     % use in error messages. Also, if the context of the goal is empty,
@@ -1184,8 +1181,11 @@
     % the typecheck_info. (That should probably be done in make_hlds,
     % but it was easier to do here.)
     %
-typecheck_goal(hlds_goal(GoalExpr0, GoalInfo0), hlds_goal(GoalExpr, GoalInfo),
-        !Info) :-
+:- pred typecheck_goal(hlds_goal::in, hlds_goal::out,
+    typecheck_info::in, typecheck_info::out) is det.
+
+typecheck_goal(Goal0, Goal, !Info) :-
+    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
     Context = goal_info_get_context(GoalInfo0),
     term.context_init(EmptyContext),
     ( Context = EmptyContext ->
@@ -1233,7 +1233,8 @@
         )
     ;
         typecheck_goal_2(GoalExpr0, GoalExpr, GoalInfo, !Info)
-    ).
+    ),
+    Goal = hlds_goal(GoalExpr, GoalInfo).
 
 :- pred typecheck_goal_2(hlds_goal_expr::in, hlds_goal_expr::out,
     hlds_goal_info::in, typecheck_info::in, typecheck_info::out) is det.
@@ -1986,20 +1987,25 @@
 :- pred typecheck_unification(prog_var::in, unify_rhs::in, unify_rhs::out,
     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), GoalId, !Info) :-
+typecheck_unification(X, RHS0, RHS, GoalId, !Info) :-
+    (
+        RHS0 = rhs_var(Y),
+        typecheck_unify_var_var(X, Y, !Info),
+        RHS = RHS0
+    ;
+        RHS0 = rhs_functor(Functor, _ExistConstraints, Args),
     typecheck_unify_var_functor(X, Functor, Args, GoalId, !Info),
-    perform_context_reduction(!Info).
-typecheck_unification(X,
-        rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
+        perform_context_reduction(!Info),
+        RHS = RHS0
+    ;
+        RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
             NonLocals, Vars, Modes, Det, Goal0),
-        rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
-            NonLocals, Vars, Modes, Det, Goal), _, !Info) :-
     typecheck_lambda_var_has_type(Purity, PredOrFunc, EvalMethod, X, Vars,
         !Info),
-    typecheck_goal(Goal0, Goal, !Info).
+        typecheck_goal(Goal0, Goal, !Info),
+        RHS = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
+            NonLocals, Vars, Modes, Det, Goal)
+    ).
 
 :- pred typecheck_unify_var_var(prog_var::in, prog_var::in,
     typecheck_info::in, typecheck_info::out) is det.
@@ -2968,7 +2974,7 @@
 %-----------------------------------------------------------------------------%
 
     % Note: changes here may require changes to
-    % post_resolve_unify_functor,
+    % post_typecheck.resolve_unify_functor,
     % intermod.module_qualify_unify_rhs,
     % recompilation.usage.find_matching_constructors
     % and recompilation.check.check_functor_ambiguities.
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.139
diff -u -b -r1.139 unique_modes.m
--- compiler/unique_modes.m	17 Aug 2011 03:28:13 -0000	1.139
+++ compiler/unique_modes.m	29 Aug 2011 15:54:50 -0000
@@ -515,18 +515,24 @@
         mode_checkpoint(exit, "trace scope", !ModeInfo),
         GoalExpr = scope(Reason, SubGoal)
     ;
-        Reason = from_ground_term(TermVar, from_ground_term_construct),
-        mode_checkpoint(enter, "from_ground_term_construct scope", !ModeInfo),
+        Reason = from_ground_term(TermVar, FGT),
+        (
+            FGT = from_ground_term_construct,
+            mode_checkpoint(enter, "from_ground_term_construct scope",
+                !ModeInfo),
         mode_info_var_is_live(!.ModeInfo, TermVar, LiveTermVar),
         (
             LiveTermVar = is_live,
-            % The subgoal was left in its final state during (non-unique) mode
-            % checking. All we need to do here is to add the relevant
+                % The subgoal was left in its final state during (non-unique)
+                % mode checking. All we need to do here is to add the relevant
             % information in the goal to ModeInfo.
             SubGoal = SubGoal0,
             SubGoal = hlds_goal(_, SubGoalInfo),
             InstMapDelta = goal_info_get_instmap_delta(SubGoalInfo),
-            ( instmap_delta_search_var(InstMapDelta, TermVar, TermVarInst) ->
+                (
+                    instmap_delta_search_var(InstMapDelta, TermVar,
+                        TermVarInst)
+                ->
                 mode_info_get_instmap(!.ModeInfo, InstMap0),
                 instmap_set_var(TermVar, TermVarInst, InstMap0, InstMap),
                 mode_info_set_instmap(InstMap, !ModeInfo)
@@ -539,11 +545,22 @@
             % The term constructed by the scope is not used anywhere.
             GoalExpr = conj(plain_conj, [])
         ),
-        mode_checkpoint(exit, "from_ground_term_construct scope", !ModeInfo)
+            mode_checkpoint(exit, "from_ground_term_construct scope",
+                !ModeInfo)
+        ;
+            ( FGT = from_ground_term_deconstruct
+            ; FGT = from_ground_term_other
+            ),
+            mode_checkpoint(enter, "scope", !ModeInfo),
+            unique_modes_check_goal(SubGoal0, SubGoal, !ModeInfo),
+            mode_checkpoint(exit, "scope", !ModeInfo),
+            GoalExpr = scope(Reason, SubGoal)
+        ;
+            FGT = from_ground_term_initial,
+            unexpected($module, $pred, "from_ground_term_initial")
+        )
     ;
-        ( Reason = from_ground_term(_, from_ground_term_deconstruct)
-        ; Reason = from_ground_term(_, from_ground_term_other)
-        ; Reason = exist_quant(_)
+        ( Reason = exist_quant(_)
         ; Reason = promise_solutions(_, _)
         ; Reason = promise_purity(_)
         ; Reason = require_detism(_)
Index: compiler/untupling.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/untupling.m,v
retrieving revision 1.40
diff -u -b -r1.40 untupling.m
--- compiler/untupling.m	23 May 2011 05:08:15 -0000	1.40
+++ compiler/untupling.m	29 Aug 2011 15:54:50 -0000
@@ -535,7 +535,12 @@
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
         GoalExpr0 = scope(Reason, SubGoal0),
-        ( Reason = from_ground_term(_, from_ground_term_construct) ->
+        (
+            Reason = from_ground_term(_, FGT),
+            ( FGT = from_ground_term_construct
+            ; FGT = from_ground_term_deconstruct
+            )
+        ->
             % There are no calls in these scopes.
             Goal = Goal0
         ;
Index: compiler/unused_args.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unused_args.m,v
retrieving revision 1.171
diff -u -b -r1.171 unused_args.m
--- compiler/unused_args.m	21 Jul 2011 06:58:27 -0000	1.171
+++ compiler/unused_args.m	29 Aug 2011 15:54:50 -0000
@@ -651,6 +651,8 @@
             % unification that binds TermVar to a constant, i.e. nothing.
             true
         ;
+            % XXX We could treat from_ground_term_deconstruct specially
+            % as well.
             unused_args_traverse_goal(Info, SubGoal, !VarDep)
         )
     ;
cvs diff: Diffing compiler/notes
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_cairo
cvs diff: Diffing extras/graphics/mercury_cairo/samples
cvs diff: Diffing extras/graphics/mercury_cairo/samples/data
cvs diff: Diffing extras/graphics/mercury_cairo/tutorial
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/monte
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/appengine
cvs diff: Diffing samples/appengine/war
cvs diff: Diffing samples/appengine/war/WEB-INF
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/concurrency
cvs diff: Diffing samples/concurrency/dining_philosophers
cvs diff: Diffing samples/concurrency/midimon
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/java_interface
cvs diff: Diffing samples/java_interface/java_calls_mercury
cvs diff: Diffing samples/java_interface/mercury_calls_java
cvs diff: Diffing samples/lazy_list
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list