[m-rev.] for review: lookup disjunctions and model_non lookup switches

Zoltan Somogyi zs at csse.unimelb.edu.au
Tue Sep 29 15:08:02 AEST 2009


For review by anyone.

Zoltan.

Implement lookup disjunctions and model_non lookup switches.

compiler/ml_disj_gen.m:
	New module that looks after code generation for disjunctions.
	Note the link to disj_gen.m.

	Part of the code in it comes from ml_code_gen.m, but the part that
	implements lookup disjunctions is new, and its bulk is what justifies
	a separate module.

	Even the old code has been restructured to make the decision
	about whether this is a model_non disj or not just once, instead
	of once for every single disjunct.

compiler/ml_backend.m:
compiler/notes/compiler_design.html:
	Mention the new module.

compiler/mlds.m:
	Use a purpose-specific type instead of a bool to represent
	whether a loop can loop zero times.

compiler/ml_code_gen.m:
	Remove the code moved to ml_disj_gen.m.

	Improve the style of the ml_gen_maybe_convert_goal_code_model
	predicate.

compiler/ml_lookup_switch.m:
	Implement model_non lookup switches.

	Note the link to lookup_switch.m.

	Give better names to some predicates and variables.

	Remove the predicates moved to ml_code_util.m, goal_form.m and
	ml_util.m.

compiler/switch_util.m:
	When a switch arm has several solutions, store the first solution
	separately. This assures statically that there IS a first solution
	(which a simple list of solutions does not), and prepares the first
	solution for its special treatment (it is stored in a different vector
	than the later solutions, and in the LLDS backend, we take the liveness
	after the arms from it).

compiler/ml_code_util.m:
	Move here the predicates previously in ml_lookup_switch.m that are now
	needed by ml_disj_gen.m as well. Make it possible to generate
	constants for individual arms, as well as individual field assigns,
	since ml_disj_gen.m now needs this capability.

compiler/goal_form.m:
	Move here a suitably generalized version of the two previously
	backend-specific versions of the predicates that test goals to see
	if they can be part of a lookup switch or disjunction.

compiler/ml_util.m:
	Move here from ml_lookup_switch.m a predicate now needed by
	ml_disj_gen.m as well.

compiler/lookup_util.m:
	Remove the predicate moved to goal_form.m.

	Make it possible to generate constants for a single disjunct.

	Avoid uselessly wrapping up a return argument in a yes().

compiler/disj_gen.m:
compiler/lookup_switch.m:
	Move a cheap test significantly earlier, to avoid wasting time
	on disjunctions on which it would fail.

	Conform to the changes in the backend libraries.

	In lookup_switch.m, note the paper that describes the code generation
	scheme followed by the module.

compiler/mlds_to_c.m:
	Conform to the changes above.

	When generating scalar and vector static cells, indicate the row
	numbers in comments, since without this, it is too difficult to check
	visually whether the generated code is correct.

compiler/mlds_to_java.m:
	Conform to the changes above.

	Improve the style of a big predicate.

compiler/ml_accurate_gc.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tailcall.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
	Conform to the changes above.

tests/hard_coded/dense_lookup_switch_non.{m,exp}:
	Make this test case significantly more comprehensive, by making it
	test all combinations of the presence and absence of both range checks
	and bit vector checks.

tests/hard_coded/lookup_switch_simple_bitvec.{m,exp}:
	This test was not doing its job, because the switch had too few arms
	for ml_switch_gen.m to decide that a lookup switch was worthwhile.
	It succeeded, but did not exercise the lookup switch code that existed
	in the MLDS backend before this diff. Fix this by adding more arms.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: disj_gen.m
--- /home/zs/mer/ws00/compiler/disj_gen.m	2009-01-06 14:59:23.000000000 +1100
+++ disj_gen.m	2009-09-29 11:06:44.000000000 +1000
@@ -126,8 +126,19 @@
     set(prog_var)::in, list(hlds_goal)::in, hlds_goal_info::in,
     lookup_disj_info::out, code_info::in, code_info::out) is semidet.
 
