[m-dev.] for review: structure reuse non-locals computation

Simon Taylor stayl at cs.mu.OZ.AU
Mon Feb 7 14:47:43 AEDT 2000



Estimated hours taken: 3

compiler/quantification.m:
	Add an alternative method of computing the non-locals for 
	goals which do structure reuse, This is done to avoid unnecessary
	field extractions and variable saves for arguments of reused terms.
	The code-gen non-locals are the same as the ordinary non-locals
	except that arguments of a reconstruction which are taken
	from the reused cell are not included in the non-locals set.
	Mode analysis still uses the full non-locals set.

	Add a field to type quant_info to record which set
	of non-locals is being computed. Use record syntax
	for the access predicates.

compiler/hlds_goal.m:
	Add access predicates to extract and update the code_gen_nonlocals
	in a goal_info. When structure reuse is not performed, the nonlocals
	and the code-gen nonlocals will always be the same.
	
	Use record syntax for hlds_goal_info access predicates.

compiler/goal_util.m:
	Add a predicate `goal_contains_reconstruction', which
	succeeds if the goal does any structure reuse.
	This will always fail on the main branch.

	Add missing disjuncts for par_conj goals in `goal_calls' and
	`goal_calls_pred_id'.

compiler/liveness.m:
compiler/live_vars.m:
compiler/ml_code_gen.m:
compiler/par_conj_gen.m:
	Use the code_gen_nonlocals rather than the ordinary nonlocals.

configure.in:
	Add a test for record syntax.




Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.200
diff -u -u -r1.200 configure.in
--- configure.in	2000/01/05 16:38:00	1.200
+++ configure.in	2000/02/07 00:51:54
@@ -84,12 +84,21 @@
 		:- pred main(io__state::di, io__state::uo) is det.
 		:- implementation.
 		:- import_module list.
+
+		% Check that record syntax is recognised.
+		:- type foo ---> foo(field1::int).
+
 		% Check that promise declarations can be parsed
 		% and that every variable in the assertion doesn't
 		% need to be explicitly quantified.
 		:- promise all [[H,T,L]] (list__last([[H|T]], L)).
 		main --> 
-			print("Hello, world\n").
+			{ Foo = foo(1) },
+			( { Foo ^ field1 = 1 } ->
+				print("Hello, world\n")
+			;
+				[[]]
+			).
 EOF
 	if
 	 	 echo $BOOTSTRAP_MC conftest >&AC_FD_CC 2>&1 &&
Index: goal_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.60
diff -u -u -r1.60 goal_util.m
--- goal_util.m	1999/10/28 00:57:02	1.60
+++ goal_util.m	2000/02/04 05:45:16
@@ -130,6 +130,11 @@
 :- mode goal_calls_pred_id(in, in) is semidet.
 :- mode goal_calls_pred_id(in, out) is nondet.
 
+	% Test whether the goal contains a reconstruction
+	% (a construction where the `cell_to_reuse' field is `yes(_)').
+:- pred goal_contains_reconstruction(hlds_goal).
+:- mode goal_contains_reconstruction(in) is semidet.
+
 	% goal_contains_goal(Goal, SubGoal) is true iff Goal contains SubGoal,
 	% i.e. iff Goal = SubGoal or Goal contains SubGoal as a direct
 	% or indirect sub-goal.
@@ -786,6 +791,8 @@
 
 goal_expr_calls(conj(Goals), PredProcId) :-
 	goals_calls(Goals, PredProcId).
+goal_expr_calls(par_conj(Goals, _), PredProcId) :-
+	goals_calls(Goals, PredProcId).
 goal_expr_calls(disj(Goals, _), PredProcId) :-
 	goals_calls(Goals, PredProcId).
 goal_expr_calls(switch(_, _, Goals, _), PredProcId) :-
@@ -844,6 +851,8 @@
 
 goal_expr_calls_pred_id(conj(Goals), PredId) :-
 	goals_calls_pred_id(Goals, PredId).
+goal_expr_calls_pred_id(par_conj(Goals, _), PredId) :-
+	goals_calls_pred_id(Goals, PredId).
 goal_expr_calls_pred_id(disj(Goals, _), PredId) :-
 	goals_calls_pred_id(Goals, PredId).
 goal_expr_calls_pred_id(switch(_, _, Goals, _), PredId) :-
@@ -862,6 +871,43 @@
 	goal_calls_pred_id(Goal, PredId).
 goal_expr_calls_pred_id(call(PredId, _, _, _, _, _), PredId).
 
+%-----------------------------------------------------------------------------%
+ 
+goal_contains_reconstruction(_Goal - _) :-
+	% This will only succeed on the alias branch with structure reuse.
+	semidet_fail.
+	%goal_expr_contains_reconstruction(Goal).
+
+:- pred goal_expr_contains_reconstruction(hlds_goal_expr).
+:- mode goal_expr_contains_reconstruction(in) is semidet.
+
+goal_expr_contains_reconstruction(conj(Goals)) :-
+	goals_contain_reconstruction(Goals).
+goal_expr_contains_reconstruction(disj(Goals, _)) :-
+	goals_contain_reconstruction(Goals).
+goal_expr_contains_reconstruction(par_conj(Goals, _)) :-
+	goals_contain_reconstruction(Goals).
+goal_expr_contains_reconstruction(switch(_, _, Cases, _)) :-
+	list__member(Case, Cases),
+	Case = case(_, Goal),
+ 	goal_contains_reconstruction(Goal).
+goal_expr_contains_reconstruction(if_then_else(_, Cond, Then, Else, _)) :-
+ 	goals_contain_reconstruction([Cond, Then, Else]).
+goal_expr_contains_reconstruction(not(Goal)) :-
+	goal_contains_reconstruction(Goal).
+goal_expr_contains_reconstruction(some(_, _, Goal)) :-
+	goal_contains_reconstruction(Goal).
+goal_expr_contains_reconstruction(unify(_, _, _, Unify, _)) :-
+	Unify = construct(_, _, _, _, Reuse, _, _),
+	Reuse = yes(_).
+
+:- pred goals_contain_reconstruction(list(hlds_goal)).
+:- mode goals_contain_reconstruction(in) is semidet.
+
+goals_contain_reconstruction(Goals) :-
+	list__member(Goal, Goals),
+	goal_contains_reconstruction(Goal).
+ 
 %-----------------------------------------------------------------------------%
 
 	% goal_contains_goal(Goal, SubGoal) is true iff Goal contains SubGoal,
Index: hlds_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.67
diff -u -u -r1.67 hlds_goal.m
--- hlds_goal.m	2000/01/13 06:15:38	1.67
+++ hlds_goal.m	2000/02/07 03:38:22
@@ -400,6 +400,9 @@
 					% of the lambda expression.
 			maybe(cell_to_reuse),
 					% Cell to destructively update.
