diff: liveness bug fix

Fergus Henderson fjh at cs.mu.oz.au
Mon Aug 25 17:53:15 AEST 1997


Here's the diff I forgot for this one.

> Fix a bug which caused the code generator to fail on certain
> examples involving predicates with determinism `erroneous'.
> 
> compiler/inst_match.m:
> 	Change `inst_is_bound' so that it succeeds for `not_reached' insts.
> 	This change is so that the behaviour of the predicate matches
> 	the documentation, and so that it is consistent with the behaviour
> 	of `inst_is_ground'.
> 
> compiler/liveness.m:
> 	When computing the value-giving occurrences, check explicitly
> 	for unreachable instmaps.  This is necessary to handle the above
> 	change to `inst_is_bound'.
> 
> 	Fix a bug in detect_deadness: it was applying the deaths before
> 	the births, but it should be done in the other order.
> 	Normally deaths must be applied before births, but in detect_deadness
> 	we are traversing the goal backwards, so we must apply births first
> 	and then deaths.
> 
> 	The old solution of just cancelling out any vars that occur in
> 	both the post-death and post-birth set was not quite right;
> 	instead we just need to apply them in the correct order.
> 
> compiler/code_info.m:
> 	Change the code so that it applies the pre/post deaths
> 	before applying the corresponding births.
> 
> compiler/live_vars.m:
> compiler/store_alloc.m:
> compiler/hlds_goal.m:
> 	Add some comments about making sure we always apply the deaths
> 	before applying the births.  (The code here was already correct,
> 	I just added some documentation.)
> 
> compiler/hlds_out.m:
> 	Print out the pre/post deaths before the pre/post births, so
> 	that the order that they are printed out in matches the order
> 	in which they should be applied.
> 
> tests/hard_coded/Mmake:
> tests/hard_coded/erroneous_liveness.m:
> tests/hard_coded/erroneous_liveness.exp:
> tests/hard_coded/erroneous_liveness.inp:
> 	Regression test for the above-mentioned bug fix.

