[m-dev.] for review: fix the handling of unique modes in parallel conjunction

Thomas Conway conway at cs.mu.OZ.AU
Mon Aug 30 14:56:47 AEST 1999


Hi

Since this only affects parallel conjunction, I'll commit it now, but it
still needs to be reviewed. Fergus, or someone else who is familiar with
uniqueness?

-- 
 Thomas Conway )O+     Every sword has two edges.
     Mercurian            <conway at cs.mu.oz.au>


compiler/unique_modes.m:
compiler/par_conj_gen.m:
	Fix the handling of uniqueness in parallel conjunctions so that
	variables that occur in more than one conjunct become shared.

Index: unique_modes.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/unique_modes.m,v
retrieving revision 1.56
diff -u -r1.56 unique_modes.m
--- unique_modes.m	1999/08/26 17:49:04	1.56
+++ unique_modes.m	1999/08/30 01:49:36
@@ -62,7 +62,8 @@
 :- import_module modes, prog_data, mode_errors, llds, unify_proc.
 :- import_module (inst), instmap, inst_match, inst_util.
 :- import_module term, varset.
-:- import_module int, list, map, set, std_util, require, assoc_list, string.
+:- import_module assoc_list, bag, int, list, map.
+:- import_module require, set, std_util, string.
 
 %-----------------------------------------------------------------------------%
 
@@ -264,7 +265,11 @@
 	mode_checkpoint(enter, "par_conj"),
 	{ goal_info_get_nonlocals(GoalInfo0, NonLocals) },
 	mode_info_add_live_vars(NonLocals),
-	unique_modes__check_par_conj(List0, List, InstMapList),
+		% Build a multiset of the nonlocals of the conjuncts
+		% so that we can figure out which variables must be
+		% made shared at the start of the parallel conjunction.
+	{ make_par_conj_nonlocal_multiset(List0, NonLocalsBag) },
+	unique_modes__check_par_conj(List0, NonLocalsBag, List, InstMapList),
 	instmap__unify(NonLocals, InstMapList),
 	mode_info_remove_live_vars(NonLocals),
 	mode_checkpoint(exit, "par_conj").
