[m-rev.] for review: tupling transformation (part 2)

Julien Fischer juliensf at cs.mu.OZ.AU
Wed Mar 2 17:53:26 AEDT 2005


Index: compiler/stack_opt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_opt.m,v
retrieving revision 1.17
diff -u -r1.17 stack_opt.m
--- compiler/stack_opt.m	22 Feb 2005 04:43:24 -0000	1.17
+++ compiler/stack_opt.m	2 Mar 2005 00:15:48 -0000
@@ -55,12 +55,12 @@
 % we get a consistent set of answers.
 %
 % The first pass (whose main predicate is optimize_live_sets_in_goal) records
-% its results in the var_save_info field of the opt_info data structure it
-% passes around. This field then becomes the main input to the second pass
-% (whose main predicate is record_decisions_in_goal), which performs the
-% source-to-source transformation that makes each segment access via the cell
-% variable the field variables that have been selected to be so accessed
-% by the first pass.
+% its results in the left_anchor_inserts field of the stack_opt_info data
+% structure it passes around. This field then becomes the main input to the
+% second pass (whose main predicate is record_decisions_in_goal), which
+% performs the source-to-source transformation that makes each segment access
+% via the cell variable the field variables that have been selected to be so
+% accessed by the first pass.
 %
 % The principles of this optimization are documented in the paper "Using the
 % heap to eliminate stack accesses" by Zoltan Somogyi and Peter Stuckey.
@@ -83,6 +83,7 @@

 :- implementation.

+:- import_module backend_libs__interval.
 :- import_module backend_libs__matching.
 :- import_module check_hlds__goal_path.
 :- import_module check_hlds__inst_match.
@@ -134,64 +135,13 @@
 		par_conj_own_slots	:: set(prog_var)
 	).

-:- type save_point_type
-	--->	call_site
-	;	resume_point.
-
-:- type save_point --->
-	save_point(
-		save_point_type,
-		goal_path
-	).
-
-:- type branch_construct
-	--->	ite
-	;	disj
-	;	switch
-	;	neg
-	;	par_conj.
-
-:- type resume_save_status
-	--->	has_resume_save
-	;	has_no_resume_save.
-
-:- type anchor
-	--->	proc_start
-	;	proc_end
-	;	branch_start(branch_construct, goal_path)
-	;	cond_then(goal_path)
-	;	branch_end(branch_construct, goal_path)
-	;	call_site(goal_path).
-
-:- type interval_id	--->	interval_id(int).
-
-:- type branch_end_info --->
-	branch_end_info(
-		flushed_after_branch	:: set(prog_var),
-		accessed_after_branch	:: set(prog_var),
-		interval_after_branch	:: interval_id
-	).
-
-:- type insert_spec --->
-	insert_spec(
-		hlds_goal,
-		set(prog_var)
-	).
-
-:- type insert_map		==	map(anchor, list(insert_spec)).
-
-:- type anchor_follow_info	==	pair(set(prog_var), set(interval_id)).
-
-:- type opt_params --->
-	opt_params(
-		module_info		:: module_info,
-		var_types		:: vartypes,
+:- type stack_opt_params --->
+	stack_opt_params(
 		matching_params		:: matching_params,
 		all_path_node_ratio	:: int,
 		fixpoint_loop		:: bool,
 		full_path		:: bool,
 		on_stack		:: bool,
-		opt_at_most_zero_calls	:: bool,
 		non_candidate_vars	:: set(prog_var)
 	).

@@ -208,33 +158,13 @@
 		set(anchor)
 	).

-:- type opt_info --->
-	opt_info(
-		opt_params		:: opt_params,
-		flushed_later		:: set(prog_var),
-		accessed_later		:: set(prog_var),
-		branch_resume_map	:: map(goal_path, resume_save_status),
-		branch_end_map		:: map(goal_path, branch_end_info),
-		cond_end_map		:: map(goal_path, interval_id),
-		cur_interval		:: interval_id,
-		interval_counter	:: counter,
-		open_intervals		:: set(interval_id),
-		anchor_follow_map	:: map(anchor, anchor_follow_info),
-		model_non_anchors	:: set(anchor),
+:- type stack_opt_info --->
+	stack_opt_info(
+		stack_opt_params	:: stack_opt_params,
 		left_anchor_inserts	:: insert_map,
-		interval_start		:: map(interval_id, anchor),
-		interval_end		:: map(interval_id, anchor),
-		interval_succ		:: map(interval_id, list(interval_id)),
-		interval_vars		:: map(interval_id, set(prog_var)),
-		interval_delvars	:: map(interval_id,
-						list(set(prog_var))),
 		matching_results	:: list(matching_result)
 	).

-:- type maybe_needs_flush
-	--->	needs_flush
-	;	doesnt_need_flush.
-
 stack_opt_cell(PredId, ProcId, !ProcInfo, !ModuleInfo, !IO) :-
 	% This simplication is necessary to fix some bad inputs from
 	% getting to the liveness computation.
@@ -348,29 +278,31 @@
 		optimize_saved_vars_cell_on_stack, OnStack),
 	globals__lookup_bool_option(Globals,
 		opt_no_return_calls, OptNoReturnCalls),
-	OptParams = opt_params(ModuleInfo, VarTypes0, MatchingParams,
-		AllPathNodeRatio, FixpointLoop, FullPath, OnStack,
-		OptNoReturnCalls, NonCandidateVars),
-	OptInfo0 = opt_info(OptParams, set__init, OutputArgs, map__init,
-		map__init, map__init, CurIntervalId, Counter1,
+	IntParams = interval_params(ModuleInfo, VarTypes0, OptNoReturnCalls),
+	IntervalInfo0 = interval_info(IntParams, set__init, OutputArgs,
+		map__init, map__init, map__init, CurIntervalId, Counter1,
 		set__make_singleton_set(CurIntervalId),
-		map__init, set__init, InsertMap0, StartMap0, EndMap0,
-		SuccMap0, VarsMap0, map__init, []),
-	optimize_live_sets_in_goal(Goal0, OptInfo0, OptInfo),
+		map__init, set__init, StartMap0, EndMap0,
+		SuccMap0, VarsMap0, map__init),
+	StackOptParams = stack_opt_params(MatchingParams, AllPathNodeRatio,
+		FixpointLoop, FullPath, OnStack, NonCandidateVars),
+	StackOptInfo0 = stack_opt_info(StackOptParams, InsertMap0, []),
+	build_interval_info_in_goal(Goal0, IntervalInfo0, IntervalInfo,
+		StackOptInfo0, StackOptInfo),
 	( DebugStackOpt = PredIdInt ->
-		dump_opt_info(OptInfo, !IO)
+		dump_interval_info(IntervalInfo, !IO),
+		dump_stack_opt_info(StackOptInfo, !IO)
 	;
 		true
 	),
-	InsertMap = OptInfo ^ left_anchor_inserts,
+	InsertMap = StackOptInfo ^ left_anchor_inserts,
 	( map__is_empty(InsertMap) ->
 		Changed = no
 	;
-		VarInfo0 = var_info(VarSet0, VarTypes0),
-		record_decisions_in_goal(Goal0, Goal1, VarInfo0, VarInfo,
-			map__init, RenameMap, InsertMap),
+		record_decisions_in_goal(Goal0, Goal1, VarSet0, VarSet,
+			VarTypes0, VarTypes, map__init, RenameMap,
+			InsertMap, yes(stack_opt)),
 		apply_headvar_correction(HeadVars, RenameMap, Goal1, Goal),
-		VarInfo = var_info(VarSet, VarTypes),
 		proc_info_set_goal(Goal, !ProcInfo),
 		proc_info_set_varset(VarSet, !ProcInfo),
 		proc_info_set_vartypes(VarTypes, !ProcInfo),
@@ -378,311 +310,6 @@
 	).

 %-----------------------------------------------------------------------------%
