[m-dev.] for review: fixing cse_detection for existential types

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Dec 8 17:50:58 AEDT 2000


On 06-Dec-2000, David Glen JEFFERY <dgj at cs.mu.OZ.AU> wrote:
> > compiler/cse_detection.m:
> > 	Fix common subexpression elimination so that it works when the
> > 	deconstruction it hoists out of a branched control structure
> > 	involves a functor with existentially typed arguments.
> > 
> > compiler/options.m:
> > 	Put the default value of --compare-specialization back to 4, now
> > 	that the bug that prevented it from working at levels above 1 has
> > 	been fixed.
> 
> This basically looks pretty good. A couple of comments, though.

I followed your comments, and fixed the bug that caused the stage 3 mode
errors. Here is the log message and diff I am committing.

compiler/cse_detection.m:
	Put back the earlier clarification of cse_detection code, but without
	the bug this time :-( The bug was that cse_detection did not insist
	on all branches of the branched control structure containing a copy
	of the "common" deconstruction unification. By hoisting that
	unification before the branched control structure, cse_detection
	was effectively adding a test into some computation paths.

	Fix common subexpression elimination so that it works when the
	deconstruction it hoists out of a branched control structure
	involves a functor with existentially typed arguments.

compiler/switch_detection.m:
	Modify the code called by cse_detection to look for deconstruction
	unifications to make it explicit whether the search was successful.

compiler/options.m:
	Put the default value of --compare-specialization back to 4, now
	that the bug that prevented it from working at levels above 1 (in the
	presence of existentially typed arguments) has been fixed.

Zoltan.

cvs diff: Diffing .
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/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/cse_detection.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/cse_detection.m,v
retrieving revision 1.67
diff -u -b -r1.67 cse_detection.m
--- compiler/cse_detection.m	2000/12/06 16:48:24	1.67
+++ compiler/cse_detection.m	2000/12/07 07:59:55
@@ -20,13 +20,12 @@
 
 :- import_module hlds_module, hlds_pred, io.
 
-:- pred detect_cse(module_info, module_info, io__state, io__state).
-:- mode detect_cse(in, out, di, uo) is det.
+:- pred detect_cse(module_info::in, module_info::out,
+	io__state::di, io__state::uo) is det.
 
-:- pred detect_cse_in_proc(proc_id, pred_id, module_info, module_info,
-			io__state, io__state).
-% :- mode detect_cse_in_proc(in, in, di, uo, di, uo) is det.
-:- mode detect_cse_in_proc(in, in, in, out, di, uo) is det.
+:- pred detect_cse_in_proc(proc_id::in, pred_id::in,
+	module_info::in, module_info::out, io__state::di, io__state::uo)
+	is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -34,11 +33,12 @@
 :- implementation.
 
 :- import_module hlds_goal, hlds_data, options, globals, goal_util, hlds_out.
-:- import_module modes, mode_util, quantification, instmap.
+:- import_module type_util, modes, mode_util, quantification, instmap.
 :- import_module prog_data, switch_detection, det_util, inst_match.
 :- import_module switch_detection, term, varset.
 
-:- import_module int, bool, list, map, set, std_util, require.
+:- import_module int, bool, list, assoc_list, map, multi_map.
+:- import_module set, std_util, require.
 
 %-----------------------------------------------------------------------------%
 
@@ -49,9 +49,9 @@
 	{ module_info_predids(ModuleInfo0, PredIds) },
 	detect_cse_in_preds(PredIds, ModuleInfo0, ModuleInfo).
 
-:- pred detect_cse_in_preds(list(pred_id), module_info, module_info,
-	io__state, io__state).
-:- mode detect_cse_in_preds(in, in, out, di, uo) is det.
+:- pred detect_cse_in_preds(list(pred_id)::in,
+	module_info::in, module_info::out, io__state::di, io__state::uo)
+	is det.
 
 detect_cse_in_preds([], ModuleInfo, ModuleInfo) --> [].
 detect_cse_in_preds([PredId | PredIds], ModuleInfo0, ModuleInfo) -->
@@ -60,18 +60,17 @@
 	detect_cse_in_pred(PredId, PredInfo, ModuleInfo0, ModuleInfo1),
 	detect_cse_in_preds(PredIds, ModuleInfo1, ModuleInfo).
 
-:- pred detect_cse_in_pred(pred_id, pred_info, module_info, module_info,
-	io__state, io__state).
-:- mode detect_cse_in_pred(in, in, in, out, di, uo) is det.
+:- pred detect_cse_in_pred(pred_id::in, pred_info::in,
+	module_info::in, module_info::out, io__state::di, io__state::uo)
+	is det.
 
 detect_cse_in_pred(PredId, PredInfo0, ModuleInfo0, ModuleInfo) -->
 	{ pred_info_non_imported_procids(PredInfo0, ProcIds) },
 	detect_cse_in_procs(ProcIds, PredId, ModuleInfo0, ModuleInfo).
 
-:- pred detect_cse_in_procs(list(proc_id), pred_id, module_info, module_info,
-			io__state, io__state).
-% :- mode detect_cse_in_procs(in, in, di, uo, di, uo) is det.
-:- mode detect_cse_in_procs(in, in, in, out, di, uo) is det.
+:- pred detect_cse_in_procs(list(proc_id)::in, pred_id::in,
+	module_info::in, module_info::out, io__state::di, io__state::uo)
+	is det.
 
 detect_cse_in_procs([], _PredId, ModuleInfo, ModuleInfo) --> [].
 detect_cse_in_procs([ProcId | ProcIds], PredId, ModuleInfo0, ModuleInfo) -->
@@ -120,11 +119,16 @@
 	).
 
 :- type cse_info
-	--->	cse_info(prog_varset, map(prog_var, type), module_info).
+	--->	cse_info(
+			varset			:: prog_varset,
+			vartypes		:: vartypes,
+			type_info_varmap	:: type_info_varmap,
+			typeclass_info_varmap	:: typeclass_info_varmap,
+			module_info		:: module_info
+		).
 
-:- pred detect_cse_in_proc_2(proc_id, pred_id, bool, module_info, module_info).
-% :- mode detect_cse_in_proc_2(in, in, out, di, uo) is det.
-:- mode detect_cse_in_proc_2(in, in, out, in, out) is det.
+:- pred detect_cse_in_proc_2(proc_id::in, pred_id::in, bool::out,
+	module_info::in, module_info::out) is det.
 
 detect_cse_in_proc_2(ProcId, PredId, Redo, ModuleInfo0, ModuleInfo) :-
 	module_info_preds(ModuleInfo0, PredTable0),
@@ -140,7 +144,10 @@
 	proc_info_get_initial_instmap(ProcInfo0, ModuleInfo0, InstMap0),
 	proc_info_varset(ProcInfo0, Varset0),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