-is_lookup_disj(AddTrailOps, AddRegionOps, ResumeVars, Goals, DisjGoalInfo,
+is_lookup_disj(AddTrailOps, AddRegionOps, ResumeVars, Disjuncts, DisjGoalInfo,
         LookupDisjInfo, !CI) :-
+    % Since we generate two code sequences, one for the first solution and one
+    % for all the later solutions, we don't get any benefit over the code
+    % sequence generated by generate_real_disj unless there are at least three
+    % solutions.
+    Disjuncts = [FirstDisjunct | LaterDisjuncts],
+    LaterDisjuncts = [_, _ | _],
+
+    DisjNonLocals = goal_info_get_nonlocals(DisjGoalInfo),
+    goal_is_conj_of_unify(DisjNonLocals, FirstDisjunct),
+    all_disjuncts_are_conj_of_unify(DisjNonLocals, LaterDisjuncts),
+
     get_maybe_trace_info(!.CI, MaybeTraceInfo),
     MaybeTraceInfo = no,
 
@@ -139,13 +150,6 @@
     % to handle region operations.
     AddRegionOps = do_not_add_region_ops,
 
-    % Since we generate two code sequences, one for the first solution and one
-    % for all the later solutions, we don't get any benefit over the code
-    % sequence generated by generate_real_disj unless there are at least three
-    % solutions.
-    Goals = [_, _, _ | _],
-    all_disjuncts_are_conj_of_unify(Goals),
-
     figure_out_output_vars(!.CI, DisjGoalInfo, OutVars),
     VarTypes = get_var_types(!.CI),
     list.map(map.lookup(VarTypes), OutVars, OutTypes),
@@ -172,14 +176,11 @@
     remember_position(!.CI, CurPos),
 
     goal_info_get_store_map(DisjGoalInfo, StoreMap),
-    generate_constants_for_disjuncts(Goals, OutVars, StoreMap, Solns,
-        no, MaybeEnd, MaybeLiveness, !CI),
-    (
-        MaybeLiveness = yes(Liveness)
-    ;
-        MaybeLiveness = no,
-        unexpected(this_file, "is_lookup_disj: no liveness")
-    ),
+    generate_constants_for_disjunct(FirstDisjunct, OutVars, StoreMap,
+        FirstSoln, no, MaybeEnd1, Liveness, !CI),
+    generate_constants_for_disjuncts(LaterDisjuncts, OutVars, StoreMap,
+        LaterSolns, MaybeEnd1, MaybeEnd, !CI),
+    Solns = [FirstSoln | LaterSolns],
     reset_to_position(CurPos, !CI),
 
     get_exprn_opts(!.CI, ExprnOpts),
Index: goal_form.m
--- /home/zs/mer/ws00/compiler/goal_form.m	2009-08-19 17:49:38.000000000 +1000
+++ goal_form.m	2009-09-29 11:05:33.000000000 +1000
@@ -21,8 +21,24 @@
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
+:- import_module parse_tree.prog_data.
 
 :- import_module bool.
+:- import_module list.
+:- import_module set.
+
+%-----------------------------------------------------------------------------%
+
+    % Is the input goal a conjunction of unifications that constructs every
+    % variable in the given set? A from_ground_term_construct scope counts
+    % as a unification.
+    %
+:- pred goal_is_conj_of_unify(set(prog_var)::in, hlds_goal::in) is semidet.
+
+    % Run goal_is_conj_of_unify on each goal in the list.
+    %
+:- pred all_disjuncts_are_conj_of_unify(set(prog_var)::in,
+    list(hlds_goal)::in) is semidet.
 
 %-----------------------------------------------------------------------------%
 
@@ -168,19 +184,53 @@
 
 :- implementation.
 
+:- import_module hlds.code_model.
+:- import_module hlds.hlds_goal.
 :- 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 bool.
 :- import_module int.
-:- import_module list.
 :- import_module map.
 :- import_module maybe.
 :- import_module pair.
 
 %-----------------------------------------------------------------------------%
+
+goal_is_conj_of_unify(ToAssignVars0, Goal) :-
+    Goal = hlds_goal(_GoalExpr, GoalInfo),
+    CodeModel = goal_info_get_code_model(GoalInfo),
+    CodeModel = model_det,
+    goal_to_conj_list(Goal, Conj),
+    only_constant_goals(Conj, ToAssignVars0, ToAssignVars),
+    set.empty(ToAssignVars).
+
+all_disjuncts_are_conj_of_unify(_ToAssignVars, []).
+all_disjuncts_are_conj_of_unify(ToAssignVars, [Disjunct | Disjuncts]) :-
+    goal_is_conj_of_unify(ToAssignVars, Disjunct),
+    all_disjuncts_are_conj_of_unify(ToAssignVars, Disjuncts).
+
+:- pred only_constant_goals(list(hlds_goal)::in,
+    set(prog_var)::in, set(prog_var)::out) is semidet.
+
+only_constant_goals([], !ToAssignVars).
+only_constant_goals([Goal | Goals], !ToAssignVars) :-
+    Goal = hlds_goal(GoalExpr, _),
+    % We could allow calls as well. Some procedures have an output inst
+    % that fixes the value of the output variable, which is thus a constant.
+    % However, calls to such procedures should have been inlined by now.
+    (
+        GoalExpr = unify(_, _, _, Unification, _),
+        Unification = construct(Var, _, _, _, _, _, _)
+    ;
+        GoalExpr = scope(Reason, _),
+        Reason = from_ground_term(Var, from_ground_term_construct)
+    ),
+    set.delete(!.ToAssignVars, Var, !:ToAssignVars),
+    only_constant_goals(Goals, !ToAssignVars).
+
+%-----------------------------------------------------------------------------%
 %
 % A version of goal_cannot_loop_or_throw that uses results from the
 % intermodule-analysis framework.
Index: lookup_switch.m
--- /home/zs/mer/ws00/compiler/lookup_switch.m	2009-09-21 15:23:03.000000000 +1000
+++ lookup_switch.m	2009-09-29 11:11:50.000000000 +1000
@@ -126,18 +126,13 @@
     % end because we may have allocated some new static ground terms.
 
     figure_out_output_vars(!.CI, GoalInfo, OutVars),
+    set.list_to_set(OutVars, ArmNonLocals),
     remember_position(!.CI, CurPos),
-    generate_constants_for_lookup_switch(TaggedCases, OutVars, StoreMap,
-        MaybeLiveness, map.init, CaseSolnMap, !MaybeEnd,
+    generate_constants_for_lookup_switch(TaggedCases, OutVars, ArmNonLocals,
+        StoreMap, Liveness, map.init, CaseSolnMap, !MaybeEnd,
         set.init, ResumeVars, no, GoalsMayModifyTrail, !CI),
     map.to_assoc_list(CaseSolnMap, CaseSolns),
     reset_to_position(CurPos, !CI),
-    (
-        MaybeLiveness = yes(Liveness)
-    ;
-        MaybeLiveness = no,
-        unexpected(this_file, "is_lookup_switch: no liveness!")
-    ),
     VarTypes = get_var_types(!.CI),
     list.map(map.lookup(VarTypes), OutVars, OutTypes),
     ( project_all_to_one_solution(CaseSolns, [], RevCaseValuePairs) ->
@@ -160,15 +155,17 @@
 %---------------------------------------------------------------------------%
 
 :- pred generate_constants_for_lookup_switch(list(tagged_case)::in,
-    list(prog_var)::in, abs_store_map::in, maybe(set(prog_var))::out,
+    list(prog_var)::in, set(prog_var)::in, abs_store_map::in,
+    set(prog_var)::out,
     map(int, soln_consts(rval))::in, map(int, soln_consts(rval))::out,
     branch_end::in, branch_end::out, set(prog_var)::in, set(prog_var)::out,
     bool::in, bool::out, code_info::in, code_info::out) is semidet.
 
-generate_constants_for_lookup_switch([], _Vars, _StoreMap, no, !IndexMap,
+generate_constants_for_lookup_switch([], _Vars, _ArmNonLocals, _StoreMap,
+        set.init, !IndexMap,
         !MaybeEnd, !ResumeVars, !GoalsMayModifyTrail, !CI).
 generate_constants_for_lookup_switch([TaggedCase | TaggedCases], Vars,
-        StoreMap, MaybeLiveness, !IndexMap, !MaybeEnd, !ResumeVars,
+        ArmNonLocals, StoreMap, Liveness, !IndexMap, !MaybeEnd, !ResumeVars,
         !GoalsMayModifyTrail, !CI) :-
     TaggedCase = tagged_case(TaggedMainConsId, TaggedOtherConsIds, _, Goal),
     Goal = hlds_goal(GoalExpr, GoalInfo),
@@ -179,14 +176,18 @@
     not set.member(feature_save_deep_excp_vars, Features),
 
     ( GoalExpr = disj(Disjuncts) ->
-        bool.or(goal_may_modify_trail(GoalInfo), !GoalsMayModifyTrail),
         (
             Disjuncts = [],
             % Cases like this should have been filtered out by
             % filter_out_failing_cases.
             unexpected(this_file, "generate_constants: disj([])")
         ;
-            Disjuncts = [FirstDisjunct | _],
+            Disjuncts = [FirstDisjunct | LaterDisjuncts],
+            goal_is_conj_of_unify(ArmNonLocals, FirstDisjunct),
+            all_disjuncts_are_conj_of_unify(ArmNonLocals, LaterDisjuncts),
+
+            bool.or(goal_may_modify_trail(GoalInfo), !GoalsMayModifyTrail),
+
             FirstDisjunct = hlds_goal(_, FirstDisjunctGoalInfo),
             goal_info_get_resume_point(FirstDisjunctGoalInfo, ThisResumePoint),
             (
@@ -194,9 +195,7 @@
                 set.union(ThisResumeVars, !ResumeVars)
             ;
                 ThisResumePoint = no_resume_point
-            )
         ),
-        all_disjuncts_are_conj_of_unify(Disjuncts),
 
         % We execute the pre- and post-goal update for the disjunction.
         % The pre- and post-goal updates for the disjuncts themselves are
@@ -204,26 +203,28 @@
         % generate_constants_for_disjuncts in lookup_util.m.
         pre_goal_update(GoalInfo, has_subgoals, !CI),
         get_instmap(!.CI, InstMap),
-        generate_constants_for_disjuncts(Disjuncts, Vars, StoreMap, Solns,
-            !MaybeEnd, MaybeLiveness, !CI),
+            generate_constants_for_disjunct(FirstDisjunct, Vars, StoreMap,
+                FirstSoln, !MaybeEnd, Liveness, !CI),
+            generate_constants_for_disjuncts(LaterDisjuncts, Vars, StoreMap,
+                LaterSolns, !MaybeEnd, !CI),
         set_instmap(InstMap, !CI),
         post_goal_update(GoalInfo, !CI),
-        SolnConsts = several_solns(Solns)
+            SolnConsts = several_solns(FirstSoln, LaterSolns)
+        )
     ;
-        goal_is_conj_of_unify(Goal),
+        goal_is_conj_of_unify(ArmNonLocals, Goal),
         % The pre- and post-goal updates for the goals themselves
         % are done as part of the call to generate_goal in
         % generate_constants_for_disjuncts in lookup_util.m.
         generate_constants_for_arm(Goal, Vars, StoreMap, Soln,
             !MaybeEnd, Liveness, !CI),
-        MaybeLiveness = yes(Liveness),
         SolnConsts = one_soln(Soln)
     ),
     record_lookup_for_tagged_cons_id(SolnConsts, TaggedMainConsId, !IndexMap),
     list.foldl(record_lookup_for_tagged_cons_id(SolnConsts),
         TaggedOtherConsIds, !IndexMap),
-    generate_constants_for_lookup_switch(TaggedCases, Vars,
-        StoreMap, _MaybeLivenessRest, !IndexMap, !MaybeEnd, !ResumeVars,
+    generate_constants_for_lookup_switch(TaggedCases, Vars, ArmNonLocals,
+        StoreMap, _LivenessRest, !IndexMap, !MaybeEnd, !ResumeVars,
         !GoalsMayModifyTrail, !CI).
 
 :- pred record_lookup_for_tagged_cons_id(soln_consts(rval)::in,
@@ -709,10 +710,7 @@
             ControlRvals = [const(llconst_int(0)), const(llconst_int(0))],
             MainRow = ControlRvals ++ Rvals
         ;
-            Soln = several_solns([]),
-            unexpected(this_file, "construct_several_soln_vector: several = 0")
-        ;
-            Soln = several_solns([FirstSoln | LaterSolns]),
+            Soln = several_solns(FirstSoln, LaterSolns),
             !:SeveralSolnCaseCount = !.SeveralSolnCaseCount + 1,
             list.length(LaterSolns, NumLaterSolns),
             FirstRowOffset = !.LaterNextRow * NumLLDSTypes,
Index: lookup_util.m
--- /home/zs/mer/ws00/compiler/lookup_util.m	2009-09-21 15:23:04.000000000 +1000
+++ lookup_util.m	2009-09-28 19:24:20.000000000 +1000
@@ -26,7 +26,6 @@
 :- import_module parse_tree.prog_data.
 
 :- import_module list.
-:- import_module maybe.
 :- import_module set.
 
     % Figure out which variables are bound in the goal.
@@ -36,15 +35,6 @@
 :- pred figure_out_output_vars(code_info::in, hlds_goal_info::in,
     list(prog_var)::out) is det.
 
-    % Is the input goal a conjunction of unifications? A
-    % from_ground_term_construct scope counts as a unification.
-    %
-:- pred goal_is_conj_of_unify(hlds_goal::in) is semidet.
-
-    % Run goal_is_conj_of_unify on each goal in the list.
-    %
-:- pred all_disjuncts_are_conj_of_unify(list(hlds_goal)::in) is semidet.
-
     % To figure out if the outputs are constants, we
     %
     % - check whether the determinism and structure of the goal are right,
@@ -62,10 +52,14 @@
     abs_store_map::in, list(rval)::out, branch_end::in, branch_end::out,
     set(prog_var)::out, code_info::in, code_info::out) is semidet.
 
+:- pred generate_constants_for_disjunct(hlds_goal::in,
+    list(prog_var)::in, abs_store_map::in, list(rval)::out,
+    branch_end::in, branch_end::out, set(prog_var)::out,
+    code_info::in, code_info::out) is semidet.
+
 :- pred generate_constants_for_disjuncts(list(hlds_goal)::in,
     list(prog_var)::in, abs_store_map::in, list(list(rval))::out,
-    branch_end::in, branch_end::out, maybe(set(prog_var))::out,
-    code_info::in, code_info::out) is semidet.
+    branch_end::in, branch_end::out, code_info::in, code_info::out) is semidet.
 
 :- pred set_liveness_and_end_branch(abs_store_map::in, branch_end::in,
     set(prog_var)::in, llds_code::out, code_info::in, code_info::out) is det.
@@ -89,6 +83,7 @@
 :- import_module bool.
 :- import_module cord.
 :- import_module int.
+:- import_module maybe.
 :- import_module pair.
 
 figure_out_output_vars(CI, GoalInfo, OutVars) :-
@@ -115,34 +110,6 @@
     instmap_lookup_var(InstMapAfter, Var, Final),
     mode_is_output(ModuleInfo, (Initial -> Final)).
 
-goal_is_conj_of_unify(Goal) :-
-    Goal = hlds_goal(_GoalExpr, GoalInfo),
-    CodeModel = goal_info_get_code_model(GoalInfo),
-    CodeModel = model_det,
-    goal_to_conj_list(Goal, Conj),
-    only_constant_goals(Conj).
-
-all_disjuncts_are_conj_of_unify([]).
-all_disjuncts_are_conj_of_unify([Disjunct | Disjuncts]) :-
-    goal_is_conj_of_unify(Disjunct),
-    all_disjuncts_are_conj_of_unify(Disjuncts).
-
-:- pred only_constant_goals(list(hlds_goal)::in) is semidet.
-
-only_constant_goals([]).
-only_constant_goals([Goal | Goals]) :-
-    Goal = hlds_goal(GoalExpr, _),
-    % We could allow calls as well. Some procedures have an output inst
-    % that fixes the value of the output variable, which is thus a constant.
-    % However, calls to such procedures should have been inlined by now.
-    (
-        GoalExpr = unify(_, _, _, _, _)
-    ;
-        GoalExpr = scope(Reason, _),
-        Reason = from_ground_term(_, from_ground_term_construct)
-    ),
-    only_constant_goals(Goals).
-
 generate_constants_for_arm(Goal, Vars, StoreMap, !MaybeEnd, CaseRvals,
         Liveness, !CI) :-
     do_generate_constants_for_arm(Goal, Vars, StoreMap, no, !MaybeEnd,
@@ -176,10 +143,8 @@
     generate_branch_end(StoreMap, !MaybeEnd, _EndCode, !CI),
     reset_to_position(BranchStart, !CI).
 
-generate_constants_for_disjuncts([], _Vars, _StoreMap, [], !MaybeEnd,
-        no, !CI).
-generate_constants_for_disjuncts([Disjunct0 | Disjuncts], Vars, StoreMap,
-        [Soln | Solns], !MaybeEnd, yes(Liveness), !CI) :-
+generate_constants_for_disjunct(Disjunct0, Vars, StoreMap, Soln,
+        !MaybeEnd, Liveness, !CI) :-
     % The pre_goal_update sanity check insists on no_resume_point, to ensure
     % that all resume points have been handled by surrounding code.
     Disjunct0 = hlds_goal(DisjunctGoalExpr, DisjunctGoalInfo0),
@@ -187,9 +152,15 @@
         DisjunctGoalInfo0, DisjunctGoalInfo),
     Disjunct = hlds_goal(DisjunctGoalExpr, DisjunctGoalInfo),
     do_generate_constants_for_arm(Disjunct, Vars, StoreMap, yes, Soln,
-        !MaybeEnd, Liveness, !CI),
-    generate_constants_for_disjuncts(Disjuncts, Vars, StoreMap, Solns,
-        !MaybeEnd, _, !CI).
+        !MaybeEnd, Liveness, !CI).
+
+generate_constants_for_disjuncts([], _Vars, _StoreMap, [], !MaybeEnd, !CI).
+generate_constants_for_disjuncts([Disjunct0 | Disjuncts0], Vars, StoreMap,
+        [Soln | Solns], !MaybeEnd, !CI) :-
+    generate_constants_for_disjunct(Disjunct0, Vars, StoreMap, Soln,
+        !MaybeEnd, _Liveness, !CI),
+    generate_constants_for_disjuncts(Disjuncts0, Vars, StoreMap, Solns,
+        !MaybeEnd, !CI).
 
 %---------------------------------------------------------------------------%
 
Index: ml_accurate_gc.m
--- /home/zs/mer/ws00/compiler/ml_accurate_gc.m	2009-09-25 15:13:02.000000000 +1000
+++ ml_accurate_gc.m	2009-09-28 13:23:09.000000000 +1000
@@ -460,9 +460,9 @@
             Statements0, Statements, !Fixup),
         Stmt = ml_stmt_block(Defns, Statements)
     ;
-        Stmt0 = ml_stmt_while(Rval, Statement0, Once),
+        Stmt0 = ml_stmt_while(Kind, Rval, Statement0),
         fixup_newobj_in_statement(Statement0, Statement, !Fixup),
-        Stmt = ml_stmt_while(Rval, Statement, Once)
+        Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         Stmt0 = ml_stmt_if_then_else(Cond, Then0, MaybeElse0),
         fixup_newobj_in_statement(Then0, Then, !Fixup),
Index: ml_backend.m
--- /home/zs/mer/ws00/compiler/ml_backend.m	2009-09-25 15:15:29.000000000 +1000
+++ ml_backend.m	2009-09-27 00:58:49.000000000 +1000
@@ -44,6 +44,7 @@
    :- include_module ml_foreign_proc_gen.
    :- include_module ml_closure_gen.
    :- include_module ml_commit_gen.
+   :- include_module ml_disj_gen.
    :- include_module ml_switch_gen.
       :- include_module ml_simplify_switch.
       :- include_module ml_string_switch.
Index: ml_code_gen.m
--- /home/zs/mer/ws00/compiler/ml_code_gen.m	2009-09-25 15:15:29.000000000 +1000
+++ ml_code_gen.m	2009-09-28 13:44:21.000000000 +1000
@@ -318,89 +318,6 @@
 %
 %-----------------------------------------------------------------------------%
 %
-% Code for empty disjunctions (`fail')
-%
-%
-%   model_semi goal:
-%       <succeeded = fail>
-%   ===>
-%       succeeded = MR_FALSE;
-%
-%   model_non goal:
-%       <fail && CONT()>
-%   ===>
-%       /* fall through */
-%
-%-----------------------------------------------------------------------------%
-%
-% Code for non-empty disjunctions
-%
-%
-% model_det disj:
-%
-%   model_det Goal:
-%       <do (Goal ; Goals)>
-%   ===>
-%       <do Goal>
-%       /* <Goals> will never be reached */
-%
-%   model_semi Goal:
-%       <do (Goal ; Goals)>
-%   ===>
-%       MR_bool succeeded;
-%
-%       <succeeded = Goal>;
-%       if (!succeeded) {
-%           <do Goals>;
-%       }
-%
-% model_semi disj:
-%
-%   model_det Goal:
-%       <succeeded = (Goal ; Goals)>
-%   ===>
-%       MR_bool succeeded;
-%
-%       <do Goal>
-%       succeeded = MR_TRUE
-%       /* <Goals> will never be reached */
-%
-%   model_semi Goal:
-%       <succeeded = (Goal ; Goals)>
-%   ===>
-%       MR_bool succeeded;
-%
-%       <succeeded = Goal>;
-%       if (!succeeded) {
-%           <succeeded = Goals>;
-%       }
-%
-% model_non disj:
-%
-%   model_det Goal:
-%       <(Goal ; Goals) && SUCCEED()>
-%   ===>
-%       <Goal>
-%       SUCCEED();
-%       <Goals && SUCCEED()>
-%
-%   model_semi Goal:
-%       <(Goal ; Goals) && SUCCEED()>
-%   ===>
-%       MR_bool succeeded;
-%
-%       <succeeded = Goal>
-%       if (succeeded) SUCCEED();
-%       <Goals && SUCCEED()>
-%
-%   model_non Goal:
-%       <(Goal ; Goals) && SUCCEED()>
-%   ===>
-%       <Goal && SUCCEED()>
-%       <Goals && SUCCEED()>
-%
-%-----------------------------------------------------------------------------%
-%
 % Code for if-then-else
 %
 %
@@ -600,6 +517,7 @@
 :- import_module backend_libs.foreign. % XXX needed for pragma foreign code
 :- import_module check_hlds.mode_util.
 :- import_module check_hlds.type_util.
+:- import_module hlds.goal_form.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
 :- import_module libs.compiler_util.
@@ -608,6 +526,7 @@
 :- import_module ml_backend.ml_call_gen.
 :- import_module ml_backend.ml_code_util.
 :- import_module ml_backend.ml_commit_gen.
+:- import_module ml_backend.ml_disj_gen.
 :- import_module ml_backend.ml_foreign_proc_gen.
 :- import_module ml_backend.ml_gen_info.
 :- import_module ml_backend.ml_global_data.
@@ -771,7 +690,8 @@
         ml_gen_conj(Goals, CodeModel, Context, Decls, Statements, !Info)
     ;
         GoalExpr = disj(Goals),
-        ml_gen_disj(Goals, CodeModel, Context, Decls, Statements, !Info)
+        ml_gen_disj(Goals, GoalInfo, CodeModel, Context, Statements, !Info),
+        Decls = []
     ;
         GoalExpr = switch(Var, CanFail, CasesList),
         ml_gen_switch(Var, CanFail, CasesList, CodeModel, Context, GoalInfo,
@@ -963,37 +883,51 @@
 
 %-----------------------------------------------------------------------------%
 
+ml_gen_maybe_convert_goal_code_model(OuterCodeModel, InnerCodeModel, Context,
+        !Statements, !Info) :-
+    (
     % If the inner and outer code models are equal, we don't need to do
     % anything.
     %
+        (
+            OuterCodeModel = model_det,
+            InnerCodeModel = model_det
+        ;
+            OuterCodeModel = model_semi,
+            InnerCodeModel = model_semi
+        ;
+            OuterCodeModel = model_non,
+            InnerCodeModel = model_non
+        )
+    ;
     % If the inner code model is less precise than the outer code model,
     % then that is either a determinism error, or a situation in which
-    % simplify.m is supposed to wrap the goal inside a `some' to indicate that
-    % a commit is needed.
-    %
-    % If the inner code model is more precise than the outer code model,
-    % then we need to append some statements to convert the calling convention
-    % for the inner code model to that of the outer code model.
-
-ml_gen_maybe_convert_goal_code_model(model_det, model_det, _,
-        !Statements, !Info).
-ml_gen_maybe_convert_goal_code_model(model_semi, model_semi, _,
-        !Statements, !Info).
-ml_gen_maybe_convert_goal_code_model(model_non, model_non, _,
-        !Statements, !Info).
-
-ml_gen_maybe_convert_goal_code_model(model_det, model_semi, _, _, _, !Info) :-
+        % simplify.m is supposed to wrap the goal inside a `some' to indicate
+        % that a commit is needed.
+        (
+            OuterCodeModel = model_det,
+            InnerCodeModel = model_semi,
     unexpected(this_file,
-        "ml_gen_maybe_convert_goal_code_model: semi in det").
-ml_gen_maybe_convert_goal_code_model(model_det, model_non, _, _, _, !Info) :-
+                "ml_gen_maybe_convert_goal_code_model: semi in det")
+        ;
+            OuterCodeModel = model_det,
+            InnerCodeModel = model_non,
     unexpected(this_file,
-        "ml_gen_maybe_convert_goal_code_model: nondet in det").
-ml_gen_maybe_convert_goal_code_model(model_semi, model_non, _, _, _, !Info) :-
+                "ml_gen_maybe_convert_goal_code_model: nondet in det")
+        ;
+            OuterCodeModel = model_semi,
+            InnerCodeModel = model_non,
     unexpected(this_file,
-        "ml_gen_maybe_convert_goal_code_model: nondet in semi").
+                "ml_gen_maybe_convert_goal_code_model: nondet in semi")
+        )
+    ;
+        % If the inner code model is more precise than the outer code model,
+        % then we need to append some statements to convert the calling
+        % convention for the inner code model to that of the outer code model.
+        (
+            OuterCodeModel = model_semi,
+            InnerCodeModel = model_det,
 
-ml_gen_maybe_convert_goal_code_model(model_semi, model_det, Context,
-        !Statements, !Info) :-
     % det goal in semidet context:
     %   <succeeded = Goal>
     % ===>
@@ -1002,10 +936,11 @@
 
     ml_gen_set_success(!.Info, ml_const(mlconst_true), Context,
         SetSuccessTrue),
-    !:Statements = !.Statements ++ [SetSuccessTrue].
+            !:Statements = !.Statements ++ [SetSuccessTrue]
+        ;
+            OuterCodeModel = model_non,
+            InnerCodeModel = model_det,
 
-ml_gen_maybe_convert_goal_code_model(model_non, model_det, Context,
-        !Statements, !Info) :-
     % det goal in nondet context:
     %   <Goal && SUCCEED()>
     % ===>
@@ -1013,10 +948,11 @@
     %   SUCCEED()
 
     ml_gen_call_current_success_cont(Context, CallCont, !Info),
-    !:Statements = !.Statements ++ [CallCont].
+            !:Statements = !.Statements ++ [CallCont]
+        ;
+            OuterCodeModel = model_non,
+            InnerCodeModel = model_semi,
 
-ml_gen_maybe_convert_goal_code_model(model_non, model_semi, Context,
-        !Statements, !Info) :-
     % semi goal in nondet context:
     %   <Goal && SUCCEED()>
     % ===>
@@ -1029,7 +965,9 @@
     ml_gen_call_current_success_cont(Context, CallCont, !Info),
     IfStmt = ml_stmt_if_then_else(Succeeded, CallCont, no),
     IfStatement = statement(IfStmt, mlds_make_context(Context)),
-    !:Statements = !.Statements ++ [IfStatement].
+            !:Statements = !.Statements ++ [IfStatement]
+        )
+    ).
 
 %-----------------------------------------------------------------------------%
 
@@ -1154,8 +1092,9 @@
         ml_gen_set_cond_var(!.Info, CondVar, ml_const(mlconst_true),
             ThenContext, SetCondTrue),
         ml_gen_goal_as_block(CodeModel, Then, ThenStatement, !Info),
-        ThenFuncBody = ml_gen_block([], [SetCondTrue, ThenStatement],
-            ThenContext),
+        ThenFuncBody = statement(
+            ml_stmt_block([], [SetCondTrue, ThenStatement]),
+            mlds_make_context(ThenContext)),
         % pop nesting level
         ml_gen_nondet_label_func(!.Info, ThenFuncLabel, ThenContext,
             ThenFuncBody, ThenFunc),
@@ -1272,110 +1211,6 @@
     ).
 
 %-----------------------------------------------------------------------------%
-%
-% Code for disjunctions.
-%
-
-:- pred ml_gen_disj(hlds_goals::in, code_model::in, prog_context::in,
-    list(mlds_defn)::out, list(statement)::out,
-    ml_gen_info::in, ml_gen_info::out) is det.
-
-ml_gen_disj(Goals, CodeModel, Context, Decls, Statements, !Info) :-
-    (
-        Goals = [],
-        % Handle empty disjunctions (a.ka. `fail').
-        ml_gen_failure(CodeModel, Context, Statements, !Info),
-        Decls = []
-    ;
-        Goals = [SingleGoal],
-        % Handle singleton disjunctions.
-        % (The HLDS should not contain singleton disjunctions, but this code
-        % is needed to handle recursive calls to ml_gen_disj).
-        % Note that we place each non-first arm of a model_non disjunction
-        % into a block. This is so that we can avoid having to figure out
-        % how to merge their declarations with the declarations of the first
-        % disjunct.
-        ml_gen_goal_as_branch_block(CodeModel, SingleGoal, Statement, !Info),
-        Statements = [Statement],
-        Decls = []
-    ;
-        Goals = [FirstGoal | LaterGoals],
-        LaterGoals = [_ | _],
-        (
-            CodeModel = model_non,
-            % model_non disj:
-            %
-            %       <(Goal ; Goals) && SUCCEED()>
-            %   ===>
-            %       <Goal && SUCCEED()>
-            %       <Goals && SUCCEED()>
-
-            ml_gen_goal_as_branch_block(model_non, FirstGoal, FirstStatement,
-                !Info),
-            ml_gen_disj(LaterGoals, model_non, Context,
-                LaterDecls, LaterStatements, !Info),
-            (
-                LaterDecls = [],
-                Statements = [FirstStatement | LaterStatements],
-                Decls = []
-            ;
-                LaterDecls = [_ | _],
-                unexpected(this_file, "ml_gen_disj: LaterDecls not empty.")
-            )
-        ;
-            ( CodeModel = model_det
-            ; CodeModel = model_semi
-            ),
-            % model_det/model_semi disj:
-            %
-            %   model_det goal:
-            %       <Goal ; Goals>
-            %   ===>
-            %       <Goal>
-            %       /* <Goals> will never be reached */
-            %
-            %   model_semi goal:
-            %       <Goal ; Goals>
-            %   ===>
-            %   {
-            %       MR_bool succeeded;
-            %
-            %       <succeeded = Goal>;
-            %       if (!succeeded) {
-            %           <Goals>;
-            %       }
-            %   }
-
-            FirstGoal = hlds_goal(_, FirstGoalInfo),
-            FirstCodeModel = goal_info_get_code_model(FirstGoalInfo),
-            (
-                FirstCodeModel = model_det,
-                ml_gen_goal(model_det, FirstGoal, Decls, Statements, !Info)
-            ;
-                FirstCodeModel = model_semi,
-                ml_gen_goal_as_branch(model_semi, FirstGoal,
-                    FirstDecls, FirstStatements, !Info),
-                ml_gen_test_success(!.Info, Succeeded),
-                ml_gen_disj(LaterGoals, CodeModel, Context,
-                    LaterDecls, LaterStatements, !Info),
-                LaterStatement = ml_gen_block(LaterDecls, LaterStatements,
-                    Context),
-                IfStmt = ml_stmt_if_then_else(
-                    ml_unop(std_unop(logical_not), Succeeded),
-                    LaterStatement, no),
-                IfStatement = statement(IfStmt, mlds_make_context(Context)),
-                Decls = FirstDecls,
-                Statements = FirstStatements ++ [IfStatement]
-            ;
-                FirstCodeModel = model_non,
-                % simplify.m should get wrap commits around these.
-                unexpected(this_file,
-                    "model_non disj in model_det disjunction")
-            )
-        )
-    ).
-
-%-----------------------------------------------------------------------------%
 
 :- func this_file = string.
 
Index: ml_code_util.m
--- /home/zs/mer/ws00/compiler/ml_code_util.m	2009-09-25 15:15:29.000000000 +1000
+++ ml_code_util.m	2009-09-29 02:33:20.000000000 +1000
@@ -19,14 +19,15 @@
 
 :- import_module backend_libs.builtin_ops.
 :- import_module hlds.code_model.
+:- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
 :- import_module hlds.hlds_rtti.
 :- import_module libs.globals.
 :- import_module mdbcomp.prim_data.
-:- import_module ml_backend.mlds.
 :- import_module ml_backend.ml_gen_info.
 :- import_module ml_backend.ml_global_data.
+:- import_module ml_backend.mlds.
 :- import_module parse_tree.prog_data.
 
 :- import_module bool.
@@ -494,6 +495,27 @@
 
 %-----------------------------------------------------------------------------%
 %
+% Routines for dealing with lookup tables.
+%
+
+:- pred ml_generate_constants_for_arms(list(prog_var)::in, list(hlds_goal)::in,
+    list(list(mlds_rval))::out, ml_gen_info::in, ml_gen_info::out) is det.
+
+:- pred ml_generate_constants_for_arm(list(prog_var)::in, hlds_goal::in,
+    list(mlds_rval)::out, ml_gen_info::in, ml_gen_info::out) is det.
+
+:- pred ml_generate_field_assign(mlds_lval::in, mlds_type::in,
+    mlds_field_id::in, mlds_vector_common::in, mlds_type::in,
+    mlds_rval::in, mlds_context::in, statement::out,
+    ml_gen_info::in, ml_gen_info::out) is det.
+
+:- pred ml_generate_field_assigns(list(prog_var)::in, list(mlds_type)::in,
+    list(mlds_field_id)::in, mlds_vector_common::in, mlds_type::in,
+    mlds_rval::in, mlds_context::in, list(statement)::out,
+    ml_gen_info::in, ml_gen_info::out) is det.
+
+%-----------------------------------------------------------------------------%
+%
 % Miscellaneous routines.
 %
 
@@ -523,7 +545,6 @@
 :- import_module check_hlds.mode_util.
 :- import_module check_hlds.polymorphism.
 :- import_module check_hlds.type_util.
-:- import_module hlds.hlds_goal.
 :- import_module hlds.instmap.
 :- import_module libs.compiler_util.
 :- import_module libs.globals.
@@ -2003,6 +2024,63 @@
 
 %-----------------------------------------------------------------------------%
 %
+% Routines for dealing with lookup tables.
+%
+
+ml_generate_constants_for_arms(_Vars, [], [], !Info).
+ml_generate_constants_for_arms(Vars, [Goal | Goals], [Soln | Solns], !Info) :-
+    ml_generate_constants_for_arm(Vars, Goal, Soln, !Info),
+    ml_generate_constants_for_arms(Vars, Goals, Solns, !Info).
+
+ml_generate_constants_for_arm(Vars, Goal, Soln, !Info) :-
+    ml_gen_info_get_const_var_map(!.Info, InitConstVarMap),
+    ml_gen_goal(model_det, Goal, _Decls, _Statements, !Info),
+    ml_gen_info_get_const_var_map(!.Info, FinalConstVarMap),
+    list.map(lookup_ground_rval(FinalConstVarMap), Vars, Soln),
+    ml_gen_info_set_const_var_map(InitConstVarMap, !Info).
+
+:- pred lookup_ground_rval(ml_ground_term_map::in, prog_var::in,
+    mlds_rval::out) is det.
+
+lookup_ground_rval(FinalConstVarMap, Var, Rval) :-
+    map.lookup(FinalConstVarMap, Var, GroundTerm),
+    GroundTerm = ml_ground_term(Rval, _, _).
+
+ml_generate_field_assign(OutVarLval, FieldType, FieldId, VectorCommon,
+        StructType, IndexRval, Context, Statement, !Info) :-
+    BaseRval = ml_vector_common_row(VectorCommon, IndexRval),
+    FieldLval = ml_field(yes(0), BaseRval, FieldId, FieldType, StructType),
+    AtomicStmt = assign(OutVarLval, ml_lval(FieldLval)),
+    Stmt = ml_stmt_atomic(AtomicStmt),
+    Statement = statement(Stmt, Context).
+
+ml_generate_field_assigns(OutVars, FieldTypes, FieldIds, VectorCommon,
+        StructType, IndexRval, Context, Statements, !Info) :-
+    (
+        OutVars = [],
+        FieldTypes = [],
+        FieldIds = []
+    ->
+        Statements = []
+    ;
+        OutVars = [HeadOutVar | TailOutVars],
+        FieldTypes = [HeadFieldType | TailFieldTypes],
+        FieldIds = [HeadFieldId | TailFieldIds]
+    ->
+        ml_gen_var(!.Info, HeadOutVar, HeadOutVarLval),
+        ml_generate_field_assign(HeadOutVarLval, HeadFieldType, HeadFieldId,
+            VectorCommon, StructType, IndexRval, Context, HeadStatement,
+            !Info),
+        ml_generate_field_assigns(TailOutVars, TailFieldTypes, TailFieldIds,
+            VectorCommon, StructType, IndexRval, Context, TailStatements,
+            !Info),
+        Statements = [HeadStatement | TailStatements]
+    ;
+        unexpected(this_file, "ml_generate_offset_assigns: mismatched lists")
+    ).
+
+%-----------------------------------------------------------------------------%
+%
 % Miscellaneous routines.
 %
 
Index: ml_disj_gen.m
--- /dev/null	2009-04-09 10:45:37.000000000 +1000
+++ ml_disj_gen.m	2009-09-29 11:08:52.000000000 +1000
@@ -0,0 +1,354 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2009 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: ml_disj_gen.m.
+% Authors: fjh, zs.
+%
+% Generate MLDS code for disjunctions.
+%
+%-----------------------------------------------------------------------------%
+%
+% Code for empty disjunctions (`fail')
+%
+%
+%   model_semi goal:
+%       <succeeded = fail>
+%   ===>
+%       succeeded = MR_FALSE;
+%
+%   model_non goal:
+%       <fail && CONT()>
+%   ===>
+%       /* fall through */
+%
+%-----------------------------------------------------------------------------%
+%
+% Code for non-empty disjunctions
+%
+%
+% model_det disj:
+%
+%   model_det Goal:
+%       <do (Goal ; Goals)>
+%   ===>
+%       <do Goal>
+%       /* <Goals> will never be reached */
+%
+%   model_semi Goal:
+%       <do (Goal ; Goals)>
+%   ===>
+%       MR_bool succeeded;
+%
+%       <succeeded = Goal>;
+%       if (!succeeded) {
+%           <do Goals>;
+%       }
+%
+% model_semi disj:
+%
+%   model_det Goal:
+%       <succeeded = (Goal ; Goals)>
+%   ===>
+%       MR_bool succeeded;
+%
+%       <do Goal>
+%       succeeded = MR_TRUE
+%       /* <Goals> will never be reached */
+%
+%   model_semi Goal:
+%       <succeeded = (Goal ; Goals)>
+%   ===>
+%       MR_bool succeeded;
+%
+%       <succeeded = Goal>;
+%       if (!succeeded) {
+%           <succeeded = Goals>;
+%       }
+%
+% model_non disj:
+%
+%   model_det Goal:
+%       <(Goal ; Goals) && SUCCEED()>
+%   ===>
+%       <Goal>
+%       SUCCEED();
+%       <Goals && SUCCEED()>
+%
+%   model_semi Goal:
+%       <(Goal ; Goals) && SUCCEED()>
+%   ===>
+%       MR_bool succeeded;
+%
+%       <succeeded = Goal>
+%       if (succeeded) SUCCEED();
+%       <Goals && SUCCEED()>
+%
+%   model_non Goal:
+%       <(Goal ; Goals) && SUCCEED()>
+%   ===>
+%       <Goal && SUCCEED()>
+%       <Goals && SUCCEED()>
+%
+%-----------------------------------------------------------------------------%
+
+:- module ml_backend.ml_disj_gen.
+:- interface.
+
+:- import_module hlds.code_model.
+:- import_module hlds.hlds_goal.
+:- import_module ml_backend.mlds.
+:- import_module ml_backend.ml_gen_info.
+:- import_module parse_tree.prog_data.
+
+:- import_module list.
+
+:- pred ml_gen_disj(list(hlds_goal)::in, hlds_goal_info::in, code_model::in,
+    prog_context::in, list(statement)::out,
+    ml_gen_info::in, ml_gen_info::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module backend_libs.builtin_ops.
+:- import_module hlds.goal_form.
+:- import_module hlds.hlds_module.
+:- import_module libs.compiler_util.
+:- import_module ml_backend.ml_code_gen.
+:- import_module ml_backend.ml_code_util.
+:- import_module ml_backend.ml_gen_info.
+:- import_module ml_backend.ml_global_data.
+:- import_module ml_backend.ml_util.
+
+:- import_module map.
+:- import_module maybe.
+:- import_module set.
+
+ml_gen_disj(Disjuncts, GoalInfo, CodeModel, Context, Statements, !Info) :-
+    % Note that we place each arm of the disjunction into a block. This is so
+    % that we can avoid having to figure out how to merge their declarations
+    % with the declarations of the other disjuncts.
+    (
+        Disjuncts = [],
+        % Handle empty disjunctions (a.ka. `fail').
+        ml_gen_failure(CodeModel, Context, Statements, !Info)
+    ;
+        Disjuncts = [FirstDisjunct | LaterDisjuncts],
+        (
+            LaterDisjuncts = [],
+            unexpected(this_file, "ml_gen_disj: single disjunct")
+        ;
+            LaterDisjuncts = [_ | _],
+            (
+                CodeModel = model_non,
+                DisjNonLocals = goal_info_get_nonlocals(GoalInfo),
+                ( all_disjuncts_are_conj_of_unify(DisjNonLocals, Disjuncts) ->
+                    % Since the MLDS backend implements trailing by a
+                    % HLDS-to-HLDS transform (which is in add_trail_ops.m),
+                    % if we get here, then trailing is not enabled, and we do
+                    % not have to worry about resetting the trail at the
+                    % starts of all non-first disjuncts.
+                    NonLocals = goal_info_get_nonlocals(GoalInfo),
+                    OutVars = set.to_sorted_list(NonLocals),
+                    list.map_foldl(ml_generate_constants_for_arm(OutVars),
+                        Disjuncts, Solns, !Info),
+                    ml_gen_lookup_disj(OutVars, Solns, Context,
+                        Statements, !Info)
+                ;
+                    ml_gen_ordinary_model_non_disj(FirstDisjunct,
+                        LaterDisjuncts, Context, Statements, !Info)
+                )
+            ;
+                ( CodeModel = model_det
+                ; CodeModel = model_semi
+                ),
+                ml_gen_ordinary_model_det_semi_disj(FirstDisjunct,
+                    LaterDisjuncts, CodeModel, Context, Statements, !Info)
+            )
+        )
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred ml_gen_ordinary_model_det_semi_disj(hlds_goal::in, list(hlds_goal)::in,
+    code_model::in, prog_context::in, list(statement)::out,
+    ml_gen_info::in, ml_gen_info::out) is det.
+
+ml_gen_ordinary_model_det_semi_disj(FirstDisjunct, LaterDisjuncts, CodeModel,
+        Context, Statements, !Info) :-
+    (
+        LaterDisjuncts = [],
+        ml_gen_goal_as_branch_block(CodeModel, FirstDisjunct, Statement,
+            !Info),
+        Statements = [Statement]
+    ;
+        LaterDisjuncts = [FirstLaterDisjunct | LaterLaterDisjuncts],
+        % model_det/model_semi disj:
+        %
+        %   model_det goal:
+        %       <Goal ; Goals>
+        %   ===>
+        %       <Goal>
+        %       /* <Goals> will never be reached */
+        %
+        %   model_semi goal:
+        %       <Goal ; Goals>
+        %   ===>
+        %   {
+        %       MR_bool succeeded;
+        %
+        %       <succeeded = Goal>;
+        %       if (!succeeded) {
+        %           <Goals>;
+        %       }
+        %   }
+
+        FirstDisjunct = hlds_goal(_, FirstGoalInfo),
+        FirstCodeModel = goal_info_get_code_model(FirstGoalInfo),
+        (
+            FirstCodeModel = model_det,
+            ml_gen_goal_as_branch_block(model_det, FirstDisjunct, Statement,
+                !Info),
+            Statements = [Statement]
+        ;
+            FirstCodeModel = model_semi,
+            ml_gen_goal_as_branch_block(model_semi, FirstDisjunct,
+                FirstStatement, !Info),
+            ml_gen_test_success(!.Info, Succeeded),
+            ml_gen_ordinary_model_det_semi_disj(FirstLaterDisjunct,
+                LaterLaterDisjuncts, CodeModel, Context, LaterStatements,
+                !Info),
+            LaterStatement = ml_gen_block([], LaterStatements, Context),
+            IfStmt = ml_stmt_if_then_else(
+                ml_unop(std_unop(logical_not), Succeeded),
+                LaterStatement, no),
+            IfStatement = statement(IfStmt, mlds_make_context(Context)),
+            Statements = [FirstStatement, IfStatement]
+        ;
+            FirstCodeModel = model_non,
+            % simplify.m should get wrap commits around these.
+            unexpected(this_file,
+                "model_non disjunct in model_det or model_semi disjunction")
+        )
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred ml_gen_ordinary_model_non_disj(hlds_goal::in, list(hlds_goal)::in,
+    prog_context::in, list(statement)::out,
+    ml_gen_info::in, ml_gen_info::out) is det.
+
+ml_gen_ordinary_model_non_disj(FirstDisjunct, LaterDisjuncts, Context,
+        Statements, !Info) :-
+    (
+        LaterDisjuncts = [],
+        ml_gen_goal_as_branch_block(model_non, FirstDisjunct, Statement,
+            !Info),
+        Statements = [Statement]
+    ;
+        LaterDisjuncts = [FirstLaterDisjunct | LaterLaterDisjuncts],
+        % model_non disj:
+        %
+        %       <(Goal ; Goals) && SUCCEED()>
+        %   ===>
+        %       <Goal && SUCCEED()>
+        %       <Goals && SUCCEED()>
+
+        ml_gen_goal_as_branch_block(model_non, FirstDisjunct, FirstStatement,
+            !Info),
+        ml_gen_ordinary_model_non_disj(FirstLaterDisjunct, LaterLaterDisjuncts,
+            Context, LaterStatements, !Info),
+        Statements = [FirstStatement | LaterStatements]
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred ml_gen_lookup_disj(list(prog_var)::in, list(list(mlds_rval))::in,
+    prog_context::in, list(statement)::out,
+    ml_gen_info::in, ml_gen_info::out) is det.
+
+ml_gen_lookup_disj(OutVars, Solns, Context, Statements, !Info) :-
+    ml_gen_info_get_module_info(!.Info, ModuleInfo),
+    module_info_get_name(ModuleInfo, ModuleName),
+    MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
+    MLDS_Context = mlds_make_context(Context),
+    ml_gen_info_get_target(!.Info, Target),
+
+    ml_gen_info_get_var_types(!.Info, VarTypes),
+    list.map(map.lookup(VarTypes), OutVars, FieldTypes),
+    MLDS_FieldTypes =
+        list.map(mercury_type_to_mlds_type(ModuleInfo), FieldTypes),
+
+    ml_gen_info_get_global_data(!.Info, GlobalData0),
+    ml_gen_static_vector_type(MLDS_ModuleName, MLDS_Context, Target,
+        MLDS_FieldTypes, StructTypeNum, StructType, FieldIds,
+        GlobalData0, GlobalData1),
+
+    ml_construct_disjunction_vector(ModuleInfo, StructType, Solns,
+        RowInitializers),
+    list.length(RowInitializers, NumRows),
+
+    ml_gen_static_vector_defn(MLDS_ModuleName, StructTypeNum, RowInitializers,
+        VectorCommon, GlobalData1, GlobalData),
+    ml_gen_info_set_global_data(GlobalData, !Info),
+
+    ml_gen_info_new_aux_var_name("slot", SlotVar, !Info),
+    SlotVarType = mlds_native_int_type,
+    % We never need to trace ints.
+    SlotVarGCStatement = gc_no_stmt,
+    SlotVarDefn = ml_gen_mlds_var_decl(mlds_data_var(SlotVar),
+        SlotVarType, SlotVarGCStatement, MLDS_Context),
+    ml_gen_var_lval(!.Info, SlotVar, SlotVarType, SlotVarLval),
+    SlotVarRval = ml_lval(SlotVarLval),
+
+    ml_generate_field_assigns(OutVars, MLDS_FieldTypes, FieldIds,
+        VectorCommon, StructType, SlotVarRval, MLDS_Context, LookupStatements,
+        !Info),
+    ml_gen_call_current_success_cont(Context, CallContStatement, !Info),
+
+    InitSlotVarStmt = ml_stmt_atomic(assign(SlotVarLval,
+        ml_const(mlconst_int(0)))),
+    InitSlotVarStatement = statement(InitSlotVarStmt, MLDS_Context),
+
+    IncrSlotVarStmt = ml_stmt_atomic(assign(SlotVarLval,
+        ml_binop(int_add, SlotVarRval, ml_const(mlconst_int(1))))),
+    IncrSlotVarStatement = statement(IncrSlotVarStmt, MLDS_Context),
+
+    LoopBodyStmt = ml_stmt_block([],
+        LookupStatements ++ [CallContStatement, IncrSlotVarStatement]),
+    LoopBodyStatement = statement(LoopBodyStmt, MLDS_Context),
+
+    LoopCond = ml_binop(int_lt, SlotVarRval, ml_const(mlconst_int(NumRows))),
+    LoopStmt = ml_stmt_while(loop_at_least_once, LoopCond, LoopBodyStatement),
+    LoopStatement = statement(LoopStmt, MLDS_Context),
+
+    Stmt = ml_stmt_block([SlotVarDefn], [InitSlotVarStatement, LoopStatement]),
+    Statement = statement(Stmt, MLDS_Context),
+    Statements = [Statement].
+
+:- pred ml_construct_disjunction_vector(module_info::in, mlds_type::in,
+        list(list(mlds_rval))::in, list(mlds_initializer)::out) is det.
+
+ml_construct_disjunction_vector(_ModuleInfo, _StructType, [], []).
+ml_construct_disjunction_vector(ModuleInfo, StructType,
+        [Soln | Solns], [RowInitializer | RowInitializers]) :-
+    FieldInitializers = list.map(wrap_init_obj, Soln),
+    RowInitializer = init_struct(StructType, FieldInitializers),
+    ml_construct_disjunction_vector(ModuleInfo, StructType,
+        Solns, RowInitializers).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "ml_disj_gen.m".
+
+%-----------------------------------------------------------------------------%
+:- end_module ml_disj_gen.
+%-----------------------------------------------------------------------------%
Index: ml_elim_nested.m
--- /home/zs/mer/ws00/compiler/ml_elim_nested.m	2009-09-21 15:23:04.000000000 +1000
+++ ml_elim_nested.m	2009-09-28 13:23:44.000000000 +1000
@@ -1448,10 +1448,10 @@
             !Info),
         Stmt = ml_stmt_block(Defns, Statements)
     ;
-        Stmt0 = ml_stmt_while(Rval0, Statement0, Once),
+        Stmt0 = ml_stmt_while(Kind, Rval0, Statement0),
         fixup_rval(Action, !.Info, Rval0, Rval),
         flatten_statement(Action, Statement0, Statement, !Info),
-        Stmt = ml_stmt_while(Rval, Statement, Once)
+        Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         Stmt0 = ml_stmt_if_then_else(Cond0, Then0, MaybeElse0),
         fixup_rval(Action, !.Info, Cond0, Cond),
@@ -2270,7 +2270,7 @@
         ; statements_contains_matching_defn(Filter, Statements)
         )
     ;
-        Stmt = ml_stmt_while(_Rval, Statement, _Once),
+        Stmt = ml_stmt_while(_Kind, _Rval, Statement),
         statement_contains_matching_defn(Filter, Statement)
     ;
         Stmt = ml_stmt_if_then_else(_Cond, Then, MaybeElse),
@@ -2411,9 +2411,9 @@
             !Info),
         Stmt = ml_stmt_block(Defns, Statements)
     ;
-        Stmt0 = ml_stmt_while(Rval, Statement0, Once),
+        Stmt0 = ml_stmt_while(Kind, Rval, Statement0),
         add_unchain_stack_to_statement(Action, Statement0, Statement, !Info),
-        Stmt = ml_stmt_while(Rval, Statement, Once)
+        Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         Stmt0 = ml_stmt_if_then_else(Cond, Then0, MaybeElse0),
         add_unchain_stack_to_statement(Action, Then0, Then, !Info),
Index: ml_lookup_switch.m
--- /home/zs/mer/ws00/compiler/ml_lookup_switch.m	2009-09-25 15:15:29.000000000 +1000
+++ ml_lookup_switch.m	2009-09-29 11:10:20.000000000 +1000
@@ -31,7 +31,7 @@
 :- pred ml_gen_lookup_switch(prog_var::in, list(tagged_case)::in,
     set(prog_var)::in, code_model::in, prog_context::in,
     int::in, int::in, need_bit_vec_check::in, need_range_check::in,
-    list(statement)::out, ml_gen_info::in, ml_gen_info::out) is semidet.
+    statement::out, ml_gen_info::in, ml_gen_info::out) is semidet.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -47,6 +47,7 @@
 :- import_module ml_backend.ml_code_gen.
 :- import_module ml_backend.ml_code_util.
 :- import_module ml_backend.ml_global_data.