-
-:- pred optimize_live_sets_in_goal(hlds_goal::in,
-	opt_info::in, opt_info::out) is det.
-
-optimize_live_sets_in_goal(conj(Goals) - _GoalInfo, !OptInfo) :-
-	optimize_live_sets_in_conj(Goals, !OptInfo).
-
-optimize_live_sets_in_goal(par_conj(Goals) - _GoalInfo, !OptInfo) :-
-	optimize_live_sets_in_par_conj(Goals, !OptInfo).
-
-optimize_live_sets_in_goal(disj(Goals) - GoalInfo, !OptInfo) :-
-	( Goals = [FirstDisjunct | _] ->
-		reached_branch_end(GoalInfo, yes(FirstDisjunct), disj,
-			StartAnchor, EndAnchor, BeforeId, AfterId,
-			MaybeResumeVars, !OptInfo),
-		optimize_live_sets_in_disj(Goals, doesnt_need_flush,
-			StartAnchor, EndAnchor, BeforeId, AfterId,
-			OpenIntervals, !OptInfo),
-		leave_branch_start(disj, StartAnchor, BeforeId,
-			MaybeResumeVars, OpenIntervals, !OptInfo)
-	;
-		% We could reset the set of variables in the current interval
-		% to the empty set, since any variable accesses after a fail
-		% goal (which is what an empty disjunction represent) will not
-		% be executed at runtime. However, simplify should have removed
-		% any goals in the current branch from after the fail, so the
-		% set of variables in the current interval will already be
-		% the empty set.
-		no_open_intervals(!OptInfo)
-	).
-
-optimize_live_sets_in_goal(switch(Var, _Det, Cases) - GoalInfo, !OptInfo) :-
-	reached_branch_end(GoalInfo, no, switch,
-		StartAnchor, EndAnchor, BeforeId, AfterId, MaybeResumeVars,
-		!OptInfo),
-	optimize_live_sets_in_cases(Cases, StartAnchor, EndAnchor,
-		BeforeId, AfterId, OpenIntervalsList, !OptInfo),
-	OpenIntervals = set__union_list(OpenIntervalsList),
-	leave_branch_start(switch, StartAnchor, BeforeId, MaybeResumeVars,
-		OpenIntervals, !OptInfo),
-	require_in_regs([Var], !OptInfo),
-	require_access([Var], !OptInfo).
-
-optimize_live_sets_in_goal(not(Goal) - GoalInfo, !OptInfo) :-
-	reached_branch_end(GoalInfo, yes(Goal), neg,
-		StartAnchor, EndAnchor, BeforeId, AfterId, MaybeResumeVars,
-		!OptInfo),
-	enter_branch_tail(EndAnchor, AfterId, !OptInfo),
-	optimize_live_sets_in_goal(Goal, !OptInfo),
-	reached_branch_start(needs_flush, StartAnchor, BeforeId,
-		OpenIntervals, !OptInfo),
-	leave_branch_start(neg, StartAnchor, BeforeId, MaybeResumeVars,
-		OpenIntervals, !OptInfo).
-
-optimize_live_sets_in_goal(if_then_else(_, Cond, Then, Else) - GoalInfo,
-		!OptInfo) :-
-	reached_branch_end(GoalInfo, yes(Cond), ite, StartAnchor, EndAnchor,
-		BeforeId, AfterId, MaybeResumeVars, !OptInfo),
-	enter_branch_tail(EndAnchor, AfterId, !OptInfo),
-	optimize_live_sets_in_goal(Then, !OptInfo),
-	reached_cond_then(GoalInfo, !OptInfo),
-	optimize_live_sets_in_goal(Cond, !OptInfo),
-	reached_branch_start(doesnt_need_flush, StartAnchor, BeforeId,
-		CondOpenIntervals, !OptInfo),
-	enter_branch_tail(EndAnchor, AfterId, !OptInfo),
-	optimize_live_sets_in_goal(Else, !OptInfo),
-	reached_branch_start(needs_flush, StartAnchor, BeforeId,
-		_ElseOpenIntervals, !OptInfo),
-	leave_branch_start(ite, StartAnchor, BeforeId, MaybeResumeVars,
-		CondOpenIntervals, !OptInfo).
-
-optimize_live_sets_in_goal(some(_Vars, _CanRemove, Goal) - _GoalInfo,
-		!OptInfo) :-
-	optimize_live_sets_in_goal(Goal, !OptInfo).
-
-optimize_live_sets_in_goal(Goal - GoalInfo, !OptInfo) :-
-	OptParams = !.OptInfo ^ opt_params,
-	Goal = generic_call(GenericCall, ArgVars, ArgModes, Detism),
-	goal_info_get_maybe_need_across_call(GoalInfo, MaybeNeedAcrossCall),
-	VarTypes = OptParams ^ var_types,
-	list__map(map__lookup(VarTypes), ArgVars, ArgTypes),
-	ModuleInfo = OptParams ^ module_info,
-	arg_info__compute_in_and_out_vars(ModuleInfo, ArgVars,
-		ArgModes, ArgTypes, InputArgs, _OutputArgs),
-	determinism_to_code_model(Detism, CodeModel),
-
-	% unsafe_casts are generated inline.
-	( GenericCall = unsafe_cast ->
-		require_in_regs(InputArgs, !OptInfo),
-		require_access(InputArgs, !OptInfo)
-	;
-		call_gen__generic_call_info(CodeModel, GenericCall, _,
-			GenericVarsArgInfos, _),
-		assoc_list__keys(GenericVarsArgInfos, GenericVars),
-		list__append(GenericVars, InputArgs, Inputs),
-		optimize_live_sets_at_call(Inputs,
-			MaybeNeedAcrossCall, GoalInfo, !OptInfo)
-	).
-
-optimize_live_sets_in_goal(Goal - GoalInfo, !OptInfo) :-
-	Goal = call(PredId, ProcId, ArgVars, Builtin, _, _),
-	OptParams = !.OptInfo ^ opt_params,
-	ModuleInfo = OptParams ^ module_info,
-	module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
-		_PredInfo, ProcInfo),
-	VarTypes = OptParams ^ var_types,
-	arg_info__partition_proc_call_args(ProcInfo, VarTypes,
-		ModuleInfo, ArgVars, InputArgs, _, _),
-	set__to_sorted_list(InputArgs, Inputs),
-	( Builtin = inline_builtin ->
-		require_in_regs(Inputs, !OptInfo),
-		require_access(Inputs, !OptInfo)
-	;
-		goal_info_get_maybe_need_across_call(GoalInfo,
-			MaybeNeedAcrossCall),
-		optimize_live_sets_at_call(Inputs, MaybeNeedAcrossCall,
-			GoalInfo, !OptInfo)
-	).
-
-optimize_live_sets_in_goal(Goal - GoalInfo, !OptInfo) :-
-	Goal = foreign_proc(_Attributes, PredId, ProcId, Args, ExtraArgs,
-		_PragmaCode),
-	OptParams = !.OptInfo ^ opt_params,
-	ModuleInfo = OptParams ^ module_info,
-	module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
-		_PredInfo, ProcInfo),
-	VarTypes = OptParams ^ var_types,
-	ArgVars = list__map(foreign_arg_var, Args),
-	ExtraVars = list__map(foreign_arg_var, ExtraArgs),
-	arg_info__partition_proc_call_args(ProcInfo, VarTypes,
-		ModuleInfo, ArgVars, InputArgVarSet, _, _),
-	set__to_sorted_list(InputArgVarSet, InputArgVars),
-	list__append(InputArgVars, ExtraVars, InputVars),
-	(
-		goal_info_maybe_get_maybe_need_across_call(GoalInfo,
-			MaybeNeedAcrossCall),
-		MaybeNeedAcrossCall = yes(_)
-	->
-		optimize_live_sets_at_call(InputVars, MaybeNeedAcrossCall,
-			GoalInfo, !OptInfo)
-	;
-		require_in_regs(InputVars, !OptInfo),
-		require_access(InputVars, !OptInfo)
-	).
-
-optimize_live_sets_in_goal(Goal - GoalInfo, !OptInfo) :-
-	Goal = unify(_, _, _, Unification, _),
-	(
-		Unification = construct(CellVar, _ConsId, ArgVars, _,
-			HowToConstruct, _, _),
-		( HowToConstruct = reuse_cell(_) ->
-			error("optimize_live_sets_in_goal: reuse")
-		;
-			true
-		),
-		require_in_regs(ArgVars, !OptInfo),
-		require_access([CellVar | ArgVars], !OptInfo)
-		% use_cell(CellVar, ArgVars, ConsId, Goal - GoalInfo, !OptInfo)
-		% We cannot use such cells, because some of the ArgVars
-		% may need to be saved on the stack before this construction.
-	;
-		Unification = deconstruct(CellVar, ConsId, ArgVars,
-			ArgModes, _, _),
-		OptParams = !.OptInfo ^ opt_params,
-		ModuleInfo = OptParams ^ module_info,
-		( shared_left_to_right_deconstruct(ModuleInfo, ArgModes) ->
-			use_cell(CellVar, ArgVars, ConsId, Goal - GoalInfo,
-				!OptInfo)
-		;
-			true
-		),
-		require_in_regs([CellVar], !OptInfo),
-		require_access([CellVar | ArgVars], !OptInfo)
-	;
-		Unification = assign(ToVar, FromVar),
-		require_in_regs([FromVar], !OptInfo),
-		require_access([FromVar, ToVar], !OptInfo)
-	;
-		Unification = simple_test(Var1, Var2),
-		require_in_regs([Var1, Var2], !OptInfo),
-		require_access([Var1, Var2], !OptInfo)
-	;
-		Unification = complicated_unify(_, _, _),
-		error("optimize_live_sets_in_goal: complicated_unify")
-	).
-
-optimize_live_sets_in_goal(shorthand(_) - _, !OptInfo) :-
-	error("shorthand in optimize_live_sets_in_goal").
-
-:- pred shared_left_to_right_deconstruct(module_info::in, list(uni_mode)::in)
-	is semidet.
-
-shared_left_to_right_deconstruct(_, []).
-shared_left_to_right_deconstruct(ModuleInfo, [ArgMode | ArgsModes]) :-
-	ArgMode = ((InitCell - InitArg) -> (FinalCell - FinalArg)),
-	mode_is_fully_input(ModuleInfo, InitCell -> FinalCell),
-	mode_is_output(ModuleInfo, InitArg -> FinalArg),
-	inst_is_not_partly_unique(ModuleInfo, FinalCell),
-	inst_is_not_partly_unique(ModuleInfo, FinalArg),
-	shared_left_to_right_deconstruct(ModuleInfo, ArgsModes).
-
-%-----------------------------------------------------------------------------%
-
-:- pred optimize_live_sets_at_call(list(prog_var)::in,
-	maybe(need_across_call)::in, hlds_goal_info::in,
-	opt_info::in, opt_info::out) is det.
-
-optimize_live_sets_at_call(Inputs, MaybeNeedAcrossCall, GoalInfo, !OptInfo) :-
-	(
-		MaybeNeedAcrossCall = yes(NeedAcrossCall),
-		NeedAcrossCall = need_across_call(ForwardVars,
-			ResumeVars, NondetLiveVars),
-		VarsOnStack0 = set__union_list([ForwardVars, ResumeVars,
-			NondetLiveVars]),
-		goal_info_get_goal_path(GoalInfo, GoalPath),
-		CallAnchor = call_site(GoalPath),
-		get_cur_interval(AfterCallId, !.OptInfo),
-		new_interval_id(BeforeCallId, !OptInfo),
-		record_interval_start(AfterCallId, CallAnchor, !OptInfo),
-		record_interval_end(BeforeCallId, CallAnchor, !OptInfo),
-		goal_info_get_instmap_delta(GoalInfo, InstMapDelta),
-		OptParams = !.OptInfo ^ opt_params,
-		(
-			( instmap_delta_is_reachable(InstMapDelta)
-			; OptParams ^ opt_at_most_zero_calls = no
-			)
-		->
-			record_interval_succ(BeforeCallId, AfterCallId,
-				!OptInfo),
-			VarsOnStack = VarsOnStack0
-		;
-			% If the call cannot succeed, then execution cannot
-			% get from BeforeCallId to AfterCallId.
-			record_interval_no_succ(BeforeCallId, !OptInfo),
-			VarsOnStack = set__init
-		),
-		set_cur_interval(BeforeCallId, !OptInfo),
-		assign_open_intervals_to_anchor(CallAnchor, !OptInfo),
-		goal_info_get_code_model(GoalInfo, CodeModel),
-		( CodeModel = model_non ->
-			record_model_non_anchor(CallAnchor, !OptInfo)
-		;
-			true
-		),
-		one_open_interval(BeforeCallId, !OptInfo),
-		require_flushed(VarsOnStack, !OptInfo),
-		require_in_regs(Inputs, !OptInfo),
-		require_access(Inputs, !OptInfo)
-	;
-		MaybeNeedAcrossCall = no,
-		error("optimize_live_sets_at_call: no need across call")
-	).
-
-%-----------------------------------------------------------------------------%
-
-:- pred optimize_live_sets_in_conj(list(hlds_goal)::in,
-	opt_info::in, opt_info::out) is det.
-
-optimize_live_sets_in_conj([], !OptInfo).
-optimize_live_sets_in_conj([Goal | Goals], !OptInfo) :-
-	optimize_live_sets_in_conj(Goals, !OptInfo),
-	optimize_live_sets_in_goal(Goal, !OptInfo).
-
-:- pred optimize_live_sets_in_par_conj(list(hlds_goal)::in,
-	opt_info::in, opt_info::out) is det.
-
-optimize_live_sets_in_par_conj([], !OptInfo).
-optimize_live_sets_in_par_conj([Goal | Goals], !OptInfo) :-
-	% XXX zs: I am not sure that passing opt_info from the first goal to
-	% the rest is OK. Maybe we should pass the initial opt_info to all the
-	% conjuncts, and then merge the resulting opt_infos.
-	optimize_live_sets_in_par_conj(Goals, !OptInfo),
-	optimize_live_sets_in_goal(Goal, !OptInfo).
-
-:- pred optimize_live_sets_in_disj(list(hlds_goal)::in, maybe_needs_flush::in,
-	anchor::in, anchor::in, interval_id::in, interval_id::in,
-	set(interval_id)::out, opt_info::in, opt_info::out) is det.
-
-optimize_live_sets_in_disj([], _, _, _, _, _, set__init, !OptInfo).
-optimize_live_sets_in_disj([Goal | Goals], MaybeNeedsFlush,
-		StartAnchor, EndAnchor, BeforeId, AfterId, OpenIntervals,
-		!OptInfo) :-
-	enter_branch_tail(EndAnchor, AfterId, !OptInfo),
-	optimize_live_sets_in_goal(Goal, !OptInfo),
-	reached_branch_start(MaybeNeedsFlush, StartAnchor, BeforeId,
-		OpenIntervals, !OptInfo),
-	optimize_live_sets_in_disj(Goals, needs_flush, StartAnchor, EndAnchor,
-		BeforeId, AfterId, _OpenIntervals, !OptInfo).
-
-:- pred optimize_live_sets_in_cases(list(case)::in,
-	anchor::in, anchor::in, interval_id::in, interval_id::in,
-	list(set(interval_id))::out, opt_info::in, opt_info::out) is det.
-
-optimize_live_sets_in_cases([], _, _, _, _, [], !OptInfo).
-optimize_live_sets_in_cases([case(_Var, Goal) | Cases], StartAnchor, EndAnchor,
-		BeforeId, AfterId, [OpenIntervals | OpenIntervalsList],
-		!OptInfo) :-
-	enter_branch_tail(EndAnchor, AfterId, !OptInfo),
-	optimize_live_sets_in_goal(Goal, !OptInfo),
-	reached_branch_start(doesnt_need_flush, StartAnchor, BeforeId,
-		OpenIntervals, !OptInfo),
-	optimize_live_sets_in_cases(Cases, StartAnchor, EndAnchor,
-		BeforeId, AfterId, OpenIntervalsList, !OptInfo).
-
-%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

 :- instance stack_alloc_info(opt_stack_alloc) where [
@@ -713,328 +340,9 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

-:- pred reached_branch_end(hlds_goal_info::in, maybe(hlds_goal)::in,
-	branch_construct::in, anchor::out, anchor::out,
-	interval_id::out, interval_id::out, maybe(set(prog_var))::out,
-	opt_info::in, opt_info::out) is det.
-
-reached_branch_end(GoalInfo, MaybeResumeGoal, Construct,
-		StartAnchor, EndAnchor, BeforeIntervalId, AfterIntervalId,
-		MaybeResumeVars, !OptInfo) :-
-	goal_info_get_goal_path(GoalInfo, GoalPath),
-	record_branch_end_info(GoalPath, !OptInfo),
-	(
-		MaybeResumeGoal = yes(_ResumeGoalExpr - ResumeGoalInfo),
-		goal_info_maybe_get_resume_point(ResumeGoalInfo, ResumePoint),
-		ResumePoint = resume_point(ResumeVars, ResumeLocs),
-		ResumeLocs \= orig_only
-	->
-		HasResumeSave = has_resume_save,
-		MaybeResumeVars = yes(ResumeVars)
-	;
-		HasResumeSave = has_no_resume_save,
-		MaybeResumeVars = no
-	),
-	record_branch_resume(GoalPath, HasResumeSave, !OptInfo),
-	( goal_info_maybe_get_store_map(GoalInfo, StoreMap) ->
-		map__sorted_keys(StoreMap, StoreMapVarList),
-		set__sorted_list_to_set(StoreMapVarList, StoreMapVars),
-		require_flushed(StoreMapVars, !OptInfo)
-	;
-		error("reached_branch_end: no store map")
-	),
-	EndAnchor = branch_end(Construct, GoalPath),
-	StartAnchor = branch_start(Construct, GoalPath),
-	assign_open_intervals_to_anchor(EndAnchor, !OptInfo),
-	goal_info_get_code_model(GoalInfo, CodeModel),
-	( CodeModel = model_non ->
-		record_model_non_anchor(EndAnchor, !OptInfo)
-	;
-		true
-	),
-	no_open_intervals(!OptInfo),
-	get_cur_interval(AfterIntervalId, !.OptInfo),
-	record_interval_start(AfterIntervalId, EndAnchor, !OptInfo),
-	new_interval_id(BeforeIntervalId, !OptInfo).
-
-:- pred enter_branch_tail(anchor::in, interval_id::in,
-	opt_info::in, opt_info::out) is det.
-
-enter_branch_tail(EndAnchor, AfterId, !OptInfo) :-
-	new_interval_id(BranchTailId, !OptInfo),
-	record_interval_end(BranchTailId, EndAnchor, !OptInfo),
-	record_interval_succ(BranchTailId, AfterId, !OptInfo),
-	set_cur_interval(BranchTailId, !OptInfo),
-	one_open_interval(BranchTailId, !OptInfo).
-
-:- pred reached_branch_start(maybe_needs_flush::in, anchor::in,
-	interval_id::in, set(interval_id)::out, opt_info::in, opt_info::out)
-	is det.
-
-reached_branch_start(MaybeNeedsFlush, StartAnchor, BeforeId, OpenIntervals,
-		!OptInfo) :-
-	get_cur_interval(BranchStartId, !.OptInfo),
-	record_interval_start(BranchStartId, StartAnchor, !OptInfo),
-	record_interval_succ(BeforeId, BranchStartId, !OptInfo),
-	get_open_intervals(!.OptInfo, OpenIntervals),
-	(
-		MaybeNeedsFlush = doesnt_need_flush
-	;
-		MaybeNeedsFlush = needs_flush,
-		assign_open_intervals_to_anchor(StartAnchor, !OptInfo)
-	).
-
-:- pred reached_cond_then(hlds_goal_info::in, opt_info::in, opt_info::out)
-	is det.
-
-reached_cond_then(GoalInfo, !OptInfo) :-
-	goal_info_get_goal_path(GoalInfo, GoalPath),
-	record_cond_end(GoalPath, !OptInfo),
-	get_cur_interval(ThenStartId, !.OptInfo),
-	record_interval_start(ThenStartId, CondThenAnchor, !OptInfo),
-	new_interval_id(CondTailId, !OptInfo),
-	CondThenAnchor = cond_then(GoalPath),
-	record_interval_end(CondTailId, CondThenAnchor, !OptInfo),
-	record_interval_succ(CondTailId, ThenStartId, !OptInfo),
-	set_cur_interval(CondTailId, !OptInfo),
-	get_open_intervals(!.OptInfo, OpenIntervals0),
-	svset__insert(CondTailId, OpenIntervals0, OpenIntervals),
-	set_open_intervals(OpenIntervals, !OptInfo).
-
-:- pred leave_branch_start(branch_construct::in, anchor::in, interval_id::in,
-	maybe(set(prog_var))::in, set(interval_id)::in,
-	opt_info::in, opt_info::out) is det.
-
-leave_branch_start(_BranchConstruct, StartArchor, BeforeId, MaybeResumeVars,
-		OpenIntervals, !OptInfo) :-
-	record_interval_end(BeforeId, StartArchor, !OptInfo),
-	(
-		MaybeResumeVars = yes(ResumeVars),
-		require_flushed(ResumeVars, !OptInfo)
-	;
-		MaybeResumeVars = no
-	),
-	set_cur_interval(BeforeId, !OptInfo),
-	set_open_intervals(OpenIntervals, !OptInfo).
-
-:- pred get_open_intervals(opt_info::in, set(interval_id)::out) is det.
-
-get_open_intervals(OptInfo, OpenIntervals) :-
-	OpenIntervals = OptInfo ^ open_intervals.
-
-:- pred set_open_intervals(set(interval_id)::in,
-	opt_info::in, opt_info::out) is det.
-
-set_open_intervals(OpenIntervals, !OptInfo) :-
-	!:OptInfo = !.OptInfo ^ open_intervals := OpenIntervals.
-
-:- pred no_open_intervals(opt_info::in, opt_info::out) is det.
-
-no_open_intervals(!OptInfo) :-
-	!:OptInfo = !.OptInfo ^ open_intervals := set__init.
-
-:- pred one_open_interval(interval_id::in, opt_info::in, opt_info::out) is det.
-
-one_open_interval(IntervalId, !OptInfo) :-
-	!:OptInfo = !.OptInfo ^ open_intervals :=
-		set__make_singleton_set(IntervalId).
-
-:- pred assign_open_intervals_to_anchor(anchor::in,
-	opt_info::in, opt_info::out) is det.
-
-assign_open_intervals_to_anchor(Anchor, !OptInfo) :-
-	AnchorFollowMap0 = !.OptInfo ^ anchor_follow_map,
-	IntervalVarMap = !.OptInfo ^ interval_vars,
-	CurOpenIntervals = !.OptInfo ^ open_intervals,
-	set__fold(gather_interval_vars(IntervalVarMap), CurOpenIntervals,
-		set__init, CurOpenIntervalVars),
-	( map__search(AnchorFollowMap0, Anchor, AnchorFollowInfo0) ->
-		AnchorFollowInfo0 = OpenIntervalVars0 - OpenIntervals0,
-		OpenIntervalVars =
-			set__union(OpenIntervalVars0, CurOpenIntervalVars),
-		OpenIntervals =
-			set__union(OpenIntervals0, CurOpenIntervals),
-		AnchorFollowInfo = OpenIntervalVars - OpenIntervals,
-		svmap__det_update(Anchor, AnchorFollowInfo,
-			AnchorFollowMap0, AnchorFollowMap)
-	;
-		AnchorFollowInfo = CurOpenIntervalVars - CurOpenIntervals,
-		svmap__det_insert(Anchor, AnchorFollowInfo,
-			AnchorFollowMap0, AnchorFollowMap)
-	),
-	!:OptInfo = !.OptInfo ^ anchor_follow_map := AnchorFollowMap.
-
-:- pred gather_interval_vars(map(interval_id, set(prog_var))::in,
-	interval_id::in, set(prog_var)::in, set(prog_var)::out) is det.
-
-gather_interval_vars(IntervalVarMap, IntervalId, !OpenIntervalVars) :-
-	map__lookup(IntervalVarMap, IntervalId, IntervalVars),
-	!:OpenIntervalVars = set__union(!.OpenIntervalVars, IntervalVars).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- pred get_cur_interval(interval_id::out, opt_info::in) is det.
-
-get_cur_interval(OptInfo ^ cur_interval, OptInfo).
-
-:- pred set_cur_interval(interval_id::in, opt_info::in, opt_info::out) is det.
-
-set_cur_interval(CurInterval, OptInfo,
-	OptInfo ^ cur_interval := CurInterval).
-
-:- pred new_interval_id(interval_id::out, opt_info::in, opt_info::out) is det.
-
-new_interval_id(Id, !OptInfo) :-
-	Counter0 = !.OptInfo ^ interval_counter,
-	IntervalVars0 = !.OptInfo ^ interval_vars,
-	counter__allocate(Num, Counter0, Counter),
-	Id = interval_id(Num),
-	svmap__det_insert(Id, set__init, IntervalVars0, IntervalVars),
-	!:OptInfo = !.OptInfo ^ interval_counter := Counter,
-	!:OptInfo = !.OptInfo ^ interval_vars := IntervalVars.
-
-:- pred record_branch_end_info(goal_path::in,
-	opt_info::in, opt_info::out) is det.
-
-record_branch_end_info(GoalPath, !OptInfo) :-
-	FlushedLater = !.OptInfo ^ flushed_later,
-	AccessedLater = !.OptInfo ^ accessed_later,
-	CurInterval = !.OptInfo ^ cur_interval,
-	BranchEndMap0 = !.OptInfo ^ branch_end_map,
-	BranchEndInfo = branch_end_info(FlushedLater, AccessedLater,
-		CurInterval),
-	svmap__det_insert(GoalPath, BranchEndInfo,
-		BranchEndMap0, BranchEndMap),
-	!:OptInfo = !.OptInfo ^ branch_end_map := BranchEndMap.
-
-:- pred record_cond_end(goal_path::in, opt_info::in, opt_info::out) is det.
-
-record_cond_end(GoalPath, !OptInfo) :-
-	CurInterval = !.OptInfo ^ cur_interval,
-	CondEndMap0 = !.OptInfo ^ cond_end_map,
-	svmap__det_insert(GoalPath, CurInterval, CondEndMap0, CondEndMap),
-	!:OptInfo = !.OptInfo ^ cond_end_map := CondEndMap.
-
-:- pred record_interval_end(interval_id::in, anchor::in,
-	opt_info::in, opt_info::out) is det.
-
-record_interval_end(Id, End, !OptInfo) :-
-	EndMap0 = !.OptInfo ^ interval_end,
-	svmap__det_insert(Id, End, EndMap0, EndMap),
-	!:OptInfo = !.OptInfo ^ interval_end := EndMap.
-
-:- pred record_interval_start(interval_id::in, anchor::in,
-	opt_info::in, opt_info::out) is det.
-
-record_interval_start(Id, Start, !OptInfo) :-
-	StartMap0 = !.OptInfo ^ interval_start,
-	svmap__det_insert(Id, Start, StartMap0, StartMap),
-	!:OptInfo = !.OptInfo ^ interval_start := StartMap.
-
-:- pred record_interval_succ(interval_id::in, interval_id::in,
-	opt_info::in, opt_info::out) is det.
-
-record_interval_succ(Id, Succ, !OptInfo) :-
-	SuccMap0 = !.OptInfo ^ interval_succ,
-	( map__search(SuccMap0, Id, Succ0) ->
-		svmap__det_update(Id, [Succ | Succ0], SuccMap0, SuccMap)
-	;
-		svmap__det_insert(Id, [Succ], SuccMap0, SuccMap)
-	),
-	!:OptInfo = !.OptInfo ^ interval_succ := SuccMap.
-
-:- pred record_interval_no_succ(interval_id::in,
-	opt_info::in, opt_info::out) is det.
-
-record_interval_no_succ(Id, !OptInfo) :-
-	SuccMap0 = !.OptInfo ^ interval_succ,
-	( map__search(SuccMap0, Id, _Succ0) ->
-		error("record_interval_no_succ: already in succ map")
-	;
-		svmap__det_insert(Id, [], SuccMap0, SuccMap)
-	),
-	!:OptInfo = !.OptInfo ^ interval_succ := SuccMap.
-
-:- pred record_interval_vars(interval_id::in, list(prog_var)::in,
-	opt_info::in, opt_info::out) is det.
-
-record_interval_vars(Id, NewVars, !OptInfo) :-
-	VarsMap0 = !.OptInfo ^ interval_vars,
-	( map__search(VarsMap0, Id, Vars0) ->
-		svset__insert_list(NewVars, Vars0, Vars),
-		svmap__det_update(Id, Vars, VarsMap0, VarsMap)
-	;
-		set__list_to_set(NewVars, Vars),
-		svmap__det_insert(Id, Vars, VarsMap0, VarsMap)
-	),
-	!:OptInfo = !.OptInfo ^ interval_vars := VarsMap.
-
-:- pred delete_interval_vars(interval_id::in, set(prog_var)::in,
-	set(prog_var)::out, opt_info::in, opt_info::out) is det.
-
-delete_interval_vars(Id, ToDeleteVars, DeletedVars, !OptInfo) :-
-	VarsMap0 = !.OptInfo ^ interval_vars,
-	map__lookup(VarsMap0, Id, Vars0),
-	DeletedVars = set__intersect(Vars0, ToDeleteVars),
-	Vars = set__difference(Vars0, DeletedVars),
-	svmap__det_update(Id, Vars, VarsMap0, VarsMap),
-	!:OptInfo = !.OptInfo ^ interval_vars := VarsMap,
-
-	% The deletions are recorded only for debugging. The algorithm itself
-	% does not need this information to be recorded.
-	DeleteMap0 = !.OptInfo ^ interval_delvars,
-	( map__search(DeleteMap0, Id, Deletions0) ->
-		Deletions = [DeletedVars | Deletions0],
-		svmap__det_update(Id, Deletions, DeleteMap0, DeleteMap)
-	;
-		Deletions = [DeletedVars],
-		svmap__det_insert(Id, Deletions, DeleteMap0, DeleteMap)
-	),
-	!:OptInfo = !.OptInfo ^ interval_delvars := DeleteMap.
-
-:- pred require_in_regs(list(prog_var)::in, opt_info::in, opt_info::out)
-	is det.
-
-require_in_regs(Vars, !OptInfo) :-
-	CurIntervalId = !.OptInfo ^ cur_interval,
-	record_interval_vars(CurIntervalId, Vars, !OptInfo).
-
-:- pred require_flushed(set(prog_var)::in,
-	opt_info::in, opt_info::out) is det.
-
-require_flushed(Vars, !OptInfo) :-
-	FlushedLater0 = !.OptInfo ^ flushed_later,
-	FlushedLater = set__union(FlushedLater0, Vars),
-	!:OptInfo = !.OptInfo ^ flushed_later := FlushedLater.
-
-:- pred require_access(list(prog_var)::in,
-	opt_info::in, opt_info::out) is det.
-
-require_access(Vars, !OptInfo) :-
-	AccessedLater0 = !.OptInfo ^ accessed_later,
-	svset__insert_list(Vars, AccessedLater0, AccessedLater),
-	!:OptInfo = !.OptInfo ^ accessed_later := AccessedLater.
-
-:- pred record_branch_resume(goal_path::in, resume_save_status::in,
-	opt_info::in, opt_info::out) is det.
-
-record_branch_resume(GoalPath, ResumeSaveStatus, !OptInfo) :-
-	BranchResumeMap0 = !.OptInfo ^ branch_resume_map,
-	svmap__det_insert(GoalPath, ResumeSaveStatus,
-		BranchResumeMap0, BranchResumeMap),
-	!:OptInfo = !.OptInfo ^ branch_resume_map := BranchResumeMap.
-
-:- pred record_model_non_anchor(anchor::in, opt_info::in, opt_info::out)
-	is det.
-
-record_model_non_anchor(Anchor, !OptInfo) :-
-	ModelNonAnchors0 = !.OptInfo ^ model_non_anchors,
-	svset__insert(Anchor, ModelNonAnchors0, ModelNonAnchors),
-	!:OptInfo = !.OptInfo ^ model_non_anchors := ModelNonAnchors.
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
+:- instance build_interval_info_acc(stack_opt_info) where [
+	pred(use_cell/8) is stack_opt__use_cell
+].

 :- type match_path_info
 	--->	match_path_info(
@@ -1063,12 +371,13 @@
 		).

 :- pred use_cell(prog_var::in, list(prog_var)::in, cons_id::in, hlds_goal::in,
-	opt_info::in, opt_info::out) is det.
+	interval_info::in, interval_info::out, stack_opt_info::in,
+	stack_opt_info::out) is det.