Index: inst_match.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/inst_match.m,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -u -r1.33 -r1.34
--- inst_match.m	1997/07/27 15:00:36	1.33
+++ inst_match.m	1997/08/23 20:32:58	1.34
@@ -741,6 +741,7 @@
         % or is a user-defined inst which is not defined as `free'.
         % Abstract insts must be bound.
 
+inst_is_bound(_, not_reached).
 inst_is_bound(_, any(_)).
 inst_is_bound(_, ground(_, _)).
 inst_is_bound(_, bound(_, _)).
Index: liveness.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/liveness.m,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -u -r1.78 -r1.79
--- liveness.m	1997/07/27 15:00:49	1.78
+++ liveness.m	1997/08/23 20:33:02	1.79
@@ -23,6 +23,10 @@
 % track of aliasing and for structure re-use optimization, whereas here
 % we are concerned with the liveness of the variable itself, for the
 % purposes of optimizing stack slot and register usage.
+% Variables have a lifetime: each variable is born, gets used, and then dies.
+% To minimize stack slot and register usage, the birth should be
+% as late as possible (but before the first possible use), and the
+% death should be as early as possible (but after the last possible use).
 %
 % We compute liveness related information in three distinct passes.
 %
@@ -154,35 +158,39 @@
 	set__difference(NonLocals, Liveness0, NewVarsSet),
 	set__to_sorted_list(NewVarsSet, NewVarsList),
 	goal_info_get_instmap_delta(GoalInfo0, InstMapDelta),
-	set__init(Births0),
-	find_value_giving_occurrences(NewVarsList, LiveInfo, InstMapDelta,
-		Births0, Births),
-	set__union(Liveness0, Births, Liveness),
 	set__init(Empty),
+	( instmap_delta_is_unreachable(InstMapDelta) ->
+		Births = Empty
+	;
+		set__init(Births0),
+		find_value_giving_occurrences(NewVarsList, LiveInfo,
+			InstMapDelta, Births0, Births)
+	),
+	set__union(Liveness0, Births, Liveness),
 	(
 		goal_is_atomic(Goal0)
 	->
-		PreBirths = Births,
 		PreDeaths = Empty,
-		PostBirths = Empty,
+		PreBirths = Births,
 		PostDeaths = Empty,
+		PostBirths = Empty,
 		Goal = Goal0
 	;
-		PreBirths = Empty,
 		PreDeaths = Empty,
+		PreBirths = Empty,
 		detect_liveness_in_goal_2(Goal0, Liveness0, NonLocals,
 			LiveInfo, ActualLiveness, Goal),
 		set__intersect(NonLocals, ActualLiveness, NonLocalLiveness),
 		set__union(NonLocalLiveness, Liveness0, FinalLiveness),
-		set__difference(Liveness, FinalLiveness, PostBirths),
-		set__difference(FinalLiveness, Liveness, PostDeaths)
+		set__difference(FinalLiveness, Liveness, PostDeaths),
+		set__difference(Liveness, FinalLiveness, PostBirths)
 	),
 		% We initialize all the fields in order to obliterate any
 		% annotations left by a previous invocation of this module.
-	goal_info_set_pre_births(GoalInfo0, PreBirths, GoalInfo1),
-	goal_info_set_post_births(GoalInfo1, PostBirths, GoalInfo2),
-	goal_info_set_pre_deaths(GoalInfo2, PreDeaths, GoalInfo3),
-	goal_info_set_post_deaths(GoalInfo3, PostDeaths, GoalInfo4),
+	goal_info_set_pre_deaths(GoalInfo0, PreDeaths, GoalInfo1),
+	goal_info_set_pre_births(GoalInfo1, PreBirths, GoalInfo2),
+	goal_info_set_post_deaths(GoalInfo2, PostDeaths, GoalInfo3),
+	goal_info_set_post_births(GoalInfo3, PostBirths, GoalInfo4),
 	goal_info_set_resume_point(GoalInfo4, no_resume_point, GoalInfo).
 
 %-----------------------------------------------------------------------------%
@@ -329,35 +337,49 @@
 
 detect_deadness_in_goal(Goal0 - GoalInfo0, Deadness0, LiveInfo, Deadness,
 		Goal - GoalInfo) :-
-	goal_info_get_pre_births(GoalInfo0, PreBirths0),
-	goal_info_get_post_births(GoalInfo0, PostBirths0),
 	goal_info_get_pre_deaths(GoalInfo0, PreDeaths0),
+	goal_info_get_pre_births(GoalInfo0, PreBirths0),
 	goal_info_get_post_deaths(GoalInfo0, PostDeaths0),
-	set__union(Deadness0, PostDeaths0, Deadness1),
-	set__difference(Deadness1, PostBirths0, Deadness2),
+	goal_info_get_post_births(GoalInfo0, PostBirths0),
+
+	set__difference(Deadness0, PostBirths0, Deadness1),
+	set__union(Deadness1, PostDeaths0, Deadness2),
 
 	liveness__get_nonlocals_and_typeinfos(LiveInfo, GoalInfo0, NonLocals),
 	set__init(Empty),
 	(
 		goal_is_atomic(Goal0)
 	->
-		NewPreDeaths = Empty,
+		% 
+		% The code below is slightly dodgy: the new postdeaths really
+		% ought to be computed as the difference between the liveness
+		% immediately before goal and the deadness immediately after
+		% goal.  But we don't have liveness available here, and
+		% computing it would be complicated and perhaps costly.  So
+		% instead we use the non-locals.  The effect of this is that a
+		% variable will die after its last occurence, even if it has
+		% never been born.  (This can occur in the case of variables
+		% with `free->free' modes, or for goals with determinism
+		% erroneous.)  Thus the code generator must be willing to
+		% handle that -- it is not considered an error for a variable
+		% that is not yet live to die.  [If we ever wanted to
+		% change this, the easiest thing to do would be to put
+		% some extra code in the third pass (detect_resume_points)
+		% to delete any such untimely deaths.]
+		% 
 		set__difference(NonLocals, Deadness2, NewPostDeaths),
 		set__union(Deadness2, NewPostDeaths, Deadness3),
 		Goal = Goal0
 	;
-		NewPreDeaths = Empty,
 		NewPostDeaths = Empty,
 		detect_deadness_in_goal_2(Goal0, GoalInfo0, Deadness2,
 			LiveInfo, Deadness3, Goal)
 	),