+:- import_module ml_backend.ml_util.
 
 :- import_module assoc_list.
 :- import_module bool.
@@ -59,15 +60,17 @@
 %-----------------------------------------------------------------------------%
 
 ml_gen_lookup_switch(SwitchVar, TaggedCases, NonLocals, CodeModel, Context,
-        StartVal, EndVal, NeedBitVecCheck, NeedRangeCheck, Statements,
-        !Info) :-
+        StartVal, EndVal, NeedBitVecCheck, NeedRangeCheck, Statement, !Info) :-
     set.remove(NonLocals, SwitchVar, OtherNonLocals),
     set.to_sorted_list(OtherNonLocals, OutVars),
-    ml_generate_constants_for_lookup_switch(CodeModel, OtherNonLocals, OutVars,
-        TaggedCases, map.init, CaseSolnMap, no, GoalsMayModifyTrail, !Info),
-
-    % XXX We should implement the case GoalsMayModifyTrail = yes.
-    GoalsMayModifyTrail = no,
+    ml_generate_constants_for_lookup_switch(CodeModel, OutVars, OtherNonLocals,
+        TaggedCases, map.init, CaseSolnMap, !Info),
+    % While the LLDS backend has to worry about about implementing trailing
+    % for model_non lookup switches, we do not. The MLDS backend implements
+    % trailing by a HLDS-to-HLDS transform (which is in add_trail_ops.m),
+    % so we can get here only if trailing is not enabled, since otherwise
+    % the calls or foreign_procs inserted into all non-first disjuncts
+    % would have caused ml_generate_constants_for_lookup_switch to fail.
 
     ml_gen_var(!.Info, SwitchVar, SwitchVarLval),
     SwitchVarRval = ml_lval(SwitchVarLval),
