[m-rev.] diff: split up some very big predicates

Zoltan Somogyi zs at csse.unimelb.edu.au
Thu Feb 4 10:23:07 AEDT 2010


compiler/jumpopt.m:
compiler/type_constraints.m:
compiler/write_dep_file.m:
	Split up some of the compiler's biggest predicates.

	There are no algorithmic changes, but in jumpopt, this diff
	bundles up a bunch of parameters into a single structure.
	This is probably why this diff improves the speed of the compiler
	by 1.8%.

compiler/llds.m:
	Add some insts needed by jumpopt.m.

Zoltan.

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: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.112
diff -u -b -r1.112 jumpopt.m
--- compiler/jumpopt.m	21 Oct 2009 06:36:19 -0000	1.112
+++ compiler/jumpopt.m	3 Feb 2010 23:17:13 -0000
@@ -81,22 +81,22 @@
 % We then traverse the instruction list, using the information in the
 % tables to short-circuit jumps.
 %
-% Instrmap:     Maps each label to the next real (non-comment, non-livevals)
+% InstrMap:     Maps each label to the next real (non-comment, non-livevals)
 %               instruction after that label.
-% Lvalmap:      Maps each label to yes(Livevals) if the label is followed
+% LvalMap:      Maps each label to yes(Livevals) if the label is followed
 %               by a livevals instruction, and to no otherwise.
-% Blockmap:     Maps each label to the block following that label.
+% BlockMap:     Maps each label to the block following that label.
 %               This includes all instructions up to the first one that
 %               cannot fall through.
-% Procmap:      Maps each label that begins a det epilog to the epilog.
-% Succmap:      Maps each label that begins a nondet epilog to the epilog.
-% Sdprocmap:    Maps each label that begins a semidet epilog to the epilog.
+% ProcMap:      Maps each label that begins a det epilog to the epilog.
+% SuccMap:      Maps each label that begins a nondet epilog to the epilog.
+% SdprocMap:    Maps each label that begins a semidet epilog to the epilog.
 %               This can be the success epilog or the failure epilog.
