[m-dev.] cannot_fail deconstruct -vs- goal_info determinism

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Jan 23 12:45:36 AEDT 2001


On 22-Jan-2001, Peter Ross <peter.ross at miscrit.be> wrote:
> On Mon, Jan 22, 2001 at 08:42:43PM +1100, Fergus Henderson wrote:
> > I've analyzed the bug that caused an internal compiler error when
> > extras/trailed_update/var.m was compiled with `-O4 --high-level-code'.
> > 
> > Deforestation was performance some optimizations, and then rerunning
> > mode analysis, but not rerunning determinims analysis.  One of the
> > deconstruction unifications was originally marked by mode analysis as
> > `can_fail' and hence by determinism analysis as `semidet'.  When mode
> > analysis was rerun by deforestation, the more precise insts lead to
> > the unification being marked as `cannot_fail'.  However, determinism
> > analysis was not rerun, so the determinism in the goal_info was still
> > `semidet'.  ml_unify_gen.m was checking that the `can_fail' field in
> > deconstruct unifications matched the determinism on the goal_info,
> > and this check failed, leading to the call to error/1.
> > 
> > It would be easy to modify ml_unify_gen.m so that it doesn't make that
> > assumption.  However, I'm not sure if that is the right solution.
> > There's three possible solutions, and I'm not sure which is best:
> > 
> > 	- Document this invariant in hlds_goal.m, as an invariant that
> > 	  must hold at all stages after determinism analysis, and modify
> > 	  deforestation to preserve the invariant (e.g. by rerunning
> > 	  determinism analysis after it reruns mode analysis).
> > 
> > 	- Document this invariant in hlds_goal.m, as an invariant that
> > 	  must hold when generating code, and add code in simplify.m to
> > 	  ensure that the invariant holds.  (This would match what we do
> > 	  for the invariant that the determinism match the instmap_delta
> > 	  with regard to at_most_zero_solns/unreachable.)
> > 
> > 	- Modify ml_unify_gen.m so that it doesn't depend on this
> > 	  invariant, but instead allows the determinism in the
> > 	  goal_info to be any conservative approximation.
> > 
> > Any suggestions as to which of these we should adopt?
>
> I suggest the second option.

A rationale would help a lot.

After thinking about it a bit, I'm inclined to go with the last
solution.  The first option is fragile, since there might well be
other passes of the compiler that produce code which doesn't meet that
invariant.  As for the choice between the second and third, handling
it in ml_unify_gen.m is easier, I think.

So I plan to commit the following diff
(on both the main and release branches).

----------

Estimated hours taken: 3

Fix a bug that broke extras/trailed_update/samples/vqueens.m
when compiled with `-H -O4'.

compiler/ml_code_gen.m:
	Export ml_gen_wrap_goal, for use by ml_unify_gen.m.

compiler/ml_unify_gen.m:
	Handle deconstruct unifications where the goal_info determinism
	doesn't match the can_fail field of the deconstruct by calling
	ml_gen_wrap_goal, rather than aborting.

Workspace: /home/hg/fjh/mercury
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.73
diff -u -d -r1.73 ml_code_gen.m
--- compiler/ml_code_gen.m	2001/01/17 17:37:15	1.73
+++ compiler/ml_code_gen.m	2001/01/22 09:23:07
@@ -741,6 +741,21 @@
 			ml_gen_info, ml_gen_info).
 :- mode ml_gen_goal(in, in, out, out, in, out) is det.
 
+	% ml_gen_wrap_goal(OuterCodeModel, InnerCodeModel, Context,
+	%		MLDS_Statements0, MLDS_Statements):
+	%
+	%	OuterCodeModel is the code model expected by the
+	%	context in which a goal is called. InnerCodeModel
+	%	is the code model which the goal actually has.
+	%	This predicate converts the code generated for
+	%	the goal using InnerCodeModel into code that uses
+	%	the calling convention appropriate for OuterCodeModel.
+	%
+:- pred ml_gen_wrap_goal(code_model, code_model, prog_context,
+		mlds__statements, mlds__statements,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_wrap_goal(in, in, in, in, out, in, out) is det.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -1428,12 +1443,8 @@
 	%	This predicate converts the code generated for
 	%	the goal using InnerCodeModel into code that uses
 	%	the calling convention appropriate for OuterCodeModel.
-	%
-:- pred ml_gen_wrap_goal(code_model, code_model, prog_context,
-		mlds__statements, mlds__statements,
-		ml_gen_info, ml_gen_info).
-:- mode ml_gen_wrap_goal(in, in, in, in, out, in, out) is det.
 
+	%
 	% If the inner and outer code models are equal,
 	% we don't need to do anything special.
 
Index: compiler/ml_unify_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_unify_gen.m,v
retrieving revision 1.26
diff -u -d -r1.26 ml_unify_gen.m
--- compiler/ml_unify_gen.m	2000/12/14 11:48:42	1.26
+++ compiler/ml_unify_gen.m	2001/01/22 09:21:47
@@ -145,14 +145,12 @@
 		CodeModel, Context, MLDS_Decls, MLDS_Statements) -->
 	(
 		{ CanFail = can_fail },
-		{ require(unify(CodeModel, model_semi),
-			"ml_code_gen: can_fail deconstruct not semidet") },
+		{ ExpectedCodeModel = model_semi },
 		ml_gen_semi_deconstruct(Var, ConsId, Args, ArgModes, Context,
 			MLDS_Decls, MLDS_Unif_Statements)
 	;
 		{ CanFail = cannot_fail },
-		{ require(unify(CodeModel, model_det),
-			"ml_code_gen: cannot_fail deconstruct not det") },
+		{ ExpectedCodeModel = model_det },
 		ml_gen_det_deconstruct(Var, ConsId, Args, ArgModes, Context,
 			MLDS_Decls, MLDS_Unif_Statements)
 	),
@@ -171,8 +169,17 @@
 		{ CanCGC = no },
 		{ MLDS_CGC_Statements = [] }
 	),
-	{ MLDS_Statements = MLDS_Unif_Statements `list__append`
-			MLDS_CGC_Statements }.
+	{ MLDS_Statements0 = MLDS_Unif_Statements `list__append`
+			MLDS_CGC_Statements },
+	%
+	% We used to require that CodeModel = ExpectedCodeModel.
+	% But the determinism field in the goal_info is allowed to
+	% be a conservative approximation, so we need to handle
+	% the case were CodeModel is less precise than
+	% ExpectedCodeModel.
+	%
+	ml_gen_wrap_goal(CodeModel, ExpectedCodeModel, Context,
+		MLDS_Statements0, MLDS_Statements).
 
 ml_gen_unification(complicated_unify(_, _, _), _, _, [], []) -->
 	% simplify.m should convert these into procedure calls
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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