@@ -83,11 +86,13 @@
         list.reverse(RevCaseValuePairs, CaseValuePairs),
         ml_gen_simple_lookup_switch(IndexRval, OutVars, CaseValuePairs,
             CodeModel, Context, StartVal, EndVal,
-            NeedBitVecCheck, NeedRangeCheck, Statement, !Info),
-        Statements = [Statement]
+            NeedBitVecCheck, NeedRangeCheck, Statement, !Info)
     ;
-        % XXX We should implement this case.
-        fail
+        expect(unify(CodeModel, model_non), this_file,
+            "ml_gen_lookup_switch: CodeModel != model_non"),
+        ml_gen_model_non_lookup_switch(IndexRval, OutVars, CaseSolns,
+            Context, StartVal, EndVal, NeedBitVecCheck, NeedRangeCheck,
+            Statement, !Info)
     ).
 
 %-----------------------------------------------------------------------------%
@@ -115,14 +120,14 @@
         MLDS_FieldTypes, StructTypeNum, StructType, FieldIds,
         GlobalData0, GlobalData1),
 
-    ml_construct_simple_vector(ModuleInfo, Context, StructType,
+    ml_construct_simple_switch_vector(ModuleInfo, StructType,
         MLDS_FieldTypes, StartVal, CaseValues, RowInitializers),
 
     ml_gen_static_vector_defn(MLDS_ModuleName, StructTypeNum, RowInitializers,
         VectorCommon, GlobalData1, GlobalData),
     ml_gen_info_set_global_data(GlobalData, !Info),
 
-    ml_generate_offset_assigns(OutVars, MLDS_FieldTypes, FieldIds,
+    ml_generate_field_assigns(OutVars, MLDS_FieldTypes, FieldIds,
         VectorCommon, StructType, IndexRval, MLDS_Context, LookupStatements,
         !Info),
 
@@ -138,26 +143,43 @@
         CodeModel = model_semi,
         ml_gen_set_success(!.Info, ml_const(mlconst_true), Context,
             SetSuccessTrueStatement),
-        LookupStmt = ml_stmt_block([],
+        LookupSucceedStmt = ml_stmt_block([],
             LookupStatements ++ [SetSuccessTrueStatement]),
-        LookupStatement = statement(LookupStmt, MLDS_Context),
+        LookupSucceedStatement = statement(LookupSucceedStmt, MLDS_Context),
+        (
+            NeedRangeCheck = dont_need_range_check,
         (
+                NeedBitVecCheck = dont_need_bit_vec_check,
+                Statement = LookupSucceedStatement
+            ;
+                NeedBitVecCheck = need_bit_vec_check,
+                ml_generate_bitvec_test(MLDS_ModuleName, Context, IndexRval,
+                    CaseValues, StartVal, EndVal, BitVecCheckCond, !Info),
+
+                ml_gen_set_success(!.Info, ml_const(mlconst_false), Context,
+                    SetSuccessFalseStatement),
+
+                Stmt = ml_stmt_if_then_else(BitVecCheckCond,
+                    LookupSucceedStatement, yes(SetSuccessFalseStatement)),
+                Statement = statement(Stmt, MLDS_Context)
+            )
+        ;
             NeedRangeCheck = need_range_check,
             Difference = EndVal - StartVal,
-            RangeCheckRval = ml_binop(unsigned_le, IndexRval,
+            RangeCheckCond = ml_binop(unsigned_le, IndexRval,
                 ml_const(mlconst_int(Difference))),
             ml_gen_set_success(!.Info, ml_const(mlconst_false), Context,
                 SetSuccessFalseStatement),
             (
                 NeedBitVecCheck = dont_need_bit_vec_check,
-                RangeCheckSuccessStatement = LookupStatement
+                RangeCheckSuccessStatement = LookupSucceedStatement
             ;
                 NeedBitVecCheck = need_bit_vec_check,
                 ml_generate_bitvec_test(MLDS_ModuleName, Context, IndexRval,
-                    CaseValues, StartVal, EndVal, BitVecCheckRval, !Info),
+                    CaseValues, StartVal, EndVal, BitVecCheckCond, !Info),
 
-                RangeCheckSuccessStmt = ml_stmt_if_then_else(BitVecCheckRval,
-                    LookupStatement, yes(SetSuccessFalseStatement)),
+                RangeCheckSuccessStmt = ml_stmt_if_then_else(BitVecCheckCond,
+                    LookupSucceedStatement, yes(SetSuccessFalseStatement)),
                 RangeCheckSuccessStatement =
                     statement(RangeCheckSuccessStmt, MLDS_Context)
             ),
@@ -165,32 +187,184 @@
             % We want to execute the bit vector test only if the range check
             % succeeded, since otherwise the bit vector test will probably
             % access the bit vector outside its bounds.
-            Stmt = ml_stmt_if_then_else(RangeCheckRval,
+            Stmt = ml_stmt_if_then_else(RangeCheckCond,
                 RangeCheckSuccessStatement, yes(SetSuccessFalseStatement)),
             Statement = statement(Stmt, MLDS_Context)
+        )
         ;
-            NeedRangeCheck = dont_need_range_check,
+        CodeModel = model_non,
+        % If all the switch arms have exactly one solution, then the switch
+        % as a whole cannot be model_non.
+        unexpected(this_file, "ml_gen_simple_lookup_switch: model_non")
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred ml_gen_model_non_lookup_switch(mlds_rval::in, list(prog_var)::in,
+    assoc_list(int, soln_consts(mlds_rval))::in, prog_context::in,
+    int::in, int::in, need_bit_vec_check::in, need_range_check::in,
+    statement::out, ml_gen_info::in, ml_gen_info::out) is det.
+
+ml_gen_model_non_lookup_switch(IndexRval, OutVars, CaseSolns, Context,
+        StartVal, EndVal, NeedBitVecCheck, NeedRangeCheck, Statement,
+        !Info) :-
+    ml_gen_info_get_module_info(!.Info, ModuleInfo),
+    module_info_get_name(ModuleInfo, ModuleName),
+    MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
+    MLDS_Context = mlds_make_context(Context),
+    ml_gen_info_get_target(!.Info, Target),
+
+    MLDS_IntType = mlds_native_int_type,
+
+    ml_gen_info_new_aux_var_name("num_later_solns", NumLaterSolnsVar, !Info),
+    % We never need to trace ints.
+    NumLaterSolnsVarDefn = ml_gen_mlds_var_decl(mlds_data_var(NumLaterSolnsVar),
+        MLDS_IntType, gc_no_stmt, MLDS_Context),
+    ml_gen_var_lval(!.Info, NumLaterSolnsVar, MLDS_IntType,
+        NumLaterSolnsVarLval),
+    NumLaterSolnsVarRval = ml_lval(NumLaterSolnsVarLval),
+
+    ml_gen_info_new_aux_var_name("later_slot", LaterSlotVar, !Info),
+    % We never need to trace ints.
+    LaterSlotVarDefn = ml_gen_mlds_var_decl(mlds_data_var(LaterSlotVar),
+        MLDS_IntType, gc_no_stmt, MLDS_Context),
+    ml_gen_var_lval(!.Info, LaterSlotVar, MLDS_IntType, LaterSlotVarLval),
+    LaterSlotVarRval = ml_lval(LaterSlotVarLval),
+
+    ml_gen_info_new_aux_var_name("limit", LimitVar, !Info),
+    % We never need to trace ints.
+    LimitVarDefn = ml_gen_mlds_var_decl(mlds_data_var(LimitVar),
+        MLDS_IntType, gc_no_stmt, MLDS_Context),
+    ml_gen_var_lval(!.Info, LimitVar, MLDS_IntType, LimitVarLval),
+    LimitVarRval = ml_lval(LimitVarLval),
+
+    ml_gen_info_get_var_types(!.Info, VarTypes),
+    list.map(map.lookup(VarTypes), OutVars, FieldTypes),
+    MLDS_FieldTypes =
+        list.map(mercury_type_to_mlds_type(ModuleInfo), FieldTypes),
+    FirstSolnFieldTypes = [MLDS_IntType, MLDS_IntType | MLDS_FieldTypes],
+    LaterSolnFieldTypes = MLDS_FieldTypes,
+
+    ml_gen_call_current_success_cont(Context, CallContStatement, !Info),
+
+    ml_gen_info_get_global_data(!.Info, GlobalData0),
+    ml_gen_static_vector_type(MLDS_ModuleName, MLDS_Context, Target,
+        FirstSolnFieldTypes, FirstSolnStructTypeNum, FirstSolnStructType,
+        FirstSolnTableFieldIds, GlobalData0, GlobalData1),
+    ml_gen_static_vector_type(MLDS_ModuleName, MLDS_Context, Target,
+        LaterSolnFieldTypes, LaterSolnStructTypeNum, LaterSolnStructType,
+        LaterSolnFieldIds, GlobalData1, GlobalData2),
+    (
+        ( FirstSolnTableFieldIds = []
+        ; FirstSolnTableFieldIds = [_]
+        ),
+        unexpected(this_file,
+            "ml_gen_model_non_lookup_switch: not enough field_ids")
+    ;
+        FirstSolnTableFieldIds =
+            [NumLaterSolnsFieldId, FirstLaterRowFieldId | FirstSolnFieldIds]
+    ),
+
+    ml_construct_model_non_switch_vector(ModuleInfo, StartVal, EndVal,
+        0, CaseSolns,
+        FirstSolnStructType, LaterSolnStructType, LaterSolnFieldTypes,
+        FirstSolnRowInitializers, LaterSolnRowInitializers,
+        no, HadDummyRows),
+
+    ml_gen_static_vector_defn(MLDS_ModuleName, FirstSolnStructTypeNum,
+        FirstSolnRowInitializers, FirstSolnVectorCommon,
+        GlobalData2, GlobalData3),
+    ml_gen_static_vector_defn(MLDS_ModuleName, LaterSolnStructTypeNum,
+        LaterSolnRowInitializers, LaterSolnVectorCommon,
+        GlobalData3, GlobalData),
+    ml_gen_info_set_global_data(GlobalData, !Info),
+
+    ml_generate_field_assign(NumLaterSolnsVarLval, MLDS_IntType,
+        NumLaterSolnsFieldId,
+        FirstSolnVectorCommon, FirstSolnStructType, IndexRval,
+        MLDS_Context, NumLaterSolnsLookupStatement, !Info),
+    ml_generate_field_assign(LaterSlotVarLval, MLDS_IntType,
+        FirstLaterRowFieldId,
+        FirstSolnVectorCommon, FirstSolnStructType, IndexRval,
+        MLDS_Context, LaterSlotVarLookupStatement, !Info),
+    % We must use LaterSolnFieldTypes here, since we handle the assignments
+    % from the first two fields separately.
+    ml_generate_field_assigns(OutVars, LaterSolnFieldTypes, FirstSolnFieldIds,
+        FirstSolnVectorCommon, FirstSolnStructType, IndexRval,
+        MLDS_Context, FirstSolnLookupStatements, !Info),
+    ml_generate_field_assigns(OutVars, LaterSolnFieldTypes, LaterSolnFieldIds,
+        LaterSolnVectorCommon, LaterSolnStructType, LaterSlotVarRval,
+        MLDS_Context, LaterSolnLookupStatements, !Info),
+
+    LimitAssignStmt = ml_stmt_atomic(assign(LimitVarLval, 
+        ml_binop(int_add, LaterSlotVarRval, NumLaterSolnsVarRval))),
+    LimitAssignStatement = statement(LimitAssignStmt, MLDS_Context),
+
+    IncrLaterSlotVarStmt = ml_stmt_atomic(assign(LaterSlotVarLval,
+        ml_binop(int_add, LaterSlotVarRval, ml_const(mlconst_int(1))))),
+    IncrLaterSlotVarStatement = statement(IncrLaterSlotVarStmt, MLDS_Context),
+
+    FirstLookupSucceedStmt = ml_stmt_block([],
+        FirstSolnLookupStatements ++ [CallContStatement]),
+    FirstLookupSucceedStatement =
+        statement(FirstLookupSucceedStmt, MLDS_Context),
+
+    LaterLookupSucceedStmt = ml_stmt_block([],
+        LaterSolnLookupStatements ++
+        [CallContStatement, IncrLaterSlotVarStatement]),
+    LaterLookupSucceedStatement =
+        statement(LaterLookupSucceedStmt, MLDS_Context),
+
+    MoreSolnsLoopCond = ml_binop(int_lt, LaterSlotVarRval, LimitVarRval),
+    MoreSolnsLoopStmt = ml_stmt_while(may_loop_zero_times, MoreSolnsLoopCond,
+        LaterLookupSucceedStatement),
+    MoreSolnsLoopStatement = statement(MoreSolnsLoopStmt, MLDS_Context),
+
+    OneOrMoreSolnsStatements = [FirstLookupSucceedStatement,
+        LaterSlotVarLookupStatement, LimitAssignStatement,
+        MoreSolnsLoopStatement],
+
             (
                 NeedBitVecCheck = dont_need_bit_vec_check,
-                Statement = LookupStatement
+        expect(unify(HadDummyRows, no), this_file,
+            "ml_gen_model_non_lookup_switch: bad dont_need_bit_vec_check"),
+        InRangeStmt = ml_stmt_block(
+            [NumLaterSolnsVarDefn, LaterSlotVarDefn, LimitVarDefn],
+            [NumLaterSolnsLookupStatement | OneOrMoreSolnsStatements]),
+        InRangeStatement = statement(InRangeStmt, MLDS_Context)
             ;
                 NeedBitVecCheck = need_bit_vec_check,
-                ml_generate_bitvec_test(MLDS_ModuleName, Context, IndexRval,
-                    CaseValues, StartVal, EndVal, BitVecCheckRval, !Info),
+        expect(unify(HadDummyRows, yes), this_file,
+            "ml_gen_model_non_lookup_switch: bad need_bit_vec_check"),
 
-                ml_gen_set_success(!.Info, ml_const(mlconst_false), Context,
-                    SetSuccessFalseStatement),
+        OneOrMoreSolnsBlockStmt = ml_stmt_block([], OneOrMoreSolnsStatements),
+        OneOrMoreSolnsBlockStatement =
+            statement(OneOrMoreSolnsBlockStmt, MLDS_Context),
+
+        AnySolnsCond = ml_binop(int_ge,
+            NumLaterSolnsVarRval, ml_const(mlconst_int(0))),
+        ZeroOrMoreSolnsStmt = ml_stmt_if_then_else(AnySolnsCond,
+            OneOrMoreSolnsBlockStatement, no),
+        ZeroOrMoreSolnsStatement =
+            statement(ZeroOrMoreSolnsStmt, MLDS_Context),
+
+        InRangeStmt = ml_stmt_block(
+            [NumLaterSolnsVarDefn, LaterSlotVarDefn, LimitVarDefn],
+            [NumLaterSolnsLookupStatement, ZeroOrMoreSolnsStatement]),
+        InRangeStatement = statement(InRangeStmt, MLDS_Context)
+    ),
+    (
+        NeedRangeCheck = dont_need_range_check,
+        Statement = InRangeStatement
+    ;
+        NeedRangeCheck = need_range_check,
+        Difference = EndVal - StartVal,
 
-                Stmt = ml_stmt_if_then_else(BitVecCheckRval,
-                    LookupStatement, yes(SetSuccessFalseStatement)),
+        RangeCheckCond = ml_binop(unsigned_le, IndexRval,
+            ml_const(mlconst_int(Difference))),
+
+        Stmt = ml_stmt_if_then_else(RangeCheckCond, InRangeStatement, no),
                 Statement = statement(Stmt, MLDS_Context)
-            )
-        )
-    ;
-        CodeModel = model_non,
-        % If all the switch arms have exactly one solution, then the switch
-        % as a whole cannot be model_non.
-        unexpected(this_file, "ml_gen_simple_lookup_switch: model_non")
     ).
 
 %-----------------------------------------------------------------------------%
@@ -302,12 +476,12 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred ml_construct_simple_vector(module_info::in, prog_context::in,
+:- pred ml_construct_simple_switch_vector(module_info::in,
     mlds_type::in, list(mlds_type)::in, int::in,
     assoc_list(int, list(mlds_rval))::in, list(mlds_initializer)::out) is det.
 
-ml_construct_simple_vector(_, _, _, _, _, [], []).
-ml_construct_simple_vector(ModuleInfo, Context, StructType, FieldTypes,
+ml_construct_simple_switch_vector(_, _, _, _, [], []).
+ml_construct_simple_switch_vector(ModuleInfo, StructType, FieldTypes,
         CurIndex, [Pair | Pairs], [RowInitializer | RowInitializers]) :-
     Pair = Index - Rvals,
     ( CurIndex < Index ->
@@ -319,12 +493,114 @@
     ),
     FieldInitializers = list.map(wrap_init_obj, FieldRvals),
     RowInitializer = init_struct(StructType, FieldInitializers),
-    ml_construct_simple_vector(ModuleInfo, Context, StructType, FieldTypes,
+    ml_construct_simple_switch_vector(ModuleInfo, StructType, FieldTypes,
         CurIndex + 1, RemainingPairs, RowInitializers).
 
-:- func wrap_init_obj(mlds_rval) = mlds_initializer.
+:- pred ml_construct_model_non_switch_vector(module_info::in,
+    int::in, int::in, int::in, assoc_list(int, soln_consts(mlds_rval))::in,
+    mlds_type::in, mlds_type::in, list(mlds_type)::in,
+    list(mlds_initializer)::out, list(mlds_initializer)::out,
+    bool::in, bool::out) is det.
+
+ml_construct_model_non_switch_vector(ModuleInfo, CurIndex, EndVal,
+        NextLaterSolnRow, [],
+        FirstSolnStructType, LaterSolnStructType, FieldTypes,
+        FirstSolnRowInitializers, LaterSolnRowInitializers, !HadDummyRows) :-
+    ( CurIndex > EndVal ->
+        FirstSolnRowInitializers = [],
+        LaterSolnRowInitializers = []
+    ;
+        !:HadDummyRows = yes,
+        FieldRvals = list.map(ml_default_value_for_type, FieldTypes),
+        FieldInitializers = list.map(wrap_init_obj, FieldRvals),
+        NumLaterSolnsInitializer = gen_init_int(-1),
+        FirstLaterSlotInitializer = gen_init_int(-1),
+        FirstSolnFieldInitializers =
+            [NumLaterSolnsInitializer, FirstLaterSlotInitializer
+                | FieldInitializers],
+        FirstSolnRowInitializer =
+            init_struct(FirstSolnStructType, FirstSolnFieldInitializers),
+        ml_construct_model_non_switch_vector(ModuleInfo, CurIndex + 1, EndVal,
+            NextLaterSolnRow, [],
+            FirstSolnStructType, LaterSolnStructType, FieldTypes,
+            FirstSolnRowInitializersTail, LaterSolnRowInitializers,
+            !HadDummyRows),
+        FirstSolnRowInitializers =
+            [FirstSolnRowInitializer | FirstSolnRowInitializersTail]
+    ).
+ml_construct_model_non_switch_vector(ModuleInfo, CurIndex, EndVal,
+        NextLaterSolnRow, [Pair | Pairs],
+        FirstSolnStructType, LaterSolnStructType, FieldTypes,
+        FirstSolnRowInitializers, LaterSolnRowInitializers, !HadDummyRows) :-
+    Pair = Index - Soln,
+    ( CurIndex < Index ->
+        !:HadDummyRows = yes,
+        FieldRvals = list.map(ml_default_value_for_type, FieldTypes),
+        FieldInitializers = list.map(wrap_init_obj, FieldRvals),
+        NumLaterSolnsInitializer = gen_init_int(-1),
+        FirstLaterSlotInitializer = gen_init_int(-1),
+        FirstSolnFieldInitializers =
+            [NumLaterSolnsInitializer, FirstLaterSlotInitializer
+                | FieldInitializers],
+        FirstSolnRowInitializer =
+            init_struct(FirstSolnStructType, FirstSolnFieldInitializers),
+        ml_construct_model_non_switch_vector(ModuleInfo, CurIndex + 1, EndVal,
+            NextLaterSolnRow, [Pair | Pairs],
+            FirstSolnStructType, LaterSolnStructType, FieldTypes,
+            FirstSolnRowInitializersTail, LaterSolnRowInitializers,
+            !HadDummyRows),
+        FirstSolnRowInitializers =
+            [FirstSolnRowInitializer | FirstSolnRowInitializersTail]
+    ;
+        (
+            Soln = one_soln(FieldRvals),
+            FieldInitializers = list.map(wrap_init_obj, FieldRvals),
+            NumLaterSolnsInitializer = gen_init_int(0),
+            FirstLaterSlotInitializer = gen_init_int(-1),
+            FirstSolnFieldInitializers =
+                [NumLaterSolnsInitializer, FirstLaterSlotInitializer
+                    | FieldInitializers],
+            FirstSolnRowInitializer =
+                init_struct(FirstSolnStructType, FirstSolnFieldInitializers),
+            ml_construct_model_non_switch_vector(ModuleInfo,
+                CurIndex + 1, EndVal, NextLaterSolnRow, Pairs,
+                FirstSolnStructType, LaterSolnStructType, FieldTypes,
+                FirstSolnRowInitializersTail, LaterSolnRowInitializers,
+                !HadDummyRows),
+            FirstSolnRowInitializers =
+                [FirstSolnRowInitializer | FirstSolnRowInitializersTail]
+        ;
+            Soln = several_solns(FirstSolnRvals, LaterSolns),
+            FieldInitializers = list.map(wrap_init_obj, FirstSolnRvals),
+            list.length(LaterSolns, NumLaterSolns),
+            NumLaterSolnsInitializer = gen_init_int(NumLaterSolns),
+            FirstLaterSlotInitializer = gen_init_int(NextLaterSolnRow),
+            FirstSolnFieldInitializers =
+                [NumLaterSolnsInitializer, FirstLaterSlotInitializer
+                    | FieldInitializers],
+            HeadLaterSolnRowInitializers = list.map(
+                ml_construct_later_soln_row(LaterSolnStructType),
+                LaterSolns),
+            FirstSolnRowInitializer =
+                init_struct(FirstSolnStructType, FirstSolnFieldInitializers),
+            ml_construct_model_non_switch_vector(ModuleInfo,
+                CurIndex + 1, EndVal, NextLaterSolnRow + NumLaterSolns, Pairs,
+                FirstSolnStructType, LaterSolnStructType, FieldTypes,
+                FirstSolnRowInitializersTail, LaterSolnRowInitializersTail,
+                !HadDummyRows),
+            FirstSolnRowInitializers =
+                [FirstSolnRowInitializer | FirstSolnRowInitializersTail],
+            LaterSolnRowInitializers =
+                HeadLaterSolnRowInitializers ++ LaterSolnRowInitializersTail
+        )
+    ).
 
-wrap_init_obj(Rval) = init_obj(Rval).
+:- func ml_construct_later_soln_row(mlds_type, list(mlds_rval)) =
+    mlds_initializer.
+
+ml_construct_later_soln_row(StructType, Rvals) = RowInitializer :-
+    FieldInitializers = list.map(wrap_init_obj, Rvals),
+    RowInitializer = init_struct(StructType, FieldInitializers).
 
 :- func ml_default_value_for_type(mlds_type) = mlds_rval.
 
@@ -366,72 +642,46 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred ml_generate_offset_assigns(list(prog_var)::in, list(mlds_type)::in,
-    list(mlds_field_id)::in, mlds_vector_common::in, mlds_type::in,
-    mlds_rval::in, mlds_context::in, list(statement)::out,
-    ml_gen_info::in, ml_gen_info::out) is det.
-
-ml_generate_offset_assigns(OutVars, FieldTypes, FieldIds, VectorCommon,
-        StructType, IndexRval, Context, Statements, !Info) :-
-    (
-        OutVars = [],
-        FieldTypes = [],
-        FieldIds = []
-    ->
-        Statements = []
-    ;
-        OutVars = [HeadOutVar | TailOutVars],
-        FieldTypes = [HeadFieldType | TailFieldTypes],
-        FieldIds = [HeadFieldId | TailFieldIds]
-    ->
-        ml_generate_offset_assigns(TailOutVars, TailFieldTypes, TailFieldIds,
-            VectorCommon, StructType, IndexRval, Context, TailStatements,
-            !Info),
-
-        ml_gen_var(!.Info, HeadOutVar, HeadOutVarLval),
-        BaseRval = ml_vector_common_row(VectorCommon, IndexRval),
-        HeadFieldLval = ml_field(yes(0), BaseRval, HeadFieldId,
-            HeadFieldType, StructType),
-        HeadAtomicStmt = assign(HeadOutVarLval, ml_lval(HeadFieldLval)),
-        HeadStmt = ml_stmt_atomic(HeadAtomicStmt),
-        HeadStatement = statement(HeadStmt, Context),
-
-        Statements = [HeadStatement | TailStatements]
-    ;
-        unexpected(this_file, "ml_generate_offset_assigns: mismatched lists")
-    ).
-
-%-----------------------------------------------------------------------------%
-
 :- pred ml_generate_constants_for_lookup_switch(code_model::in,
-    set(prog_var)::in, list(prog_var)::in, list(tagged_case)::in,
+    list(prog_var)::in, set(prog_var)::in, list(tagged_case)::in,
     map(int, soln_consts(mlds_rval))::in,
     map(int, soln_consts(mlds_rval))::out,
-    bool::in, bool::out, ml_gen_info::in, ml_gen_info::out) is semidet.
+    ml_gen_info::in, ml_gen_info::out) is semidet.
 
-ml_generate_constants_for_lookup_switch(_CodeModel, _NonLocals, _OutVars,
-        [], !IndexMap, !GoalsMayModifyTrail, !Info).
-ml_generate_constants_for_lookup_switch(CodeModel, NonLocals, OutVars,
-        [TaggedCase | TaggedCases], !IndexMap, !GoalsMayModifyTrail, !Info) :-
+ml_generate_constants_for_lookup_switch(_CodeModel, _OutVars, _ArmNonLocals,
+        [], !IndexMap, !Info).
+ml_generate_constants_for_lookup_switch(CodeModel, OutVars, ArmNonLocals,
+        [TaggedCase | TaggedCases], !IndexMap, !Info) :-
     TaggedCase = tagged_case(TaggedMainConsId, TaggedOtherConsIds, _, Goal),
-    Goal = hlds_goal(GoalExpr, GoalInfo),
+    Goal = hlds_goal(GoalExpr, _GoalInfo),
     ( GoalExpr = disj(Disjuncts) ->
-        bool.or(goal_may_modify_trail(GoalInfo), !GoalsMayModifyTrail),
-        ml_all_disjuncts_are_conj_of_unify(NonLocals, Disjuncts),
-        ml_generate_constants_for_disjuncts(CodeModel, OutVars, Disjuncts,
-            Solns, !Info),
-        SolnConsts = several_solns(Solns)
-    ;
-        ml_goal_is_conj_of_unify(NonLocals, Goal),
-        ml_generate_constants_for_arm(CodeModel, OutVars, Goal, Soln, !Info),
-        SolnConsts = one_soln(Soln)
-    ),
+        (
+            Disjuncts = []
+        ;
+            Disjuncts = [FirstDisjunct | LaterDisjuncts],
+            goal_is_conj_of_unify(ArmNonLocals, FirstDisjunct),
+            all_disjuncts_are_conj_of_unify(ArmNonLocals, LaterDisjuncts),
+            ml_generate_constants_for_arm(OutVars, FirstDisjunct, FirstSoln,
+                !Info),
+            ml_generate_constants_for_arms(OutVars, LaterDisjuncts, LaterSolns,
+                !Info),
+            SolnConsts = several_solns(FirstSoln, LaterSolns),
+            ml_record_lookup_for_tagged_cons_id(SolnConsts,
+                TaggedMainConsId, !IndexMap),
+            list.foldl(ml_record_lookup_for_tagged_cons_id(SolnConsts),
+                TaggedOtherConsIds, !IndexMap)
+        )
+    ;
+        goal_is_conj_of_unify(ArmNonLocals, Goal),
+        ml_generate_constants_for_arm(OutVars, Goal, Soln, !Info),
+        SolnConsts = one_soln(Soln),
     ml_record_lookup_for_tagged_cons_id(SolnConsts,
         TaggedMainConsId, !IndexMap),
     list.foldl(ml_record_lookup_for_tagged_cons_id(SolnConsts),
-        TaggedOtherConsIds, !IndexMap),
-    ml_generate_constants_for_lookup_switch(CodeModel, NonLocals, OutVars,
-        TaggedCases, !IndexMap, !GoalsMayModifyTrail, !Info).
+            TaggedOtherConsIds, !IndexMap)
+    ),
+    ml_generate_constants_for_lookup_switch(CodeModel, OutVars, ArmNonLocals,
+        TaggedCases, !IndexMap, !Info).
 
 :- pred ml_record_lookup_for_tagged_cons_id(soln_consts(mlds_rval)::in,
     tagged_cons_id::in,
@@ -447,89 +697,6 @@
             "ml_record_lookup_for_tagged_cons_id: not int_tag")
     ).
 
-:- pred ml_generate_constants_for_disjuncts(code_model::in, list(prog_var)::in,
-    list(hlds_goal)::in, list(list(mlds_rval))::out,
-    ml_gen_info::in, ml_gen_info::out) is semidet.
-
-ml_generate_constants_for_disjuncts(_CodeModel, _Vars, [], [], !Info).
-ml_generate_constants_for_disjuncts(CodeModel, Vars,
-        [Goal | Goals], [Soln | Solns], !Info) :-
-    ml_generate_constants_for_arm(CodeModel, Vars, Goal, Soln, !Info),
-    ml_generate_constants_for_disjuncts(CodeModel, Vars, Goals, Solns, !Info).
-
-:- pred ml_generate_constants_for_arm(code_model::in, list(prog_var)::in,
-    hlds_goal::in, list(mlds_rval)::out,
-    ml_gen_info::in, ml_gen_info::out) is semidet.
-
-ml_generate_constants_for_arm(CodeModel, Vars, Goal, Soln, !Info) :-
-    ml_gen_info_get_const_var_map(!.Info, InitConstVarMap),
-    ml_gen_goal(CodeModel, Goal, _Decls, _Statements, !Info),
-    ml_gen_info_get_const_var_map(!.Info, FinalConstVarMap),
-    ml_gen_info_set_const_var_map(InitConstVarMap, !Info),
-    list.map(search_ground_rval(FinalConstVarMap), Vars, Soln).
-
-:- pred search_ground_rval(ml_ground_term_map::in, prog_var::in,
-    mlds_rval::out) is semidet.
-
-search_ground_rval(FinalConstVarMap, Var, Rval) :-
-    map.search(FinalConstVarMap, Var, GroundTerm),
-    GroundTerm = ml_ground_term(Rval, _, _).
-
-%-----------------------------------------------------------------------------%
-
-    % Is the input goal a conjunction of unifications? A
-    % from_ground_term_construct scope counts as a unification.
-    %
-    % Unlike goal_is_conj_of_unify in lookup_util, we also insist that
-    % (a) the unification be a static construction, and (b) the only nonlocal
-    % variables being constructed be in the provided set.
-    %
-:- pred ml_goal_is_conj_of_unify(set(prog_var)::in, hlds_goal::in) is semidet.
-
-ml_goal_is_conj_of_unify(AllowedVars, Goal) :-
-    Goal = hlds_goal(_GoalExpr, GoalInfo),
-    CodeModel = goal_info_get_code_model(GoalInfo),
-    CodeModel = model_det,
-    NonLocals = goal_info_get_nonlocals(GoalInfo),
-    goal_to_conj_list(Goal, Conj),
-    ml_only_constant_goals(NonLocals, AllowedVars, Conj).
-
-    % Run ml_goal_is_conj_of_unify on each goal in the list.
-    %
-:- pred ml_all_disjuncts_are_conj_of_unify(set(prog_var)::in,
-    list(hlds_goal)::in) is semidet.
-
-ml_all_disjuncts_are_conj_of_unify(_AllowedVars, []).
-ml_all_disjuncts_are_conj_of_unify(AllowedVars, [Disjunct | Disjuncts]) :-
-    ml_goal_is_conj_of_unify(AllowedVars, Disjunct),
-    ml_all_disjuncts_are_conj_of_unify(AllowedVars, Disjuncts).
-
-:- pred ml_only_constant_goals(set(prog_var)::in, set(prog_var)::in,
-    list(hlds_goal)::in) is semidet.
-
-ml_only_constant_goals(_NonLocals, AllowedVars0, []) :-
-    set.empty(AllowedVars0).
-ml_only_constant_goals(NonLocals, AllowedVars0, [Goal | Goals]) :-
-    Goal = hlds_goal(GoalExpr, _),
-    % We could allow calls as well. Some procedures have an output inst
-    % that fixes the value of the output variable, which is thus a constant.
-    % However, calls to such procedures should have been inlined by now.
-    (
-        GoalExpr = unify(_, _, _, Unify, _),
-        Unify = construct(Var, _, _, _, construct_statically, _, _)
-    ;
-        GoalExpr = scope(Reason, _),
-        Reason = from_ground_term(Var, from_ground_term_construct)
-    ),
-    ( set.member(Var, NonLocals) ->
-        set.remove(AllowedVars0, Var, AllowedVars)
-    ;
-        % The conjunction is allowed to bind local variables, since these
-        % may later be used to construct variables in AllowedVars0.
-        AllowedVars = AllowedVars0
-    ),
-    ml_only_constant_goals(NonLocals, AllowedVars, Goals).
-
 %-----------------------------------------------------------------------------%
 
 :- func this_file = string.
Index: ml_optimize.m
--- /home/zs/mer/ws00/compiler/ml_optimize.m	2009-09-21 15:23:04.000000000 +1000
+++ ml_optimize.m	2009-09-28 13:24:57.000000000 +1000
@@ -171,9 +171,9 @@
         optimize_in_statements(OptInfo, Statements3, Statements),
         Stmt = ml_stmt_block(Defns, Statements)
     ;
-        Stmt0 = ml_stmt_while(Rval, Statement0, Once),
+        Stmt0 = ml_stmt_while(Kind, Rval, Statement0),
         optimize_in_statement(OptInfo, Statement0, Statement),
-        Stmt = ml_stmt_while(Rval, Statement, Once)
+        Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         Stmt0 = ml_stmt_if_then_else(Rval, Then0, MaybeElse0),
         optimize_in_statement(OptInfo, Then0, Then),
@@ -443,12 +443,12 @@
             %   }
             % Any tail calls in the function body will have
             % been replaced with `continue' statements.
-            Stmt = ml_stmt_while(ml_const(mlconst_true),
+            Stmt = ml_stmt_while(may_loop_zero_times, ml_const(mlconst_true),
                 statement(ml_stmt_block([],
                     [CommentStmt,
                     statement(Stmt0, Context),
                     statement(ml_stmt_goto(goto_break), Context)]),
-                Context), no)
+                Context))
         ;
             % Add a loop_top label at the start of the function
             % body:
@@ -1118,10 +1118,10 @@
             !VarElimInfo),
         Stmt = ml_stmt_block(Defns, Statements)
     ;
-        Stmt0 = ml_stmt_while(Rval0, Statement0, Once),
+        Stmt0 = ml_stmt_while(Kind, Rval0, Statement0),
         eliminate_var_in_rval(Rval0, Rval, !VarElimInfo),
         eliminate_var_in_statement(Statement0, Statement, !VarElimInfo),
-        Stmt = ml_stmt_while(Rval, Statement, Once)
+        Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         Stmt0 = ml_stmt_if_then_else(Cond0, Then0, MaybeElse0),
         eliminate_var_in_rval(Cond0, Cond, !VarElimInfo),
Index: ml_string_switch.m
--- /home/zs/mer/ws00/compiler/ml_string_switch.m	2009-09-25 15:15:29.000000000 +1000
+++ ml_string_switch.m	2009-09-28 13:42:32.000000000 +1000
@@ -191,7 +191,7 @@
             GotoEndStatement
         ]),
         MLDS_Context),
-    LoopBody = ml_gen_block([], [
+    LoopBody = statement(ml_stmt_block([], [
         statement(ml_stmt_atomic(comment(
             "lookup the string for this hash slot")), MLDS_Context),
         statement(
@@ -212,8 +212,8 @@
                     ml_vector_common_row(VectorCommon, SlotVarRval),
                     NextSlotFieldId, MLDS_NextSlotType, StructType)))),
             MLDS_Context)
-        ],
-        Context),
+        ]),
+        MLDS_Context),
     HashLookupStatements = [
         statement(ml_stmt_atomic(comment("hashed string switch")),
             MLDS_Context),
@@ -228,11 +228,11 @@
         statement(ml_stmt_atomic(comment("hash chain loop")), MLDS_Context),
         statement(
             ml_stmt_while(
+                loop_at_least_once,
                 ml_binop(int_ge,
                     ml_lval(SlotVarLval),
                     ml_const(mlconst_int(0))),
-                LoopBody,
-                yes), % This is a do...while loop.
+                LoopBody),
             MLDS_Context)
         ],
     EndLabelStatement = statement(ml_stmt_label(EndLabel), MLDS_Context),
Index: ml_switch_gen.m
--- /home/zs/mer/ws00/compiler/ml_switch_gen.m	2009-09-25 15:15:29.000000000 +1000
+++ ml_switch_gen.m	2009-09-28 20:30:04.000000000 +1000
@@ -232,9 +232,9 @@
                 NonLocals = goal_info_get_nonlocals(GoalInfo),
                 ml_gen_lookup_switch(SwitchVar, FilteredTaggedCases,
                     NonLocals, CodeModel, Context, FirstVal, LastVal,
-                    NeedBitVecCheck, NeedRangeCheck, StatementsPrime, !Info)
+                    NeedBitVecCheck, NeedRangeCheck, LookupStatement, !Info)
             ->
-                Statements = StatementsPrime
+                Statements = [LookupStatement]
             ;
                 target_supports_computed_goto(Globals)
             ->
Index: ml_tailcall.m
--- /home/zs/mer/ws00/compiler/ml_tailcall.m	2009-09-21 15:23:04.000000000 +1000
+++ ml_tailcall.m	2009-09-28 13:25:10.000000000 +1000
@@ -253,9 +253,9 @@
     ;
         % The statement in the body of a while loop is never in a tail
         % position.
-        Stmt0 = ml_stmt_while(Rval, Statement0, Once),
+        Stmt0 = ml_stmt_while(Kind, Rval, Statement0),
         mark_tailcalls_in_statement(no, Locals, Statement0, Statement),
-        Stmt = ml_stmt_while(Rval, Statement, Once)
+        Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         % Both the `then' and the `else' parts of an if-then-else are in a
         % tail position iff the if-then-else is in a tail position.