-% Forkmap:      Maps each label that begins a full semidet epilog (code to
+% ForkMap:      Maps each label that begins a full semidet epilog (code to
 %               test r1, and to execute the the success or failure epilog
 %               depending on the result) to the epilog.
 %
-% Blockmap will not contain the initial block of the procedure unless
+% BlockMap will not contain the initial block of the procedure unless
 % Recjump is set. The intention is that Recjump will not be set until
 % frameopt, which can do a better job of optimizing this block, have
 % been applied.
@@ -104,34 +104,35 @@
 optimize_jumps_in_proc(LayoutLabels, MayAlterRtti, ProcLabel, Fulljumpopt,
         Recjump, PessimizeTailCalls, CheckedNondetTailCall, !C, !Instrs,
         Mod) :-
-    some [!Instrmap, !Blockmap, !Lvalmap, !Procmap, !Sdprocmap, !Succmap,
-        !Forkmap]
+    some [!InstrMap, !BlockMap, !LvalMap, !ProcMap, !SdprocMap, !SuccMap,
+        !ForkMap]
     (
         Instrs0 = !.Instrs,
-        map.init(!:Instrmap),
-        map.init(!:Blockmap),
-        map.init(!:Lvalmap),
-        map.init(!:Procmap),
-        map.init(!:Sdprocmap),
-        map.init(!:Succmap),
-        jump_opt_build_maps(!.Instrs, Recjump, !Instrmap, !Blockmap, !Lvalmap,
-            !Procmap, !Sdprocmap, !Succmap),
-        jump_opt_build_forkmap(!.Instrs, !.Sdprocmap, map.init, !:Forkmap),
+        map.init(!:InstrMap),
+        map.init(!:BlockMap),
+        map.init(!:LvalMap),
+        map.init(!:ProcMap),
+        map.init(!:SdprocMap),
+        map.init(!:SuccMap),
+        jump_opt_build_maps(!.Instrs, Recjump, !InstrMap, !BlockMap, !LvalMap,
+            !ProcMap, !SdprocMap, !SuccMap),
+        jump_opt_build_forkmap(!.Instrs, !.SdprocMap, map.init, !:ForkMap),
         (
             PessimizeTailCalls = no
         ;
             PessimizeTailCalls = yes,
-            !:Procmap = map.init,
-            !:Sdprocmap = map.init,
-            !:Succmap = map.init,
-            !:Forkmap = map.init
-        ),
+            !:ProcMap = map.init,
+            !:SdprocMap = map.init,
+            !:SuccMap = map.init,
+            !:ForkMap = map.init
+        ),
+        JumpOptInfo = jump_opt_info(!.InstrMap, !.BlockMap, !.LvalMap,
+            !.ProcMap, !.SdprocMap, !.ForkMap, !.SuccMap, LayoutLabels,
+            Fulljumpopt, MayAlterRtti),
         (
             CheckedNondetTailCall = yes,
             CheckedNondetTailCallInfo0 = yes(ProcLabel - !.C),
-            jump_opt_instr_list(!.Instrs, comment(""), !.Instrmap, !.Blockmap,
-                !.Lvalmap, !.Procmap, !.Sdprocmap, !.Forkmap, !.Succmap,
-                LayoutLabels, Fulljumpopt, MayAlterRtti,
+            jump_opt_instr_list(!.Instrs, comment(""), JumpOptInfo,
                 CheckedNondetTailCallInfo0, CheckedNondetTailCallInfo,
                 [], RevInstrs),
             (
@@ -144,9 +145,7 @@
         ;
             CheckedNondetTailCall = no,
             CheckedNondetTailCallInfo0 = no,
-            jump_opt_instr_list(!.Instrs, comment(""), !.Instrmap, !.Blockmap,
-                !.Lvalmap, !.Procmap, !.Sdprocmap, !.Forkmap, !.Succmap,
-                LayoutLabels, Fulljumpopt, MayAlterRtti,
+            jump_opt_instr_list(!.Instrs, comment(""), JumpOptInfo,
                 CheckedNondetTailCallInfo0, _, [], RevInstrs)
         ),
         list.reverse(RevInstrs, !:Instrs),
@@ -165,36 +164,36 @@
     lvalmap::in, lvalmap::out, tailmap::in, tailmap::out,
     tailmap::in, tailmap::out, tailmap::in, tailmap::out) is det.
 
-jump_opt_build_maps([], _, !Instrmap, !Blockmap,
-        !Lvalmap, !Procmap, !Sdprocmap, !Succmap).
-jump_opt_build_maps([Instr0 | Instrs0], Recjump, !Instrmap, !Blockmap,
-        !Lvalmap, !Procmap, !Sdprocmap, !Succmap) :-
+jump_opt_build_maps([], _, !InstrMap, !BlockMap,
+        !LvalMap, !ProcMap, !SdprocMap, !SuccMap).
+jump_opt_build_maps([Instr0 | Instrs0], Recjump, !InstrMap, !BlockMap,
+        !LvalMap, !ProcMap, !SdprocMap, !SuccMap) :-
     Instr0 = llds_instr(Uinstr0, _),
     ( Uinstr0 = label(Label) ->
         opt_util.skip_comments(Instrs0, Instrs1),
         ( Instrs1 = [Instr1 | _], Instr1 = llds_instr(livevals(_), _) ->
-            svmap.det_insert(Label, yes(Instr1), !Lvalmap)
+            svmap.det_insert(Label, yes(Instr1), !LvalMap)
         ;
-            svmap.det_insert(Label, no, !Lvalmap)
+            svmap.det_insert(Label, no, !LvalMap)
         ),
         opt_util.skip_comments_livevals(Instrs1, Instrs2),
         ( Instrs2 = [Instr2 | _] ->
-            svmap.det_insert(Label, Instr2, !Instrmap)
+            svmap.det_insert(Label, Instr2, !InstrMap)
         ;
             true
         ),
         ( opt_util.is_proceed_next(Instrs1, Between1) ->
-            svmap.det_insert(Label, Between1, !Procmap)
+            svmap.det_insert(Label, Between1, !ProcMap)
         ;
             true
         ),
         ( opt_util.is_sdproceed_next(Instrs1, Between2) ->
-            svmap.det_insert(Label, Between2, !Sdprocmap)
+            svmap.det_insert(Label, Between2, !SdprocMap)
         ;
             true
         ),
         ( opt_util.is_succeed_next(Instrs1, Between3) ->
-            svmap.det_insert(Label, Between3, !Succmap)
+            svmap.det_insert(Label, Between3, !SuccMap)
         ;
             true
         ),
@@ -206,15 +205,15 @@
             )
         ->
             opt_util.find_no_fallthrough(Instrs1, Block),
-            svmap.det_insert(Label, Block, !Blockmap)
+            svmap.det_insert(Label, Block, !BlockMap)
         ;
             true
         )
     ;
         true
     ),
-    jump_opt_build_maps(Instrs0, Recjump, !Instrmap, !Blockmap, !Lvalmap,
-        !Procmap, !Sdprocmap, !Succmap).
+    jump_opt_build_maps(Instrs0, Recjump, !InstrMap, !BlockMap, !LvalMap,
+        !ProcMap, !SdprocMap, !SuccMap).
 
     % Find labels followed by a test of r1 where both paths set r1 to
     % its original value and proceed.
@@ -222,21 +221,35 @@
 :- pred jump_opt_build_forkmap(list(instruction)::in, tailmap::in,
     tailmap::in, tailmap::out) is det.
 
-jump_opt_build_forkmap([], _Sdprocmap, !Forkmap).
-jump_opt_build_forkmap([llds_instr(Uinstr, _Comment) | Instrs], Sdprocmap,
-        !Forkmap) :-
+jump_opt_build_forkmap([], _SdprocMap, !ForkMap).
+jump_opt_build_forkmap([llds_instr(Uinstr, _Comment) | Instrs], SdprocMap,
+        !ForkMap) :-
     (
         Uinstr = label(Label),
-        opt_util.is_forkproceed_next(Instrs, Sdprocmap, Between)
+        opt_util.is_forkproceed_next(Instrs, SdprocMap, Between)
     ->
-        svmap.det_insert(Label, Between, !Forkmap)
+        svmap.det_insert(Label, Between, !ForkMap)
     ;
         true
     ),
-    jump_opt_build_forkmap(Instrs, Sdprocmap, !Forkmap).
+    jump_opt_build_forkmap(Instrs, SdprocMap, !ForkMap).
 
 %-----------------------------------------------------------------------------%
 
+:- type jump_opt_info
+    --->    jump_opt_info(
+                joi_instr_map       :: instrmap,
+                joi_block_map       :: tailmap,
+                joi_lval_map        :: lvalmap,
+                joi_proc_map        :: tailmap,
+                joi_sdproc_map      :: tailmap,
+                joi_fork_map        :: tailmap,
+                joi_succ_map        :: tailmap,
+                joi_layout_labels   :: set(label),
+                joi_full_jump_opt   :: bool,
+                joi_may_alter_rtti  :: may_alter_rtti
+            ).
+
 :- type new_remain
     --->    specified(
                 new_instructions        :: list(instruction),
@@ -272,42 +285,212 @@
     % building it in right order would make instr_list not tail recursive,
     % and thus unable to handle very long instruction lists.
     %
-:- pred jump_opt_instr_list(list(instruction)::in, instr::in, instrmap::in,
-    tailmap::in, lvalmap::in, tailmap::in, tailmap::in, tailmap::in,
-    tailmap::in, set(label)::in, bool::in, may_alter_rtti::in,
+:- pred jump_opt_instr_list(list(instruction)::in, instr::in,
+    jump_opt_info::in,
     maybe(pair(proc_label, counter))::in,
     maybe(pair(proc_label, counter))::out,
     list(instruction)::in, list(instruction)::out) is det.
 
-jump_opt_instr_list([], _PrevInstr, _Instrmap, _Blockmap, _Lvalmap,
-        _Procmap, _Sdprocmap, _Forkmap, _Succmap, _LayoutLabels,
-        _Fulljumpopt, _MayAlterRtti, !CheckedNondetTailCallInfo, !RevInstrs).
-jump_opt_instr_list([Instr0 | Instrs0], PrevInstr, Instrmap, Blockmap,
-        Lvalmap, Procmap, Sdprocmap, Forkmap, Succmap, LayoutLabels,
-        Fulljumpopt, MayAlterRtti, !CheckedNondetTailCallInfo, !RevInstrs) :-
+jump_opt_instr_list([], _PrevInstr, _, !CheckedNondetTailCallInfo, !RevInstrs).
+jump_opt_instr_list([Instr0 | Instrs0], PrevInstr, JumpOptInfo,
+        !CheckedNondetTailCallInfo, !RevInstrs) :-
     Instr0 = llds_instr(Uinstr0, Comment0),
     % We do a switch on the instruction type to ensure that we short circuit
-    % all the labels that are in Instrmap but not in LayoutLabels in *all*
+    % all the labels that are in InstrMap but not in LayoutLabels in *all*
     % instructions in which they occur. This means we must fully search
     % every part of every instruction that may possibly hold a label.
     % In theory, this means every lval and every rval, but in practice we
     % know that rvals representing e.g. the tags of fields cannot contain
     % labels.
     (
-        Uinstr0 = llcall(Proc, RetAddr, LiveInfos, Context, GoalPath,
-            CallModel),
+        Uinstr0 = llcall(_, _, _, _, _, _),
+        jump_opt_llcall(Uinstr0, Comment0, Instrs0, PrevInstr, JumpOptInfo,
+            !CheckedNondetTailCallInfo, NewRemain)
+    ;
+        Uinstr0 = goto(_),
+        jump_opt_goto(Uinstr0, Comment0, Instrs0, PrevInstr, JumpOptInfo,
+            !CheckedNondetTailCallInfo, NewRemain)
+    ;
+        Uinstr0 = computed_goto(Index, MaybeTargets0),
+        InstrMap = JumpOptInfo ^ joi_instr_map,
+        % Short-circuit all the destination labels.
+        short_maybe_labels(InstrMap, MaybeTargets0, MaybeTargets),
+        ( MaybeTargets = MaybeTargets0 ->
+            NewRemain = usual_case
+        ;
+            Shorted = Comment0 ++ " (some shortcircuits)",
+            NewInstrs =
+                [llds_instr(computed_goto(Index, MaybeTargets), Shorted)],
+            NewRemain = specified(NewInstrs, Instrs0)
+        )
+    ;
+        Uinstr0 = if_val(_, _),
+        jump_opt_if_val(Uinstr0, Comment0, Instrs0, PrevInstr, JumpOptInfo,
+            !CheckedNondetTailCallInfo, NewRemain)
+    ;
+        Uinstr0 = assign(Lval, Rval0),
+        % Any labels mentioned in Rval0 should be short-circuited.
+        InstrMap = JumpOptInfo ^ joi_instr_map,
+        short_labels_rval(InstrMap, Rval0, Rval),
+        ( Rval = Rval0 ->
+            NewRemain = usual_case
+        ;
+            Shorted = Comment0 ++ " (some shortcircuits)",
+            NewInstrs = [llds_instr(assign(Lval, Rval), Shorted)],
+            NewRemain = specified(NewInstrs, Instrs0)
+        )
+    ;
+        Uinstr0 = keep_assign(Lval, Rval0),
+        % Any labels mentioned in Rval0 should be short-circuited.
+        InstrMap = JumpOptInfo ^ joi_instr_map,
+        short_labels_rval(InstrMap, Rval0, Rval),
+        ( Rval = Rval0 ->
+            NewRemain = usual_case
+        ;
+            Shorted = Comment0 ++ " (some shortcircuits)",
+            NewInstrs = [llds_instr(keep_assign(Lval, Rval), Shorted)],
+            NewRemain = specified(NewInstrs, Instrs0)
+        )
+    ;
+        Uinstr0 = mkframe(FrameInfo, Redoip),
+        ( Redoip = yes(code_label(Label0)) ->
+            InstrMap = JumpOptInfo ^ joi_instr_map,
+            short_label(InstrMap, Label0, Label),
+            ( Label = Label0 ->
+                NewRemain = usual_case
+            ;
+                Shorted = Comment0 ++ " (some shortcircuits)",
+                NewInstrs =
+                    [llds_instr(mkframe(FrameInfo, yes(code_label(Label))),
+                        Shorted)],
+                NewRemain = specified(NewInstrs, Instrs0)
+            )
+        ;
+            NewRemain = usual_case
+        )
+    ;
+        Uinstr0 = foreign_proc_code(_, _, _, _, _, _, _, _, _, _),
+        jump_opt_foreign_proc_code(Uinstr0, Comment0, Instrs0, PrevInstr,
+            JumpOptInfo, !CheckedNondetTailCallInfo, NewRemain)
+    ;
+        Uinstr0 = block(_, _, _),
+        % These are supposed to be introduced only after jumpopt is run
+        % for the last time.
+        unexpected(this_file, "jump_opt_instr_list: block")
+    ;
+        Uinstr0 = fork_new_child(SyncTerm, Child0),
+        InstrMap = JumpOptInfo ^ joi_instr_map,
+        short_label(InstrMap, Child0, Child),
+        ( Child = Child0 ->
+            NewRemain = usual_case
+        ;
+            Uinstr = fork_new_child(SyncTerm, Child),
+            Comment = Comment0 ++ " (redirect)",
+            Instr = llds_instr(Uinstr, Comment),
+            NewRemain = specified([Instr], Instrs0)
+        )
+    ;
+        Uinstr0 = join_and_continue(SyncTerm, Label0),
+        InstrMap = JumpOptInfo ^ joi_instr_map,
+        short_label(InstrMap, Label0, Label),
+        ( Label = Label0 ->
+            NewRemain = usual_case
+        ;
+            Uinstr = join_and_continue(SyncTerm, Label),
+            Comment = Comment0 ++ " (redirect)",
+            Instr = llds_instr(Uinstr, Comment),
+            NewRemain = specified([Instr], Instrs0)
+        )
+    ;
+        ( Uinstr0 = arbitrary_c_code(_, _, _)
+        ; Uinstr0 = comment(_)
+        ; Uinstr0 = livevals(_)
+        ; Uinstr0 = label(_)
+        ; Uinstr0 = save_maxfr(_)
+        ; Uinstr0 = restore_maxfr(_)
+        ; Uinstr0 = incr_sp(_, _, _)
+        ; Uinstr0 = decr_sp(_)
+        ; Uinstr0 = decr_sp_and_return(_)
+        ; Uinstr0 = push_region_frame(_, _)
+        ; Uinstr0 = region_fill_frame(_, _, _, _, _)
+        ; Uinstr0 = region_set_fixed_slot(_, _, _)
+        ; Uinstr0 = use_and_maybe_pop_region_frame(_, _)
+        ; Uinstr0 = store_ticket(_)
+        ; Uinstr0 = reset_ticket(_, _)
+        ; Uinstr0 = discard_ticket
+        ; Uinstr0 = prune_ticket
+        ; Uinstr0 = prune_tickets_to(_)
+        ; Uinstr0 = mark_ticket_stack(_)
+        ; Uinstr0 = mark_hp(_)
+        ; Uinstr0 = free_heap(_)
+        ; Uinstr0 = incr_hp(_, _, _, _, _, _, _, _)
+        ; Uinstr0 = restore_hp(_)
+        ; Uinstr0 = init_sync_term(_, _)
+        ),
+        NewRemain = usual_case
+    ),
+    (
+        NewRemain = usual_case,
+        ReplacementInstrsEmpty = no,
+        RecurseInstrs = Instrs0,
+        !:RevInstrs = [Instr0 | !.RevInstrs]
+    ;
+        NewRemain = specified(ReplacementInstrs, RecurseInstrs),
+        % ReplacementInstrs are in the right order, but they will be reversed
+        % by our caller. We therefore reverse them here, which allows that
+        % final reverse to put them in the right order.
+        !:RevInstrs = list.reverse(ReplacementInstrs) ++ !.RevInstrs,
+        (
+            ReplacementInstrs = [],
+            ReplacementInstrsEmpty = yes
+        ;
+            ReplacementInstrs = [_ | _],
+            ReplacementInstrsEmpty = no
+        )
+    ),
+    (
+        ( Uinstr0 = comment(_)
+        ; ReplacementInstrsEmpty = yes
+        )
+    ->
+        NewPrevInstr = PrevInstr
+    ;
+        NewPrevInstr = Uinstr0
+    ),
+    jump_opt_instr_list(RecurseInstrs, NewPrevInstr, JumpOptInfo,
+        !CheckedNondetTailCallInfo, !RevInstrs).
+
+:- pred jump_opt_llcall(instr::in(instr_llcall), string::in,
+    list(instruction)::in, instr::in, jump_opt_info::in,
+    maybe(pair(proc_label, counter))::in,
+    maybe(pair(proc_label, counter))::out,
+    new_remain::out) is det.
+
+jump_opt_llcall(Uinstr0, Comment0, Instrs0, PrevInstr, JumpOptInfo,
+        !CheckedNondetTailCallInfo, NewRemain) :-
+    Uinstr0 = llcall(Proc, RetAddr, LiveInfos, Context, GoalPath, CallModel),
         ( RetAddr = code_label(RetLabel) ->
             (
+            (
+                JumpOptInfo ^ joi_may_alter_rtti = must_not_alter_rtti
+            ;
+                LayoutLabels = JumpOptInfo ^ joi_layout_labels,
+                set.member(RetLabel, LayoutLabels)
+            )
+        ->
+            % We cannot optimize the call. Test for this once, here, instead
+            % of at the end of each of the following conditions.
+            NewRemain = usual_case
+        ;
                 % Look for det style tailcalls. We look for this even if
                 % the call is semidet, because one of the optimizations below
                 % turns a pair of semidet epilogs into a det epilog.
                 ( CallModel = call_model_det
                 ; CallModel = call_model_semidet
                 ),
-                map.search(Procmap, RetLabel, Between0),
-                PrevInstr = livevals(Livevals),
-                MayAlterRtti = may_alter_rtti,
-                not set.member(RetLabel, LayoutLabels)
+            ProcMap = JumpOptInfo ^ joi_proc_map,
+            map.search(ProcMap, RetLabel, Between0),
+            PrevInstr = livevals(Livevals)
             ->
                 opt_util.filter_out_livevals(Between0, Between1),
                 NewInstrs = Between1 ++ [llds_instr(livevals(Livevals), ""),
@@ -316,10 +499,9 @@
             ;
                 % Look for semidet style tailcalls.
                 CallModel = call_model_semidet,
-                map.search(Forkmap, RetLabel, Between),
-                PrevInstr = livevals(Livevals),
-                MayAlterRtti = may_alter_rtti,
-                not set.member(RetLabel, LayoutLabels)
+            ForkMap = JumpOptInfo ^ joi_fork_map,
+            map.search(ForkMap, RetLabel, Between),
+            PrevInstr = livevals(Livevals)
             ->
                 NewInstrs = Between ++ [llds_instr(livevals(Livevals), ""),
                     llds_instr(goto(Proc), redirect_comment(Comment0))],
@@ -328,12 +510,10 @@
                 % Look for nondet style tailcalls which do not need
                 % a runtime check.
                 CallModel = call_model_nondet(unchecked_tail_call),
-                map.search(Succmap, RetLabel, BetweenIncl),
-                BetweenIncl = [llds_instr(livevals(_), _),
-                    llds_instr(goto(_), _)],
-                PrevInstr = livevals(Livevals),
-                MayAlterRtti = may_alter_rtti,
-                not set.member(RetLabel, LayoutLabels)
+            SuccMap = JumpOptInfo ^ joi_succ_map,
+            map.search(SuccMap, RetLabel, BetweenIncl),
+            BetweenIncl = [llds_instr(livevals(_), _), llds_instr(goto(_), _)],
+            PrevInstr = livevals(Livevals)
             ->
                 NewInstrs = [
                     llds_instr(assign(maxfr, lval(prevfr_slot(lval(curfr)))),
@@ -351,12 +531,11 @@
                 % a runtime check.
                 CallModel = call_model_nondet(checked_tail_call),
                 !.CheckedNondetTailCallInfo = yes(ProcLabel - Counter0),
-                map.search(Succmap, RetLabel, BetweenIncl),
+            SuccMap = JumpOptInfo ^ joi_succ_map,
+            map.search(SuccMap, RetLabel, BetweenIncl),
                 BetweenIncl = [llds_instr(livevals(_), _),
                     llds_instr(goto(_), _)],
-                PrevInstr = livevals(Livevals),
-                MayAlterRtti = may_alter_rtti,
-                not set.member(RetLabel, LayoutLabels)
+            PrevInstr = livevals(Livevals)
             ->
                 counter.allocate(LabelNum, Counter0, Counter1),
                 NewLabel = internal_label(LabelNum, ProcLabel),
@@ -374,20 +553,18 @@
                     llds_instr(goto(Proc), redirect_comment(Comment0)),
                     llds_instr(label(NewLabel), "non tail call"),
                     llds_instr(livevals(Livevals), ""),
-                    Instr0
+                llds_instr(Uinstr0, Comment0)
                 ],
                 NewRemain = specified(NewInstrs, Instrs0),
                 !:CheckedNondetTailCallInfo = yes(ProcLabel - Counter1)
             ;
                 % Short circuit the return label if possible.
-                map.search(Instrmap, RetLabel, RetInstr),
-                MayAlterRtti = may_alter_rtti,
-                not set.member(RetLabel, LayoutLabels)
+            InstrMap = JumpOptInfo ^ joi_instr_map,
+            map.search(InstrMap, RetLabel, RetInstr)
             ->
-                final_dest(Instrmap, RetLabel, DestLabel,
-                    RetInstr, _DestInstr),
+            final_dest(InstrMap, RetLabel, DestLabel, RetInstr, _DestInstr),
                 ( RetLabel = DestLabel ->
-                    NewInstrs = [Instr0]
+                NewInstrs = [llds_instr(Uinstr0, Comment0)]
                 ;
                     NewInstrs = [llds_instr(llcall(Proc, code_label(DestLabel),
                         LiveInfos, Context, GoalPath, CallModel),
@@ -399,8 +576,16 @@
             )
         ;
             NewRemain = usual_case
-        )
-    ;
+    ).
+
+:- pred jump_opt_goto(instr::in(instr_goto), string::in,
+    list(instruction)::in, instr::in, jump_opt_info::in,
+    maybe(pair(proc_label, counter))::in,
+    maybe(pair(proc_label, counter))::out,
+    new_remain::out) is det.
+
+jump_opt_goto(Uinstr0, Comment0, Instrs0, PrevInstr, JumpOptInfo,
+        !CheckedNondetTailCallInfo, NewRemain) :-
         Uinstr0 = goto(TargetAddr),
         ( TargetAddr = code_label(TargetLabel) ->
             (
@@ -419,11 +604,12 @@
                 % we could use profiling feedback on this.
                 % We cannot eliminate the instruction here because
                 % that would require altering the if_val instruction.
-                NewInstrs = [Instr0],
+            NewInstrs = [llds_instr(Uinstr0, Comment0)],
                 NewRemain = specified(NewInstrs, Instrs0)
             ;
                 % Replace a jump to a det epilog with the epilog.
-                map.search(Procmap, TargetLabel, Between0)
+            ProcMap = JumpOptInfo ^ joi_proc_map,
+            map.search(ProcMap, TargetLabel, Between0)
             ->
                 adjust_livevals(PrevInstr, Between0, Between),
                 NewInstrs = Between ++
@@ -431,7 +617,8 @@
                 NewRemain = specified(NewInstrs, Instrs0)
             ;
                 % Replace a jump to a semidet epilog with the epilog.
-                map.search(Sdprocmap, TargetLabel, Between0)
+            SdprocMap = JumpOptInfo ^ joi_sdproc_map,
+            map.search(SdprocMap, TargetLabel, Between0)
             ->
                 adjust_livevals(PrevInstr, Between0, Between),
                 NewInstrs = Between ++
@@ -439,50 +626,50 @@
                 NewRemain = specified(NewInstrs, Instrs0)
             ;
                 % Replace a jump to a nondet epilog with the epilog.
-                map.search(Succmap, TargetLabel, BetweenIncl0)
+            SuccMap = JumpOptInfo ^ joi_succ_map,
+            map.search(SuccMap, TargetLabel, BetweenIncl0)
             ->
                 adjust_livevals(PrevInstr, BetweenIncl0, NewInstrs),
                 NewRemain = specified(NewInstrs, Instrs0)
             ;
-                % Replace a jump to a non-epilog block with the
-                % block itself. These jumps are treated separately
-                % from jumps to epilog blocks, for two reasons.
-                % First, epilog blocks are always short, so we
-                % always want to replace jumps to them, whereas
-                % other blocks may be long, so we want to replace
-                % jumps to them only if the fulljumps option
-                % was given. Second, non-epilog blocks may contain
-                % branches to other labels in this procedure, and
-                % we want to make sure that these are short-circuited.
-                % This short-circuiting is necessary because
-                % another optimization below eliminates labels,
-                % which is correct only if jumps to those labels
-                % are short-circuited everywhere.
-                Fulljumpopt = yes,
-                map.search(Instrmap, TargetLabel, TargetInstr),
-                final_dest(Instrmap, TargetLabel, DestLabel,
+            % Replace a jump to a non-epilog block with the block itself.
+            % These jumps are treated separately from jumps to epilog blocks,
+            % for two reasons. First, epilog blocks are always short, so we
+            % always want to replace jumps to them, whereas other blocks
+            % may be long, so we want to replace jumps to them only if the
+            % fulljumps option was given. Second, non-epilog blocks may contain
+            % branches to other labels in this procedure, and we want to
+            % make sure that these are short-circuited. This short-circuiting
+            % is necessary because another optimization below eliminates
+            % labels, which is correct only if jumps to those labels are
+            % short-circuited everywhere.
+            JumpOptInfo ^ joi_full_jump_opt = yes,
+            InstrMap = JumpOptInfo ^ joi_instr_map,
+            map.search(InstrMap, TargetLabel, TargetInstr),
+            final_dest(InstrMap, TargetLabel, DestLabel,
                     TargetInstr, _DestInstr),
-                map.search(Blockmap, DestLabel, Block),
+            BlockMap = JumpOptInfo ^ joi_block_map,
+            map.search(BlockMap, DestLabel, Block),
                 block_may_be_duplicated(Block) = yes
             ->
                 opt_util.filter_out_labels(Block, FilteredBlock),
-                adjust_livevals(PrevInstr, FilteredBlock,
-                    AdjustedBlock),
-                % Block may end with a goto to DestLabel. We avoid
-                % infinite expansion in such cases by removing
-                % DestLabel from Blockmap, though only while
-                % processing AdjustedBlock.
-                map.delete(Blockmap, DestLabel, CrippledBlockmap),
-                jump_opt_instr_list(AdjustedBlock, comment(""), Instrmap,
-                    CrippledBlockmap, Lvalmap, Procmap, Sdprocmap, Forkmap,
-                    Succmap, LayoutLabels, Fulljumpopt, MayAlterRtti,
-                    !CheckedNondetTailCallInfo, [], RevNewInstrs),
+            adjust_livevals(PrevInstr, FilteredBlock, AdjustedBlock),
+            % Block may end with a goto to DestLabel. We avoid infinite
+            % expansion in such cases by removing DestLabel from BlockMap,
+            % though only while processing AdjustedBlock.
+            map.delete(BlockMap, DestLabel, CrippledBlockMap),
+            CrippledJumpOptInfo = JumpOptInfo ^ joi_block_map :=
+                CrippledBlockMap,
+            jump_opt_instr_list(AdjustedBlock, comment(""),
+                CrippledJumpOptInfo, !CheckedNondetTailCallInfo,
+                [], RevNewInstrs),
                 NewRemain = specified(list.reverse(RevNewInstrs), Instrs0)
             ;
                 % Short-circuit the goto.
-                map.search(Instrmap, TargetLabel, TargetInstr)
+            InstrMap = JumpOptInfo ^ joi_instr_map,
+            map.search(InstrMap, TargetLabel, TargetInstr)
             ->
-                final_dest(Instrmap, TargetLabel, DestLabel,
+            final_dest(InstrMap, TargetLabel, DestLabel,
                     TargetInstr, DestInstr),
                 DestInstr = llds_instr(UdestInstr, _Destcomment),
                 Shorted = "shortcircuited jump: " ++ Comment0,
@@ -493,15 +680,15 @@
                 ;
                     Canfallthrough = yes,
                     ( TargetLabel = DestLabel ->
-                        NewInstrs0 = [Instr0]
+                    NewInstrs0 = [llds_instr(Uinstr0, Comment0)]
                     ;
                         NewInstrs0 =
                             [llds_instr(goto(code_label(DestLabel)), Shorted)]
                     )
                 ),
-                ( map.search(Lvalmap, DestLabel, yes(Lvalinstr)) ->
-                    adjust_livevals(PrevInstr, [Lvalinstr | NewInstrs0],
-                        NewInstrs)
+            LvalMap = JumpOptInfo ^ joi_lval_map,
+            ( map.search(LvalMap, DestLabel, yes(Lvalinstr)) ->
+                adjust_livevals(PrevInstr, [Lvalinstr | NewInstrs0], NewInstrs)
                 ;
                     NewInstrs = NewInstrs0
                 ),
@@ -511,22 +698,21 @@
             )
         ;
             NewRemain = usual_case
-        )
-    ;
-        Uinstr0 = computed_goto(Index, MaybeTargets0),
-        % Short-circuit all the destination labels.
-        short_maybe_labels(Instrmap, MaybeTargets0, MaybeTargets),
-        ( MaybeTargets = MaybeTargets0 ->
-            NewRemain = usual_case
-        ;
-            Shorted = Comment0 ++ " (some shortcircuits)",
-            NewInstrs =
-                [llds_instr(computed_goto(Index, MaybeTargets), Shorted)],
-            NewRemain = specified(NewInstrs, Instrs0)
-        )
-    ;
+    ).
+
+:- pred jump_opt_if_val(instr::in(instr_if_val), string::in,
+    list(instruction)::in, instr::in, jump_opt_info::in,
+    maybe(pair(proc_label, counter))::in,
+    maybe(pair(proc_label, counter))::out,
+    new_remain::out) is det.
+
+jump_opt_if_val(Uinstr0, Comment0, Instrs0, _PrevInstr, JumpOptInfo,
+        !CheckedNondetTailCallInfo, NewRemain) :-
         Uinstr0 = if_val(Cond, TargetAddr),
         ( TargetAddr = code_label(TargetLabel) ->
+        JumpOptInfo = jump_opt_info(InstrMap, BlockMap, _LvalMap,
+            _ProcMap, _SdprocMap, _ForkMap, _SuccMap, LayoutLabels,
+            Fulljumpopt, _MayAlterRtti),
             (
                 % Attempt to transform code such as
                 %
@@ -565,8 +751,7 @@
                 LabelInstr = llds_instr(label(TargetLabel), _)
             ->
                 code_util.neg_rval(Cond, NotCond),
-                NewInstr =
-                    llds_instr(if_val(NotCond, GotoTarget), GotoComment),
+            NewInstr = llds_instr(if_val(NotCond, GotoTarget), GotoComment),
                 NewInstrs = [],
                 % The transformed code may fit the pattern again,
                 % so make sure that we look for the pattern again
@@ -597,13 +782,13 @@
                 % if_val, to get the recursive call to replace the goto
                 % to L1 with the code at L1.
                 Fulljumpopt = yes,
-                map.search(Blockmap, TargetLabel, _TargetBlock),
+            map.search(BlockMap, TargetLabel, _TargetBlock),
                 opt_util.skip_comments(Instrs0, Instrs1),
                 Instrs1 = [GotoInstr | AfterGoto],
                 GotoInstr = llds_instr(goto(GotoAddr), GotoComment),
                 \+ (
                     GotoAddr = code_label(GotoLabel),
-                    map.search(Blockmap, GotoLabel, _)
+                map.search(BlockMap, GotoLabel, _)
                 )
             ->
                 code_util.neg_rval(Cond, NotCond),
@@ -616,9 +801,9 @@
                 RemainInstrs = [NewGotoInstr | AfterGoto],
                 NewRemain = specified(NewInstrs, RemainInstrs)
             ;
-                map.search(Instrmap, TargetLabel, TargetInstr)
+            map.search(InstrMap, TargetLabel, TargetInstr)
             ->
-                final_dest(Instrmap, TargetLabel, DestLabel,
+            final_dest(InstrMap, TargetLabel, DestLabel,
                     TargetInstr, _DestInstr),
                 (
                     % Attempt to transform code such as
@@ -637,12 +822,10 @@
                     %   <epilog>
                     %
                     opt_util.is_sdproceed_next(Instrs0, BetweenFT),
-                    map.search(Blockmap, DestLabel, Block),
+                map.search(BlockMap, DestLabel, Block),
                     opt_util.is_sdproceed_next(Block, BetweenBR),
-                    opt_util.filter_out_r1(BetweenFT, yes(SuccessFT),
-                        Between),
-                    opt_util.filter_out_r1(BetweenBR, yes(SuccessBR),
-                        Between),
+                opt_util.filter_out_r1(BetweenFT, yes(SuccessFT), Between),
+                opt_util.filter_out_r1(BetweenBR, yes(SuccessBR), Between),
                     (
                         SuccessFT = llconst_true,
                         SuccessBR = llconst_false,
@@ -669,8 +852,7 @@
                 ->
                     Shorted = "shortcircuited jump: " ++ Comment0,
                     NewInstrs = [
-                        llds_instr(if_val(Cond, code_label(DestLabel)),
-                            Shorted)
+                    llds_instr(if_val(Cond, code_label(DestLabel)), Shorted)
                     ],
                     NewRemain = specified(NewInstrs, Instrs0)
                 ;
@@ -681,55 +863,26 @@
             )
         ;
             NewRemain = usual_case
-        )
-    ;
-        Uinstr0 = assign(Lval, Rval0),
-        % Any labels mentioned in Rval0 should be short-circuited.
-        short_labels_rval(Instrmap, Rval0, Rval),
-        ( Rval = Rval0 ->
-            NewRemain = usual_case
-        ;
-            Shorted = Comment0 ++ " (some shortcircuits)",
-            NewInstrs = [llds_instr(assign(Lval, Rval), Shorted)],
-            NewRemain = specified(NewInstrs, Instrs0)
-        )
-    ;
-        Uinstr0 = keep_assign(Lval, Rval0),
-        % Any labels mentioned in Rval0 should be short-circuited.
-        short_labels_rval(Instrmap, Rval0, Rval),
-        ( Rval = Rval0 ->
-            NewRemain = usual_case
-        ;
-            Shorted = Comment0 ++ " (some shortcircuits)",
-            NewInstrs = [llds_instr(keep_assign(Lval, Rval), Shorted)],
-            NewRemain = specified(NewInstrs, Instrs0)
-        )
-    ;
-        Uinstr0 = mkframe(FrameInfo, Redoip),
-        ( Redoip = yes(code_label(Label0)) ->
-            short_label(Instrmap, Label0, Label),
-            ( Label = Label0 ->
-                NewRemain = usual_case
-            ;
-                Shorted = Comment0 ++ " (some shortcircuits)",
-                NewInstrs =
-                    [llds_instr(mkframe(FrameInfo, yes(code_label(Label))),
-                        Shorted)],
-                NewRemain = specified(NewInstrs, Instrs0)
-            )
-        ;
-            NewRemain = usual_case
-        )
-    ;
+    ).
+
+:- pred jump_opt_foreign_proc_code(instr::in(instr_foreign_proc_code),
+    string::in, list(instruction)::in, instr::in, jump_opt_info::in,
+    maybe(pair(proc_label, counter))::in,
+    maybe(pair(proc_label, counter))::out,
+    new_remain::out) is det.
+
+jump_opt_foreign_proc_code(Uinstr0, Comment0, Instrs0, _PrevInstr,
+        JumpOptInfo, !CheckedNondetTailCallInfo, NewRemain) :-
         Uinstr0 = foreign_proc_code(Decls, Components0, MayCallMercury,
             MaybeFixNoLayout, MaybeFixLayout, MaybeFixOnlyLayout,
             MaybeNoFix0, MaybeDefLabel, StackSlotRef, MaybeDup),
         some [!Redirect] (
-            list.map_foldl(short_foreign_proc_component(Instrmap),
+        InstrMap = JumpOptInfo ^ joi_instr_map,
+        list.map_foldl(short_foreign_proc_component(InstrMap),
                 Components0, Components, no, !:Redirect),
             (
                 MaybeNoFix0 = yes(NoFix),
-                short_label(Instrmap, NoFix, NoFixDest),
+            short_label(InstrMap, NoFix, NoFixDest),
                 MaybeNoFix = yes(NoFixDest),
                 !:Redirect = yes
             ;
@@ -738,12 +891,12 @@
             ),
 % These sanity checks are too strong, because we don't prohibit labels
 % appearing these slots of foreign_proc_code instructions from appearing
-% in Instrmap; we only prohibit the use of those entries in Instrmap
+% in InstrMap; we only prohibit the use of those entries in InstrMap
 % to optimize away these labels.
 %
 %           (
 %               MaybeFixNoLayout = yes(FixNoLayout),
-%               short_label(Instrmap, FixNoLayout, FixNoLayoutDest),
+%           short_label(InstrMap, FixNoLayout, FixNoLayoutDest),
 %               FixNoLayoutDest \= FixNoLayout
 %           ->
 %               error("jump_opt_instr_list: foreign_proc_code fix_no_layout")
@@ -752,7 +905,7 @@
 %           ),
 %           (
 %               MaybeFixLayout = yes(FixLayout),
-%               short_label(Instrmap, FixLayout, FixLayoutDest),
+%           short_label(InstrMap, FixLayout, FixLayoutDest),
 %               FixLayoutDest \= FixLayout
 %           ->
 %               error("jump_opt_instr_list: foreign_proc_code fix_layout")
@@ -761,7 +914,7 @@
 %           ),
 %           (
 %               MaybeFixOnlyLayout = yes(FixOnlyLayout),
-%               short_label(Instrmap, FixOnlyLayout, FixOnlyLayoutDest),
+%           short_label(InstrMap, FixOnlyLayout, FixOnlyLayoutDest),
 %               FixOnlyLayoutDest \= FixOnlyLayout
 %           ->
 %               error("jump_opt_instr_list: foreign_proc_code fix_only_layout")
@@ -780,93 +933,7 @@
                 Instr = llds_instr(Uinstr, Comment),
                 NewRemain = specified([Instr], Instrs0)
             )
-        )
-    ;
-        Uinstr0 = block(_, _, _),
-        % These are supposed to be introduced only after jumpopt is run
-        % for the last time.
-        unexpected(this_file, "instr_list: block")
-    ;
-        Uinstr0 = fork_new_child(SyncTerm, Child0),
-        short_label(Instrmap, Child0, Child),
-        ( Child = Child0 ->
-            NewRemain = usual_case
-        ;
-            Uinstr = fork_new_child(SyncTerm, Child),
-            Comment = Comment0 ++ " (redirect)",
-            Instr = llds_instr(Uinstr, Comment),
-            NewRemain = specified([Instr], Instrs0)
-        )
-    ;
-        Uinstr0 = join_and_continue(SyncTerm, Label0),
-        short_label(Instrmap, Label0, Label),
-        ( Label = Label0 ->
-            NewRemain = usual_case
-        ;
-            Uinstr = join_and_continue(SyncTerm, Label),
-            Comment = Comment0 ++ " (redirect)",
-            Instr = llds_instr(Uinstr, Comment),
-            NewRemain = specified([Instr], Instrs0)
-        )
-    ;
-        ( Uinstr0 = arbitrary_c_code(_, _, _)
-        ; Uinstr0 = comment(_)
-        ; Uinstr0 = livevals(_)
-        ; Uinstr0 = label(_)
-        ; Uinstr0 = save_maxfr(_)
-        ; Uinstr0 = restore_maxfr(_)
-        ; Uinstr0 = incr_sp(_, _, _)
-        ; Uinstr0 = decr_sp(_)
-        ; Uinstr0 = decr_sp_and_return(_)
-        ; Uinstr0 = push_region_frame(_, _)
-        ; Uinstr0 = region_fill_frame(_, _, _, _, _)
-        ; Uinstr0 = region_set_fixed_slot(_, _, _)
-        ; Uinstr0 = use_and_maybe_pop_region_frame(_, _)
-        ; Uinstr0 = store_ticket(_)
-        ; Uinstr0 = reset_ticket(_, _)
-        ; Uinstr0 = discard_ticket
-        ; Uinstr0 = prune_ticket
-        ; Uinstr0 = prune_tickets_to(_)
-        ; Uinstr0 = mark_ticket_stack(_)
-        ; Uinstr0 = mark_hp(_)
-        ; Uinstr0 = free_heap(_)
-        ; Uinstr0 = incr_hp(_, _, _, _, _, _, _, _)
-        ; Uinstr0 = restore_hp(_)
-        ; Uinstr0 = init_sync_term(_, _)
-        ),
-        NewRemain = usual_case
-    ),
-    (
-        NewRemain = usual_case,
-        ReplacementInstrsEmpty = no,
-        RecurseInstrs = Instrs0,
-        !:RevInstrs = [Instr0 | !.RevInstrs]
-    ;
-        NewRemain = specified(ReplacementInstrs, RecurseInstrs),
-        % ReplacementInstrs are in the right order, but they will be reversed
-        % by our caller. We therefore reverse them here, which allows that
-        % final reverse to put them in the right order.
-        !:RevInstrs = list.reverse(ReplacementInstrs) ++ !.RevInstrs,
-        (
-            ReplacementInstrs = [],
-            ReplacementInstrsEmpty = yes
-        ;
-            ReplacementInstrs = [_ | _],
-            ReplacementInstrsEmpty = no
-        )
-    ),
-    (
-        ( Uinstr0 = comment(_)
-        ; ReplacementInstrsEmpty = yes
-        )
-    ->
-        NewPrevInstr = PrevInstr
-    ;
-        NewPrevInstr = Uinstr0
-    ),
-    jump_opt_instr_list(RecurseInstrs, NewPrevInstr, Instrmap, Blockmap,
-        Lvalmap, Procmap, Sdprocmap, Forkmap, Succmap, LayoutLabels,
-        Fulljumpopt, MayAlterRtti, !CheckedNondetTailCallInfo, !RevInstrs).
+    ).
 
 :- func block_may_be_duplicated(list(instruction)) = bool.
 
@@ -963,9 +1030,9 @@
     %
 :- pred short_label(instrmap::in, label::in, label::out) is det.
 
-short_label(Instrmap, Label0, Label) :-
-    ( map.search(Instrmap, Label0, Instr0) ->
-        final_dest(Instrmap, Label0, Label, Instr0, _Instr)
+short_label(InstrMap, Label0, Label) :-
+    ( map.search(InstrMap, Label0, Instr0) ->
+        final_dest(InstrMap, Label0, Label, Instr0, _Instr)
     ;
         Label = Label0
     ).
@@ -973,18 +1040,18 @@
 :- pred short_maybe_labels(instrmap::in,
     list(maybe(label))::in, list(maybe(label))::out) is det.
 
-short_maybe_labels(_Instrmap, [], []).
-short_maybe_labels(Instrmap, [MaybeLabel0 | MaybeLabels0],
+short_maybe_labels(_InstrMap, [], []).
+short_maybe_labels(InstrMap, [MaybeLabel0 | MaybeLabels0],
         [MaybeLabel | MaybeLabels]) :-
     (
         MaybeLabel0 = yes(Label0),
-        short_label(Instrmap, Label0, Label),
+        short_label(InstrMap, Label0, Label),
         MaybeLabel = yes(Label)
     ;
         MaybeLabel0 = no,
         MaybeLabel = no
     ),
-    short_maybe_labels(Instrmap, MaybeLabels0, MaybeLabels).
+    short_maybe_labels(InstrMap, MaybeLabels0, MaybeLabels).
 
 %-----------------------------------------------------------------------------%
 
@@ -994,13 +1061,13 @@
 :- pred final_dest(instrmap::in, label::in, label::out, instruction::in,
     instruction::out) is det.
 
-final_dest(Instrmap, SrcLabel, DestLabel, SrcInstr, DestInstr) :-
-    final_dest_2(Instrmap, [], SrcLabel, DestLabel, SrcInstr, DestInstr).
+final_dest(InstrMap, SrcLabel, DestLabel, SrcInstr, DestInstr) :-
+    final_dest_2(InstrMap, [], SrcLabel, DestLabel, SrcInstr, DestInstr).
 
 :- pred final_dest_2(instrmap::in, list(label)::in,
     label::in, label::out, instruction::in, instruction::out) is det.
 
-final_dest_2(Instrmap, LabelsSofar, SrcLabel, DestLabel,
+final_dest_2(InstrMap, LabelsSofar, SrcLabel, DestLabel,
         SrcInstr, DestInstr) :-
     (
         SrcInstr = llds_instr(SrcUinstr, _Comment),
@@ -1009,10 +1076,10 @@
         ;
             SrcUinstr = label(TargetLabel)
         ),
-        map.search(Instrmap, TargetLabel, TargetInstr),
+        map.search(InstrMap, TargetLabel, TargetInstr),
         \+ list.member(SrcLabel, LabelsSofar)
     ->
-        final_dest_2(Instrmap, [SrcLabel | LabelsSofar],
+        final_dest_2(InstrMap, [SrcLabel | LabelsSofar],
             TargetLabel, DestLabel, TargetInstr, DestInstr)
     ;
         DestLabel = SrcLabel,
@@ -1023,20 +1090,20 @@
 
 :- pred short_labels_rval(instrmap::in, rval::in, rval::out) is det.
 
-short_labels_rval(Instrmap, lval(Lval0), lval(Lval)) :-
-    short_labels_lval(Instrmap, Lval0, Lval).
+short_labels_rval(InstrMap, lval(Lval0), lval(Lval)) :-
+    short_labels_lval(InstrMap, Lval0, Lval).
 short_labels_rval(_, var(_), _) :-
     unexpected(this_file, "var rval in short_labels_rval").
-short_labels_rval(Instrmap, mkword(Tag, Rval0), mkword(Tag, Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_rval(Instrmap, const(Const0), const(Const)) :-
-    short_labels_const(Instrmap, Const0, Const).
-short_labels_rval(Instrmap, unop(Op, Rval0), unop(Op, Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_rval(Instrmap, binop(Op, LRval0, RRval0),
+short_labels_rval(InstrMap, mkword(Tag, Rval0), mkword(Tag, Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_rval(InstrMap, const(Const0), const(Const)) :-
+    short_labels_const(InstrMap, Const0, Const).
+short_labels_rval(InstrMap, unop(Op, Rval0), unop(Op, Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_rval(InstrMap, binop(Op, LRval0, RRval0),
         binop(Op, LRval, RRval)) :-
-    short_labels_rval(Instrmap, LRval0, LRval),
-    short_labels_rval(Instrmap, RRval0, RRval).
+    short_labels_rval(InstrMap, LRval0, LRval),
+    short_labels_rval(InstrMap, RRval0, RRval).
 short_labels_rval(_, mem_addr(MemRef), mem_addr(MemRef)).
 
 :- pred short_labels_const(instrmap::in,
@@ -1049,10 +1116,10 @@
 short_labels_const(_, llconst_float(F), llconst_float(F)).
 short_labels_const(_, llconst_string(S), llconst_string(S)).
 short_labels_const(_, llconst_multi_string(S), llconst_multi_string(S)).
-short_labels_const(Instrmap, llconst_code_addr(CodeAddr0),
+short_labels_const(InstrMap, llconst_code_addr(CodeAddr0),
         llconst_code_addr(CodeAddr)) :-
     ( CodeAddr0 = code_label(Label0) ->
-        short_label(Instrmap, Label0, Label),
+        short_label(InstrMap, Label0, Label),
         CodeAddr = code_label(Label)
     ;
         CodeAddr = CodeAddr0
@@ -1064,21 +1131,21 @@
     list(maybe(rval))::out) is det.
 
 short_labels_maybe_rvals(_, [], []).
-short_labels_maybe_rvals(Instrmap, [MaybeRval0 | MaybeRvals0],
+short_labels_maybe_rvals(InstrMap, [MaybeRval0 | MaybeRvals0],
         [MaybeRval | MaybeRvals]) :-
-    short_labels_maybe_rval(Instrmap, MaybeRval0, MaybeRval),
-    short_labels_maybe_rvals(Instrmap, MaybeRvals0, MaybeRvals).
+    short_labels_maybe_rval(InstrMap, MaybeRval0, MaybeRval),
+    short_labels_maybe_rvals(InstrMap, MaybeRvals0, MaybeRvals).
 
 :- pred short_labels_maybe_rval(instrmap::in,
     maybe(rval)::in, maybe(rval)::out) is det.
 
-short_labels_maybe_rval(Instrmap, MaybeRval0, MaybeRval) :-
+short_labels_maybe_rval(InstrMap, MaybeRval0, MaybeRval) :-
     (
         MaybeRval0 = no,
         MaybeRval = no
     ;
         MaybeRval0 = yes(Rval0),
-        short_labels_rval(Instrmap, Rval0, Rval),
+        short_labels_rval(InstrMap, Rval0, Rval),
         MaybeRval = yes(Rval)
     ).
 
@@ -1096,22 +1163,22 @@
 short_labels_lval(_, parent_stackvar(N), parent_stackvar(N)).
 short_labels_lval(_, framevar(N), framevar(N)).
 short_labels_lval(_, global_var_ref(Var), global_var_ref(Var)).
-short_labels_lval(Instrmap, succip_slot(Rval0), succip_slot(Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_lval(Instrmap, redoip_slot(Rval0), redoip_slot(Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_lval(Instrmap, redofr_slot(Rval0), redofr_slot(Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_lval(Instrmap, succfr_slot(Rval0), succfr_slot(Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_lval(Instrmap, prevfr_slot(Rval0), prevfr_slot(Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
-short_labels_lval(Instrmap, field(Tag, Rval0, Field0),
+short_labels_lval(InstrMap, succip_slot(Rval0), succip_slot(Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_lval(InstrMap, redoip_slot(Rval0), redoip_slot(Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_lval(InstrMap, redofr_slot(Rval0), redofr_slot(Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_lval(InstrMap, succfr_slot(Rval0), succfr_slot(Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_lval(InstrMap, prevfr_slot(Rval0), prevfr_slot(Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
+short_labels_lval(InstrMap, field(Tag, Rval0, Field0),
         field(Tag, Rval, Field)) :-
-    short_labels_rval(Instrmap, Rval0, Rval),
-    short_labels_rval(Instrmap, Field0, Field).
-short_labels_lval(Instrmap, mem_ref(Rval0), mem_ref(Rval)) :-
-    short_labels_rval(Instrmap, Rval0, Rval).
+    short_labels_rval(InstrMap, Rval0, Rval),
+    short_labels_rval(InstrMap, Field0, Field).
+short_labels_lval(InstrMap, mem_ref(Rval0), mem_ref(Rval)) :-
+    short_labels_rval(InstrMap, Rval0, Rval).
 short_labels_lval(_, lvar(_), _) :-
     unexpected(this_file, "lvar lval in short_labels_lval").
 
@@ -1119,7 +1186,7 @@
     foreign_proc_component::in, foreign_proc_component::out,
     bool::in, bool::out) is det.
 
-short_foreign_proc_component(Instrmap, !Component, !Redirect) :-
+short_foreign_proc_component(InstrMap, !Component, !Redirect) :-
     (
         !.Component = foreign_proc_inputs(_)
     ;
@@ -1130,7 +1197,7 @@
         !.Component = foreign_proc_raw_code(_, _, _, _)
     ;
         !.Component = foreign_proc_fail_to(Label0),
-        short_label(Instrmap, Label0, Label),
+        short_label(InstrMap, Label0, Label),
         !:Component = foreign_proc_fail_to(Label),
         ( Label = Label0 ->
             true
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.365
diff -u -b -r1.365 llds.m
--- compiler/llds.m	30 Oct 2009 03:33:14 -0000	1.365
+++ compiler/llds.m	3 Feb 2010 23:17:13 -0000
@@ -629,6 +629,16 @@
             % The label gives the address of the code following the parallel
             % conjunction. 
 
+:- inst instr_llcall
+    --->    llcall(ground, ground, ground, ground, ground, ground).
+:- inst instr_goto
+    --->    goto(ground).
+:- inst instr_if_val
+    --->    if_val(ground, ground).
+:- inst instr_foreign_proc_code
+    --->    foreign_proc_code(ground, ground, ground, ground, ground,
+                ground, ground, ground, ground, ground).
+
 :- type stack_incr_kind
     --->    stack_incr_leaf         % The incr_sp creates the stack frame
                                     % of a leaf procedure.
Index: compiler/type_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/type_constraints.m,v
retrieving revision 1.7
diff -u -b -r1.7 type_constraints.m
--- compiler/type_constraints.m	4 Sep 2009 02:27:55 -0000	1.7
+++ compiler/type_constraints.m	3 Feb 2010 23:17:13 -0000
@@ -352,7 +352,8 @@
 
 %-----------------------------------------------------------------------------%
 %
-% General typechecking utility predicates
+% General typechecking utility predicates.
+%
 
     % A compiler-generated predicate only needs type checking if
     % (a) it is a user-defined equality pred, or
@@ -544,7 +545,9 @@
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
-% Constraint solving
+%
+% Constraint solving.
+%
 
     % Tries to solve a constraint on the types of variables in a predicate.
     % If a definite solution cannot be found, use labeling to guess the value
@@ -951,6 +954,7 @@
 %-----------------------------------------------------------------------------%
 %
 % Constraint solving utility predicates.
+%
 
     % Returns the type variable that is unified with Target in the constraint.
     % Fails if no such variable exists.
@@ -1451,7 +1455,8 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Error diagnosis
+% Error diagnosis.
+%
 
     % If the list of type constraints contains more than one predicate call
     % constraint, return an error message describing the ambiguity and one
@@ -1609,7 +1614,8 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 %
-% Constraint generation
+% Constraint generation.
+%
 
     % Turn a goal expression to a constraint on the types of variable
     % appearing within that goal, then update all relevant maps with the
@@ -1619,14 +1625,58 @@
     type_constraint_info::in, type_constraint_info::out) is det.
 
 goal_to_constraint(Environment, Goal, !TCInfo) :-
-    Environment = tconstr_environment(_, _, FuncEnv, PredEnv),
+    % Environment = tconstr_environment(_, _, FuncEnv, PredEnv),
     Goal = hlds_goal(GoalExpr, GoalInfo),
     (
-        GoalExpr = unify(L, RHS, _, _, _),
+        GoalExpr = unify(_, _, _, _, _),
+        unify_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo)
+    ;
+        GoalExpr = plain_call(_, _, _, _, _, _),
+        plain_call_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo)
+    ;
+        GoalExpr = call_foreign_proc(_, _, _, _, _, _, _),
+        foreign_proc_goal_to_constraint(Environment, GoalExpr, GoalInfo,
+            !TCInfo)
+    ;
+        GoalExpr = generic_call(_, _, _, _),
+        generic_call_goal_to_constraint(Environment, GoalExpr, GoalInfo,
+            !TCInfo)
+    ;
+        GoalExpr = conj(_, Goals),
+        list.foldl(goal_to_constraint(Environment), Goals, !TCInfo)
+    ;
+        GoalExpr = disj(Goals),
+        list.foldl(goal_to_constraint(Environment), Goals, !TCInfo)
+    ;
+        GoalExpr = negation(SubGoal),
+        goal_to_constraint(Environment, SubGoal, !TCInfo)
+    ;
+        GoalExpr = scope(_, SubGoal),
+        goal_to_constraint(Environment, SubGoal, !TCInfo)
+    ;
+        GoalExpr = if_then_else(_, Cond, Then, Else),
+        goal_to_constraint(Environment, Cond, !TCInfo),
+        goal_to_constraint(Environment, Then, !TCInfo),
+        goal_to_constraint(Environment, Else, !TCInfo)
+    ;
+        GoalExpr = switch(_, _, Cases),
+        list.map(get_case_goal, Cases, Goals),
+        list.foldl(goal_to_constraint(Environment), Goals, !TCInfo)
+    ;
+        GoalExpr = shorthand(_),
+        shorthand_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo)
+    ).
+
         % Transform a unification constraint into an assignment of types
         % to the variables being unified.
+    %
+:- pred unify_goal_to_constraint(tconstr_environment::in,
+    hlds_goal_expr::in(goal_expr_unify), hlds_goal_info::in,
+    type_constraint_info::in, type_constraint_info::out) is det.
 
+unify_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo) :-
         Context = goal_info_get_context(GoalInfo),
+    GoalExpr = unify(L, RHS, _, _, _),
         get_var_type(L, LTVar, !TCInfo),
         (
             RHS = rhs_var(R),
@@ -1649,8 +1699,9 @@
                 Arity = list.length(Args)
             ->
                 list.map_foldl(get_var_type, Args, ArgTypeVars, !TCInfo),
-                % If it is a data constructor, create a disjunction
-                % constraint with each possible type of the constructor.
+            % If it is a data constructor, create a disjunction constraint
+            % with each possible type of the constructor.
+            Environment = tconstr_environment(_, _, FuncEnv, PredEnv),
                 ( map.search(FuncEnv, ConsId, Cons_Defns) ->
                     list.map_foldl(
                         functor_unif_constraint(LTVar, ArgTypeVars, GoalInfo),
@@ -1704,28 +1755,38 @@
             RelevantTVars = [LTVar | ArgTVars],
             goal_to_constraint(Environment, LambdaGoal, !TCInfo)
         ),
-        add_type_constraint(Constraints, RelevantTVars, !TCInfo)
-    ;
+    add_type_constraint(Constraints, RelevantTVars, !TCInfo).
+
+:- pred plain_call_goal_to_constraint(tconstr_environment::in,
+    hlds_goal_expr::in(goal_expr_plain_call), hlds_goal_info::in,
+    type_constraint_info::in, type_constraint_info::out) is det.
+
+plain_call_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo) :-
+    Environment = tconstr_environment(_, _, _FuncEnv, PredEnv),
         GoalExpr = plain_call(_, _, Args, _, _, Name),
         % Transform a call to variable assignments of the variables
         % used in the call.
         (
-            predicate_table_search_pred_sym(PredEnv,
-                may_be_partially_qualified, Name, PredIds0)
+        predicate_table_search_pred_sym(PredEnv, may_be_partially_qualified,
+            Name, PredIds0)
         ->
             PredIds1 = PredIds0
         ;
             PredIds1 = []
         ),
         predicate_table_get_preds(PredEnv, Preds),
-        list.filter(pred_has_arity(Preds, list.length(Args)),
-            PredIds1, PredIds),
+    list.filter(pred_has_arity(Preds, list.length(Args)), PredIds1, PredIds),
         list.map_foldl(get_var_type, Args, ArgTVars, !TCInfo),
         list.map2_foldl(pred_call_constraint(Preds, GoalInfo, ArgTVars),
             PredIds, Constraints, PredTVars, !TCInfo),
         list.condense([ArgTVars | PredTVars], TVars),
-        add_type_constraint(Constraints, TVars, !TCInfo)
-    ;
+    add_type_constraint(Constraints, TVars, !TCInfo).
+
+:- pred foreign_proc_goal_to_constraint(tconstr_environment::in,
+    hlds_goal_expr::in(goal_expr_foreign_proc), hlds_goal_info::in,
+    type_constraint_info::in, type_constraint_info::out) is det.
+
+foreign_proc_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo) :-
         GoalExpr = call_foreign_proc(_, PredId, _, ForeignArgs, _, _, _),
         Context = goal_info_get_context(GoalInfo),
         ArgVars = list.map(foreign_arg_var, ForeignArgs),
@@ -1742,8 +1803,13 @@
                 ArgVars, ArgTypes, !TCInfo)
         ;
             unexpected(this_file, "cannot find pred_info for foreign_proc")
-        )
-    ;
+    ).
+
+:- pred generic_call_goal_to_constraint(tconstr_environment::in,
+    hlds_goal_expr::in(goal_expr_generic_call), hlds_goal_info::in,
+    type_constraint_info::in, type_constraint_info::out) is det.
+
+generic_call_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo) :-
         GoalExpr = generic_call(Details, Vars, _, _),
         Context = goal_info_get_context(GoalInfo),
         list.map_foldl(get_var_type, Vars, ArgTVars, !TCInfo),
@@ -1815,35 +1881,17 @@
         ;
             % Casts do not contain any type information.
             Details = cast(_)
-        )
-    ;
-        GoalExpr = conj(_, Goals),
-        list.foldl(goal_to_constraint(Environment), Goals, !TCInfo)
-    ;
-        GoalExpr = disj(Goals),
-        list.foldl(goal_to_constraint(Environment), Goals, !TCInfo)
-    ;
-        GoalExpr = negation(SubGoal),
-        goal_to_constraint(Environment, SubGoal, !TCInfo)
-    ;
-        GoalExpr = scope(_, SubGoal),
-        goal_to_constraint(Environment, SubGoal, !TCInfo)
-    ;
-        GoalExpr = if_then_else(_, Cond, Then, Else),
-        goal_to_constraint(Environment, Cond, !TCInfo),
-        goal_to_constraint(Environment, Then, !TCInfo),
-        goal_to_constraint(Environment, Else, !TCInfo)
-    ;
-        GoalExpr = switch(_, _, Cases),
-        list.map(get_case_goal, Cases, Goals),
-        list.foldl(goal_to_constraint(Environment), Goals, !TCInfo)
-    ;
-        GoalExpr = shorthand(bi_implication(GoalA, GoalB)),
-        goal_to_constraint(Environment, GoalA, !TCInfo),
-        goal_to_constraint(Environment, GoalB, !TCInfo)
-    ;
-        GoalExpr = shorthand(atomic_goal(GoalType, Outer, Inner,
-            _, Main, Alternatives, _)),
+    ).
+
+:- pred shorthand_goal_to_constraint(tconstr_environment::in,
+    hlds_goal_expr::in(goal_expr_shorthand), hlds_goal_info::in,
+    type_constraint_info::in, type_constraint_info::out) is det.
+
+shorthand_goal_to_constraint(Environment, GoalExpr, GoalInfo, !TCInfo) :-
+    GoalExpr = shorthand(Shorthand),
+    (
+        Shorthand = atomic_goal(GoalType, Outer, Inner, _,
+            Main, Alternatives, _),
         % Atomic goals are handled by forcing their inner arguments
         % to be of type stm_atomic_type, their outer arguments to be
         % of type stm_atomic_type or io_state_type, depending on the type
@@ -1889,7 +1937,7 @@
         list.foldl(goal_to_constraint(Environment), [Main | Alternatives],
             !TCInfo)
     ;
-        GoalExpr = shorthand(try_goal(MaybeIO, _ResultVar, SubGoal)),
+        Shorthand = try_goal(MaybeIO, _ResultVar, SubGoal),
         Context = goal_info_get_context(GoalInfo),
         (
             MaybeIO = yes(try_io_state_vars(IOVarA, IOVarB)),
@@ -1905,6 +1953,10 @@
             MaybeIO = no
         ),
         goal_to_constraint(Environment, SubGoal, !TCInfo)
+    ;
+        Shorthand = bi_implication(GoalA, GoalB),
+        goal_to_constraint(Environment, GoalA, !TCInfo),
+        goal_to_constraint(Environment, GoalB, !TCInfo)
     ).
 
     % Creates a constraint from the information stored in a predicate
@@ -2053,6 +2105,7 @@
 %-----------------------------------------------------------------------------%
 %
 % Constraint generation utility predicates.
+%
 
 :- pred pred_has_arity(pred_table::in, int::in, pred_id::in) is semidet.
 
@@ -2162,6 +2215,7 @@
 %-----------------------------------------------------------------------------%
 %
 % Constraint printing.
+%
 
 :- pred print_guess(tvarset::in, pair(tvar, type_domain)::in, io::di, io::uo)
     is det.
@@ -2428,6 +2482,7 @@
 %-----------------------------------------------------------------------------%
 %
 % General purpose utilities.
+%
 
 :- pred remove_maybe(maybe(T)::in, T::out) is semidet.
 
Index: compiler/write_deps_file.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/write_deps_file.m,v
retrieving revision 1.7
diff -u -b -r1.7 write_deps_file.m
--- compiler/write_deps_file.m	14 Oct 2009 05:28:45 -0000	1.7
+++ compiler/write_deps_file.m	3 Feb 2010 23:17:13 -0000
@@ -1730,6 +1730,40 @@
     module_name_to_file_name(Globals, ModuleName, "_init.pic_o",
         do_create_dirs, InitPicObjFileName, !IO),
 
+    globals.lookup_bool_option(Globals, intermodule_optimization, Intermod),
+    globals.lookup_bool_option(Globals, transitive_optimization, TransOpt),
+    globals.lookup_bool_option(Globals, generate_mmc_make_module_dependencies,
+        MmcMakeDeps),
+
+    generate_dep_file_exec_library_targets(Globals, DepStream, ModuleName,
+        MakeVarName, InitFileName, InitObjFileName,
+        Intermod, TransOpt, MmcMakeDeps,
+        MaybeOptsVar, MaybeTransOptsVar, MaybeModuleDepsVar,
+        ExeFileName, JarFileName, LibFileName, SharedLibFileName, !IO),
+    generate_dep_file_init_targets(Globals, DepStream, ModuleName,
+        MakeVarName, InitCFileName, InitFileName, DepFileName, DvFileName,
+        !IO),
+    generate_dep_file_install_targets(Globals, DepStream, ModuleName, DepsMap,
+        MakeVarName, MmcMakeDeps, Intermod, TransOpt,
+        MaybeModuleDepsVar, MaybeOptsVar, MaybeTransOptsVar, !IO),
+    generate_dep_file_collective_targets(Globals, DepStream, ModuleName,
+        MakeVarName, !IO),
+    generate_dep_file_clean_targets(Globals, DepStream, ModuleName,
+        MakeVarName, ExeFileName, InitCFileName, InitAsmFileName,
+        InitObjFileName, InitPicObjFileName, InitFileName,
+        LibFileName, SharedLibFileName, JarFileName, DepFileName, DvFileName,
+        !IO).
+
+:- pred generate_dep_file_exec_library_targets(globals::in,
+    io.output_stream::in, module_name::in, string::in, string::in, string::in,
+    bool::in, bool::in, bool::in, string::out, string::out, string::out,
+    string::out, string::out, string::out, string::out, io::di, io::uo) is det.
+
+generate_dep_file_exec_library_targets(Globals, DepStream, ModuleName,
+        MakeVarName, InitFileName, InitObjFileName,
+        Intermod, TransOpt, MmcMakeDeps,
+        MaybeOptsVar, MaybeTransOptsVar, MaybeModuleDepsVar,
+        ExeFileName, JarFileName, LibFileName, SharedLibFileName, !IO) :-
     % Note we have to do some ``interesting'' hacks to get
     % `$(ALL_MLLIBS_DEP)' to work in the dependency list
     % (and not complain about undefined variables).
@@ -1773,10 +1807,12 @@
     ILMainRule = [ExeFileName, " : ", ExeFileName, ".exe\n",
         ExeFileName, ".exe : ", "$(", MakeVarName, ".dlls) ",
         "$(", MakeVarName, ".foreign_dlls)\n"],
-    Else = ["else\n"],
-    IfJava = [" ifeq ($(findstring java,$(GRADE)),java)\n"],
+    IfJava2 = [" ifeq ($(findstring java,$(GRADE)),java)\n"],
     JavaMainRule = [ExeFileName, " : $(", MakeVarName, ".classes)\n"],
+
+    Else = ["else\n"],
     Else2 = [" else\n"],
+    EndIf = ["endif\n"],
     EndIf2 = [" endif\n"],
 
     % XXX The output here is GNU Make-specific.
@@ -1794,13 +1830,12 @@
         "\t$(ML) $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) -- $(ALL_LDFLAGS) ",
             "-o ", ExeFileName, "$(EXT_FOR_EXE) ", InitObjFileName, " \\\n",
         "\t\t$(", MakeVarName, ".os) ", All_MLObjsString, " $(ALL_MLLIBS)\n"],
-    EndIf = ["endif\n"],
 
     globals.get_target(Globals, Target),
     (
         Gmake = yes,
         Rules = IfIL ++ ILMainRule ++ Else ++
-            IfJava ++ JavaMainRule ++ Else2 ++
+            IfJava2 ++ JavaMainRule ++ Else2 ++
             MainRule ++ EndIf2 ++ EndIf
     ;
         Gmake = no,
@@ -1824,29 +1859,23 @@
     ),
     io.write_strings(DepStream, Rules, !IO),
 
-    globals.lookup_bool_option(Globals, intermodule_optimization, Intermod),
     (
         Intermod = yes,
-        string.append_list(["$(", MakeVarName, ".opts) "], MaybeOptsVar)
+        MaybeOptsVar = "$(" ++ MakeVarName ++ ".opts) "
     ;
         Intermod = no,
         MaybeOptsVar = ""
     ),
-    globals.lookup_bool_option(Globals, transitive_optimization, TransOpt),
     (
         TransOpt = yes,
-        string.append_list(["$(", MakeVarName, ".trans_opts) "],
-            MaybeTransOptsVar)
+        MaybeTransOptsVar = "$(" ++ MakeVarName ++ ".trans_opts) "
     ;
         TransOpt = no,
         MaybeTransOptsVar = ""
     ),
-    globals.lookup_bool_option(Globals, generate_mmc_make_module_dependencies,
-        MmcMakeDeps),
     (
         MmcMakeDeps = yes,
-        string.append_list(["$(", MakeVarName, ".module_deps) "],
-            MaybeModuleDepsVar)
+        MaybeModuleDepsVar = "$(" ++ MakeVarName ++ ".module_deps) "
     ;
         MmcMakeDeps = no,
         MaybeModuleDepsVar = ""
@@ -1899,7 +1928,7 @@
     (
         Gmake = yes,
         LibRules = IfIL ++ ILLibRule ++ Else ++
-            IfJava ++ JavaLibRule ++ Else2 ++
+            IfJava2 ++ JavaLibRule ++ Else2 ++
             LibRule ++ EndIf2 ++ EndIf
     ;
         Gmake = no,
@@ -1954,8 +1983,15 @@
         JarFileName, " : ", "$(", MakeVarName, ".classes)\n",
         "\t$(JAR) $(JAR_CREATE_FLAGS) ", JarFileName, " ",
         ListClassFiles, "\n\n"
-    ], !IO),
+    ], !IO).
 
+:- pred generate_dep_file_init_targets(globals::in, io.output_stream::in,
+    module_name::in, string::in, string::in, string::in,
+    string::out, string::out, io::di, io::uo) is det.
+
+generate_dep_file_init_targets(Globals, DepStream, ModuleName,
+        MakeVarName, InitCFileName, InitFileName, DepFileName, DvFileName,
+        !IO) :-
     module_name_to_file_name(Globals, ModuleName, ".dep",
         do_not_create_dirs, DepFileName, !IO),
     module_name_to_file_name(Globals, ModuleName, ".dv",
@@ -1990,7 +2026,19 @@
             "--init-c-file ", TmpInitCFileName,
             " $(", MakeVarName, ".init_cs) $(ALL_C2INITARGS)\n",
         "\t at mercury_update_interface ", InitCFileName, "\n\n"
-    ], !IO),
+    ], !IO).
+
+:- pred generate_dep_file_install_targets(globals::in, io.output_stream::in,
+    module_name::in, deps_map::in, string::in, bool::in, bool::in, bool::in,
+    string::in, string::in, string::in, io::di, io::uo) is det.
+
+generate_dep_file_install_targets(Globals, DepStream, ModuleName, DepsMap,
+        MakeVarName, MmcMakeDeps, Intermod, TransOpt,
+        MaybeModuleDepsVar, MaybeOptsVar, MaybeTransOptsVar, !IO) :-
+    % XXX  Note that we install the `.opt' and `.trans_opt' files
+    % in two places: in the `lib/$(GRADE)/opts' directory, so
+    % that mmc will find them, and also in the `ints' directory,
+    % so that Mmake will find them.  That's not ideal, but it works.
 
     module_name_to_lib_file_name(Globals, "lib", ModuleName, ".install_ints",
         do_not_create_dirs, LibInstallIntsTargetName, !IO),
@@ -2063,11 +2111,6 @@
         "\tdone\n\n"
     ], !IO),
 
-    % XXX  Note that we install the `.opt' and `.trans_opt' files
-    % in two places: in the `lib/$(GRADE)/opts' directory, so
-    % that mmc will find them, and also in the `ints' directory,
-    % so that Mmake will find them.  That's not ideal, but it works.
-
     module_name_to_lib_file_name(Globals, "lib", ModuleName, ".install_opts",
         do_not_create_dirs, LibInstallOptsTargetName, !IO),
     io.write_strings(DepStream,
@@ -2091,12 +2134,12 @@
         "\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
         "\t\tfi; \\\n",
         "\tdone\n",
-        "\t# The following is needed to support the `--use-subdirs' option\n",
-        "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
+            "\t# The following is needed to support the",
+                " `--use-subdirs' option\n",
+            "\t# We try using `$(LN_S)', but if that fails,",
+                " then we just use\n",
         "\t# `$(INSTALL)'.\n",
-        "\tfor ext in ",
-        OptStr, TransOptStr,
-        "; do \\\n",
+            "\tfor ext in ", OptStr, TransOptStr, "; do \\\n",
         "\t\tdir=""$(INSTALL_GRADE_INT_DIR)/Mercury/$${ext}s""; \\\n",
         "\t\trm -rf ""$$dir""; \\\n",
         "\t\t$(LN_S) .. ""$$dir"" || { \\\n",
@@ -2170,8 +2213,13 @@
     "\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
     "\t\t\t$(INSTALL_INT_DIR); \\\n",
     "\t} || exit 1\n",
-    "endif\n\n"], !IO),
+    "endif\n\n"], !IO).
+
+:- pred generate_dep_file_collective_targets(globals::in, io.output_stream::in,
+    module_name::in, string::in, io::di, io::uo) is det.
 
+generate_dep_file_collective_targets(Globals, DepStream, ModuleName,
+        MakeVarName, !IO) :-
     module_name_to_file_name(Globals, ModuleName, ".check",
         do_not_create_dirs, CheckTargetName, !IO),
     module_name_to_file_name(Globals, ModuleName, ".ints",
@@ -2193,11 +2241,10 @@
     module_name_to_file_name(Globals, ModuleName, ".classes",
         do_not_create_dirs, ClassesTargetName, !IO),
 
-    % We need to explicitly mention
-    % $(foo.pic_ss) somewhere in the Mmakefile, otherwise it
-    % won't build properly with --target asm: GNU Make's pattern rule
-    % algorithm will try to use the .m -> .c_date -> .c -> .pic_o rule chain
-    % rather than the .m -> .pic_s_date -> .pic_s -> .pic_o chain.
+    % We need to explicitly mention $(foo.pic_ss) somewhere in the Mmakefile,
+    % otherwise it won't build properly with --target asm: GNU Make's pattern
+    % rule algorithm will try to use the .m -> .c_date -> .c -> .pic_o rule
+    % chain rather than the .m -> .pic_s_date -> .pic_s -> .pic_o chain.
     % So don't remove the pic_ss target here.
 
     io.write_strings(DepStream, [
@@ -2222,8 +2269,17 @@
         JavasTargetName, " : $(", MakeVarName, ".javas)\n\n",
         ".PHONY : ", ClassesTargetName, "\n",
         ClassesTargetName, " : $(", MakeVarName, ".classes)\n\n"
-    ], !IO),
+    ], !IO).
 
+:- pred generate_dep_file_clean_targets(globals::in, io.output_stream::in,
+    module_name::in, string::in, string::in, string::in, string::in,
+    string::in, string::in, string::in, string::in, string::in, string::in,
+    string::in, string::in, io::di, io::uo) is det.
+
+generate_dep_file_clean_targets(Globals, DepStream, ModuleName, MakeVarName,
+        ExeFileName, InitCFileName, InitAsmFileName,
+        InitObjFileName, InitPicObjFileName, InitFileName, LibFileName,
+        SharedLibFileName, JarFileName, DepFileName, DvFileName, !IO) :-
     % If you change the clean targets below, please also update the
     % documentation in doc/user_guide.texi.
     %
@@ -2262,11 +2318,10 @@
         "\t-echo $(", MakeVarName, ".javas) | xargs rm -f\n",
         "\t-echo $(", MakeVarName, ".profs) | xargs rm -f\n",
         "\t-echo $(", MakeVarName, ".errs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".foreign_cs) | xargs rm -f\n"
+        "\t-echo $(", MakeVarName, ".foreign_cs) | xargs rm -f\n",
+        "\n"
     ], !IO),
 
-    io.write_string(DepStream, "\n", !IO),
-
     module_name_to_file_name(Globals, ModuleName, ".realclean",
         do_not_create_dirs, RealCleanTargetName, !IO),
     io.write_strings(DepStream, [
cvs diff: Diffing compiler/notes
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
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