-	CseInfo0 = cse_info(Varset0, VarTypes0, ModuleInfo0),
+	proc_info_typeinfo_varmap(ProcInfo0, TypeInfoVarMap0),
+	proc_info_typeclass_info_varmap(ProcInfo0, TypeClassInfoVarMap0),
+	CseInfo0 = cse_info(Varset0, VarTypes0,
+		TypeInfoVarMap0, TypeClassInfoVarMap0, ModuleInfo0),
 	detect_cse_in_goal(Goal0, InstMap0, CseInfo0, CseInfo, Redo, Goal1),
 
 	(
@@ -150,15 +157,20 @@
 		Redo = yes,
 
 		% ModuleInfo should not be changed by detect_cse_in_goal
-		CseInfo = cse_info(Varset1, VarTypes1, _),
+		CseInfo = cse_info(VarSet1, VarTypes1,
+			TypeInfoVarMap, TypeClassInfoVarMap, _),
 		proc_info_headvars(ProcInfo0, HeadVars),
 
-		implicitly_quantify_clause_body(HeadVars, Goal1, Varset1,
-			VarTypes1, Goal, Varset, VarTypes, _Warnings),
+		implicitly_quantify_clause_body(HeadVars, Goal1, VarSet1,
+			VarTypes1, Goal, VarSet, VarTypes, _Warnings),
 
 		proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
-		proc_info_set_varset(ProcInfo1, Varset, ProcInfo2),
-		proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo),
+		proc_info_set_varset(ProcInfo1, VarSet, ProcInfo2),
+		proc_info_set_vartypes(ProcInfo2, VarTypes, ProcInfo3),
+		proc_info_set_typeinfo_varmap(ProcInfo3,
+			TypeInfoVarMap, ProcInfo4),
+		proc_info_set_typeclass_info_varmap(ProcInfo4,
+			TypeClassInfoVarMap, ProcInfo),
 
 		map__det_update(ProcTable0, ProcId, ProcInfo, ProcTable),
 		pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
@@ -173,9 +185,8 @@
 	% and hoist these out of the disjunction. At the moment
 	% we only look for cses that are deconstruction unifications.
 
-:- pred detect_cse_in_goal(hlds_goal, instmap, cse_info, cse_info,
-	bool, hlds_goal).
-:- mode detect_cse_in_goal(in, in, in, out, out, out) is det.
+:- pred detect_cse_in_goal(hlds_goal::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, hlds_goal::out) is det.
 
 detect_cse_in_goal(Goal0, InstMap0, CseInfo0, CseInfo, Redo, Goal) :-
 	detect_cse_in_goal_1(Goal0, InstMap0, CseInfo0, CseInfo,
@@ -186,9 +197,8 @@
 	% computed by applying the instmap delta specified in the
 	% goal's goalinfo.
 
-:- pred detect_cse_in_goal_1(hlds_goal, instmap, cse_info, cse_info, bool,
-	hlds_goal, instmap).
-:- mode detect_cse_in_goal_1(in, in, in, out, out, out, out) is det.
+:- pred detect_cse_in_goal_1(hlds_goal::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, hlds_goal::out, instmap::out) is det.
 
 detect_cse_in_goal_1(Goal0 - GoalInfo, InstMap0, CseInfo0, CseInfo, Redo,
 		Goal - GoalInfo, InstMap) :-
@@ -199,9 +209,9 @@
 
 	% Here we process each of the different sorts of goals.
 
-:- pred detect_cse_in_goal_2(hlds_goal_expr, hlds_goal_info, instmap,
-	cse_info, cse_info, bool, hlds_goal_expr).
-:- mode detect_cse_in_goal_2(in, in, in, in, out, out, out) is det.
+:- pred detect_cse_in_goal_2(hlds_goal_expr::in, hlds_goal_info::in,
+	instmap::in, cse_info::in, cse_info::out, bool::out,
+	hlds_goal_expr::out) is det.
 
 detect_cse_in_goal_2(pragma_foreign_code(A,B,C,D,E,F,G), _, _, CseInfo,
 	CseInfo, no, pragma_foreign_code(A,B,C,D,E,F,G)).
@@ -218,7 +228,7 @@
 		B0 = lambda_goal(PredOrFunc, EvalMethod, FixModes,
 			NonLocalVars, Vars, Modes, Det, Goal0)
 	->
-		CseInfo0 = cse_info(_, _, ModuleInfo),
+		ModuleInfo = CseInfo0 ^ module_info,
 		instmap__pre_lambda_update(ModuleInfo, 
 			Vars, Modes, InstMap0, InstMap),
 		detect_cse_in_goal(Goal0, InstMap, CseInfo0, CseInfo, Redo,
@@ -245,7 +255,8 @@
 
 detect_cse_in_goal_2(par_conj(Goals0, SM), _, InstMap, CseInfo0, CseInfo, Redo,
 		par_conj(Goals, SM)) :-
-	detect_cse_in_par_conj(Goals0, InstMap, CseInfo0, CseInfo, Redo, Goals).
+	detect_cse_in_par_conj(Goals0, InstMap, CseInfo0, CseInfo,
+		Redo, Goals).
 
 detect_cse_in_goal_2(disj(Goals0, SM), GoalInfo, InstMap, CseInfo0, CseInfo,
 		Redo, Goal) :-
@@ -280,9 +291,8 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred detect_cse_in_conj(list(hlds_goal), instmap, cse_info, cse_info,
-	bool, list(hlds_goal)).
-:- mode detect_cse_in_conj(in, in, in, out, out, out) is det.
+:- pred detect_cse_in_conj(list(hlds_goal)::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, list(hlds_goal)::out) is det.
 
 detect_cse_in_conj([], _InstMap, CseInfo, CseInfo, no, []).
 detect_cse_in_conj([Goal0 | Goals0], InstMap0, CseInfo0, CseInfo,
@@ -299,9 +309,8 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred detect_cse_in_par_conj(list(hlds_goal), instmap, cse_info, cse_info,
-	bool, list(hlds_goal)).
-:- mode detect_cse_in_par_conj(in, in, in, out, out, out) is det.
+:- pred detect_cse_in_par_conj(list(hlds_goal)::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, list(hlds_goal)::out) is det.
 
 detect_cse_in_par_conj([], _InstMap, CseInfo, CseInfo, no, []).
 detect_cse_in_par_conj([Goal0 | Goals0], InstMap0, CseInfo0, CseInfo,
@@ -318,9 +327,9 @@
 	% structure. Now for each non-local variable, we check whether each
 	% branch matches that variable against the same functor.
 
-:- pred detect_cse_in_disj(list(prog_var), list(hlds_goal), hlds_goal_info,
-	store_map, instmap, cse_info, cse_info, bool, hlds_goal_expr).
-:- mode detect_cse_in_disj(in, in, in, in, in, in, out, out, out) is det.
+:- pred detect_cse_in_disj(list(prog_var)::in, list(hlds_goal)::in,
+	hlds_goal_info::in, store_map::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, hlds_goal_expr::out) is det.
 
 detect_cse_in_disj([], Goals0, _, SM, InstMap, CseInfo0, CseInfo,
 		Redo, disj(Goals, SM)) :-
@@ -329,15 +338,16 @@
 		CseInfo0, CseInfo, Redo, Goal) :-
 	(
 		instmap__lookup_var(InstMap, Var, VarInst0),
-		CseInfo0 = cse_info(_, _, ModuleInfo),
+		ModuleInfo = CseInfo0 ^ module_info,
 		% XXX we only need inst_is_bound, but leave this as it is
 		% until mode analysis can handle aliasing between free
 		% variables.
 		inst_is_ground_or_any(ModuleInfo, VarInst0),
 		common_deconstruct(Goals0, Var, CseInfo0, CseInfo1,
-			Unify, Goals)
+			Unify, FirstOldNew, LaterOldNew, Goals)
 	->
-		CseInfo = CseInfo1,
+		maybe_update_existential_data_structures(Unify,
+			FirstOldNew, LaterOldNew, CseInfo1, CseInfo),
 		Goal = conj([Unify, disj(Goals, SM) - GoalInfo0]),
 		Redo = yes
 	;
@@ -345,22 +355,20 @@
 			CseInfo0, CseInfo, Redo, Goal)
 	).
 
-:- pred detect_cse_in_disj_2(list(hlds_goal), instmap, cse_info, cse_info,
-	bool, list(hlds_goal)).
-:- mode detect_cse_in_disj_2(in, in, in, out, out, out) is det.
+:- pred detect_cse_in_disj_2(list(hlds_goal)::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, list(hlds_goal)::out) is det.
 
 detect_cse_in_disj_2([], _InstMap, CseInfo, CseInfo, no, []).
 detect_cse_in_disj_2([Goal0 | Goals0], InstMap0, CseInfo0, CseInfo, Redo,
 		[Goal | Goals]) :-
 	detect_cse_in_goal(Goal0, InstMap0, CseInfo0, CseInfo1, Redo1, Goal),
-	detect_cse_in_disj_2(Goals0, InstMap0, CseInfo1, CseInfo, Redo2, Goals),
+	detect_cse_in_disj_2(Goals0, InstMap0, CseInfo1, CseInfo,
+		Redo2, Goals),
 	bool__or(Redo1, Redo2, Redo).
 
-:- pred detect_cse_in_cases(list(prog_var), prog_var, can_fail, list(case),
-	hlds_goal_info, store_map, instmap, cse_info, cse_info, bool,
-	hlds_goal_expr).
-:- mode detect_cse_in_cases(in, in, in, in, in, in, in, in, out, out, out)
-	is det.
+:- pred detect_cse_in_cases(list(prog_var)::in, prog_var::in, can_fail::in,
+	list(case)::in, hlds_goal_info::in, store_map::in, instmap::in,
+	cse_info::in, cse_info::out, bool::out, hlds_goal_expr::out) is det.
 
 detect_cse_in_cases([], SwitchVar, CanFail, Cases0, _GoalInfo, SM, InstMap,
 		CseInfo0, CseInfo, Redo,
@@ -371,15 +379,16 @@
 	(
 		Var \= SwitchVar,
 		instmap__lookup_var(InstMap, Var, VarInst0),
-		CseInfo0 = cse_info(_, _, ModuleInfo),
+		ModuleInfo = CseInfo0 ^ module_info,
 		% XXX we only need inst_is_bound, but leave this as it is
 		% until mode analysis can handle aliasing between free
 		% variables.
 		inst_is_ground_or_any(ModuleInfo, VarInst0),
 		common_deconstruct_cases(Cases0, Var, CseInfo0, CseInfo1,
-			Unify, Cases)
+			Unify, FirstOldNew, LaterOldNew, Cases)
 	->
-		CseInfo = CseInfo1,
+		maybe_update_existential_data_structures(Unify,
+			FirstOldNew, LaterOldNew, CseInfo1, CseInfo),
 		Goal = conj([Unify, switch(SwitchVar, CanFail, Cases, SM)
 			- GoalInfo]),
 		Redo = yes
@@ -388,9 +397,8 @@
 			SM, InstMap, CseInfo0, CseInfo, Redo, Goal)
 	).
 