@@ -642,25 +647,77 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred unique_modes__check_par_conj(list(hlds_goal), list(hlds_goal),
-		list(pair(instmap, set(prog_var))), mode_info, mode_info).
-:- mode unique_modes__check_par_conj(in, out, out,
+	% make_par_conj_nonlocal_multiset builds a multiset (bag) of all
+	% the nonlocals of the conjuncts.
+:- pred make_par_conj_nonlocal_multiset(list(hlds_goal), bag(prog_var)).
+:- mode make_par_conj_nonlocal_multiset(in, out) is det.
+
+make_par_conj_nonlocal_multiset([], Empty) :-
+	bag__init(Empty).
+make_par_conj_nonlocal_multiset([G|Gs], NonLocalsMultiSet) :-
+	make_par_conj_nonlocal_multiset(Gs, NonLocalsMultiSet0),
+	unique_modes__goal_get_nonlocals(G, NonLocals),
+	set__to_sorted_list(NonLocals, NonLocalsList),
+	bag__from_list(NonLocalsList, NonLocalsMultiSet1),
+	bag__union(NonLocalsMultiSet0, NonLocalsMultiSet1, NonLocalsMultiSet).
+
+	% To unique-modecheck a parallel conjunction, we find the variables
+	% that are nonlocal to more than one conjunct and make them shared,
+	% then we unique-modecheck the conjuncts.
+	%
+	% The variables that occur in more than one conjunct must be shared
+	% because otherwise it would be possible to make them become clobbered
+	% which would introduce an implicit dependency between the conjuncts
+	% which we do not allow.
+:- pred unique_modes__check_par_conj(list(hlds_goal), bag(prog_var),
+		list(hlds_goal), list(pair(instmap, set(prog_var))),
+		mode_info, mode_info).
+:- mode unique_modes__check_par_conj(in, in, out, out,
 		mode_info_di, mode_info_uo) is det.
 
+unique_modes__check_par_conj(Goals0, NonLocalVarsBag, Goals, Instmaps) -->
+	unique_modes__check_par_conj_0(NonLocalVarsBag),
+	unique_modes__check_par_conj_1(Goals0, Goals, Instmaps).
+
+		% Figure out which variables occur in more than one
+		% conjunct and make them shared.
+:- pred unique_modes__check_par_conj_0(bag(prog_var), mode_info, mode_info).
+:- mode unique_modes__check_par_conj_0(in, mode_info_di, mode_info_uo) is det.
+
+unique_modes__check_par_conj_0(NonLocalVarsBag, ModeInfo0, ModeInfo) :-
+	bag__to_assoc_list(NonLocalVarsBag, NonLocalVarsList),
+	list__filter_map((pred(Pair::in, Var::out) is semidet :-
+		Pair = Var - Multiplicity,
+		Multiplicity > 1
+	), NonLocalVarsList, SharedList),
+	mode_info_dcg_get_instmap(InstMap0, ModeInfo0, ModeInfo1),
+	instmap__lookup_vars(SharedList, InstMap0, VarInsts),
+	mode_info_get_module_info(ModeInfo1, ModuleInfo0),
+	make_shared_inst_list(VarInsts, ModuleInfo0,
+		SharedVarInsts, ModuleInfo1),
+	mode_info_set_module_info(ModeInfo1, ModuleInfo1, ModeInfo2),
+	instmap__set_vars(InstMap0, SharedList, SharedVarInsts, InstMap1),
+	mode_info_set_instmap(InstMap1, ModeInfo2, ModeInfo).
+
 	% Just process each conjunct in turn.
 	% Because we have already done modechecking, we know that
 	% there are no attempts to bind a variable in multiple
 	% parallel conjuncts, so we don't need to lock/unlock variables.
+
+:- pred unique_modes__check_par_conj_1(list(hlds_goal), list(hlds_goal),
+		list(pair(instmap, set(prog_var))), mode_info, mode_info).
+:- mode unique_modes__check_par_conj_1(in, out, out,
+		mode_info_di, mode_info_uo) is det.
 
-unique_modes__check_par_conj([], [], []) --> [].
-unique_modes__check_par_conj([Goal0 | Goals0], [Goal | Goals],
+unique_modes__check_par_conj_1([], [], []) --> [].
+unique_modes__check_par_conj_1([Goal0 | Goals0], [Goal | Goals],
 		[InstMap - NonLocals|InstMaps]) -->
 	{ unique_modes__goal_get_nonlocals(Goal0, NonLocals) },
 	mode_info_dcg_get_instmap(InstMap0),
 	unique_modes__check_goal(Goal0, Goal),
 	mode_info_dcg_get_instmap(InstMap),
 	mode_info_set_instmap(InstMap0),
-	unique_modes__check_par_conj(Goals0, Goals, InstMaps).
+	unique_modes__check_par_conj_1(Goals0, Goals, InstMaps).
 
 %-----------------------------------------------------------------------------%
 
Index: par_conj_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/par_conj_gen.m,v
retrieving revision 1.4
diff -u -r1.4 par_conj_gen.m
--- par_conj_gen.m	1999/04/16 06:04:48	1.4
+++ par_conj_gen.m	1999/08/30 01:39:49
@@ -68,7 +68,13 @@
 % conjunction, determinism analysis works by inferring the determinism of
 % each conjunct and reporting an error if it is not a model_det determinism.
 %
-% XXX Unique modes
+% We conservatively require that any variable that is nonlocal to more
+% than one parallel conjunct become shared at the start of the parallel
+% conjunction. This avoids problems where one conjunct has a use in a
+% di mode and another in a ui mode. This would introduce an implicit
+% dependency between the two conjuncts, which at present is illegal,
+% since parallel conjunction is currently *independent* parallel
+% conjunction only.
 %
 % The code generated for a parallel conjunction consists of a piece of
 % initialization code which creates a term on the heap to be used for
--------------------------------------------------------------------------
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