-	set__union(PreDeaths0, NewPreDeaths, PreDeaths),
 	set__union(PostDeaths0, NewPostDeaths, PostDeaths),
-	goal_info_set_pre_deaths(GoalInfo0, PreDeaths, GoalInfo1),
-	goal_info_set_post_deaths(GoalInfo1, PostDeaths, GoalInfo),
+	goal_info_set_post_deaths(GoalInfo0, PostDeaths, GoalInfo),
 
-	set__union(Deadness3, PreDeaths0, Deadness4),
-	set__difference(Deadness4, PreBirths0, Deadness).
+	set__difference(Deadness3, PreBirths0, Deadness4),
+	set__union(Deadness4, PreDeaths0, Deadness).
 
 	% Here we process each of the different sorts of goals.
 
@@ -497,10 +519,10 @@
 
 detect_resume_points_in_goal(Goal0 - GoalInfo0, Liveness0, LiveInfo,
 		ResumeVars0, Goal - GoalInfo0, Liveness) :-
-	goal_info_get_pre_births(GoalInfo0, PreBirths0),
-	goal_info_get_post_births(GoalInfo0, PostBirths0),
 	goal_info_get_pre_deaths(GoalInfo0, PreDeaths0),
+	goal_info_get_pre_births(GoalInfo0, PreBirths0),
 	goal_info_get_post_deaths(GoalInfo0, PostDeaths0),
+	goal_info_get_post_births(GoalInfo0, PostBirths0),
 
 	set__difference(Liveness0, PreDeaths0, Liveness1),
 	set__union(Liveness1, PreBirths0, Liveness2),
@@ -576,29 +598,7 @@
 	CondResume = resume_point(CondResumeVars, CondResumeLocs),
 	goal_set_resume_point(Cond1, CondResume, Cond),
 
-	(
-		set__equal(LivenessThen, LivenessElse)
-	->
-		true
-	;
-		live_info_get_varset(LiveInfo, Varset),
-		set__to_sorted_list(LivenessThen, ThenVarsList),
-		set__to_sorted_list(LivenessElse, ElseVarsList),
-		list__map(varset__lookup_name(Varset),
-			ThenVarsList, ThenVarNames),
-		list__map(varset__lookup_name(Varset),
-			ElseVarsList, ElseVarNames),
-		Pad = lambda([S0::in, S::out] is det,
-			string__append(S0, " ", S)),
-		list__map(Pad, ThenVarNames, PaddedThenNames),
-		list__map(Pad, ElseVarNames, PaddedElseNames),
-		string__append_list(PaddedThenNames, ThenNames),
-		string__append_list(PaddedElseNames, ElseNames),
-		string__append_list([
-			"branches of if-then-else disagree on liveness\nThen: ",
-			ThenNames, "\nElse: ", ElseNames], Msg),
-		error(Msg)
-	).
+	require_equal(LivenessThen, LivenessElse, "if-then-else", LiveInfo).
 
 detect_resume_points_in_goal_2(some(Vars, Goal0), _, Liveness0, LiveInfo,
 		ResumeVars0, some(Vars, Goal), Liveness) :-
@@ -759,8 +759,7 @@
 	set__difference(Liveness0, PreDeaths, NeededFirst),
 	set__union(NeededFirst, NeededRest, Needed),
 
-	require(set__equal(Liveness, LivenessRest),
-		"branches of disjunction disagree on liveness").
+	require_equal(Liveness, LivenessRest, "disjunction", LiveInfo).
 
 :- pred detect_resume_points_in_last_disjunct(hlds_goal, set(var), live_info,
 	set(var), hlds_goal, set(var), set(var)).
@@ -788,12 +787,44 @@
 	( Cases0 = [_ | _] ->
 		detect_resume_points_in_cases(Cases0, Liveness0, LiveInfo,
 			ResumeVars0, Cases, LivenessRest),
-		require(set__equal(LivenessFirst, LivenessRest),
-			"branches of switch disagree on liveness")
+		require_equal(LivenessFirst, LivenessRest, "switch",
+			LiveInfo)
 	;
 		Cases = Cases0
 	).
 