-:- pred detect_cse_in_cases_2(list(case), instmap, cse_info, cse_info,
-	bool, list(case)).
-:- mode detect_cse_in_cases_2(in, in, in, out, out, out) is det.
+:- pred detect_cse_in_cases_2(list(case)::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, list(case)::out) is det.
 
 detect_cse_in_cases_2([], _, CseInfo, CseInfo, no, []).
 detect_cse_in_cases_2([Case0 | Cases0], InstMap, CseInfo0, CseInfo, Redo,
@@ -398,14 +406,14 @@
 	Case0 = case(Functor, Goal0),
 	detect_cse_in_goal(Goal0, InstMap, CseInfo0, CseInfo1, Redo1, Goal),
 	Case = case(Functor, Goal),
-	detect_cse_in_cases_2(Cases0, InstMap, CseInfo1, CseInfo, Redo2, Cases),
+	detect_cse_in_cases_2(Cases0, InstMap, CseInfo1, CseInfo,
+		Redo2, Cases),
 	bool__or(Redo1, Redo2, Redo).
 
-:- pred detect_cse_in_ite(list(prog_var), list(prog_var),
-	hlds_goal, hlds_goal, hlds_goal, hlds_goal_info,
-	store_map, instmap, cse_info, cse_info, bool, hlds_goal_expr).
-:- mode detect_cse_in_ite(in, in, in, in, in, in, in, in, in, out, out, out)
-	is det.
+:- pred detect_cse_in_ite(list(prog_var)::in, list(prog_var)::in,
+	hlds_goal::in, hlds_goal::in, hlds_goal::in, hlds_goal_info::in,
+	store_map::in, instmap::in, cse_info::in,
+	cse_info::out, bool::out, hlds_goal_expr::out) is det.
 
 detect_cse_in_ite([], IfVars, Cond0, Then0, Else0, _, SM, InstMap, CseInfo0,
 		CseInfo, Redo, if_then_else(IfVars, Cond, Then, Else, SM)) :-
@@ -414,17 +422,18 @@
 detect_cse_in_ite([Var | Vars], IfVars, Cond0, Then0, Else0, GoalInfo,
 		SM, InstMap, CseInfo0, CseInfo, Redo, Goal) :-
 	(
-		CseInfo0 = cse_info(_, _, ModuleInfo),
+		ModuleInfo = CseInfo0 ^ module_info,
 		instmap__lookup_var(InstMap, Var, VarInst0),
 		% XXX we only need inst_is_bound, but leave this as it is
 		% until mode analysis can handle aliasing between free
 		% variables.
 		inst_is_ground_or_any(ModuleInfo, VarInst0),
 		common_deconstruct([Then0, Else0], Var, CseInfo0, CseInfo1,
-			Unify, Goals),
+			Unify, FirstOldNew, LaterOldNew, Goals),
 		Goals = [Then, Else]
 	->
-		CseInfo = CseInfo1,
+		maybe_update_existential_data_structures(Unify,
+			FirstOldNew, LaterOldNew, CseInfo1, CseInfo),
 		Goal = conj([Unify, if_then_else(IfVars, Cond0, Then, Else, SM)
 			- GoalInfo]),
 		Redo = yes
@@ -433,9 +442,9 @@
 			SM, InstMap, CseInfo0, CseInfo, Redo, Goal)
 	).
 
-:- pred detect_cse_in_ite_2(hlds_goal, hlds_goal, hlds_goal,
-	instmap, cse_info, cse_info, bool, hlds_goal, hlds_goal, hlds_goal).
-:- mode detect_cse_in_ite_2(in, in, in, in, in, out, out, out, out, out) is det.
+:- pred detect_cse_in_ite_2(hlds_goal::in, hlds_goal::in, hlds_goal::in,
+	instmap::in, cse_info::in, cse_info::out, bool::out,
+	hlds_goal::out, hlds_goal::out, hlds_goal::out) is det.
 
 detect_cse_in_ite_2(Cond0, Then0, Else0, InstMap0, CseInfo0, CseInfo, Redo,
 		Cond, Then, Else) :-
@@ -461,189 +470,406 @@
 %	has been hoisted out, with the new variables as the functor arguments.
 %	Unify is the unification that was hoisted out.
 