-use_cell(CellVar, FieldVarList, ConsId, Goal, !OptInfo) :-
-	FlushedLater = !.OptInfo ^ flushed_later,
-	OptParams = !.OptInfo ^ opt_params,
-	NonCandidateVars = OptParams ^ non_candidate_vars,
+use_cell(CellVar, FieldVarList, ConsId, Goal, !IntervalInfo, !StackOptInfo) :-
+	FlushedLater = !.IntervalInfo ^ flushed_later,
+	StackOptParams = !.StackOptInfo ^ stack_opt_params,
+	NonCandidateVars = StackOptParams ^ non_candidate_vars,
 	set__list_to_set(FieldVarList, FieldVars),
 	set__intersect(FieldVars, FlushedLater, FlushedLaterFieldVars),
 	set__difference(FlushedLaterFieldVars, NonCandidateVars,
@@ -1079,7 +388,8 @@
 		true
 	;
 		ConsId = cons(_Name, _Arity),
-		VarTypes = OptParams ^ var_types,
+		IntParams = !.IntervalInfo ^ interval_params,
+		VarTypes = IntParams ^ var_types,
 		map__lookup(VarTypes, CellVar, Type),
 		(
 			type_is_tuple(Type, _)
@@ -1087,7 +397,7 @@
 			FreeOfCost = no
 		;
 			type_to_ctor_and_args(Type, TypeCtor, _),
-			ModuleInfo = OptParams ^ module_info,
+			ModuleInfo = IntParams ^ module_info,
 			module_info_types(ModuleInfo, TypeTable),
 			map__lookup(TypeTable, TypeCtor, TypeDefn),
 			hlds_data__get_type_defn_body(TypeDefn, TypeBody),
@@ -1105,7 +415,7 @@
 	->
 		RelevantVars = set__insert(FieldVars, CellVar),
 		find_all_branches_from_cur_interval(RelevantVars, MatchInfo,
-			!.OptInfo),
+			!.IntervalInfo, !.StackOptInfo),
 		MatchInfo = match_info(PathsInfo, RelevantAfterVars,
 			AfterModelNon, InsertAnchors, InsertIntervals),
 		(
@@ -1114,12 +424,13 @@
 				ViaCellVars),
 			record_matching_result(CellVar, ConsId,
 				FieldVarList, ViaCellVars, Goal,
-				InsertAnchors, InsertIntervals, !OptInfo)
+				InsertAnchors, InsertIntervals, !IntervalInfo,
+				!StackOptInfo)
 		;
 			FreeOfCost = no,
 			(
 				AfterModelNon = no,
-				OnStack = OptParams ^ on_stack,
+				OnStack = StackOptParams ^ on_stack,
 				set__difference(CandidateArgVars0,
 					RelevantAfterVars, CandidateArgVars),
 			(
@@ -1146,12 +457,12 @@
 					)
 				),
 				apply_matching(CellVar, CellVarFlushedLater,
-					OptParams, PathsInfo, CandidateArgVars,
-					ViaCellVars),
+					IntParams, StackOptParams, PathsInfo,
+					CandidateArgVars, ViaCellVars),
 				record_matching_result(CellVar, ConsId,
 					FieldVarList, ViaCellVars, Goal,
 					InsertAnchors, InsertIntervals,
-					!OptInfo)
+					!IntervalInfo, !StackOptInfo)
 			;
 				AfterModelNon = yes
 			)
