[m-rev.] for review: exception analysis, intermodule-analysis and optimization

Julien Fischer juliensf at cs.mu.OZ.AU
Thu Feb 16 01:10:23 AEDT 2006


For review by anyone. (Peter, could you please have a look the changes
to exception_analysis.m.)

Estimated hours taken: 10
Branches: main

Convert those optimization passes that make use of exception analysis
information to make use of the intermodule-analysis framework.

Make preparations to do the same thing for the termination analyses.

s/list(prog_var)/prog_vars/
s/list(hlds_goal)/hlds_goals/

Style cleanups and formatting fixes for these modules as necessary.

compiler/exception_analysis.m:
	Export a predicate that allows optimizations to access exception
	analysis results without worrying about where they are stored.  When
	using intermodule-analysis information about imported procedures is
	stored in the analysis registry, not in the exception_info table; with
	intermodule-optimization information about imported procedures is
	stored in the exception_info table.

compiler/goal_form.m:
	Add a version of goal_cannot_throw that uses information from the
	intermodule-analysis framework.

	Mention that the existing versions of this predicate are deprecated
	and will eventually be deleted.

compiler/goal_util.m:
	Provide alternative versions of the predicates can_reorder_goals and
	reordering_maintains_termination that can use information from the
	intermodule-analysis framework.  We will eventually use these versions
	exclusively.

compiler/simplify.m:
compiler/constraint.m:
	Use information from the intermodule-analysis framework when
	performing these optimizations.

compiler/accumulator.m:
	Mention that this module needs to be updated to use the
	intermodule-analysis framework.  (I'll do this as separate change
	since it's probably going to require a fairly major rewrite of this
	module to do this.)

compiler/deforest.m:
compiler/pd_util.m:
compiler/size_prof.m:
	Conform to the above changes.

Julien.

Index: compiler/accumulator.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/accumulator.m,v
retrieving revision 1.48
diff -u -r1.48 accumulator.m
--- compiler/accumulator.m	28 Nov 2005 04:11:36 -0000	1.48
+++ compiler/accumulator.m	15 Feb 2006 13:49:19 -0000
@@ -137,6 +137,9 @@
 % until one succeeds.  This makes the order of independent recursive
 % calls in the body irrelevant.

+% XXX replace calls to can_reorder_goals with calls to the version that
+%     use the intermodule-analysis framework.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.67
diff -u -r1.67 constraint.m
--- compiler/constraint.m	17 Nov 2005 15:57:05 -0000	1.67
+++ compiler/constraint.m	15 Feb 2006 14:02:49 -0000
@@ -5,18 +5,18 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-%
+
 % File: constraint.m
 % Main author: stayl.
-%
+
 % The constraint propagation transformation attempts to improve the efficiency
 % of a generate-and-test style program by statically scheduling constraints as
 % early as possible, where a "constraint" is any pure goal which has no
 % outputs, can fail, cannot loop and cannot throw an exception.
-%
+
 %-----------------------------------------------------------------------------%

-:- module transform_hlds__constraint.
+:- module transform_hlds.constraint.
 :- interface.

 :- import_module hlds.hlds_goal.
@@ -25,6 +25,7 @@
 :- import_module parse_tree.prog_data.

 :- import_module bool.
+:- import_module io.

 %-----------------------------------------------------------------------------%

@@ -37,7 +38,7 @@
     % goal feature.
     %
 :- pred propagate_constraints_in_goal(hlds_goal::in, hlds_goal::out,
-    constraint_info::in, constraint_info::out) is det.
+    constraint_info::in, constraint_info::out, io::di, io::uo) is det.

 :- pred constraint_info_init(module_info::in, vartypes::in, prog_varset::in,
     instmap::in, constraint_info::out) is det.
@@ -72,7 +73,7 @@

 %-----------------------------------------------------------------------------%

-propagate_constraints_in_goal(Goal0, Goal, !Info) :-
+propagate_constraints_in_goal(Goal0, Goal, !Info, !IO) :-
     % We need to strip off any existing constraint markers first.
     % Constraint markers are meant to indicate where a constraint is
     % meant to be attached to a call, and that deforest.m should
@@ -80,12 +81,13 @@
     % deforest.m rearranges the goal, the constraints may not remain
     % next to the call.
     Goal1 = strip_constraint_markers(Goal0),
-    propagate_goal(Goal1, [], Goal, !Info).
+    propagate_goal(Goal1, [], Goal, !Info, !IO).

 :- pred propagate_goal(hlds_goal::in, list(constraint)::in,
-    hlds_goal::out, constraint_info::in, constraint_info::out) is det.
+    hlds_goal::out, constraint_info::in, constraint_info::out,
+    io::di, io::uo) is det.

-propagate_goal(Goal0, Constraints, Goal, !Info) :-
+propagate_goal(Goal0, Constraints, Goal, !Info, !IO) :-
     % We need to treat all single goals as conjunctions so that
     % propagate_conj can move the constraints to the left of the goal
     % if that is allowed.
@@ -93,7 +95,7 @@
     goal_info_get_features(GoalInfo0, Features0),
     goal_info_get_context(GoalInfo0, Context),
     goal_to_conj_list(Goal0, Goals0),
-    propagate_conj(Goals0, Constraints, Goals, !Info),
+    propagate_conj(Goals0, Constraints, Goals, !Info, !IO),
     goal_list_nonlocals(Goals, NonLocals),
     goal_list_instmap_delta(Goals, Delta),
     goal_list_determinism(Goals, ConjDetism),
@@ -106,9 +108,9 @@

 :- pred propagate_conj_sub_goal(hlds_goal::in,
     list(constraint)::in, hlds_goals::out,
-    constraint_info::in, constraint_info::out) is det.
+    constraint_info::in, constraint_info::out, io::di, io::uo) is det.

-propagate_conj_sub_goal(Goal0, Constraints, Goals, !Info) :-
+propagate_conj_sub_goal(Goal0, Constraints, Goals, !Info, !IO) :-
     Goal0 = GoalExpr0 - _,
     ( goal_is_atomic(GoalExpr0) ->
         true
@@ -119,67 +121,67 @@
         constraint_info_update_changed(Constraints, !Info)
     ),
     InstMap0 = !.Info ^ instmap,
-    propagate_conj_sub_goal_2(Goal0, Constraints, Goals, !Info),
+    propagate_conj_sub_goal_2(Goal0, Constraints, Goals, !Info, !IO),
     !:Info = !.Info ^ instmap := InstMap0.

 :- pred propagate_conj_sub_goal_2(hlds_goal::in, list(constraint)::in,
-    list(hlds_goal)::out, constraint_info::in, constraint_info::out)
-    is det.
+    list(hlds_goal)::out, constraint_info::in, constraint_info::out,
+    io::di, io::uo) is det.

 propagate_conj_sub_goal_2(conj(Goals0) - Info, Constraints,
-        [conj(Goals) - Info], !Info) :-
-    propagate_conj(Goals0, Constraints, Goals, !Info).
+        [conj(Goals) - Info], !Info, !IO) :-
+    propagate_conj(Goals0, Constraints, Goals, !Info, !IO).

 propagate_conj_sub_goal_2(disj(Goals0) - Info, Constraints,
-        [disj(Goals) - Info], !Info) :-
-    propagate_disj(Goals0, Constraints, Goals, !Info).
+        [disj(Goals) - Info], !Info, !IO) :-
+    propagate_disj(Goals0, Constraints, Goals, !Info, !IO).

 propagate_conj_sub_goal_2(switch(Var, CanFail, Cases0) - Info,
-        Constraints, [switch(Var, CanFail, Cases) - Info], !Info) :-
-    propagate_cases(Var, Constraints, Cases0, Cases, !Info).
+        Constraints, [switch(Var, CanFail, Cases) - Info], !Info, !IO) :-
+    propagate_cases(Var, Constraints, Cases0, Cases, !Info, !IO).

 propagate_conj_sub_goal_2(
         if_then_else(Vars, Cond0, Then0, Else0) - Info,
         Constraints,
-        [if_then_else(Vars, Cond, Then, Else) - Info], !Info) :-
+        [if_then_else(Vars, Cond, Then, Else) - Info], !Info, !IO) :-
     InstMap0 = !.Info ^ instmap,

     % We can't safely propagate constraints into
     % the condition of an if-then-else, because that
     % would change the answers generated by the procedure.
-    propagate_goal(Cond0, [], Cond, !Info),
+    propagate_goal(Cond0, [], Cond, !Info, !IO),
     constraint_info_update_goal(Cond, !Info),
-    propagate_goal(Then0, Constraints, Then, !Info),
+    propagate_goal(Then0, Constraints, Then, !Info, !IO),
     !:Info = !.Info ^ instmap := InstMap0,
-    propagate_goal(Else0, Constraints, Else, !Info).
+    propagate_goal(Else0, Constraints, Else, !Info, !IO).

     % XXX propagate constraints into par_conjs -- this isn't
     % possible at the moment because par_conj goals must have
     % determinism det.
 propagate_conj_sub_goal_2(par_conj(Goals0) - GoalInfo,
         Constraints0,
-        [par_conj(Goals) - GoalInfo | Constraints], !Info) :-
+        [par_conj(Goals) - GoalInfo | Constraints], !Info, !IO) :-
     % Propagate constraints within the goals of the conjunction.
     % propagate_disj treats its list of goals as
     % independent rather than specifically disjoint, so we can
     % use it to process a list of independent parallel conjuncts.
-    propagate_disj(Goals0, [], Goals, !Info),
+    propagate_disj(Goals0, [], Goals, !Info, !IO),
     flatten_constraints(Constraints0, Constraints).

 propagate_conj_sub_goal_2(scope(Reason, Goal0) - GoalInfo, Constraints,
-        [scope(Reason, Goal) - GoalInfo], !Info) :-
-    propagate_goal(Goal0, Constraints, Goal, !Info).
+        [scope(Reason, Goal) - GoalInfo], !Info, !IO) :-
+    propagate_goal(Goal0, Constraints, Goal, !Info, !IO).

 propagate_conj_sub_goal_2(not(NegGoal0) - GoalInfo, Constraints0,
-        [not(NegGoal) - GoalInfo | Constraints], !Info) :-
+        [not(NegGoal) - GoalInfo | Constraints], !Info, !IO) :-
     % We can't safely propagate constraints into a negation,
     % because that would change the answers computed by the
     % procedure.
-    propagate_goal(NegGoal0, [], NegGoal, !Info),
+    propagate_goal(NegGoal0, [], NegGoal, !Info, !IO),
     flatten_constraints(Constraints0, Constraints).

 propagate_conj_sub_goal_2(Goal, Constraints0,
-        [Goal | Constraints], !Info) :-
+        [Goal | Constraints], !Info, !IO) :-
     % propagate_conj will move the constraints
     % to the left of the call if that is possible, so nothing
     % needs to be done here.
