[m-rev.] for review: fix MLDS tail recursion bug
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Jan 31 23:13:28 AEDT 2002
Estimated hours taken: 2
Fix a bug where we weren't getting proper tail recursion optimization in
the MLDS->C back-end for procedures with output arguments and determinism
`erroneous'.
compiler/ml_call_gen.m:
Mark calls with determinism `erroneous' or `failure' as tail calls.
compiler/ml_code_gen.m:
Pass the determinism (instead of the code_model) to ml_call_gen.m.
compiler/ml_tailcall.m:
Add a comment.
tests/hard_coded/exceptions/Mmakefile:
tests/hard_coded/exceptions/looptest.m:
tests/hard_coded/exceptions/looptest.exp:
Add a regression test.
Workspace: /home/earth/fjh/ws-earth4/mercury
Index: compiler/ml_call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_call_gen.m,v
retrieving revision 1.28
diff -u -d -r1.28 ml_call_gen.m
--- compiler/ml_call_gen.m 30 Jan 2002 12:46:58 -0000 1.28
+++ compiler/ml_call_gen.m 31 Jan 2002 11:44:51 -0000
@@ -26,7 +26,7 @@
% Generate MLDS code for an HLDS generic_call goal.
% This includes boxing/unboxing the arguments if necessary.
:- pred ml_gen_generic_call(generic_call, list(prog_var), list(mode),
- code_model, prog_context, mlds__defns, mlds__statements,
+ determinism, prog_context, mlds__defns, mlds__statements,
ml_gen_info, ml_gen_info).
:- mode ml_gen_generic_call(in, in, in, in, in, out, out, in, out) is det.
@@ -97,7 +97,7 @@
:- implementation.
-:- import_module hlds_module.
+:- import_module hlds_module, hlds_data.
:- import_module builtin_ops.
:- import_module type_util, mode_util, error_util.
:- import_module options, globals.
@@ -116,7 +116,7 @@
% XXX For typeclass method calls, we do some unnecessary
% boxing/unboxing of the arguments.
%
-ml_gen_generic_call(GenericCall, ArgVars, ArgModes, CodeModel, Context,
+ml_gen_generic_call(GenericCall, ArgVars, ArgModes, Determinism, Context,
MLDS_Decls, MLDS_Statements) -->
%
% allocate some fresh type variables to use as the Mercury types
@@ -136,6 +136,7 @@
{ ml_gen_info_get_varset(MLDSGenInfo, VarSet) },
{ ArgNames = ml_gen_var_names(VarSet, ArgVars) },
{ PredOrFunc = generic_call_pred_or_func(GenericCall) },
+ { determinism_to_code_model(Determinism, CodeModel) },
{ Params0 = ml_gen_params(ModuleInfo, ArgNames,
BoxedArgTypes, ArgModes, PredOrFunc, CodeModel) },
@@ -243,7 +244,7 @@
{ ObjectRval = no },
{ DoGenCall = ml_gen_mlds_call(Signature, ObjectRval, FuncVarRval,
[ClosureRval | InputRvals], OutputLvals, OutputTypes,
- CodeModel, Context) },
+ Determinism, Context) },
( { ConvArgDecls = [], ConvOutputStatements = [] } ->
DoGenCall(MLDS_Decls0, MLDS_Statements0)
@@ -352,8 +353,9 @@
% to generate it.)
%
{ ObjectRval = no },
+ { proc_info_interface_determinism(ProcInfo, Detism) },
{ DoGenCall = ml_gen_mlds_call(Signature, ObjectRval, FuncRval,
- InputRvals, OutputLvals, OutputTypes, CodeModel, Context) },
+ InputRvals, OutputLvals, OutputTypes, Detism, Context) },
( { ConvArgDecls = [], ConvOutputStatements = [] } ->
DoGenCall(MLDS_Decls, MLDS_Statements)
@@ -392,16 +394,17 @@
%
:- pred ml_gen_mlds_call(mlds__func_signature, maybe(mlds__rval), mlds__rval,
list(mlds__rval), list(mlds__lval), list(mlds__type),
- code_model, prog_context, mlds__defns, mlds__statements,
+ determinism, prog_context, mlds__defns, mlds__statements,
ml_gen_info, ml_gen_info).
:- mode ml_gen_mlds_call(in, in, in, in, in, in, in, in, out, out, in, out)
is det.
ml_gen_mlds_call(Signature, ObjectRval, FuncRval, ArgRvals0, RetLvals0,
- RetTypes0, CodeModel, Context, MLDS_Decls, MLDS_Statements) -->
+ RetTypes0, Detism, Context, MLDS_Decls, MLDS_Statements) -->
%
% append the extra arguments or return val for this code_model
%
+ { determinism_to_code_model(Detism, CodeModel) },
(
{ CodeModel = model_non },
% create a new success continuation, if necessary
@@ -444,7 +447,14 @@
%
% build the MLDS call statement
%
- { CallOrTailcall = call },
+ % if the called procedure has determinism `erroneous' or `failure',
+ % then it's always safe to make this call a tail call.
+ { determinism_components(Detism, _, NumSolns) },
+ { NumSolns = at_most_zero ->
+ CallOrTailcall = tail_call
+ ;
+ CallOrTailcall = call
+ },
{ MLDS_Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals,
CallOrTailcall) },
{ MLDS_Statement = mlds__statement(MLDS_Stmt,
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.107
diff -u -d -r1.107 ml_code_gen.m
--- compiler/ml_code_gen.m 16 Jan 2002 01:13:30 -0000 1.107
+++ compiler/ml_code_gen.m 31 Jan 2002 08:38:50 -0000
@@ -2012,7 +2012,7 @@
{ determinism_to_code_model(Detism, CallCodeModel) },
{ require(unify(CodeModel, CallCodeModel),
"ml_gen_generic_call: code model mismatch") },
- ml_gen_generic_call(GenericCall, Vars, Modes, CodeModel, Context,
+ ml_gen_generic_call(GenericCall, Vars, Modes, Detism, Context,
MLDS_Decls, MLDS_Statements).
ml_gen_goal_expr(call(PredId, ProcId, ArgVars, BuiltinState, _, PredName),
Index: compiler/ml_tailcall.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_tailcall.m,v
retrieving revision 1.12
diff -u -d -r1.12 ml_tailcall.m
--- compiler/ml_tailcall.m 11 Jan 2002 07:41:25 -0000 1.12
+++ compiler/ml_tailcall.m 31 Jan 2002 08:46:54 -0000
@@ -43,6 +43,9 @@
% optimization (turn self-tailcalls into loops) is done in ml_optimize.
% Individual backends may wish to treat tailcalls separately if there is
% any backend support for them.
+%
+% Note that ml_call_gen.m will also mark calls to procedures with determinism
+% `erroneous' or `failure' as tail calls when it generates them.
%-----------------------------------------------------------------------------%
Index: tests/hard_coded/exceptions/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/exceptions/Mmakefile,v
retrieving revision 1.8
diff -u -d -r1.8 Mmakefile
--- tests/hard_coded/exceptions/Mmakefile 31 May 2001 06:00:23 -0000 1.8
+++ tests/hard_coded/exceptions/Mmakefile 31 Jan 2002 12:10:27 -0000
@@ -21,8 +21,12 @@
#
# XXX the following tests are not enabled because we do not pass them yet:
+# looptest.m
+# (fails in debugging grades, because debugging breaks
+# tail recursion optimization)
# test_memo.m test_loop_check.m
-# (those two tests test the combination of tabling and exceptions).
+# (those two tests test the combination of
+# tabling and exceptions).
#
# Also currently the compiler has a bug where it generates
# static ground terms even for things with `di' modes;
@@ -44,6 +48,8 @@
check: $(PROGS:.m=.res)
#-----------------------------------------------------------------------------#
+
+MCFLAGS-looptest = --infer-all
# test_uncaught_exception is *supposed* to return an error exit status.
# We also need to pipe the output through sed to avoid hard-coding
Index: tests/hard_coded/exceptions/looptest.exp
===================================================================
RCS file: tests/hard_coded/exceptions/looptest.exp
diff -N tests/hard_coded/exceptions/looptest.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/exceptions/looptest.exp 31 Jan 2002 11:52:33 -0000
@@ -0,0 +1 @@
+exception(univ_cons("finished"))
Index: tests/hard_coded/exceptions/looptest.m
===================================================================
RCS file: tests/hard_coded/exceptions/looptest.m
diff -N tests/hard_coded/exceptions/looptest.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/exceptions/looptest.m 31 Jan 2002 12:01:50 -0000
@@ -0,0 +1,33 @@
+% This module is a regression test;
+% it tests that we do correct tail recursion optimization
+% for procedures with output arguments and determinism
+% of `erroneous' or `failure', such as loop//1 below.
+
+% This test is designed so that if the compiler doesn't
+% do tail recursion optimization, then the program will
+% overflow the limit on stack size.
+
+:- module looptest.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is cc_multi.
+
+:- implementation.
+:- import_module int, string, exception.
+
+main -->
+ { try(do_loop, R) },
+ io__print(R), nl.
+
+:- mode do_loop(out) is det.
+do_loop(X) :-
+ loop(100000000, 42, X).
+
+loop(N) -->
+ ( { N = 0 } ->
+ { throw("finished") }
+ ;
+ loop(N - 1)
+ ).
+
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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