[m-dev.] diff: fix bug in Aditi compilation

Simon Taylor stayl at cs.mu.OZ.AU
Mon Mar 13 15:05:48 AEDT 2000


Estimated hours taken: 2

Make sure that magic.m and rl_gen.m agree on which Aditi procedures
can be compiled together.

compiler/magic.m:
	Run dead_proc_elim before working out which Aditi procedures
	can be compiled together, so that calls from dead procedures
	are not considered.

compiler/dead_proc_elim.m:
	Remove the dependency graph if anything changed, because
	the old dependency graph will still contain references
	to the dead procedures.

compiler/dependency_graph.m:
	Add a comment that dead_proc_elim should be run before
	module_info_ensure_aditi_dependency_info.


Index: dead_proc_elim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dead_proc_elim.m,v
retrieving revision 1.53
diff -u -u -r1.53 dead_proc_elim.m
--- dead_proc_elim.m	2000/03/10 13:37:40	1.53
+++ dead_proc_elim.m	2000/03/13 00:28:54
@@ -524,26 +524,39 @@
 	--->	elimination_info(
 			needed_map,	% collected usage counts 
 			module_info,	% ye olde module_info
-			pred_table	% table of predicates in this module:
+			pred_table,	% table of predicates in this module:
 					% preds and procs in this table
 					% may be eliminated
+			bool		% has anything changed
 		).
 			
 dead_proc_elim__eliminate(ModuleInfo0, Needed0, ModuleInfo, State0, State) :-
 	module_info_predids(ModuleInfo0, PredIds),
 	module_info_preds(ModuleInfo0, PredTable0),
 
-	ElimInfo0 = elimination_info(Needed0, ModuleInfo0, PredTable0),
+	Changed0 = no,
+	ElimInfo0 = elimination_info(Needed0, ModuleInfo0,
+			PredTable0, Changed0),
 	list__foldl2(dead_proc_elim__eliminate_pred, PredIds, ElimInfo0, 
 		ElimInfo, State0, State),
-	ElimInfo = elimination_info(Needed, ModuleInfo1, PredTable),
+	ElimInfo = elimination_info(Needed, ModuleInfo1, PredTable, Changed),
 
 	module_info_set_preds(ModuleInfo1, PredTable, ModuleInfo2),
 	module_info_type_ctor_gen_infos(ModuleInfo2, TypeCtorGenInfos0),
 	dead_proc_elim__eliminate_base_gen_infos(TypeCtorGenInfos0, Needed,
 		TypeCtorGenInfos),
 	module_info_set_type_ctor_gen_infos(ModuleInfo2, TypeCtorGenInfos,
-		ModuleInfo).
+		ModuleInfo3),
+	(
+		Changed = yes,
+		% The dependency graph will still contain references to the
+		% eliminated procedures, so it must be rebuilt if it will
+		% be used later.
+		module_info_clobber_dependency_info(ModuleInfo3, ModuleInfo)
+	;
+		Changed	= no,
+		ModuleInfo = ModuleInfo3
+	).
 
 		% eliminate any unused procedures for this pred
 
@@ -552,7 +565,7 @@
 :- mode dead_proc_elim__eliminate_pred(in, in, out, di, uo) is det.
 
 dead_proc_elim__eliminate_pred(PredId, ElimInfo0, ElimInfo, State0, State) :-
-	ElimInfo0 = elimination_info(Needed, ModuleInfo, PredTable0),
+	ElimInfo0 = elimination_info(Needed, ModuleInfo, PredTable0, Changed0),
 	map__lookup(PredTable0, PredId, PredInfo0),
 	pred_info_import_status(PredInfo0, Status),
 	(
@@ -572,7 +585,8 @@
 		pred_info_procedures(PredInfo0, ProcTable0),
 		list__foldl2(dead_proc_elim__eliminate_proc(PredId, Keep, 
 			ElimInfo0),
-			ProcIds, ProcTable0, ProcTable, State0, State),
+			ProcIds, Changed0 - ProcTable0, Changed - ProcTable,
+			State0, State),
 		pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
 		map__det_update(PredTable0, PredId, PredInfo, PredTable)
 	;
@@ -580,6 +594,7 @@
 		% unoptimized opt_imported preds
 		Status = opt_imported
 	->
+		Changed = yes,
 		pred_info_procids(PredInfo0, ProcIds),
 		pred_info_procedures(PredInfo0, ProcTable0),
 			% Reduce memory usage by replacing the goals with 
@@ -610,20 +625,22 @@
 	;
 		% This predicate is not defined in this module.
 		State = State0,
-		PredTable = PredTable0
+		PredTable = PredTable0,
+		Changed = Changed0
 	),