@@ -1160,36 +471,37 @@
 		true
 	).

-:- pred apply_matching(prog_var::in, bool::in, opt_params::in,
-	list(match_path_info)::in, set(prog_var)::in, set(prog_var)::out)
-	is det.
-
-apply_matching(CellVar, CellVarFlushedLater, OptParams, PathInfos,
-		CandidateArgVars0, ViaCellVars) :-
-	apply_matching_loop(CellVar, CellVarFlushedLater, OptParams, PathInfos,
+:- pred apply_matching(prog_var::in, bool::in, interval_params::in,
+	stack_opt_params::in, list(match_path_info)::in,
+	set(prog_var)::in, set(prog_var)::out) is det.
+
+apply_matching(CellVar, CellVarFlushedLater, IntParams, StackOptParams,
+		PathInfos, CandidateArgVars0, ViaCellVars) :-
+	apply_matching_loop(CellVar, CellVarFlushedLater, IntParams,
+		StackOptParams, PathInfos,
 		CandidateArgVars0, BenefitNodeSets, CostNodeSets,
 		ViaCellVars0),
 	BenefitNodes = set__union_list(BenefitNodeSets),
 	CostNodes = set__union_list(CostNodeSets),
 	set__count(BenefitNodes, NumBenefitNodes),
 	set__count(CostNodes, NumCostNodes),
-	AllPathNodeRatio = OptParams ^ all_path_node_ratio,
+	AllPathNodeRatio = StackOptParams ^ all_path_node_ratio,
 	( NumBenefitNodes * 100 >= NumCostNodes * AllPathNodeRatio ->
 		ViaCellVars = ViaCellVars0
 	;
 		ViaCellVars = set__init
 	).

-:- pred apply_matching_loop(prog_var::in, bool::in, opt_params::in,
-	list(match_path_info)::in, set(prog_var)::in,
+:- pred apply_matching_loop(prog_var::in, bool::in, interval_params::in,
+	stack_opt_params::in, list(match_path_info)::in, set(prog_var)::in,
 	list(set(benefit_node))::out, list(set(cost_node))::out,
 	set(prog_var)::out) is det.

-apply_matching_loop(CellVar, CellVarFlushedLater, OptParams, PathInfos,
-		CandidateArgVars0, BenefitNodeSets, CostNodeSets,
+apply_matching_loop(CellVar, CellVarFlushedLater, IntParams, StackOptParams,
+		PathInfos, CandidateArgVars0, BenefitNodeSets, CostNodeSets,
 		ViaCellVars) :-
 	list__map3(apply_matching_for_path(CellVar, CellVarFlushedLater,
-		OptParams, CandidateArgVars0), PathInfos,
+		StackOptParams, CandidateArgVars0), PathInfos,
 		BenefitNodeSets0, CostNodeSets0, PathViaCellVars),
 	( list__all_same(PathViaCellVars) ->
 		BenefitNodeSets = BenefitNodeSets0,
@@ -1201,7 +513,7 @@
 		)
 	;
 		CandidateArgVars1 = set__intersect_list(PathViaCellVars),
-		FixpointLoop = OptParams ^ fixpoint_loop,
+		FixpointLoop = StackOptParams ^ fixpoint_loop,
 		(
 			FixpointLoop = no,
 			BenefitNodeSets = BenefitNodeSets0,
@@ -1210,17 +522,18 @@
 		;
 			FixpointLoop = yes,
 			apply_matching_loop(CellVar, CellVarFlushedLater,
-				OptParams, PathInfos, CandidateArgVars1,
+				IntParams, StackOptParams, PathInfos,
+				CandidateArgVars1,
 				BenefitNodeSets, CostNodeSets, ViaCellVars)
 		)
 	).

-:- pred apply_matching_for_path(prog_var::in, bool::in, opt_params::in,
+:- pred apply_matching_for_path(prog_var::in, bool::in, stack_opt_params::in,
 	set(prog_var)::in, match_path_info::in,
 	set(benefit_node)::out, set(cost_node)::out, set(prog_var)::out)
 	is det.

-apply_matching_for_path(CellVar, CellVarFlushedLater, OptParams,
+apply_matching_for_path(CellVar, CellVarFlushedLater, StackOptParams,
 		CandidateArgVars, PathInfo, BenefitNodes, CostNodes,
 		ViaCellVars) :-
 	( set__empty(CandidateArgVars) ->
@@ -1229,7 +542,7 @@
 		ViaCellVars = set__init
 	;
 		PathInfo = match_path_info(FirstSegment, LaterSegments),
-		MatchingParams = OptParams ^ matching_params,
+		MatchingParams = StackOptParams ^ matching_params,
 		find_via_cell_vars(CellVar, CandidateArgVars,
 			CellVarFlushedLater, FirstSegment, LaterSegments,
 			MatchingParams, BenefitNodes, CostNodes, ViaCellVars)
@@ -1237,22 +550,27 @@

 :- pred record_matching_result(prog_var::in, cons_id::in, list(prog_var)::in,
 	set(prog_var)::in, hlds_goal::in, set(anchor)::in,
-	set(interval_id)::in, opt_info::in, opt_info::out) is det.
+	set(interval_id)::in, interval_info::in, interval_info::out,
+	stack_opt_info::in, stack_opt_info::out) is det.

 record_matching_result(CellVar, ConsId, ArgVars, ViaCellVars, Goal,
-		PotentialAnchors, PotentialIntervals, OptInfo0, OptInfo) :-
+		PotentialAnchors, PotentialIntervals,
+		IntervalInfo0, IntervalInfo, StackOptInfo0, StackOptInfo) :-
 	( set__empty(ViaCellVars) ->
-		OptInfo = OptInfo0
+		IntervalInfo = IntervalInfo0,
+		StackOptInfo = StackOptInfo0
 	;
 		set__to_sorted_list(PotentialIntervals, PotentialIntervalList),
 		set__to_sorted_list(PotentialAnchors, PotentialAnchorList),
-		list__foldl2(
+		list__foldl3(
 			record_cell_var_for_interval(CellVar, ViaCellVars),
-			PotentialIntervalList, OptInfo0, OptInfo1,
+			PotentialIntervalList, IntervalInfo0, IntervalInfo1,
+			StackOptInfo0, StackOptInfo1,
 			set__init, InsertIntervals),
-		list__foldl2(
+		list__foldl3(
 			add_anchor_inserts(Goal, ViaCellVars, InsertIntervals),
-			PotentialAnchorList, OptInfo1, OptInfo2,
+			PotentialAnchorList, IntervalInfo1, IntervalInfo2,
+			StackOptInfo1, StackOptInfo2,
 			set__init, InsertAnchors),
 		Goal = _ - GoalInfo,
 		goal_info_get_goal_path(GoalInfo, GoalPath),
@@ -1260,20 +578,24 @@
 			ArgVars, ViaCellVars, GoalPath,
 			PotentialIntervals, InsertIntervals,
 			PotentialAnchors, InsertAnchors),
-		MatchingResults0 = OptInfo2 ^ matching_results,
+		MatchingResults0 = StackOptInfo2 ^ matching_results,
 		MatchingResults = [MatchingResult | MatchingResults0],
-		OptInfo = OptInfo2 ^ matching_results := MatchingResults
+		IntervalInfo = IntervalInfo2,
+		StackOptInfo = StackOptInfo2
+			^ matching_results := MatchingResults
 	).

 :- pred record_cell_var_for_interval(prog_var::in, set(prog_var)::in,
-	interval_id::in, opt_info::in, opt_info::out,
+	interval_id::in, interval_info::in, interval_info::out,
+	stack_opt_info::in, stack_opt_info::out,
 	set(interval_id)::in, set(interval_id)::out) is det.

 record_cell_var_for_interval(CellVar, ViaCellVars, IntervalId,
-		OptInfo0, OptInfo, InsertIntervals0, InsertIntervals) :-
-	record_interval_vars(IntervalId, [CellVar], OptInfo0, OptInfo1),
+		!IntervalInfo, !StackOptInfo,
+		InsertIntervals0, InsertIntervals) :-
+	record_interval_vars(IntervalId, [CellVar], !IntervalInfo),
 	delete_interval_vars(IntervalId, ViaCellVars, DeletedVars,
-		OptInfo1, OptInfo),
+		!IntervalInfo),
 	( set__non_empty(DeletedVars) ->
 		svset__insert(IntervalId, InsertIntervals0, InsertIntervals)
 	;
@@ -1281,18 +603,19 @@
 	).

 :- pred add_anchor_inserts(hlds_goal::in, set(prog_var)::in,
-	set(interval_id)::in, anchor::in, opt_info::in, opt_info::out,
+	set(interval_id)::in, anchor::in, interval_info::in,
+	interval_info::out, stack_opt_info::in, stack_opt_info::out,
 	set(anchor)::in, set(anchor)::out) is det.

 add_anchor_inserts(Goal, ArgVarsViaCellVar, InsertIntervals, Anchor,
-		OptInfo0, OptInfo, InsertAnchors0, InsertAnchors) :-
-	map__lookup(OptInfo0 ^ anchor_follow_map, Anchor, AnchorFollow),
+		!IntervalInfo, !StackOptInfo, !InsertAnchors) :-
+	map__lookup(!.IntervalInfo ^ anchor_follow_map, Anchor, AnchorFollow),
 	AnchorFollow = _ - AnchorIntervals,
 	set__intersect(AnchorIntervals, InsertIntervals,
 		AnchorInsertIntervals),
 	( set__non_empty(AnchorInsertIntervals) ->
 		Insert = insert_spec(Goal, ArgVarsViaCellVar),
-		InsertMap0 = OptInfo0 ^ left_anchor_inserts,
+		InsertMap0 = !.StackOptInfo ^ left_anchor_inserts,
 		( map__search(InsertMap0, Anchor, Inserts0) ->
 			Inserts = [Insert | Inserts0],
 			svmap__det_update(Anchor, Inserts,
@@ -1302,11 +625,11 @@
 			svmap__det_insert(Anchor, Inserts,
 				InsertMap0, InsertMap)
 		),
-		OptInfo = OptInfo0 ^ left_anchor_inserts := InsertMap,
-		svset__insert(Anchor, InsertAnchors0, InsertAnchors)
+		!:StackOptInfo = !.StackOptInfo
+			^ left_anchor_inserts := InsertMap,
+		svset__insert(Anchor, !InsertAnchors)
 	;
-		OptInfo = OptInfo0,
-		InsertAnchors = InsertAnchors0
+		true
 	).

 %-----------------------------------------------------------------------------%
@@ -1393,13 +716,14 @@
 	svset__insert(Anchor, Anchors0, Anchors),
 	!:Path = !.Path ^ flush_anchors := Anchors.

-:- func anchor_requires_close(opt_info, anchor) = bool.
+:- func anchor_requires_close(interval_info, anchor) = bool.

 anchor_requires_close(_, proc_start) = no.
 anchor_requires_close(_, proc_end) = yes.
-anchor_requires_close(OptInfo, branch_start(_, GoalPath)) =
+anchor_requires_close(IntervalInfo, branch_start(_, GoalPath)) =
 		resume_save_status_requires_close(ResumeSaveStatus) :-
-	map__lookup(OptInfo ^ branch_resume_map, GoalPath, ResumeSaveStatus).
+	map__lookup(IntervalInfo ^ branch_resume_map, GoalPath,
+		ResumeSaveStatus).
 anchor_requires_close(_, cond_then(_)) = no.
 anchor_requires_close(_, branch_end(BranchConstruct, _)) =
 	( BranchConstruct = neg ->
@@ -1461,30 +785,21 @@
 may_have_more_successors(branch_end(_, _), no).
 may_have_more_successors(call_site(_), no).

-:- pred lookup_inserts(insert_map::in, anchor::in, list(insert_spec)::out)
-	is det.
-
-lookup_inserts(InsertMap, Anchor, Inserts) :-
-	( map__search(InsertMap, Anchor, InsertsPrime) ->
-		Inserts = InsertsPrime
-	;
-		Inserts = []
-	).
-
 %-----------------------------------------------------------------------------%

 :- pred find_all_branches_from_cur_interval(set(prog_var)::in,
-	match_info::out, opt_info::in) is det.
+	match_info::out, interval_info::in, stack_opt_info::in) is det.

-find_all_branches_from_cur_interval(RelevantVars, MatchInfo, OptInfo) :-
-	IntervalId = OptInfo ^ cur_interval,
-	map__lookup(OptInfo ^ interval_vars, IntervalId, IntervalVars),
+find_all_branches_from_cur_interval(RelevantVars, MatchInfo, IntervalInfo,
+		StackOptInfo) :-
+	IntervalId = IntervalInfo ^ cur_interval,
+	map__lookup(IntervalInfo ^ interval_vars, IntervalId, IntervalVars),
 	IntervalRelevantVars = set__intersect(RelevantVars, IntervalVars),
 	Path0 = path(current_is_before_first_flush, IntervalRelevantVars,
 		set__init, [], set__init, set__init),
 	AllPaths0 = all_paths(set__make_singleton_set(Path0), no, set__init),
-	find_all_branches(RelevantVars, IntervalId, no, OptInfo,
-		AllPaths0, AllPaths),
+	find_all_branches(RelevantVars, IntervalId, no, IntervalInfo,
+		StackOptInfo, AllPaths0, AllPaths),
 	AllPaths = all_paths(Paths, AfterModelNon, RelevantAfter),
 	set__to_sorted_list(Paths, PathList),
 	list__map3(extract_match_and_save_info, PathList,
@@ -1495,12 +810,13 @@
 		FlushAnchors, OccurringIntervals).

 :- pred find_all_branches(set(prog_var)::in, interval_id::in,
-	maybe(anchor)::in, opt_info::in, all_paths::in, all_paths::out) is det.
+	maybe(anchor)::in, interval_info::in, stack_opt_info::in,
+	all_paths::in, all_paths::out) is det.

 find_all_branches(RelevantVars, IntervalId, MaybeSearchAnchor0,
-		OptInfo, AllPaths0, AllPaths) :-
-	map__lookup(OptInfo ^ interval_end, IntervalId, End),
-	map__lookup(OptInfo ^ interval_succ, IntervalId, SuccessorIds),
+		IntervalInfo, StackOptInfo, AllPaths0, AllPaths) :-
+	map__lookup(IntervalInfo ^ interval_end, IntervalId, End),
+	map__lookup(IntervalInfo ^ interval_succ, IntervalId, SuccessorIds),
 	(
 		SuccessorIds = [],
 		require(may_have_no_successor(End),
@@ -1528,7 +844,7 @@
 			AllPaths = all_paths(Paths0, AfterModelNon, set__init)
 		;
 			End = branch_end(_, EndGoalPath),
-			map__lookup(OptInfo ^ branch_end_map, EndGoalPath,
+			map__lookup(IntervalInfo ^ branch_end_map, EndGoalPath,
 				BranchEndInfo),
 			OnStackAfterBranch =
 				BranchEndInfo ^ flushed_after_branch,
@@ -1545,39 +861,40 @@
 				RelevantAfter)
 		;
 			find_all_branches_from(End, RelevantVars,
-				MaybeSearchAnchor0, OptInfo,
+				MaybeSearchAnchor0, IntervalInfo, StackOptInfo,
 				[SuccessorId | MoreSuccessorIds],
 				AllPaths0, AllPaths)
 		)
 	).

 :- pred find_all_branches_from(anchor::in, set(prog_var)::in,
-	maybe(anchor)::in, opt_info::in, list(interval_id)::in,
-	all_paths::in, all_paths::out) is det.
+	maybe(anchor)::in, interval_info::in, stack_opt_info::in,
+	list(interval_id)::in, all_paths::in, all_paths::out) is det.