+					% Constructions for which this
+					% field is `yes(_)' are described
+					% as "reconstructions".
 			cell_is_unique,	% Can the cell be allocated
 					% in shared data.
 			maybe(rl_exprn_id)
@@ -621,20 +624,22 @@
 	% if this structure is modified.
 :- type hlds_goal_info
 	---> goal_info(
-		set(prog_var),	% the pre-birth set
-		set(prog_var),	% the post-birth set
-		set(prog_var),	% the pre-death set
-		set(prog_var),	% the post-death set
+		pre_births :: set(prog_var),	% the pre-birth set
+		post_births :: set(prog_var),	% the post-birth set
+		pre_deaths :: set(prog_var),	% the pre-death set
+		post_deaths :: set(prog_var),	% the post-death set
 				% (all four are computed by liveness.m)
 				% NB for atomic goals, the post-deadness
 				% should be applied _before_ the goal
 
-		determinism, 	% the overall determinism of the goal
+		determinism :: determinism, 
+				% the overall determinism of the goal
 				% (computed during determinism analysis)
 				% [because true determinism is undecidable,
 				% this may be a conservative approximation]
 
-		instmap_delta,	% the change in insts over this goal
+		instmap_delta :: instmap_delta,
+				% the change in insts over this goal
 				% (computed during mode analysis)
 				% [because true unreachability is undecidable,
 				% the instmap_delta may be reachable even
@@ -653,9 +658,10 @@
 				% conservative approximations, so if either
 				% says a goal is unreachable then it is.
 
-		prog_context,
+		context :: prog_context,
 
-		set(prog_var),	% the non-local vars in the goal,
+		nonlocals :: set(prog_var),
+				% the non-local vars in the goal,
 				% i.e. the variables that occur both inside
 				% and outside of the goal.
 				% (computed by quantification.m)
@@ -663,25 +669,46 @@
 				% conservative approximation: it may be
 				% a superset of the real non-locals]
 
-		maybe(follow_vars),
+		/*
+		code_gen_nonlocals :: maybe(set(prog_var)),
+				% the non-local vars in the goal,
+				% modified slightly for code generation.
+				% The difference between the code-gen nonlocals
+				% and the ordinary nonlocals is that arguments
+				% of a reconstruction which are taken from the
+				% reused cell are not considered to be
+				% `code_gen_nonlocals' of the goal.
+				% This avoids allocating stack slots and
+				% generating unnecessary field extraction
+				% instructions for those arguments.
+				% Mode information is still computed using
+				% the ordinary non-locals.
+				% 
+				% If the field has value `no', the ordinary
+				% nonlocals are used instead. This will
+				% be the case if the procedure body does not
+				% contain any reconstructions.
+		*/
+
+		follow_vars :: maybe(follow_vars),
 				% advisory information about where variables
 				% ought to be put next. The legal range
 				% includes the nonexistent register r(-1),
 				% which indicates any available register.
 
-		set(goal_feature),
+		features :: set(goal_feature),
 				% The set of used-defined "features" of
 				% this goal, which optimisers may wish
 				% to know about.
 
-		resume_point,
+		resume_point :: resume_point,
 				% If this goal establishes a resumption point,
 				% state what variables need to be saved for
 				% that resumption point, and which entry
 				% labels of the resumption point will be
 				% needed. (See compiler/notes/allocation.html)
 
-		goal_path
+		goal_path :: goal_path
 				% The path to this goal from the root in
 				% reverse order.
 	).
@@ -786,9 +813,16 @@
 :- pred goal_info_get_nonlocals(hlds_goal_info, set(prog_var)).
 :- mode goal_info_get_nonlocals(in, out) is det.
 
+:- pred goal_info_get_code_gen_nonlocals(hlds_goal_info, set(prog_var)).
+:- mode goal_info_get_code_gen_nonlocals(in, out) is det.
+
 :- pred goal_info_set_nonlocals(hlds_goal_info, set(prog_var), hlds_goal_info).
 :- mode goal_info_set_nonlocals(in, in, out) is det.
 
+:- pred goal_info_set_code_gen_nonlocals(hlds_goal_info,
+		set(prog_var), hlds_goal_info).
+:- mode goal_info_set_code_gen_nonlocals(in, in, out) is det.
+
 :- pred goal_info_get_features(hlds_goal_info, set(goal_feature)).
 :- mode goal_info_get_features(in, out) is det.
 
@@ -1056,106 +1090,74 @@
 	goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo1),
 	goal_info_set_instmap_delta(GoalInfo1, InstMapDelta, GoalInfo2),
 	goal_info_set_determinism(GoalInfo2, Detism, GoalInfo).
+
+goal_info_get_pre_births(GoalInfo, GoalInfo ^ pre_births).
+
+goal_info_get_post_births(GoalInfo, GoalInfo ^ post_births).
+
+goal_info_get_pre_deaths(GoalInfo, GoalInfo ^ pre_deaths).
+
+goal_info_get_post_deaths(GoalInfo, GoalInfo ^ post_deaths).
+
+goal_info_get_determinism(GoalInfo, GoalInfo ^ determinism).
+
+goal_info_get_instmap_delta(GoalInfo, GoalInfo ^ instmap_delta).
+
+goal_info_get_context(GoalInfo, GoalInfo ^ context).
+
+goal_info_get_nonlocals(GoalInfo, GoalInfo ^ nonlocals).
+
+	% The code-gen non-locals are always the same as the
+	% non-locals when structure reuse is not being performed.
+goal_info_get_code_gen_nonlocals(GoalInfo, NonLocals) :-
+	goal_info_get_nonlocals(GoalInfo, NonLocals).
+
+goal_info_get_follow_vars(GoalInfo, GoalInfo ^ follow_vars).
+
+goal_info_get_features(GoalInfo, GoalInfo ^ features).
+
+goal_info_get_resume_point(GoalInfo, GoalInfo ^ resume_point).
+
+goal_info_get_goal_path(GoalInfo, GoalInfo ^ goal_path).
+
+goal_info_set_pre_births(GoalInfo0, PreBirths,
+		GoalInfo0 ^ pre_births := PreBirths).
+
+goal_info_set_post_births(GoalInfo0, PostBirths,
+		GoalInfo0 ^ post_births := PostBirths).
+
+goal_info_set_pre_deaths(GoalInfo0, PreDeaths,
+		GoalInfo0 ^ pre_deaths := PreDeaths).
+
+goal_info_set_post_deaths(GoalInfo0, PostDeaths,
+		GoalInfo0 ^ post_deaths := PostDeaths).
+
+goal_info_set_determinism(GoalInfo0, Determinism,
+		GoalInfo0 ^ determinism := Determinism).
+
+goal_info_set_instmap_delta(GoalInfo0, InstMapDelta,
+		GoalInfo0 ^ instmap_delta := InstMapDelta).
+
+goal_info_set_context(GoalInfo0, Context, GoalInfo0 ^ context := Context).
+
+goal_info_set_nonlocals(GoalInfo0, NonLocals,
+		GoalInfo0 ^ nonlocals := NonLocals).
+
+	% The code-gen non-locals are always the same as the
+	% non-locals when structure reuse is not being performed.
+goal_info_set_code_gen_nonlocals(GoalInfo0, NonLocals, GoalInfo) :-
+	goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo).
 
-goal_info_get_pre_births(GoalInfo, PreBirths) :-
-	GoalInfo = goal_info(PreBirths, _, _, _, _, _, _, _, _, _, _, _).
+goal_info_set_follow_vars(GoalInfo0, FollowVars,
+		GoalInfo0 ^ follow_vars := FollowVars).
 
-goal_info_get_post_births(GoalInfo, PostBirths) :-
-	GoalInfo = goal_info(_, PostBirths, _, _, _, _, _, _, _, _, _, _).
+goal_info_set_features(GoalInfo0, Features, GoalInfo0 ^ features := Features).
 
-goal_info_get_pre_deaths(GoalInfo, PreDeaths) :-
-	GoalInfo = goal_info(_, _, PreDeaths, _, _, _, _, _, _, _, _, _).
+goal_info_set_resume_point(GoalInfo0, ResumePoint,
+		GoalInfo0 ^ resume_point := ResumePoint).
 
-goal_info_get_post_deaths(GoalInfo, PostDeaths) :-
-	GoalInfo = goal_info(_, _, _, PostDeaths, _, _, _, _, _, _, _, _).
-
-goal_info_get_determinism(GoalInfo, Determinism) :-
-	GoalInfo = goal_info(_, _, _, _, Determinism, _, _, _, _, _, _, _).
-
-goal_info_get_instmap_delta(GoalInfo, InstMapDelta) :-
-	GoalInfo = goal_info(_, _, _, _, _, InstMapDelta, _, _, _, _, _, _).
-
-goal_info_get_context(GoalInfo, Context) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, Context, _, _, _, _, _).
-
-goal_info_get_nonlocals(GoalInfo, NonLocals) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, NonLocals, _, _, _, _).
-
-goal_info_get_follow_vars(GoalInfo, MaybeFollowVars) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, MaybeFollowVars, _, _, _).
-
-goal_info_get_features(GoalInfo, Features) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, Features, _, _).
-
-goal_info_get_resume_point(GoalInfo, ResumePoint) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, ResumePoint, _).
-
-goal_info_get_goal_path(GoalInfo, GoalPath) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, _, GoalPath).
-
-% :- type hlds_goal_info
-% 	--->	goal_info(
-% 		A	set(prog_var),	% the pre-birth set
-% 		B	set(prog_var),	% the post-birth set
-% 		C	set(prog_var),	% the pre-death set
-% 		D	set(prog_var),	% the post-death set
-% 		E	determinism, 	% the overall determinism of the goal
-% 		F	instmap_delta,	% the change in insts over this goal
-% 		G	prog_context,
-% 		H	set(prog_var),	% the non-local vars in the goal
-% 		I	maybe(follow_vars),
-% 		J	set(goal_feature),
-%		K	resume_point,
-%		L	goal_path
-% 	).
-
-goal_info_set_pre_births(GoalInfo0, PreBirths, GoalInfo) :-
-	GoalInfo0 = goal_info(_, B, C, D, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(PreBirths, B, C, D, E, F, G, H, I, J, K, L).
-
-goal_info_set_post_births(GoalInfo0, PostBirths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, _, C, D, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, PostBirths, C, D, E, F, G, H, I, J, K, L).
-
-goal_info_set_pre_deaths(GoalInfo0, PreDeaths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, _, D, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, PreDeaths, D, E, F, G, H, I, J, K, L).
-
-goal_info_set_post_deaths(GoalInfo0, PostDeaths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, _, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, PostDeaths, E, F, G, H, I, J, K, L).
-
-goal_info_set_determinism(GoalInfo0, Determinism, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, _, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, D, Determinism, F, G, H, I, J, K, L).
-
-goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, _, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, D, E, InstMapDelta, G, H, I, J, K, L).
-
-goal_info_set_context(GoalInfo0, Context, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, _, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, D, E, F, Context, H, I, J, K, L).
-
-goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, _, I, J, K, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, NonLocals, I, J, K, L).
-
-goal_info_set_follow_vars(GoalInfo0, FollowVars, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, _, J, K, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, FollowVars, J, K, L).
-
-goal_info_set_features(GoalInfo0, Features, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, _, K, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, Features, K, L).
-
-goal_info_set_resume_point(GoalInfo0, ResumePoint, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, _, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, ResumePoint, L).
-
-goal_info_set_goal_path(GoalInfo0, GoalPath, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, K, _),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, K, GoalPath).
+goal_info_set_goal_path(GoalInfo0, GoalPath,
+		GoalInfo0 ^ goal_path := GoalPath).
 
 goal_info_get_code_model(GoalInfo, CodeModel) :-
 	goal_info_get_determinism(GoalInfo, Determinism),
Index: live_vars.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/live_vars.m,v
retrieving revision 1.85
diff -u -u -r1.85 live_vars.m
--- live_vars.m	1999/10/25 03:49:06	1.85
+++ live_vars.m	2000/02/04 05:14:01
@@ -191,7 +191,7 @@
 build_live_sets_in_goal_2(par_conj(Goals0, _SM), Liveness0, ResumeVars0,
 		LiveSets0, GoalInfo, ModuleInfo, ProcInfo, TypeInfoLiveness,
 		Liveness, ResumeVars, LiveSets) :-
-	goal_info_get_nonlocals(GoalInfo, NonLocals),
+	goal_info_get_code_gen_nonlocals(GoalInfo, NonLocals),
 	set__union(NonLocals, Liveness0, LiveSet),
 		% We insert all the union of the live vars and the nonlocals.
 		% Since each parallel conjunct may be run on a different
Index: liveness.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.102
diff -u -u -r1.102 liveness.m
--- liveness.m	1999/10/25 03:49:08	1.102
+++ liveness.m	2000/02/04 05:12:57
@@ -472,7 +472,7 @@
 detect_deadness_in_goal_2(par_conj(Goals0, SM), GoalInfo, Deadness0, LiveInfo,
 		Deadness, par_conj(Goals, SM)) :-
 	set__init(Union0),
-	goal_info_get_nonlocals(GoalInfo, NonLocals),
+	goal_info_get_code_gen_nonlocals(GoalInfo, NonLocals),
 	detect_deadness_in_par_conj(Goals0, Deadness0, NonLocals,
 		LiveInfo, Union0, Union, Goals),
 	set__union(Union, Deadness0, Deadness).
@@ -979,7 +979,7 @@
 		% typeinfo vars.
 	module_info_globals(ModuleInfo, Globals),
 	proc_info_goal(ProcInfo, _Goal - GoalInfo),
-	goal_info_get_nonlocals(GoalInfo, NonLocals0),
+	goal_info_get_code_gen_nonlocals(GoalInfo, NonLocals0),
 	module_info_pred_info(ModuleInfo, PredId, PredInfo),
 	body_should_use_typeinfo_liveness(Globals, TypeinfoLiveness),
 	pred_info_module(PredInfo, PredModule),
@@ -1172,7 +1172,7 @@
 
 liveness__get_nonlocals_and_typeinfos(LiveInfo, GoalInfo, 
 		NonLocals) :-
-	goal_info_get_nonlocals(GoalInfo, NonLocals0),
+	goal_info_get_code_gen_nonlocals(GoalInfo, NonLocals0),
 	live_info_get_typeinfo_liveness(LiveInfo, TypeinfoLiveness),
 	( 
 		TypeinfoLiveness = yes
Index: ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.27
diff -u -u -r1.27 ml_code_gen.m
--- ml_code_gen.m	2000/01/26 02:04:25	1.27
+++ ml_code_gen.m	2000/02/04 05:17:56
@@ -819,10 +819,10 @@
 	%
 	proc_info_headvars(ProcInfo, HeadVars),
 	Goal0 = GoalExpr - GoalInfo0,
-	goal_info_get_nonlocals(GoalInfo0, NonLocals0),
+	goal_info_get_code_gen_nonlocals(GoalInfo0, NonLocals0),
 	set__list_to_set(HeadVars, HeadVarsSet),
 	set__intersect(HeadVarsSet, NonLocals0, NonLocals),
-	goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo),
+	goal_info_set_code_gen_nonlocals(GoalInfo0, NonLocals, GoalInfo),
 	Goal = GoalExpr - GoalInfo,
 
 	goal_info_get_context(GoalInfo, Context),
@@ -996,7 +996,7 @@
 	goal_util__goal_vars(Goal, GoalVars),
 	% delete the non-locals
 	Goal = _ - GoalInfo,
-	goal_info_get_nonlocals(GoalInfo, NonLocalVars),
+	goal_info_get_code_gen_nonlocals(GoalInfo, NonLocalVars),
 	set__difference(GoalVars, NonLocalVars, LocalVars).
 
 :- func union_of_direct_subgoal_locals(hlds_goal) = set(prog_var).
Index: par_conj_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/par_conj_gen.m,v
retrieving revision 1.5
diff -u -u -r1.5 par_conj_gen.m
--- par_conj_gen.m	1999/08/30 04:57:54	1.5
+++ par_conj_gen.m	2000/02/04 05:15:07
@@ -128,7 +128,7 @@
 	{ globals__lookup_int_option(Globals, sync_term_size, STSize) },
 	code_info__get_known_variables(Vars),
 	code_info__save_variables_on_stack(Vars, SaveCode),
-	{ goal_info_get_nonlocals(GoalInfo, Nonlocals) },
+	{ goal_info_get_code_gen_nonlocals(GoalInfo, Nonlocals) },
 	{ set__to_sorted_list(Nonlocals, Variables) },
 	code_info__get_instmap(Initial),
 	{ goal_info_get_instmap_delta(GoalInfo, Delta) },
Index: quantification.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/quantification.m,v
retrieving revision 1.70
diff -u -u -r1.70 quantification.m
--- quantification.m	1999/12/22 03:31:24	1.70
+++ quantification.m	2000/02/07 01:49:02
@@ -41,6 +41,45 @@
 :- import_module hlds_goal, hlds_pred, prog_data.
 :- import_module map, list, set.
 
+	%
+	% When the compiler performs structure reuse, using
+	% the ordinary non-locals during code generation
+	% causes variables taken from the reused cell in
+	% a reconstruction to be extracted and possibly stored
+	% on the stack unnecessarily.
+	%
+	% For the example below, the variables `B' ... `H' are
+	% extracted from the term and stored on the stack across
+	% the call.
+	% 
+	% To avoid this, the compiler computes a set of `code-gen non-locals'
+	% which are the same as the ordinary non-locals, except that the
+	% variables taken from the reused cell are considered to be local
+	% to the goal. No renaming is performed when computing
+	% the code-gen non-locals to avoid stuffing up the ordinary
+	% non-locals.
+	%
+	% Mode information is always computed using the ordinary non-locals.
+	%
+	% :- pred update(X::in, foo::di, foo::uo) is det.
+	% update(A0, Foo0, Foo) :-
+	% 	Foo0 = foo(_, B, C, D, E, F, G, H),
+	%	some_call(A0, A),
+	% 	Foo0 = foo(A, B, C, D, E, F, G, H).
+	%
+:- type nonlocals_to_recompute
+	--->	ordinary_nonlocals
+	;	code_gen_nonlocals.
+
+:- pred implicitly_quantify_clause_body(nonlocals_to_recompute, list(prog_var),
+		hlds_goal, prog_varset, map(prog_var, type),
+		hlds_goal, prog_varset, map(prog_var, type),
+		list(quant_warning)).
+:- mode implicitly_quantify_clause_body(in, in, in, in, in, out, out, out, out)
+	is det.
+
+	
+	% As above, with `ordinary_nonlocals' passed as the first argument.
 :- pred implicitly_quantify_clause_body(list(prog_var),
 		hlds_goal, prog_varset, map(prog_var, type),
 		hlds_goal, prog_varset, map(prog_var, type),
@@ -48,11 +87,22 @@
 :- mode implicitly_quantify_clause_body(in, in, in, in, out, out, out, out)
 	is det.
 
+:- pred implicitly_quantify_goal(nonlocals_to_recompute, hlds_goal, prog_varset,
+		map(prog_var, type), set(prog_var), hlds_goal, prog_varset,
+		map(prog_var, type), list(quant_warning)).
+:- mode implicitly_quantify_goal(in, in, in, in, in,
+		out, out, out, out) is det.
+
+	% As above, with `ordinary_nonlocals' passed as the first argument.
 :- pred implicitly_quantify_goal(hlds_goal, prog_varset, map(prog_var, type),
-		set(prog_var), hlds_goal, prog_varset, map(prog_var, type),
-		list(quant_warning)).
+		set(prog_var), hlds_goal, prog_varset,
+		map(prog_var, type), list(quant_warning)).
 :- mode implicitly_quantify_goal(in, in, in, in, out, out, out, out) is det.
 
+:- pred requantify_proc(nonlocals_to_recompute, proc_info, proc_info) is det.
+:- mode requantify_proc(in, in, out) is det.
+
+	% As above, with `ordinary_nonlocals' passed as the first argument.
 :- pred requantify_proc(proc_info, proc_info) is det.
 :- mode requantify_proc(in, out) is det.
 
@@ -66,6 +116,11 @@
 	% quantification__goal_vars(Goal, Vars):
 	%	Vars is the set of variables that are free (unquantified)
 	%	in Goal.
+:- pred quantification__goal_vars(nonlocals_to_recompute,
+		hlds_goal, set(prog_var)).
+:- mode quantification__goal_vars(in, in, out) is det.
+
+	% As above, with `ordinary_nonlocals' passed as the first argument.
 :- pred quantification__goal_vars(hlds_goal, set(prog_var)).
 :- mode quantification__goal_vars(in, out) is det.
 
@@ -84,16 +139,18 @@
 	% 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.
+	% The nonlocals_to_recompute field is constant.
 :- type quant_info
 	--->	quant_info(
-			set(prog_var), % outside vars
-			set(prog_var), % quant vars
-			set(prog_var), % outside lambda vars
-			set(prog_var), % nonlocals
-			set(prog_var), % seen so far
-			prog_varset,
-			map(prog_var, type),
-			list(quant_warning)
+			nonlocals_to_recompute :: nonlocals_to_recompute,
+			outside :: set(prog_var),
+			quant_vars :: set(prog_var),
+			lambda_outside :: set(prog_var),
+			nonlocals :: set(prog_var),
+			seen :: set(prog_var),
+			varset :: prog_varset,
+			vartypes :: vartypes,
+			warnings :: list(quant_warning)
 		).
 
 	% `OutsideVars' are the variables that have occurred free outside
@@ -127,24 +184,68 @@
 
 implicitly_quantify_clause_body(HeadVars, Goal0, Varset0, VarTypes0,
 		Goal, Varset, VarTypes, Warnings) :-
+	implicitly_quantify_clause_body(ordinary_nonlocals,
+		HeadVars, Goal0, Varset0, VarTypes0,
+		Goal, Varset, VarTypes, Warnings).
+
+implicitly_quantify_clause_body(RecomputeNonLocals, HeadVars, Goal0,
+		Varset0, VarTypes0, Goal, Varset, VarTypes, Warnings) :-
 	set__list_to_set(HeadVars, OutsideVars),
-	implicitly_quantify_goal(Goal0, Varset0, VarTypes0,
+	implicitly_quantify_goal(RecomputeNonLocals, Goal0, Varset0, VarTypes0,
 			OutsideVars, Goal, Varset, VarTypes, Warnings).
 
 requantify_proc(ProcInfo0, ProcInfo) :-
+	requantify_proc(ordinary_nonlocals, ProcInfo0, ProcInfo).
+
+requantify_proc(RecomputeNonLocals, ProcInfo0, ProcInfo) :-
 	proc_info_varset(ProcInfo0, Varset0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
 	proc_info_headvars(ProcInfo0, HeadVars),
 	proc_info_goal(ProcInfo0, Goal0),
-	implicitly_quantify_clause_body(HeadVars, Goal0, Varset0, VarTypes0,
-		Goal, Varset, VarTypes, _),
+	implicitly_quantify_clause_body(RecomputeNonLocals, HeadVars,
+		Goal0, Varset0, VarTypes0, Goal, Varset, VarTypes, _),
 	proc_info_set_varset(ProcInfo0, Varset, ProcInfo1),
 	proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
 	proc_info_set_goal(ProcInfo2, Goal, ProcInfo).
 
 implicitly_quantify_goal(Goal0, Varset0, VarTypes0, OutsideVars,
-				Goal, Varset, VarTypes, Warnings) :-
-	quantification__init(OutsideVars, Varset0, VarTypes0, QuantInfo0),
+		Goal, Varset, VarTypes, Warnings) :-
+	implicitly_quantify_goal(ordinary_nonlocals, Goal0, Varset0, VarTypes0,
+		OutsideVars, Goal, Varset, VarTypes, Warnings).
+
+implicitly_quantify_goal(RecomputeNonLocals, Goal0, Varset0, VarTypes0,
+		OutsideVars, Goal, Varset, VarTypes, Warnings) :-
+	implicitly_quantify_goal_2(ordinary_nonlocals,
+		Goal0, Varset0, VarTypes0, OutsideVars,
+		Goal1, Varset1, VarTypes1, Warnings),
+	(
+		RecomputeNonLocals = code_gen_nonlocals,
+
+		% If the goal does not contain a reconstruction,
+		% the code-gen nonlocals and the ordinary non-locals
+		% are the same.
+		goal_contains_reconstruction(Goal1)
+	->
+		implicitly_quantify_goal_2(code_gen_nonlocals,
+			Goal1, Varset1, VarTypes1, OutsideVars,
+			Goal, Varset, VarTypes, _)
+	;
+		Goal = Goal1,
+		Varset = Varset1,
+		VarTypes = VarTypes1
+	).
+
+:- pred implicitly_quantify_goal_2(nonlocals_to_recompute, hlds_goal,
+		prog_varset, vartypes, set(prog_var), hlds_goal,
+		prog_varset, vartypes, list(quant_warning)).
+:- mode implicitly_quantify_goal_2(in, in, in, in, in,
+		out, out, out, out) is det.
+		
+implicitly_quantify_goal_2(RecomputeNonLocals,
+		Goal0, Varset0, VarTypes0, OutsideVars,
+		Goal, Varset, VarTypes, Warnings) :-
+	quantification__init(RecomputeNonLocals, OutsideVars,
+		Varset0, VarTypes0, QuantInfo0),
 	implicitly_quantify_goal(Goal0, Goal, QuantInfo0, QuantInfo),
 	quantification__get_varset(Varset, QuantInfo, _),
 	quantification__get_vartypes(VarTypes, QuantInfo, _),
@@ -160,11 +261,13 @@
 	{ goal_info_get_context(GoalInfo0, Context) },
 	implicitly_quantify_goal_2(Goal0, Context, Goal1),
 	quantification__get_nonlocals(NonLocalVars),
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
 	(
 		% If there are any variables that are local to the goal
 		% which we have come across before, then we rename them
 		% apart.
-		{ quantification__goal_vars(Goal0 - GoalInfo0, GoalVars0) },
+		{ quantification__goal_vars(NonLocalsToRecompute,
+			Goal0 - GoalInfo0, GoalVars0) },
 		{ set__difference(GoalVars0, NonLocalVars, LocalVars) },
 		{ set__intersect(SeenVars, LocalVars, RenameVars) },
 		{ \+ set__empty(RenameVars) }
@@ -175,7 +278,7 @@
 		{ Goal = Goal1 },
 		{ GoalInfo1 = GoalInfo0 }
 	),
-	{ goal_info_set_nonlocals(GoalInfo1, NonLocalVars, GoalInfo2) },
+	quantification__set_goal_nonlocals(GoalInfo1, NonLocalVars, GoalInfo2),
 	%
 	% If the non-locals set has shrunk (e.g. because some optimization
 	% optimizes away the other occurrences of a variable, causing it
@@ -292,7 +395,9 @@
 		{ goal_util__rename_var_list(Vars0, no, RenameMap, Vars) }
 	),
 	{ set__insert_list(QuantVars, Vars, QuantVars1) },
-	{ quantification__goal_vars(Then1, VarsThen, LambdaVarsThen) },
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
+	{ quantification__goal_vars(NonLocalsToRecompute,
+		Then1, VarsThen, LambdaVarsThen) },
 	{ set__union(OutsideVars, VarsThen, OutsideVars1) },
 	{ set__union(LambdaOutsideVars, LambdaVarsThen, LambdaOutsideVars1) },
 	quantification__set_quant_vars(QuantVars1),
@@ -334,19 +439,25 @@
 	quantification__get_outside(OutsideVars),
 	quantification__get_lambda_outside(LambdaOutsideVars),
 	{ quantification__get_unify_typeinfos(Unification0, TypeInfoVars) },
-	implicitly_quantify_unify_rhs(UnifyRHS0, Unification0, Context,
-		UnifyRHS, Unification),
+
+	{ Unification0 = construct(_, _, _, _, CellToReuse0, _, _) ->
+		CellToReuse = CellToReuse0
+	;
+		CellToReuse = no
+	},
+
+	implicitly_quantify_unify_rhs(UnifyRHS0, CellToReuse,
+		Unification0, Context, UnifyRHS, Unification),
 	quantification__get_nonlocals(VarsUnifyRHS),
 	{ set__insert(VarsUnifyRHS, Var, GoalVars0) },
 	{ set__insert_list(GoalVars0, TypeInfoVars, GoalVars1) },
-	{
-		Unification = construct(_, _, _, _, CellToReuse, _, _),
-		CellToReuse = yes(cell_to_reuse(ReuseVar, _, _))
-	->
+
+	{ CellToReuse = yes(cell_to_reuse(ReuseVar, _, _)) ->
 		set__insert(GoalVars1, ReuseVar, GoalVars)
 	;
 		GoalVars = GoalVars1
 	},
+
 	quantification__update_seen_vars(GoalVars),
 	{ set__intersect(GoalVars, OutsideVars, NonLocalVars1) },
 	{ set__intersect(GoalVars, LambdaOutsideVars, NonLocalVars2) },
@@ -358,6 +469,7 @@
 	implicitly_quantify_atomic_goal(Vars).
 
 implicitly_quantify_goal_2(bi_implication(LHS0, RHS0), Context, Goal) -->
+
 		% get the initial values of various settings
 	quantification__get_quant_vars(QuantVars0),
 	quantification__get_outside(OutsideVars0),
@@ -375,7 +487,9 @@
 		% prepare for quantifying the LHS:
 		% add variables from the RHS to the outside vars
 		% and the outside lambda vars sets.
-	{ quantification__goal_vars(RHS0, RHS_Vars, RHS_LambdaVars) },
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
+	{ quantification__goal_vars(NonLocalsToRecompute,
+			RHS0, RHS_Vars, RHS_LambdaVars) },
 	{ set__union(OutsideVars1, RHS_Vars, LHS_OutsideVars) },
 	{ set__union(LambdaOutsideVars1, RHS_LambdaVars,
 			LHS_LambdaOutsideVars) },
@@ -424,9 +538,11 @@
 		%
 	{ goal_info_init(GoalInfo0) },
 	{ goal_info_set_context(GoalInfo0, Context, GoalInfo1) },
-	{ goal_info_set_nonlocals(GoalInfo1, LHS_NonLocalVars, LHS_GI) },
-	{ goal_info_set_nonlocals(GoalInfo1, RHS_NonLocalVars, RHS_GI) },
-	{ goal_info_set_nonlocals(GoalInfo1, NonLocalVars, GI) },
+	quantification__set_goal_nonlocals(GoalInfo1,
+		LHS_NonLocalVars, LHS_GI),
+	quantification__set_goal_nonlocals(GoalInfo1,
+		RHS_NonLocalVars, RHS_GI),
+	quantification__set_goal_nonlocals(GoalInfo1, NonLocalVars, GI),
 	{ NotLHS = not(LHS) - LHS_GI },
 	{ NotRHS = not(RHS) - RHS_GI },
 	{ ForwardsImplication = not(conj([LHS, NotRHS]) - GI) - GI },
@@ -436,7 +552,8 @@
 		% we've just duplicated.
 		%
 	{ ReverseImplication0 = not(conj([RHS, NotLHS]) - GI) - GI },
-	{ quantification__goal_vars(ReverseImplication0, GoalVars) },
+	{ quantification__goal_vars(NonLocalsToRecompute,
+		ReverseImplication0, GoalVars) },
 	{ set__difference(GoalVars, NonLocalVars, RenameVars) },
 	quantification__rename_apart(RenameVars, _,
 		ReverseImplication0, ReverseImplication),
@@ -456,22 +573,35 @@
 	{ set__union(NonLocals1, NonLocals2, NonLocals) },
 	quantification__set_nonlocals(NonLocals).
 
-:- pred implicitly_quantify_unify_rhs(unify_rhs, unification, prog_context,
-					unify_rhs, unification,
-					quant_info, quant_info).
-:- mode implicitly_quantify_unify_rhs(in, in, in, out, out, in, out) is det.
+:- pred implicitly_quantify_unify_rhs(unify_rhs, maybe(cell_to_reuse),
+		unification, prog_context, unify_rhs, unification,
+		quant_info, quant_info).
+:- mode implicitly_quantify_unify_rhs(in, in, in, in,
+		out, out, in, out) is det.
 
-implicitly_quantify_unify_rhs(var(X), Unification, _, var(X), Unification) -->
+implicitly_quantify_unify_rhs(var(X), _, Unification, _,
+		var(X), Unification) -->
 	{ set__singleton_set(Vars, X) },
 	quantification__set_nonlocals(Vars).
-implicitly_quantify_unify_rhs(functor(Functor, ArgVars), Unification, _,
+implicitly_quantify_unify_rhs(functor(Functor, ArgVars), Reuse, Unification, _,
 				functor(Functor, ArgVars), Unification) -->
-	{ set__list_to_set(ArgVars, Vars) },
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
+	{
+		NonLocalsToRecompute = code_gen_nonlocals,
+		Reuse = yes(cell_to_reuse(_, _, SetArgs))
+	->
+		% The fields taken from the reused cell aren't
+		% counted as code-gen nonlocals.
+		quantification__get_updated_fields(SetArgs, ArgVars, Vars0),
+		set__list_to_set(Vars0, Vars)
+	;	
+		set__list_to_set(ArgVars, Vars)
+	},
 	quantification__set_nonlocals(Vars).
 implicitly_quantify_unify_rhs(
 		lambda_goal(PredOrFunc, EvalMethod, FixModes, LambdaNonLocals0,
 			LambdaVars0, Modes, Det, Goal0),
-		Unification0,
+		_, Unification0,
 		Context,
 		lambda_goal(PredOrFunc, EvalMethod, FixModes, LambdaNonLocals,
 			LambdaVars, Modes, Det, Goal),
@@ -577,7 +707,8 @@
 :- mode implicitly_quantify_conj(in, out, in, out) is det.
 
 implicitly_quantify_conj(Goals0, Goals) -->
-	{ get_vars(Goals0, FollowingVarsList) },
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
+	{ get_vars(NonLocalsToRecompute, Goals0, FollowingVarsList) },
 	implicitly_quantify_conj_2(Goals0, FollowingVarsList, Goals).
 
 :- pred implicitly_quantify_conj_2(list(hlds_goal), list(pair(set(prog_var))),
@@ -667,76 +798,100 @@
 	% contains following variables that occur not in lambda goals,
 	% and the second contains following variables that
 	% occur in lambda goals.
-
-:- pred get_vars(list(hlds_goal), list(pair(set(prog_var)))).
-:- mode get_vars(in, out) is det.
 
-get_vars([], []).
-get_vars([_Goal | Goals], [Set - LambdaSet | SetPairs]) :-
-	get_vars_2(Goals, Set, LambdaSet, SetPairs).
-
-:- pred get_vars_2(list(hlds_goal), set(prog_var), set(prog_var),
+:- pred get_vars(nonlocals_to_recompute, list(hlds_goal),
 		list(pair(set(prog_var)))).
-:- mode get_vars_2(in, out, out, out) is det.
+:- mode get_vars(in, in, out) is det.
+
+get_vars(_, [], []).
+get_vars(NonLocalsToRecompute, [_Goal | Goals],
+		[Set - LambdaSet | SetPairs]) :-
+	get_vars_2(NonLocalsToRecompute, Goals, Set, LambdaSet, SetPairs).
+
+:- pred get_vars_2(nonlocals_to_recompute, list(hlds_goal),
+		set(prog_var), set(prog_var), list(pair(set(prog_var)))).
+:- mode get_vars_2(in, in, out, out, out) is det.
 
-get_vars_2([], Set, LambdaSet, []) :-
+get_vars_2(_, [], Set, LambdaSet, []) :-
 	set__init(Set),
 	set__init(LambdaSet).
-get_vars_2([Goal | Goals], Set, LambdaSet, SetPairList) :-
-	get_vars_2(Goals, Set0, LambdaSet0, SetPairList0),
-	quantification__goal_vars(Goal, Set1, LambdaSet1),
+get_vars_2(NonLocalsToRecompute, [Goal | Goals],
+		Set, LambdaSet, SetPairList) :-
+	get_vars_2(NonLocalsToRecompute, Goals,
+		Set0, LambdaSet0, SetPairList0),
+	quantification__goal_vars(NonLocalsToRecompute,
+		Goal, Set1, LambdaSet1),
 	set__union(Set0, Set1, Set),
 	set__union(LambdaSet0, LambdaSet1, LambdaSet),
 	SetPairList = [Set0 - LambdaSet0 | SetPairList0].
-
-:- pred goal_list_vars_2(list(hlds_goal), set(prog_var), set(prog_var),
-			set(prog_var), set(prog_var)).
-:- mode goal_list_vars_2(in, in, in, out, out) is det.
-
-goal_list_vars_2([], Set, LambdaSet, Set, LambdaSet).
-goal_list_vars_2([Goal - _GoalInfo| Goals], Set0, LambdaSet0, Set, LambdaSet) :-
-	quantification__goal_vars_2(Goal, Set0, LambdaSet0, Set1, LambdaSet1),
-	goal_list_vars_2(Goals, Set1, LambdaSet1, Set, LambdaSet).
-
-:- pred case_list_vars_2(list(case), set(prog_var), set(prog_var),
-		set(prog_var), set(prog_var)).
-:- mode case_list_vars_2(in, in, in, out, out) is det.
 
-case_list_vars_2([], Set, LambdaSet, Set, LambdaSet).
-case_list_vars_2([case(_Cons, Goal - _GoalInfo)| Cases], Set0, LambdaSet0,
-			Set, LambdaSet) :-
-	quantification__goal_vars_2(Goal, Set0, LambdaSet0, Set1, LambdaSet1),
-	case_list_vars_2(Cases, Set1, LambdaSet1, Set, LambdaSet).
+:- pred goal_list_vars_2(nonlocals_to_recompute, list(hlds_goal),
+		set(prog_var), set(prog_var), set(prog_var), set(prog_var)).
+:- mode goal_list_vars_2(in, in, in, in, out, out) is det.
+
+goal_list_vars_2(_, [], Set, LambdaSet, Set, LambdaSet).
+goal_list_vars_2(NonLocalsToRecompute, [Goal - _GoalInfo| Goals],
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	quantification__goal_vars_2(NonLocalsToRecompute,
+		Goal, Set0, LambdaSet0, Set1, LambdaSet1),
+	goal_list_vars_2(NonLocalsToRecompute, Goals,
+		Set1, LambdaSet1, Set, LambdaSet).
+
+:- pred case_list_vars_2(nonlocals_to_recompute, list(case),
+		set(prog_var), set(prog_var), set(prog_var), set(prog_var)).
+:- mode case_list_vars_2(in, in, in, in, out, out) is det.
+
+case_list_vars_2(_, [], Set, LambdaSet, Set, LambdaSet).
+case_list_vars_2(NonLocalsToRecompute,
+		[case(_Cons, Goal - _GoalInfo)| Cases], Set0,
+		LambdaSet0, Set, LambdaSet) :-
+	quantification__goal_vars_2(NonLocalsToRecompute,
+		Goal, Set0, LambdaSet0, Set1, LambdaSet1),
+	case_list_vars_2(NonLocalsToRecompute, Cases,
+		Set1, LambdaSet1, Set, LambdaSet).
 
-	% quantification__goal_vars(Goal, Vars):
+	% quantification__goal_vars(NonLocalsToRecompute, Goal, Vars):
 	%	Vars is the set of variables that occur free (unquantified)
-	%	in Goal.
-quantification__goal_vars(Goal, BothSet) :-
-	quantification__goal_vars(Goal, NonLambdaSet, LambdaSet),
+	%	in Goal, excluding unset fields of reconstructions if
+	%	NonLocalsToRecompute is `code_gen_nonlocals'.
+quantification__goal_vars(NonLocalsToRecompute, Goal, BothSet) :-
+	quantification__goal_vars(NonLocalsToRecompute,
+		Goal, NonLambdaSet, LambdaSet),
 	set__union(NonLambdaSet, LambdaSet, BothSet).
 
+quantification__goal_vars(Goal, BothSet) :-
+	quantification__goal_vars(ordinary_nonlocals, Goal, BothSet).
+
 	% quantification__goal_vars(Goal, NonLambdaSet, LambdaSet):
 	%	Set is the set of variables that occur free (unquantified)
 	%	in Goal, not counting occurrences in lambda expressions.
 	%	LambdaSet is the set of variables that occur free (unquantified)
 	%	in lambda expressions in Goal.
-:- pred quantification__goal_vars(hlds_goal, set(prog_var), set(prog_var)).
-:- mode quantification__goal_vars(in, out, out) is det.
+:- pred quantification__goal_vars(nonlocals_to_recompute,
+		hlds_goal, set(prog_var), set(prog_var)).
+:- mode quantification__goal_vars(in, in, out, out) is det.
 
-quantification__goal_vars(Goal - _GoalInfo, Set, LambdaSet) :-
+quantification__goal_vars(NonLocalsToRecompute,
+		Goal - _GoalInfo, Set, LambdaSet) :-
 	set__init(Set0),
 	set__init(LambdaSet0),
-	quantification__goal_vars_2(Goal, Set0, LambdaSet0, Set, LambdaSet).
+	quantification__goal_vars_2(NonLocalsToRecompute,
+		Goal, Set0, LambdaSet0, Set, LambdaSet).
 
-:- pred quantification__goal_vars_2(hlds_goal_expr, set(prog_var),
-		set(prog_var), set(prog_var), set(prog_var)).
-:- mode quantification__goal_vars_2(in, in, in, out, out) is det.
+:- pred quantification__goal_vars_2(nonlocals_to_recompute, hlds_goal_expr,
+		set(prog_var), set(prog_var), set(prog_var), set(prog_var)).
+:- mode quantification__goal_vars_2(in, in, in, in, out, out) is det.
 
-quantification__goal_vars_2(unify(A, B, _, Unification, _), Set0, LambdaSet0,
+quantification__goal_vars_2(NonLocalsToRecompute,
+		unify(A, B, _, Unification, _), Set0, LambdaSet0,
 		Set, LambdaSet) :-
 	set__insert(Set0, A, Set1),
+	( Unification = construct(_, _, _, _, Reuse0, _, _) ->
+		Reuse = Reuse0
+	;
+		Reuse = no
+	),
 	(
-		Unification = construct(_, _, _, _, Reuse, _, _),
 		Reuse = yes(cell_to_reuse(ReuseVar, _, _))
 	->
 		set__insert(Set1, ReuseVar, Set2)
@@ -747,87 +902,148 @@
 	;
 		Set2 = Set1
 	),
-	quantification__unify_rhs_vars(B, Set2, LambdaSet0, Set, LambdaSet).
+	quantification__unify_rhs_vars(NonLocalsToRecompute, B, Reuse,
+		Set2, LambdaSet0, Set, LambdaSet).
 
-quantification__goal_vars_2(generic_call(GenericCall, ArgVars1, _, _),
+quantification__goal_vars_2(_, generic_call(GenericCall, ArgVars1, _, _),
 		Set0, LambdaSet, Set, LambdaSet) :-
 	goal_util__generic_call_vars(GenericCall, ArgVars0),
 	set__insert_list(Set0, ArgVars0, Set1),
 	set__insert_list(Set1, ArgVars1, Set).
 
-quantification__goal_vars_2(call(_, _, ArgVars, _, _, _), Set0, LambdaSet,
+quantification__goal_vars_2(_, call(_, _, ArgVars, _, _, _), Set0, LambdaSet,
 		Set, LambdaSet) :-
 	set__insert_list(Set0, ArgVars, Set).
-
-quantification__goal_vars_2(conj(Goals), Set0, LambdaSet0, Set, LambdaSet) :-
-	goal_list_vars_2(Goals, Set0, LambdaSet0, Set, LambdaSet).
-
-quantification__goal_vars_2(par_conj(Goals, _SM), Set0, LambdaSet0, Set, LambdaSet) :-
-	goal_list_vars_2(Goals, Set0, LambdaSet0, Set, LambdaSet).
 
-quantification__goal_vars_2(disj(Goals, _), Set0, LambdaSet0, Set, LambdaSet) :-
-	goal_list_vars_2(Goals, Set0, LambdaSet0, Set, LambdaSet).
+quantification__goal_vars_2(NonLocalsToRecompute, conj(Goals),
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	goal_list_vars_2(NonLocalsToRecompute, Goals,
+		Set0, LambdaSet0, Set, LambdaSet).
+
+quantification__goal_vars_2(NonLocalsToRecompute, par_conj(Goals, _SM),
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	goal_list_vars_2(NonLocalsToRecompute, Goals,
+		Set0, LambdaSet0, Set, LambdaSet).
+
+quantification__goal_vars_2(NonLocalsToRecompute, disj(Goals, _),
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	goal_list_vars_2(NonLocalsToRecompute, Goals, Set0, LambdaSet0,
+		Set, LambdaSet).
 
-quantification__goal_vars_2(switch(Var, _Det, Cases, _), Set0, LambdaSet0,
-		Set, LambdaSet) :-
+quantification__goal_vars_2(NonLocalsToRecompute, switch(Var, _Det, Cases, _),
+		Set0, LambdaSet0, Set, LambdaSet) :-
 	set__insert(Set0, Var, Set1),
-	case_list_vars_2(Cases, Set1, LambdaSet0, Set, LambdaSet).
+	case_list_vars_2(NonLocalsToRecompute, Cases,
+		Set1, LambdaSet0, Set, LambdaSet).
 
-quantification__goal_vars_2(some(Vars, _, Goal), Set0, LambdaSet0,
-		Set, LambdaSet) :-
-	quantification__goal_vars(Goal, Set1, LambdaSet1),
+quantification__goal_vars_2(NonLocalsToRecompute, some(Vars, _, Goal),
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	quantification__goal_vars(NonLocalsToRecompute,
+		Goal, Set1, LambdaSet1),
 	set__delete_list(Set1, Vars, Set2),
 	set__delete_list(LambdaSet1, Vars, LambdaSet2),
 	set__union(Set0, Set2, Set),
 	set__union(LambdaSet0, LambdaSet2, LambdaSet).
 
-quantification__goal_vars_2(not(Goal - _GoalInfo), Set0, LambdaSet0,
-		Set, LambdaSet) :-
-	quantification__goal_vars_2(Goal, Set0, LambdaSet0, Set, LambdaSet).
-
-quantification__goal_vars_2(if_then_else(Vars, A, B, C, _), Set0, LambdaSet0,
-		Set, LambdaSet) :-
+quantification__goal_vars_2(NonLocalsToRecompute, not(Goal - _GoalInfo),
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	quantification__goal_vars_2(NonLocalsToRecompute, Goal,
+		Set0, LambdaSet0, Set, LambdaSet).
+
+quantification__goal_vars_2(NonLocalsToRecompute,
+		if_then_else(Vars, A, B, C, _),
+		Set0, LambdaSet0, Set, LambdaSet) :-
 	% This code does the following:
 	%     Set = Set0 + ( (vars(A) + vars(B)) \ Vars ) + vars(C)
 	% where `+' is set union and `\' is relative complement.
-	quantification__goal_vars(A, Set1, LambdaSet1),
-	quantification__goal_vars(B, Set2, LambdaSet2),
+	quantification__goal_vars(NonLocalsToRecompute, A, Set1, LambdaSet1),
+	quantification__goal_vars(NonLocalsToRecompute, B, Set2, LambdaSet2),
 	set__union(Set1, Set2, Set3),
 	set__union(LambdaSet1, LambdaSet2, LambdaSet3),
 	set__delete_list(Set3, Vars, Set4),
 	set__delete_list(LambdaSet3, Vars, LambdaSet4),
 	set__union(Set0, Set4, Set5),
 	set__union(LambdaSet0, LambdaSet4, LambdaSet5),
-	quantification__goal_vars(C, Set6, LambdaSet6),
+	quantification__goal_vars(NonLocalsToRecompute, C, Set6, LambdaSet6),
 	set__union(Set5, Set6, Set),
 	set__union(LambdaSet5, LambdaSet6, LambdaSet).
 
-quantification__goal_vars_2(pragma_c_code(_, _, _, ArgVars, _, _, _),
+quantification__goal_vars_2(_, pragma_c_code(_, _, _, ArgVars, _, _, _),
 		Set0, LambdaSet, Set, LambdaSet) :-
 	set__insert_list(Set0, ArgVars, Set).
+
+quantification__goal_vars_2(NonLocalsToRecompute, bi_implication(LHS, RHS),
+		Set0, LambdaSet0, Set, LambdaSet) :-
+	goal_list_vars_2(NonLocalsToRecompute, [LHS, RHS],
+		Set0, LambdaSet0, Set, LambdaSet).
 
-quantification__goal_vars_2(bi_implication(LHS, RHS), Set0, LambdaSet0, Set,
-		LambdaSet) :-
-	goal_list_vars_2([LHS, RHS], Set0, LambdaSet0, Set, LambdaSet).
-
-:- pred quantification__unify_rhs_vars(unify_rhs, set(prog_var), set(prog_var),
-					set(prog_var), set(prog_var)).
-:- mode quantification__unify_rhs_vars(in, in, in, out, out) is det.
+:- pred quantification__unify_rhs_vars(nonlocals_to_recompute, unify_rhs,
+		maybe(cell_to_reuse), set(prog_var), set(prog_var),
+		set(prog_var), set(prog_var)).
+:- mode quantification__unify_rhs_vars(in, in, in, in, in, out, out) is det.
 
-quantification__unify_rhs_vars(var(X), Set0, LambdaSet, Set, LambdaSet) :-
+quantification__unify_rhs_vars(_, var(X), _,
+		Set0, LambdaSet, Set, LambdaSet) :-
 	set__insert(Set0, X, Set).
-quantification__unify_rhs_vars(functor(_Functor, ArgVars), Set0, LambdaSet,
-		Set, LambdaSet) :-
-	set__insert_list(Set0, ArgVars, Set).
-quantification__unify_rhs_vars(
+quantification__unify_rhs_vars(NonLocalsToRecompute,
+		functor(_Functor, ArgVars), Reuse,
+		Set0, LambdaSet, Set, LambdaSet) :-
+	(
+		NonLocalsToRecompute = code_gen_nonlocals,
+		Reuse = yes(cell_to_reuse(_, _, SetArgs))
+	->
+		% Ignore the fields taken from the reused cell.
+		quantification__get_updated_fields(SetArgs, ArgVars,
+			ArgsToSet),
+		set__insert_list(Set0, ArgsToSet, Set)
+	;
+		set__insert_list(Set0, ArgVars, Set)
+	).
+quantification__unify_rhs_vars(NonLocalsToRecompute,
 		lambda_goal(_POrF, _E, _F, _N, LambdaVars, _M, _D, Goal), 
-		Set, LambdaSet0, Set, LambdaSet) :-
+		_, Set, LambdaSet0, Set, LambdaSet) :-
 	% Note that the NonLocals list is not counted, since all the 
 	% variables in that list must occur in the goal.
-	quantification__goal_vars(Goal, GoalVars),
+	quantification__goal_vars(NonLocalsToRecompute, Goal, GoalVars),
 	set__delete_list(GoalVars, LambdaVars, GoalVars1),
 	set__union(LambdaSet0, GoalVars1, LambdaSet).
 
+:- pred quantification__insert_set_fields(list(bool), list(prog_var),
+		set(prog_var), set(prog_var)).
+:- mode quantification__insert_set_fields(in, in, in, out) is det.
+
+quantification__insert_set_fields(SetArgs, Args, Set0, Set) :-
+	quantification__get_updated_fields(SetArgs, Args,  ArgsToSet),
+	set__insert_list(Set0, ArgsToSet, Set).
+
+:- pred quantification__get_updated_fields(list(bool),
+		list(prog_var), list(prog_var)).
+:- mode quantification__get_updated_fields(in, in, out) is det.
+
+quantification__get_updated_fields(SetArgs, Args, ArgsToSet) :-
+	quantification__get_updated_fields(SetArgs, Args, [], ArgsToSet).
+
+:- pred quantification__get_updated_fields(list(bool),
+		list(prog_var), list(prog_var), list(prog_var)).
+:- mode quantification__get_updated_fields(in, in, in, out) is det.
+
+quantification__get_updated_fields([], [], Fields, Fields).
+quantification__get_updated_fields([], [_|_], _, _) :-
+	error("quantification__get_updated_fields").
+quantification__get_updated_fields([_|_], [], _, _) :-
+	error("quantification__get_updated_fields").
+quantification__get_updated_fields([SetArg | SetArgs], [Arg | Args],
+		ArgsToSet0, ArgsToSet) :-
+	(
+		SetArg = yes,
+		ArgsToSet1 = [Arg | ArgsToSet0]
+	;
+		SetArg = no,
+		ArgsToSet1 = ArgsToSet0
+	),
+	quantification__get_updated_fields(SetArgs, Args,
+		ArgsToSet1, ArgsToSet).
+
 :- pred quantification__get_unify_typeinfos(unification, list(prog_var)).
 :- mode quantification__get_unify_typeinfos(in, out) is det.
 
@@ -862,7 +1078,21 @@
 :- mode quantification__rename_apart(in, out, in, out, in, out) is det.
 
 quantification__rename_apart(RenameSet, RenameMap, Goal0, Goal) -->
-	( { set__empty(RenameSet) } ->
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
+	( 
+		%
+		% Don't rename apart variables when recomputing the
+		% code-gen nonlocals -- that would stuff up the
+		% ordinary non-locals and the mode information.
+		% The ordinary non-locals are always recomputed
+		% before the code-gen nonlocals -- any necessary
+		% renaming will have been done while recomputing
+		% the ordinary non-locals.
+		%
+		{ set__empty(RenameSet)
+		; NonLocalsToRecompute = code_gen_nonlocals
+		}
+	->
 		{ map__init(RenameMap) },
 		{ Goal = Goal0 }
 	;
@@ -890,129 +1120,133 @@
 	).
 
 %-----------------------------------------------------------------------------%
+
+:- pred quantification__set_goal_nonlocals(hlds_goal_info,
+		set(prog_var), hlds_goal_info, quant_info, quant_info).
+:- mode quantification__set_goal_nonlocals(in, in, out, in, out) is det.
+
+quantification__set_goal_nonlocals(GoalInfo0, NonLocals, GoalInfo) -->
+	quantification__get_nonlocals_to_recompute(NonLocalsToRecompute),
+	{
+		NonLocalsToRecompute = ordinary_nonlocals,
+		goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo)
+	;
+		NonLocalsToRecompute = code_gen_nonlocals,
+		goal_info_set_code_gen_nonlocals(GoalInfo0,
+			NonLocals, GoalInfo)
+	}.
+
+%-----------------------------------------------------------------------------%
 
-:- pred quantification__init(set(prog_var), prog_varset, map(prog_var, type),
-		quant_info).
-:- mode quantification__init(in, in, in, out) is det.
+%-----------------------------------------------------------------------------%
+
+:- pred quantification__init(nonlocals_to_recompute, set(prog_var),
+		prog_varset, map(prog_var, type), quant_info).
+:- mode quantification__init(in, in, in, in, out) is det.
 
-quantification__init(OutsideVars, Varset, VarTypes, QuantInfo) :-
+quantification__init(RecomputeNonLocals, OutsideVars,
+		Varset, VarTypes, QuantInfo) :-
 	set__init(QuantVars),
 	set__init(NonLocals),
 	set__init(LambdaOutsideVars),
 	Seen = OutsideVars,
 	OverlapWarnings = [],
-	QuantInfo = quant_info(OutsideVars, QuantVars, LambdaOutsideVars,
-		NonLocals, Seen, Varset, VarTypes, OverlapWarnings).
+	QuantInfo = quant_info(RecomputeNonLocals, OutsideVars, QuantVars,
+		LambdaOutsideVars, NonLocals, Seen, Varset, VarTypes,
+		OverlapWarnings).
+
+:- pred quantification__get_nonlocals_to_recompute(nonlocals_to_recompute,
+		quant_info, quant_info).
+:- mode quantification__get_nonlocals_to_recompute(out, in, out) is det.
+
+quantification__get_nonlocals_to_recompute(Q ^ nonlocals_to_recompute, Q, Q).
 
 :- pred quantification__get_outside(set(prog_var), quant_info, quant_info).
 :- mode quantification__get_outside(out, in, out) is det.
 
-quantification__get_outside(A, Q, Q) :-
-	Q = quant_info(A, _, _, _, _, _, _, _).
+quantification__get_outside(Q ^ outside, Q, Q).
 
 :- pred quantification__set_outside(set(prog_var), quant_info, quant_info).
 :- mode quantification__set_outside(in, in, out) is det.
 
-quantification__set_outside(A, Q0, Q) :-
-	Q0 = quant_info(_, B, C, D, E, F, G, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_outside(Outside, Q0, Q0 ^ outside := Outside).
 
 :- pred quantification__get_quant_vars(set(prog_var), quant_info, quant_info).
 :- mode quantification__get_quant_vars(out, in, out) is det.
 
-quantification__get_quant_vars(B, Q, Q) :-
-	Q = quant_info(_, B, _, _, _, _, _, _).
+quantification__get_quant_vars(Q ^ quant_vars, Q, Q).
 
 :- pred quantification__set_quant_vars(set(prog_var), quant_info, quant_info).
 :- mode quantification__set_quant_vars(in, in, out) is det.
 
-quantification__set_quant_vars(B, Q0, Q) :-
-	Q0 = quant_info(A, _, C, D, E, F, G, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_quant_vars(QuantVars, Q0, Q0 ^ quant_vars := QuantVars).
 
 :- pred quantification__get_lambda_outside(set(prog_var),
 		quant_info, quant_info).
 :- mode quantification__get_lambda_outside(out, in, out) is det.
 
-quantification__get_lambda_outside(C, Q, Q) :-
-	Q  = quant_info(_, _, C, _, _, _, _, _).
+quantification__get_lambda_outside(Q ^ lambda_outside, Q, Q).
 
 :- pred quantification__set_lambda_outside(set(prog_var),
 		quant_info, quant_info).
 :- mode quantification__set_lambda_outside(in, in, out) is det.
 
-quantification__set_lambda_outside(C, Q0, Q) :-
-	Q0 = quant_info(A, B, _, D, E, F, G, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_lambda_outside(LambdaOutsideVars, Q0,
+		Q0 ^ lambda_outside := LambdaOutsideVars).
 
 :- pred quantification__get_nonlocals(set(prog_var), quant_info, quant_info).
 :- mode quantification__get_nonlocals(out, in, out) is det.
 
-quantification__get_nonlocals(D, Q, Q) :-
-	Q  = quant_info(_, _, _, D, _, _, _, _).
+quantification__get_nonlocals(Q ^ nonlocals, Q, Q).
 
 :- pred quantification__set_nonlocals(set(prog_var), quant_info, quant_info).
 :- mode quantification__set_nonlocals(in, in, out) is det.
 
-quantification__set_nonlocals(D, Q0, Q) :-
-	Q0 = quant_info(A, B, C, _, E, F, G, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_nonlocals(NonLocals, Q0, Q0 ^ nonlocals := NonLocals).
 
 :- pred quantification__get_seen(set(prog_var), quant_info, quant_info).
 :- mode quantification__get_seen(out, in, out) is det.
 
-quantification__get_seen(E, Q, Q) :-
-	Q  = quant_info(_, _, _, _, E, _, _, _).
+quantification__get_seen(Q ^ seen, Q, Q).
 
 :- pred quantification__set_seen(set(prog_var), quant_info, quant_info).
 :- mode quantification__set_seen(in, in, out) is det.
 
-quantification__set_seen(E, Q0, Q) :-
-	Q0 = quant_info(A, B, C, D, _, F, G, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_seen(Seen, Q0, Q0 ^ seen := Seen).
 
 :- pred quantification__get_varset(prog_varset, quant_info, quant_info).
 :- mode quantification__get_varset(out, in, out) is det.
 
-quantification__get_varset(F, Q, Q) :-
-	Q  = quant_info(_, _, _, _, _, F, _, _).
+quantification__get_varset(Q ^ varset, Q, Q).
 
 :- pred quantification__set_varset(prog_varset, quant_info, quant_info).
 :- mode quantification__set_varset(in, in, out) is det.
 
-quantification__set_varset(F, Q0, Q) :-
-	Q0 = quant_info(A, B, C, D, E, _, G, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_varset(Varset, Q0, Q0 ^ varset := Varset).
 
 :- pred quantification__get_vartypes(map(prog_var, type),
 		quant_info, quant_info).
 :- mode quantification__get_vartypes(out, in, out) is det.
 
-quantification__get_vartypes(G, Q, Q) :-
-	Q  = quant_info(_, _, _, _, _, _, G, _).
+quantification__get_vartypes(Q ^ vartypes, Q, Q).
 
 :- pred quantification__set_vartypes(map(prog_var, type),
 		quant_info, quant_info).
 :- mode quantification__set_vartypes(in, in, out) is det.
 
-quantification__set_vartypes(G, Q0, Q) :-
-	Q0 = quant_info(A, B, C, D, E, F, _, H),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_vartypes(VarTypes, Q0, Q0 ^ vartypes := VarTypes).
 
 :- pred quantification__get_warnings(list(quant_warning),
 					quant_info, quant_info).
 :- mode quantification__get_warnings(out, in, out) is det.
 
-quantification__get_warnings(H, Q, Q) :-
-	Q  = quant_info(_, _, _, _, _, _, _, H).
+quantification__get_warnings(Q ^ warnings, Q, Q).
 
 :- pred quantification__set_warnings(list(quant_warning),
 					quant_info, quant_info).
 :- mode quantification__set_warnings(in, in, out) is det.
 
-quantification__set_warnings(H, Q0, Q) :-
-	Q0 = quant_info(A, B, C, D, E, F, G, _),
-	Q  = quant_info(A, B, C, D, E, F, G, H).
+quantification__set_warnings(Warnings, Q0, Q0 ^ warnings := Warnings).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list