+:- pred require_equal(set(var), set(var), string, live_info).
+:- mode require_equal(in, in, in, in) is det.
+
+require_equal(LivenessFirst, LivenessRest, GoalType, LiveInfo) :-
+	(
+		set__equal(LivenessFirst, LivenessRest)
+	->
+		true
+	;
+		live_info_get_varset(LiveInfo, Varset),
+		set__to_sorted_list(LivenessFirst, FirstVarsList),
+		set__to_sorted_list(LivenessRest, RestVarsList),
+		list__map(varset__lookup_name(Varset),
+			FirstVarsList, FirstVarNames),
+		list__map(varset__lookup_name(Varset),
+			RestVarsList, RestVarNames),
+		Pad = lambda([S0::in, S::out] is det,
+			string__append(S0, " ", S)),
+		list__map(Pad, FirstVarNames, PaddedFirstNames),
+		list__map(Pad, RestVarNames, PaddedRestNames),
+		string__append_list(PaddedFirstNames, FirstNames),
+		string__append_list(PaddedRestNames, RestNames),
+		string__append_list(["branches of ", GoalType, 
+			" disagree on liveness\nFirst: ",
+			FirstNames, "\nRest: ", RestNames], Msg),
+		% error(Msg)
+		dump(Msg) % XXX temporary debugging hack
+	).
+
+:- pred dump(string::in) is det.
+:- pragma c_code(dump(S::in), "puts(S);").
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -902,47 +933,13 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-	% Consider a goal such as
-	%
-	% ( Cond ->
-	%	DCG = value1
-	%	error
-	% ;
-	%	...
-	%	DCG = value2
-	% )
-	%
-	% When working working on the goal representing the then-part,
-	% detect_liveness_in_goal will put DCG into its post-death set,
-	% because the then-part cannot succeed and thus the lifetime of DCG
-	% is over at the end of the then-part.
-	%
-	% Later, at the end of the processing of the if-then-else, we will
-	% then put DCG into the post-birth set of the then-part, since it
-	% would have to be produced by the then-part if it ever terminated.
-	%
-	% Rather than end up with DCG in both the post-death and post-birth
-	% sets, which can cause problems if they are applied in the wrong
-	% order, we instead put into neither. This is fine; the intended
-	% result is that DCG should be live after the then-part, and it must
-	% have been born during the then-part (otherwise it would not have
-	% been put into the post-death set).
-
 :- pred add_liveness_after_goal(hlds_goal, set(var), hlds_goal).
 :- mode add_liveness_after_goal(in, in, out) is det.
 
 add_liveness_after_goal(Goal - GoalInfo0, Residue, Goal - GoalInfo) :-
-	goal_info_get_post_deaths(GoalInfo0, PostDeaths0),
 	goal_info_get_post_births(GoalInfo0, PostBirths0),
-
-	set__intersect(Residue, PostDeaths0, CancelledDeaths),
-	set__difference(Residue, CancelledDeaths, NewBirths),
-
-	set__difference(PostDeaths0, CancelledDeaths, PostDeaths),
-	set__union(PostBirths0, NewBirths, PostBirths),
-
-	goal_info_set_post_births(GoalInfo0, PostBirths, GoalInfo1),
-	goal_info_set_post_deaths(GoalInfo1, PostDeaths, GoalInfo).
+	set__union(PostBirths0, Residue, PostBirths),
+	goal_info_set_post_births(GoalInfo0, PostBirths, GoalInfo).
 
 :- pred add_deadness_before_goal(hlds_goal, set(var), hlds_goal).
 :- mode add_deadness_before_goal(in, in, out) is det.
Index: code_info.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/code_info.m,v
retrieving revision 1.207
retrieving revision 1.208
diff -u -u -r1.207 -r1.208
--- code_info.m	1997/07/27 14:59:57	1.207
+++ code_info.m	1997/08/23 20:33:07	1.208
@@ -752,11 +752,12 @@
 	;
 		{ MaybeFollowVars = no }
 	),
-	{ goal_info_get_pre_births(GoalInfo, PreBirths) },
+	% note: we must be careful to apply deaths before births
 	{ goal_info_get_pre_deaths(GoalInfo, PreDeaths) },