-find_all_branches_from(End, RelevantVars, MaybeSearchAnchor0, OptInfo,
-		SuccessorIds, !AllPaths) :-
-	( anchor_requires_close(OptInfo, End) = yes ->
+find_all_branches_from(End, RelevantVars, MaybeSearchAnchor0, IntervalInfo,
+		StackOptInfo, SuccessorIds, !AllPaths) :-
+	( anchor_requires_close(IntervalInfo, End) = yes ->
 		Paths0 = !.AllPaths ^ paths_so_far,
 		Paths1 = set__map(close_path, Paths0),
 		!:AllPaths = !.AllPaths ^ paths_so_far := Paths1
 	;
 		true
 	),
-	OptParams = OptInfo ^ opt_params,
-	FullPath = OptParams ^ full_path,
+	StackOptParams = StackOptInfo ^ stack_opt_params,
+	FullPath = StackOptParams ^ full_path,
 	(
 		FullPath = yes,
 		End = branch_start(disj, EndGoalPath)
 	->
 		MaybeSearchAnchor1 = yes(branch_end(disj, EndGoalPath)),
 		one_after_another(RelevantVars, MaybeSearchAnchor1,
-			OptInfo, SuccessorIds, !AllPaths),
-		map__lookup(OptInfo ^ branch_end_map, EndGoalPath,
+			IntervalInfo, StackOptInfo, SuccessorIds, !AllPaths),
+		map__lookup(IntervalInfo ^ branch_end_map, EndGoalPath,
 			BranchEndInfo),
 		ContinueId = BranchEndInfo ^ interval_after_branch,
 		apply_interval_find_all_branches(RelevantVars,
-			MaybeSearchAnchor0, OptInfo, ContinueId, !AllPaths)
+			MaybeSearchAnchor0, IntervalInfo, StackOptInfo,
+			ContinueId, !AllPaths)
 	;
 		FullPath = yes,
 		End = branch_start(ite, EndGoalPath)
@@ -1590,84 +907,91 @@
 		),
 		MaybeSearchAnchorCond = yes(cond_then(EndGoalPath)),
 		apply_interval_find_all_branches(RelevantVars,
-			MaybeSearchAnchorCond, OptInfo,
+			MaybeSearchAnchorCond, IntervalInfo, StackOptInfo,
 			CondStartId, !AllPaths),
 		MaybeSearchAnchorEnd = yes(branch_end(ite, EndGoalPath)),