@@ -187,21 +189,21 @@
     flatten_constraints(Constraints0, Constraints).

 propagate_conj_sub_goal_2(Goal, Constraints0,
-        [Goal | Constraints], !Info) :-
+        [Goal | Constraints], !Info, !IO) :-
     Goal = generic_call(_, _, _, _) - _,
     flatten_constraints(Constraints0, Constraints).

 propagate_conj_sub_goal_2(Goal, Constraints0,
-        [Goal | Constraints], !Info) :-
+        [Goal | Constraints], !Info, !IO) :-
     Goal = foreign_proc(_, _, _, _, _, _) - _,
     flatten_constraints(Constraints0, Constraints).

-propagate_conj_sub_goal_2(Goal, _, _, !Info) :-
+propagate_conj_sub_goal_2(Goal, _, _, !Info, !IO) :-
     Goal = shorthand(_) - _,
     unexpected(this_file, "propagate_conj_sub_goal_2: shorthand").

 propagate_conj_sub_goal_2(Goal, Constraints0,
-        [Goal | Constraints], !Info) :-
+        [Goal | Constraints], !Info, !IO) :-
     Goal = unify(_, _, _, _, _) - _,
     flatten_constraints(Constraints0, Constraints).

@@ -209,7 +211,7 @@

     % Put the constant constructions in front of the constraint.
     %
-:- pred flatten_constraints(list(constraint)::in, list(hlds_goal)::out) is det.
+:- pred flatten_constraints(list(constraint)::in, hlds_goals::out) is det.

 flatten_constraints(Constraints0, Goals) :-
     list__map((pred(Constraint::in, Lists::out) is det :-
@@ -221,31 +223,31 @@

 %-----------------------------------------------------------------------------%

-:- pred propagate_disj(list(hlds_goal)::in, list(constraint)::in,
-    list(hlds_goal)::out, constraint_info::in, constraint_info::out)
-    is det.
+:- pred propagate_disj(hlds_goals::in, list(constraint)::in,
+    hlds_goals::out, constraint_info::in, constraint_info::out,
+    io::di, io::uo) is det.

-propagate_disj([], _, [], !Info).
-propagate_disj([Goal0 | Goals0], Constraints, [Goal | Goals], !Info) :-
+propagate_disj([], _, [], !Info, !IO).
+propagate_disj([Goal0 | Goals0], Constraints, [Goal | Goals], !Info, !IO) :-
     InstMap0 = !.Info ^ instmap,
-    propagate_goal(Goal0, Constraints, Goal, !Info),
+    propagate_goal(Goal0, Constraints, Goal, !Info, !IO),
     !:Info = !.Info ^ instmap := InstMap0,
-    propagate_disj(Goals0, Constraints, Goals, !Info).
+    propagate_disj(Goals0, Constraints, Goals, !Info, !IO).

 %-----------------------------------------------------------------------------%

 :- pred propagate_cases(prog_var::in, list(constraint)::in,
     list(case)::in, list(case)::out,
-    constraint_info::in, constraint_info::out) is det.
+    constraint_info::in, constraint_info::out, io::di, io::uo) is det.

-propagate_cases(_, _, [], [], !Info).
+propagate_cases(_, _, [], [], !Info, !IO).
 propagate_cases(Var, Constraints, [case(ConsId, Goal0) | Cases0],
-        [case(ConsId, Goal) | Cases], !Info) :-
+        [case(ConsId, Goal) | Cases], !Info, !IO) :-
     InstMap0 = !.Info ^ instmap,
     constraint_info_bind_var_to_functor(Var, ConsId, !Info),
-    propagate_goal(Goal0, Constraints, Goal, !Info),
+    propagate_goal(Goal0, Constraints, Goal, !Info, !IO),
     !:Info = !.Info ^ instmap := InstMap0,
-    propagate_cases(Var, Constraints, Cases0, Cases, !Info).
+    propagate_cases(Var, Constraints, Cases0, Cases, !Info, !IO).

 %-----------------------------------------------------------------------------%

@@ -255,16 +257,16 @@
     % encountered to increase the likelihood of folding recursive
     % calls.
     %
-:- pred propagate_conj(list(hlds_goal)::in, list(constraint)::in,
-    list(hlds_goal)::out, constraint_info::in, constraint_info::out)
-    is det.
+:- pred propagate_conj(hlds_goals::in, list(constraint)::in,
+    hlds_goals::out, constraint_info::in, constraint_info::out,
+    io::di, io::uo) is det.

-propagate_conj(Goals0, Constraints, Goals, !Info) :-
+propagate_conj(Goals0, Constraints, Goals, !Info, !IO) :-
     constraint_info_update_changed(Constraints, !Info),
     ( Goals0 = [] ->
         flatten_constraints(Constraints, Goals)
     ; Goals0 = [Goal0], Constraints = [] ->
-        propagate_conj_sub_goal(Goal0, [], Goals, !Info)
+        propagate_conj_sub_goal(Goal0, [], Goals, !Info, !IO)
     ;
         InstMap0 = !.Info ^ instmap,
         ModuleInfo = !.Info ^ module_info,
@@ -272,8 +274,8 @@
         annotate_conj_output_vars(Goals0, ModuleInfo,
             VarTypes, InstMap0, [], RevGoals1),
         annotate_conj_constraints(ModuleInfo, RevGoals1,
-            Constraints, [], Goals2, !Info),
-        propagate_conj_constraints(Goals2, [], Goals, !Info)
+            Constraints, [], Goals2, !Info, !IO),
+        propagate_conj_constraints(Goals2, [], Goals, !Info, !IO)
     ).

     % Annotate each conjunct with the variables it produces.
@@ -389,12 +391,12 @@

     % Pass backwards over the conjunction, annotating each conjunct
     % with the constraints that should be pushed into it.
-    %
+    %
 :- pred annotate_conj_constraints(module_info::in, annotated_conj::in,
     list(constraint)::in, constrained_conj::in, constrained_conj::out,
-    constraint_info::in, constraint_info::out) is det.
+    constraint_info::in, constraint_info::out, io::di, io::uo) is det.

-annotate_conj_constraints(_, [], Constraints0, Goals0, Goals, !Info) :-
+annotate_conj_constraints(_, [], Constraints0, Goals0, Goals, !Info, !IO) :-
     flatten_constraints(Constraints0, Constraints1),
     list__map((pred(Goal::in, CnstrGoal::out) is det :-
             CnstrGoal = Goal - []
@@ -402,11 +404,15 @@
     list__append(Constraints, Goals0, Goals).
 annotate_conj_constraints(ModuleInfo,
         [Conjunct | RevConjuncts0],
-        Constraints0, Goals0, Goals, !Info) :-
+        Constraints0, Goals0, Goals, !Info, !IO) :-
     Conjunct = annotated_conjunct(Goal, ChangedVars, OutputVars,
         IncompatibleInstVars),
     Goal = GoalExpr - GoalInfo,
     goal_info_get_nonlocals(GoalInfo, NonLocals),
+    CI_ModuleInfo0 = !.Info ^ module_info,
+    goal_cannot_loop_or_throw(Goal, GoalCannotLoopOrThrow,
+        CI_ModuleInfo0, CI_ModuleInfo, !IO),
+    !:Info = !.Info ^ module_info := CI_ModuleInfo,
     (
         % Propagate goals that can fail and have no output
         % variables.  Propagating cc_nondet goals would be
@@ -428,8 +434,8 @@
         % Don't propagate impure goals.
         goal_info_is_pure(GoalInfo),

-        % Don't propagate goals that can loop or throw exceptions..
-        goal_cannot_loop_or_throw(ModuleInfo, Goal)
+        % Don't propagate goals that can loop or throw exceptions.
+        GoalCannotLoopOrThrow = no
     ->
         % It's a constraint, add it to the list of constraints
         % to be attached to goals earlier in the conjunction.
@@ -508,7 +514,7 @@
             | Goals0]
     ),
     annotate_conj_constraints(ModuleInfo, RevConjuncts0,
-        Constraints1, Goals1, Goals, !Info).
+        Constraints1, Goals1, Goals, !Info, !IO).

 :- pred add_empty_constraints(hlds_goal::in,
     pair(hlds_goal, list(constraint))::out) is det.
@@ -668,22 +674,23 @@
     %
 :- pred propagate_conj_constraints(constrained_conj::in,
     list(hlds_goal)::in, list(hlds_goal)::out,
-    constraint_info::in, constraint_info::out) is det.
+    constraint_info::in, constraint_info::out,
+    io::di, io::uo) is det.

-propagate_conj_constraints([], RevGoals, Goals, !Info) :-
+propagate_conj_constraints([], RevGoals, Goals, !Info, !IO) :-
     list__reverse(RevGoals, Goals).
 propagate_conj_constraints([Goal0 - Constraints0 | Goals0],
-        RevGoals0, RevGoals, !Info) :-
+        RevGoals0, RevGoals, !Info, !IO) :-
     filter_complex_constraints(Constraints0,
         SimpleConstraints, ComplexConstraints0),
-    propagate_conj_sub_goal(Goal0, SimpleConstraints, GoalList1, !Info),
+    propagate_conj_sub_goal(Goal0, SimpleConstraints, GoalList1, !Info, !IO),
     flatten_constraints(ComplexConstraints0, ComplexConstraints),
     list__reverse(ComplexConstraints, RevComplexConstraints),
     list__reverse(GoalList1, RevGoalList1),
     list__condense([RevComplexConstraints, RevGoalList1, RevGoals0],
         RevGoals1),
     constraint_info_update_goal(Goal0, !Info),
-    propagate_conj_constraints(Goals0, RevGoals1, RevGoals, !Info).
+    propagate_conj_constraints(Goals0, RevGoals1, RevGoals, !Info, !IO).

 :- pred filter_complex_constraints(list(constraint)::in,
     list(constraint)::out, list(constraint)::out) is det.
Index: compiler/deforest.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/deforest.m,v
retrieving revision 1.57
diff -u -r1.57 deforest.m
--- compiler/deforest.m	28 Nov 2005 04:11:40 -0000	1.57
+++ compiler/deforest.m	15 Feb 2006 08:04:51 -0000
@@ -208,7 +208,7 @@
         % Inlining may have created some opportunities for simplification.
         globals__io_get_globals(Globals, !IO),
         simplify__find_simplifications(no, Globals, Simplifications),
-        pd_util__simplify_goal(Simplifications, !Goal, !PDInfo),
+        pd_util__simplify_goal(Simplifications, !Goal, !PDInfo, !IO),

         pd_util__propagate_constraints(!Goal, !PDInfo, !IO),

@@ -1629,7 +1629,7 @@
     % Be a bit more aggressive with common structure elimination.
     % This helps achieve folding in some cases.
     Simplifications = [extra_common_struct | Simplifications0],