-:- pred common_deconstruct(list(hlds_goal), prog_var, cse_info, cse_info,
-	hlds_goal, list(hlds_goal)).
-:- mode common_deconstruct(in, in, in, out, out, out) is semidet.
-
-common_deconstruct(Goals0, Var, CseInfo0, CseInfo, Unify, Goals) :-
-	common_deconstruct_2(Goals0, Var, no, CseInfo0, CseInfo,
-		Goals, MaybeUnifyGoal),
-	MaybeUnifyGoal = yes(Unify).
-
-:- pred common_deconstruct_2(list(hlds_goal), prog_var, maybe(hlds_goal),
-	cse_info, cse_info, list(hlds_goal), maybe(hlds_goal)).
-:- mode common_deconstruct_2(in, in, in, in, out, out, out) is semidet.
-
-common_deconstruct_2([], _Var, MaybeUnify, CseInfo, CseInfo, [], MaybeUnify).
-common_deconstruct_2([Goal0 | Goals0], Var, MaybeUnify0,
-		CseInfo0, CseInfo, [Goal | Goals], MaybeUnify) :-
+:- pred common_deconstruct(list(hlds_goal)::in, prog_var::in, cse_info::in,
+	cse_info::out, hlds_goal::out, assoc_list(prog_var)::out,
+	list(assoc_list(prog_var))::out, list(hlds_goal)::out) is semidet.
+
+common_deconstruct(Goals0, Var, CseInfo0, CseInfo, Unify,
+		FirstOldNew, LaterOldNew, Goals) :-
+	common_deconstruct_2(Goals0, Var, before_candidate,
+		have_candidate(Unify, FirstOldNew, LaterOldNew),
+		CseInfo0, CseInfo, Goals),
+	LaterOldNew = [_ | _].
+
+:- pred common_deconstruct_2(list(hlds_goal)::in, prog_var::in,
+	cse_state::in, cse_state::out, cse_info::in, cse_info::out,
+	list(hlds_goal)::out) is semidet.
+
+common_deconstruct_2([], _Var, CseState, CseState, CseInfo, CseInfo, []).
+common_deconstruct_2([Goal0 | Goals0], Var, CseState0, CseState,
+		CseInfo0, CseInfo, [Goal | Goals]) :-
 	find_bind_var(Var, find_bind_var_for_cse_in_deconstruct, Goal0, Goal,
-		MaybeUnify0 - no, MaybeUnify1 - yes, CseInfo0, CseInfo1),
-	MaybeUnify1 = yes(_),
-	common_deconstruct_2(Goals0, Var, MaybeUnify1, CseInfo1, CseInfo,
-		Goals, MaybeUnify).
+		CseState0, CseState1, CseInfo0, CseInfo1, yes),
+	CseState1 = have_candidate(_, _, _),
+	common_deconstruct_2(Goals0, Var, CseState1, CseState,
+		CseInfo1, CseInfo, Goals).
 
 %-----------------------------------------------------------------------------%
 
-:- pred common_deconstruct_cases(list(case), prog_var, cse_info, cse_info,
-	hlds_goal, list(case)).
-:- mode common_deconstruct_cases(in, in, in, out, out, out) is semidet.
+:- pred common_deconstruct_cases(list(case)::in, prog_var::in,
+	cse_info::in, cse_info::out, hlds_goal::out, assoc_list(prog_var)::out,
+	list(assoc_list(prog_var))::out, list(case)::out) is semidet.
 
 common_deconstruct_cases(Cases0, Var, CseInfo0, CseInfo,
-		Unify, Cases) :-
-	common_deconstruct_cases_2(Cases0, Var, no, CseInfo0, CseInfo,
-		Cases, MaybeUnifyGoal),
-	MaybeUnifyGoal = yes(Unify).
-
-:- pred common_deconstruct_cases_2(list(case), prog_var, maybe(hlds_goal),
-	cse_info, cse_info, list(case), maybe(hlds_goal)).
-:- mode common_deconstruct_cases_2(in, in, in, in, out, out, out) is semidet.
-
-common_deconstruct_cases_2([], _Var, MaybeUnify, CseInfo, CseInfo,
-	[], MaybeUnify).
-common_deconstruct_cases_2([case(ConsId, Goal0) | Cases0], Var, MaybeUnify0,
-		CseInfo0, CseInfo, [case(ConsId, Goal) | Cases], MaybeUnify) :-
+		Unify, FirstOldNew, LaterOldNew, Cases) :-
+	common_deconstruct_cases_2(Cases0, Var, before_candidate,
+		have_candidate(Unify, FirstOldNew, LaterOldNew),
+		CseInfo0, CseInfo, Cases),
+	LaterOldNew = [_ | _].
+
+:- pred common_deconstruct_cases_2(list(case)::in, prog_var::in,
+	cse_state::in, cse_state::out, cse_info::in, cse_info::out,
+	list(case)::out) is semidet.
+
+common_deconstruct_cases_2([], _Var, CseState, CseState, CseInfo, CseInfo, []).
+common_deconstruct_cases_2([case(ConsId, Goal0) | Cases0], Var,
+		CseState0, CseState, CseInfo0, CseInfo,
+		[case(ConsId, Goal) | Cases]) :-
 	find_bind_var(Var, find_bind_var_for_cse_in_deconstruct, Goal0, Goal,
-		MaybeUnify0 - no, MaybeUnify1 - yes, CseInfo0, CseInfo1),
-	MaybeUnify1 = yes(_),
-	common_deconstruct_cases_2(Cases0, Var, MaybeUnify1, CseInfo1, CseInfo,
-		Cases, MaybeUnify).
+		CseState0, CseState1, CseInfo0, CseInfo1, yes),
+	CseState1 = have_candidate(_, _, _),
+	common_deconstruct_cases_2(Cases0, Var, CseState1, CseState,
+		CseInfo1, CseInfo, Cases).
 
 %-----------------------------------------------------------------------------%
+
+	% This data structure represents the state of the search for
+	% deconstructions in all the branches of a branched control structure
+	% that deconstruct a given variable with the same functor.
+	% Initially, we don't know what unification we will hoist out, so the
+	% state is before_candidate. When we find a unification we want to
+	% hoist out, this fixes the functor, and the state is have_candidate.
+	% If we find that some branches unify that variable with some other
+	% functor, we have multiple_candidates, which means that we don't hoist
+	% out any of them. (Although our caller may try again with another
+	% variable.)
+	%
+	% The goal field contains the unification we are proposing to put
+	% before the branched control structure. The first_old_new field
+	% gives the mapping from argument variables in the old unification
+	% in the first branch to the freshly created variables in the goal
+	% being hoisted before the branched control structure. The
+	% later_old_new field contains the same information for the second
+	% and later branches.
+:- type cse_state
+	--->	before_candidate
+	;	have_candidate(
+			goal		::	hlds_goal,
+			first_old_new	::	assoc_list(prog_var),
+			later_old_new	::	list(assoc_list(prog_var))
+		)
+	;	multiple_candidates.
 