-		CondEndMap = OptInfo ^ cond_end_map,
+		CondEndMap = IntervalInfo ^ cond_end_map,
 		map__lookup(CondEndMap, EndGoalPath, ThenStartId),
-		one_after_another(RelevantVars, MaybeSearchAnchorEnd, OptInfo,
-			[ThenStartId, ElseStartId], !AllPaths),
-		map__lookup(OptInfo ^ branch_end_map, EndGoalPath,
+		one_after_another(RelevantVars, MaybeSearchAnchorEnd,
+			IntervalInfo, StackOptInfo, [ThenStartId, ElseStartId],
+			!AllPaths),
+		map__lookup(IntervalInfo ^ branch_end_map, EndGoalPath,
 			BranchEndInfo),
 		ContinueId = BranchEndInfo ^ interval_after_branch,
 		apply_interval_find_all_branches(RelevantVars,
-			MaybeSearchAnchor0, OptInfo, ContinueId, !AllPaths)
+			MaybeSearchAnchor0, IntervalInfo, StackOptInfo,
+			ContinueId, !AllPaths)
 	;
 		End = branch_start(BranchType, EndGoalPath)
 	->
 		MaybeSearchAnchor1 = yes(branch_end(BranchType, EndGoalPath)),
 		list__map(apply_interval_find_all_branches_map(RelevantVars,
-			MaybeSearchAnchor1, OptInfo, !.AllPaths),
+			MaybeSearchAnchor1, IntervalInfo, StackOptInfo,
+			!.AllPaths),
 			SuccessorIds, AllPathsList),
 		consolidate_after_join(AllPathsList, !:AllPaths),
-		map__lookup(OptInfo ^ branch_end_map, EndGoalPath,
+		map__lookup(IntervalInfo ^ branch_end_map, EndGoalPath,
 			BranchEndInfo),
 		ContinueId = BranchEndInfo ^ interval_after_branch,
 		apply_interval_find_all_branches(RelevantVars,
-			MaybeSearchAnchor0, OptInfo, ContinueId, !AllPaths)
+			MaybeSearchAnchor0, IntervalInfo, StackOptInfo,
+			ContinueId, !AllPaths)
 	;
 		( SuccessorIds = [SuccessorId] ->
 			apply_interval_find_all_branches(RelevantVars,
-				MaybeSearchAnchor0, OptInfo,
-				SuccessorId, !AllPaths)
+				MaybeSearchAnchor0, IntervalInfo,
+				StackOptInfo, SuccessorId, !AllPaths)
 		;
 			error("more successor ids")
 		)
 	).

-:- pred one_after_another(set(prog_var)::in, maybe(anchor)::in, opt_info::in,
-	list(interval_id)::in, all_paths::in, all_paths::out) is det.
+:- pred one_after_another(set(prog_var)::in, maybe(anchor)::in,
+	interval_info::in, stack_opt_info::in, list(interval_id)::in,
+	all_paths::in, all_paths::out) is det.

-one_after_another(_, _, _, [], !AllPaths).
-one_after_another(RelevantVars, MaybeSearchAnchor1, OptInfo,
+one_after_another(_, _, _, _, [], !AllPaths).
+one_after_another(RelevantVars, MaybeSearchAnchor1, IntervalInfo, StackOptInfo,
 		[SuccessorId | MoreSuccessorIds], !AllPaths) :-
 	apply_interval_find_all_branches(RelevantVars, MaybeSearchAnchor1,
-		OptInfo, SuccessorId, !AllPaths),
-	one_after_another(RelevantVars, MaybeSearchAnchor1, OptInfo,
-		MoreSuccessorIds, !AllPaths).
+		IntervalInfo, StackOptInfo, SuccessorId, !AllPaths),
+	one_after_another(RelevantVars, MaybeSearchAnchor1, IntervalInfo,
+		StackOptInfo, MoreSuccessorIds, !AllPaths).

 	% We need a version of apply_interval_find_all_branches with this
 	% argument order for use in higher order caode.

 :- pred apply_interval_find_all_branches_map(set(prog_var)::in,
-	maybe(anchor)::in, opt_info::in, all_paths::in,
-	interval_id::in, all_paths::out) is det.
+	maybe(anchor)::in, interval_info::in, stack_opt_info::in,
+	all_paths::in, interval_id::in, all_paths::out) is det.

 apply_interval_find_all_branches_map(RelevantVars, MaybeSearchAnchor0,
-		OptInfo, !.AllPaths, IntervalId, !:AllPaths) :-
+		IntervalInfo, StackOptInfo, !.AllPaths, IntervalId,
+		!:AllPaths) :-
 	apply_interval_find_all_branches(RelevantVars, MaybeSearchAnchor0,
-		OptInfo, IntervalId, !AllPaths).
+		IntervalInfo, StackOptInfo, IntervalId, !AllPaths).

 :- pred apply_interval_find_all_branches(set(prog_var)::in,
-	maybe(anchor)::in, opt_info::in, interval_id::in,
-	all_paths::in, all_paths::out) is det.
+	maybe(anchor)::in, interval_info::in, stack_opt_info::in,
+	interval_id::in, all_paths::in, all_paths::out) is det.

 apply_interval_find_all_branches(RelevantVars, MaybeSearchAnchor0,
-		OptInfo, IntervalId, !AllPaths) :-
-	map__lookup(OptInfo ^ interval_vars, IntervalId, IntervalVars),
+		IntervalInfo, StackOptInfo, IntervalId, !AllPaths) :-
+	map__lookup(IntervalInfo ^ interval_vars, IntervalId, IntervalVars),
 	RelevantIntervalVars = set__intersect(RelevantVars, IntervalVars),
 	!.AllPaths = all_paths(Paths0, AfterModelNon0, RelevantAfter),
 	Paths1 = set__map(
 		add_interval_to_path(IntervalId, RelevantIntervalVars),
 		Paths0),
-	map__lookup(OptInfo ^ interval_start, IntervalId, Start),
+	map__lookup(IntervalInfo ^ interval_start, IntervalId, Start),
 	(
 		% Check if intervals starting at Start use any RelevantVars.
 		( Start = call_site(_)
 		; Start = branch_end(_, _)
 		; Start = branch_start(_, _)
 		),
-		map__search(OptInfo ^ anchor_follow_map, Start, StartInfo),
+		map__search(IntervalInfo ^ anchor_follow_map, Start,
+			StartInfo),
 		StartInfo = AnchorFollowVars - _,
 		set__intersect(RelevantVars, AnchorFollowVars, NeededVars),
 		set__non_empty(NeededVars)
@@ -1676,14 +1000,14 @@
 	;
 		Paths2 = Paths1
 	),