-    pd_util__simplify_goal(Simplifications, Goal2, Goal3, !PDInfo),
+    pd_util__simplify_goal(Simplifications, Goal2, Goal3, !PDInfo, !IO),
     pd_info_set_instmap(InstMap0, !PDInfo),

     % Perform any folding which may now be possible.
@@ -1858,7 +1858,7 @@
         pd_info_get_module_info(!.PDInfo, ModuleInfo),
         module_info_get_globals(ModuleInfo, Globals),
         simplify__find_simplifications(no, Globals, Simplifications),
-        pd_util__simplify_goal(Simplifications, Goal3, Goal4, !PDInfo),
+        pd_util__simplify_goal(Simplifications, Goal3, Goal4, !PDInfo, !IO),

         pd_info_get_cost_delta(!.PDInfo, CostDelta1),
         CostDelta = CostDelta1 - CostDelta0,
Index: compiler/exception_analysis.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/exception_analysis.m,v
retrieving revision 1.19
diff -u -r1.19 exception_analysis.m
--- compiler/exception_analysis.m	6 Feb 2006 05:39:41 -0000	1.19
+++ compiler/exception_analysis.m	15 Feb 2006 05:30:29 -0000
@@ -81,6 +81,7 @@
 :- import_module analysis.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
+:- import_module parse_tree.prog_data.

 :- import_module io.

@@ -96,6 +97,19 @@
 :- pred write_pragma_exceptions(module_info::in, exception_info::in,
     pred_id::in, io::di, io::uo) is det.

+    % Look the exception status of the given procedure.  This predicate
+    % is intended to be used by optimisations that use exception analysis
+    % information, *not* for use within the exception analysis itself.
+    % This predicate abstracts away differences between
+    % intermodule-optimization and intermodule-analysis.
+    %
+    % NOTE: if intermodule-analysis is enabled then this procedure will
+    %       update the IMDG as well.
+    %
+:- pred lookup_exception_analysis_result(pred_proc_id::in,
+    exception_status::out, module_info::in, module_info::out, io::di, io::uo)
+    is det.
+
 %----------------------------------------------------------------------------%
 %
 % Types and instances for the intermodule analysis framework
@@ -125,7 +139,6 @@
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.modules.
-:- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
@@ -1162,6 +1175,63 @@
     ).

 %----------------------------------------------------------------------------%
+%
+% External interface to exception analysis information
+%
+
+lookup_exception_analysis_result(PPId, ExceptionStatus, !ModuleInfo, !IO) :-
+    PPId = proc(PredId, _),
+    module_info_pred_info(!.ModuleInfo, PredId, PredInfo),
+    IsImported = pred_to_bool(pred_info_is_imported(PredInfo)),
+    globals.io_lookup_bool_option(intermodule_analysis, IntermodAnalysis,
+        !IO),
+    %
+    % If we the procedure we are calling is imported and we are using
+    % intermodule-analysis then we need to look up the exception status in the
+    % analysis registry; otherwise we look it up in the the exception_info
+    % table.
+    %
+    UseAnalysisRegistry = IsImported `bool.and` IntermodAnalysis,
+    (
+        % If the procedure is not imported then it's exception_status
+        % will be in the exception_info table.
+        UseAnalysisRegistry = no,
+        module_info_get_exception_info(!.ModuleInfo, ExceptionInfo),
+        (
+            map.search(ExceptionInfo, PPId, ProcExceptionInfo)
+        ->
+            ProcExceptionInfo = proc_exception_info(ExceptionStatus, _)
+        ;
+            ExceptionStatus = may_throw(user_exception)
+        )
+    ;
+        UseAnalysisRegistry = yes,
+        some [!AnalysisInfo] (
+            module_info_get_analysis_info(!.ModuleInfo, !:AnalysisInfo),
+            module_id_func_id(!.ModuleInfo, PPId, ModuleId, FuncId),
+            lookup_best_result(ModuleId, FuncId, any_call, MaybeBestStatus,
+                !AnalysisInfo, !IO),
+            (
+                MaybeBestStatus = yes({_Call, Answer, AnalysisStatus}),
+                ( AnalysisStatus = invalid ->
+                    % Don't make use of invalid analysis results.
+                    ExceptionStatus = may_throw(user_exception)
+                ;
+                    Answer = exception_analysis_answer(ExceptionStatus)
+                )
+            ;
+                MaybeBestStatus = no,
+                ExceptionStatus = may_throw(user_exception)
+            ),
+            module_info_get_name(!.ModuleInfo, ThisModuleName),
+            ThisModuleId = module_name_to_module_id(ThisModuleName),
+            record_dependency(ThisModuleId, analysis_name, ModuleId, FuncId,
+                any_call, !AnalysisInfo),
+            module_info_set_analysis_info(!.AnalysisInfo, !ModuleInfo)
+        )
+    ).
+
+%----------------------------------------------------------------------------%

 :- func this_file = string.

Index: compiler/goal_form.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_form.m,v
retrieving revision 1.24
diff -u -r1.24 goal_form.m
--- compiler/goal_form.m	1 Feb 2006 04:02:45 -0000	1.24
+++ compiler/goal_form.m	15 Feb 2006 13:38:32 -0000
@@ -5,14 +5,13 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-%
+
 % File: goal_form.m.
 % Main authors: conway, zs.
-%
+
 % A module that provides functions that check whether goals fulfill particular
 % criteria.
-%
-%
+
 %-----------------------------------------------------------------------------%

 :- module hlds__goal_form.
@@ -22,14 +21,41 @@
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.

-:- import_module list.
+:- import_module bool.
+:- import_module io.
+
+%-----------------------------------------------------------------------------%
+%
+% These versions use information from the intermodule-analysis framework
+%
+
+% XXX Eventually we will only use these versions and the others can be
+%     deleted.
+
+    % Return `yes' if the given goal cannot throw an exception; return `no'
+    % otherwise.
+    %
+    % This version differs from the ones below in that it can use results from
+    % the intermodule-analysis framework (if they are available).  The HLDS
+    % and I/O state need to be threaded through in case analysis files need to
+    % be read and in case IMDGs need to be updated.
+    %
+:- pred goal_cannot_throw(hlds_goal::in, bool::out,
+    module_info::in, module_info::out, io::di, io::uo) is det.
+
+    % Return `yes' if the goal cannot loop and cannot throw an exception;
+    % return `no' otherwise.
+    %
+:- pred goal_cannot_loop_or_throw(hlds_goal::in, bool::out, module_info::in,
+    module_info::out, io::di, io::uo) is det.

 %-----------------------------------------------------------------------------%

 %
 % The first three versions may be more accurate because they can use
 % results of the termination and exception analyses.
-%
+% XXX These don't work with the intermodule-analysis framework, so don't
+%     use them in new code.

     % Succeeds if the goal cannot loop forever.
     %
@@ -82,7 +108,7 @@
     % allocate heap space, such as construction of boxed constants.
     %
 :- pred goal_may_allocate_heap(hlds_goal::in) is semidet.
-:- pred goal_list_may_allocate_heap(list(hlds_goal)::in) is semidet.
+:- pred goal_list_may_allocate_heap(hlds_goals::in) is semidet.

     % Succeed if execution of the given goal cannot encounter a context
     % that causes any variable to be flushed to its stack slot.  If such a
@@ -129,15 +155,132 @@
 :- import_module hlds.hlds_data.
 :- import_module libs.compiler_util.
 :- import_module parse_tree.prog_data.
+:- import_module transform_hlds.exception_analysis.
 :- import_module transform_hlds.term_constr_main.
 :- import_module transform_hlds.term_util.

-:- import_module bool.
 :- import_module int.
+:- import_module list.
 :- import_module map.
 :- import_module std_util.

 %-----------------------------------------------------------------------------%
+%
+% A version of goal_cannot_loop_or_throw that uses results from the
+% intermodule-analysis framework
+%
+
+goal_cannot_throw(GoalExpr - GoalInfo, Result, !ModuleInfo, !IO) :-
+    goal_info_get_determinism(GoalInfo, Determinism),
+    ( Determinism \= erroneous ->
+        goal_cannot_throw_2(GoalExpr, GoalInfo, Result, !ModuleInfo, !IO)
+    ;
+        Result = no
+    ).
+
+:- pred goal_cannot_throw_2(hlds_goal_expr::in, hlds_goal_info::in,
+    bool::out, module_info::in, module_info::out, io::di, io::uo) is det.
+
+goal_cannot_throw_2(Goal, _GoalInfo, Result, !ModuleInfo, !IO) :-
+    (
+        Goal = conj(Goals)
+    ;
+        Goal = disj(Goals)
+    ;
+        Goal = par_conj(Goals)
+    ;
+        Goal = if_then_else(_, IfGoal, ThenGoal, ElseGoal),
+        Goals = [IfGoal, ThenGoal, ElseGoal]
+    ),
+    goals_cannot_throw(Goals, Result, !ModuleInfo, !IO).
+goal_cannot_throw_2(Goal, _GoalInfo, Result, !ModuleInfo, !IO) :-
+    Goal = call(PredId, ProcId, _, _, _, _),
+    lookup_exception_analysis_result(proc(PredId, ProcId),
+        Status, !ModuleInfo, !IO),
+    ( Status = will_not_throw ->
+        Result = yes
+    ;
+        Result = no
+    ).
+goal_cannot_throw_2(Goal, _GoalInfo, Result, !ModuleInfo, !IO) :-
+    % XXX We should use results form closure analysis here.
+    Goal = generic_call(_, _, _, _),
+    Result = no.
+goal_cannot_throw_2(Goal, _GoalInfo, Result, !ModuleInfo, !IO) :-
+    Goal = switch(_, _, Cases),
+    cases_cannot_throw(Cases, Result, !ModuleInfo, !IO).
+goal_cannot_throw_2(Goal, _GoalInfo, Result, !ModuleInfo, !IO) :-
+    Goal = unify(_, _, _, Uni, _),
+    % Complicated unifies are _non_builtin_
+    ( Uni = complicated_unify(_, _, _) ->
+        Result = no
+    ;
+        Result = yes
+    ).
+goal_cannot_throw_2(OuterGoal, _, Result, !ModuleInfo, !IO) :-
+    (
+        OuterGoal = not(InnerGoal)
+    ;
+        OuterGoal = scope(_, InnerGoal)
+    ),
+    goal_cannot_throw(InnerGoal, Result, !ModuleInfo, !IO).
+goal_cannot_throw_2(Goal, _, Result, !ModuleInfo, !IO) :-
+    Goal = foreign_proc(Attributes, _, _, _, _, _),
+    ExceptionStatus = may_throw_exception(Attributes),
+    (
+        (
+            ExceptionStatus = will_not_throw_exception
+        ;
+            ExceptionStatus = default_exception_behaviour,
+            may_call_mercury(Attributes) = will_not_call_mercury
+        )
+    ->
+        Result = yes
+    ;
+        Result = no
+    ).
+goal_cannot_throw_2(Goal, _, yes, !ModuleInfo, !IO) :-
+    Goal = shorthand(_).    % XXX maybe call unexpected/2 here.
+
+:- pred goals_cannot_throw(hlds_goals::in, bool::out,
+    module_info::in, module_info::out, io::di, io::uo) is det.
+
+goals_cannot_throw([], yes, !ModuleInfo, !IO).
+goals_cannot_throw([Goal | Goals], Result, !ModuleInfo, !IO) :-
+    goal_cannot_throw(Goal, Result0, !ModuleInfo, !IO),
+    (
+        Result0 = yes,
+        goals_cannot_throw(Goals, Result, !ModuleInfo, !IO)
+    ;
+        Result0 = no,
+        Result  = no
+    ).
+
+:- pred cases_cannot_throw(list(case)::in, bool::out,
+    module_info::in, module_info::out, io::di, io::uo) is det.
+
+cases_cannot_throw([], yes, !ModuleInfo, !IO).
+cases_cannot_throw([Case | Cases], Result, !ModuleInfo, !IO) :-
+    Case = case(_, Goal),
+    goal_cannot_throw(Goal, Result0, !ModuleInfo, !IO),
+    (
+        Result0 = yes,
+        cases_cannot_throw(Cases, Result, !ModuleInfo, !IO)
+    ;
+        Result0 = no,
+        Result  = no
+    ).
+
+goal_cannot_loop_or_throw(Goal, Result, !ModuleInfo, !IO) :-
+    % XXX this will need to change after the termination analyses are
+    %     converted to use the intermodule-analysis framework.
+    ( goal_cannot_loop(!.ModuleInfo, Goal) ->
+        goal_cannot_throw(Goal, Result, !ModuleInfo, !IO)
+    ;
+        Result = no
+    ).
+
+%-----------------------------------------------------------------------------%

 goal_cannot_loop(ModuleInfo, Goal) :-
     goal_cannot_loop_aux(yes(ModuleInfo), Goal).
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.121
diff -u -r1.121 goal_util.m
--- compiler/goal_util.m	25 Jan 2006 03:27:34 -0000	1.121
+++ compiler/goal_util.m	15 Feb 2006 13:27:36 -0000
@@ -14,7 +14,7 @@

 %-----------------------------------------------------------------------------%