-	% The hlds_goal is the common unification we are attemping to hoist.
-	% The boolean states whether such a deconstruction has been seen in
-	% this branch.
-:- type cse_result == pair(maybe(hlds_goal), bool).
-
-:- pred find_bind_var_for_cse_in_deconstruct(prog_var, hlds_goal,
-		list(hlds_goal), cse_result, cse_result, cse_info, cse_info).
-:- mode find_bind_var_for_cse_in_deconstruct(in, in, out,
-	in, out, in, out) is det.
+:- pred find_bind_var_for_cse_in_deconstruct(prog_var::in, hlds_goal::in,
+	list(hlds_goal)::out, cse_state::in, cse_state::out,
+	cse_info::in, cse_info::out) is det.
 
 find_bind_var_for_cse_in_deconstruct(Var, Goal0, Goals,
-		CseResult0, CseResult, CseInfo0, CseInfo) :-
-	CseResult0 = MaybeUnify0 - _,
+		CseState0, CseState, CseInfo0, CseInfo) :-
 	(
-		MaybeUnify0 = no,
-		CseInfo0 = cse_info(Varset0, Typemap0, ModuleInfo),
-		construct_common_unify(Var, Goal0, Goal,
-			Varset0, Varset, Typemap0, Typemap, Goals),
-		CseInfo = cse_info(Varset, Typemap, ModuleInfo),
-		MaybeUnify = yes(Goal),
-		Seen = yes
+		CseState0 = before_candidate,
+		construct_common_unify(Var, Goal0, CseInfo0, CseInfo,
+			OldNewVars, HoistedGoal, Goals),
+		CseState = have_candidate(HoistedGoal, OldNewVars, [])
 	;
-		MaybeUnify0 = yes(OldUnifyGoal),
+		CseState0 = have_candidate(HoistedGoal,
+			FirstOldNewVars, LaterOldNewVars0),
 		CseInfo = CseInfo0,
 		Goal0 = _ - GoalInfo,
 		goal_info_get_context(GoalInfo, Context),
 		(
-			find_similar_deconstruct(OldUnifyGoal,
-				Goal0, Context, Goals0)
+			find_similar_deconstruct(HoistedGoal,
+				Goal0, Context, OldNewVars, Goals0)
 		->
 			Goals = Goals0,
-			MaybeUnify = MaybeUnify0,
-			Seen = yes
+			LaterOldNewVars = [OldNewVars | LaterOldNewVars0],
+			CseState = have_candidate(HoistedGoal,
+				FirstOldNewVars, LaterOldNewVars)
 		;	
 			Goals = [Goal0],
-			MaybeUnify = no,
-			Seen = no
+			CseState = multiple_candidates
 		)
-	),
-	CseResult = MaybeUnify - Seen.
+	;
+		CseState0 = multiple_candidates,
+		Goals = [Goal0],
+		CseState = multiple_candidates,
+		CseInfo = CseInfo0
+	).
 
-:- pred construct_common_unify(prog_var, hlds_goal, hlds_goal, prog_varset,
-	prog_varset, map(prog_var, type), map(prog_var, type), list(hlds_goal)).
-:- mode construct_common_unify(in, in, out, in, out, in, out, out) is det.
+:- pred construct_common_unify(prog_var::in, hlds_goal::in,
+	cse_info::in, cse_info::out, assoc_list(prog_var)::out,
+	hlds_goal::out, list(hlds_goal)::out) is det.
 
-construct_common_unify(Var, GoalExpr0 - GoalInfo, Goal, Varset0, Varset,
-		Typemap0, Typemap, Replacements) :-
+construct_common_unify(Var, GoalExpr0 - GoalInfo, CseInfo0, CseInfo,
+		OldNewVars, HoistedGoal, Replacements) :-
 	(
 		GoalExpr0 = unify(_, Term, Umode, Unif0, Ucontext),
 		Unif0 = deconstruct(_, Consid, Args, Submodes, CanFail, CanCGC)
 	->
-		Unif = deconstruct(Var, Consid, Args,
-				Submodes, CanFail, CanCGC),
+		Unif = deconstruct(Var, Consid, Args, Submodes, CanFail,
+			CanCGC),
 		( Term = functor(_, _) ->
 			GoalExpr1 = unify(Var, Term, Umode, Unif, Ucontext)
 		;
-			error("unexpected unify structure in construct_common_unify")
+			error("non-functor unify in construct_common_unify")
 		),
 		goal_info_get_context(GoalInfo, Context),
 		create_parallel_subterms(Args, Context, Ucontext,
-			Varset0, Varset, Typemap0, Typemap, Sub, Replacements),
-		goal_util__rename_vars_in_goal(GoalExpr1 - GoalInfo, Sub, Goal)
+			CseInfo0, CseInfo, OldNewVars, Replacements),
+		map__from_assoc_list(OldNewVars, Sub),
+		goal_util__rename_vars_in_goal(GoalExpr1 - GoalInfo, Sub,
+			HoistedGoal)
 	;
-		error("unexpected goal in construct_common_unify")
+		error("non-unify goal in construct_common_unify")
 	).
+
+:- pred create_parallel_subterms(list(prog_var)::in, prog_context::in,
+	unify_context::in, cse_info::in, cse_info::out,
+	assoc_list(prog_var)::out, list(hlds_goal)::out) is det.
+
+create_parallel_subterms([], _, _, CseInfo, CseInfo, [], []).
+create_parallel_subterms([OFV | OFV0], Context, UnifyContext,
+		CseInfo0, CseInfo, OldNewVars, Replacements) :-
+	create_parallel_subterms(OFV0, Context, UnifyContext,
+		CseInfo0, CseInfo1, OldNewVars1, Replacements1),
+	create_parallel_subterm(OFV, Context, UnifyContext,
+		CseInfo1, CseInfo, OldNewVars1, OldNewVars, Goal),
+	Replacements = [Goal | Replacements1].
 
-:- pred create_parallel_subterms(list(prog_var), prog_context, unify_context,
-	prog_varset, prog_varset, map(prog_var, type), map(prog_var, type),
-	map(prog_var, prog_var), list(hlds_goal)).
-:- mode create_parallel_subterms(in, in, in, in, out, in, out, out, out) is det.
-
-create_parallel_subterms([], _, _, Varset, Varset, Typemap, Typemap, Sub, []) :-
-	map__init(Sub).
-create_parallel_subterms([OFV | OFV0], Context, UnifyContext, Varset0, Varset,
-		Typemap0, Typemap, Sub, Replacements) :-
-	create_parallel_subterms(OFV0, Context, UnifyContext, Varset0, Varset1,
-		Typemap0, Typemap1, Sub1, Replacements1),
-	varset__new_var(Varset1, NFV, Varset),
-	map__lookup(Typemap1, OFV, Type),
-	map__det_insert(Typemap1, NFV, Type, Typemap),
-	map__det_insert(Sub1, OFV, NFV, Sub),
+:- pred create_parallel_subterm(prog_var::in, prog_context::in,
+	unify_context::in, cse_info::in, cse_info::out,
+	assoc_list(prog_var)::in, assoc_list(prog_var)::out,
+	hlds_goal::out) is det.
+
+create_parallel_subterm(OFV, Context, UnifyContext,
+		CseInfo0, CseInfo, OldNewVar0, OldNewVar, Goal) :-
+	VarSet0 = CseInfo0 ^ varset,
+	VarTypes0 = CseInfo0 ^ vartypes,
+	varset__new_var(VarSet0, NFV, VarSet),
+	map__lookup(VarTypes0, OFV, Type),
+	map__det_insert(VarTypes0, NFV, Type, VarTypes),
+	OldNewVar = [OFV - NFV | OldNewVar0],
 	UnifyContext = unify_context(MainCtxt, SubCtxt),
 	create_atomic_unification(OFV, var(NFV),
 		Context, MainCtxt, SubCtxt, Goal),
-	Replacements = [Goal | Replacements1].
+	CseInfo = (CseInfo0 ^ varset := VarSet) ^ vartypes := VarTypes.
 
 %-----------------------------------------------------------------------------%
 
-:- pred find_similar_deconstruct(hlds_goal, hlds_goal, prog_context,
-		list(hlds_goal)).
-:- mode find_similar_deconstruct(in, in, in, out) is semidet.
+:- pred find_similar_deconstruct(hlds_goal::in, hlds_goal::in,
+	prog_context::in, assoc_list(prog_var)::out, list(hlds_goal)::out)
+	is semidet.
 
