[m-rev.] for review: fix equivalence type performance problems

Simon Taylor stayl at cs.mu.OZ.AU
Fri Dec 12 00:47:30 AEDT 2003


Estimated hours taken: 15
Branches: main

Fix excessive memory usage caused by the equiv_type_hlds pass.

compiler/equiv_type_hlds.m:
compiler/equiv_type.m:
	Maintain sharing in insts in the equiv_type_hlds pass.

	Avoid duplicating types and insts which do not contain
	equivalence types to expand.  (It should be possible
	and may be worthwhile to implement a source to source
	transformation to do this sort of thing automatically.
	There are plenty of other instances of this in the
	compiler and library).

compiler/make_hlds.m:
	Change required by the above.

compiler/mercury_compile.m:
	Re-enable equiv_type_hlds.m.

tests/hard_coded/Mmakefile:
	Re-enable testing of equiv_type_hlds.m.

Index: compiler/equiv_type.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/equiv_type.m,v
retrieving revision 1.34
diff -u -u -r1.34 equiv_type.m
--- compiler/equiv_type.m	1 Dec 2003 15:55:32 -0000	1.34
+++ compiler/equiv_type.m	11 Dec 2003 07:48:28 -0000
@@ -45,9 +45,15 @@
 		in, out, di, uo) is det.
 
 	% Replace equivalence types in a given type.