-:- module hlds__goal_util.
+:- module hlds.goal_util.
 :- interface.

 :- import_module hlds.hlds_goal.
@@ -26,6 +26,7 @@

 :- import_module assoc_list.
 :- import_module bool.
+:- import_module io.
 :- import_module list.
 :- import_module map.
 :- import_module set.
@@ -52,10 +53,9 @@
     % insts of NewVar are taken from the insts of the corresponding
     % OutputVar in InstMapDelta (the initial inst is free).
     %
-:- pred create_renaming(list(prog_var)::in, instmap_delta::in,
+:- pred create_renaming(prog_vars::in, instmap_delta::in,
     vartypes::in, vartypes::out, prog_varset::in, prog_varset::out,
-    list(hlds_goal)::out, list(prog_var)::out,
-    prog_var_renaming::out) is det.
+    hlds_goals::out, prog_vars::out, prog_var_renaming::out) is det.

 % The predicates rename_var* take a structure and a mapping from var -> var
 % and apply that translation. If a var in the input structure does not
@@ -63,7 +63,7 @@

     % rename_vars_in_goals(MustRename, Substitution, GoalList, NewGoalList).
 :- pred rename_vars_in_goals(bool::in, prog_var_renaming::in,
-    list(hlds_goal)::in, list(hlds_goal)::out) is det.
+    hlds_goals::in, hlds_goals::out) is det.

 :- pred rename_vars_in_goal(prog_var_renaming::in,
     hlds_goal::in, hlds_goal::out) is det.
@@ -99,9 +99,8 @@
     % uniqueness in the type map for this reason - such is the sacrifice
     % for generality.)
     %
-:- pred create_variables(list(prog_var)::in, prog_varset::in,
-    vartypes::in, prog_varset::in, prog_varset::out,
-    vartypes::in, vartypes::out,
+:- pred create_variables(prog_vars::in, prog_varset::in, vartypes::in,
+    prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
     prog_var_renaming::in, prog_var_renaming::out) is det.

     % Return all the variables in the goal.
@@ -114,13 +113,12 @@
     % Unlike quantification.goal_vars, this predicate returns
     % even the explicitly quantified variables.
     %
-:- pred goals_goal_vars(list(hlds_goal)::in, set(prog_var)::in,
+:- pred goals_goal_vars(hlds_goals::in, set(prog_var)::in,
     set(prog_var)::out) is det.

     % Return all the variables in a generic call.
     %
-:- pred generic_call_vars(generic_call::in, list(prog_var)::out)
-    is det.
+:- pred generic_call_vars(generic_call::in, prog_vars::out) is det.

     % Attach the given goal features to the given goal and all its subgoals.
     %
@@ -145,9 +143,8 @@
     % i.e. a constraint which contrains an existentially quantified type
     % variable.
     %
-:- pred extra_nonlocal_typeinfos(rtti_varmaps::in,
-    vartypes::in, existq_tvars::in,
-    set(prog_var)::in, set(prog_var)::out) is det.
+:- pred extra_nonlocal_typeinfos(rtti_varmaps::in, vartypes::in,
+    existq_tvars::in, set(prog_var)::in, set(prog_var)::out) is det.

     % See whether the goal is a branched structure.
     %
@@ -159,7 +156,7 @@

     % Return an indication of the size of the list of goals.
     %
-:- pred goals_size(list(hlds_goal)::in, int::out) is det.
+:- pred goals_size(hlds_goals::in, int::out) is det.

     % Return an indication of the size of the list of clauses.
     %
@@ -201,7 +198,7 @@

     % Returns all the predids that are used in a list of goals.
     %
-:- pred predids_from_goals(list(hlds_goal)::in, list(pred_id)::out) is det.
+:- pred predids_from_goals(hlds_goals::in, list(pred_id)::out) is det.

     % Returns all the procedures that are used within a goal.
     %
@@ -214,9 +211,8 @@
     % This aborts if any of the constructors are existentially typed.
     %
 :- pred switch_to_disjunction(prog_var::in, list(case)::in,
-    instmap::in, list(hlds_goal)::out, prog_varset::in, prog_varset::out,
-    vartypes::in, vartypes::out,
-    module_info::in, module_info::out) is det.
+    instmap::in, hlds_goals::out, prog_varset::in, prog_varset::out,
+    vartypes::in, vartypes::out, module_info::in, module_info::out) is det.

     % Convert a case into a conjunction by adding a tag test
     % (deconstruction unification) to the case goal.
@@ -224,8 +220,7 @@
     %
 :- pred case_to_disjunct(prog_var::in, cons_id::in, hlds_goal::in,
     instmap::in, hlds_goal::out, prog_varset::in, prog_varset::out,
-    vartypes::in, vartypes::out,
-    module_info::in, module_info::out) is det.
+    vartypes::in, vartypes::out, module_info::in, module_info::out) is det.

     % Transform an if-then-else into ( Cond, Then ; \+ Cond, Else ),
     % since magic.m and rl_gen.m don't handle if-then-elses.
@@ -235,28 +230,67 @@

 %-----------------------------------------------------------------------------%

-    % can_reorder_goals(ModuleInfo, FullyStrict, Goal1, Goal2).
+    % can_reorder_goals(ModuleInfo, VarTypes, FullyStrict,
+    %   InstmapBeforeGoal1, Goal1, InstmapBeforegoal2, Goal2).
     %
     % Goals can be reordered if
     % - the goals are independent
     % - the goals are not impure
-    % - any possible change in termination behaviour is allowed
-    %   according to the semantics options.
+    % - any possible change in termination behaviour is allowed according
+    %   to the semantics options.
+    %
+    % NOTE: this version is deprecated; new code should use the following
+    %       version because it supports the intermodule-analysis framework.
     %
 :- pred can_reorder_goals(module_info::in, vartypes::in, bool::in,
     instmap::in, hlds_goal::in, instmap::in, hlds_goal::in) is semidet.

-    % reordering_maintains_termination(ModuleInfo,
-    %    FullyStrict, Goal1, Goal2)
+    % can_reorder_goals(VarTypes, FullyStrict, InstmapBeforeGoal1, Goal1,
+    %   InstmapBeforeGoal2, Goal2, Result, !ModuleInfo, !IO).
     %
-    % Succeeds if any possible change in termination behaviour from
-    % reordering the goals is allowed according to the semantics options.
-    % The information computed by termination analysis is used when
-    % making this decision.
+    % Result is `yes' if the goals can be reordered; no otherwise.
+    %
+    % Goals can be reordered if
+    % - the goals are independent
+    % - the goals are not impure
+    % - any possible change in termination behaviour is allowed according
+    %   to the semantics options.
+    %
+    % NOTE: new code should use this version as it supports the
+    %       intermodule-analysis framework.
+    %
+:- pred can_reorder_goals(vartypes::in, bool::in, instmap::in,
+    hlds_goal::in, instmap::in, hlds_goal::in, bool::out,
+    module_info::in, module_info::out, io::di, io::uo) is det.
+
+    % reordering_maintains_termination(ModuleInfo, FullyStrict, Goal1, Goal2).
+    %
+    % Succeeds if any possible change in termination behaviour from reordering
+    % the goals is allowed according to the semantics options.
+    % The information computed by termination and exception analyses is used
+    % when making this decision.
+    %
+    % NOTE: this version is deprecated; new code should use the following
+    %       version because it supports the intermodule-analysis framework.
     %
 :- pred reordering_maintains_termination(module_info::in, bool::in,
     hlds_goal::in, hlds_goal::in) is semidet.

+    % reordering_maintains_termination(FullyStrict, Goal1, Goal2, Result,
+    %   !ModuleInfo, !IO).
+    %
+    % Result is `yes' if any possible change in termination behaviour from
+    % reordering the goals is allowed according to the semantics options.
+    % The information computed by termination and exception analyses is used
+    % when making this decision.
+    %
+    % NOTE: new code should use this version as it supports the
+    %       intermodule-analysis framework.
+    %
+:- pred reordering_maintains_termination(bool::in, hlds_goal::in,
+    hlds_goal::in, bool::out, module_info::in, module_info::out,
+    io::di, io::uo) is det.
+
     % generate_simple_call(ModuleName, ProcName, PredOrFunc, ModeNo,
     %   Detism, Args, Features, InstMapDelta, ModuleInfo, Context,
     %   CallGoal):
@@ -272,7 +306,7 @@
     % from 0.
     %
 :- pred generate_simple_call(module_name::in, string::in,
-    pred_or_func::in, mode_no::in, determinism::in, list(prog_var)::in,
+    pred_or_func::in, mode_no::in, determinism::in, prog_vars::in,
     list(goal_feature)::in, assoc_list(prog_var, mer_inst)::in,
     module_info::in, term__context::in, hlds_goal::out) is det.

