diff: liveness bug fix
Zoltan Somogyi
zs at cs.mu.oz.au
Thu Oct 16 14:27:17 AEST 1997
Estimated hours taken: 4
compiler/liveness.m:
Recompute nonlocal sets before starting liveness computations
in order to avoid a compiler abort. The new version could in
some cases also lead to the generation of better code through
saving fewer variables across disjuncts.
tests/valid/liveness_nonlocals.m:
Test case to exercise the fix.
tests/valid/Mmakefile:
Enable the new test case.
Zoltan.
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.81
diff -u -r1.81 liveness.m
--- liveness.m 1997/09/01 14:03:04 1.81
+++ liveness.m 1997/10/14 10:50:34
@@ -52,11 +52,13 @@
% code at that resume point as well as the nature of the required
% entry labels.
%
-% Accurate Garbage Collection Notes:
+% Accurate garbage collection notes:
%
-% Note that when using accurate gc, liveness is computed slightly
-% differently. The garbage collector needs access to the typeinfo
-% variables of any variable that could be garbage collected.
+% When using accurate gc, liveness is computed slightly differently.
+% The garbage collector needs access to the typeinfo variables of any
+% variable that could be live at a garbage collection point. In the
+% present design of the garbage collector, garbage collection takes place
+% at procedure returns.
%
% Hence, the invariant needed for accurate GC is:
% a variable holding a typeinfo must be live at any continuation
@@ -75,6 +77,7 @@
%
% A typeinfo variable becomes dead after both the following conditions
% are true:
+%
% (1) The typeinfo variable is not used again (when it is no
% longer part of the nonlocals)
% (2) No other nonlocal variable's type is described by that typeinfo
@@ -91,6 +94,30 @@
% die only when no other variable needing them will be live, so the
% invariant holds.
%
+% Quantification notes:
+%
+% If a variable is not live on entry to a goal, but the goal gives it a value,
+% the code of this module assumes that
+%
+% (a) any parallel goals also give it a value, or
+% (b) the variable is local to this goal and hence does not occur in parallel
+% goals.
+%
+% If a variable occurs in the nonlocal set of the goal, the code of this
+% assumes that (b) is not true, and will therefore require (a) to be true.
+% If some of the parallel goals cannot succeed, the first pass will include
+% the variable in their post-birth sets.
+%
+% If a variable occurs in the nonlocal set of the goal, but is actually
+% local to the goal, then any occurrence of that variable in the postbirth
+% sets of parallel goals will lead to an inconsistency, because the variable
+% will not die on those parallel paths, but will die on the path that
+% actually gives a value to the variable.
+%
+% The nonlocal set of a goal is in general allowed to overapproximate the
+% true set of nonlocal variables of the goal. Since this module requires
+% *exact* information about nonlocals, it must recompute the nonlocal sets
+% before starting.
%-----------------------------------------------------------------------------%
@@ -118,30 +145,39 @@
:- implementation.
:- import_module hlds_goal, hlds_data, llds, quantification, (inst), instmap.
-:- import_module hlds_out, mode_util, code_util.
+:- import_module hlds_out, mode_util, code_util, quantification.
:- import_module prog_data, globals, passes_aux.
:- import_module bool, list, map, set, std_util, term, assoc_list, require.
:- import_module varset, string.
detect_liveness_proc(ProcInfo0, ModuleInfo, ProcInfo) :-
proc_info_goal(ProcInfo0, Goal0),
- proc_info_variables(ProcInfo0, Varset),
- proc_info_vartypes(ProcInfo0, VarTypes),
- live_info_init(ModuleInfo, ProcInfo0, VarTypes, Varset, LiveInfo),
-
- initial_liveness(ProcInfo0, ModuleInfo, Liveness0),
- detect_liveness_in_goal(Goal0, Liveness0, LiveInfo,
- _, Goal1),
+ proc_info_variables(ProcInfo0, Varset0),
+ proc_info_vartypes(ProcInfo0, VarTypes0),
+ proc_info_headvars(ProcInfo0, HeadVars),
+
+ % recompute the nonlocal sets
+ implicitly_quantify_clause_body(HeadVars, Goal0, Varset0,
+ VarTypes0, Goal1, Varset, VarTypes, _Warnings),
+
+ proc_info_set_variables(ProcInfo0, Varset, ProcInfo1),
+ proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
+
+ live_info_init(ModuleInfo, ProcInfo2, VarTypes, Varset, LiveInfo),
+
+ initial_liveness(ProcInfo2, ModuleInfo, Liveness0),
+ detect_liveness_in_goal(Goal1, Liveness0, LiveInfo,
+ _, Goal2),
- initial_deadness(ProcInfo0, ModuleInfo, Deadness0),
- detect_deadness_in_goal(Goal1, Deadness0, LiveInfo, _, Goal2),
+ initial_deadness(ProcInfo2, ModuleInfo, Deadness0),
+ detect_deadness_in_goal(Goal2, Deadness0, LiveInfo, _, Goal3),
set__init(ResumeVars0),
- detect_resume_points_in_goal(Goal2, Liveness0, LiveInfo,
+ detect_resume_points_in_goal(Goal3, Liveness0, LiveInfo,
ResumeVars0, Goal, _),
- proc_info_set_goal(ProcInfo0, Goal, ProcInfo1),
- proc_info_set_liveness_info(ProcInfo1, Liveness0, ProcInfo).
+ proc_info_set_goal(ProcInfo2, Goal, ProcInfo3),
+ proc_info_set_liveness_info(ProcInfo3, Liveness0, ProcInfo).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.1
diff -u -r1.1 Mmakefile
--- Mmakefile 1997/09/29 18:05:22 1.1
+++ Mmakefile 1997/10/14 10:53:13
@@ -49,6 +49,7 @@
lambda_switch.m \
lambda_type.m \
lazy_list.m \
+ liveness_nonlocals.m \
livevals_seq.m \
loop.m \
loop_in_disj.m \
New File: tests/valid/liveness_nonlocals.m
===================================================================
% This is a regression test. Some versions of the compiler abort on this code.
% The bug that this test case tests for is described by this comment from
% liveness.m:
% If a variable is not live on entry to a goal, but the goal gives it a value,
% the code of this module assumes that
%
% (a) any parallel goals also give it a value, or
% (b) the variable is local to this goal and hence does not occur in parallel
% goals.
%
% If a variable occurs in the nonlocal set of the goal, the code of this
% assumes that (b) is not true, and will therefore require (a) to be true.
% If some of the parallel goals cannot succeed, the first pass will include
% the variable in their post-birth sets.
%
% If a variable occurs in the nonlocal set of the goal, but is actually
% local to the goal, then any occurrence of that variable in the postbirth
% sets of parallel goals will lead to an inconsistency, because the variable
% will not die on those parallel paths, but will die on the path that
% actually gives a value to the variable.
:- module liveness_nonlocals.
:- interface.
:- import_module bool.
:- pred foo(T, bool).
:- mode foo(in, in(bound(yes))) is failure.
:- implementation.
:- import_module list, require, string.
foo(Foo, IsFoo) :-
foo_int(Foo, Int),
int_to_bool(Int, IsFoo).
:- pred foo_int(T, int).
:- mode foo_int(in, out(bound(0))) is det.
:- pragma c_code(foo_int(_V2::in, Res::out(bound(0))),
will_not_call_mercury, "Res = 0").
:- pred int_to_bool(int, bool).
:- mode int_to_bool(in(bound(1)), out(bound(yes))) is det.
:- mode int_to_bool(in(bound(0)), out(bound(no))) is det.
int_to_bool(1, yes).
int_to_bool(0, no).
More information about the developers
mailing list