Index: ml_util.m
--- /home/zs/mer/ws00/compiler/ml_util.m	2009-09-21 15:23:04.000000000 +1000
+++ ml_util.m	2009-09-28 13:56:29.000000000 +1000
@@ -185,6 +185,8 @@
 :- func gen_init_reserved_address(module_info, reserved_address) =
     mlds_initializer.
 
+:- func wrap_init_obj(mlds_rval) = mlds_initializer.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -272,7 +274,7 @@
         Stmt = ml_stmt_block(_Defns, Statements),
         statements_contains_statement(Statements, SubStatement)
     ;
-        Stmt = ml_stmt_while(_Rval, Statement, _Once),
+        Stmt = ml_stmt_while(_Kind, _Rval, Statement),
         statement_contains_statement(Statement, SubStatement)
     ;
         Stmt = ml_stmt_if_then_else(_Cond, Then, MaybeElse),
@@ -359,7 +361,7 @@
             ContainsVar = statements_contains_var(Statements, DataName)
         )
     ;
-        Stmt = ml_stmt_while(Rval, Statement, _Once),
+        Stmt = ml_stmt_while(_Kind, Rval, Statement),
         ( rval_contains_var(Rval, DataName) = yes ->
             ContainsVar = yes
         ;
@@ -915,4 +917,6 @@
     init_obj(ml_gen_reserved_address(ModuleInfo, ReservedAddress,
         mlds_generic_type)).
 
+wrap_init_obj(Rval) = init_obj(Rval).
+
 %-----------------------------------------------------------------------------%
Index: mlds.m
--- /home/zs/mer/ws00/compiler/mlds.m	2009-09-21 15:23:04.000000000 +1000
+++ mlds.m	2009-09-28 13:21:16.000000000 +1000
@@ -991,6 +991,10 @@
                 mlds_context
             ).
 