-find_similar_deconstruct(OldUnifyGoal, NewUnifyGoal, Context, Replacements) :-
+find_similar_deconstruct(HoistedUnifyGoal, OldUnifyGoal, Context,
+		OldHoistedVars, Replacements) :-
 	(
-		OldUnifyGoal = unify(_OT1, _OT2, _OM, OldUnifyInfo, OC) - _,
-		OldUnifyInfo = deconstruct(_OV, OF, OFV, _OUM, _OCF, _OCGC),
-		NewUnifyGoal = unify(_NT1, _NT2, _NM, NewUnifyInfo, _NC) - _,
-		NewUnifyInfo = deconstruct(_NV, NF, NFV, _NUM, _NCF, _NCGC)
+		HoistedUnifyGoal = unify(_, _, _, HoistedUnifyInfo, OC) - _,
+		HoistedUnifyInfo = deconstruct(_, HoistedFunctor,
+			HoistedVars, _, _, _),
+		OldUnifyGoal = unify(_, _, _, OldUnifyInfo, _NC) - _,
+		OldUnifyInfo = deconstruct(_, OldFunctor, OldVars, _, _, _)
 	->
-		OF = NF,
-		list__length(OFV, OFVC),
-		list__length(NFV, NFVC),
-		OFVC = NFVC,
-		pair_subterms(OFV, NFV, Context, OC, Replacements)
+		HoistedFunctor = OldFunctor,
+		list__length(HoistedVars, HoistedVarsCount),
+		list__length(OldVars, OldVarsCount),
+		HoistedVarsCount = OldVarsCount,
+		assoc_list__from_corresponding_lists(OldVars, HoistedVars,
+			OldHoistedVars),
+		pair_subterms(OldHoistedVars, Context, OC, Replacements)
 	;
 		error("find_similar_deconstruct: non-deconstruct unify")
 	).
 
-:- pred pair_subterms(list(prog_var), list(prog_var), prog_context,
-		unify_context, list(hlds_goal)).
-:- mode pair_subterms(in, in, in, in, out) is det.
+:- pred pair_subterms(assoc_list(prog_var)::in, prog_context::in,
+	unify_context::in, list(hlds_goal)::out) is det.
 