@@ -354,10 +388,9 @@
     list__reverse(RevNewVars, NewVars),
     list__reverse(RevUnifies, Unifies).

-:- pred create_renaming_2(list(prog_var)::in, instmap_delta::in,
+:- pred create_renaming_2(prog_vars::in, instmap_delta::in,
     vartypes::in, vartypes::out, prog_varset::in, prog_varset::out,
-    list(hlds_goal)::in, list(hlds_goal)::out,
-    list(prog_var)::in, list(prog_var)::out,
+    hlds_goals::in, hlds_goals::out, prog_vars::in, prog_vars::out,
     prog_var_renaming::in, prog_var_renaming::out) is det.

 create_renaming_2([], _, !VarTypes, !VarSet, !RevUnifies, !RevNewVars,
@@ -1059,7 +1092,7 @@
 goal_calls(GoalExpr - _, PredProcId) :-
     goal_expr_calls(GoalExpr, PredProcId).

-:- pred goals_calls(list(hlds_goal), pred_proc_id).
+:- pred goals_calls(hlds_goals, pred_proc_id).
 :- mode goals_calls(in, in) is semidet.
 :- mode goals_calls(in, out) is nondet.

@@ -1119,7 +1152,7 @@
 goal_calls_pred_id(GoalExpr - _, PredId) :-
     goal_expr_calls_pred_id(GoalExpr, PredId).

-:- pred goals_calls_pred_id(list(hlds_goal), pred_id).
+:- pred goals_calls_pred_id(hlds_goals, pred_id).
 :- mode goals_calls_pred_id(in, in) is semidet.
 :- mode goals_calls_pred_id(in, out) is nondet.

@@ -1196,7 +1229,7 @@
     Unify = construct(_, _, _, _, HowToConstruct, _, _),
     HowToConstruct = reuse_cell(_).

-:- pred goals_contain_reconstruction(list(hlds_goal)::in) is semidet.
+:- pred goals_contain_reconstruction(hlds_goals::in) is semidet.

 goals_contain_reconstruction(Goals) :-
     list__member(Goal, Goals),
@@ -1408,6 +1441,51 @@
     \+ goal_depends_on_earlier_goal(EarlierGoal, LaterGoal,
         InstmapBeforeLaterGoal, VarTypes, ModuleInfo).

+can_reorder_goals(VarTypes, FullyStrict, InstmapBeforeEarlierGoal,
+        EarlierGoal, InstmapBeforeLaterGoal, LaterGoal, CanReorder,
+        !ModuleInfo, !IO) :-
+
+    EarlierGoal = _ - EarlierGoalInfo,
+    LaterGoal = _ - LaterGoalInfo,
+
+    % Impure goals cannot be reordered.
+    ( goal_info_is_impure(EarlierGoalInfo) ->
+        CanReorder = no
+    ; goal_info_is_impure(LaterGoalInfo) ->
+        CanReorder = no
+    ;
+        reordering_maintains_termination(FullyStrict,
+            EarlierGoal, LaterGoal, MaintainsTermination, !ModuleInfo, !IO),
+        (
+            MaintainsTermination = no,
+            CanReorder = no
+        ;
+            MaintainsTermination = yes,
+            (
+                % Don't reorder the goals if the later goal depends on the
+                % outputs of the current goal.
+                %
+                goal_depends_on_earlier_goal(LaterGoal, EarlierGoal,
+                    InstmapBeforeEarlierGoal, VarTypes, !.ModuleInfo)
+            ->
+                CanReorder = no
+            ;
+                % Don't reorder the goals if the later goal changes the
+                % instantiatedness of any of the non-locals of the earlier
+                % goal. This is necessary if the later goal clobbers any of
+                % the non-locals of the earlier goal, and avoids rerunning
+                % full mode analysis in other cases.
+                %
+                goal_depends_on_earlier_goal(EarlierGoal, LaterGoal,
+                    InstmapBeforeLaterGoal, VarTypes, !.ModuleInfo)
+            ->
+                CanReorder = no
+            ;
+                CanReorder = yes
+            )
+        )
+    ).
+
 reordering_maintains_termination(ModuleInfo, FullyStrict,
         EarlierGoal, LaterGoal) :-
     EarlierGoal = _ - EarlierGoalInfo,
@@ -1437,7 +1515,43 @@
         true
     ).

+reordering_maintains_termination(FullyStrict, EarlierGoal, LaterGoal,
+        MaintainsTermination, !ModuleInfo, !IO) :-
+    EarlierGoal = _ - EarlierGoalInfo,
+    LaterGoal = _ - LaterGoalInfo,
+
+    goal_info_get_determinism(EarlierGoalInfo, EarlierDetism),
+    determinism_components(EarlierDetism, EarlierCanFail, _),
+    goal_info_get_determinism(LaterGoalInfo, LaterDetism),
+    determinism_components(LaterDetism, LaterCanFail, _),
+    %
+    % If --fully-strict was specified, don't convert (can_loop, can_fail) into
+    % (can_fail, can_loop).
     %
+    goal_cannot_loop_or_throw(EarlierGoal, EarlierCannotLoopOrThrow,
+        !ModuleInfo, !IO),
+    (
+        FullyStrict = yes,
+        EarlierCannotLoopOrThrow = no,
+        LaterCanFail = can_fail
+    ->
+        MaintainsTermination = no
+    ;
+        % Don't convert (can_fail, can_loop) into (can_loop, can_fail), since
+        % this could worsen the termination properties of the program.
+        %
+        goal_cannot_loop_or_throw(LaterGoal, LaterCannotLoopOrThrow,
+            !ModuleInfo, !IO),
+        (
+            EarlierCanFail = can_fail,
+            LaterCannotLoopOrThrow = no
+        ->
+            MaintainsTermination = no
+        ;
+            MaintainsTermination = yes
+        )
+    ).
+
     % If the earlier goal changes the instantiatedness of a variable
     % that is used in the later goal, then the later goal depends on
     % the earlier goal.
Index: compiler/pd_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pd_util.m,v
retrieving revision 1.45
diff -u -r1.45 pd_util.m
--- compiler/pd_util.m	28 Nov 2005 04:11:50 -0000	1.45
+++ compiler/pd_util.m	15 Feb 2006 13:47:07 -0000
@@ -31,6 +31,8 @@
 :- import_module set.
 :- import_module std_util.

+%-----------------------------------------------------------------------------%
+
     % Pick out the pred_proc_ids of the calls in a list of atomic goals.
     %
 :- pred goal_get_calls(hlds_goal::in, list(pred_proc_id)::out) is det.
@@ -44,7 +46,7 @@
     % Apply simplify.m to the goal.
     %
 :- pred simplify_goal(list(simplification)::in, hlds_goal::in,
-    hlds_goal::out, pd_info::in, pd_info::out) is det.
+    hlds_goal::out, pd_info::in, pd_info::out, io::di, io::uo) is det.

     % Apply unique_modes.m to the goal.
     %
@@ -86,7 +88,7 @@
     % information about the argument variables.
     %
 :- pred convert_branch_info(pd_branch_info(int)::in,
-    list(prog_var)::in, pd_branch_info(prog_var)::out) is det.
+    prog_vars::in, pd_branch_info(prog_var)::out) is det.

     % inst_MSG(InstA, InstB, InstC):
     %
@@ -130,7 +132,7 @@
     % which contain only conj, some, not and atomic goals, since deforest.m
     % only attempts to optimize those types of conjunctions.
     %