+:- type while_loop_kind
+    --->    may_loop_zero_times
+    ;       loop_at_least_once.
+
 :- type mlds_stmt
     % Sequence.
 
@@ -998,7 +1002,7 @@
 
     % Iteration.
 
-    ;       ml_stmt_while(mlds_rval, statement, bool)
+    ;       ml_stmt_while(while_loop_kind, mlds_rval, statement)
             % The `bool' is true iff the loop is guaranteed to iterate at
             % least once -- in that case, the compiler can generate a
             % `do...while' loop rather than a `while...' loop.
Index: mlds_to_c.m
--- /home/zs/mer/ws00/compiler/mlds_to_c.m	2009-09-21 15:23:04.000000000 +1000
+++ mlds_to_c.m	2009-09-29 11:33:32.000000000 +1000
@@ -1582,7 +1582,13 @@
     io.write_string("[]", !IO),
     mlds_output_type_suffix(Opts, Type, InitArraySize, !IO),
     io.write_string(" = {\n", !IO),
-    list.foldl(mlds_output_cell(Opts, Indent + 1), Rows, !IO),
+/* ###  In clause for predicate */
+/* ###    `mlds_output_scalar_cell_group_defn'/6: */
+/* ###    in argument 1 of call to predicate `list.foldl2'/6: */
+/* ###    type error: argument has type `pred(int, int, */
+/* ###    ml_backend.mlds.mlds_initializer, io.state, io.state)', */
+/* ###    expected type was `pred(L, A, A, Z, Z)'. */
+    list.foldl2(mlds_output_cell(Opts, Indent + 1), Rows, 0, _, !IO),
     io.write_string("};\n", !IO).
 
 :- pred mlds_output_vector_cell_group_defns(mlds_to_c_opts::in, indent::in,
@@ -1619,13 +1625,18 @@
     io.write_string("[]", !IO),
     mlds_output_type_suffix(Opts, Type, no_size, !IO),
     io.write_string(" = {\n", !IO),
-    list.foldl(mlds_output_cell(Opts, Indent + 1), Rows, !IO),
+    list.foldl2(mlds_output_cell(Opts, Indent + 1), Rows, 0, _, !IO),
     io.write_string("};\n", !IO).
 
-:- pred mlds_output_cell(mlds_to_c_opts::in, indent::in,
-    mlds_initializer::in, io::di, io::uo) is det.
+:- pred mlds_output_cell(mlds_to_c_opts::in, indent::in, mlds_initializer::in,
+    int::in, int::out, io::di, io::uo) is det.
 
-mlds_output_cell(Opts, Indent, Initializer, !IO) :-
+mlds_output_cell(Opts, Indent, Initializer, !RowNum, !IO) :-
+    mlds_indent(Indent, !IO),
+    io.write_string("/* row ", !IO),
+    io.write_int(!.RowNum, !IO),
+    io.write_string(" */\n", !IO),
+    !:RowNum = !.RowNum + 1,
     mlds_output_initializer_body(Opts, Indent, Initializer, !IO),
     io.write_string(",\n", !IO).
 
@@ -3045,9 +3056,9 @@
         mlds_output_context_and_indent(Context, Indent, !IO),
         io.write_string("}\n", !IO)
     ;
-        Stmt = ml_stmt_while(Cond, LoopStatement, AtLeastOnce),
+        Stmt = ml_stmt_while(Kind, Cond, LoopStatement),
         (
-            AtLeastOnce = no,
+            Kind = may_loop_zero_times,
             mlds_indent(Indent, !IO),
             io.write_string("while (", !IO),
             mlds_output_rval(Opts, Cond, !IO),
@@ -3055,7 +3066,7 @@
             mlds_output_statement(Opts, Indent + 1, FuncInfo, LoopStatement,
                 !IO)
         ;
-            AtLeastOnce = yes,
+            Kind = loop_at_least_once,
             mlds_indent(Indent, !IO),
             io.write_string("do\n", !IO),
             mlds_output_statement(Opts, Indent + 1, FuncInfo, LoopStatement,
Index: mlds_to_gcc.m
--- /home/zs/mer/ws00/compiler/mlds_to_gcc.m	2009-09-21 15:23:04.000000000 +1000
+++ mlds_to_gcc.m	2009-09-28 13:38:00.000000000 +1000
@@ -2746,17 +2746,16 @@
     %
     % iteration
     %
-gen_stmt(DefnInfo, ml_stmt_while(Cond, Statement, AtLeastOneIteration),
-        _Context) -->
+gen_stmt(DefnInfo, ml_stmt_while(Kind, Cond, Statement), _Context) -->
     gcc__gen_start_loop(Loop),
     build_rval(Cond, DefnInfo, GCC_Cond),
     (
-        { AtLeastOneIteration = yes },
+        { Kind = loop_at_least_once },
         % generate the test at the end of the loop
         gen_statement(DefnInfo, Statement),
         gcc__gen_exit_loop_if_false(Loop, GCC_Cond)
     ;
-        { AtLeastOneIteration = no },
+        { Kind = may_loop_zero_times },
         % generate the test at the start of the loop
         gcc__gen_exit_loop_if_false(Loop, GCC_Cond),
         gen_statement(DefnInfo, Statement)
Index: mlds_to_il.m
--- /home/zs/mer/ws00/compiler/mlds_to_il.m	2009-09-21 15:23:04.000000000 +1000
+++ mlds_to_il.m	2009-09-28 13:27:31.000000000 +1000
@@ -472,9 +472,9 @@
 rename_statement(statement(ml_stmt_block(Defns, Stmts), Context))
     = statement(ml_stmt_block(list.map(rename_defn, Defns),
         list.map(rename_statement, Stmts)), Context).
-rename_statement(statement(ml_stmt_while(Rval, Loop, IterateOnce), Context))
-    = statement(ml_stmt_while(rename_rval(Rval),
-        rename_statement(Loop), IterateOnce), Context).
+rename_statement(statement(ml_stmt_while(Kind, Rval, Loop), Context))
+    = statement(ml_stmt_while(Kind, rename_rval(Rval), rename_statement(Loop)),
+        Context).
 rename_statement(statement(ml_stmt_if_then_else(Rval, Then, MaybeElse),
         Context)) =
     statement(ml_stmt_if_then_else(rename_rval(Rval),
@@ -1772,12 +1772,12 @@
     unexpected(this_file, "`switch' not supported").
 
 statement_to_il(statement(WhileStmt, Context), Instrs, !Info) :-
-    WhileStmt = ml_stmt_while(Condition, Body, AtLeastOnce),
+    WhileStmt = ml_stmt_while(Kind, Condition, Body),
     generate_condition(Condition, ConditionInstrs, EndLabel, !Info),
     il_info_make_next_label(StartLabel, !Info),
     statement_to_il(Body, BodyInstrs, !Info),
     (
-        AtLeastOnce = no,
+        Kind = may_loop_zero_times,
         Instrs =
             context_node(Context) ++
             comment_node("while") ++
@@ -1787,7 +1787,7 @@
             singleton(br(label_target(StartLabel))) ++
             singleton(label(EndLabel))
     ;
-        AtLeastOnce = yes,
+        Kind = loop_at_least_once,
         % XXX This generates a branch over branch which is suboptimal.
         Instrs =
             context_node(Context) ++
Index: mlds_to_java.m
--- /home/zs/mer/ws00/compiler/mlds_to_java.m	2009-09-25 14:18:58.000000000 +1000
+++ mlds_to_java.m	2009-09-28 13:38:41.000000000 +1000
@@ -628,7 +628,7 @@
 method_ptrs_in_stmt(ml_stmt_block(Defns, Statements), !CodeAddrs) :-
     method_ptrs_in_defns(Defns, !CodeAddrs),
     method_ptrs_in_statements(Statements, !CodeAddrs).
-method_ptrs_in_stmt(ml_stmt_while(Rval, Statement, _Bool), !CodeAddrs) :-
+method_ptrs_in_stmt(ml_stmt_while(_Kind, Rval, Statement), !CodeAddrs) :-
     method_ptrs_in_rval(Rval, !CodeAddrs),
     method_ptrs_in_statement(Statement, !CodeAddrs).
 method_ptrs_in_stmt(ml_stmt_if_then_else(Rval, StatementThen,
@@ -1326,10 +1326,10 @@
             Statements0, Statements),
         !:Stmt = ml_stmt_block(Defns, Statements)
     ;
-        !.Stmt = ml_stmt_while(Rval0, Statement0, AtLeastOnce),
+        !.Stmt = ml_stmt_while(Kind, Rval0, Statement0),
         rename_class_names_rval(Renaming, Rval0, Rval),
         rename_class_names_statement(Renaming, Statement0, Statement),
-        !:Stmt = ml_stmt_while(Rval, Statement, AtLeastOnce)
+        !:Stmt = ml_stmt_while(Kind, Rval, Statement)
     ;
         !.Stmt = ml_stmt_if_then_else(Rval0, Statement0, MaybeElse0),
         rename_class_names_rval(Renaming, Rval0, Rval),
@@ -3120,10 +3120,10 @@
 :- pred output_stmt(indent::in, module_info::in, func_info::in, mlds_stmt::in,
     mlds_context::in, exit_methods::out, io::di, io::uo) is det.
 
-    % sequence
-    %
-output_stmt(Indent, ModuleInfo, FuncInfo, ml_stmt_block(Defns, Statements),
-        Context, ExitMethods, !IO) :-
+output_stmt(Indent, ModuleInfo, FuncInfo, Statement, Context, ExitMethods,
+        !IO) :-
+    (
+        Statement = ml_stmt_block(Defns, Statements),
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
     (
@@ -3137,15 +3137,14 @@
     output_statements(Indent + 1, ModuleInfo, FuncInfo, Statements,
         ExitMethods, !IO),
     indent_line(Context, Indent, !IO),
-    io.write_string("}\n", !IO).
-
-    % iteration
-    %
-output_stmt(Indent, ModuleInfo, FuncInfo, ml_stmt_while(Cond, Statement, no),
-        _, ExitMethods, !IO) :-
+        io.write_string("}\n", !IO)
+    ;
+        Statement = ml_stmt_while(Kind, Cond, BodyStatement),
+        Kind = may_loop_zero_times,
     indent_line(Indent, !IO),
     io.write_string("while (", !IO),
-    output_rval(ModuleInfo, Cond, FuncInfo ^ func_info_name ^ mod_name, !IO),
+        ModuleName = FuncInfo ^ func_info_name ^ mod_name,
+        output_rval(ModuleInfo, Cond, ModuleName, !IO),
     io.write_string(")\n", !IO),
     % The contained statement is reachable iff the while statement is
     % reachable and the condition expression is not a constant expression
@@ -3155,27 +3154,25 @@
         io.write_string("{  /* Unreachable code */  }\n", !IO),
         ExitMethods = set.make_singleton_set(can_fall_through)
     ;
-        output_statement(Indent + 1, ModuleInfo, FuncInfo, Statement,
+            output_statement(Indent + 1, ModuleInfo, FuncInfo, BodyStatement,
             StmtExitMethods, !IO),
         ExitMethods = while_exit_methods(Cond, StmtExitMethods)
-    ).
-output_stmt(Indent, ModuleInfo, FuncInfo, ml_stmt_while(Cond, Statement, yes),
-        Context, ExitMethods, !IO) :-
+        )
+    ;
+        Statement = ml_stmt_while(Kind, Cond, BodyStatement),
+        Kind = loop_at_least_once,
     indent_line(Indent, !IO),
     io.write_string("do\n", !IO),
-    output_statement(Indent + 1, ModuleInfo, FuncInfo, Statement,
+        output_statement(Indent + 1, ModuleInfo, FuncInfo, BodyStatement,
         StmtExitMethods, !IO),
     indent_line(Context, Indent, !IO),
     io.write_string("while (", !IO),
-    output_rval(ModuleInfo, Cond, FuncInfo ^ func_info_name ^ mod_name, !IO),
+        ModuleName = FuncInfo ^ func_info_name ^ mod_name,
+        output_rval(ModuleInfo, Cond, ModuleName, !IO),
     io.write_string(");\n", !IO),
-    ExitMethods = while_exit_methods(Cond, StmtExitMethods).
-
-    % selection (if-then-else)
-    %
-output_stmt(Indent, ModuleInfo, FuncInfo,
-        ml_stmt_if_then_else(Cond, Then0, MaybeElse),
-        Context, ExitMethods, !IO) :-
+        ExitMethods = while_exit_methods(Cond, StmtExitMethods)
+    ;
+        Statement = ml_stmt_if_then_else(Cond, Then0, MaybeElse),
     % We need to take care to avoid problems caused by the dangling else
     % ambiguity.
     (
@@ -3187,9 +3184,9 @@
         %   else
         %       ...
         %
-        % we need braces around the inner `if', otherwise they wouldn't parse
-        % they way we want them to: Java would match the `else' with the
-        % inner `if' rather than the outer `if'.
+            % we need braces around the inner `if', otherwise they wouldn't
+            % parse they way we want them to: Java would match the `else'
+            % with the inner `if' rather than the outer `if'.
 
         MaybeElse = yes(_),
         Then0 = statement(ml_stmt_if_then_else(_, _, no), ThenContext)
@@ -3201,10 +3198,11 @@
 
     indent_line(Indent, !IO),
     io.write_string("if (", !IO),
-    output_rval(ModuleInfo, Cond, FuncInfo ^ func_info_name ^ mod_name, !IO),
+        ModuleName = FuncInfo ^ func_info_name ^ mod_name,
+        output_rval(ModuleInfo, Cond, ModuleName, !IO),
     io.write_string(")\n", !IO),
-    output_statement(Indent + 1, ModuleInfo, FuncInfo, Then, ThenExitMethods,
-        !IO),
+        output_statement(Indent + 1, ModuleInfo, FuncInfo, Then,
+            ThenExitMethods, !IO),
     (
         MaybeElse = yes(Else),
         indent_line(Context, Indent, !IO),
@@ -3220,13 +3218,9 @@
         % An if-then statement can complete normally iff it is reachable.
         ExitMethods = ThenExitMethods `set.union`
             set.make_singleton_set(can_fall_through)
-    ).
-
-    % selection (switch)
-    %
-output_stmt(Indent, ModuleInfo, FuncInfo,
-        ml_stmt_switch(_Type, Val, _Range, Cases, Default),
-        Context, ExitMethods, !IO) :-
+        )
+    ;
+        Statement = ml_stmt_switch(_Type, Val, _Range, Cases, Default),
     indent_line(Context, Indent, !IO),
     io.write_string("switch (", !IO),
     output_rval_maybe_with_enum(ModuleInfo, Val,
@@ -3235,36 +3229,32 @@
     output_switch_cases(Indent + 1, ModuleInfo, FuncInfo, Context, Cases,
         Default, ExitMethods, !IO),
     indent_line(Context, Indent, !IO),
-    io.write_string("}\n", !IO).
-
-    % transfer of control
-    %
-output_stmt(_, _, _, ml_stmt_label(_), _, _, _, _)  :-
-    unexpected(this_file, "output_stmt: labels not supported in Java.").
-output_stmt(_, _, _, ml_stmt_goto(goto_label(_)), _, _, _, _) :-
-    unexpected(this_file, "output_stmt: gotos not supported in Java.").
-output_stmt(Indent, _, _FuncInfo, ml_stmt_goto(goto_break), _Context,
-        ExitMethods, !IO) :-
+        io.write_string("}\n", !IO)
+    ;
+        Statement = ml_stmt_label(_),
+        unexpected(this_file, "output_stmt: labels not supported in Java.")
+    ;
+        Statement = ml_stmt_goto(goto_label(_)),
+        unexpected(this_file, "output_stmt: gotos not supported in Java.")
+    ;
+        Statement = ml_stmt_goto(goto_break),
     indent_line(Indent, !IO),
     io.write_string("break;\n", !IO),
-    ExitMethods = set.make_singleton_set(can_break).
-output_stmt(Indent, _, _FuncInfo, ml_stmt_goto(goto_continue), _Context,
-        ExitMethods, !IO) :-
+        ExitMethods = set.make_singleton_set(can_break)
+    ;
+        Statement = ml_stmt_goto(goto_continue),
     indent_line(Indent, !IO),
     io.write_string("continue;\n", !IO),
-    ExitMethods = set.make_singleton_set(can_continue).
-output_stmt(_, _, _, ml_stmt_computed_goto(_, _), _, _, _, _) :-
+        ExitMethods = set.make_singleton_set(can_continue)
+    ;
+        Statement = ml_stmt_computed_goto(_, _),
     unexpected(this_file,
-        "output_stmt: computed gotos not supported in Java.").
-
-    % function call/return
-    %
-output_stmt(Indent, ModuleInfo, CallerFuncInfo, Call, Context, ExitMethods,
-        !IO) :-
-    Call = ml_stmt_call(Signature, FuncRval, MaybeObject, CallArgs, Results,
-        _IsTailCall),
+            "output_stmt: computed gotos not supported in Java.")
+    ;
+        Statement = ml_stmt_call(Signature, FuncRval, MaybeObject, CallArgs,
+            Results, _IsTailCall),
     Signature = mlds_func_signature(ArgTypes, RetTypes),
-    ModuleName = CallerFuncInfo ^ func_info_name ^ mod_name,
+        ModuleName = FuncInfo ^ func_info_name ^ mod_name,
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
     indent_line(Context, Indent + 1, !IO),
@@ -3309,10 +3299,10 @@
         % something of type java.lang.Object
         %
         % XXX This is a hack, I can't see any way to do this downcasting
-        % nicely, as it needs to effectively be wrapped around the method call
-        % itself, so it acts before this predicate's solution to multiple
-        % return values, see above.
-        %
+            % nicely, as it needs to effectively be wrapped around the method
+            % call itself, so it acts before this predicate's solution to
+            % multiple return values, see above.
+
         (
             RetTypes = []
         ;
@@ -3345,13 +3335,14 @@
             io.write_string(") ", !IO),
             output_bracketed_rval(ModuleInfo, FuncRval, ModuleName, !IO),
             io.write_string(").call___0_0(", !IO),
-            output_boxed_args(ModuleInfo, CallArgs, ArgTypes, ModuleName, !IO)
+                output_boxed_args(ModuleInfo, CallArgs, ArgTypes,
+                    ModuleName, !IO)
         ;
             io.write_string("((jmercury.runtime.MethodPtrN) ", !IO),
             output_bracketed_rval(ModuleInfo, FuncRval, ModuleName, !IO),
             io.write_string(").call___0_0(", !IO),
-            output_args_as_array(ModuleInfo, CallArgs, ArgTypes, ModuleName,
-                !IO)
+                output_args_as_array(ModuleInfo, CallArgs, ArgTypes,
+                    ModuleName, !IO)
         ),
 
         % Closes brackets, and calls unbox methods for downcasting.
@@ -3395,10 +3386,9 @@
     %
     indent_line(Indent, !IO),
     io.write_string("}\n", !IO),
-    ExitMethods = set.make_singleton_set(can_fall_through).
-
-output_stmt(Indent, ModuleInfo, FuncInfo, ml_stmt_return(Results), _,
-        ExitMethods, !IO) :-
+        ExitMethods = set.make_singleton_set(can_fall_through)
+    ;
+        Statement = ml_stmt_return(Results),
     (
         Results = [],
         indent_line(Indent, !IO),
@@ -3428,33 +3418,31 @@
         indent_line(Indent, !IO),
         io.write_string("};\n", !IO)
     ),
-    ExitMethods = set.make_singleton_set(can_return).
-
-output_stmt(Indent, ModuleInfo, FuncInfo, DoCommitStmt, _, ExitMethods,
-        !IO) :-
-    DoCommitStmt = ml_stmt_do_commit(Ref),
+        ExitMethods = set.make_singleton_set(can_return)
+    ;
+        Statement = ml_stmt_do_commit(Ref),
     indent_line(Indent, !IO),
-    output_rval(ModuleInfo, Ref, FuncInfo ^ func_info_name ^ mod_name, !IO),
+        ModuleName = FuncInfo ^ func_info_name ^ mod_name,
+        output_rval(ModuleInfo, Ref, ModuleName, !IO),
     io.write_string(" = new jmercury.runtime.Commit();\n", !IO),
     indent_line(Indent, !IO),
     io.write_string("throw ", !IO),
-    output_rval(ModuleInfo, Ref, FuncInfo ^ func_info_name ^ mod_name, !IO),
+        output_rval(ModuleInfo, Ref, ModuleName, !IO),
     io.write_string(";\n", !IO),
-    ExitMethods = set.make_singleton_set(can_throw).
-
-output_stmt(Indent, ModuleInfo, FuncInfo, TryCommitStmt, _, ExitMethods,
-        !IO) :-
-    TryCommitStmt = ml_stmt_try_commit(_Ref, Stmt, Handler),
+        ExitMethods = set.make_singleton_set(can_throw)
+    ;
+        Statement = ml_stmt_try_commit(_Ref, Stmt, Handler),
     indent_line(Indent, !IO),
     io.write_string("try\n", !IO),
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
-    output_statement(Indent + 1, ModuleInfo, FuncInfo, Stmt, TryExitMethods0,
-        !IO),
+        output_statement(Indent + 1, ModuleInfo, FuncInfo, Stmt,
+            TryExitMethods0, !IO),
     indent_line(Indent, !IO),
     io.write_string("}\n", !IO),
     indent_line(Indent, !IO),
-    io.write_string("catch (jmercury.runtime.Commit commit_variable)\n", !IO),
+        io.write_string("catch (jmercury.runtime.Commit commit_variable)\n",
+            !IO),
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
     indent_line(Indent + 1, !IO),
@@ -3463,23 +3451,13 @@
     indent_line(Indent, !IO),
     io.write_string("}\n", !IO),
     ExitMethods = (TryExitMethods0 `set.delete` can_throw)
-        `set.union`  CatchExitMethods.
-
-    % exception handling
-    %
-
-    % XXX not yet implemented
-
-    % atomic statements
-    %
-output_stmt(Indent, ModuleInfo, FuncInfo, AtomicStmt, Context, ExitMethods,
-        !IO) :-
-    AtomicStmt = ml_stmt_atomic(AtomicStatement),
-    output_atomic_stmt(Indent, ModuleInfo, FuncInfo, AtomicStatement, Context,
-        !IO),
-    ExitMethods = set.make_singleton_set(can_fall_through).
-    % Returns a set of exit_methods that describes whether the while
-    % statement can complete normally.
+            `set.union`  CatchExitMethods
+    ;
+        Statement = ml_stmt_atomic(AtomicStatement),
+        output_atomic_stmt(Indent, ModuleInfo, FuncInfo, AtomicStatement,
+            Context, !IO),
+        ExitMethods = set.make_singleton_set(can_fall_through)
+    ).
 
 %-----------------------------------------------------------------------------%
 %
Index: switch_util.m
--- /home/zs/mer/ws00/compiler/switch_util.m	2009-09-21 15:23:05.000000000 +1000
+++ switch_util.m	2009-09-28 15:12:34.000000000 +1000
@@ -128,7 +128,8 @@
 
 :- type soln_consts(Rval)
     --->    one_soln(list(Rval))
-    ;       several_solns(list(list(Rval))).
+    ;       several_solns(list(Rval), list(list(Rval))).
+            % The first solution, and all the later solutions.
 
 :- type need_range_check
     --->    need_range_check
@@ -691,8 +692,8 @@
         Soln = one_soln(Rvals),
         !:RvalsList = [Rvals | !.RvalsList]
     ;
-        Soln = several_solns(SolnRvalsList),
-        !:RvalsList = SolnRvalsList ++ !.RvalsList
+        Soln = several_solns(FirstSolnRvals, LaterSolnsRvalsList),
+        !:RvalsList = [FirstSolnRvals | LaterSolnsRvalsList] ++ !.RvalsList
     ),
     project_solns_to_rval_lists(Cases, !RvalsList).
 
cvs diff: Diffing compiler/notes
Index: compiler_design.html
--- /home/zs/mer/ws00/compiler/notes/compiler_design.html	2009-09-25 15:15:29.000000000 +1000
+++ compiler_design.html	2009-09-27 00:59:19.000000000 +1000
@@ -1560,14 +1560,15 @@
 <li> ml_proc_gen.m is the top module of the package that converts HLDS code
      to MLDS. Its main submodule is ml_code_gen.m, which handles the tasks
      common to all kinds of goals, as well as the tasks specific to some
-     goals (conjunctions, disjunctions, if-then-elses, negations). For other
-     kinds of goals, ml_code_gen.m invokes some other submodules:
+     goals (conjunctions, if-then-elses, negations). For other kinds of goals,
+     ml_code_gen.m invokes some other submodules:
 	<ul>
 	<li> ml_unify_gen.m
 	<li> ml_closure_gen.m
 	<li> ml_call_gen.m
 	<li> ml_foreign_proc_gen.m
 	<li> ml_commit_gen.m
+	<li> ml_disj_gen.m
 	<li> ml_switch_gen.m, which calls upon:
 		<ul>
 		<li> ml_lookup_switch.m
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
Index: dense_lookup_switch_non.exp
--- /home/zs/mer/ws00/tests/hard_coded/dense_lookup_switch_non.exp	2007-02-15 16:19:05.000000000 +1100
+++ dense_lookup_switch_non.exp	2009-09-29 11:48:56.000000000 +1000
@@ -1,31 +1,136 @@
-a ->
+p1 a ->
+p1_one f1 1.1
 end
 
-b ->
+p1 b ->
+p1_two f2 2.2
 end
 
-c ->
+p1 c ->
+p1_three f1 3.3
 end
 
-d ->
-four f1 4.4
+p1 d ->
+p1_four f1 4.4
 end
 
-e ->
-five f2 5.5
-five2 f3(5) 55.5
+p1 e ->
+p1_five f2 5.5
+p1_five2 f3(5) 55.5
 end
 
-f ->
-six f4("hex") 6.6
+p1 f ->
+p1_six f4("hex") 6.6
 end
 
-g ->
-seven f5(77.7) 7.7
-seven2 f1 777.7
-seven3 f2 7777.7
+p1 g ->
+p1_seven f5(77.7) 7.7
+p1_seven2 f1 777.7
+p1_seven3 f2 7777.7
 end
 
-h ->
+p1 h ->
+p1_eight f1 8.0
+end
+
+p2 a ->
+p2_one f1 1.1
+end
+
+p2 b ->
+end
+
+p2 c ->
+p2_three f1 3.3
+end
+
+p2 d ->
+p2_four f1 4.4
+end
+
+p2 e ->
+p2_five f2 5.5
+p2_five2 f3(5) 55.5
+end
+
+p2 f ->
+p2_six f4("hex") 6.6
+end
+
+p2 g ->
+p2_seven f5(77.7) 7.7
+p2_seven2 f1 777.7
+p2_seven3 f2 7777.7
+end
+
+p2 h ->
+end
+
+p3 -1 ->
+end
+
+p3 0 ->
+end
+
+p3 1 ->
+end
+
+p3 2 ->
+p3_two_a f2 6.6
+p3_two_b f2 8.8
+end
+
+p3 3 ->
+p3_three f3(5) 66.6
+end
+
+p3 4 ->
+p3_four_a f5(78.7) 7.8
+p3_four_b f1 999.7
+p3_four_c f2 9999.7
+end
+
+p3 5 ->
+p3_five f5(88.8) 9999.9
+end
+
+p3 6 ->
+end
+
+p3 7 ->
+end
+
+p4 -1 ->
+end
+
+p4 0 ->
+end
+
+p4 1 ->
+end
+
+p4 2 ->
+p4_two_a f2 6.6
+p4_two_b f2 8.8
+end
+
+p4 3 ->
+end
+
+p4 4 ->
+p4_four_a f5(78.7) 7.8
+p4_four_b f1 999.7
+p4_four_c f2 9999.7
+end
+
+p4 5 ->
+p4_five f5(88.8) 9999.9
+end
+
+p4 6 ->
+p4_six f5(66.0) 666.6
+end
+
+p4 7 ->
 end
 
Index: dense_lookup_switch_non.m
--- /home/zs/mer/ws00/tests/hard_coded/dense_lookup_switch_non.m	2006-04-26 13:06:29.000000000 +1000
+++ dense_lookup_switch_non.m	2009-09-29 11:48:44.000000000 +1000
@@ -1,3 +1,5 @@
+% vim: ts=4 sw=4 et ft=mercury
+
 :- module dense_lookup_switch_non.
 
 :- interface.
@@ -20,6 +22,12 @@
 	;	g
 	;	h.
 
+:- type test_id
+    --->    test_p1(foo)
+    ;       test_p2(foo)
+    ;       test_p3(int)
+    ;       test_p4(int).
+
 :- type bar
 	--->	f1
 	;	f2
@@ -28,20 +36,65 @@
 	;	f5(float).
 
 main(!IO) :-
-	test(a, !IO),
-	test(b, !IO),
-	test(c, !IO),
-	test(d, !IO),
-	test(e, !IO),
-	test(f, !IO),
-	test(g, !IO),
-	test(h, !IO).
-
-:- pred test(foo::in, io::di, io::uo) is det.
-
-test(Foo, !IO) :-
-	solutions(p_tuple(Foo), Solns),
-	io.write(Foo, !IO),
+    test(test_p1(a), !IO),
+    test(test_p1(b), !IO),
+    test(test_p1(c), !IO),
+    test(test_p1(d), !IO),
+    test(test_p1(e), !IO),
+    test(test_p1(f), !IO),
+    test(test_p1(g), !IO),
+    test(test_p1(h), !IO),
+
+    test(test_p2(a), !IO),
+    test(test_p2(b), !IO),
+    test(test_p2(c), !IO),
+    test(test_p2(d), !IO),
+    test(test_p2(e), !IO),
+    test(test_p2(f), !IO),
+    test(test_p2(g), !IO),
+    test(test_p2(h), !IO),
+
+    test(test_p3(-1), !IO),
+    test(test_p3(0), !IO),
+    test(test_p3(1), !IO),
+    test(test_p3(2), !IO),
+    test(test_p3(3), !IO),
+    test(test_p3(4), !IO),
+    test(test_p3(5), !IO),
+    test(test_p3(6), !IO),
+    test(test_p3(7), !IO),
+
+    test(test_p4(-1), !IO),
+    test(test_p4(0), !IO),
+    test(test_p4(1), !IO),
+    test(test_p4(2), !IO),
+    test(test_p4(3), !IO),
+    test(test_p4(4), !IO),
+    test(test_p4(5), !IO),
+    test(test_p4(6), !IO),
+    test(test_p4(7), !IO).
+
+:- pred test(test_id::in, io::di, io::uo) is det.
+
+test(FooOrInt, !IO) :-
+    solutions(p_tuple(FooOrInt), Solns),
+    (
+        FooOrInt = test_p1(Foo),
+        io.write_string("p1 ", !IO),
+        io.write(Foo, !IO)
+    ;
+        FooOrInt = test_p2(Foo),
+        io.write_string("p2 ", !IO),
+        io.write(Foo, !IO)
+    ;
+        FooOrInt = test_p3(Int),
+        io.write_string("p3 ", !IO),
+        io.write_int(Int, !IO)
+    ;
+        FooOrInt = test_p4(Int),
+        io.write_string("p4 ", !IO),
+        io.write_int(Int, !IO)
+    ),
 	io.write_string(" ->\n", !IO),
 	io.write_list(Solns, "", write_tp, !IO),
 	io.write_string("end\n\n", !IO).
@@ -59,19 +112,74 @@
 	io.write_float(Float, !IO),
 	io.nl(!IO).
 
-:- pred p_tuple(foo::in, tp::out) is nondet.
+:- pred p_tuple(test_id::in, tp::out) is nondet.
 
-p_tuple(Foo, Tuple) :-
-	p(Foo, Str, Bar, Float),
+p_tuple(FooOrInt, Tuple) :-
+    (
+        FooOrInt = test_p1(Foo),
+        p1(Foo, Str, Bar, Float)
+    ;
+        FooOrInt = test_p2(Foo),
+        p2(Foo, Str, Bar, Float)
+    ;
+        FooOrInt = test_p3(Int),
+        p3(Int, Str, Bar, Float)
+    ;
+        FooOrInt = test_p4(Int),
+        p4(Int, Str, Bar, Float)
+    ),
 	Tuple = tp(Str, Bar, Float).
 
-:- pred p(foo::in, string::out, bar::out, float::out) is nondet.
-:- pragma no_inline(p/4).
+:- pred p1(foo::in, string::out, bar::out, float::out) is multi.
+:- pragma no_inline(p1/4).
 
-p(d, "four", f1, 4.4).
-p(e, "five", f2, 5.5).
-p(e, "five2", f3(5), 55.5).
-p(f, "six", f4("hex"), 6.6).
-p(g, "seven", f5(77.7), 7.7).
-p(g, "seven2", f1, 777.7).
-p(g, "seven3", f2, 7777.7).
+% This predicate needs neither range check nor bitvec check.
+p1(a, "p1_one", f1, 1.1).
+p1(b, "p1_two", f2, 2.2).
+p1(c, "p1_three", f1, 3.3).
+p1(d, "p1_four", f1, 4.4).
+p1(e, "p1_five", f2, 5.5).
+p1(e, "p1_five2", f3(5), 55.5).
+p1(f, "p1_six", f4("hex"), 6.6).
+p1(g, "p1_seven", f5(77.7), 7.7).
+p1(g, "p1_seven2", f1, 777.7).
+p1(g, "p1_seven3", f2, 7777.7).
+p1(h, "p1_eight", f1, 8.0).
+
+:- pred p2(foo::in, string::out, bar::out, float::out) is nondet.
+:- pragma no_inline(p2/4).
+
+% This predicate needs a bitvec check but not a range check.
+p2(a, "p2_one", f1, 1.1).
+p2(c, "p2_three", f1, 3.3).
+p2(d, "p2_four", f1, 4.4).
+p2(e, "p2_five", f2, 5.5).
+p2(e, "p2_five2", f3(5), 55.5).
+p2(f, "p2_six", f4("hex"), 6.6).
+p2(g, "p2_seven", f5(77.7), 7.7).
+p2(g, "p2_seven2", f1, 777.7).
+p2(g, "p2_seven3", f2, 7777.7).
+
+:- pred p3(int::in, string::out, bar::out, float::out) is nondet.
+:- pragma no_inline(p3/4).
+
+% This predicate needs a range check but not a bitvec check.
+p3(2, "p3_two_a", f2, 6.6).
+p3(2, "p3_two_b", f2, 8.8).
+p3(3, "p3_three", f3(5), 66.6).
+p3(4, "p3_four_a", f5(78.7), 7.8).
+p3(4, "p3_four_b", f1, 999.7).
+p3(4, "p3_four_c", f2, 9999.7).
+p3(5, "p3_five", f5(88.8), 9999.9).
+
+:- pred p4(int::in, string::out, bar::out, float::out) is nondet.
+:- pragma no_inline(p4/4).
+
+% This predicate needs both range check and bitvec check.
+p4(2, "p4_two_a", f2, 6.6).
+p4(2, "p4_two_b", f2, 8.8).
+p4(4, "p4_four_a", f5(78.7), 7.8).
+p4(4, "p4_four_b", f1, 999.7).
+p4(4, "p4_four_c", f2, 9999.7).
+p4(5, "p4_five", f5(88.8), 9999.9).
+p4(6, "p4_six", f5(66.0), 666.6).
Index: lookup_switch_simple_bitvec.exp
--- /home/zs/mer/ws00/tests/hard_coded/lookup_switch_simple_bitvec.exp	2009-09-21 14:09:06.000000000 +1000
+++ lookup_switch_simple_bitvec.exp	2009-09-28 20:22:11.000000000 +1000
@@ -1,4 +1,7 @@
 N = 1: no solution
-N = 2: 22 2.2 "two" 222 - 223
-N = 3: 33 3.3 "three" 222 - 224
+N = 2: 22 2.2 "two" 222 - 222
+N = 3: 33 3.3 "three" 222 - 223
 N = 4: no solution
+N = 5: 55 5.5 "five" 222 - 225
+N = 6: 66 6.6 "six" 222 - 226
+N = 7: 77 7.7 "seven" 222 - 227
Index: lookup_switch_simple_bitvec.m
--- /home/zs/mer/ws00/tests/hard_coded/lookup_switch_simple_bitvec.m	2009-09-21 14:09:06.000000000 +1000
+++ lookup_switch_simple_bitvec.m	2009-09-28 20:21:18.000000000 +1000
@@ -18,7 +18,10 @@
     test(1, !IO),
     test(2, !IO),
     test(3, !IO),
-    test(4, !IO).
+    test(4, !IO),
+    test(5, !IO),
+    test(6, !IO),
+    test(7, !IO).
 
 :- pred test(int::in, io::di, io::uo) is det.
 
@@ -40,6 +43,8 @@
 :- pred p(int::in, int::out, float::out, string::out, pair(int)::out)
     is semidet.
 
-p(2, 22, 2.2, "two",    222 - 223).
-p(3, 33, 3.3, "three",  222 - 224).
-p(5, 55, 5.5, "five",   222 - 226).
+p(2, 22, 2.2, "two",   222 - 222).
+p(3, 33, 3.3, "three", 222 - 223).
+p(5, 55, 5.5, "five",  222 - 225).
+p(6, 66, 6.6, "six",   222 - 226).
+p(7, 77, 7.7, "seven", 222 - 227).
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list