-	ElimInfo = elimination_info(Needed, ModuleInfo, PredTable).
+	ElimInfo = elimination_info(Needed, ModuleInfo, PredTable, Changed).
 
 
 		% eliminate a procedure, if unused
 
 :- pred dead_proc_elim__eliminate_proc(pred_id, maybe(proc_id), elim_info,
-	proc_id, proc_table, proc_table, io__state, io__state).
+	proc_id, pair(bool, proc_table), pair(bool, proc_table),
+	io__state, io__state).
 :- mode dead_proc_elim__eliminate_proc(in, in, in, in, in, out, di, uo) is det.
 
 dead_proc_elim__eliminate_proc(PredId, Keep, ElimInfo, ProcId, 
-		ProcTable0, ProcTable) -->
-	{ ElimInfo = elimination_info(Needed, ModuleInfo, _PredTable) },
+		Changed0 - ProcTable0, Changed - ProcTable) -->
+	{ ElimInfo = elimination_info(Needed, ModuleInfo, _PredTable, _) },
 	(
 		% Keep the procedure if it is in the needed map
 		% or if it is to be kept because it is exported.
@@ -631,8 +648,10 @@
 		; { Keep = yes(ProcId) }
 		)
 	->
-		{ ProcTable = ProcTable0 }
+		{ ProcTable = ProcTable0 },
+		{ Changed = Changed0 }
 	;
+		{ Changed = yes },
 		globals__io_lookup_bool_option(very_verbose, VeryVerbose),
 		( { VeryVerbose = yes } ->
 			write_proc_progress_message(
Index: dependency_graph.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dependency_graph.m,v
retrieving revision 1.46
diff -u -u -r1.46 dependency_graph.m
--- dependency_graph.m	2000/02/25 03:44:32	1.46
+++ dependency_graph.m	2000/03/13 03:56:30
@@ -50,6 +50,9 @@
 	% negation or aggregation are merged into the parent SCC. This makes
 	% the low-level RL optimizations more effective while maintaining
 	% stratification. 
+	% dead_proc_elim.m should be be run before this is called
+	% to avoid missing some opportunities for merging where
+	% a procedure is called from a dead procedure.
 :- pred module_info_ensure_aditi_dependency_info(module_info, module_info).
 :- mode module_info_ensure_aditi_dependency_info(in, out) is det.
 
Index: magic.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/magic.m,v
retrieving revision 1.13
diff -u -u -r1.13 magic.m
--- magic.m	2000/02/21 01:41:31	1.13
+++ magic.m	2000/03/08 03:42:58
@@ -21,6 +21,12 @@
 % in context.m) must be applied to all Aditi predicates. The magic sets
 % and context transformations are mutually exclusive.
 %
+% It is important that no optimization which could optimize away calls
+% to Aditi procedures (e.g. simplify.m) be run between magic.m and rl_gen.m.
+% If Aditi calls are removed, the code in dependency_graph.m which merges
+% the SCCs containing Aditi predicates could become confused about which
+% predicates can be compiled together.
+%
 %-----------------------------------------------------------------------------%
 % Short example:
 %
@@ -169,16 +175,38 @@
 :- import_module dependency_graph, hlds_pred, hlds_goal, hlds_data, prog_data.
 :- import_module passes_aux, mode_util, (inst), instmap, rl_gen, rl.
 :- import_module globals, options, hlds_out, prog_out, goal_util, type_util.
-:- import_module polymorphism, quantification, saved_vars.
+:- import_module polymorphism, quantification, saved_vars, dead_proc_elim.
 
 :- import_module int, list, map, require, set, std_util, string, term, varset.
 :- import_module assoc_list, bool, simplify.
 
 magic__process_module(ModuleInfo0, ModuleInfo) -->
-	{ module_info_ensure_aditi_dependency_info(ModuleInfo0, ModuleInfo1) },
-	{ module_info_aditi_dependency_ordering(ModuleInfo1, Ordering) },
-	{ magic_info_init(ModuleInfo1, Info0) },
-	{ module_info_predids(ModuleInfo1, PredIds) },
+
+	%
+	% Run simplification on Aditi procedures, mainly to get rid of 
+	% nested explicit quantifications.
+	% 
+	globals__io_get_globals(Globals),
+	{ simplify__find_simplifications(no, Globals, Simplifications) },
+	process_matching_nonimported_procs(
+		update_module_io(
+			magic__ite_to_disj_and_simplify(Simplifications)),
+		_, hlds_pred__pred_info_is_aditi_relation,
+		ModuleInfo0, ModuleInfo1),
+
+	% We need to run dead_proc_elim before working out the
+	% Aditi dependency ordering because any calls from dead
+	% procedures could confuse the code to merge SCCs (because
+	% procedures called from multiple places are never merged).
+	%
+	% No optimizations which could optimize away calls to Aditi
+	% procedures (e.g. simplify.m) should be run after this is done.
+	dead_proc_elim(ModuleInfo1, ModuleInfo2),
+
+	{ module_info_ensure_aditi_dependency_info(ModuleInfo2, ModuleInfo3) },
+	{ module_info_aditi_dependency_ordering(ModuleInfo3, Ordering) },
+	{ magic_info_init(ModuleInfo3, Info0) },
+	{ module_info_predids(ModuleInfo3, PredIds) },
 	{ magic__process_imported_procs(PredIds, Info0, Info1) },
 	globals__io_lookup_bool_option(very_verbose, Verbose),
 
@@ -194,22 +222,79 @@
 	list__foldl2(magic__process_scc, Ordering, Info3, Info4),
 	{ list__foldl(magic__update_pred_status, PredIds, Info4, Info5) },
 
-	{ magic_info_get_module_info(ModuleInfo2, Info5, Info) },
+	{ magic_info_get_module_info(ModuleInfo4, Info5, Info) },
 	{ magic_info_get_errors(Errors, Info, _) },
 	{ set__to_sorted_list(Errors, ErrorList) },
 	( { ErrorList = [] } ->
-		{ ModuleInfo3 = ModuleInfo2 }
+		{ ModuleInfo5 = ModuleInfo4 }
 	;
 		globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
 		magic_util__report_errors(ErrorList,
-			ModuleInfo2, VerboseErrors),
-		{ module_info_incr_errors(ModuleInfo2, ModuleInfo3) },
+			ModuleInfo4, VerboseErrors),
+		{ module_info_incr_errors(ModuleInfo4, ModuleInfo5) },
 		io__set_exit_status(1)
 	),
 
 		% New procedures were created, so the dependency_info
 		% is out of date.