-pair_subterms(OFV0, NFV0, Context, UnifyContext, Replacements) :-
-	(
-		OFV0 = [OFV | OFV1],
-		NFV0 = [NFV | NFV1]
-	->
-		pair_subterms(OFV1, NFV1, Context, UnifyContext, Replacements1),
-		( OFV = NFV ->
+pair_subterms([], _Context, _UnifyContext, []).
+pair_subterms([OldVar - HoistedVar | OldHoistedVars], Context, UnifyContext,
+		Replacements) :-
+	pair_subterms(OldHoistedVars, Context, UnifyContext, Replacements1),
+	( OldVar = HoistedVar ->
 			Replacements = Replacements1
 		;
 			UnifyContext = unify_context(MainCtxt, SubCtxt),
-			create_atomic_unification(OFV, var(NFV),
+		create_atomic_unification(HoistedVar, var(OldVar),
 				Context, MainCtxt, SubCtxt, Goal),
 			Replacements = [Goal | Replacements1]
+	).
+
+%-----------------------------------------------------------------------------%
+
+% This section handles the case where the functor involved in the
+% common subexpression contains existentially typed arguments,
+% whether or not they are constrained to belong to a typeclass.
+% In such cases, what the compiler used to consider several distinct
+% types (the types of say the first the existentially typed argument
+% in the deconstructions in the different branches) become one (in this
+% case, the type of the first existentially typed argument in the
+% hoisted out deconstruction). The prog_vars describing the types
+% of the existentially typed arguments (i.e. containing their
+% typeinfos) change as well, from being some of the variables in
+% in the original deconstructions to being the corresponding variables
+% in the hoisted out deconstruction.
+%
+% As an example, consider a disjunction such as
+%
+%	(
+%		HeadVar__2_2 = x:u(TypeClassInfo_for_v_8, V_4),
+%		...
+%	;
+%		HeadVar__2_2 = x:u(TypeClassInfo_for_v_14, V_6)
+%		...
+%	)
+%	
+% The main part of cse_detection will replace this with
+%	
+%	HeadVar__2_2 = x:u(V_17, V_16)
+%	(
+%		TypeClassInfo_for_v_8 = V_17,
+%		V_4 = V_16,
+%		...
+%	;
+%		TypeClassInfo_for_v_14 = V_17,
+%		V_6 = V_16,
+%		...
+%	)
+%
+% However, this is not enough. Since TypeClassInfo_for_v_8 and
+% TypeClassInfo_for_v_14 may (and probably will) be eliminated later,
+% it is imperative that the data structures in the proc_info that refer
+% to them be updated to eliminate references to those variables.
+% Those data structures may originally contain something like this:
+%	
+% type_info varmap:
+% T_1 (number 1) -> typeclass_info(TypeClassInfo_for_v_8, 1)
+% T_3 (number 3) -> typeclass_info(TypeClassInfo_for_v_14, 1)
+% typeclass_info varmap:
+% x:v(T_1) -> TypeClassInfo_for_v_8
+% x:v(T_3) -> TypeClassInfo_for_v_14
+% variable types map:
+% V_4 (number 4) :: T_1
+% V_6 (number 6) :: T_3
+%
+% They must be updated like this:
+%	
+% type_info varmap:
+% T_1 (number 1) -> typeclass_info(V_17, 1)
+% typeclass_info varmap:
+% x:v(T_1) -> V_17
+% variable types map:
+% V_4 (number 4) :: T_1
+% V_6 (number 6) :: T_1
+
+:- pred maybe_update_existential_data_structures(hlds_goal::in,
+	assoc_list(prog_var)::in, list(assoc_list(prog_var))::in,
+	cse_info::in, cse_info::out) is det.
+
+maybe_update_existential_data_structures(Unify, FirstOldNew, LaterOldNew,
+		CseInfo0, CseInfo) :-
+	(
+		Unify = unify(_, _, _, UnifyInfo, _) - _,
+		UnifyInfo = deconstruct(Var, ConsId, _, _, _, _),
+		ModuleInfo = CseInfo0 ^ module_info,
+		VarTypes = CseInfo0 ^ vartypes,
+		map__lookup(VarTypes, Var, Type),
+		type_util__is_existq_cons(ModuleInfo, Type, ConsId)
+	->
+		update_existential_data_structures(FirstOldNew, LaterOldNew,
+			CseInfo0, CseInfo)
+	;
+		CseInfo = CseInfo0
+	).
+
+:- pred update_existential_data_structures(
+	assoc_list(prog_var)::in, list(assoc_list(prog_var))::in,
+	cse_info::in, cse_info::out) is det.
+
+update_existential_data_structures(FirstOldNew, LaterOldNews,
+		CseInfo0, CseInfo) :-
+	list__condense(LaterOldNews, LaterOldNew),
+	list__append(FirstOldNew, LaterOldNew, OldNew),
+	map__from_assoc_list(OldNew, OldNewMap),
+	map__from_assoc_list(FirstOldNew, FirstOldNewMap),
+
+	TypeInfoVarMap0 = CseInfo0 ^ type_info_varmap,
+	TypeClassInfoVarMap0 = CseInfo0 ^ typeclass_info_varmap,
+	VarTypes0 = CseInfo0 ^ vartypes,
+
+	map__to_assoc_list(TypeInfoVarMap0, TypeInfoVarList0),
+	list__foldl(find_type_info_locn_tvar_map(FirstOldNewMap),
+		TypeInfoVarList0, map__init, NewTvarMap),
+
+	list__foldl2(reconstruct_type_info_varmap(OldNewMap, NewTvarMap),
+		TypeInfoVarList0, map__init, TypeInfoVarMap1,
+		map__init, TvarSub),
+	map__keys(TvarSub, ElimTvars),
+	map__delete_list(TypeInfoVarMap1, ElimTvars, TypeInfoVarMap),
+
+	map__to_assoc_list(TypeClassInfoVarMap0, TypeClassInfoVarList0),
+	list__foldl(reconstruct_typeclass_info_varmap(OldNewMap, TvarSub),
+		TypeClassInfoVarList0, map__init, TypeClassInfoVarMap),
+
+	map__map_values(apply_tvar_rename(TvarSub), VarTypes0, VarTypes),
+
+	CseInfo1 = CseInfo0 ^ type_info_varmap := TypeInfoVarMap,
+	CseInfo2 = CseInfo1 ^ typeclass_info_varmap := TypeClassInfoVarMap,
+	CseInfo = CseInfo2 ^ vartypes := VarTypes.
+
+:- pred apply_tvar_rename(map(tvar, tvar)::in, prog_var::in,
+	(type)::in, (type)::out) is det.
+
+apply_tvar_rename(TvarSub, _Var, Type0, Type) :-
+	Type = term__apply_variable_renaming(Type0, TvarSub).
+
+:- pred find_type_info_locn_tvar_map(map(prog_var, prog_var)::in,
+	pair(tvar, type_info_locn)::in,
+ 	map(type_info_locn, tvar)::in, map(type_info_locn, tvar)::out) is det.
+ 
+find_type_info_locn_tvar_map(FirstOldNewMap, Tvar - TypeInfoLocn0,
+		NewTvarMap0, NewTvarMap) :-
+ 	type_info_locn_var(TypeInfoLocn0, Old),
+ 	( map__search(FirstOldNewMap, Old, New) ->
+  		type_info_locn_set_var(TypeInfoLocn0, New, TypeInfoLocn),
+ 		map__det_insert(NewTvarMap0, TypeInfoLocn, Tvar, NewTvarMap)
+ 	;
+ 		NewTvarMap = NewTvarMap0
+ 	).
+
+:- pred reconstruct_type_info_varmap(map(prog_var, prog_var)::in,
+	map(type_info_locn, tvar)::in, pair(tvar, type_info_locn)::in,
+ 	map(tvar, type_info_locn)::in, map(tvar, type_info_locn)::out,
+	map(tvar, tvar)::in, map(tvar, tvar)::out) is det.
+ 
+reconstruct_type_info_varmap(FirstOldNewMap, NewTvarMap, Tvar - TypeInfoLocn0,
+		TypeInfoVarMap0, TypeInfoVarMap, TvarSub0, TvarSub) :-
+ 	type_info_locn_var(TypeInfoLocn0, Old),
+ 	( map__search(FirstOldNewMap, Old, New) ->
+  		type_info_locn_set_var(TypeInfoLocn0, New, TypeInfoLocn),
+ 		map__det_insert(TypeInfoVarMap0, Tvar, TypeInfoLocn,
+			TypeInfoVarMap),
+		map__lookup(NewTvarMap, TypeInfoLocn, NewTvar),
+		( Tvar = NewTvar ->
+			TvarSub = TvarSub0
+		;
+			map__det_insert(TvarSub0, Tvar, NewTvar, TvarSub)
 		)
 	;
-		OFV0 = [],
-		NFV0 = []
-	->
-		Replacements = []
+		map__det_insert(TypeInfoVarMap0, Tvar, TypeInfoLocn0,
+			TypeInfoVarMap),
+		TvarSub = TvarSub0
+ 	).
+
+:- pred reconstruct_typeclass_info_varmap(map(prog_var, prog_var)::in,
+	map(tvar, tvar)::in, pair(class_constraint, prog_var)::in,
+	typeclass_info_varmap::in, typeclass_info_varmap::out) is det.
+
+reconstruct_typeclass_info_varmap(OldNewMap, TvarSub,
+		Constraint0 - TypeClassInfoVar0,
+		TypeClassInfoVarMap0, TypeClassInfoVarMap) :-
+	type_util__apply_variable_renaming_to_constraint(TvarSub,
+		Constraint0, Constraint),
+	( map__search(OldNewMap, TypeClassInfoVar0, TypeClassInfoVar1) ->
+		TypeClassInfoVar = TypeClassInfoVar1
+	;
+		TypeClassInfoVar = TypeClassInfoVar0
+	),
+	( map__search(TypeClassInfoVarMap0, Constraint, OldTypeClassInfoVar) ->
+		require(unify(OldTypeClassInfoVar, TypeClassInfoVar),
+			"reconstruct_typeclass_info_varmap: mismatch"),
+		TypeClassInfoVarMap = TypeClassInfoVarMap0
 	;
-		error("mismatched length lists in pair_subterms")
+		map__det_insert(TypeClassInfoVarMap0, Constraint,
+			TypeClassInfoVar, TypeClassInfoVarMap)
 	).
 
 %-----------------------------------------------------------------------------%
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.302
diff -u -b -r1.302 options.m
--- compiler/options.m	2000/12/06 06:05:11	1.302
+++ compiler/options.m	2000/12/06 06:06:42
@@ -649,7 +649,7 @@
 					% above default with a value determined
 					% at configuration time
 	max_jump_table_size	-	int(0),
-	compare_specialization	-	int(1),
+	compare_specialization	-	int(4),
 					% 0 indicates any size.
 	fact_table_max_array_size -	int(1024),
 	fact_table_hash_percent_full - 	int(90),
Index: compiler/switch_detection.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/switch_detection.m,v
retrieving revision 1.93
diff -u -b -r1.93 switch_detection.m
--- compiler/switch_detection.m	2000/12/05 02:03:45	1.93
+++ compiler/switch_detection.m	2000/12/07 04:55:48
@@ -17,25 +17,26 @@
 :- interface.
 
 :- import_module hlds_goal, hlds_module, hlds_pred, prog_data.
-:- import_module io, list.
+:- import_module bool, io, list.
 
-:- pred detect_switches(module_info, module_info, io__state, io__state).
-:- mode detect_switches(in, out, di, uo) is det.
+:- pred detect_switches(module_info::in, module_info::out,
+	io__state::di, io__state::uo) is det.
 
-:- pred detect_switches_in_proc(proc_id, pred_id, module_info, module_info).
-:- mode detect_switches_in_proc(in, in, in, out) is det.
+:- pred detect_switches_in_proc(proc_id::in, pred_id::in,
+	module_info::in, module_info::out) is det.
 
 	% find_bind_var(Var, ProcessUnify, Goal0, Goals, Subst0, Subst,
-	%		Result0, Result, Continue):
+	%		Result0, Result, FoundDeconstruct):
 	% 	Used by both switch_detection and cse_detection.
 	%	Searches through `Goal0' looking for the first deconstruction
 	%	unification with `Var' or an alias of `Var'.
 	%	If a deconstruction unification of the variable is found,
 	%	`ProcessUnify' is called to handle it and searching is stopped.
 	%	If not, `Result' is set to `Result0'.
-:- pred find_bind_var(prog_var, process_unify(Result, Info), hlds_goal,
-		hlds_goal, Result, Result, Info, Info).
-:- mode find_bind_var(in, in(process_unify), in, out, in, out, in, out) is det.
+:- pred find_bind_var(prog_var::in,
+	process_unify(Result, Info)::in(process_unify),
+	hlds_goal::in, hlds_goal::out, Result::in, Result::out,
+	Info::in, Info::out, bool::out) is det.
 
 :- type process_unify(Result, Info) ==
 	pred(prog_var, hlds_goal, list(hlds_goal), Result, Result, Info, Info).
@@ -49,7 +50,7 @@
 :- import_module hlds_goal, hlds_data, prog_data, instmap, inst_match.
 :- import_module modes, mode_util, type_util, det_util.
 :- import_module passes_aux, term.
-:- import_module bool, char, int, assoc_list, map, set, std_util, require.
+:- import_module char, int, assoc_list, map, set, std_util, require.
 
 %-----------------------------------------------------------------------------%
 
@@ -406,7 +407,7 @@
 partition_disj_trial([], _Var, Left, Left, Cases, Cases).
 partition_disj_trial([Goal0 | Goals], Var, Left0, Left, Cases0, Cases) :-
 	find_bind_var(Var, find_bind_var_for_switch_in_deconstruct,
-		Goal0, Goal, no, MaybeFunctor, unit, _),
+		Goal0, Goal, no, MaybeFunctor, unit, _, _),
 	(
 		MaybeFunctor = yes(Functor),
 		Left1 = Left0,
@@ -449,28 +450,44 @@
 %-----------------------------------------------------------------------------%
 
 find_bind_var(Var, ProcessUnify, Goal0, Goal,
-		Result0, Result, Info0, Info) :-
+		Result0, Result, Info0, Info, FoundDeconstruct) :-
 	map__init(Substitution),
 	find_bind_var(Var, ProcessUnify, Goal0, Goal, Substitution,
-		_, Result0, Result, Info0, Info, _).
-
-:- pred find_bind_var(prog_var, process_unify(Result, Info), hlds_goal,
-		hlds_goal, prog_substitution, prog_substitution, Result, Result,
-		Info, Info, bool).
-:- mode find_bind_var(in, in(process_unify), in, out, in,
-	out, in, out, in, out, out) is det.
+		_, Result0, Result, Info0, Info, DeconstructSearch),
+	(
+		DeconstructSearch = before_deconstruct,
+		FoundDeconstruct = no
+	;
+		DeconstructSearch = found_deconstruct,
+		FoundDeconstruct = yes
+	;
+		DeconstructSearch = given_up_search,
+		FoundDeconstruct = no
+	).
 
