for review: simplify.m bug fix
Simon Taylor
stayl at cs.mu.OZ.AU
Sun Aug 30 15:58:57 AEST 1998
Hi,
Fergus, could you please review this.
Simon.
Estimated hours taken: 10
Clean up the handling of commits and goals which cannot succeed.
This fixes problems with tests/hard_coded/cut_test.m.
compiler/simplify.m:
Be more careful about using `true_goal/1' and `fail_goal/1' instead
of `conj([])' and `disj([], _)'.
When removing unnecessary disjunctions or if-then-elses around goals
be sure to wrap the goal if the inner and outer determinisms are not
equal.
Rerun determinism analysis where required.
Remove `some's where the inner and outer determinisms are the same.
compiler/mode_util.m:
Enforce the invariant that if the initial instmap is unreachable,
the instmap_delta is unreachable.
compiler/ite_gen.m:
Don't barf if the `then' part of an if-then-else is unreachable.
compiler/common.m:
Check for constructions where the assigned variable is not output.
compiler/deforest.m:
Requantify before rerunning mode analysis when inlining.
compiler/det_analysis.m:
Export predicates to run determinism analysis on a goal, not an
entire procedure.
Index: compiler/common.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/common.m,v
retrieving revision 1.50
diff -u -t -u -r1.50 common.m
--- common.m 1998/04/27 04:00:46 1.50
+++ common.m 1998/08/11 06:54:36
@@ -82,7 +82,7 @@
:- import_module quantification, mode_util, type_util, prog_util.
:- import_module det_util, det_report, globals, options, inst_match, instmap.
:- import_module hlds_module, (inst), pd_cost.
-:- import_module bool, map, set, eqvclass, require, std_util.
+:- import_module bool, map, set, eqvclass, require, std_util, string.
:- type structure ---> structure(var, type, cons_id, list(var)).
@@ -124,6 +124,12 @@
(
Unification0 = construct(Var, ConsId, ArgVars, _),
(
+ % common__generate_assign assumes that the
+ % output variable is in the instmap_delta, which
+ % will not be true if the variable is a local.
+ % The optimization is pointless in that case.
+ goal_info_get_instmap_delta(GoalInfo0, InstMapDelta),
+ instmap_delta_search_var(InstMapDelta, Var, _),
common__find_matching_cell(Var, ConsId, ArgVars,
construction, Info0, OldStruct)
->
@@ -591,8 +597,12 @@
( instmap_delta_search_var(InstMapDelta0, ToVar, ToVarInst1) ->
ToVarInst = ToVarInst1
;
- error("common__generate_assign: assigned var \
- not in instmap_delta")
+ term__var_to_int(ToVar, ToVarNum),
+ term__var_to_int(FromVar, FromVarNum),
+ string__format(
+ "common__generate_assign: assigned var %i=%i not in instmap_delta",
+ [i(ToVarNum), i(FromVarNum)], Msg),
+ error(Msg)
),
UnifyContext = unify_context(explicit, []),
Index: compiler/deforest.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/deforest.m,v
retrieving revision 1.4
diff -u -t -u -r1.4 deforest.m
--- deforest.m 1998/07/08 20:55:53 1.4
+++ deforest.m 1998/08/11 06:31:39
@@ -1585,14 +1585,16 @@
pd_info_get_size_delta(SizeDelta0),
pd_info_get_changed(Changed0),
- { Goal0 = _ - GoalInfo0 },
- { Goal1 = GoalExpr1 - GoalInfo1 },
-
- % Take the non-locals from the calling goal_info,
- % everything else from the called goal_info.
- { goal_info_get_nonlocals(GoalInfo0, NonLocals0) },
- { goal_info_set_nonlocals(GoalInfo1, NonLocals0, GoalInfo2) },
- { Goal2 = GoalExpr1 - GoalInfo2 },
+ % update the quantification if not all the output
+ % arguments are used.
+ { Goal1 = _ - GoalInfo1 },
+ { goal_info_get_nonlocals(GoalInfo1, NonLocals1) },
+ { set__list_to_set(Args, NonLocals) },
+ ( { NonLocals1 = NonLocals } ->
+ pd_util__requantify_goal(Goal1, NonLocals, Goal2)
+ ;
+ { Goal2 = Goal1 }
+ ),
% Push the extra information from the call
% through the goal.
@@ -1600,7 +1602,7 @@
{ proc_info_arglives(CalledProcInfo, ModuleInfo0, ArgLives) },
{ get_live_vars(Args, ArgLives, LiveVars0) },
{ set__list_to_set(LiveVars0, LiveVars1) },
- { set__intersect(NonLocals0, LiveVars1, LiveVars) },
+ { set__intersect(NonLocals, LiveVars1, LiveVars) },
pd_util__unique_modecheck_goal(LiveVars, Goal2, Goal3, Errors),
( { Errors = [] } ->
@@ -1641,12 +1643,12 @@
)
)
->
- pd_debug__message("inlined - requantifying: cost(%i) size(%i)\n",
+ { Goal = Goal4 },
+ pd_debug__message("inlined: cost(%i) size(%i)\n",
[i(CostDelta), i(SizeDelta)]),
- { set__list_to_set(Args, NonLocals) },
- pd_util__requantify_goal(Goal4, NonLocals, Goal),
pd_info_incr_size_delta(SizeDelta),
pd_info_set_changed(yes),
+ { Goal0 = _ - GoalInfo0 },
{ goal_info_get_determinism(GoalInfo0, Det0) },
{ Goal = _ - GoalInfo },
{ goal_info_get_determinism(GoalInfo, Det) },
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/det_analysis.m,v
retrieving revision 1.134
diff -u -t -u -r1.134 det_analysis.m
--- det_analysis.m 1998/07/02 09:11:26 1.134
+++ det_analysis.m 1998/08/22 23:58:55
@@ -52,7 +52,8 @@
:- interface.
-:- import_module hlds_module, hlds_pred, hlds_data, det_report, globals.
+:- import_module hlds_goal, hlds_module, hlds_pred, hlds_data, instmap.
+:- import_module det_report, det_util, globals.
:- import_module list, std_util, io.
% Perform determinism inference for local predicates with no
@@ -74,6 +75,22 @@
determinism, determinism, list(det_msg)).
:- mode det_infer_proc(in, in, in, out, in, out, out, out) is det.
+ % Infers the determinism of `Goal0' and returns this in `Detism'.
+ % It annotates the goal and all its subgoals with their determinism
+ % and returns the annotated goal in `Goal'.
+
+:- pred det_infer_goal(hlds_goal, instmap, soln_context, det_info,
+ hlds_goal, determinism, list(det_msg)).
+:- mode det_infer_goal(in, in, in, in, out, out, out) is det.
+
+ % Work out how many solutions are needed for a given determinism.
+:- pred det_get_soln_context(determinism, soln_context).
+:- mode det_get_soln_context(in, out) is det.
+
+:- type soln_context
+ ---> all_solns
+ ; first_soln.
+
% The tables for computing the determinism of compound goals
% from the determinism of their components.
@@ -102,9 +119,9 @@
:- implementation.
-:- import_module hlds_goal, prog_data, det_report, det_util.
+:- import_module prog_data, det_report.
:- import_module type_util, modecheck_call, mode_util, options, passes_aux.
-:- import_module hlds_out, mercury_to_mercury, instmap.
+:- import_module hlds_out, mercury_to_mercury.
:- import_module assoc_list, bool, map, set, require, term.
%-----------------------------------------------------------------------------%
@@ -213,8 +230,6 @@
%-----------------------------------------------------------------------------%
-:- type soln_context ---> all_solns ; first_soln.
-
det_infer_proc(PredId, ProcId, ModuleInfo0, ModuleInfo, Globals,
Detism0, Detism, Msgs) :-
@@ -231,11 +246,9 @@
% context or not. Currently we only assume so if
% the predicate has an explicit determinism declaration
% that says so.
- (
- proc_info_declared_determinism(Proc0, yes(DeclaredDetism)),
- determinism_components(DeclaredDetism, _, at_most_many_cc)
- ->
- SolnContext = first_soln
+ proc_info_declared_determinism(Proc0, MaybeDeclaredDetism),
+ ( MaybeDeclaredDetism = yes(DeclaredDetism) ->
+ det_get_soln_context(DeclaredDetism, SolnContext)
;
SolnContext = all_solns
),
@@ -276,14 +289,6 @@
%-----------------------------------------------------------------------------%
- % Infers the determinism of `Goal0' and returns this in `Detism'.
- % It annotates the goal and all its subgoals with their determinism
- % and returns the annotated goal in `Goal'.
-
-:- pred det_infer_goal(hlds_goal, instmap, soln_context, det_info,
- hlds_goal, determinism, list(det_msg)).
-:- mode det_infer_goal(in, in, in, in, out, out, out) is det.
-
det_infer_goal(Goal0 - GoalInfo0, InstMap0, SolnContext0, DetInfo,
Goal - GoalInfo, Detism, Msgs) :-
goal_info_get_nonlocals(GoalInfo0, NonLocalVars),
@@ -935,6 +940,15 @@
det_infer_unify_canfail(complicated_unify(_, CanFail), CanFail).
%-----------------------------------------------------------------------------%
+
+det_get_soln_context(DeclaredDetism, SolnContext) :-
+ (
+ determinism_components(DeclaredDetism, _, at_most_many_cc)
+ ->
+ SolnContext = first_soln
+ ;
+ SolnContext = all_solns
+ ).
% When figuring out the determinism of a conjunction,
% if the second goal is unreachable, then then the
Index: compiler/ite_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/ite_gen.m,v
retrieving revision 1.58
diff -u -t -u -r1.58 ite_gen.m
--- ite_gen.m 1998/07/29 08:53:07 1.58
+++ ite_gen.m 1998/08/01 05:39:30
@@ -31,7 +31,7 @@
:- implementation.
-:- import_module code_gen, code_util, trace, options, globals.
+:- import_module code_gen, code_util, trace, options, globals, instmap.
:- import_module bool, set, tree, list, map, std_util, term, require.
ite_gen__generate_ite(CodeModel, CondGoal0, ThenGoal, ElseGoal, StoreMap, Code)
@@ -116,13 +116,23 @@
% XXX release any temp slots holding heap or trail pointers
- % XXX If instmap indicates we cannot reach then part,
- % do not attempt to generate it (may cause aborts)
-
- % Generate the then branch
- trace__maybe_generate_internal_event_code(ThenGoal, ThenTraceCode),
- code_gen__generate_goal(CodeModel, ThenGoal, ThenCode),
- code_info__generate_branch_end(StoreMap, no, MaybeEnd0, ThenSaveCode),
+ code_info__get_instmap(EndCondInstMap),
+ ( { instmap__is_unreachable(EndCondInstMap) } ->
+ % If instmap indicates we cannot reach then part,
+ % do not attempt to generate it (may cause aborts).
+ { ThenTraceCode = empty },
+ { ThenCode = empty },
+ { map__init(EmptyStoreMap) },
+ code_info__generate_branch_end(EmptyStoreMap, no,
+ MaybeEnd0, ThenSaveCode)
+ ;
+ % Generate the then branch
+ trace__maybe_generate_internal_event_code(ThenGoal,
+ ThenTraceCode),
+ code_gen__generate_goal(CodeModel, ThenGoal, ThenCode),
+ code_info__generate_branch_end(StoreMap, no,
+ MaybeEnd0, ThenSaveCode)
+ ),
% Generate the entry to the else branch
code_info__reset_to_position(BranchStart),
Index: compiler/mode_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/mode_util.m,v
retrieving revision 1.111
diff -u -t -u -r1.111 mode_util.m
--- mode_util.m 1998/07/08 20:56:54 1.111
+++ mode_util.m 1998/08/22 06:50:36
@@ -1082,17 +1082,26 @@
)
->
{ Goal = Goal0 },
- { GoalInfo = GoalInfo0 },
- { goal_info_get_instmap_delta(GoalInfo, InstMapDelta) }
+ { GoalInfo1 = GoalInfo0 }
;
recompute_instmap_delta_2(RecomputeAtomic, Goal0,
GoalInfo0, Goal, InstMap0, InstMapDelta0),
{ goal_info_get_nonlocals(GoalInfo0, NonLocals) },
{ instmap_delta_restrict(InstMapDelta0,
- NonLocals, InstMapDelta) },
+ NonLocals, InstMapDelta1) },
{ goal_info_set_instmap_delta(GoalInfo0,
- InstMapDelta, GoalInfo) }
- ).
+ InstMapDelta1, GoalInfo1) }
+ ),
+
+ % If the initial instmap is unreachable so is the final instmap.
+ ( { instmap__is_unreachable(InstMap0) } ->
+ { instmap_delta_init_unreachable(UnreachableInstMapDelta) },
+ { goal_info_set_instmap_delta(GoalInfo1,
+ UnreachableInstMapDelta, GoalInfo) }
+ ;
+ { GoalInfo = GoalInfo1 }
+ ),
+ { goal_info_get_instmap_delta(GoalInfo, InstMapDelta) }.
:- pred recompute_instmap_delta_2(bool, hlds_goal_expr, hlds_goal_info,
hlds_goal_expr, instmap, instmap_delta,
Index: compiler/simplify.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/simplify.m,v
retrieving revision 1.62
diff -u -t -u -r1.62 simplify.m
--- simplify.m 1998/08/04 13:13:22 1.62
+++ simplify.m 1998/08/23 00:02:31
@@ -162,15 +162,14 @@
simplify_info_init(DetInfo0, Simplifications, InstMap0,
VarSet0, VarTypes0, Info0),
simplify__process_goal(Goal0, Goal, Info0, Info),
-
- simplify_info_get_module_info(Info, ModuleInfo),
- simplify_info_get_msgs(Info, Msgs),
-
+
simplify_info_get_varset(Info, VarSet),
simplify_info_get_var_types(Info, VarTypes),
proc_info_set_varset(ProcInfo0, VarSet, ProcInfo1),
proc_info_set_vartypes(ProcInfo1, VarTypes, ProcInfo2),
- proc_info_set_goal(ProcInfo2, Goal, ProcInfo).
+ proc_info_set_goal(ProcInfo2, Goal, ProcInfo),
+ simplify_info_get_module_info(Info, ModuleInfo),
+ simplify_info_get_msgs(Info, Msgs).
simplify__process_goal(Goal0, Goal, Info0, Info) :-
simplify_info_get_simplifications(Info0, Simplifications0),
@@ -217,19 +216,30 @@
simplify_info_set_varset(Info1, VarSet, Info2),
simplify_info_set_var_types(Info2, VarTypes, Info3),
- ( simplify_info_recompute_atomic(Info3) ->
- RecomputeAtomic = yes
- ;
- RecomputeAtomic = no
- ),
+
+ % Always recompute instmap_deltas for atomic goals - this
+ % is safer in the case where unused variables should no
+ % longer be included in the instmap_delta for a goal.
+ % In the alias branch this is necessary anyway.
+ RecomputeAtomic = yes,
simplify_info_get_module_info(Info3, ModuleInfo1),
- recompute_instmap_delta(RecomputeAtomic, Goal2, Goal,
+ recompute_instmap_delta(RecomputeAtomic, Goal2, Goal3,
InstMap0, ModuleInfo1, ModuleInfo),
simplify_info_set_module_info(Info3, ModuleInfo, Info)
;
- Goal = Goal1,
+ Goal3 = Goal1,
Info = Info1
+ ),
+ ( simplify_info_rerun_det(Info) ->
+ Goal0 = _ - GoalInfo0,
+ goal_info_get_determinism(GoalInfo0, Det),
+ det_get_soln_context(Det, SolnContext),
+ simplify_info_get_det_info(Info, DetInfo),
+ det_infer_goal(Goal3, InstMap0, SolnContext,
+ DetInfo, Goal, _, _)
+ ;
+ Goal = Goal3
).
%-----------------------------------------------------------------------------%
@@ -292,8 +302,15 @@
; code_aux__goal_cannot_loop(ModuleInfo, Goal0)
)
->
+ % If the goal had any non-locals we should requantify.
+ goal_info_get_nonlocals(GoalInfo0, NonLocals0),
+ ( set__empty(NonLocals0) ->
+ Info1 = Info0
+ ;
+ simplify_info_set_requantify(Info0, Info1)
+ ),
pd_cost__goal(Goal0, CostDelta),
- simplify_info_incr_cost_delta(Info0, CostDelta, Info1),
+ simplify_info_incr_cost_delta(Info1, CostDelta, Info2),
goal_info_get_context(GoalInfo0, Context),
fail_goal(Context, Goal1)
;
@@ -308,13 +325,13 @@
% XXX we should warn about this (if the goal wasn't `true')
%
- % XXX this optimization is currently disabled,
- % since it mishandles calls to existentially typed
- % predicates.
+ % XXX this optimization is currently disabled for anything
+ % other than unifications, since it mishandles calls to
+ % existentially typed predicates.
% The fix for this is to run polymorphism.m before simplify.m.
% When that is done, we can re-enable this optimization.
- semidet_fail,
-
+ Goal0 = unify(_, _, _, _, _) - _,
+
determinism_components(Detism, cannot_fail, MaxSoln),
MaxSoln \= at_most_zero,
goal_info_get_instmap_delta(GoalInfo0, InstMapDelta),
@@ -328,28 +345,36 @@
; code_aux__goal_cannot_loop(ModuleInfo, Goal0)
)
->
+ % If the goal had any non-locals we should requantify.
+ goal_info_get_nonlocals(GoalInfo0, NonLocals0),
+ ( set__empty(NonLocals0) ->
+ Info1 = Info0
+ ;
+ simplify_info_set_requantify(Info0, Info1)
+ ),
pd_cost__goal(Goal0, CostDelta),
- simplify_info_incr_cost_delta(Info0, CostDelta, Info1),
+ simplify_info_incr_cost_delta(Info1, CostDelta, Info2),
goal_info_get_context(GoalInfo0, Context),
true_goal(Context, Goal1)
;
Goal1 = Goal0,
- Info1 = Info0
+ Info2 = Info0
),
- simplify_info_maybe_clear_structs(before, Goal1, Info1, Info2),
+ simplify_info_maybe_clear_structs(before, Goal1, Info2, Info3),
Goal1 = GoalExpr1 - GoalInfo1,
- simplify__goal_2(GoalExpr1, GoalInfo1, Goal, GoalInfo2, Info2, Info3),
- simplify_info_maybe_clear_structs(after, Goal - GoalInfo2, Info3, Info),
- simplify__enforce_invariant(GoalInfo2, GoalInfo).
+ simplify__goal_2(GoalExpr1, GoalInfo1, Goal, GoalInfo2, Info3, Info4),
+ simplify_info_maybe_clear_structs(after, Goal - GoalInfo2,
+ Info4, Info5),
+ simplify__enforce_invariant(GoalInfo2, GoalInfo, Info5, Info).
-
-:- pred simplify__enforce_invariant(hlds_goal_info, hlds_goal_info).
-:- mode simplify__enforce_invariant(in, out) is det.
+:- pred simplify__enforce_invariant(hlds_goal_info, hlds_goal_info,
+ simplify_info, simplify_info).
+:- mode simplify__enforce_invariant(in, out, in, out) is det.
%
% Ensure that the mode information and the determinism
% information say consistent things about unreachability.
%
-simplify__enforce_invariant(GoalInfo0, GoalInfo) :-
+simplify__enforce_invariant(GoalInfo0, GoalInfo, Info0, Info) :-
goal_info_get_determinism(GoalInfo0, Determinism0),
goal_info_get_instmap_delta(GoalInfo0, DeltaInstmap0),
determinism_components(Determinism0, CanFail0, NumSolns0),
@@ -359,15 +384,18 @@
->
instmap_delta_init_unreachable(UnreachableInstMapDelta),
goal_info_set_instmap_delta(GoalInfo0, UnreachableInstMapDelta,
- GoalInfo)
+ GoalInfo),
+ simplify_info_set_rerun_det(Info0, Info)
;
instmap_delta_is_unreachable(DeltaInstmap0),
NumSolns0 \= at_most_zero
->
determinism_components(Determinism, CanFail0, at_most_zero),
- goal_info_set_determinism(GoalInfo0, Determinism, GoalInfo)
+ goal_info_set_determinism(GoalInfo0, Determinism, GoalInfo),
+ simplify_info_set_rerun_det(Info0, Info)
;
- GoalInfo = GoalInfo0
+ GoalInfo = GoalInfo0,
+ Info = Info0
).
%-----------------------------------------------------------------------------%
@@ -376,13 +404,18 @@
hlds_goal_info, simplify_info, simplify_info).
:- mode simplify__goal_2(in, in, out, out, in, out) is det.
-simplify__goal_2(conj(Goals0), GoalInfo0, Goal, GoalInfo0, Info0, Info) :-
+simplify__goal_2(conj(Goals0), GoalInfo0, Goal, GoalInfo, Info0, Info) :-
simplify_info_get_instmap(Info0, InstMap0),
simplify__conj(Goals0, [], Goals, GoalInfo0, Info0, Info1),
- simplify_info_set_instmap(Info1, InstMap0, Info),
- ( Goals = [SingleGoal] ->
+ simplify_info_set_instmap(Info1, InstMap0, Info2),
+ ( Goals = [] ->
+ goal_info_get_context(GoalInfo0, Context),
+ true_goal(Context, Goal - GoalInfo),
+ Info = Info2
+ ; Goals = [SingleGoal - SingleGoalInfo] ->
% a singleton conjunction is equivalent to the goal itself
- SingleGoal = Goal - _
+ simplify__maybe_wrap_goal(GoalInfo0, SingleGoalInfo,
+ SingleGoal, Goal, GoalInfo, Info2, Info)
;
%
% Conjunctions that cannot produce solutions may nevertheless
@@ -390,6 +423,7 @@
% conjunction is put inside a `some' to appease the code
% generator.
%
+ Info = Info2,
goal_info_get_determinism(GoalInfo0, Detism),
(
simplify_do_once(Info),
@@ -404,20 +438,25 @@
Goal = some([], InnerGoal)
;
Goal = conj(Goals)
- )
+ ),
+ GoalInfo = GoalInfo0
).
-simplify__goal_2(par_conj(Goals0, SM), GoalInfo, Goal, GoalInfo, Info0, Info) :-
+simplify__goal_2(par_conj(Goals0, SM), GoalInfo0, Goal,
+ GoalInfo, Info0, Info) :-
(
Goals0 = []
->
- Goal = conj([]),
+ goal_info_get_context(GoalInfo0, Context),
+ true_goal(Context, Goal - GoalInfo),
Info = Info0
;
Goals0 = [Goal0]
->
+ GoalInfo = GoalInfo0,
simplify__goal(Goal0, Goal - _, Info0, Info)
;
+ GoalInfo = GoalInfo0,
simplify__par_conj(Goals0, Goals, Info0, Info0, Info),
Goal = par_conj(Goals, SM)
).
@@ -428,30 +467,14 @@
simplify__disj(Disjuncts0, [], Disjuncts, [], InstMaps,
Info0, Info0, Info1),
( Disjuncts = [] ->
- Goal = disj([], SM),
- GoalInfo = GoalInfo0,
+ goal_info_get_context(GoalInfo0, Context),
+ fail_goal(Context, Goal - GoalInfo),
Info = Info1
; Disjuncts = [SingleGoal] ->
% a singleton disjunction is equivalent to the goal itself
SingleGoal = Goal1 - GoalInfo1,
- Info = Info1,
- (
- % If the determinisms are not the same, we really
- % need to rerun determinism analysis on the
- % procedure. I think this is a similar situation
- % to inlining of erroneous goals. The safe thing
- % to do is to wrap a `some' around the inner goal if
- % the inner and outer determinisms are not the same.
- % It probably won't happen that often.
- goal_info_get_determinism(GoalInfo0, Det),
- goal_info_get_determinism(GoalInfo1, Det)
- ->
- Goal = Goal1,
- GoalInfo = GoalInfo1
- ;
- Goal = some([], Goal1 - GoalInfo1),
- GoalInfo = GoalInfo0
- )
+ simplify__maybe_wrap_goal(GoalInfo0, GoalInfo1,
+ Goal1, Goal, GoalInfo, Info1, Info)
;
Goal = disj(Disjuncts, SM),
simplify_info_get_module_info(Info1, ModuleInfo1),
@@ -530,8 +553,8 @@
Goal = switch(Var, SwitchCanFail, Cases, SM),
simplify_info_get_module_info(Info1, ModuleInfo1),
goal_info_get_nonlocals(GoalInfo0, NonLocals),
- merge_instmap_deltas(InstMap0, NonLocals, InstMaps, NewDelta,
- ModuleInfo1, ModuleInfo2),
+ merge_instmap_deltas(InstMap0, NonLocals, InstMaps,
+ NewDelta, ModuleInfo1, ModuleInfo2),
simplify_info_set_module_info(Info1, ModuleInfo2, Info),
goal_info_set_instmap_delta(GoalInfo0, NewDelta, GoalInfo)
).
@@ -785,7 +808,7 @@
list__append(CondList, ThenList, List),
simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo,
Info0, Info1),
- goal_info_get_context(GoalInfo, Context),
+ goal_info_get_context(GoalInfo0, Context),
simplify_info_add_msg(Info1, ite_cond_cannot_fail(Context),
Info)
; CondSolns0 = at_most_zero ->
@@ -821,7 +844,7 @@
List = [Cond | ElseList],
simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo,
Info0, Info1),
- goal_info_get_context(GoalInfo, Context),
+ goal_info_get_context(GoalInfo0, Context),
simplify_info_add_msg(Info1, ite_cond_cannot_succeed(Context),
Info)
; Else0 = disj([], _) - _ ->
@@ -847,7 +870,7 @@
CondThenDelta),
Else = _ - ElseInfo,
goal_info_get_instmap_delta(ElseInfo, ElseDelta),
- goal_info_get_nonlocals(GoalInfo0, NonLocals),
+ goal_info_get_nonlocals(GoalInfo0, NonLocals),
simplify_info_get_module_info(Info6, ModuleInfo0),
merge_instmap_deltas(InstMap0, NonLocals,
[CondThenDelta, ElseDelta], NewDelta,
@@ -881,7 +904,7 @@
GoalInfo = GoalInfo1
).
-simplify__goal_2(not(Goal0), GoalInfo, Goal, GoalInfo, Info0, Info) :-
+simplify__goal_2(not(Goal0), GoalInfo0, Goal, GoalInfo, Info0, Info) :-
% Can't use calls or unifications seen within a negation,
% since non-local variables may not be bound within the negation.
simplify_info_get_common_info(Info0, Common),
@@ -890,41 +913,56 @@
Goal1 = _ - GoalInfo1,
goal_info_get_determinism(GoalInfo1, Detism),
determinism_components(Detism, CanFail, MaxSoln),
+ goal_info_get_context(GoalInfo0, Context),
( CanFail = cannot_fail ->
- goal_info_get_context(GoalInfo, Context),
simplify_info_add_msg(Info2,
- negated_goal_cannot_fail(Context), Info)
+ negated_goal_cannot_fail(Context), Info3)
; MaxSoln = at_most_zero ->
- goal_info_get_context(GoalInfo, Context),
simplify_info_add_msg(Info2,
- negated_goal_cannot_succeed(Context), Info)
+ negated_goal_cannot_succeed(Context), Info3)
;
- Info = Info2
+ Info3 = Info2
),
(
% replace `not true' with `fail'
Goal1 = conj([]) - _GoalInfo
->
- map__init(Empty),
- Goal = disj([], Empty)
+ fail_goal(Context, Goal - GoalInfo),
+ Info = Info3
;
% replace `not fail' with `true'
Goal1 = disj([], _) - _GoalInfo2
->
- Goal = conj([])
+ true_goal(Context, Goal - GoalInfo),
+ Info = Info3
;
% remove double negation
- Goal1 = not(SubGoal - _) - _
+ Goal1 = not(SubGoal - SubGoalInfo) - _
->
- Goal = SubGoal
+ simplify__maybe_wrap_goal(GoalInfo0, SubGoalInfo, SubGoal,
+ Goal, GoalInfo, Info3, Info)
;
- Goal = not(Goal1)
+ Goal = not(Goal1),
+ GoalInfo = GoalInfo0,
+ Info = Info3
).
-simplify__goal_2(some(Vars1, Goal1), SomeInfo, Goal, SomeInfo, Info0, Info) :-
+simplify__goal_2(some(Vars1, Goal1), SomeInfo, Goal, GoalInfo, Info0, Info) :-
simplify__goal(Goal1, Goal2, Info0, Info),
simplify__nested_somes(Vars1, Goal2, Vars, Goal3),
- Goal = some(Vars, Goal3).
+ Goal3 = GoalExpr3 - GoalInfo3,
+ (
+ goal_info_get_determinism(GoalInfo3, Detism),
+ goal_info_get_determinism(SomeInfo, Detism)
+ ->
+ % If the inner and outer detisms match the `some'
+ % is unnecessary.
+ Goal = GoalExpr3,
+ GoalInfo = GoalInfo3
+ ;
+ Goal = some(Vars, Goal3),
+ GoalInfo = SomeInfo
+ ).
simplify__goal_2(Goal0, GoalInfo, Goal, GoalInfo, Info0, Info) :-
Goal0 = pragma_c_code(_, PredId, ProcId, Args, _, _, _),
@@ -981,6 +1019,35 @@
%-----------------------------------------------------------------------------%
+ % When removing a level of wrapping around a goal,
+ % if the determinisms are not the same, we really
+ % need to rerun determinism analysis on the
+ % procedure. I think this is a similar situation
+ % to inlining of erroneous goals. The safe thing
+ % to do is to wrap a `some' around the inner goal if
+ % the inner and outer determinisms are not the same.
+ % It probably won't happen that often.
+:- pred simplify__maybe_wrap_goal(hlds_goal_info::in, hlds_goal_info::in,
+ hlds_goal_expr::in, hlds_goal_expr::out, hlds_goal_info::out,
+ simplify_info::in, simplify_info::out) is det.
+
+simplify__maybe_wrap_goal(OuterGoalInfo, InnerGoalInfo,
+ Goal1, Goal, GoalInfo, Info0, Info) :-
+ (
+ goal_info_get_determinism(InnerGoalInfo, Det),
+ goal_info_get_determinism(OuterGoalInfo, Det)
+ ->
+ Goal = Goal1,
+ GoalInfo = InnerGoalInfo,
+ Info = Info0
+ ;
+ Goal = some([], Goal1 - InnerGoalInfo),
+ GoalInfo = OuterGoalInfo,
+ simplify_info_set_rerun_det(Info0, Info)
+ ).
+
+%-----------------------------------------------------------------------------%
+
:- pred simplify__conj(list(hlds_goal), list(hlds_goal),
list(hlds_goal), hlds_goal_info,
simplify_info, simplify_info).
@@ -1361,12 +1428,7 @@
Cond = Disjunct,
Cond = _CondGoal - CondGoalInfo,
- goal_info_init(ThenGoalInfo0),
- instmap_delta_init_reachable(InstMap1),
- goal_info_set_instmap_delta(ThenGoalInfo0, InstMap1,
- ThenGoalInfo1),
- goal_info_set_determinism(ThenGoalInfo1, det, ThenGoalInfo),
- Then = conj([]) - ThenGoalInfo,
+ true_goal(Then),
det_disj_to_ite(Disjuncts, GoalInfo, SM, Rest),
Rest = _RestGoal - RestGoalInfo,
@@ -1419,9 +1481,10 @@
varset,
map(var, type),
bool, % Does the goal need requantification.
- bool, % Does mode analysis need rerunning
- % rather than recompute_instmap_delta.
- unit,
+ bool, % Do we need to recompute
+ % instmap_deltas for atomic goals
+ bool, % Does determinism analysis need to
+ % be rerun.
int, % Measure of the improvement in
% the goal from simplification.
int % Count of the number of lambdas
@@ -1434,7 +1497,7 @@
set__init(Msgs),
set__list_to_set(Simplifications0, Simplifications),
Info = simplify_info(DetInfo, Msgs, Simplifications, CommonInfo,
- InstMap, VarSet, VarTypes, no, no, unit, 0, 0).
+ InstMap, VarSet, VarTypes, no, no, no, 0, 0).
% Reinitialise the simplify_info before reprocessing a goal.
:- pred simplify_info_reinit(set(simplification)::in, instmap::in,
@@ -1445,7 +1508,7 @@
VarSet, VarTypes, _, _, _, CostDelta, _),
common_info_init(Common),
Info = simplify_info(DetInfo, Msgs, Simplifications, Common, InstMap0,
- VarSet, VarTypes, no, no, unit, CostDelta, 0).
+ VarSet, VarTypes, no, no, no, CostDelta, 0).
% exported for common.m
:- interface.
@@ -1469,6 +1532,7 @@
map(var, type)::out) is det.
:- pred simplify_info_requantify(simplify_info::in) is semidet.
:- pred simplify_info_recompute_atomic(simplify_info::in) is semidet.
+:- pred simplify_info_rerun_det(simplify_info::in) is semidet.
:- pred simplify_info_get_cost_delta(simplify_info::in, int::out) is det.
:- pred simplify_info_get_module_info(simplify_info::in,
@@ -1489,10 +1553,10 @@
VarTypes).
simplify_info_requantify(simplify_info(_,_,_,_,_,_,_, yes, _,_,_,_)).
simplify_info_recompute_atomic(simplify_info(_,_,_,_,_,_,_,_, yes,_,_,_)).
+simplify_info_rerun_det(simplify_info(_,_,_,_,_,_,_,_,_, yes,_,_)).
simplify_info_get_cost_delta(simplify_info(_,_,_,_,_,_,_,_,_,_,CostDelta, _),
CostDelta).
-
simplify_info_get_module_info(Info, ModuleInfo) :-
simplify_info_get_det_info(Info, DetInfo),
det_info_get_module_info(DetInfo, ModuleInfo).
@@ -1517,6 +1581,8 @@
simplify_info::out) is det.
:- pred simplify_info_set_recompute_atomic(simplify_info::in,
simplify_info::out) is det.
+:- pred simplify_info_set_rerun_det(simplify_info::in,
+ simplify_info::out) is det.
:- pred simplify_info_add_msg(simplify_info::in, det_msg::in,
simplify_info::out) is det.
:- pred simplify_info_do_add_msg(simplify_info::in, det_msg::in,
@@ -1559,6 +1625,8 @@
simplify_info(A, B, C, D, E, F, G, yes, I, J, K, L)).
simplify_info_set_recompute_atomic(simplify_info(A, B, C, D, E, F, G,H,_,J,K,L),
simplify_info(A, B, C, D, E, F, G, H, yes, J, K, L)).
+simplify_info_set_rerun_det(simplify_info(A, B, C, D, E, F, G,H,I,_,K,L),
+ simplify_info(A, B, C, D, E, F, G, H, I, yes, K, L)).
simplify_info_set_cost_delta(simplify_info(A, B, C, D, E, F, G, H, I, J, _, L),
Delta, simplify_info(A, B, C, D, E, F, G, H, I, J, Delta, L)).
More information about the developers
mailing list