-	( set__member(Start, OptInfo ^ model_non_anchors) ->
+	( set__member(Start, IntervalInfo ^ model_non_anchors) ->
 		AfterModelNon = yes
 	;
 		AfterModelNon = AfterModelNon0
 	),
 	!:AllPaths = all_paths(Paths2, AfterModelNon, RelevantAfter),
 	find_all_branches(RelevantVars, IntervalId,
-		MaybeSearchAnchor0, OptInfo, !AllPaths).
+		MaybeSearchAnchor0, IntervalInfo, StackOptInfo, !AllPaths).

 :- pred consolidate_after_join(list(all_paths)::in, all_paths::out) is det.

@@ -1714,345 +1038,6 @@
 	% XXX should try to preserve the current segment.

 %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- type var_info
-	--->	var_info(
-			varset		:: prog_varset,
-			vartypes	:: vartypes
-		).
-
-:- type rename_map	==	map(prog_var, prog_var).
-
-:- pred record_decisions_in_goal(hlds_goal::in, hlds_goal::out,
-	var_info::in, var_info::out, rename_map::in, rename_map::out,
-	insert_map::in) is det.
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = conj(Goals0) - GoalInfo,
-	record_decisions_in_conj(Goals0, Goals, !VarInfo, !VarRename,
-		InsertMap),
-	Goal = conj(Goals) - GoalInfo.
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, VarRename0, map__init,
-		InsertMap) :-
-	Goal0 = par_conj(Goals0) - GoalInfo,
-	record_decisions_in_par_conj(Goals0, Goals, !VarInfo, VarRename0,
-		InsertMap),
-	Goal = par_conj(Goals) - GoalInfo.
-
-record_decisions_in_goal(Goal0,  Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = disj(Goals0) - GoalInfo0,
-	construct_anchors(disj, Goal0, StartAnchor, EndAnchor),
-	( Goals0 = [FirstGoal0 | LaterGoals0] ->
-		record_decisions_in_goal(FirstGoal0, FirstGoal, !VarInfo,
-			!.VarRename, _, InsertMap),
-		lookup_inserts(InsertMap, StartAnchor, StartInserts),
-		record_decisions_in_disj(LaterGoals0, LaterGoals,
-			!VarInfo, !.VarRename, StartInserts, InsertMap),
-		Goals = [FirstGoal | LaterGoals],
-		Goal1 = disj(Goals) - GoalInfo0,
-		lookup_inserts(InsertMap, EndAnchor, Inserts),
-		insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, Inserts)
-	;
-		Goal = disj(Goals0) - GoalInfo0
-	).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = switch(Var0, Det, Cases0) - GoalInfo0,
-	record_decisions_in_cases(Cases0, Cases, !VarInfo, !.VarRename,
-		InsertMap),
-	rename_var(Var0, no, !.VarRename, Var),
-	Goal1 = switch(Var, Det, Cases) - GoalInfo0,
-	construct_anchors(switch, Goal0, _StartAnchor, EndAnchor),
-	lookup_inserts(InsertMap, EndAnchor, Inserts),
-	insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, Inserts).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = not(NegGoal0) - GoalInfo0,
-	record_decisions_in_goal(NegGoal0, NegGoal, !VarInfo, !.VarRename, _,
-		InsertMap),
-	Goal1 = not(NegGoal) - GoalInfo0,
-	construct_anchors(neg, Goal0, _StartAnchor, EndAnchor),
-	lookup_inserts(InsertMap, EndAnchor, Inserts),
-	% XXX
-	insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, Inserts).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = if_then_else(Vars0, Cond0, Then0, Else0) - GoalInfo0,
-	construct_anchors(ite, Goal0, StartAnchor, EndAnchor),
-	rename_var_list(Vars0, no, !.VarRename, Vars),
-	record_decisions_in_goal(Cond0, Cond, !VarInfo, !VarRename, InsertMap),
-	record_decisions_in_goal(Then0, Then, !VarInfo, !.VarRename, _,
-		InsertMap),
-	lookup_inserts(InsertMap, StartAnchor, StartInserts),
-	make_inserted_goals(!VarInfo, map__init, VarRenameElse,
-		StartInserts, StartInsertGoals),
-	record_decisions_in_goal(Else0, Else1, !VarInfo, VarRenameElse, _,
-		InsertMap),
-	Else0 = _ - ElseGoalInfo0,
-	conj_list_to_goal(list__append(StartInsertGoals, [Else1]),
-		ElseGoalInfo0, Else),
-	Goal1 = if_then_else(Vars, Cond, Then, Else) - GoalInfo0,
-	lookup_inserts(InsertMap, EndAnchor, EndInserts),
-	insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, EndInserts).
-
-record_decisions_in_goal(some(Vars0, CanRemove, Goal0) - GoalInfo,
-		some(Vars, CanRemove, Goal) - GoalInfo, !VarInfo, !VarRename,
-		InsertMap) :-
-	rename_var_list(Vars0, no, !.VarRename, Vars),
-	record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = generic_call(GenericCall, _ , _, _) - _,
-	% unsafe_casts are generated inline.
-	( GenericCall = unsafe_cast ->
-		MustHaveMap = no
-	;
-		MustHaveMap = yes
-	),
-	record_decisions_at_call_site(Goal0, Goal, !VarInfo, !VarRename,
-		MustHaveMap, InsertMap).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = call(_, _, _, Builtin, _, _) - _,
-	( Builtin = inline_builtin ->
-		MustHaveMap = no
-	;
-		MustHaveMap = yes
-	),
-	record_decisions_at_call_site(Goal0, Goal, !VarInfo, !VarRename,
-		MustHaveMap, InsertMap).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, InsertMap) :-
-	Goal0 = foreign_proc(_, _, _, _, _, _) - _,
-	record_decisions_at_call_site(Goal0, Goal, !VarInfo,
-		!VarRename, no, InsertMap).
-
-record_decisions_in_goal(Goal0, Goal, !VarInfo, !VarRename, _InsertMap) :-
-	Goal0 = unify(_, _, _, _, _) - _,
-	rename_vars_in_goal(Goal0, !.VarRename, Goal).
-
-record_decisions_in_goal(shorthand(_) - _, _, !VarInfo, !VarRename, _) :-
-	error("shorthand in record_decisions_in_goal").
-
-%-----------------------------------------------------------------------------%
-
-:- pred insert_goals_after(hlds_goal::in, hlds_goal::out,
-	var_info::in, var_info::out, rename_map::out,
-	list(insert_spec)::in) is det.
-
-insert_goals_after(BranchesGoal, Goal, !VarInfo, VarRename, Inserts) :-
-	make_inserted_goals(!VarInfo, map__init, VarRename,
-		Inserts, InsertGoals),
-	BranchesGoal = _ - BranchesGoalInfo,
-	conj_list_to_goal([BranchesGoal | InsertGoals], BranchesGoalInfo,
-		Goal).
-
-:- pred make_inserted_goals(var_info::in, var_info::out,
-	rename_map::in, rename_map::out, list(insert_spec)::in,
-	list(hlds_goal)::out) is det.
-
-make_inserted_goals(!VarInfo, !VarRename, [], []).
-make_inserted_goals(!VarInfo, !VarRename, [Spec | Specs], [Goal | Goals]) :-
-	make_inserted_goal(!VarInfo, !VarRename, Spec, Goal),
-	make_inserted_goals(!VarInfo, !VarRename, Specs, Goals).
-
-:- pred make_inserted_goal(var_info::in, var_info::out,
-	rename_map::in, rename_map::out, insert_spec::in,
-	hlds_goal::out) is det.
-
-make_inserted_goal(!VarInfo, !VarRename, Spec, Goal) :-
-	Spec = insert_spec(Goal0, VarsToExtract),
-	Goal0 = GoalExpr0 - GoalInfo0,
-	(
-		GoalExpr0 = unify(_, _, _, Unification0, _),
-		Unification0 = deconstruct(_, _, ArgVars, _, _, _)
-	->
-		Unification1 = Unification0 ^ deconstruct_can_fail
-			:= cannot_fail,
-		GoalExpr1 = GoalExpr0 ^ unify_kind := Unification1,
-		goal_info_set_determinism(GoalInfo0, det, GoalInfo1),
-		goal_info_add_feature(GoalInfo1, stack_opt, GoalInfo2),
-		Goal2 = GoalExpr1 - GoalInfo2,
-		!.VarInfo = var_info(VarSet0, VarTypes0),
-		create_shadow_vars(ArgVars, VarsToExtract, VarSet0, VarSet,
-			VarTypes0, VarTypes, map__init, NewRename,
-			map__init, VoidRename),
-		!:VarInfo = var_info(VarSet, VarTypes),
-		map__merge(!.VarRename, NewRename, !:VarRename),
-		% We rename the original goal
-		rename_vars_in_goal(Goal2, !.VarRename, Goal3),
-		rename_vars_in_goal(Goal3, VoidRename, Goal)
-	;
-		error("make_inserted_goal: not a deconstruct")
-	).
-
-:- pred create_shadow_vars(list(prog_var)::in, set(prog_var)::in,
-	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
-	rename_map::in, rename_map::out, rename_map::in, rename_map::out)
-	is det.
-
-create_shadow_vars([], _, !VarSet, !VarTypes, !VarRename, !VoidRename).
-create_shadow_vars([Arg | Args], VarsToExtract, !VarSet, !VarTypes,
-		!VarRename, !VoidRename) :-
-	create_shadow_var(Arg, VarsToExtract, !VarSet, !VarTypes,
-		!VarRename, !VoidRename),
-	create_shadow_vars(Args, VarsToExtract, !VarSet, !VarTypes,
-		!VarRename, !VoidRename).
-
-:- pred create_shadow_var(prog_var::in, set(prog_var)::in,
-	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
-	rename_map::in, rename_map::out, rename_map::in, rename_map::out)
-	is det.
-
-create_shadow_var(Arg, VarsToExtract, !VarSet, !VarTypes,
-		!VarRename, !VoidRename) :-
-	varset__lookup_name(!.VarSet, Arg, Name),
-	svvarset__new_named_var(Name, Shadow, !VarSet),
-	map__lookup(!.VarTypes, Arg, Type),
-	svmap__det_insert(Shadow, Type, !VarTypes),
-	( set__member(Arg, VarsToExtract) ->
-		svmap__det_insert(Arg, Shadow, !VarRename)
-	;
-		svmap__det_insert(Arg, Shadow, !VoidRename)
-	).
-
-%-----------------------------------------------------------------------------%
-
-:- pred record_decisions_at_call_site(hlds_goal::in, hlds_goal::out,
-	var_info::in, var_info::out, rename_map::in, rename_map::out,
-	bool::in, insert_map::in) is det.
-
-record_decisions_at_call_site(Goal0, Goal, !VarInfo, !VarRename,
-		MustHaveMap, InsertMap) :-
-	Goal0 = _ - GoalInfo0,
-	rename_vars_in_goal(Goal0, !.VarRename, Goal1),
-	(
-		goal_info_maybe_get_maybe_need_across_call(GoalInfo0,
-			MaybeNeedAcrossCall),
-		MaybeNeedAcrossCall = yes(_NeedAcrossCall)
-	->
-		goal_info_get_goal_path(GoalInfo0, GoalPath),
-		Anchor = call_site(GoalPath),
-		lookup_inserts(InsertMap, Anchor, Inserts),
-		insert_goals_after(Goal1, Goal, !VarInfo, !:VarRename, Inserts)
-	;
-		(
-			MustHaveMap = no,
-			Goal = Goal1
-		;
-			MustHaveMap = yes,
-			error("record_decisions_at_call_site: no save map")
-		)
-	).
-
-%-----------------------------------------------------------------------------%
-
-:- pred record_decisions_in_conj(list(hlds_goal)::in, list(hlds_goal)::out,
-	var_info::in, var_info::out, rename_map::in, rename_map::out,
-	insert_map::in) is det.
-
-record_decisions_in_conj([], [], !VarInfo, !VarRename, _).
-record_decisions_in_conj([Goal0 | Goals0], Goals, !VarInfo, !VarRename,
-		InsertMap) :-
-	record_decisions_in_goal(Goal0, Goal1, !VarInfo, !VarRename,
-		InsertMap),
-	record_decisions_in_conj(Goals0, Goals1, !VarInfo, !VarRename,
-		InsertMap),
-	( Goal1 = conj(SubGoals) - _ ->
-		Goals = list__append(SubGoals, Goals1)
-	;
-		Goals = [Goal1 | Goals1]
-	).
-
-:- pred record_decisions_in_par_conj(list(hlds_goal)::in, list(hlds_goal)::out,
-	var_info::in, var_info::out, rename_map::in, insert_map::in) is det.
-
-record_decisions_in_par_conj([], [], !VarInfo, _, _).
-record_decisions_in_par_conj([Goal0 | Goals0], [Goal | Goals], !VarInfo,
-		VarRename0, InsertMap) :-
-	record_decisions_in_goal(Goal0, Goal, !VarInfo, VarRename0, _,
-		InsertMap),
-	record_decisions_in_par_conj(Goals0, Goals, !VarInfo, VarRename0,
-		InsertMap).
-
-:- pred record_decisions_in_disj(list(hlds_goal)::in, list(hlds_goal)::out,
-	var_info::in, var_info::out, rename_map::in, list(insert_spec)::in,
-	insert_map::in) is det.
-
-record_decisions_in_disj([], [], !VarInfo, _, _, _).
-record_decisions_in_disj([Goal0 | Goals0], [Goal | Goals], !VarInfo,
-		VarRename0, Inserts, InsertMap) :-
-	make_inserted_goals(!VarInfo, map__init, VarRename1,
-		Inserts, InsertGoals),
-	Goal0 = _ - GoalInfo0,
-	record_decisions_in_goal(Goal0, Goal1, !VarInfo, VarRename1, _,
-		InsertMap),
-	conj_list_to_goal(list__append(InsertGoals, [Goal1]), GoalInfo0, Goal),
-	record_decisions_in_disj(Goals0, Goals, !VarInfo, VarRename0,
-		Inserts, InsertMap).
-
-:- pred record_decisions_in_cases(list(case)::in, list(case)::out,
-	var_info::in, var_info::out, rename_map::in, insert_map::in) is det.
-
-record_decisions_in_cases([], [], !VarInfo, _, _).
-record_decisions_in_cases([case(Var, Goal0) | Cases0],
-		[case(Var, Goal) | Cases], !VarInfo, VarRename0, InsertMap) :-
-	record_decisions_in_goal(Goal0, Goal, !VarInfo, VarRename0, _,
-		InsertMap),
-	record_decisions_in_cases(Cases0, Cases, !VarInfo, VarRename0,
-		InsertMap).
-
-%-----------------------------------------------------------------------------%
-
-% The final RenameMap may ask for some of the head variables to be renamed.
-% Doing so is inconvenient, e.g. because the debugger wants head variables to
-% have names of a fixed form. Instead, we exploit the fact that the
-% transformation does not care about actual variable names or even numbers;
-% all it cares about wrt renaming is that the variables it has renamed apart
-% should stay renamed apart. We therefore swap the roles of the original and
-% the renamed variable in the goal representing the procedure body. The
-% resulting procedure definition will be isomorphic to the one we would have
-% get by applying the original renaming to the headvars.
-
-:- pred apply_headvar_correction(set(prog_var)::in, rename_map::in,
-	hlds_goal::in, hlds_goal::out) is det.
-
-apply_headvar_correction(HeadVarSet, RenameMap, Goal0, Goal) :-
-	set__to_sorted_list(HeadVarSet, HeadVars),
-	build_headvar_subst(HeadVars, RenameMap, map__init, Subst),
-	( map__is_empty(Subst) ->
-		Goal = Goal0
-	;
-		goal_util__rename_vars_in_goal(Goal0, Subst, Goal)
-	).
-
-:- pred build_headvar_subst(list(prog_var)::in, rename_map::in,
-	map(prog_var, prog_var)::in, map(prog_var, prog_var)::out) is det.
-
-build_headvar_subst([], _RenameMap, !Subst).
-build_headvar_subst([HeadVar | HeadVars], RenameMap, !Subst) :-
-	( map__search(RenameMap, HeadVar, Replacement) ->
-		svmap__det_insert(Replacement, HeadVar, !Subst),
-		svmap__det_insert(HeadVar, Replacement, !Subst)
-	;
-		true
-	),
-	build_headvar_subst(HeadVars, RenameMap, !Subst).
-
-%-----------------------------------------------------------------------------%
-
-:- pred construct_anchors(branch_construct::in, hlds_goal::in,
-	anchor::out, anchor::out) is det.
-
-construct_anchors(Construct, Goal, StartAnchor, EndAnchor) :-
-	Goal = _ - GoalInfo,
-	goal_info_get_goal_path(GoalInfo, GoalPath),
-	StartAnchor = branch_start(Construct, GoalPath),
-	EndAnchor = branch_end(Construct, GoalPath).
-
-%-----------------------------------------------------------------------------%

 % This predicate can help debug the correctness of the transformation.