-find_bind_var(Var, ProcessUnify, Goal0 - GoalInfo, Goal, Substitution0,
-		Substitution, Result0, Result, Info0, Info, Continue) :-
+:- type deconstruct_search
+	--->	before_deconstruct
+	;	found_deconstruct
+	;	given_up_search.
+
+:- pred find_bind_var(prog_var::in,
+	process_unify(Result, Info)::in(process_unify),
+	hlds_goal::in, hlds_goal::out,
+	prog_substitution::in, prog_substitution::out, Result::in, Result::out,
+	Info::in, Info::out, deconstruct_search::out) is det.
+
+find_bind_var(Var, ProcessUnify, Goal0 - GoalInfo, Goal,
+		Substitution0, Substitution, Result0, Result, Info0, Info,
+		FoundDeconstruct) :-
 	( Goal0 = some(Vars, CanRemove, SubGoal0) ->
 		find_bind_var(Var, ProcessUnify, SubGoal0, SubGoal,
 			Substitution0, Substitution, Result0, Result,
-			Info0, Info, Continue),
+			Info0, Info, FoundDeconstruct),
 		Goal = some(Vars, CanRemove, SubGoal) - GoalInfo
 	; Goal0 = conj(SubGoals0) ->
 		conj_find_bind_var(Var, ProcessUnify, SubGoals0, SubGoals,
 			Substitution0, Substitution, Result0, Result,
-			Info0, Info, Continue),
+			Info0, Info, FoundDeconstruct),
 		Goal = conj(SubGoals) - GoalInfo
 	; Goal0 = unify(A, B, _, UnifyInfo0, _) ->
 		(
@@ -488,11 +505,11 @@
 			call(ProcessUnify, Var, Goal0 - GoalInfo, Goals,
 				Result0, Result, Info0, Info),
 			conj_list_to_goal(Goals, GoalInfo, Goal),
-			Continue = no,
+			FoundDeconstruct = found_deconstruct,
 			Substitution = Substitution0
 		;
 			Goal = Goal0 - GoalInfo,
-			Continue = yes,
+			FoundDeconstruct = before_deconstruct,
 			% otherwise abstractly interpret the unification
 			Result = Result0,
 			Info = Info0,
@@ -508,33 +525,33 @@
 		Substitution = Substitution0,
 		Result = Result0,
 		Info = Info0,
-		Continue = no
+		FoundDeconstruct = given_up_search
 	).
 
-:- pred conj_find_bind_var(prog_var, process_unify(Result, Info), 
-		list(hlds_goal), list(hlds_goal), prog_substitution,
-		prog_substitution, Result, Result, Info, Info, bool).
-:- mode conj_find_bind_var(in, in(process_unify), in, out,
-	in, out, in, out, in, out, out) is det.
+:- pred conj_find_bind_var(prog_var::in,
+	process_unify(Result, Info)::in(process_unify), 
+	list(hlds_goal)::in, list(hlds_goal)::out,
+	prog_substitution::in, prog_substitution::out, Result::in, Result::out,
+	Info::in, Info::out, deconstruct_search::out) is det.
 
 conj_find_bind_var(_Var, _, [], [], Substitution, Substitution,
-		Result, Result, Info, Info, yes).
+		Result, Result, Info, Info, before_deconstruct).
 conj_find_bind_var(Var, ProcessUnify, [Goal0 | Goals0], [Goal | Goals],
 		Substitution0, Substitution, Result0, Result,
-		Info0, Info, Continue) :-
+		Info0, Info, FoundDeconstruct) :-
 	find_bind_var(Var, ProcessUnify, Goal0, Goal, Substitution0,
 		Substitution1, Result0, Result1,
-		Info0, Info1, Continue1),
-	( Continue1 = no ->
-		Continue = no,
+		Info0, Info1, FoundDeconstruct1),
+	( FoundDeconstruct1 = before_deconstruct ->
+		conj_find_bind_var(Var, ProcessUnify, Goals0, Goals,
+			Substitution1, Substitution, Result1, Result,
+			Info1, Info, FoundDeconstruct)
+	;
+		FoundDeconstruct = FoundDeconstruct1,
 		Goals = Goals0,
 		Substitution = Substitution1,
 		Result = Result1,
 		Info = Info1
-	;
-		conj_find_bind_var(Var, ProcessUnify, Goals0, Goals,
-			Substitution1, Substitution, Result1, Result,
-			Info1, Info, Continue)
 	).
 
 %-----------------------------------------------------------------------------%
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/graphics
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/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
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/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing library
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: [17:45:38] waiting for zs's lock in /home/mercury1/repository/mercury/samples/c_interface/mercury_calls_fortran
cvs diff: [17:46:08] obtained lock in /home/mercury1/repository/mercury/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/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
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 tests
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/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/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing trial
cvs diff: Diffing util
--------------------------------------------------------------------------
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