-	{ module_info_clobber_dependency_info(ModuleInfo3, ModuleInfo) }.
+	{ module_info_clobber_dependency_info(ModuleInfo5, ModuleInfo) }.
+
+%-----------------------------------------------------------------------------%
+
+	%
+	% Convert if-then-elses and switches to disjunctions,
+	% then run simplification to flatten goals and remove
+	% unnecessary existential quantifications.
+	%
+:- pred magic__ite_to_disj_and_simplify(list(simplification)::in, pred_id::in,
+	proc_id::in, proc_info::in, proc_info::out, module_info::in,
+	module_info::out, io__state::di, io__state::uo) is det.
+
+magic__ite_to_disj_and_simplify(Simplifications, PredId, ProcId,
+		ProcInfo0, ProcInfo, ModuleInfo0, ModuleInfo) -->
+	{ proc_info_goal(ProcInfo0, Goal0) },
+
+	{ Goal0 = if_then_else(_Vars, Cond, Then, Else, _SM) - GoalInfo ->
+		goal_util__if_then_else_to_disjunction(Cond, Then, Else, 
+			GoalInfo, Disj),
+		Goal1 = Disj - GoalInfo,
+		proc_info_set_goal(ProcInfo0, Goal1, ProcInfo1),
+
+		% Requantify the goal to rename apart the variables
+		% in the copies of the condition.
+		requantify_proc(ProcInfo1, ProcInfo3),
+		ModuleInfo1 = ModuleInfo0
+	; Goal0 = switch(Var, _Canfail, Cases, _SM) - GoalInfo ->
+		proc_info_varset(ProcInfo0, VarSet0),
+		proc_info_vartypes(ProcInfo0, VarTypes0),
+		proc_info_get_initial_instmap(ProcInfo0, 
+			ModuleInfo0, InstMap),
+		% XXX check for existentially typed constructors first -
+		% they will cause an abort.
+		goal_util__switch_to_disjunction(Var, Cases,
+			InstMap, Disjuncts, VarSet0, VarSet1, 
+			VarTypes0, VarTypes1, ModuleInfo0, ModuleInfo1),
+		proc_info_set_varset(ProcInfo0, VarSet1, ProcInfo1),
+		proc_info_set_vartypes(ProcInfo1, VarTypes1, ProcInfo2),
+		map__init(SM),
+		Goal1 = disj(Disjuncts, SM) - GoalInfo,
+		proc_info_set_goal(ProcInfo2, Goal1, ProcInfo3)
+	;
+		ProcInfo3 = ProcInfo0,
+		ModuleInfo1 = ModuleInfo0
+	},
+
+	simplify__proc(Simplifications, PredId, ProcId,
+		ModuleInfo1, ModuleInfo2, ProcInfo3, ProcInfo4),
+
+	%
+	% Run saved_vars so that constructions of constants are close
+	% to their uses, and constant attributes aren't unnecessarily
+	% added to relations. We should be more aggressive about this -
+	% constructions of constant compound terms should also be pushed.
+	%
+	saved_vars_proc(PredId, ProcId, ProcInfo4, ProcInfo,
+		ModuleInfo2, ModuleInfo).
 
 %-----------------------------------------------------------------------------%
 
