[m-rev.] for review: --trace shallow variable liveness problem (2)
Peter Wang
novalazy at gmail.com
Wed Oct 28 15:45:54 AEDT 2009
Branches: main
Revert a change committed on 2009-08-21 to prevent a compiler abort when using
--trace shallow on a test case. The change caused aborts with other modules.
Fix the original bug a different way, and another bug with --trace shallow.
compiler/live_vars.m:
Revert the old change.
Add a check that variables needed across a call do not appear in the
post-death set of that call.
Only add typeinfo variables to the set of variables needed across a
call for output variable which are not local to the call. Otherwise
the sanity check fails on livevars_shallow2.m.
compiler/liveness.m:
A switch variable which needs to be added to the pre-death set of a
case may require typeinfo variables which describe the type of that
variable to be added to the pre-death set as well. This fixes the
problem with livevars_shallow.m.
tests/valid/livevars_shallow.m:
Replace this test case by another derived from the same original file.
tests/valid/Mercury.options:
tests/valid/Mmakefile:
tests/valid/livevars_shallow2.m:
Add test case.
diff --git a/compiler/live_vars.m b/compiler/live_vars.m
index 6e5edeb..fb8e2cb 100644
--- a/compiler/live_vars.m
+++ b/compiler/live_vars.m
@@ -475,30 +475,36 @@ build_live_sets_in_call(OutVars, GoalInfo0, GoalInfo, ResumeVars0, AllocData,
set.difference(Liveness, OutVars, ForwardVars0),
% Might need to add more live variables with typeinfo liveness
- % calculation.
+ % calculation. We only add the typeinfo variables for nonlocal outputs.
+ NonLocals = goal_info_get_nonlocals(GoalInfo0),
+ set.intersect(OutVars, NonLocals, NonLocalOutVars),
maybe_add_typeinfo_liveness(AllocData ^ ad_proc_info,
- AllocData ^ ad_typeinfo_liveness, OutVars, ForwardVars0, ForwardVars),
+ AllocData ^ ad_typeinfo_liveness, NonLocalOutVars,
+ ForwardVars0, ForwardVars),
+
+ % Sanity check.
+ goal_info_get_post_deaths(GoalInfo0, PostDeaths0),
+ set.intersect(PostDeaths0, ForwardVars, Intersect),
+ ( set.empty(Intersect) ->
+ true
+ ;
+ unexpected(this_file,
+ "build_live_sets_in_call: ForwardVars intersects post-death set")
+ ),
Detism = goal_info_get_determinism(GoalInfo0),
(
Detism = detism_erroneous,
AllocData ^ ad_opt_no_return_calls = yes
->
- NeedAcrossCall = need_across_call(set.init, set.init, set.init),
- GoalInfo1 = GoalInfo0
+ NeedAcrossCall = need_across_call(set.init, set.init, set.init)
;
NeedAcrossCall = need_across_call(ForwardVars, ResumeVars0,
- !.NondetLiveness),
- % Make sure a variable doesn't appear in both the forward vars and
- % post-death set. (Perhaps the same thing needs to be done for
- % other need_across_call sets?)
- goal_info_get_post_deaths(GoalInfo0, PostDeaths0),
- set.difference(PostDeaths0, ForwardVars, PostDeaths1),
- goal_info_set_post_deaths(PostDeaths1, GoalInfo0, GoalInfo1)
+ !.NondetLiveness)
),
- record_call_site(NeedAcrossCall, GoalInfo1, GoalInfo, !StackAlloc),
+ record_call_site(NeedAcrossCall, GoalInfo0, GoalInfo, !StackAlloc),
% If this is a nondet call, then all the stack slots we need
% must be protected against reuse in following code.
diff --git a/compiler/liveness.m b/compiler/liveness.m
index a62f656..37352c1 100644
--- a/compiler/liveness.m
+++ b/compiler/liveness.m
@@ -865,10 +865,12 @@ detect_deadness_in_disj([Goal0 | Goals0], [Goal | Goals], Deadness0, Liveness0,
set(prog_var)::in, set(prog_var)::out, set(prog_var)::out) is det.
detect_deadness_in_cases(SwitchVar, [], [], _Deadness0, _Liveness,
- CompletedNonLocals, _LiveInfo, !Union, CompletedNonLocalUnion) :-
- % If the switch variable does not become dead in a case,
- % it must be put in the pre-death set of that case.
- set.insert(!.Union, SwitchVar, !:Union),
+ CompletedNonLocals, LiveInfo, !Union, CompletedNonLocalUnion) :-
+ % If the switch variable does not become dead in a case, it must be put in
+ % the pre-death set of that case.
+ maybe_complete_with_typeinfos(LiveInfo, set.make_singleton_set(SwitchVar),
+ CompletedSwitchVar),
+ set.union(CompletedSwitchVar, !Union),
set.intersect(!.Union, CompletedNonLocals, CompletedNonLocalUnion).
detect_deadness_in_cases(SwitchVar, [Case0 | Cases0], [Case | Cases],
Deadness0, Liveness0, CompletedNonLocals, LiveInfo, !Union,
diff --git a/tests/valid/Mercury.options b/tests/valid/Mercury.options
index ab37092..7e87400 100644
--- a/tests/valid/Mercury.options
+++ b/tests/valid/Mercury.options
@@ -97,6 +97,7 @@ MCFLAGS-intermod_user_sharing_2 = --intermodule-optimization
MCFLAGS-lambda_inference = --infer-all
MCFLAGS-livevals_seq = -O5 --opt-space
MCFLAGS-livevars_shallow = --grade none --trace shallow
+MCFLAGS-livevars_shallow2 = --grade none --trace shallow
MCFLAGS-lco_term = --optimize-constructor-last-call
MCFLAGS-loop_inv_bug = --common-struct --loop-invariants
MCFLAGS-mc_bag = --prop-mode-constraints
diff --git a/tests/valid/Mmakefile b/tests/valid/Mmakefile
index e0107ee..111d771 100644
--- a/tests/valid/Mmakefile
+++ b/tests/valid/Mmakefile
@@ -264,6 +264,7 @@ LLDS_PROGS= \
exists_cast_bug \
fzn_debug_abort \
livevars_shallow \
+ livevars_shallow2 \
untuple_bug
# These tests only work in grades that support tabling.
diff --git a/tests/valid/livevars_shallow.m b/tests/valid/livevars_shallow.m
index e7763d4..c67d73f 100644
--- a/tests/valid/livevars_shallow.m
+++ b/tests/valid/livevars_shallow.m
@@ -10,45 +10,50 @@
:- module livevars_shallow.
:- interface.
-:- pred update({}::out) is det.
+:- import_module list.
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- implementation.
-
-:- type net(AtomicTask)
- ---> net.
+:- type node(A)
+ ---> place
+ ; task
+ .
-:- type task(AtomicTask)
- ---> task.
-
-:- type task_type(AtomicTask)
- ---> atomik
+:- type task_type(A)
+ ---> atomick
; composite.
+:- pred cancellation_set_updates(list(node(A))::in, list(string)::out) is det.
+
+%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
-update(AtomicTasks) :-
- Net = net : net(int),
- classify_nodes(Net, AtomicTasks).
+:- implementation.
+
+cancellation_set_updates(Nodes, L) :-
+ classify_nodes(Nodes, L).
-:- pred classify_nodes(net(AtomicTask)::in, {}::out) is det.
+:- pred classify_nodes(list(node(A))::in, list(string)::out) is det.
-classify_nodes(_ : net(AtomicTask), AtomicTasks) :-
- Task = task : task(AtomicTask),
- TaskType = get_task_type(Task),
+classify_nodes([], []).
+classify_nodes([Node | Nodes], L) :-
(
- TaskType = atomik,
- AtomicTasks = {}
+ Node = place,
+ classify_nodes(Nodes, L)
;
- TaskType = composite,
- AtomicTasks = {}
+ Node = task,
+ classify_nodes(Nodes, L0),
+ TaskType = get_task_type(Node),
+ (
+ TaskType = atomick,
+ L = L0
+ ;
+ TaskType = composite,
+ L = L0
+ )
).
-:- func get_task_type(task(AtomicTask)) = task_type(AtomicTask).
+:- func get_task_type(node(A)) = task_type(A).
-get_task_type(_) = atomik.
+get_task_type(_) = composite.
%-----------------------------------------------------------------------------%
% vim: set sts=4 sw=4 et:
diff --git a/tests/valid/livevars_shallow2.m b/tests/valid/livevars_shallow2.m
new file mode 100644
index 0000000..00793f4
--- /dev/null
+++ b/tests/valid/livevars_shallow2.m
@@ -0,0 +1,50 @@
+%-----------------------------------------------------------------------------%
+% Regression test.
+% The compiler aborted on this module with --trace shallow due to an incorrect
+% fix.
+%-----------------------------------------------------------------------------%
+
+:- module livevars_shallow2.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- type ps ---> ps(int).
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ P = stringify_state(int_with_state),
+ io.write(P, !IO),
+ io.nl(!IO).
+
+:- pred int_with_state(int::out, ps::in, ps::out) is semidet.
+
+int_with_state(1, !PS) :-
+ semidet_true.
+
+:- pred stringify_state(
+ pred(T, ps, ps)::
+ in(pred(out, in, out) is semidet),
+ string::out,
+ ps::in,
+ ps::out)
+ is semidet.
+
+stringify_state(P, String, !PS) :-
+ P(_, !PS),
+ String = xfoo(-1).
+
+:- func xfoo(T) = string.
+
+xfoo(_) = "xfoo".
+
+%-----------------------------------------------------------------------------%
+% vim: set sts=4 sw=4 et:
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list