for review: fix bug in unique mode checking
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Apr 9 04:35:27 AEST 1999
Hi,
Could someone please review this one?
--------------------
Estimated hours taken: 4
compiler/unique_modes.m:
Fix a bug reported by Serge Varennes
<serge.varennes at detexis.thomson-csf.com>:
we need to mark variables as `mostly_unique' rather
than `unique' at all disjunctions, not just at model_non
disjunctions, because model_semi and even model_det
disjunctions can still have backtracking from one failing
disjunct into the next disjunct.
Also add a couple of comments.
tests/invalid/Mmakefile:
tests/invalid/uniq_modes.m:
tests/invalid/uniq_modes.err_exp:
Add a regression test for this change.
tests/hard_coded/purity.m:
tests/hard_coded/cc_nondet_disj.m:
Fix code that the compiler now rejects, due to the above change.
The compiler is being a bit conservative to reject these cases,
because the code won't actually violate unique-mode-correctness,
but the conservatism here with disjunctions is similar to unique
mode analysis's already existing conservatism with regard to
if-then-elses, and the work-around for cases like this is easy,
so I don't consider that to be a significant problem.
The conservatism in question is that if it sees
`{ test }, io__write_string("blah")' in a model_det/model_semi
disjunct or in the condition of an if-then-else, it will report
a unique mode error, since it doesn't realize that destructive
update only occurs _after_ we have committed to this branch.
tests/hard_coded/Mmakefile:
Disable the test case bidirectional.m, since the compiler now
rejects it, due to the above change to unique_modes.m.
The compiler is again being overly conservative in its analysis.
The problem is similar to that in the two test cases above,
unfortunately there is no easy work-around in this case.
The compiler really ought to support this style of bidirectional
code using unique modes, so I do consider this to be a significant
problem, but the fix is a fair bit of work, so I will deal with
that as a separate change.
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.50
diff -u -r1.50 unique_modes.m
--- unique_modes.m 1998/11/20 04:09:38 1.50
+++ unique_modes.m 1999/04/08 16:42:07
@@ -10,6 +10,10 @@
% This module checks that variables with a unique mode (as opposed to
% a mostly-unique mode) really are unique, and not nondet live - i.e.,
% that they cannot be referenced on backtracking.
+% (Actually the term "nondet live" is a bit of a misnomer, because
+% really we are just interested in whether something can be referenced
+% on backtracking, and this can occur after backtracking in semidet
+% code too, not just in nondet code.)
% Basically we just traverse each goal, keeping track of which variables
% are nondet live. At each procedure call, we check that any arguments
@@ -19,7 +23,9 @@
% Variables can become nondet live in several places:
% in negations, in the conditions of if-then-elses,
-% and in disjunctions, and at nondet calls.
+% in disjunctions, and at nondet calls.
+% These are the only places at which we can resume execution
+% after backtracking.
% XXX we currently make the conservative assumption that
% any non-local variable in a disjunction or nondet call
@@ -245,10 +251,10 @@
unique_modes__check_goal_2(conj(List0), _GoalInfo0, conj(List)) -->
mode_checkpoint(enter, "conj"),
- mode_info_add_goals_live_vars(List0),
( { List0 = [] } -> % for efficiency, optimize common case
{ List = [] }
;
+ mode_info_add_goals_live_vars(List0),
unique_modes__check_conj(List0, List)
),
mode_checkpoint(exit, "conj").
@@ -270,21 +276,15 @@
{ instmap__init_unreachable(InstMap) },
mode_info_set_instmap(InstMap)
;
+ %
+ % Mark all the variables which are nondet-live at the
+ % start of the disjunction and whose inst is `unique'
+ % as instead being only `mostly_unique'.
+ %
{ goal_info_get_nonlocals(GoalInfo0, NonLocals) },
- { goal_info_get_code_model(GoalInfo0, CodeModel) },
- % does this disjunction create a choice point?
- ( { CodeModel = model_non } ->
- %
- % Mark all the variables which are nondet-live at the
- % start of the disjunction and whose inst is `unique'
- % as instead being only `mostly_unique'.
- %
- mode_info_add_live_vars(NonLocals),
- make_all_nondet_live_vars_mostly_uniq,
- mode_info_remove_live_vars(NonLocals)
- ;
- []
- ),
+ mode_info_add_live_vars(NonLocals),
+ make_all_nondet_live_vars_mostly_uniq,
+ mode_info_remove_live_vars(NonLocals),
%
% Now just modecheck each disjunct in turn, and then
@@ -314,6 +314,23 @@
% safe to leave it as `unique' on entry to the condition.
% The only case we need to set it to `mostly_unique' is
% if the condition would clobber it.
+ %
+ % XXX actually that is not true; the code below does
+ % the wrong thing for examples such as this one:
+ %
+ % :- mode p(di).
+ % p(Var) :-
+ % (if
+ % (if semidet_succeed then
+ % clobber(Var), fail
+ % else
+ % true
+ % )
+ % then
+ % blah
+ % else
+ % use(Var)
+ % ).
%
mode_info_add_live_vars(C_Vars),
=(ModeInfo),
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.54
diff -u -r1.54 Mmakefile
--- Mmakefile 1999/03/26 04:34:14 1.54
+++ Mmakefile 1999/04/08 17:18:29
@@ -9,7 +9,6 @@
PROGS= \
address_of_builtins \
agg \
- bidirectional \
bigtest \
boyer \
c_write_string \
@@ -94,6 +93,8 @@
# we do no pass the following tests
# var_not_found -- "sorry, not implemented" in polymorphism.m.
+# bidirectional -- unique mode analysis is overly conservative
+# and thus rejects this test case.
#-----------------------------------------------------------------------------#
Index: tests/hard_coded/cc_nondet_disj.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/cc_nondet_disj.m,v
retrieving revision 1.4
diff -u -r1.4 cc_nondet_disj.m
--- cc_nondet_disj.m 1997/05/20 02:08:16 1.4
+++ cc_nondet_disj.m 1999/04/08 17:03:01
@@ -9,7 +9,20 @@
:- import_module list.
main --> io__read_line(Res),
+ ( { Res = ok(['y'|_]), Message = "Yes\n" }
+ ; { Res = ok(['n'|_]), Message = "No\n" }
+ ; { Message = "Huh?\n" }
+ ),
+ io__write_string(Message).
+
+/***
+% This test used to be written as follows, but currently
+% the unique mode analysis is not smart enough to realize
+% that the disjuncts which update the I/O state won't
+% backtrack over I/O if the code is written like that.
+main --> io__read_line(Res),
( { Res = ok(['y'|_]) }, io__write_string("Yes\n")
; { Res = ok(['n'|_]) }, io__write_string("No\n")
; io__write_string("Huh?\n")
).
+***/
Index: tests/hard_coded/purity.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/purity.m,v
retrieving revision 1.3
diff -u -r1.3 purity.m
--- purity.m 1998/01/06 06:31:40 1.3
+++ purity.m 1999/04/08 17:03:58
@@ -80,9 +80,24 @@
test3 -->
( { impure incr_x },
{ fail }
+ ; { semipure get_x(Y) }
+ ),
+ io__format("%d\n", [i(Y)]).
+
+/***
+% This test used to be written as follows, but currently
+% the unique mode analysis is not smart enough to realize
+% that the disjuncts which update the I/O state won't
+% backtrack over I/O if the code is written like that.
+
+% tempt compiler to optimize away impure goal in branch that cannot succeed.
+test3 -->
+ ( { impure incr_x },
+ { fail }
; { semipure get_x(Y) },
io__format("%d\n", [i(Y)])
).
+***/
% regression test for problem with calls to implied modes of impure/semipure
% preds reporting spurious warnings about impurity markers in the wrong place.
@@ -118,9 +133,24 @@
test3_inline -->
( { impure incr_x_inline },
{ fail }
+ ; { semipure get_x_inline(Y) }
+ ),
+ io__format("%d\n", [i(Y)]).
+
+/***
+% This test used to be written as follows, but currently
+% the unique mode analysis is not smart enough to realize
+% that the disjuncts which update the I/O state won't
+% backtrack over I/O if the code is written like that.
+
+% tempt compiler to optimize away impure goal in branch that cannot succeed.
+test3_inline -->
+ ( { impure incr_x_inline },
+ { fail }
; { semipure get_x_inline(Y) },
io__format("%d\n", [i(Y)])
).
+***/
% regression test for problem with calls to implied modes of impure/semipure
% preds reporting spurious warnings about impurity markers in the wrong place.
Index: tests/hard_coded/uniq_modes.m
===================================================================
RCS file: uniq_modes.m
diff -N uniq_modes.m
--- /dev/null Fri Apr 9 04:28:35 1999
+++ uniq_modes.m Fri Apr 9 04:03:24 1999
@@ -0,0 +1,18 @@
+:- module uniq_modes.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state, io__state).
+:- mode main(di, uo) is det.
+
+:- implementation.
+:- import_module list,std_util.
+
+main(In, _Out) :-
+ io__write("looking for", In, Int1),
+ io__nl(Int1, _Int2),
+ fail.
+main(In, Out) :-
+ io__write("not found", In, Int),
+ io__nl(Int, Out).
+
Index: tests/hard_coded/uniq_modes.err_exp
===================================================================
RCS file: uniq_modes.err_exp
diff -N uniq_modes.err_exp
--- /dev/null Fri Apr 9 04:28:37 1999
+++ uniq_modes.err_exp Fri Apr 9 04:06:46 1999
@@ -0,0 +1,5 @@
+uniq_modes.m:012: In clause for `main(di, uo)':
+uniq_modes.m:012: in argument 2 of call to predicate `io:write/3':
+uniq_modes.m:012: mode error: variable `In' has instantiatedness `mostly_unique',
+uniq_modes.m:012: expected instantiatedness was `unique'.
+For more information, try recompiling with `-E'.
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.37
diff -u -r1.37 Mmakefile
--- Mmakefile 1999/02/12 04:19:30 1.37
+++ Mmakefile 1999/04/08 18:00:44
@@ -61,6 +61,7 @@
undef_mode.m \
undef_symbol.m \
undef_type.m \
+ uniq_modes.m \
uu_type.m \
vars_in_wrong_places.m
--
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