-:- pred equiv_type__replace_in_type(eqv_map, type, type,
+	% The bool output is `yes' if anything changed.
+:- pred equiv_type__replace_in_type(eqv_map, type, type, bool,
 		tvarset, tvarset, equiv_type_info, equiv_type_info).
-:- mode equiv_type__replace_in_type(in, in, out, in, out, in, out) is det.
+:- mode equiv_type__replace_in_type(in, in, out, out, in, out, in, out) is det.
+
+:- pred equiv_type__replace_in_type_list(eqv_map, list(type), list(type),
+		bool, tvarset, tvarset, equiv_type_info, equiv_type_info).
+:- mode equiv_type__replace_in_type_list(in, in, out, out, in, out,
+		in, out) is det.
 
 :- pred equiv_type__replace_in_class_constraints(eqv_map, class_constraints, 
 		class_constraints, tvarset, tvarset,
@@ -389,8 +395,8 @@
 	equiv_type__replace_in_class_constraint_list(EqvMap,
 		Constraints0, Constraints, VarSet0, VarSet1,
 		UsedTypeCtors0, UsedTypeCtors1),
-	equiv_type__replace_in_type_list(EqvMap, Ts0, Ts, _, VarSet1, VarSet,
-		UsedTypeCtors1, UsedTypeCtors),
+	equiv_type__replace_in_type_list(EqvMap, Ts0, Ts, _, _,
+		VarSet1, VarSet, UsedTypeCtors1, UsedTypeCtors),
 	list__length(Ts0, Arity),
 	equiv_type__finish_recording_expanded_items(
 		item_id(typeclass, ClassName - Arity),
@@ -426,7 +432,7 @@
 equiv_type__replace_in_type_defn(EqvMap, TypeCtor, eqv_type(TBody0),
 		eqv_type(TBody), ContainsCirc, !VarSet, !Info) :-
 	equiv_type__replace_in_type_2(EqvMap, [TypeCtor], TBody0, TBody,
-		ContainsCirc, !VarSet, !Info).
+		_, ContainsCirc, !VarSet, !Info).
 
 equiv_type__replace_in_type_defn(EqvMap, _,
 		du_type(TBody0, IsSolverType, EqPred),
@@ -457,7 +463,8 @@
 equiv_type__replace_in_class_constraint(EqvMap, Constraint0, Constraint,
 		!VarSet, !Info) :-
 	Constraint0 = constraint(ClassName, Ts0),
-	equiv_type__replace_in_type_list(EqvMap, Ts0, Ts, _, !VarSet, !Info),
+	equiv_type__replace_in_type_list(EqvMap, Ts0, Ts,
+		_, _, !VarSet, !Info),
 	Constraint = constraint(ClassName, Ts).
 
 %-----------------------------------------------------------------------------%
@@ -523,7 +530,7 @@
 equiv_type__replace_in_subst(_EqvMap, [], [], !VarSet, !Info).
 equiv_type__replace_in_subst(EqvMap, [Var - Type0 | Subst0],
 		[Var - Type | Subst], !VarSet, !Info) :-
-	equiv_type__replace_in_type(EqvMap, Type0, Type, !VarSet, !Info),
+	equiv_type__replace_in_type(EqvMap, Type0, Type, _, !VarSet, !Info),
 	equiv_type__replace_in_subst(EqvMap, Subst0, Subst, !VarSet, !Info).
 
 %-----------------------------------------------------------------------------%
@@ -546,31 +553,43 @@
 
 %-----------------------------------------------------------------------------%
 
+equiv_type__replace_in_type_list(EqvMap, Ts0, Ts, Changed,
+		!VarSet, !Info) :-
+	equiv_type__replace_in_type_list_2(EqvMap, [], Ts0, Ts,
+		Changed, no, _, !VarSet, !Info).
+
 :- pred equiv_type__replace_in_type_list(eqv_map, list(type), list(type),
-		bool, tvarset, tvarset, equiv_type_info, equiv_type_info).
-:- mode equiv_type__replace_in_type_list(in, in, out, out, in, out,
+		bool, bool, tvarset, tvarset, equiv_type_info, equiv_type_info).
+:- mode equiv_type__replace_in_type_list(in, in, out, out, out, in, out,
 		in, out) is det.
 
-equiv_type__replace_in_type_list(EqvMap, Ts0, Ts, ContainsCirc,
+equiv_type__replace_in_type_list(EqvMap, Ts0, Ts, Changed, ContainsCirc,
 		!VarSet, !Info) :-
 	equiv_type__replace_in_type_list_2(EqvMap, [], Ts0, Ts,
-		no, ContainsCirc, !VarSet, !Info).
+		Changed, no, ContainsCirc, !VarSet, !Info).
 
 :- pred equiv_type__replace_in_type_list_2(eqv_map, list(type_ctor),
-		list(type), list(type), bool, bool, tvarset, tvarset,
+		list(type), list(type), bool, bool, bool, tvarset, tvarset,
 		equiv_type_info, equiv_type_info).
-:- mode equiv_type__replace_in_type_list_2(in, in, in, out,
+:- mode equiv_type__replace_in_type_list_2(in, in, in, out, out,
 		in, out, in, out, in, out) is det.
 
-equiv_type__replace_in_type_list_2(_EqvMap, _Seen, [], [],
+equiv_type__replace_in_type_list_2(_EqvMap, _Seen, [], [], no,
 		!ContainsCirc, !VarSet, !Info).
-equiv_type__replace_in_type_list_2(EqvMap, Seen, [T0 | Ts0], [T | Ts],
-		!Circ, !VarSet, !Info) :-
-	equiv_type__replace_in_type_2(EqvMap, Seen, T0, T, ContainsCirc,
-		!VarSet, !Info),
+equiv_type__replace_in_type_list_2(EqvMap, Seen, List0 @ [T0 | Ts0], List,
+		Changed, !Circ, !VarSet, !Info) :-
+	equiv_type__replace_in_type_2(EqvMap, Seen, T0, T, Changed0,
+		ContainsCirc, !VarSet, !Info),
 	!:Circ = ContainsCirc `or` !.Circ,
 	equiv_type__replace_in_type_list_2(EqvMap, Seen, Ts0, Ts,
-		!Circ, !VarSet, !Info).
+		Changed1, !Circ, !VarSet, !Info),
+	( ( Changed0 = yes ; Changed1 = yes ) ->
+		Changed = yes,
+		List = [T | Ts]
+	;
+		Changed = no,
+		List = List0
+	).
 
 %-----------------------------------------------------------------------------%
 
@@ -595,7 +614,7 @@
 		!VarSet, !Info).
 equiv_type__replace_in_ctor_arg_list_2(EqvMap, Seen, [N - T0 | As0],
 		[N - T | As], !Circ, !VarSet, !Info) :-
-	equiv_type__replace_in_type_2(EqvMap, Seen, T0, T, ContainsCirc,
+	equiv_type__replace_in_type_2(EqvMap, Seen, T0, T, _, ContainsCirc,
 		!VarSet, !Info),
 	!:Circ = !.Circ `or` ContainsCirc,
 	equiv_type__replace_in_ctor_arg_list_2(EqvMap, Seen, As0, As,
@@ -603,28 +622,28 @@
 
 %-----------------------------------------------------------------------------%
 
-equiv_type__replace_in_type(EqvMap, Type0, Type, !VarSet, !Info) :-
-	equiv_type__replace_in_type_2(EqvMap, [], Type0, Type, _,
+equiv_type__replace_in_type(EqvMap, Type0, Type, Changed, !VarSet, !Info) :-
+	equiv_type__replace_in_type_2(EqvMap, [], Type0, Type, Changed, _,
 		!VarSet, !Info).
 
 	% Replace all equivalence types in a given type, detecting  
 	% any circularities.
 :- pred equiv_type__replace_in_type_2(eqv_map, list(type_ctor), type, type,
-	bool, tvarset, tvarset, equiv_type_info, equiv_type_info).
-:- mode equiv_type__replace_in_type_2(in, in, in, out, out,
+	bool, bool, tvarset, tvarset, equiv_type_info, equiv_type_info).
+:- mode equiv_type__replace_in_type_2(in, in, in, out, out, out,
 	in, out, in, out) is det.
 
 equiv_type__replace_in_type_2(_EqvMap, _Seen,
-		term__variable(V), term__variable(V), no, !VarSet, !Info).
+		term__variable(V), term__variable(V), no, no, !VarSet, !Info).
 equiv_type__replace_in_type_2(EqvMap, TypeCtorsAlreadyExpanded, Type0, Type,
-		Circ, !VarSet, !Info) :- 
+		Changed, Circ, !VarSet, !Info) :- 
 	Type0 = term__functor(_, _, _),
 	(
 		type_to_ctor_and_args(Type0, EqvTypeCtor, TArgs0)
 	->
 		equiv_type__replace_in_type_list_2(EqvMap,
 			TypeCtorsAlreadyExpanded, TArgs0, TArgs1,
-			no, Circ0, !VarSet, !Info),
+			ArgsChanged, no, Circ0, !VarSet, !Info),
 
 		( list__member(EqvTypeCtor, TypeCtorsAlreadyExpanded) ->
 			Circ1 = yes
@@ -651,6 +670,7 @@
 			Circ0 = no,
 			Circ1 = no
 		->
+			Changed = yes,
 			equiv_type__record_expanded_item(
 				item_id(type, EqvTypeCtor), !Info),
 			term__term_list_to_var_list(Args, ArgVars),
@@ -658,12 +678,20 @@
 							Body, Type1),
 			equiv_type__replace_in_type_2(EqvMap,
 				[EqvTypeCtor | TypeCtorsAlreadyExpanded],
-				Type1, Type, Circ, !VarSet, !Info)
+				Type1, Type, _, Circ, !VarSet, !Info)
 		;
+			ArgsChanged = yes
+		->
+			Changed = yes,
 			construct_type(EqvTypeCtor, TArgs1, Type),
 			bool__or(Circ0, Circ1, Circ)
+		;
+			Changed = no,
+			Type = Type0,
+			bool__or(Circ0, Circ1, Circ)
 		)
 	;
+		Changed = no,
 		Type = Type0,
 		Circ = no
 	).
@@ -735,7 +763,7 @@
 	(
 		MaybeWithType0 = yes(WithType0),
 		equiv_type__replace_in_type(EqvMap, WithType0, WithType,
-			!TypeVarSet, !Info),
+			_, !TypeVarSet, !Info),
 		(
 			type_is_higher_order(WithType, _Purity, PredOrFunc,
 				_EvalMethod, ExtraTypes0)
@@ -872,11 +900,11 @@
 
 equiv_type__replace_in_tm(EqvMap, type_only(Type0),
 		type_only(Type), !VarSet, !Info) :-
-	equiv_type__replace_in_type(EqvMap, Type0, Type, !VarSet, !Info).
+	equiv_type__replace_in_type(EqvMap, Type0, Type, _, !VarSet, !Info).
 
 equiv_type__replace_in_tm(EqvMap, type_and_mode(Type0, Mode),
 		type_and_mode(Type, Mode), !VarSet, !Info) :-
-	equiv_type__replace_in_type(EqvMap, Type0, Type, !VarSet, !Info).
+	equiv_type__replace_in_type(EqvMap, Type0, Type, _, !VarSet, !Info).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/equiv_type_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/equiv_type_hlds.m,v
retrieving revision 1.1
diff -u -u -r1.1 equiv_type_hlds.m
--- compiler/equiv_type_hlds.m	1 Dec 2003 15:55:32 -0000	1.1
+++ compiler/equiv_type_hlds.m	11 Dec 2003 13:28:17 -0000
@@ -51,12 +51,15 @@
 	module_info_set_types(Types, !ModuleInfo),
 	module_info_set_maybe_recompilation_info(MaybeRecompInfo, !ModuleInfo),
 
+	InstCache0 = map__init,
+
 	module_info_insts(!.ModuleInfo, Insts0),
-	replace_in_inst_table(EqvMap, Insts0, Insts),
+	replace_in_inst_table(EqvMap, Insts0, Insts, InstCache0, InstCache1),
 	module_info_set_insts(Insts, !ModuleInfo),
 
 	module_info_predids(!.ModuleInfo, PredIds),
-	list__foldl(replace_in_pred(EqvMap), PredIds, !ModuleInfo).
+	list__foldl2(replace_in_pred(EqvMap), PredIds, !ModuleInfo,
+		InstCache1, _).
 
 :- pred add_type_to_eqv_map(type_ctor::in, hlds_type_defn::in,
 		eqv_map::in, eqv_map::out) is det.
@@ -89,7 +92,7 @@
 		Body = Body0 ^ du_type_ctors := Ctors
 	;
 		Body0 = eqv_type(Type0),
-		equiv_type__replace_in_type(EqvMap, Type0, Type,
+		equiv_type__replace_in_type(EqvMap, Type0, Type, _,
 			TVarSet0, TVarSet, EquivTypeInfo0, EquivTypeInfo),
 		Body = eqv_type(Type)
 	;
@@ -110,9 +113,10 @@
 	hlds_data__set_type_defn_tvarset(Defn1, TVarSet, Defn).
 
 :- pred replace_in_inst_table(eqv_map::in,
-		inst_table::in, inst_table::out) is det.
+		inst_table::in, inst_table::out,
+		inst_cache::in, inst_cache::out) is det.
 
-replace_in_inst_table(EqvMap, !InstTable) :-
+replace_in_inst_table(EqvMap, !InstTable, !Cache) :-
 	/*
 	%
 	% We currently have no syntax for typed user-defined insts,
@@ -143,16 +147,16 @@
 	inst_table_get_shared_insts(!.InstTable, SharedInsts0),
 	inst_table_get_mostly_uniq_insts(!.InstTable, MostlyUniqInsts0),
 	replace_in_inst_table(replace_in_maybe_inst_det(EqvMap),
-		EqvMap, UnifyInsts0, UnifyInsts),
-	replace_in_merge_inst_table(EqvMap, MergeInsts0, MergeInsts),
+		EqvMap, UnifyInsts0, UnifyInsts, !Cache),
+	replace_in_merge_inst_table(EqvMap, MergeInsts0, MergeInsts, !Cache),
 	replace_in_inst_table(replace_in_maybe_inst_det(EqvMap),
-		EqvMap, GroundInsts0, GroundInsts),
+		EqvMap, GroundInsts0, GroundInsts, !Cache),
 	replace_in_inst_table(replace_in_maybe_inst_det(EqvMap),
-		EqvMap, AnyInsts0, AnyInsts),
+		EqvMap, AnyInsts0, AnyInsts, !Cache),
 	replace_in_inst_table(replace_in_maybe_inst(EqvMap),
-		EqvMap, SharedInsts0, SharedInsts),
+		EqvMap, SharedInsts0, SharedInsts, !Cache),
 	replace_in_inst_table(replace_in_maybe_inst(EqvMap),
-		EqvMap, MostlyUniqInsts0, MostlyUniqInsts),
+		EqvMap, MostlyUniqInsts0, MostlyUniqInsts, !.Cache, _),
 	inst_table_set_unify_insts(!.InstTable, UnifyInsts, !:InstTable),
 	inst_table_set_merge_insts(!.InstTable, MergeInsts, !:InstTable),
 	inst_table_set_ground_insts(!.InstTable, GroundInsts, !:InstTable),
@@ -161,63 +165,71 @@
 	inst_table_set_mostly_uniq_insts(!.InstTable,
 		MostlyUniqInsts, !:InstTable).
 
-:- pred replace_in_inst_table(pred(T, T)::(pred(in, out) is det), eqv_map::in,
-		map(inst_name, T)::in, map(inst_name, T)::out) is det.
+:- pred replace_in_inst_table(
+	pred(T, T, inst_cache, inst_cache)::(pred(in, out, in, out) is det),
+	eqv_map::in, map(inst_name, T)::in, map(inst_name, T)::out,
+	inst_cache::in, inst_cache::out) is det.
 
-replace_in_inst_table(P, EqvMap, Map0, Map) :-
+replace_in_inst_table(P, EqvMap, Map0, Map, !Cache) :-
 	map__to_assoc_list(Map0, AL0),
-	list__map(
-		(pred((Name0 - T0)::in, (Name - T)::out) is det :-
+	list__map_foldl(
+		(pred((Name0 - T0)::in, (Name - T)::out,
+				!.Cache::in, !:Cache::out) is det :-
 			% XXX We don't have a valid tvarset here.
 			varset__init(TVarSet),
-			replace_in_inst_name(EqvMap, Name0, Name, TVarSet, _),
-			P(T0, T)
-		), AL0, AL),
+			replace_in_inst_name(EqvMap, Name0, Name,
+				_, TVarSet, _, !Cache),
+			P(T0, T, !Cache)
+		), AL0, AL, !Cache),
 	map__from_assoc_list(AL, Map).
 
 :- pred replace_in_merge_inst_table(eqv_map::in, merge_inst_table::in,
-		merge_inst_table::out) is det.
+		merge_inst_table::out, inst_cache::in, inst_cache::out) is det.
 
-replace_in_merge_inst_table(EqvMap, Map0, Map) :-
+replace_in_merge_inst_table(EqvMap, Map0, Map, !Cache) :-
 	map__to_assoc_list(Map0, AL0),
-	list__map(
+	list__map_foldl(
 		(pred(((InstA0 - InstB0) - MaybeInst0)::in,
-				((InstA - InstB) - MaybeInst)::out) is det :-
+				((InstA - InstB) - MaybeInst)::out,
+				!.Cache::in, !:Cache::out) is det :-
 			some [!TVarSet] (
 				% XXX We don't have a valid tvarset here.
 				!:TVarSet = varset__init,
 				replace_in_inst(EqvMap, InstA0, InstA,
-					!TVarSet),
-				replace_in_inst(EqvMap, InstB0, InstB,
-					!.TVarSet, _),
+					_, !TVarSet, !Cache),
+				replace_in_inst(EqvMap, InstB0, InstB, _,
+					!.TVarSet, _, !Cache),
 				replace_in_maybe_inst(EqvMap, MaybeInst0,
-					MaybeInst)
+					MaybeInst, !Cache)
 			)
-		), AL0, AL),
+		), AL0, AL, !Cache),
 	map__from_assoc_list(AL, Map).
 
-:- pred replace_in_maybe_inst(eqv_map::in,
-		maybe_inst::in, maybe_inst::out) is det.
+:- pred replace_in_maybe_inst(eqv_map::in, maybe_inst::in, maybe_inst::out,
+		inst_cache::in, inst_cache::out) is det.
 
-replace_in_maybe_inst(_, unknown, unknown).
-replace_in_maybe_inst(EqvMap, known(Inst0), known(Inst)) :-
+replace_in_maybe_inst(_, unknown, unknown, !Cache).
+replace_in_maybe_inst(EqvMap, known(Inst0), known(Inst), !Cache) :-
 	% XXX We don't have a valid tvarset here.
 	varset__init(TVarSet),
-	replace_in_inst(EqvMap, Inst0, Inst, TVarSet, _).
+	replace_in_inst(EqvMap, Inst0, Inst, _, TVarSet, _, !Cache).
 	
 :- pred replace_in_maybe_inst_det(eqv_map::in,
-		maybe_inst_det::in, maybe_inst_det::out) is det.
+		maybe_inst_det::in, maybe_inst_det::out,
+		inst_cache::in, inst_cache::out) is det.
 
-replace_in_maybe_inst_det(_, unknown, unknown).
-replace_in_maybe_inst_det(EqvMap, known(Inst0, Det), known(Inst, Det)) :-
+replace_in_maybe_inst_det(_, unknown, unknown, !Cache).
+replace_in_maybe_inst_det(EqvMap, known(Inst0, Det), known(Inst, Det),
+		!Cache) :-
 	% XXX We don't have a valid tvarset here.
 	varset__init(TVarSet),
-	replace_in_inst(EqvMap, Inst0, Inst, TVarSet, _).	
+	replace_in_inst(EqvMap, Inst0, Inst, _, TVarSet, _, !Cache).
 
 :- pred replace_in_pred(eqv_map::in, pred_id::in,
-		module_info::in, module_info::out) is det.
+		module_info::in, module_info::out,
+		inst_cache::in, inst_cache::out) is det.
 
-replace_in_pred(EqvMap, PredId, !ModuleInfo) :-
+replace_in_pred(EqvMap, PredId, !ModuleInfo, !Cache) :-
     some [!PredInfo, !EquivTypeInfo] (
 	module_info_name(!.ModuleInfo, ModuleName),
 	module_info_pred_info(!.ModuleInfo, PredId, !:PredInfo),
@@ -230,8 +242,8 @@
 		MaybeRecompInfo0, !:EquivTypeInfo),
 
 	pred_info_arg_types(!.PredInfo, ArgTVarSet0, ExistQVars, ArgTypes0),
-	list__map_foldl2(equiv_type__replace_in_type(EqvMap),
-		ArgTypes0, ArgTypes, ArgTVarSet0, ArgTVarSet1, !EquivTypeInfo),
+	equiv_type__replace_in_type_list(EqvMap, ArgTypes0, ArgTypes,
+		_, ArgTVarSet0, ArgTVarSet1, !EquivTypeInfo),
 
 	% The constraint_proofs aren't used after polymorphism,
 	% so they don't need to be processed.
@@ -252,31 +264,32 @@
 
     	pred_info_procedures(!.PredInfo, Procs0),
 	map__map_foldl(replace_in_proc(EqvMap), Procs0, Procs,
-		{!.ModuleInfo, !.PredInfo}, {!:ModuleInfo, !:PredInfo}),
+		{!.ModuleInfo, !.PredInfo, !.Cache},
+		{!:ModuleInfo, !:PredInfo, !:Cache}),
     	pred_info_set_procedures(Procs, !PredInfo),
 
     	module_info_set_pred_info(PredId, !.PredInfo, !ModuleInfo)
     ).
 
 :- pred replace_in_proc(eqv_map::in, proc_id::in,
-	proc_info::in, proc_info::out, {module_info, pred_info}::in,
-	{module_info, pred_info}::out) is det.
+	proc_info::in, proc_info::out,
+	{module_info, pred_info, inst_cache}::in,
+	{module_info, pred_info, inst_cache}::out) is det.
 
-replace_in_proc(EqvMap, _, !ProcInfo, {!.ModuleInfo, !.PredInfo},
-		{!:ModuleInfo, !:PredInfo}) :-
+replace_in_proc(EqvMap, _, !ProcInfo, {!.ModuleInfo, !.PredInfo, !.Cache},
+		{!:ModuleInfo, !:PredInfo, !:Cache}) :-
     some [!TVarSet] (
 	pred_info_typevarset(!.PredInfo, !:TVarSet),
 
 	proc_info_argmodes(!.ProcInfo, ArgModes0),
-	list__map_foldl(replace_in_mode(EqvMap),
-		ArgModes0, ArgModes, !TVarSet),
+	replace_in_modes(EqvMap, ArgModes0, ArgModes, _, !TVarSet, !Cache),
 	proc_info_set_argmodes(ArgModes, !ProcInfo),
 
 	proc_info_maybe_declared_argmodes(!.ProcInfo, MaybeDeclModes0),
 	(
 		MaybeDeclModes0 = yes(DeclModes0),
-		list__map_foldl(replace_in_mode(EqvMap),
-			DeclModes0, DeclModes, !TVarSet),
+		replace_in_modes(EqvMap, DeclModes0, DeclModes, _,
+			!TVarSet, !Cache),
 		proc_info_set_maybe_declared_argmodes(yes(DeclModes),
 			!ProcInfo)
 	;
@@ -288,7 +301,7 @@
 		(pred(_::in, VarType0::in, VarType::out,
 				!.TVarSet::in, !:TVarSet::out) is det :-
 			equiv_type__replace_in_type(EqvMap,
-				VarType0, VarType, !TVarSet, no, _)	
+				VarType0, VarType, _, !TVarSet, no, _)	
 		),
 		VarTypes0, VarTypes, !TVarSet),
 	proc_info_set_vartypes(VarTypes, !ProcInfo),
@@ -307,9 +320,9 @@
 	proc_info_goal(!.ProcInfo, Goal0),
 	replace_in_goal(EqvMap, Goal0, Goal,
 		replace_info(!.ModuleInfo, !.PredInfo,
-				!.ProcInfo, !.TVarSet, no),
+				!.ProcInfo, !.TVarSet, !.Cache, no),
 		replace_info(!:ModuleInfo, !:PredInfo,
-				!:ProcInfo, !:TVarSet, Recompute)),
+				!:ProcInfo, !:TVarSet, _XXX, Recompute)),
 	proc_info_set_goal(Goal, !ProcInfo),
 
 	( Recompute = yes ->
@@ -322,81 +335,238 @@
 	pred_info_set_typevarset(!.TVarSet, !PredInfo)
     ).
 
-:- pred replace_in_mode(eqv_map::in, (mode)::in, (mode)::out,
-		tvarset::in, tvarset::out) is det.
+%-----------------------------------------------------------------------------%
+
+% Note that we go out of our way to avoid duplicating unchanged
+% insts and modes.  This means we don't need to hash-cons those
+% insts to avoid losing sharing.
+
+:- pred replace_in_modes(eqv_map::in, list(mode)::in, list(mode)::out,
+	bool::out, tvarset::in, tvarset::out,
+	inst_cache::in, inst_cache::out) is det.
+
+replace_in_modes(_EqvMap, [], [], no, !TVarSet, !Cache).
+replace_in_modes(EqvMap, List0 @ [Mode0 | Modes0], List, Changed,
+		!TVarSet, !Cache) :-
+	replace_in_mode(EqvMap, Mode0, Mode, Changed0, !TVarSet, !Cache),
+	replace_in_modes(EqvMap, Modes0, Modes, Changed1, !TVarSet, !Cache),
+	( ( Changed0 = yes ; Changed1 = yes ) ->
+		Changed = yes,
+		List = [Mode | Modes]
+	;
+		Changed = no,
+		List = List0
+	).
 
-replace_in_mode(EqvMap, (InstA0 -> InstB0), (InstA -> InstB), !TVarSet) :-
-	replace_in_inst(EqvMap, InstA0, InstA, !TVarSet),
-	replace_in_inst(EqvMap, InstB0, InstB, !TVarSet).
-replace_in_mode(EqvMap, user_defined_mode(Name, Insts0),
-		user_defined_mode(Name, Insts), !TVarSet) :-
-	list__map_foldl(replace_in_inst(EqvMap), Insts0, Insts, !TVarSet).
+:- pred replace_in_mode(eqv_map::in, (mode)::in, (mode)::out, bool::out,
+	tvarset::in, tvarset::out, inst_cache::in, inst_cache::out) is det.
+
+replace_in_mode(EqvMap, Mode0 @ (InstA0 -> InstB0), Mode,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_inst(EqvMap, InstA0, InstA, ChangedA, !TVarSet, !Cache),
+	replace_in_inst(EqvMap, InstB0, InstB, ChangedB, !TVarSet, !Cache),
+	( ( ChangedA = yes ; ChangedB = yes ) ->
+		Changed = yes,
+		Mode = (InstA -> InstB)
+	;
+		Changed = no,
+		Mode = Mode0
+	).
+replace_in_mode(EqvMap, Mode0 @ user_defined_mode(Name, Insts0), Mode,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_insts(EqvMap, Insts0, Insts, Changed, !TVarSet, !Cache),
+	( Changed = yes, Mode = user_defined_mode(Name, Insts)
+	; Changed = no, Mode = Mode0
+	).
 
 :- pred replace_in_inst(eqv_map::in, (inst)::in, (inst)::out,
-		tvarset::in, tvarset::out) is det.
+	bool::out, tvarset::in, tvarset::out,
+	inst_cache::in, inst_cache::out) is det.
 
-replace_in_inst(_, any(_) @ Inst, Inst, !TVarSet).
-replace_in_inst(_, free @ Inst, Inst, !TVarSet).
-replace_in_inst(EqvMap, free(Type0), free(Type), !TVarSet) :-
-	equiv_type__replace_in_type(EqvMap, Type0, Type, !TVarSet, no, _).
-replace_in_inst(EqvMap, bound(Uniq, BoundInsts0),
-		bound(Uniq, BoundInsts), !TVarSet) :-
-	list__map_foldl(
-		(pred(functor(ConsId, Insts0)::in, functor(ConsId, Insts)::out,
-				!.TVarSet::in, !:TVarSet::out) is det :-
-			list__map_foldl(replace_in_inst(EqvMap),
-				Insts0, Insts, !TVarSet)
-		), BoundInsts0, BoundInsts, !TVarSet).
-replace_in_inst(_, ground(_, none) @ Inst, Inst, !TVarSet).
-replace_in_inst(EqvMap,
-		ground(Uniq, higher_order(pred_inst_info(PorF, Modes0, Det))),
-		ground(Uniq, higher_order(pred_inst_info(PorF, Modes, Det))),
-		!TVarSet) :-
-	list__map_foldl(replace_in_mode(EqvMap), Modes0, Modes, !TVarSet).
-replace_in_inst(_, not_reached @ Inst, Inst, !TVarSet).
-replace_in_inst(_, inst_var(_) @ Inst, Inst, !TVarSet).
-replace_in_inst(EqvMap, constrained_inst_vars(Vars, Inst0),
-		constrained_inst_vars(Vars, Inst), !TVarSet) :-
-	replace_in_inst(EqvMap, Inst0, Inst, !TVarSet).
-replace_in_inst(EqvMap, defined_inst(InstName0),
-		defined_inst(InstName), !TVarSet) :-
-	replace_in_inst_name(EqvMap, InstName0, InstName, !TVarSet).
-replace_in_inst(EqvMap, abstract_inst(Name, Insts0),
-		abstract_inst(Name, Insts), !TVarSet) :-
-	list__map_foldl(replace_in_inst(EqvMap), Insts0, Insts, !TVarSet).
+replace_in_inst(EqvMap, Inst0, Inst, Changed, !TVarSet, !Cache) :-
+	replace_in_inst_2(EqvMap, Inst0, Inst1, Changed, !TVarSet, !Cache),
+	( Changed = yes ->
+		% Doing this when the inst has not changed is too slow,
+		% and makes the cache potentially very large. 
+		hash_cons_inst(Inst1, Inst, !Cache)
+	;
+		Inst = Inst1
+	).
+
+:- pred replace_in_inst_2(eqv_map::in, (inst)::in, (inst)::out, bool::out,
+	tvarset::in, tvarset::out, inst_cache::in, inst_cache::out) is det.
+
+replace_in_inst_2(_, any(_) @ Inst, Inst, no, !TVarSet, !Cache).
+replace_in_inst_2(_, free @ Inst, Inst, no, !TVarSet, !Cache).
+replace_in_inst_2(EqvMap, Inst0 @ free(Type0), Inst, Changed,
+		!TVarSet, !Cache) :-
+	equiv_type__replace_in_type(EqvMap, Type0, Type, Changed,
+			!TVarSet, no, _),
+	( Changed = yes, Inst = free(Type)
+	; Changed = no, Inst = Inst0
+	).
+replace_in_inst_2(EqvMap, Inst0 @ bound(Uniq, BoundInsts0), Inst,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_bound_insts(EqvMap, BoundInsts0, BoundInsts,
+		Changed, !TVarSet, !Cache),
+	( Changed = yes, Inst = bound(Uniq, BoundInsts)
+	; Changed = no, Inst = Inst0
+	).
+replace_in_inst_2(_, ground(_, none) @ Inst, Inst, no, !TVarSet, !Cache).
+replace_in_inst_2(EqvMap,
+		Inst0 @ ground(Uniq,
+			higher_order(pred_inst_info(PorF, Modes0, Det))),
+		Inst, Changed, !TVarSet, !Cache) :-
+	replace_in_modes(EqvMap, Modes0, Modes, Changed, !TVarSet, !Cache),
+	( Changed = yes,
+		Inst = ground(Uniq,
+			higher_order(pred_inst_info(PorF, Modes, Det)))
+	; Changed = no,
+		Inst = Inst0
+	).	
+replace_in_inst_2(_, not_reached @ Inst, Inst, no, !TVarSet, !Cache).
+replace_in_inst_2(_, inst_var(_) @ Inst, Inst, no, !TVarSet, !Cache).
+replace_in_inst_2(EqvMap, Inst0 @ constrained_inst_vars(Vars, CInst0), Inst,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_inst(EqvMap, CInst0, CInst, Changed, !TVarSet, !Cache),
+	( Changed = yes, Inst = constrained_inst_vars(Vars, CInst)
+	; Changed = no, Inst = Inst0
+	).
+replace_in_inst_2(EqvMap, Inst0 @ defined_inst(InstName0), Inst,
+		 Changed, !TVarSet, !Cache) :-
+	replace_in_inst_name(EqvMap, InstName0, InstName, Changed,
+		!TVarSet, !Cache),
+	( Changed = yes, Inst = defined_inst(InstName)
+	; Changed = no, Inst = Inst0
+	).
+replace_in_inst_2(EqvMap, Inst0 @ abstract_inst(Name, Insts0), Inst,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_insts(EqvMap, Insts0, Insts, Changed, !TVarSet, !Cache),
+	( Changed = yes, Inst = abstract_inst(Name, Insts)
+	; Changed = no, Inst = Inst0
+	).
 
 :- pred replace_in_inst_name(eqv_map::in, inst_name::in, inst_name::out,
-		tvarset::in, tvarset::out) is det.
+	bool::out, tvarset::in, tvarset::out,
+	inst_cache::in, inst_cache::out) is det.
 
-replace_in_inst_name(EqvMap, user_inst(Name, Insts0),
-		user_inst(Name, Insts), !TVarSet) :-
-	list__map_foldl(replace_in_inst(EqvMap), Insts0, Insts, !TVarSet).
-replace_in_inst_name(EqvMap, merge_inst(Name, Inst0),
-		merge_inst(Name, Inst), !TVarSet) :-
-	replace_in_inst(EqvMap, Inst0, Inst, !TVarSet).
-replace_in_inst_name(EqvMap, unify_inst(Live, InstA0, InstB0, Real),
-		unify_inst(Live, InstA, InstB, Real), !TVarSet) :-
-	replace_in_inst(EqvMap, InstA0, InstA, !TVarSet),
-	replace_in_inst(EqvMap, InstB0, InstB, !TVarSet).
-replace_in_inst_name(EqvMap, ground_inst(Name0, Live, Uniq, Real),
-		ground_inst(Name, Live, Uniq, Real), !TVarSet) :-
-	replace_in_inst_name(EqvMap, Name0, Name, !TVarSet).
-replace_in_inst_name(EqvMap, any_inst(Name0, Live, Uniq, Real),
-		any_inst(Name, Live, Uniq, Real), !TVarSet) :-
-	replace_in_inst_name(EqvMap, Name0, Name, !TVarSet).
-replace_in_inst_name(EqvMap, shared_inst(Name0),
-		shared_inst(Name), !TVarSet) :-
-	replace_in_inst_name(EqvMap, Name0, Name, !TVarSet).
-replace_in_inst_name(EqvMap, mostly_uniq_inst(Name0),
-		mostly_uniq_inst(Name), !TVarSet) :-
-	replace_in_inst_name(EqvMap, Name0, Name, !TVarSet).
-replace_in_inst_name(EqvMap, typed_ground(Uniq, Type0),
-		typed_ground(Uniq, Type), !TVarSet) :-
-	replace_in_type(EqvMap, Type0, Type, !TVarSet, no, _).
-replace_in_inst_name(EqvMap, typed_inst(Type0, Name0),
-		typed_inst(Type, Name), !TVarSet) :-
-	replace_in_type(EqvMap, Type0, Type, !TVarSet, no, _),
-	replace_in_inst_name(EqvMap, Name0, Name, !TVarSet).
+replace_in_inst_name(EqvMap, InstName0 @ user_inst(Name, Insts0), InstName,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_insts(EqvMap, Insts0, Insts, Changed, !TVarSet, !Cache),
+	( Changed = yes, InstName = user_inst(Name, Insts)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ merge_inst(InstA0, InstB0), InstName,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_inst(EqvMap, InstA0, InstA, ChangedA, !TVarSet, !Cache),
+	replace_in_inst(EqvMap, InstB0, InstB, ChangedB, !TVarSet, !Cache),
+	Changed = ChangedA `or` ChangedB,
+	( Changed = yes, InstName = merge_inst(InstA, InstB)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap,
+		InstName0 @ unify_inst(Live, InstA0, InstB0, Real),
+		InstName, Changed, !TVarSet, !Cache) :-
+	replace_in_inst(EqvMap, InstA0, InstA, ChangedA, !TVarSet, !Cache),
+	replace_in_inst(EqvMap, InstB0, InstB, ChangedB, !TVarSet, !Cache),
+	Changed = ChangedA `or` ChangedB,
+	( Changed = yes, InstName = unify_inst(Live, InstA, InstB, Real)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ ground_inst(Name0, Live, Uniq, Real),
+		InstName, Changed, !TVarSet, !Cache) :-
+	replace_in_inst_name(EqvMap, Name0, Name, Changed, !TVarSet, !Cache),
+	( Changed = yes, InstName = ground_inst(Name, Live, Uniq, Real)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ any_inst(Name0, Live, Uniq, Real),
+		InstName, Changed, !TVarSet, !Cache) :-
+	replace_in_inst_name(EqvMap, Name0, Name, Changed, !TVarSet, !Cache),
+	( Changed = yes, InstName = any_inst(Name, Live, Uniq, Real)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ shared_inst(Name0), InstName,
+		 Changed, !TVarSet, !Cache) :-
+	replace_in_inst_name(EqvMap, Name0, Name, Changed, !TVarSet, !Cache),
+	( Changed = yes, InstName = shared_inst(Name)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ mostly_uniq_inst(Name0),
+		InstName, Changed, !TVarSet, !Cache) :-
+	replace_in_inst_name(EqvMap, Name0, Name, Changed, !TVarSet, !Cache),
+	( Changed = yes, InstName = mostly_uniq_inst(Name)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ typed_ground(Uniq, Type0), InstName,
+		Changed, !TVarSet, !Cache) :-
+	replace_in_type(EqvMap, Type0, Type, Changed, !TVarSet, no, _),
+	( Changed = yes, InstName = typed_ground(Uniq, Type)
+	; Changed = no, InstName = InstName0
+	).
+replace_in_inst_name(EqvMap, InstName0 @ typed_inst(Type0, Name0),
+		InstName, Changed, !TVarSet, !Cache) :-
+	replace_in_type(EqvMap, Type0, Type, TypeChanged, !TVarSet, no, _),
+	replace_in_inst_name(EqvMap, Name0, Name, Changed0, !TVarSet, !Cache),
+	( ( TypeChanged = yes ; Changed0 = yes ) ->
+		Changed = yes,
+		InstName = typed_inst(Type, Name)
+	;
+		Changed = no,
+		InstName = InstName0
+	).
+
+:- pred replace_in_bound_insts(eqv_map::in, list(bound_inst)::in,
+	list(bound_inst)::out, bool::out, tvarset::in, tvarset::out,
+	inst_cache::in, inst_cache::out) is det.
+
+replace_in_bound_insts(_EqvMap, [], [], no, !TVarSet, !Cache).
+replace_in_bound_insts(EqvMap, List0 @ [functor(ConsId, Insts0) | BoundInsts0],
+		List, Changed, !TVarSet, !Cache) :-
+	replace_in_insts(EqvMap, Insts0, Insts,
+		InstsChanged, !TVarSet, !Cache),
+	replace_in_bound_insts(EqvMap, BoundInsts0, BoundInsts, Changed0,
+		!TVarSet, !Cache),
+	( ( Changed0 = yes ; InstsChanged = yes ) ->
+		Changed = yes,
+		List = [functor(ConsId, Insts) | BoundInsts]
+	;
+		Changed = no,
+		List = List0
+	).
+
+:- pred replace_in_insts(eqv_map::in, list(inst)::in, list(inst)::out,
+	bool::out, tvarset::in, tvarset::out,
+	inst_cache::in, inst_cache::out) is det.
+
+replace_in_insts(_EqvMap, [], [], no, !TVarSet, !Cache).
+replace_in_insts(EqvMap, List0 @ [Inst0 | Insts0], List, Changed,
+		!TVarSet, !Cache) :-
+	replace_in_inst(EqvMap, Inst0, Inst, Changed0, !TVarSet, !Cache),
+	replace_in_insts(EqvMap, Insts0, Insts, Changed1, !TVarSet, !Cache),
+	( ( Changed0 = yes ; Changed1 = yes ) ->
+		Changed = yes,
+		List = [Inst | Insts]
+	;
+		Changed = no,
+		List = List0
+	).
+
+	% We hash-cons (actually map-cons) insts created by this pass
+	% to avoid losing sharing.
+:- type inst_cache == map(inst, inst).
+
+:- pred hash_cons_inst((inst)::in, (inst)::out,
+		inst_cache::in, inst_cache::out) is det.
+
+hash_cons_inst(Inst0, Inst, !Cache) :-
+	( Inst1 = map__search(!.Cache, Inst0) ->
+		Inst = Inst1
+	;
+		Inst = Inst0,
+		!:Cache = map__det_insert(!.Cache, Inst, Inst)
+	).
+
+%-----------------------------------------------------------------------------%
 
 :- type replace_info
 	---> replace_info(
@@ -404,6 +574,7 @@
 		pred_info :: pred_info,
 		proc_info :: proc_info,
 		tvarset :: tvarset,
+		inst_cache :: inst_cache,
 		recompute :: bool
 	).
 
@@ -416,12 +587,17 @@
 
 	goal_info_get_instmap_delta(GoalInfo0, InstMapDelta0),
 	TVarSet0 = !.Info ^ tvarset,
+	Cache0 = !.Info ^ inst_cache,
 	instmap_delta_map_foldl(
 		(pred(_::in, Inst0::in, Inst::out,
-				!.TVarSet::in, !:TVarSet::out) is det :-
-			replace_in_inst(EqvMap, Inst0, Inst, !TVarSet)
-		), InstMapDelta0, InstMapDelta, TVarSet0, TVarSet),
-	!:Info = !.Info ^ tvarset := TVarSet,
+				{TVarSet1, Cache1}::in,
+				{TVarSet2, Cache2}::out) is det :-
+			replace_in_inst(EqvMap, Inst0, Inst, _,
+				TVarSet1, TVarSet2, Cache1, Cache2)
+		), InstMapDelta0, InstMapDelta,
+		{TVarSet0, Cache0}, {TVarSet, Cache}),
+	!:Info = (!.Info ^ tvarset := TVarSet)
+			^ inst_cache := Cache,
 	goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo).
 
 :- pred replace_in_goal_expr(eqv_map::in,
@@ -454,16 +630,18 @@
 replace_in_goal_expr(EqvMap, foreign_proc(_, _, _, _, _, _, _) @ Goal0, Goal,
 			!Info) :-
 	TVarSet0 = !.Info ^ tvarset,
-	list__map_foldl2(replace_in_type(EqvMap), Goal0 ^ foreign_types,
-		Types, TVarSet0, TVarSet, no, _),
+	replace_in_type_list(EqvMap, Goal0 ^ foreign_types, Types,
+		_, TVarSet0, TVarSet, no, _),
 	!:Info = !.Info ^ tvarset := TVarSet,
 	Goal = Goal0 ^ foreign_types := Types.	
 replace_in_goal_expr(EqvMap, generic_call(A, B, Modes0, D),
 		generic_call(A, B, Modes, D), !Info) :-
 	TVarSet0 = !.Info ^ tvarset,
-	list__map_foldl(replace_in_mode(EqvMap), Modes0, Modes,
-		TVarSet0, TVarSet),
-	!:Info = !.Info ^ tvarset := TVarSet.
+	Cache0 = !.Info ^ inst_cache,
+	replace_in_modes(EqvMap, Modes0, Modes, _,
+		TVarSet0, TVarSet, Cache0, Cache),
+	!:Info = (!.Info ^ tvarset := TVarSet)
+			^ inst_cache := Cache.
 replace_in_goal_expr(EqvMap, unify(Var, _, _, _, _) @ Goal0, Goal, !Info) :-
 	module_info_types(!.Info ^ module_info, Types),
 	proc_info_vartypes(!.Info ^ proc_info, VarTypes),
@@ -528,9 +706,13 @@
 	;
 		Goal0 ^ unify_mode = LMode0 - RMode0,
 		TVarSet0 = !.Info ^ tvarset,
-		replace_in_mode(EqvMap, LMode0, LMode, TVarSet0, TVarSet1),
-		replace_in_mode(EqvMap, RMode0, RMode, TVarSet1, TVarSet),
-		!:Info = !.Info ^ tvarset := TVarSet,
+		Cache0 = !.Info ^ inst_cache,
+		replace_in_mode(EqvMap, LMode0, LMode, _, TVarSet0, TVarSet1,
+			Cache0, Cache1),
+		replace_in_mode(EqvMap, RMode0, RMode, _, TVarSet1, TVarSet,
+			Cache1, Cache),
+		!:Info = (!.Info ^ tvarset := TVarSet)
+				^ inst_cache := Cache,
 		replace_in_unification(EqvMap, Goal0 ^ unify_kind, Unification,
 			!Info),
 		Goal = (Goal0 ^ unify_mode := LMode - RMode)
@@ -563,11 +745,13 @@
 
 replace_in_uni_mode(EqvMap, ((InstA0 - InstB0) -> (InstC0 - InstD0)),
 		((InstA - InstB) -> (InstC - InstD)), !Info) :-
-	some [!TVarSet] (
+	some [!TVarSet, !Cache] (
 		!:TVarSet = !.Info ^ tvarset,
-		replace_in_inst(EqvMap, InstA0, InstA, !TVarSet),
-		replace_in_inst(EqvMap, InstB0, InstB, !TVarSet),
-		replace_in_inst(EqvMap, InstC0, InstC, !TVarSet),
-		replace_in_inst(EqvMap, InstD0, InstD, !TVarSet),
-		!:Info = !.Info ^ tvarset := !.TVarSet
+		!:Cache = !.Info ^ inst_cache,
+		replace_in_inst(EqvMap, InstA0, InstA, _, !TVarSet, !Cache),
+		replace_in_inst(EqvMap, InstB0, InstB, _, !TVarSet, !Cache),
+		replace_in_inst(EqvMap, InstC0, InstC, _, !TVarSet, !Cache),
+		replace_in_inst(EqvMap, InstD0, InstD, _, !TVarSet, !Cache),
+		!:Info = (!.Info ^ tvarset := !.TVarSet)
+				^ inst_cache := !.Cache
 	).
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.457
diff -u -u -r1.457 make_hlds.m
--- compiler/make_hlds.m	2 Dec 2003 10:01:50 -0000	1.457
+++ compiler/make_hlds.m	11 Dec 2003 07:18:56 -0000
@@ -8127,7 +8127,7 @@
 	% because at the moment no recompilation.item_id can depend on a
 	% clause item.
 	RecordExpanded = no,
-	equiv_type__replace_in_type(EqvMap, Type2, Type, TVarSet1, TVarSet,
+	equiv_type__replace_in_type(EqvMap, Type2, Type, _, TVarSet1, TVarSet,
 		RecordExpanded, _)
 	},
 	update_var_types(VarTypes0, Var, Type, Context, VarTypes),
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.296
diff -u -u -r1.296 mercury_compile.m
--- compiler/mercury_compile.m	9 Dec 2003 12:58:29 -0000	1.296
+++ compiler/mercury_compile.m	10 Dec 2003 12:38:07 -0000
@@ -2968,11 +2968,7 @@
 	maybe_write_string(Verbose,
 		"% Fully expanding equivalence types..."),
 	maybe_flush_output(Verbose),
-
-	{ HLDS = HLDS0 },
-	% XXX There's a performance bug (excessive memory usage)
-	% in here somewhere.
-	% { equiv_type_hlds__replace_in_hlds(HLDS0, HLDS) },
+	{ equiv_type_hlds__replace_in_hlds(HLDS0, HLDS) },
 	maybe_write_string(Verbose, " done.\n").
 
 %-----------------------------------------------------------------------------%
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.212
diff -u -u -r1.212 Mmakefile
--- tests/hard_coded/Mmakefile	11 Dec 2003 07:35:23 -0000	1.212
+++ tests/hard_coded/Mmakefile	11 Dec 2003 07:37:02 -0000
@@ -55,6 +55,7 @@
 	existential_types_test \
 	expand \
 	export_test \
+	export_test2 \
 	external_unification_pred \
 	failure_unify \
 	field_syntax \
@@ -253,8 +254,6 @@
 # XXX compare_rep_array doesn't work because MR_COMPARE_BY_RTTI is
 #     not yet implemented for arrays.
 #
-# XXX export_test2 doesn't work because the equiv_type_hlds pass is disabled
-#     due to performance problems.
 
 # The following tests are passed only in some grades.
 
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list