@@ -2075,100 +1060,20 @@

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

-% These predicates can help debug the performance of the transformation.
-
-:- pred dump_opt_info(opt_info::in, io::di, io::uo) is det.
+% This predicate (along with dump_interval_info) can help debug the
+% performance of the transformation.

-dump_opt_info(OptInfo, !IO) :-
-	map__keys(OptInfo ^ interval_start, StartIds),
-	map__keys(OptInfo ^ interval_end, EndIds),
-	map__keys(OptInfo ^ interval_vars, VarsIds),
-	map__keys(OptInfo ^ interval_succ, SuccIds),
-	list__condense([StartIds, EndIds, VarsIds, SuccIds], IntervalIds0),
-	list__sort_and_remove_dups(IntervalIds0, IntervalIds),
-	io__write_string("INTERVALS:\n", !IO),
-	list__foldl(dump_interval_info(OptInfo), IntervalIds, !IO),
-
-	map__to_assoc_list(OptInfo ^ anchor_follow_map, AnchorFollows),
-	io__write_string("\nANCHOR FOLLOW:\n", !IO),
-	list__foldl(dump_anchor_follow, AnchorFollows, !IO),
+:- pred dump_stack_opt_info(stack_opt_info::in, io::di, io::uo)
+	is det.

-	map__to_assoc_list(OptInfo ^ left_anchor_inserts, Inserts),
+dump_stack_opt_info(StackOptInfo, !IO) :-
+	map__to_assoc_list(StackOptInfo ^ left_anchor_inserts, Inserts),
 	io__write_string("\nANCHOR INSERT:\n", !IO),
 	list__foldl(dump_anchor_inserts, Inserts, !IO),

 	io__write_string("\nMATCHING RESULTS:\n", !IO),
-	list__foldl(dump_matching_result, OptInfo ^ matching_results, !IO),
-	io__write_string("\n", !IO).
-
-:- pred dump_interval_info(opt_info::in, interval_id::in, io::di, io::uo)
-	is det.
-
-dump_interval_info(OptInfo, IntervalId, !IO) :-
-	io__write_string("\ninterval ", !IO),
-	io__write_int(interval_id_to_int(IntervalId), !IO),
-	io__write_string(": ", !IO),
-	( map__search(OptInfo ^ interval_succ, IntervalId, SuccIds) ->
-		SuccNums = list__map(interval_id_to_int, SuccIds),
-		io__write_string("succ [", !IO),
-		write_int_list(SuccNums, !IO),
-		io__write_string("]\n", !IO)
-	;
-		io__write_string("no succ\n", !IO)
-	),
-	( map__search(OptInfo ^ interval_start, IntervalId, Start) ->
-		io__write_string("start ", !IO),
-		io__write(Start, !IO),
-		io__write_string("\n", !IO)
-	;
-		io__write_string("no start\n", !IO)
-	),
-	( map__search(OptInfo ^ interval_end, IntervalId, End) ->
-		io__write_string("end ", !IO),
-		io__write(End, !IO),
-		io__write_string("\n", !IO)
-	;
-		io__write_string("no end\n", !IO)
-	),
-	( map__search(OptInfo ^ interval_vars, IntervalId, Vars) ->
-		list__map(term__var_to_int, set__to_sorted_list(Vars),
-			VarNums),
-		io__write_string("vars [", !IO),
-		write_int_list(VarNums, !IO),
-		io__write_string("]\n", !IO)
-	;
-		io__write_string("no vars\n", !IO)
-	),
-	( map__search(OptInfo ^ interval_delvars, IntervalId, Deletions) ->
-		io__write_string("deletions", !IO),
-		list__foldl(dump_deletion, Deletions, !IO),
-		io__write_string("\n", !IO)
-	;
-		true
-	).
-
-:- pred dump_deletion(set(prog_var)::in, io::di, io::uo) is det.
-
-dump_deletion(Vars, !IO) :-
-	list__map(term__var_to_int, set__to_sorted_list(Vars), VarNums),
-	io__write_string(" [", !IO),
-	write_int_list(VarNums, !IO),
-	io__write_string("]", !IO).
-
-:- pred dump_anchor_follow(pair(anchor, anchor_follow_info)::in,
-	io::di, io::uo) is det.
-
-dump_anchor_follow(Anchor - AnchorFollowInfo, !IO) :-
-	AnchorFollowInfo = Vars - Intervals,
-	io__write_string("\n", !IO),
-	io__write(Anchor, !IO),
-	io__write_string(" =>\n", !IO),
-	list__map(term__var_to_int, set__to_sorted_list(Vars), VarNums),
-	io__write_string("vars [", !IO),
-	write_int_list(VarNums, !IO),
-	io__write_string("]\nintervals: ", !IO),
-	set__to_sorted_list(Intervals, IntervalList),
-	write_int_list(list__map(interval_id_to_int, IntervalList), !IO),
+	list__foldl(dump_matching_result,
+		StackOptInfo ^ matching_results, !IO),
 	io__write_string("\n", !IO).

 :- pred dump_anchor_inserts(pair(anchor, list(insert_spec))::in,
@@ -2246,14 +1151,5 @@
 	io__write_list(set__to_sorted_list(InsertAnchors), " ", io__write,
 		!IO),
 	io__write_string("\n", !IO).
-
-:- pred write_int_list(list(int)::in, io::di, io::uo) is det.
-
-write_int_list(List, !IO) :-
-	io__write_list(List, ", ", io__write_int, !IO).
-
-:- func interval_id_to_int(interval_id) = int.
-
-interval_id_to_int(interval_id(Num)) = Num.

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

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



More information about the reviews mailing list