-:- pred goals_match(module_info::in, hlds_goal::in, list(prog_var)::in,
+:- pred goals_match(module_info::in, hlds_goal::in, prog_vars::in,
     list(mer_type)::in, hlds_goal::in, vartypes::in,
     map(prog_var, prog_var)::out, tsubst::out) is semidet.

@@ -142,10 +144,15 @@
     % - any possible change in termination behaviour is allowed
     %   according to the semantics options.
     %
+    % XXX use the intermodule-analysis framework here (and see if this
+    %     version can be merged with the similarly named predicate in
+    %     goal_util.m).
+    %
 :- pred can_reorder_goals(module_info::in, bool::in,
     hlds_goal::in, hlds_goal::in) is semidet.

 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%

 :- implementation.

@@ -205,7 +212,7 @@
         constraint_info_init(ModuleInfo0, VarTypes0, VarSet0, InstMap, CInfo0),
         Goal0 = _ - GoalInfo0,
         goal_info_get_nonlocals(GoalInfo0, NonLocals),
-        constraint__propagate_constraints_in_goal(!Goal, CInfo0, CInfo),
+        constraint__propagate_constraints_in_goal(!Goal, CInfo0, CInfo, !IO),
         constraint_info_deconstruct(CInfo, ModuleInfo, VarTypes, VarSet,
             Changed),
         pd_info_set_module_info(ModuleInfo, !PDInfo),
@@ -221,10 +228,10 @@
             rerun_det_analysis(!Goal, !PDInfo, !IO),
             module_info_get_globals(ModuleInfo, Globals),
             simplify__find_simplifications(no, Globals, Simplifications),
-            simplify_goal(Simplifications, !Goal, !PDInfo)
+            simplify_goal(Simplifications, !Goal, !PDInfo, !IO)
         ;
             % Use Goal0 rather than the output of propagate_constraints_in_goal
-            % because constraint propagation can make the % quantification
+            % because constraint propagation can make the quantification
             % information more conservative even if it doesn't optimize
             % anything.
             Changed = no,
@@ -236,7 +243,7 @@

 %-----------------------------------------------------------------------------%

-simplify_goal(Simplifications, Goal0, Goal, !PDInfo) :-
+simplify_goal(Simplifications, Goal0, Goal, !PDInfo, !IO) :-
     % Construct a simplify_info.
     pd_info_get_module_info(!.PDInfo, ModuleInfo0),
     module_info_get_globals(ModuleInfo0, Globals),
@@ -248,7 +255,7 @@
     simplify_info_init(DetInfo0, Simplifications, InstMap0, ProcInfo0,
         SimplifyInfo0),

-    simplify__process_goal(Goal0, Goal, SimplifyInfo0, SimplifyInfo),
+    simplify__process_goal(Goal0, Goal, SimplifyInfo0, SimplifyInfo, !IO),

     % Deconstruct the simplify_info.
     simplify_info_get_module_info(SimplifyInfo, ModuleInfo),
@@ -328,7 +335,7 @@
     get_goal_live_vars_2(ModuleInfo, NonLocalsList, InstMap, InstMapDelta,
         !Vars).

-:- pred get_goal_live_vars_2(module_info::in, list(prog_var)::in,
+:- pred get_goal_live_vars_2(module_info::in, prog_vars::in,
     instmap::in, instmap_delta::in,
     set(prog_var)::in, set(prog_var)::out) is det.

@@ -401,7 +408,7 @@
     VarInfo = pd_branch_info(BranchVarMap, LeftVars, OpaqueVars).

 :- pred convert_branch_info_2(assoc_list(int, set(int))::in,
-    list(prog_var)::in, pd_var_info::in, pd_var_info::out) is det.
+    prog_vars::in, pd_var_info::in, pd_var_info::out) is det.

 convert_branch_info_2([], _, !VarInfo).
 convert_branch_info_2([ArgNo - Branches | ArgInfos], Args,
@@ -481,7 +488,7 @@
     % in the branches, compute the argument numbers for which we have extra
     % information.
     %
-:- pred get_extra_info_headvars(list(prog_var)::in, int::in,
+:- pred get_extra_info_headvars(prog_vars::in, int::in,
     set(prog_var)::in, pd_var_info::in,
     branch_info_map(int)::in, branch_info_map(int)::out,
     set(int)::in, set(int)::out) is det.
@@ -530,7 +537,7 @@
         MaybeBranchInfo = no
     ).

-:- pred get_branch_vars_goal_2(module_info::in, list(hlds_goal)::in,
+:- pred get_branch_vars_goal_2(module_info::in, hlds_goals::in,
     bool::in, vartypes::in, instmap::in,
     set(prog_var)::in, set(prog_var)::out,
     pd_var_info::in, pd_var_info::out) is semidet.
@@ -643,7 +650,7 @@
     % Look at the goals in the branches for extra information.
     %
 :- pred get_sub_branch_vars_goal(pd_arg_info::in,
-    list(hlds_goal)::in, vartypes::in, instmap::in,
+    hlds_goals::in, vartypes::in, instmap::in,
     branch_info_map(prog_var)::in, branch_info_map(prog_var)::out,
     module_info::in, module_info::out) is det.

@@ -676,7 +683,7 @@
         VarTypes, InstMap, Vars2, SubVars, !ModuleInfo).

 :- pred examine_branch_list(module_info::in, pd_arg_info::in, int::in,
-    list(hlds_goal)::in, vartypes::in, instmap::in,
+    hlds_goals::in, vartypes::in, instmap::in,
     branch_info_map(prog_var)::in, branch_info_map(prog_var)::out) is det.

 examine_branch_list(_, _, _, [], _, _, !Vars).
@@ -708,7 +715,7 @@
         VarTypes, InstMap, !Vars, !ModuleInfo).

 :- pred examine_branch(module_info::in, pd_arg_info::in, int::in,
-    list(hlds_goal)::in, vartypes::in, instmap::in,
+    hlds_goals::in, vartypes::in, instmap::in,
     branch_info_map(prog_var)::in, branch_info_map(prog_var)::out) is det.

 examine_branch(_, _, _, [], _, _, !Vars).
@@ -740,7 +747,7 @@
     examine_branch(ModuleInfo, ProcArgInfo, BranchNo,
         Goals, VarTypes, InstMap1, !Vars).

-:- pred combine_vars(int::in, list(prog_var)::in,
+:- pred combine_vars(int::in, prog_vars::in,
     branch_info_map(prog_var)::in, branch_info_map(prog_var)::out) is det.

 combine_vars(_, [], !Vars).
@@ -966,7 +973,7 @@
     map__apply_to_list(NewArgs, NewVarTypes, NewArgTypes),
     type_list_subsumes(MatchingArgTypes, NewArgTypes, TypeSubn).

-:- pred collect_matching_arg_types(list(prog_var)::in, list(mer_type)::in,
+:- pred collect_matching_arg_types(prog_vars::in, list(mer_type)::in,
     map(prog_var, prog_var)::in, list(mer_type)::in, list(mer_type)::out)
     is det.

@@ -989,7 +996,7 @@
     % Check that the shape of the goals matches, and that there is a mapping
     % from the variables in the old goal to the variables in the new goal.
     %
-:- pred goals_match_2(list(hlds_goal)::in, list(hlds_goal)::in,
+:- pred goals_match_2(hlds_goals::in, hlds_goals::in,
     map(prog_var, prog_var)::in, map(prog_var, prog_var)::out) is semidet.

 goals_match_2([], [], !ONRenaming).
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.162
diff -u -r1.162 simplify.m
--- compiler/simplify.m	27 Jan 2006 05:52:05 -0000	1.162
+++ compiler/simplify.m	15 Feb 2006 13:42:42 -0000
@@ -56,10 +56,11 @@

 :- pred simplify_proc_return_msgs(list(simplification)::in, pred_id::in,
     proc_id::in, module_info::in, module_info::out,
-    proc_info::in, proc_info::out, set(context_det_msg)::out) is det.
+    proc_info::in, proc_info::out, set(context_det_msg)::out,
+    io::di, io::uo) is det.

 :- pred process_goal(hlds_goal::in, hlds_goal::out,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

     % Find out which simplifications should be run from the options table
     % stored in the globals. The first argument states whether warnings
@@ -144,7 +145,7 @@
     ),
     MaybeMsgs0 = no,
     simplify_procs(Simplifications, PredId, ProcIds, !ModuleInfo, !PredInfo,
-        MaybeMsgs0, MaybeMsgs),
+        MaybeMsgs0, MaybeMsgs, !IO),
     (
         MaybeMsgs = yes(Msgs0 - Msgs1),
         set__union(Msgs0, Msgs1, Msgs2),
@@ -162,15 +163,16 @@
     list(proc_id)::in, module_info::in, module_info::out,
     pred_info::in, pred_info::out,
     maybe(pair(set(context_det_msg)))::in,
-    maybe(pair(set(context_det_msg)))::out) is det.
+    maybe(pair(set(context_det_msg)))::out,
+    io::di, io::uo) is det.

-simplify_procs(_, _, [], !ModuleInfo, !PredInfo, !Msgs).
+simplify_procs(_, _, [], !ModuleInfo, !PredInfo, !Msgs, !IO).
 simplify_procs(Simplifications, PredId, [ProcId | ProcIds], !ModuleInfo,
-        !PredInfo, !MaybeMsgs) :-
+        !PredInfo, !MaybeMsgs, !IO) :-
     pred_info_procedures(!.PredInfo, Procs0),
     map__lookup(Procs0, ProcId, Proc0),
     simplify_proc_return_msgs(Simplifications, PredId, ProcId,
-        !ModuleInfo, Proc0, Proc, ProcMsgSet),
+        !ModuleInfo, Proc0, Proc, ProcMsgSet, !IO),
     map__det_update(Procs0, ProcId, Proc, Procs),
     pred_info_set_procedures(Procs, !PredInfo),
     set__to_sorted_list(ProcMsgSet, ProcMsgs),
@@ -189,15 +191,15 @@
         !:MaybeMsgs = yes(ProcAnyModeMsgSet - ProcAllModeMsgSet)
     ),
     simplify_procs(Simplifications, PredId, ProcIds, !ModuleInfo, !PredInfo,
-        !MaybeMsgs).
+        !MaybeMsgs, !IO).

 simplify_proc(Simplifications, PredId, ProcId, !ModuleInfo, !Proc, !IO)  :-
     write_pred_progress_message("% Simplifying ", PredId, !.ModuleInfo, !IO),
     simplify_proc_return_msgs(Simplifications, PredId, ProcId, !ModuleInfo,
-        !Proc, _).
+        !Proc, _, !IO).

 simplify_proc_return_msgs(Simplifications, PredId, ProcId, !ModuleInfo,
-        !ProcInfo, DetMsgs) :-
+        !ProcInfo, DetMsgs, !IO) :-
     module_info_get_globals(!.ModuleInfo, Globals),
     proc_info_vartypes(!.ProcInfo, VarTypes0),
     det_info_init(!.ModuleInfo, VarTypes0, PredId, ProcId, Globals,
@@ -221,7 +223,7 @@
         Goal1 = Goal0
     ),

-    process_goal(Goal1, Goal, Info0, Info),
+    process_goal(Goal1, Goal, Info0, Info, !IO),

     simplify_info_get_varset(Info, VarSet),
     simplify_info_get_var_types(Info, VarTypes),
@@ -264,7 +266,7 @@
         DetMsgs = DetMsgs1
     ).

-process_goal(Goal0, Goal, !Info) :-
+process_goal(Goal0, Goal, !Info, !IO) :-
     simplify_info_get_simplifications(!.Info, Simplifications0),
     simplify_info_get_instmap(!.Info, InstMap0),

@@ -279,7 +281,7 @@
         set__delete_list(Simplifications0, NotOnFirstPass, Simplifications1),
         simplify_info_set_simplifications(Simplifications1, !Info),

-        do_process_goal(Goal0, Goal1, !Info),
+        do_process_goal(Goal0, Goal1, !Info, !IO),

         NotOnSecondPass = [warn_simple_code, warn_duplicate_calls,
             common_struct, duplicate_calls],
@@ -290,14 +292,14 @@
     ),
     % On the second pass do excess assignment elimination and some cleaning up
     % after the common structure pass.