@@ -1344,70 +1429,16 @@
 
 magic__preprocess_proc(PredProcId, PredInfo, ProcInfo0, ProcInfo) -->
 	{ proc_info_goal(ProcInfo0, Goal0) },
-
-	%
-	% Convert if-then-elses and switches to disjunctions.
-	%
-	( { Goal0 = if_then_else(_Vars, Cond, Then, Else, _SM) - GoalInfo } ->
-		{ goal_util__if_then_else_to_disjunction(Cond, Then, Else, 
-			GoalInfo, Disj) },
-		{ Goal1 = Disj - GoalInfo },
-		{ ProcInfo2 = ProcInfo0 }
-	; { Goal0 = switch(Var, _Canfail, Cases, _SM) - GoalInfo } ->
-		{ proc_info_varset(ProcInfo0, VarSet0) },
-		{ proc_info_vartypes(ProcInfo0, VarTypes0) },
-		magic_info_get_module_info(ModuleInfo0),
-		{ proc_info_get_initial_instmap(ProcInfo0, 
-			ModuleInfo0, InstMap) },
-		% XXX check for existentially typed constructors first -
-		% they will cause an abort.
-		{ goal_util__switch_to_disjunction(Var, Cases,
-			InstMap, Disjuncts, VarSet0, VarSet1, 
-			VarTypes0, VarTypes1, ModuleInfo0, ModuleInfo1) },
-		magic_info_set_module_info(ModuleInfo1),
-		{ proc_info_set_varset(ProcInfo0, VarSet1, ProcInfo1) },
-		{ proc_info_set_vartypes(ProcInfo1, VarTypes1, ProcInfo2) },
-		{ map__init(SM) },
-		{ Goal1 = disj(Disjuncts, SM) - GoalInfo }
-	;
-		{ Goal1 = Goal0 },
-		{ ProcInfo2 = ProcInfo0 }
-	),
-
-	{ proc_info_set_goal(ProcInfo2, Goal1, ProcInfo3) },
-
-	%
-	% Run simplification, mainly to get rid of 
-	% nested explicit quantifications.
-	% 
-	magic_info_get_module_info(ModuleInfo2),
-	{ module_info_globals(ModuleInfo2, Globals) },
-	{ simplify__find_simplifications(no, Globals, Simplifications) },
-	{ PredProcId = proc(PredId, ProcId) },
-	{ simplify__proc_2(Simplifications, PredId, ProcId, 
-		ModuleInfo2, ModuleInfo3, ProcInfo3, ProcInfo4, _) },
-
-	%
-	% Run saved_vars so that constructions of constants are close
-	% to their uses, and constant attributes aren't unnecessarily
-	% added to relations. We should be more aggressive about this -
-	% constructions of constant compound terms should also be pushed.
-	%
-	{ saved_vars_proc_no_io(PredId, ProcId, ProcInfo4, ProcInfo5,
-		ModuleInfo3, ModuleInfo4) },
-
-	{ proc_info_goal(ProcInfo5, Goal2) },
 	magic_info_set_curr_pred_proc_id(PredProcId),
 	magic_info_set_pred_info(PredInfo),
-	magic_info_set_proc_info(ProcInfo5),
-	magic_info_set_module_info(ModuleInfo4),
-	{ Goal2 = _ - GoalInfo2 },
-	{ goal_to_disj_list(Goal2, GoalList2) },
+	magic_info_set_proc_info(ProcInfo0),
+	{ Goal0 = _ - GoalInfo0 },
+	{ goal_to_disj_list(Goal0, GoalList0) },
 	list__map_foldl(magic__preprocess_disjunct, 
-			GoalList2, GoalList),
-	{ disj_list_to_goal(GoalList, GoalInfo2, Goal) },
-	magic_info_get_proc_info(ProcInfo6),
-	{ proc_info_set_goal(ProcInfo6, Goal, ProcInfo) }.
+			GoalList0, GoalList),
+	{ disj_list_to_goal(GoalList, GoalInfo0, Goal) },
+	magic_info_get_proc_info(ProcInfo1),
+	{ proc_info_set_goal(ProcInfo1, Goal, ProcInfo) }.
 
 	% Undo common structure elimination of higher-order terms in an
 	% attempt to avoid creating procedures with higher-order arguments
--------------------------------------------------------------------------
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