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