-    do_process_goal(Goal1, Goal, !Info).
+    do_process_goal(Goal1, Goal, !Info, !IO).

 :- pred do_process_goal(hlds_goal::in, hlds_goal::out,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

-do_process_goal(Goal0, Goal, !Info) :-
+do_process_goal(Goal0, Goal, !Info, !IO) :-
     simplify_info_get_instmap(!.Info, InstMap0),
-    simplify_goal(Goal0, Goal1, !Info),
+    simplify_goal(Goal0, Goal1, !Info, !IO),
     simplify_info_get_varset(!.Info, VarSet0),
     simplify_info_get_var_types(!.Info, VarTypes0),
     ( simplify_info_requantify(!.Info) ->
@@ -393,12 +395,16 @@
 %-----------------------------------------------------------------------------%

 :- pred simplify_goal(hlds_goal::in, hlds_goal::out,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

-simplify_goal(Goal0, Goal - GoalInfo, !Info) :-
+simplify_goal(Goal0, Goal - GoalInfo, !Info, !IO) :-
     Goal0 = _ - GoalInfo0,
     goal_info_get_determinism(GoalInfo0, Detism),
     simplify_info_get_det_info(!.Info, DetInfo),
+    simplify_info_get_module_info(!.Info, ModuleInfo0),
+    goal_cannot_loop_or_throw(Goal0, Goal0CannotLoopOrThrow, ModuleInfo0,
+        ModuleInfo, !IO),
+    simplify_info_set_module_info(ModuleInfo, !Info),
     (
         %
         % if --no-fully-strict,
@@ -408,7 +414,7 @@
         % ensure goal is pure or semipure
         \+ goal_info_is_impure(GoalInfo0),
         ( det_info_get_fully_strict(DetInfo, no)
-        ; goal_cannot_loop_or_throw(Goal0)
+        ; Goal0CannotLoopOrThrow = yes
         )
     ->
         % warn about this, unless the goal was an explicit
@@ -456,7 +462,7 @@
         % ensure goal is pure or semipure
         \+ goal_info_is_impure(GoalInfo0),
         ( det_info_get_fully_strict(DetInfo, no)
-        ; goal_cannot_loop_or_throw(Goal0)
+        ; Goal0CannotLoopOrThrow = yes
         )
     ->
 % The following warning is disabled, because it often results in spurious
@@ -521,7 +527,7 @@
     ),
     simplify_info_maybe_clear_structs(before, Goal2, !Info),
     Goal2 = GoalExpr2 - GoalInfo2,
-    simplify_goal_2(GoalExpr2, Goal, GoalInfo2, GoalInfo3, !Info),
+    simplify_goal_2(GoalExpr2, Goal, GoalInfo2, GoalInfo3, !Info, !IO),
     simplify_info_maybe_clear_structs(after, Goal - GoalInfo3, !Info),
     enforce_invariant(GoalInfo3, GoalInfo, !Info).

@@ -558,12 +564,12 @@

 :- pred simplify_goal_2(hlds_goal_expr::in, hlds_goal_expr::out,
     hlds_goal_info::in, hlds_goal_info::out,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

-simplify_goal_2(conj(Goals0), Goal, GoalInfo0, GoalInfo, !Info) :-
+simplify_goal_2(conj(Goals0), Goal, GoalInfo0, GoalInfo, !Info, !IO) :-
     simplify_info_get_instmap(!.Info, InstMap0),
     excess_assigns_in_conj(GoalInfo0, Goals0, Goals1, !Info),
-    simplify_conj(Goals1, [], Goals, GoalInfo0, !Info),
+    simplify_conj(Goals1, [], Goals, GoalInfo0, !Info, !IO),
     simplify_info_set_instmap(InstMap0, !Info),
     (
         Goals = [],
@@ -597,26 +603,27 @@
         GoalInfo = GoalInfo0
     ).

-simplify_goal_2(par_conj(Goals0), Goal, GoalInfo0, GoalInfo, !Info) :-
+simplify_goal_2(par_conj(Goals0), Goal, GoalInfo0, GoalInfo, !Info, !IO) :-
     (
         Goals0 = [],
         goal_info_get_context(GoalInfo0, Context),
         true_goal(Context, Goal - GoalInfo)
     ;
         Goals0 = [SingleGoal0],
-        simplify_goal(SingleGoal0, SingleGoal - SingleGoalInfo, !Info),
+        simplify_goal(SingleGoal0, SingleGoal - SingleGoalInfo, !Info, !IO),
         maybe_wrap_goal(GoalInfo0, SingleGoalInfo, SingleGoal, Goal, GoalInfo,
             !Info)
     ;
         Goals0 = [_, _ | _],
         GoalInfo = GoalInfo0,
-        simplify_par_conj(Goals0, Goals, !.Info, !Info),
+        simplify_par_conj(Goals0, Goals, !.Info, !Info, !IO),
         Goal = par_conj(Goals)
     ).

-simplify_goal_2(disj(Disjuncts0), Goal, GoalInfo0, GoalInfo, !Info) :-
+simplify_goal_2(disj(Disjuncts0), Goal, GoalInfo0, GoalInfo, !Info, !IO) :-
     simplify_info_get_instmap(!.Info, InstMap0),
-    simplify_disj(Disjuncts0, [], Disjuncts, [], InstMaps, !.Info, !Info),
+    simplify_disj(Disjuncts0, [], Disjuncts, [], InstMaps, !.Info, !Info,
+        !IO),
     (
         Disjuncts = [],
         goal_info_get_context(GoalInfo0, Context),
@@ -662,7 +669,7 @@
     ).

 simplify_goal_2(switch(Var, SwitchCanFail0, Cases0), Goal,
-        GoalInfo0, GoalInfo, !Info) :-
+        GoalInfo0, GoalInfo, !Info, !IO) :-
     simplify_info_get_instmap(!.Info, InstMap0),
     simplify_info_get_module_info(!.Info, ModuleInfo0),
     instmap__lookup_var(InstMap0, Var, VarInst),
@@ -676,7 +683,7 @@
         MaybeConsIds = no
     ),
     simplify_switch(Var, Cases1, [], Cases, [], InstMaps,
-        SwitchCanFail0, SwitchCanFail, !.Info, !Info),
+        SwitchCanFail0, SwitchCanFail, !.Info, !Info, !IO),
     (
         Cases = [],
         % An empty switch always fails.
@@ -780,7 +787,7 @@
         true
     ).

-simplify_goal_2(Goal0, Goal, GoalInfo, GoalInfo, !Info) :-
+simplify_goal_2(Goal0, Goal, GoalInfo, GoalInfo, !Info, !IO) :-
     Goal0 = generic_call(GenericCall, Args, Modes, Det),
     (
         simplify_do_calls(!.Info),
@@ -807,7 +814,7 @@
         Goal = Goal0
     ).

-simplify_goal_2(Goal0, Goal, GoalInfo0, GoalInfo, !Info) :-
+simplify_goal_2(Goal0, Goal, GoalInfo0, GoalInfo, !Info, !IO) :-
     Goal0 = call(PredId, ProcId, Args, IsBuiltin, _, _),
     simplify_info_get_module_info(!.Info, ModuleInfo),
     module_info_pred_info(ModuleInfo, PredId, PredInfo),
@@ -838,7 +845,7 @@
             GoalInfo0, GoalInfo, !Info)
     ).

-simplify_goal_2(Goal0, Goal, GoalInfo0, GoalInfo, !Info) :-
+simplify_goal_2(Goal0, Goal, GoalInfo0, GoalInfo, !Info, !IO) :-
     Goal0 = unify(LT0, RT0, M, U0, C),
     (
         % A unification of the form X = X can be safely
@@ -866,7 +873,7 @@
         simplify_info_set_common_info(common_info_init, !Info),

         % Don't attempt to pass structs out of lambda_goals.
-        simplify_goal(LambdaGoal0, LambdaGoal, !Info),
+        simplify_goal(LambdaGoal0, LambdaGoal, !Info, !IO),
         simplify_info_set_common_info(Common1, !Info),
         simplify_info_set_instmap(InstMap1, !Info),
         RT = lambda_goal(Purity, PredOrFunc, EvalMethod, FixModes,
@@ -879,7 +886,7 @@
     ->
         ( RT0 = var(V) ->
             process_compl_unify(LT0, V, UniMode, CanFail, TypeInfoVars, C,
-                GoalInfo0, Goal1, !Info),
+                GoalInfo0, Goal1, !Info, !IO),
             Goal1 = Goal - GoalInfo
         ;
             unexpected(this_file, "invalid RHS for complicated unify")
@@ -909,7 +916,7 @@
     ).

 simplify_goal_2(if_then_else(Vars, Cond0, Then0, Else0), Goal,
-        GoalInfo0, GoalInfo, !Info) :-
+        GoalInfo0, GoalInfo, !Info, !IO) :-
     % (A -> B ; C) is logically equivalent to (A, B ; ~A, C).
     % If the determinism of A means that one of these disjuncts
     % cannot succeed, then we replace the if-then-else with the
@@ -942,7 +949,7 @@
         goal_to_conj_list(Cond0, CondList),
         goal_to_conj_list(Then0, ThenList),
         list__append(CondList, ThenList, List),
-        simplify_goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info),
+        simplify_goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info, !IO),
         goal_info_get_context(GoalInfo0, Context),
         Msg = ite_cond_cannot_fail,
         ContextMsg = context_det_msg(Context, Msg),
@@ -985,7 +992,7 @@
         ),
         goal_to_conj_list(Else0, ElseList),
         List = [Cond | ElseList],
-        simplify_goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info),
+        simplify_goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info, !IO),
         goal_info_get_context(GoalInfo0, Context),
         Msg = ite_cond_cannot_succeed,
         ContextMsg = context_det_msg(Context, Msg),
@@ -997,7 +1004,7 @@
         goal_to_conj_list(Cond0, CondList),
         goal_to_conj_list(Then0, ThenList),
         list__append(CondList, ThenList, List),
-        simplify_goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info),
+        simplify_goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info, !IO),
         simplify_info_set_requantify(!Info),
         simplify_info_set_rerun_det(!Info)
     ;
@@ -1007,11 +1014,11 @@
         %
         Info0 = !.Info,
         simplify_info_get_instmap(!.Info, InstMap0),
-        simplify_goal(Cond0, Cond, !Info),
+        simplify_goal(Cond0, Cond, !Info, !IO),
         simplify_info_update_instmap(Cond, !Info),
-        simplify_goal(Then0, Then, !Info),
+        simplify_goal(Then0, Then, !Info, !IO),
         simplify_info_post_branch_update(Info0, !Info),
-        simplify_goal(Else0, Else, !Info),
+        simplify_goal(Else0, Else, !Info, !IO),
         simplify_info_post_branch_update(Info0, !Info),
         Cond = _ - CondInfo,
         goal_info_get_instmap_delta(CondInfo, CondDelta),
@@ -1048,7 +1055,8 @@
             )
         ->
             simplify_info_undo_goal_updates(Info0, !Info),
-            simplify_goal_2(IfThenElse, Goal, GoalInfo1, GoalInfo, !Info)
+            simplify_goal_2(IfThenElse, Goal, GoalInfo1, GoalInfo, !Info,
+                !IO)
         ;
             (
                 % If-then-elses that are det or semidet may nevertheless
@@ -1073,11 +1081,11 @@
         )
     ).

-simplify_goal_2(not(Goal0), Goal, GoalInfo0, GoalInfo, !Info) :-
+simplify_goal_2(not(Goal0), Goal, GoalInfo0, GoalInfo, !Info, !IO) :-
     % 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(!.Info, Common),
-    simplify_goal(Goal0, Goal1, !Info),
+    simplify_goal(Goal0, Goal1, !Info, !IO),
     simplify_info_set_common_info(Common, !Info),
     Goal1 = _ - GoalInfo1,
     goal_info_get_determinism(GoalInfo1, Detism),
@@ -1120,9 +1128,9 @@
     ).

 simplify_goal_2(scope(Reason0, Goal1), GoalExpr, SomeInfo, GoalInfo,
-        !Info) :-
+        !Info, !IO) :-
     simplify_info_get_common_info(!.Info, Common),
-    simplify_goal(Goal1, Goal2, !Info),
+    simplify_goal(Goal1, Goal2, !Info, !IO),
     nested_scopes(Reason0, Goal2, SomeInfo, Goal),
     Goal = GoalExpr - GoalInfo,
     ( Goal = scope(FinalReason, _) - _ ->
@@ -1168,7 +1176,7 @@
         true
     ).

-simplify_goal_2(Goal0, Goal, GoalInfo, GoalInfo, !Info) :-
+simplify_goal_2(Goal0, Goal, GoalInfo, GoalInfo, !Info, !IO) :-
     Goal0 = foreign_proc(_, PredId, ProcId, Args, ExtraArgs, _),
     (
         simplify_do_calls(!.Info),
@@ -1182,7 +1190,7 @@
         Goal = Goal0
     ).