-	code_info__add_forward_live_vars(PreBirths),
 	code_info__rem_forward_live_vars(PreDeaths),
 	code_info__make_vars_forward_dead(PreDeaths),
+	{ goal_info_get_pre_births(GoalInfo, PreBirths) },
+	code_info__add_forward_live_vars(PreBirths),
 	( { Atomic = yes } ->
 		{ goal_info_get_post_deaths(GoalInfo, PostDeaths) },
 		code_info__rem_forward_live_vars(PostDeaths)
@@ -767,11 +768,12 @@
 	% Update the code info structure to be consistent
 	% immediately after generating a goal
 code_info__post_goal_update(GoalInfo) -->
-	{ goal_info_get_post_births(GoalInfo, PostBirths) },
+	% note: we must be careful to apply deaths before births
 	{ goal_info_get_post_deaths(GoalInfo, PostDeaths) },
-	code_info__add_forward_live_vars(PostBirths),
 	code_info__rem_forward_live_vars(PostDeaths),
 	code_info__make_vars_forward_dead(PostDeaths),
+	{ goal_info_get_post_births(GoalInfo, PostBirths) },
+	code_info__add_forward_live_vars(PostBirths),
 	code_info__make_vars_forward_live(PostBirths),
 	{ goal_info_get_instmap_delta(GoalInfo, InstMapDelta) },
 	code_info__apply_instmap_delta(InstMapDelta).
@@ -2090,7 +2092,8 @@
 	code_info__get_stack_slots(StackSlots),
 	code_info__get_exprn_info(Exprn0),
 	{ set__to_sorted_list(Vars, VarList) },
-	{ code_info__make_vars_forward_live_2(VarList, StackSlots, 1, Exprn0, Exprn) },
+	{ code_info__make_vars_forward_live_2(VarList, StackSlots, 1,
+		Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
 :- pred code_info__make_vars_forward_live_2(list(var), stack_slots, int,
Index: live_vars.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/live_vars.m,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -u -r1.65 -r1.66
--- live_vars.m	1997/07/27 15:00:46	1.65
+++ live_vars.m	1997/08/23 20:33:12	1.66
@@ -69,10 +69,11 @@
 
 build_live_sets_in_goal(Goal0 - GoalInfo, Liveness0, ResumeVars0, LiveSets0,
 		ModuleInfo, ProcInfo, Liveness, ResumeVars, LiveSets) :-
-	goal_info_get_pre_births(GoalInfo, PreBirths),
+	% note: we must be careful to apply deaths before births
 	goal_info_get_pre_deaths(GoalInfo, PreDeaths),
-	goal_info_get_post_births(GoalInfo, PostBirths),
+	goal_info_get_pre_births(GoalInfo, PreBirths),
 	goal_info_get_post_deaths(GoalInfo, PostDeaths),
+	goal_info_get_post_births(GoalInfo, PostBirths),
 
 	set__difference(Liveness0, PreDeaths, Liveness1),
 	set__union(Liveness1, PreBirths, Liveness2),
Index: store_alloc.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/store_alloc.m,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -u -r1.53 -r1.54
--- store_alloc.m	1997/07/27 15:01:40	1.53
+++ store_alloc.m	1997/08/23 20:33:14	1.54
@@ -73,10 +73,11 @@
 
 store_alloc_in_goal(Goal0 - GoalInfo0, Liveness0, ResumeVars0, ModuleInfo,
 		Goal - GoalInfo0, Liveness) :-
-	goal_info_get_pre_births(GoalInfo0, PreBirths),
+	% note: we must be careful to apply deaths before births
 	goal_info_get_pre_deaths(GoalInfo0, PreDeaths),
-	goal_info_get_post_births(GoalInfo0, PostBirths),
+	goal_info_get_pre_births(GoalInfo0, PreBirths),
 	goal_info_get_post_deaths(GoalInfo0, PostDeaths),
+	goal_info_get_post_births(GoalInfo0, PostBirths),
 
 	set__difference(Liveness0,  PreDeaths, Liveness1),
 	set__union(Liveness1, PreBirths, Liveness2),
Index: hlds_goal.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_goal.m,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -u -r1.38 -r1.39
--- hlds_goal.m	1997/07/27 15:00:28	1.38
+++ hlds_goal.m	1997/08/23 20:33:23	1.39
@@ -478,7 +478,11 @@
 
 % Instead of recording the liveness of every variable at every
 % part of the goal, we just keep track of the initial liveness
-% and the changes in liveness.
+% and the changes in liveness.  Note that when traversing forwards
+% through a goal, deaths must be applied before births;
+% this is necessary to handle certain circumstances where a
+% variable can occur in both the post-death and post-birth sets,
+% or in both the pre-death and pre-birth sets.
 
 :- pred goal_info_get_pre_births(hlds_goal_info, set(var)).
 :- mode goal_info_get_pre_births(in, out) is det.
Index: hlds_out.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_out.m,v
retrieving revision 1.170
retrieving revision 1.171
diff -u -u -r1.170 -r1.171
--- hlds_out.m	1997/08/22 13:55:01	1.170
+++ hlds_out.m	1997/08/23 20:33:31	1.171
@@ -660,23 +660,23 @@
 		[]
 	),
 	( { string__contains_char(Verbose, 'p') } ->
-		{ goal_info_get_pre_births(GoalInfo, PreBirths) },
-		{ set__to_sorted_list(PreBirths, PreBirthList) },
-		( { PreBirthList \= [] } ->
+		{ goal_info_get_pre_deaths(GoalInfo, PreDeaths) },
+		{ set__to_sorted_list(PreDeaths, PreDeathList) },
+		( { PreDeathList \= [] } ->
 			hlds_out__write_indent(Indent),
-			io__write_string("% pre-births: "),
-			mercury_output_vars(PreBirthList, VarSet,
+			io__write_string("% pre-deaths: "),
+			mercury_output_vars(PreDeathList, VarSet,
 				AppendVarnums),
 			io__write_string("\n")
 		;
 			[]
 		),
-		{ goal_info_get_pre_deaths(GoalInfo, PreDeaths) },
-		{ set__to_sorted_list(PreDeaths, PreDeathList) },
-		( { PreDeathList \= [] } ->
+		{ goal_info_get_pre_births(GoalInfo, PreBirths) },
+		{ set__to_sorted_list(PreBirths, PreBirthList) },
+		( { PreBirthList \= [] } ->
 			hlds_out__write_indent(Indent),
-			io__write_string("% pre-deaths: "),
-			mercury_output_vars(PreDeathList, VarSet,
+			io__write_string("% pre-births: "),
+			mercury_output_vars(PreBirthList, VarSet,
 				AppendVarnums),
 			io__write_string("\n")
 		;
@@ -731,23 +731,23 @@
 		[]
 	),
 	( { string__contains_char(Verbose, 'p') } ->
-		{ goal_info_get_post_births(GoalInfo, PostBirths) },
-		{ set__to_sorted_list(PostBirths, PostBirthList) },
-		( { PostBirthList \= [] } ->
+		{ goal_info_get_post_deaths(GoalInfo, PostDeaths) },
+		{ set__to_sorted_list(PostDeaths, PostDeathList) },
+		( { PostDeathList \= [] } ->
 			hlds_out__write_indent(Indent),
-			io__write_string("% post-births: "),
-			mercury_output_vars(PostBirthList, VarSet,
+			io__write_string("% post-deaths: "),
+			mercury_output_vars(PostDeathList, VarSet,
 				AppendVarnums),
 			io__write_string("\n")
 		;
 			[]
 		),
-		{ goal_info_get_post_deaths(GoalInfo, PostDeaths) },
-		{ set__to_sorted_list(PostDeaths, PostDeathList) },
-		( { PostDeathList \= [] } ->
+		{ goal_info_get_post_births(GoalInfo, PostBirths) },
+		{ set__to_sorted_list(PostBirths, PostBirthList) },
+		( { PostBirthList \= [] } ->
 			hlds_out__write_indent(Indent),
-			io__write_string("% post-deaths: "),
-			mercury_output_vars(PostDeathList, VarSet,
+			io__write_string("% post-births: "),
+			mercury_output_vars(PostBirthList, VarSet,
 				AppendVarnums),
 			io__write_string("\n")
 		;

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list