-simplify_goal_2(shorthand(_), _, _, _, !Info) :-
+simplify_goal_2(shorthand(_), _, _, _, _, _, _, _) :-
     % These should have been expanded out by now.
     unexpected(this_file, "goal_2: unexpected shorthand").

@@ -1404,10 +1412,11 @@

 :- pred process_compl_unify(prog_var::in, prog_var::in, uni_mode::in,
     can_fail::in, list(prog_var)::in, unify_context::in, hlds_goal_info::in,
-    hlds_goal::out, simplify_info::in, simplify_info::out) is det.
+    hlds_goal::out, simplify_info::in, simplify_info::out,
+    io::di, io::uo) is det.

 process_compl_unify(XVar, YVar, UniMode, CanFail, _OldTypeInfoVars, Context,
-        GoalInfo0, Goal, !Info) :-
+        GoalInfo0, Goal, !Info, !IO) :-
     simplify_info_get_module_info(!.Info, ModuleInfo),
     simplify_info_get_var_types(!.Info, VarTypes),
     map__lookup(VarTypes, XVar, Type),
@@ -1430,7 +1439,7 @@
         generate_simple_call(mercury_private_builtin_module,
             "builtin_unify_pred", predicate, mode_no(0), semidet,
             [XVar, YVar], [], [], ModuleInfo, GContext, Call0 - _),
-        simplify_goal_2(Call0, Call1, GoalInfo0, GoalInfo, !Info),
+        simplify_goal_2(Call0, Call1, GoalInfo0, GoalInfo, !Info, !IO),
         Call = Call1 - GoalInfo,
         ExtraGoals = []
     ;
@@ -1476,7 +1485,8 @@
             make_type_info_vars(TypeArgs, TypeInfoVars, ExtraGoals, !Info),
             call_specific_unify(TypeCtor, TypeInfoVars, XVar, YVar, ProcId,
                 ModuleInfo, Context, GoalInfo0, Call0, CallGoalInfo0),
-            simplify_goal_2(Call0, Call1, CallGoalInfo0, CallGoalInfo1, !Info),
+            simplify_goal_2(Call0, Call1, CallGoalInfo0, CallGoalInfo1, !Info,
+                !IO),
             Call = Call1 - CallGoalInfo1
         )
     ),
@@ -1736,25 +1746,25 @@

 :- pred simplify_conj(list(hlds_goal)::in, list(hlds_goal)::in,
     list(hlds_goal)::out, hlds_goal_info::in,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

-simplify_conj([], RevGoals, Goals, _, !Info) :-
+simplify_conj([], RevGoals, Goals, _, !Info, !IO) :-
     list__reverse(RevGoals, Goals).
-simplify_conj([Goal0 | Goals0], !.RevGoals, Goals, ConjInfo, !Info) :-
+simplify_conj([Goal0 | Goals0], !.RevGoals, Goals, ConjInfo, !Info, !IO) :-
     Info0 = !.Info,
     % Flatten conjunctions.
     ( Goal0 = conj(SubGoals) - _ ->
         list__append(SubGoals, Goals0, Goals1),
-        simplify_conj(Goals1, !.RevGoals, Goals, ConjInfo, !Info)
+        simplify_conj(Goals1, !.RevGoals, Goals, ConjInfo, !Info, !IO)
     ;
-        simplify_goal(Goal0, Goal1, !Info),
+        simplify_goal(Goal0, Goal1, !Info, !IO),
         (
             % Flatten conjunctions.
             Goal1 = conj(SubGoals1) - _
         ->
             simplify_info_undo_goal_updates(Info0, !Info),
             list__append(SubGoals1, Goals0, Goals1),
-            simplify_conj(Goals1, !.RevGoals, Goals, ConjInfo, !Info)
+            simplify_conj(Goals1, !.RevGoals, Goals, ConjInfo, !Info, !IO)
         ;
             % Delete unreachable goals.
             (
@@ -1791,7 +1801,7 @@
         ;
             conjoin_goal_and_rev_goal_list(Goal1, !RevGoals),
             simplify_info_update_instmap(Goal1, !Info),
-            simplify_conj(Goals0, !.RevGoals, Goals, ConjInfo, !Info)
+            simplify_conj(Goals0, !.RevGoals, Goals, ConjInfo, !Info, !IO)
         )
     ).

@@ -1809,13 +1819,14 @@
 %-----------------------------------------------------------------------------%

 :- pred simplify_par_conj(list(hlds_goal)::in, list(hlds_goal)::out,
-    simplify_info::in, simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::in, simplify_info::out,
+    io::di, io::uo) is det.

-simplify_par_conj([], [], _, !Info).
-simplify_par_conj([Goal0 |Goals0], [Goal | Goals], Info0, !Info) :-
-    simplify_goal(Goal0, Goal, !Info),
+simplify_par_conj([], [], _, !Info, !IO).
+simplify_par_conj([Goal0 |Goals0], [Goal | Goals], Info0, !Info, !IO) :-
+    simplify_goal(Goal0, Goal, !Info, !IO),
     simplify_info_post_branch_update(Info0, !Info),
-    simplify_par_conj(Goals0, Goals, Info0, !Info).
+    simplify_par_conj(Goals0, Goals, Info0, !Info, !IO).

 %-----------------------------------------------------------------------------%

@@ -1954,12 +1965,12 @@
 :- pred simplify_switch(prog_var::in, list(case)::in, list(case)::in,
     list(case)::out, list(instmap_delta)::in, list(instmap_delta)::out,
     can_fail::in, can_fail::out, simplify_info::in,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

-simplify_switch(_, [], RevCases, Cases, !InstMaps, !CanFail, _, !Info) :-
+simplify_switch(_, [], RevCases, Cases, !InstMaps, !CanFail, _, !Info, !IO) :-
     list__reverse(RevCases, Cases).
 simplify_switch(Var, [Case0 | Cases0], RevCases0, Cases, !InstMaps,
-        !CanFail, Info0, !Info) :-
+        !CanFail, Info0, !Info, !IO) :-
     simplify_info_get_instmap(Info0, InstMap0),
     Case0 = case(ConsId, Goal0),
     simplify_info_get_module_info(!.Info, ModuleInfo0),
@@ -1969,7 +1980,7 @@
         ModuleInfo0, ModuleInfo1),
     simplify_info_set_module_info(ModuleInfo1, !Info),
     simplify_info_set_instmap(InstMap1, !Info),
-    simplify_goal(Goal0, Goal, !Info),
+    simplify_goal(Goal0, Goal, !Info, !IO),

         % Remove failing branches.
     ( Goal = disj([]) - _ ->
@@ -1998,7 +2009,7 @@

     simplify_info_post_branch_update(Info0, !Info),
     simplify_switch(Var, Cases0, RevCases, Cases, !InstMaps, !CanFail, Info0,
-        !Info).
+        !Info, !IO).

     % Create a semidet unification at the start of a singleton case
     % in a can_fail switch.
@@ -2053,13 +2064,14 @@
 :- pred simplify_disj(list(hlds_goal)::in, list(hlds_goal)::in,
     list(hlds_goal)::out,
     list(instmap_delta)::in, list(instmap_delta)::out,
-    simplify_info::in, simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::in, simplify_info::out,
+    io::di, io::uo) is det.

-simplify_disj([], RevGoals, Goals, !PostBranchInstMaps, _, !Info) :-
+simplify_disj([], RevGoals, Goals, !PostBranchInstMaps, _, !Info, !IO) :-
     list__reverse(RevGoals, Goals).
 simplify_disj([Goal0 | Goals0], RevGoals0, Goals, !PostBranchInstMaps,
-        Info0, !Info) :-
-    simplify_goal(Goal0, Goal, !Info),
+        Info0, !Info, !IO) :-
+    simplify_goal(Goal0, Goal, !Info, !IO),
     Goal = _ - GoalInfo,

     (
@@ -2108,7 +2120,8 @@
     ),

     simplify_info_post_branch_update(Info0, !Info),
-    simplify_disj(Goals0, RevGoals1, Goals, !PostBranchInstMaps, Info0, !Info).
+    simplify_disj(Goals0, RevGoals1, Goals, !PostBranchInstMaps, Info0, !Info,
+        !IO).

     % Disjunctions that cannot succeed more than once when viewed from the
     % outside generally need some fixing up, and/or some warnings to be issued.
@@ -2140,11 +2153,11 @@
     %
 :- pred fixup_disj(list(hlds_goal)::in, determinism::in, bool::in,
     hlds_goal_info::in, hlds_goal_expr::out,
-    simplify_info::in, simplify_info::out) is det.
+    simplify_info::in, simplify_info::out, io::di, io::uo) is det.

-fixup_disj(Disjuncts, _, _OutputVars, GoalInfo, Goal, !Info) :-
+fixup_disj(Disjuncts, _, _OutputVars, GoalInfo, Goal, !Info, !IO) :-
     det_disj_to_ite(Disjuncts, GoalInfo, IfThenElse),
-    simplify_goal(IfThenElse, Simplified, !Info),
+    simplify_goal(IfThenElse, Simplified, !Info, !IO),
     Simplified = Goal - _.

     % det_disj_to_ite is used to transform disjunctions that occur
Index: compiler/size_prof.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/size_prof.m,v
retrieving revision 1.30
diff -u -r1.30 size_prof.m
--- compiler/size_prof.m	28 Nov 2005 04:11:54 -0000	1.30
+++ compiler/size_prof.m	15 Feb 2006 08:06:12 -0000
@@ -221,22 +221,22 @@
         hlds_out__write_pred_proc_id(!.ModuleInfo, PredId, ProcId, !IO),
         io__write_string(": ", !IO),
         process_proc(Transform, PredId, ProcId, ProcInfo0, ProcInfo,
-            !ModuleInfo),
+            !ModuleInfo, !IO),
         io__write_string("done.\n", !IO)
     ;
         VeryVerbose = no,
         process_proc(Transform, PredId, ProcId, ProcInfo0, ProcInfo,
-            !ModuleInfo)
+            !ModuleInfo, !IO)
     ).

 :- pred process_proc(construct_transform::in, pred_id::in, proc_id::in,
-    proc_info::in, proc_info::out, module_info::in, module_info::out)
-    is det.
+    proc_info::in, proc_info::out, module_info::in, module_info::out,
+    io::di, io::uo) is det.

-process_proc(Transform, PredId, ProcId, !ProcInfo, !ModuleInfo) :-
+process_proc(Transform, PredId, ProcId, !ProcInfo, !ModuleInfo, !IO) :-
     Simplifications = [],
     simplify_proc_return_msgs(Simplifications, PredId, ProcId,
-        !ModuleInfo, !ProcInfo, _Msgs),
+        !ModuleInfo, !ProcInfo, _Msgs, !IO),

     proc_info_goal(!.ProcInfo, Goal0),
     proc_info_varset(!.ProcInfo, VarSet0),

--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list