[m-rev.] for review: optimize successive field updates

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue May 17 15:00:41 AEST 2005


For review by Julien.

Zoltan.

Fix a problem reported by Michael Day. When a piece of code had several updates
to the fields of a cell in a row, we were constructing all the intermediate
versions of the cell. With this change, we now construct only the final one.

compiler/simplify.m:
	The cause of the problem was simplify's use of the cannot_flush
	predicate from goal_form.m. Each field update consists of a pair of
	deconstruct/construct unifications inside a removable barrier scope,
	but cannot_flush assumed that any goal not on its small approved list
	may cause a stack flush. Simplify therefore told common.m to throw away
	its list of known cells when emerging from the scope.

	The fix is to replace the use of cannot_flush with a new predicate
	that is explicitly written for the needs of simplify, which is not
	too conservative. The concern about increasing the set of output
	variables of an existentially quantified scope is now addressed
	only when simplify__goal_2 when processing scope goals, not in two
	places (redundantly) as before.

	Simplify the logic of simplify_info_maybe_clear_structs.

	Simplify the mechanism for initializing simplify_infos.

	Use more descriptive variables names in simplify__pred.

	Switch to four-space indentation to reduce the number of bad line
	breaks.

compiler/pd_util.m:
	Conform to the new mechanism for initializing simplify_infos.

compiler/goal_form.m:
	Delete the cannot_flush predicate, since it now has no users.

compiler/common.m:
	Clean up some code. Break up an excessively large predicate, factor
	out some common code, and make comments conform to our conventions.

cvs diff: I know nothing about aditi_backend.m
Index: common.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/common.m,v
retrieving revision 1.77
diff -u -b -r1.77 common.m
--- common.m	24 Mar 2005 02:00:18 -0000	1.77
+++ common.m	17 May 2005 04:43:52 -0000
@@ -40,11 +40,11 @@
 
     % If we find a deconstruction or a construction we cannot optimize,
     % record the details of the memory cell in CommonInfo.
-
+    %
     % If we find a construction that constructs a cell identical to one
     % we have seen before, replace the construction with an assignment
     % from the variable unified with that cell.
-
+    %
 :- pred common__optimise_unification(unification::in, prog_var::in,
     unify_rhs::in, unify_mode::in, unify_context::in,
     hlds_goal_expr::in, hlds_goal_expr::out,
@@ -57,7 +57,7 @@
     % A call is considered replaceable if it has no uniquely moded outputs
     % and no destructive inputs.
     % It is the caller's responsibility to check that the call is pure.
-
+    %
 :- pred common__optimise_call(pred_id::in, proc_id::in, list(prog_var)::in,
     hlds_goal_info::in, hlds_goal_expr::in, hlds_goal_expr::out,
     simplify_info::in, simplify_info::out) is det.
@@ -67,16 +67,19 @@
     hlds_goal_expr::in, hlds_goal_expr::out,
     simplify_info::in, simplify_info::out) is det.
 
-    % Succeeds if the two variables are equivalent
-    % according to the specified equivalence class.
+    % Succeeds if the two variables are equivalent according to the specified
+    % equivalence class.
+    %
 :- pred common__vars_are_equivalent(prog_var::in, prog_var::in,
     common_info::in) is semidet.
 
     % Assorted stuff used here that simplify.m doesn't need to know about.
+    %
 :- type common_info.
 :- func common_info_init = common_info.
 
     % Clear the list of structs seen since the last stack flush.
+    %
 :- pred common_info_clear_structs(common_info::in, common_info::out) is det.
 
 %---------------------------------------------------------------------------%
@@ -222,8 +225,8 @@
     map__init(SeenCalls0),
     CommonInfo = common_info(VarEqv0, StructMap0, StructMap0, SeenCalls0).
 
-    % Clear structs seen since the last call.
-common_info_clear_structs(Info, Info ^ since_call_structs := map__init).
+common_info_clear_structs(!Info) :-
+    !:Info = !.Info ^ since_call_structs := map__init.
 
 %---------------------------------------------------------------------------%
 
@@ -231,16 +234,44 @@
         Goal0, Goal, GoalInfo0, GoalInfo, !Info) :-
     (
         Unification0 = construct(Var, ConsId, ArgVars, _, _, _, _),
+        common__optimise_construct(Var, ConsId, ArgVars, Mode,
+            Goal0, Goal, GoalInfo0, GoalInfo, !Info)
+    ;
+        Unification0 = deconstruct(Var, ConsId, ArgVars, UniModes, CanFail, _),
+        common__optimise_deconstruct(Var, ConsId, ArgVars, UniModes, CanFail,
+            Mode, Goal0, Goal, GoalInfo0, GoalInfo, !Info)
+    ;
+        Unification0 = assign(Var1, Var2),
+        common__record_equivalence(Var1, Var2, !Info),
+        Goal = Goal0,
+        GoalInfo = GoalInfo0
+    ;
+        Unification0 = simple_test(Var1, Var2),
+        common__record_equivalence(Var1, Var2, !Info),
+        Goal = Goal0,
+        GoalInfo = GoalInfo0
+    ;
+        Unification0 = complicated_unify(_, _, _),
+        Goal = Goal0,
+        GoalInfo = GoalInfo0
+    ).
+
+:- pred common__optimise_construct(prog_var::in, cons_id::in,
+    list(prog_var)::in, unify_mode::in,
+    hlds_goal_expr::in, hlds_goal_expr::out,
+    hlds_goal_info::in, hlds_goal_info::out,
+    simplify_info::in, simplify_info::out) is det.
+
+common__optimise_construct(Var, ConsId, ArgVars, Mode, Goal0, Goal,
+        GoalInfo0, GoalInfo, !Info) :-
         Mode = LVarMode - _,
         simplify_info_get_module_info(!.Info, ModuleInfo),
         mode_get_insts(ModuleInfo, LVarMode, _, Inst),
         (
-                % Don't optimise partially instantiated
-                % deconstruction unifications, because it's
-                % tricky to work out how to mode the
-                % replacement asssignment unifications.
-                % In the vast majority of cases, the
-                % variable is ground.
+            % Don't optimise partially instantiated deconstruction
+            % unifications, because it's tricky to work out how to mode
+            % the replacement asssignment unifications. In the vast
+            % majority of cases, the variable is ground.
             \+ inst_is_ground(ModuleInfo, Inst)
         ->
             Goal = Goal0,
@@ -252,7 +283,6 @@
             list__map_foldl(eqvclass__ensure_element_partition_id,
                 ArgVars, ArgVarIds, VarEqv0, VarEqv1),
             AllStructMap0 = CommonInfo0 ^ all_structs,
-            SinceCallStructMap0 = CommonInfo0 ^ since_call_structs,
             (
                 % common__generate_assign assumes that the output variable
                 % is in the instmap_delta, which will not be true if the
@@ -290,26 +320,24 @@
                 Goal = Goal0,
                 GoalInfo = GoalInfo0,
                 Struct = structure(Var, ArgVars),
-                common__do_record_cell(TypeCtor, ConsId, Struct,
-                    AllStructMap0, AllStructMap),
-                common__do_record_cell(TypeCtor, ConsId, Struct,
-                    SinceCallStructMap0, SinceCallStructMap),
-                CommonInfo = (((CommonInfo0 ^ var_eqv := VarEqv1)
-                    ^ all_structs := AllStructMap)
-                    ^ since_call_structs := SinceCallStructMap),
-                simplify_info_set_common_info(CommonInfo, !Info)
-            )
+            record_cell_in_maps(TypeCtor, ConsId, Struct, VarEqv1, !Info)
         )
-    ;
-        Unification0 = deconstruct(Var, ConsId, ArgVars, UniModes, CanFail, _),
+    ).
+
+:- pred common__optimise_deconstruct(prog_var::in, cons_id::in,
+    list(prog_var)::in, list(uni_mode)::in, can_fail::in, unify_mode::in,
+    hlds_goal_expr::in, hlds_goal_expr::out,
+    hlds_goal_info::in, hlds_goal_info::out,
+    simplify_info::in, simplify_info::out) is det.
+
+common__optimise_deconstruct(Var, ConsId, ArgVars, UniModes, CanFail, Mode,
+        Goal0, Goal, GoalInfo0, GoalInfo, !Info) :-
         simplify_info_get_module_info(!.Info, ModuleInfo),
         (
-                % Don't optimise partially instantiated
-                % deconstruction unifications, because it's
-                % tricky to work out how to mode the
-                % replacement asssignment unifications.
-                % In the vast majority of cases, the
-                % variable is ground.
+            % Don't optimise partially instantiated deconstruction
+            % unifications, because it's tricky to work out how to mode
+            % the replacement asssignment unifications. In the vast
+            % majority of cases, the variable is ground.
             Mode = LVarMode - _,
             mode_get_insts(ModuleInfo, LVarMode, Inst0, _),
             \+ inst_is_ground(ModuleInfo, Inst0)
@@ -319,9 +347,7 @@
             TypeCtor = lookup_var_type_ctor(!.Info, Var),
             simplify_info_get_common_info(!.Info, CommonInfo0),
             VarEqv0 = CommonInfo0 ^ var_eqv,
-            eqvclass__ensure_element_partition_id(Var, VarId,
-                VarEqv0, VarEqv1),
-            AllStructMap0 = CommonInfo0 ^ all_structs,
+        eqvclass__ensure_element_partition_id(Var, VarId, VarEqv0, VarEqv1),
             SinceCallStructMap0 = CommonInfo0 ^ since_call_structs,
             (
                 % Do not delete deconstruction unifications inserted by
@@ -332,16 +358,15 @@
 
                 map__search(SinceCallStructMap0, TypeCtor, ConsIdMap0),
                 map__search(ConsIdMap0, ConsId, Structs),
-                find_matching_cell_deconstruct(Structs, VarEqv1, VarId,
-                    OldStruct)
+            find_matching_cell_deconstruct(Structs, VarEqv1, VarId, OldStruct)
             ->
                 OldStruct = structure(_, OldArgVars),
                 eqvclass__ensure_corresponding_equivalences(ArgVars,
                     OldArgVars, VarEqv1, VarEqv),
                 CommonInfo = CommonInfo0 ^ var_eqv := VarEqv,
                 simplify_info_set_common_info(CommonInfo, !Info),
-                common__create_output_unifications(GoalInfo0, ArgVars,
-                    OldArgVars, UniModes, Goals, !Info),
+            common__create_output_unifications(GoalInfo0, ArgVars, OldArgVars,
+                UniModes, Goals, !Info),
                 Goal = conj(Goals),
                 pd_cost__goal(Goal0 - GoalInfo0, Cost),
                 simplify_info_incr_cost_delta(Cost, !Info),
@@ -355,32 +380,10 @@
             ;
                 Goal = Goal0,
                 Struct = structure(Var, ArgVars),
-                common__do_record_cell(TypeCtor, ConsId, Struct,
-                    AllStructMap0, AllStructMap),
-                common__do_record_cell(TypeCtor, ConsId, Struct,
-                    SinceCallStructMap0, SinceCallStructMap),
-                CommonInfo = (((CommonInfo0 ^ var_eqv := VarEqv1)
-                    ^ all_structs := AllStructMap)
-                    ^ since_call_structs := SinceCallStructMap),
-                simplify_info_set_common_info(CommonInfo, !Info)
+            record_cell_in_maps(TypeCtor, ConsId, Struct, VarEqv1, !Info)
             )
         ),
-        GoalInfo = GoalInfo0
-    ;
-        Unification0 = assign(Var1, Var2),
-        common__record_equivalence(Var1, Var2, !Info),
-        Goal = Goal0,
-        GoalInfo = GoalInfo0
-    ;
-        Unification0 = simple_test(Var1, Var2),
-        common__record_equivalence(Var1, Var2, !Info),
-        Goal = Goal0,
-        GoalInfo = GoalInfo0
-    ;
-        Unification0 = complicated_unify(_, _, _),
-        Goal = Goal0,
-        GoalInfo = GoalInfo0
-    ).
+    GoalInfo = GoalInfo0.
 
 :- func lookup_var_type_ctor(simplify_info, prog_var) = type_ctor.
 
@@ -437,10 +440,28 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred common__do_record_cell(type_ctor::in, cons_id::in, structure::in,
-    struct_map::in, struct_map::out) is det.
+:- pred record_cell_in_maps(type_ctor::in, cons_id::in, structure::in,
+    eqvclass(prog_var)::in, simplify_info::in, simplify_info::out) is det.
+
+record_cell_in_maps(TypeCtor, ConsId, Struct, VarEqv, !Info) :-
+    some [!CommonInfo] (
+        simplify_info_get_common_info(!.Info, !:CommonInfo),
+        AllStructMap0 = !.CommonInfo ^ all_structs,
+        SinceCallStructMap0 = !.CommonInfo ^ since_call_structs,
+        common__do_record_cell_in_struct_map(TypeCtor, ConsId, Struct,
+            AllStructMap0, AllStructMap),
+        common__do_record_cell_in_struct_map(TypeCtor, ConsId, Struct,
+            SinceCallStructMap0, SinceCallStructMap),
+        !:CommonInfo = !.CommonInfo ^ var_eqv := VarEqv,
+        !:CommonInfo = !.CommonInfo ^ all_structs := AllStructMap,
+        !:CommonInfo = !.CommonInfo ^ since_call_structs := SinceCallStructMap,
+        simplify_info_set_common_info(!.CommonInfo, !Info)
+    ).
+
+:- pred common__do_record_cell_in_struct_map(type_ctor::in, cons_id::in,
+    structure::in, struct_map::in, struct_map::out) is det.
 
-common__do_record_cell(TypeCtor, ConsId, Struct, !StructMap) :-
+common__do_record_cell_in_struct_map(TypeCtor, ConsId, Struct, !StructMap) :-
     ( map__search(!.StructMap, TypeCtor, ConsIdMap0) ->
         ( map__search(ConsIdMap0, ConsId, Structs0) ->
             Structs = [Struct | Structs0],
Index: goal_form.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_form.m,v
retrieving revision 1.15
diff -u -b -r1.15 goal_form.m
--- goal_form.m	7 Apr 2005 06:32:07 -0000	1.15
+++ goal_form.m	16 May 2005 09:49:15 -0000
@@ -98,12 +98,6 @@
 	%
 :- pred cannot_stack_flush(hlds_goal::in) is semidet.
 
-	% Succeed if execution of the given goal cannot encounter a context
-	% that causes any variable to be flushed to its stack slot or to a
-	% register.
-	%
-:- pred cannot_flush(hlds_goal::in) is semidet.
-
 	% Succeed if the given goal cannot fail before encountering a
 	% context that forces all variables to be flushed to their stack
 	% slots.  If such a goal needs a resume point, the only entry
@@ -471,27 +465,6 @@
 cannot_stack_flush_cases([case(_, Goal) | Cases]) :-
 	cannot_stack_flush(Goal),
 	cannot_stack_flush_cases(Cases).
-
-%-----------------------------------------------------------------------------%
-
-cannot_flush(GoalExpr - _) :-
-	cannot_flush_2(GoalExpr).
-
-:- pred cannot_flush_2(hlds_goal_expr::in) is semidet.
-
-cannot_flush_2(unify(_, _, _, Unify, _)) :-
-	Unify \= complicated_unify(_, _, _).
-cannot_flush_2(call(_, _, _, BuiltinState, _, _)) :-
-	BuiltinState = inline_builtin.
-cannot_flush_2(conj(Goals)) :-
-	cannot_flush_goals(Goals).
-
-:- pred cannot_flush_goals(list(hlds_goal)::in) is semidet.
-
-cannot_flush_goals([]).
-cannot_flush_goals([Goal | Goals]) :-
-	cannot_flush(Goal),
-	cannot_flush_goals(Goals).
 
 %-----------------------------------------------------------------------------%
 
cvs diff: I know nothing about maybe_mlds_to_gcc.m
Index: pd_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/pd_util.m,v
retrieving revision 1.35
diff -u -b -r1.35 pd_util.m
--- pd_util.m	24 Mar 2005 05:34:11 -0000	1.35
+++ pd_util.m	16 May 2005 13:40:29 -0000
@@ -240,16 +240,12 @@
 	module_info_globals(ModuleInfo0, Globals),
 	pd_info_get_pred_proc_id(!.PDInfo, proc(PredId, ProcId)),
 	proc_info_vartypes(ProcInfo0, VarTypes0),
-	det_info_init(ModuleInfo0, VarTypes0, PredId, ProcId,
-		Globals, DetInfo0),
+	det_info_init(ModuleInfo0, VarTypes0, PredId, ProcId, Globals,
+		DetInfo0),
 	pd_info_get_instmap(!.PDInfo, InstMap0),
 	pd_info_get_proc_info(!.PDInfo, ProcInfo0),
-	proc_info_varset(ProcInfo0, VarSet0),
-	proc_info_inst_varset(ProcInfo0, InstVarSet0),
-	proc_info_typeinfo_varmap(ProcInfo0, TVarMap0),
-	proc_info_typeclass_info_varmap(ProcInfo0, TCVarMap0),
-	simplify_info_init(DetInfo0, Simplifications, InstMap0,
-		VarSet0, InstVarSet0, TVarMap0, TCVarMap0, SimplifyInfo0),
+	simplify_info_init(DetInfo0, Simplifications, InstMap0, ProcInfo0,
+		SimplifyInfo0),
 
 	simplify__process_goal(Goal0, Goal, SimplifyInfo0, SimplifyInfo),
 
cvs diff: I know nothing about rl_file.m
cvs diff: I know nothing about rl_out.m
Index: simplify.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.139
diff -u -b -r1.139 simplify.m
--- simplify.m	24 Mar 2005 05:34:14 -0000	1.139
+++ simplify.m	17 May 2005 04:57:07 -0000
@@ -1,4 +1,6 @@
 %-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
 % Copyright (C) 1996-2005 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
@@ -18,6 +20,7 @@
 % Simplification is done in two passes. The first pass performs common
 % structure and duplicate call elimination. The second pass performs
 % excess assignment elimination and cleans up the code after the first pass.
+%
 % Two passes are required because the goal must be requantified after the
 % optimizations in common.m are run so that excess assignment elimination
 % works properly.
@@ -118,29 +121,29 @@
 
 %-----------------------------------------------------------------------------%
 
-simplify__pred(Simplifications0, PredId, !ModuleInfo,
-		!PredInfo, WarnCnt, ErrCnt, !IO) :-
-	write_pred_progress_message("% Simplifying ", PredId, !.ModuleInfo,
-		!IO),
+simplify__pred(Simplifications0, PredId, !ModuleInfo, !PredInfo,
+        WarnCnt, ErrCnt, !IO) :-
+    write_pred_progress_message("% Simplifying ", PredId, !.ModuleInfo, !IO),
 	ProcIds = pred_info_non_imported_procids(!.PredInfo),
 	(
 		% Don't warn for compiler-generated procedures.
 		list__member(warn_simple_code, Simplifications0),
 		is_unify_or_compare_pred(!.PredInfo)
 	->
-		list__delete_all(Simplifications0, warn_simple_code,
-			Simplifications)
+        list__delete_all(Simplifications0, warn_simple_code, Simplifications)
 	;
 		Simplifications = Simplifications0
 	),
 	MaybeMsgs0 = no,
-	simplify__procs(Simplifications, PredId, ProcIds, !ModuleInfo,
-		!PredInfo, MaybeMsgs0, MaybeMsgs),
-	( MaybeMsgs = yes(Msgs0 - Msgs1) ->
+    simplify__procs(Simplifications, PredId, ProcIds, !ModuleInfo, !PredInfo,
+        MaybeMsgs0, MaybeMsgs),
+    (
+        MaybeMsgs = yes(Msgs0 - Msgs1),
 		set__union(Msgs0, Msgs1, Msgs2),
 		set__to_sorted_list(Msgs2, Msgs),
 		det_report_msgs(Msgs, !.ModuleInfo, WarnCnt, ErrCnt, !IO)
 	;
+        MaybeMsgs = no,
 		WarnCnt = 0,
 		ErrCnt = 0
 	).
@@ -156,28 +159,30 @@
 	pred_info_procedures(!.PredInfo, Procs0),
 	map__lookup(Procs0, ProcId, Proc0),
 	simplify__proc_return_msgs(Simplifications, PredId, ProcId,
-		!ModuleInfo, Proc0, Proc, Msgs1),
+        !ModuleInfo, Proc0, Proc, ProcMsgSet),
 	map__det_update(Procs0, ProcId, Proc, Procs),
 	pred_info_set_procedures(Procs, !PredInfo),
-	set__to_sorted_list(Msgs1, Msgs2),
+    set__to_sorted_list(ProcMsgSet, ProcMsgs),
 	list__filter((pred(Msg::in) is semidet :-
 			det_msg_is_any_mode_msg(Msg, any_mode)
-		), Msgs2, AnyModeMsgs1, AllModeMsgs1),
-	set__sorted_list_to_set(AnyModeMsgs1, AnyModeMsgs2),
-	set__sorted_list_to_set(AllModeMsgs1, AllModeMsgs2),
-	( !.MaybeMsgs = yes(AnyModeMsgs0 - AllModeMsgs0) ->
-		set__union(AnyModeMsgs0, AnyModeMsgs2, AnyModeMsgs),
-		set__intersect(AllModeMsgs0, AllModeMsgs2, AllModeMsgs),
-		!:MaybeMsgs = yes(AllModeMsgs - AnyModeMsgs)
+        ), ProcMsgs, ProcAnyModeMsgs, ProcAllModeMsgs),
+    set__sorted_list_to_set(ProcAnyModeMsgs, ProcAnyModeMsgSet),
+    set__sorted_list_to_set(ProcAllModeMsgs, ProcAllModeMsgSet),
+    (
+        !.MaybeMsgs = yes(AnyModeMsgSet0 - AllModeMsgSet0),
+        set__union(AnyModeMsgSet0, ProcAnyModeMsgSet, AnyModeMsgSet),
+        set__intersect(AllModeMsgSet0, ProcAllModeMsgSet,
+            AllModeMsgSet),
+        !:MaybeMsgs = yes(AllModeMsgSet - AnyModeMsgSet)
 	;
-		!:MaybeMsgs = yes(AnyModeMsgs2 - AllModeMsgs2)
+        !.MaybeMsgs = no,
+        !:MaybeMsgs = yes(ProcAnyModeMsgSet - ProcAllModeMsgSet)
 	),
-	simplify__procs(Simplifications, PredId, ProcIds, !ModuleInfo,
-		!PredInfo, !MaybeMsgs).
+    simplify__procs(Simplifications, PredId, ProcIds, !ModuleInfo, !PredInfo,
+        !MaybeMsgs).
 
 simplify__proc(Simplifications, PredId, ProcId, !ModuleInfo, !Proc, !IO)  :-
-	write_pred_progress_message("% Simplifying ", PredId, !.ModuleInfo,
-		!IO),
+    write_pred_progress_message("% Simplifying ", PredId, !.ModuleInfo, !IO),
 	simplify__proc_return_msgs(Simplifications, PredId, ProcId, !ModuleInfo,
 		!Proc, _).
 
@@ -188,14 +193,9 @@
 	det_info_init(!.ModuleInfo, VarTypes0, PredId, ProcId, Globals,
 		DetInfo0),
 	proc_info_get_initial_instmap(!.ProcInfo, !.ModuleInfo, InstMap0),
-	proc_info_varset(!.ProcInfo, VarSet0),
-	proc_info_inst_varset(!.ProcInfo, InstVarSet0),
-	proc_info_typeinfo_varmap(!.ProcInfo, TVarMap0),
-	proc_info_typeclass_info_varmap(!.ProcInfo, TCVarMap0),
+    simplify_info_init(DetInfo0, Simplifications, InstMap0, !.ProcInfo, Info0),
 	proc_info_goal(!.ProcInfo, Goal0),
 
-	simplify_info_init(DetInfo0, Simplifications, InstMap0,
-		VarSet0, InstVarSet0, TVarMap0, TCVarMap0, Info0),
 	simplify__process_goal(Goal0, Goal, Info0, Info),
 
 	simplify_info_get_varset(Info, VarSet),
@@ -222,16 +222,14 @@
 		% On the first pass do common structure and call elimination.
 		NotOnFirstPass = [do_once, excess_assigns],
 
-		set__delete_list(Simplifications0, NotOnFirstPass,
-			Simplifications1),
+        set__delete_list(Simplifications0, NotOnFirstPass, Simplifications1),
 		simplify_info_set_simplifications(Simplifications1, !Info),
 
 		simplify__do_process_goal(Goal0, Goal1, !Info),
 
 		NotOnSecondPass = [warn_simple_code, warn_duplicate_calls,
 			common_struct, duplicate_calls],
-		set__delete_list(Simplifications0, NotOnSecondPass,
-			Simplifications2),
+        set__delete_list(Simplifications0, NotOnSecondPass, Simplifications2),
 		simplify_info_reinit(Simplifications2, InstMap0, !Info)
 	;
 		Goal1 = Goal0
@@ -264,9 +262,8 @@
 		RecomputeAtomic = yes,
 
 		simplify_info_get_module_info(!.Info, ModuleInfo0),
-		recompute_instmap_delta(RecomputeAtomic, Goal2, Goal3,
-			VarTypes1, !.Info ^ inst_varset, InstMap0,
-			ModuleInfo0, ModuleInfo1),
+        recompute_instmap_delta(RecomputeAtomic, Goal2, Goal3, VarTypes1,
+            !.Info ^ inst_varset, InstMap0, ModuleInfo0, ModuleInfo1),
 		simplify_info_set_module_info(ModuleInfo1, !Info)
 	;
 		Goal3 = Goal1
@@ -294,8 +291,7 @@
 		simplify_info_set_module_info(ModuleInfo3, !Info),
 
 		simplify_info_get_det_info(!.Info, DetInfo),
-		det_infer_goal(Goal3, InstMap0, SolnContext,
-			DetInfo, Goal, _, _)
+        det_infer_goal(Goal3, InstMap0, SolnContext, DetInfo, Goal, _, _)
 	;
 		Goal = Goal3
 	).
@@ -330,9 +326,11 @@
 simplify__lookup_option(Globals, Option, Simplification,
 		Simplifications0, Simplifications) :-
 	globals__lookup_bool_option(Globals, Option, Result),
-	( Result = yes ->
+    (
+        Result = yes,
 		Simplifications = [Simplification | Simplifications0]
 	;
+        Result = no,
 		Simplifications = Simplifications0
 	).
 
@@ -368,8 +366,7 @@
 				SubGoal = disj([]) - _
 			)
 		->
-			simplify_info_add_msg(goal_cannot_succeed(Context),
-				!Info)
+            simplify_info_add_msg(goal_cannot_succeed(Context), !Info)
 		;
 			true
 		),
@@ -399,8 +396,7 @@
 		goal_info_get_instmap_delta(GoalInfo0, InstMapDelta),
 		goal_info_get_nonlocals(GoalInfo0, NonLocalVars),
 		simplify_info_get_instmap(!.Info, InstMap0),
-		det_no_output_vars(NonLocalVars, InstMap0, InstMapDelta,
-			DetInfo),
+        det_no_output_vars(NonLocalVars, InstMap0, InstMapDelta, DetInfo),
 		% ensure goal is pure or semipure
 		\+ goal_info_is_impure(GoalInfo0),
 		( det_info_get_fully_strict(DetInfo, no)
@@ -514,14 +510,17 @@
 		Goals0, Goals1, !Info),
 	simplify__conj(Goals1, [], Goals, GoalInfo0, !Info),
 	simplify_info_set_instmap(InstMap0, !Info),
-	( Goals = [] ->
+    (
+        Goals = [],
 		goal_info_get_context(GoalInfo0, Context),
 		true_goal(Context, Goal - GoalInfo)
-	; Goals = [SingleGoal - SingleGoalInfo] ->
+    ;
+        Goals = [SingleGoal - SingleGoalInfo],
 		% a singleton conjunction is equivalent to the goal itself
 		simplify__maybe_wrap_goal(GoalInfo0, SingleGoalInfo,
 			SingleGoal, Goal, GoalInfo, !Info)
 	;
+        Goals = [_, _ | _],
 		%
 		% Conjunctions that cannot produce solutions may nevertheless
 		% contain nondet and multi goals. If this happens, the
@@ -534,10 +533,8 @@
 			determinism_components(Detism, CanFail, at_most_zero),
 			simplify__contains_multisoln_goal(Goals)
 		->
-			determinism_components(InnerDetism,
-				CanFail, at_most_many),
-			goal_info_set_determinism(GoalInfo0,
-				InnerDetism, InnerInfo),
+            determinism_components(InnerDetism, CanFail, at_most_many),
+            goal_info_set_determinism(GoalInfo0, InnerDetism, InnerInfo),
 			InnerGoal = conj(Goals) - InnerInfo,
 			Goal = scope(commit(dont_force_pruning), InnerGoal)
 		;
@@ -548,18 +545,17 @@
 
 simplify__goal_2(par_conj(Goals0), Goal, GoalInfo0, GoalInfo, !Info) :-
 	(
-		Goals0 = []
-	->
+        Goals0 = [],
 		goal_info_get_context(GoalInfo0, Context),
 		true_goal(Context, Goal - GoalInfo)
 	;
-		Goals0 = [SingleGoal0]
-	->
+        Goals0 = [SingleGoal0],
 		simplify__goal(SingleGoal0, SingleGoal - SingleGoalInfo,
 			!Info),
 		simplify__maybe_wrap_goal(GoalInfo0, SingleGoalInfo,
 			SingleGoal, Goal, GoalInfo, !Info)
 	;
+        Goals0 = [_, _ | _],
 		GoalInfo = GoalInfo0,
 		simplify__par_conj(Goals0, Goals, !.Info, !Info),
 		Goal = par_conj(Goals)
@@ -568,15 +564,18 @@
 simplify__goal_2(disj(Disjuncts0), Goal, GoalInfo0, GoalInfo, !Info) :-
 	simplify_info_get_instmap(!.Info, InstMap0),
 	simplify__disj(Disjuncts0, [], Disjuncts, [], InstMaps, !.Info, !Info),
-	( Disjuncts = [] ->
+    (
+        Disjuncts = [],
 		goal_info_get_context(GoalInfo0, Context),
 		fail_goal(Context, Goal - GoalInfo)
-	; Disjuncts = [SingleGoal] ->
-		% a singleton disjunction is equivalent to the goal itself
+    ;
+        Disjuncts = [SingleGoal],
+        % A singleton disjunction is equivalent to the goal itself.
 		SingleGoal = Goal1 - GoalInfo1,
-		simplify__maybe_wrap_goal(GoalInfo0, GoalInfo1,
-			Goal1, Goal, GoalInfo, !Info)
+        simplify__maybe_wrap_goal(GoalInfo0, GoalInfo1, Goal1, Goal, GoalInfo,
+            !Info)
 	;
+        Disjuncts = [_, _ | _],
 		Goal = disj(Disjuncts),
 		simplify_info_get_module_info(!.Info, ModuleInfo1),
 		goal_info_get_nonlocals(GoalInfo0, NonLocals),
@@ -586,10 +585,9 @@
 		simplify_info_set_module_info(ModuleInfo2, !Info),
 		goal_info_set_instmap_delta(GoalInfo0, NewDelta, GoalInfo)
 	),
-	(
-		list__length(Disjuncts) \=
-			list__length(Disjuncts0) `with_type` int
-	->
+    list__length(Disjuncts, DisjunctsLength),
+    list__length(Disjuncts0, Disjuncts0Length),
+    ( DisjunctsLength \= Disjuncts0Length ->
 		%
 		% If we pruned some disjuncts, variables used by those
 		% disjuncts may no longer be non-local to the disjunction.
@@ -623,15 +621,17 @@
 	),
 	simplify__switch(Var, Cases1, [], Cases, [], InstMaps,
 		SwitchCanFail0, SwitchCanFail, !.Info, !Info),
-	( Cases = [] ->
+    (
+        Cases = [],
 		% An empty switch always fails.
 		pd_cost__eliminate_switch(CostDelta),
 		simplify_info_incr_cost_delta(CostDelta, !Info),
 		goal_info_get_context(GoalInfo0, Context),
 		fail_goal(Context, Goal - GoalInfo)
-	; Cases = [case(ConsId, SingleGoal)] ->
-		% a singleton switch is equivalent to the goal itself with
-		% a possibly can_fail unification with the functor on the front.
+    ;
+        Cases = [case(ConsId, SingleGoal)],
+        % A singleton switch is equivalent to the goal itself with a
+        % possibly can_fail unification with the functor on the front.
 		Arity = cons_id_arity(ConsId),
 		(
 		    SwitchCanFail = can_fail,
@@ -648,18 +648,14 @@
 		    simplify_info_get_var_types(!.Info, VarTypes1),
 		    map__lookup(VarTypes1, Var, Type),
 		    simplify_info_get_module_info(!.Info, ModuleInfo1),
-		    (
-			type_util__is_existq_cons(ModuleInfo1,
-					Type, ConsId)
-		    ->
+            ( type_util__is_existq_cons(ModuleInfo1, Type, ConsId) ->
 		    	Goal = switch(Var, SwitchCanFail, Cases),
 			goal_info_get_nonlocals(GoalInfo0, NonLocals),
 			simplify_info_get_var_types(!.Info, VarTypes),
 			merge_instmap_deltas(InstMap0, NonLocals, VarTypes,
 				InstMaps, NewDelta, ModuleInfo1, ModuleInfo2),
 			simplify_info_set_module_info(ModuleInfo2, !Info),
-			goal_info_set_instmap_delta(GoalInfo0,
-				NewDelta, GoalInfo)
+                goal_info_set_instmap_delta(GoalInfo0, NewDelta, GoalInfo)
 		    ;
 			simplify__create_test_unification(Var, ConsId, Arity,
 				UnifyGoal, !Info),
@@ -696,6 +692,7 @@
 		pd_cost__eliminate_switch(CostDelta),
 		simplify_info_incr_cost_delta(CostDelta, !Info)
 	;
+        Cases = [_, _ | _],
 		Goal = switch(Var, SwitchCanFail, Cases),
 		simplify_info_get_module_info(!.Info, ModuleInfo1),
 		goal_info_get_nonlocals(GoalInfo0, NonLocals),
@@ -705,7 +702,9 @@
 		simplify_info_set_module_info(ModuleInfo2, !Info),
 		goal_info_set_instmap_delta(GoalInfo0, NewDelta, GoalInfo)
 	),
-	( list__length(Cases) \= list__length(Cases0) `with_type` int ->
+    list__length(Cases0, Cases0Length),
+    list__length(Cases, CasesLength),
+    ( CasesLength \= Cases0Length ->
 		%
 		% If we pruned some cases, variables used by those
 		% cases may no longer be non-local to the switch.
@@ -760,8 +759,7 @@
 	%
 	(
 		Args = [TI, X, Y],
-		mercury_public_builtin_module =
-			hlds_pred__pred_info_module(PredInfo),
+        mercury_public_builtin_module = hlds_pred__pred_info_module(PredInfo),
 		Name = hlds_pred__pred_info_name(PredInfo),
 		( Name =  "@<", Inequality = "<", Invert = no
 		; Name = "@=<", Inequality = ">", Invert = yes
@@ -816,9 +814,8 @@
 		U0 = complicated_unify(UniMode, CanFail, TypeInfoVars)
 	->
 		( RT0 = var(V) ->
-			simplify__process_compl_unify(LT0, V,
-				UniMode, CanFail, TypeInfoVars,
-				C, GoalInfo0, Goal1, !Info),
+            simplify__process_compl_unify(LT0, V, UniMode, CanFail,
+                TypeInfoVars, C, GoalInfo0, Goal1, !Info),
 			Goal1 = Goal - GoalInfo
 		;
 			error("simplify.m: invalid RHS for complicated unify")
@@ -881,8 +878,7 @@
 		goal_to_conj_list(Cond0, CondList),
 		goal_to_conj_list(Then0, ThenList),
 		list__append(CondList, ThenList, List),
-		simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo,
-			!Info),
+        simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info),
 		goal_info_get_context(GoalInfo0, Context),
 		simplify_info_add_msg(ite_cond_cannot_fail(Context), !Info),
 		simplify_info_set_requantify(!Info),
@@ -905,33 +901,27 @@
 				MaybeNegDetism = yes(NegDetism1),
 				(
 					NegDetism1 = erroneous,
-					instmap_delta_init_unreachable(
-						NegInstMapDelta1)
+                    instmap_delta_init_unreachable(NegInstMapDelta1)
 				;
 					NegDetism1 = det,
-					instmap_delta_init_reachable(
-						NegInstMapDelta1)
+                    instmap_delta_init_reachable(NegInstMapDelta1)
 				)
 			->
 				NegDetism = NegDetism1,
 				NegInstMapDelta = NegInstMapDelta1
 			;
-				error("simplify__goal_2: " ++
-					"cannot get negated determinism")
+                error("simplify__goal_2: cannot get negated determinism")
 			),
-			goal_info_set_determinism(CondInfo0,
-				NegDetism, NegCondInfo0),
-			goal_info_set_instmap_delta(NegCondInfo0,
-				NegInstMapDelta, NegCondInfo),
+            goal_info_set_determinism(CondInfo0, NegDetism, NegCondInfo0),
+            goal_info_set_instmap_delta(NegCondInfo0, NegInstMapDelta,
+                NegCondInfo),
 			Cond = not(Cond0) - NegCondInfo
 		),
 		goal_to_conj_list(Else0, ElseList),
 		List = [Cond | ElseList],
-		simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo,
-			!Info),
+        simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info),
 		goal_info_get_context(GoalInfo0, Context),
-		simplify_info_add_msg(ite_cond_cannot_succeed(Context),
-			!Info),
+        simplify_info_add_msg(ite_cond_cannot_succeed(Context), !Info),
 		simplify_info_set_requantify(!Info),
 		simplify_info_set_rerun_det(!Info)
 	; Else0 = disj([]) - _ ->
@@ -939,8 +929,7 @@
 		goal_to_conj_list(Cond0, CondList),
 		goal_to_conj_list(Then0, ThenList),
 		list__append(CondList, ThenList, List),
-		simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo,
-			!Info),
+        simplify__goal(conj(List) - GoalInfo0, Goal - GoalInfo, !Info),
 		simplify_info_set_requantify(!Info),
 		simplify_info_set_rerun_det(!Info)
 	;
@@ -994,8 +983,7 @@
 			)
 		->
 			simplify_info_undo_goal_updates(Info0, !Info),
-			simplify__goal_2(IfThenElse, Goal, GoalInfo1, GoalInfo,
-				!Info)
+            simplify__goal_2(IfThenElse, Goal, GoalInfo1, GoalInfo, !Info)
 		;
 			(
 				%
@@ -1012,8 +1000,7 @@
 			->
 				determinism_components(InnerDetism,
 					IfThenElseCanFail, at_most_many),
-				goal_info_set_determinism(GoalInfo1,
-					InnerDetism, InnerInfo),
+                goal_info_set_determinism(GoalInfo1, InnerDetism, InnerInfo),
 				Goal = scope(commit(dont_force_pruning),
 					IfThenElse - InnerInfo)
 			;
@@ -1036,8 +1023,7 @@
 	( CanFail = cannot_fail ->
 		simplify_info_add_msg(negated_goal_cannot_fail(Context), !Info)
 	; MaxSoln = at_most_zero ->
-		simplify_info_add_msg(negated_goal_cannot_succeed(Context),
-			!Info)
+        simplify_info_add_msg(negated_goal_cannot_succeed(Context), !Info)
 	;
 		true
 	),
@@ -1073,7 +1059,33 @@
 	simplify__goal(Goal1, Goal2, !Info),
 	simplify__nested_scopes(Reason0, Goal2, SomeInfo, Goal),
 	Goal = GoalExpr - GoalInfo,
-	( Goal = scope(_, _) - _ ->
+    ( Goal = scope(FinalReason, _) - _ ->
+        (
+            FinalReason = promise_purity(_, _),
+            KeepCommon = yes
+        ;
+            FinalReason = commit(_),
+            KeepCommon = yes
+        ;
+            FinalReason = from_ground_term(_),
+            KeepCommon = yes
+        ;
+            FinalReason = barrier(removable),
+            KeepCommon = yes
+        ;
+            FinalReason = barrier(not_removable),
+            KeepCommon = no
+        ;
+            FinalReason = exist_quant(_),
+            KeepCommon = no
+        ;
+            FinalReason = promise_equivalent_solutions(_),
+            KeepCommon = no
+        ),
+        (
+            KeepCommon = yes
+        ;
+            KeepCommon = no,
 		% Replacing calls, constructions or deconstructions
 		% outside a commit with references to variables created
 		% inside the commit would increase the set of output
@@ -1085,6 +1097,7 @@
 		% to ensure that we don't make any such replacements
 		% when processing the rest of the goal.
 		simplify_info_set_common_info(Common, !Info)
+        )
 	;
 		true
 	).
@@ -1097,8 +1110,8 @@
 		ExtraArgs = []
 	->
 		ArgVars = list__map(foreign_arg_var, Args),
-		common__optimise_call(PredId, ProcId, ArgVars, GoalInfo,
-			Goal0, Goal, !Info)
+        common__optimise_call(PredId, ProcId, ArgVars, GoalInfo, Goal0, Goal,
+            !Info)
 	;
 		Goal = Goal0
 	).
@@ -1139,12 +1152,11 @@
 	instmap__lookup_var(InstMap, X, XInst),
 	instmap__lookup_var(InstMap, Y, YInst),
 	simplify_info_get_module_info(!.Info, ModuleInfo),
-	ModeNo   = ( if inst_is_unique(ModuleInfo, XInst) then
-			( if inst_is_unique(ModuleInfo, YInst) then 1
-							       else 2 )
+    ModeNo =
+        ( if inst_is_unique(ModuleInfo, XInst) then
+            ( if inst_is_unique(ModuleInfo, YInst) then 1 else 2 )
 		     else
-		     	( if inst_is_unique(ModuleInfo, YInst) then 3
-		     					       else 0 )
+            ( if inst_is_unique(ModuleInfo, YInst) then 3 else 0 )
 		   ),
 
 	Unique   = ground(unique, none),
@@ -1164,10 +1176,8 @@
 	UMode    = ((Unique -> Bound) - (Bound -> Bound)),
 	RHS      = functor(ConsId, no, []),
 	UKind    = deconstruct(R, ConsId, [], [], can_fail, no),
-	UContext = unify_context(
-			implicit(
-			    "replacement of inequality with call to compare/3"),
-			[]),
+    UContext = unify_context(implicit(
+                "replacement of inequality with call to compare/3"), []),
 	UfyExpr  = unify(R, RHS, UMode, UKind, UContext),
 	goal_info_get_nonlocals(GoalInfo, UfyNonLocals0),
 	goal_info_set_nonlocals(GoalInfo, UfyNonLocals0 `insert` R, UfyInfo),
@@ -1191,8 +1201,7 @@
 simplify__call_goal(PredId, ProcId, Args, IsBuiltin, Goal0, Goal,
 		GoalInfo0, GoalInfo, !Info) :-
 	simplify_info_get_module_info(!.Info, ModuleInfo),
-	module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
-		PredInfo, ProcInfo),
+    module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo, ProcInfo),
 	%
 	% check for calls to predicates with `pragma obsolete' declarations
 	%
@@ -1212,8 +1221,7 @@
 	->
 
 		goal_info_get_context(GoalInfo0, Context1),
-		simplify_info_add_msg(warn_obsolete(PredId, Context1),
-			!Info)
+        simplify_info_add_msg(warn_obsolete(PredId, Context1), !Info)
 	;
 		true
 	),
@@ -1313,16 +1321,16 @@
 		simplify_do_calls(!.Info),
 		goal_info_is_pure(GoalInfo0)
 	->
-		common__optimise_call(PredId, ProcId, Args, GoalInfo0,
-			Goal0, Goal1, !Info)
+        common__optimise_call(PredId, ProcId, Args, GoalInfo0, Goal0, Goal1,
+            !Info)
 	;
 		simplify_do_warn_calls(!.Info),
 		goal_info_is_pure(GoalInfo0)
 	->
 		% we need to do the pass, for the warnings, but we ignore
 		% the optimized goal and instead use the original one
-		common__optimise_call(PredId, ProcId, Args, GoalInfo0,
-			Goal0, _Goal1, !Info),
+        common__optimise_call(PredId, ProcId, Args, GoalInfo0, Goal0, _Goal1,
+            !Info),
 		Goal1 = Goal0
 	;
 		Goal1 = Goal0
@@ -1338,9 +1346,8 @@
 		simplify_info_get_var_types(!.Info, VarTypes),
 		(
 			Goal1 = call(_, _, _, _, _, _),
-			const_prop.evaluate_call(PredId, ProcId, Args,
-				GoalInfo0, VarTypes, Instmap0, ModuleInfo2,
-				Goal2, GoalInfo2)
+            const_prop.evaluate_call(PredId, ProcId, Args, GoalInfo0, VarTypes,
+                Instmap0, ModuleInfo2, Goal2, GoalInfo2)
 		->
 			Goal = Goal2,
 			GoalInfo = GoalInfo2,
@@ -1377,10 +1384,9 @@
 		% associated with the type of the variables that
 		% are being unified.
 		%
-		simplify__type_info_locn(TypeVar, TypeInfoVar, ExtraGoals,
-			!Info),
-		simplify__call_generic_unify(TypeInfoVar, XVar, YVar,
-			ModuleInfo, !.Info, Context, GoalInfo0, Call)
+        simplify__type_info_locn(TypeVar, TypeInfoVar, ExtraGoals, !Info),
+        simplify__call_generic_unify(TypeInfoVar, XVar, YVar, ModuleInfo,
+            !.Info, Context, GoalInfo0, Call)
 
 	; type_is_higher_order(Type, _, _, _, _) ->
 		%
@@ -1402,11 +1408,10 @@
 			error("simplify: type_to_ctor_and_args failed")
 		),
 		determinism_components(Det, CanFail, at_most_one),
-		unify_proc__lookup_mode_num(ModuleInfo, TypeCtor, UniMode,
-			Det, ProcId),
+        unify_proc__lookup_mode_num(ModuleInfo, TypeCtor, UniMode, Det,
+            ProcId),
 		module_info_globals(ModuleInfo, Globals),
-		globals__lookup_bool_option(Globals, special_preds,
-			SpecialPreds),
+        globals__lookup_bool_option(Globals, special_preds, SpecialPreds),
 		(
 			hlds_pred__in_in_unification_proc_id(ProcId),
 			(
@@ -1422,8 +1427,7 @@
 				% higher_order.m will specialize these cases
 				% if possible.
 				%
-				special_pred_is_generated_lazily(ModuleInfo,
-					TypeCtor)
+                special_pred_is_generated_lazily(ModuleInfo, TypeCtor)
 			)
 		->
 			simplify__make_type_info_vars([Type], TypeInfoVars,
@@ -1432,8 +1436,7 @@
 				TypeInfoVar = TypeInfoVarPrime
 			;
 				error("simplify__process_compl_unify: " ++
-					"more than one typeinfo " ++
-					"for one type var")
+                    "more than one typeinfo for one type var")
 			),
 			simplify__call_generic_unify(TypeInfoVar, XVar, YVar,
 				ModuleInfo, !.Info, Context, GoalInfo0, Call)
@@ -1444,13 +1447,12 @@
 			% inserting extra typeinfo arguments if necessary.
 			%
 
-			simplify__make_type_info_vars(TypeArgs,
-				TypeInfoVars, ExtraGoals, !Info),
-			simplify__call_specific_unify(TypeCtor, TypeInfoVars,
-				XVar, YVar, ProcId, ModuleInfo, Context,
-				GoalInfo0, Call0, CallGoalInfo0),
-			simplify__goal_2(Call0, Call1,
-				CallGoalInfo0, CallGoalInfo1, !Info),
+            simplify__make_type_info_vars(TypeArgs, TypeInfoVars, ExtraGoals,
+                !Info),
+            simplify__call_specific_unify(TypeCtor, TypeInfoVars, XVar, YVar,
+                ProcId, ModuleInfo, Context, GoalInfo0, Call0, CallGoalInfo0),
+            simplify__goal_2(Call0, Call1, CallGoalInfo0, CallGoalInfo1,
+                !Info),
 			Call = Call1 - CallGoalInfo1
 		)
 	),
@@ -1558,8 +1560,7 @@
 	;
 			% If the typeinfo is in a typeclass_info
 			% then we need to extract it
-		TypeInfoLocn =
-			typeclass_info(TypeClassInfoVar, Index),
+        TypeInfoLocn = typeclass_info(TypeClassInfoVar, Index),
 		simplify__extract_type_info(TypeVar, TypeClassInfoVar, Index,
 			Goals, TypeInfoVar, !Info)
 	).
@@ -1575,8 +1576,7 @@
 	simplify_info_get_var_types(!.Info, VarTypes0),
 
 	polymorphism__gen_extract_type_info(TypeVar, TypeClassInfoVar, Index,
-		ModuleInfo, Goals, TypeInfoVar,
-		VarSet0, VarSet, VarTypes0, VarTypes),
+        ModuleInfo, Goals, TypeInfoVar, VarSet0, VarSet, VarTypes0, VarTypes),
 
 	simplify_info_set_var_types(VarTypes, !Info),
 	simplify_info_set_varset(VarSet, !Info).
@@ -1705,8 +1705,7 @@
 		Goal = Goal1,
 		GoalInfo = InnerGoalInfo
 	;
-		Goal = scope(commit(dont_force_pruning),
-			Goal1 - InnerGoalInfo),
+        Goal = scope(commit(dont_force_pruning), Goal1 - InnerGoalInfo),
 		GoalInfo = OuterGoalInfo,
 		simplify_info_set_rerun_det(!Info)
 	).
@@ -1733,8 +1732,7 @@
 		->
 			simplify_info_undo_goal_updates(Info0, !Info),
 			list__append(SubGoals1, Goals0, Goals1),
-			simplify__conj(Goals1, RevGoals0, Goals, ConjInfo,
-				!Info)
+            simplify__conj(Goals1, RevGoals0, Goals, ConjInfo, !Info)
 		;
 			% Delete unreachable goals.
 			(
@@ -1743,13 +1741,11 @@
 			;
 				Goal1 = _ - GoalInfo1,
 				goal_info_get_determinism(GoalInfo1, Detism1),
-				determinism_components(Detism1, _,
-					at_most_zero)
+                determinism_components(Detism1, _, at_most_zero)
 			)
 		->
 			simplify__conjoin_goal_and_rev_goal_list(Goal1,
 				RevGoals0, RevGoals1),
-
 			(
 				( Goal1 = disj([]) - _
 				; Goals0 = []
@@ -1778,8 +1774,7 @@
 			simplify__conjoin_goal_and_rev_goal_list(Goal1,
 				RevGoals0, RevGoals1),
 			simplify_info_update_instmap(Goal1, !Info),
-			simplify__conj(Goals0, RevGoals1, Goals, ConjInfo,
-				!Info)
+            simplify__conj(Goals0, RevGoals1, Goals, ConjInfo, !Info)
 		)
 	).
 
@@ -1818,20 +1813,17 @@
 		simplify_info_get_module_info(!.Info, ModuleInfo),
 		module_info_globals(ModuleInfo, Globals),
 		globals__get_trace_level(Globals, TraceLevel),
-		globals__lookup_bool_option(Globals,
-			trace_optimized, TraceOptimized),
+        globals__lookup_bool_option(Globals, trace_optimized, TraceOptimized),
 		simplify_info_get_varset(!.Info, VarSet0),
-		simplify__find_excess_assigns_in_conj(TraceLevel,
-			TraceOptimized, VarSet0, ConjNonLocals,
-			Goals0, [], RevGoals, Subn0, Subn1),
+        simplify__find_excess_assigns_in_conj(TraceLevel, TraceOptimized,
+            VarSet0, ConjNonLocals, Goals0, [], RevGoals, Subn0, Subn1),
 		( map__is_empty(Subn1) ->
 			Goals = Goals0
 		;
 			renaming_transitive_closure(Subn1, Subn),
 			list__reverse(RevGoals, Goals1),
 			MustSub = no,
-			goal_util__rename_vars_in_goals(Goals1, MustSub,
-				Subn, Goals),
+            goal_util__rename_vars_in_goals(Goals1, MustSub, Subn, Goals),
 			map__keys(Subn0, RemovedVars),
 			varset__delete_vars(VarSet0, RemovedVars, VarSet),
 			simplify_info_set_varset(VarSet, !Info),
@@ -1839,8 +1831,7 @@
 			apply_substitutions_to_var_map(TVarMap0,
 				map__init, map__init, Subn, TVarMap),
 			simplify_info_set_type_info_varmap(TVarMap, !Info),
-			simplify_info_get_typeclass_info_varmap(!.Info,
-				TCVarMap0),
+            simplify_info_get_typeclass_info_varmap(!.Info, TCVarMap0),
 			apply_substitutions_to_typeclass_var_map(TCVarMap0,
 				map__init, map__init, Subn, TCVarMap),
 			simplify_info_set_typeclass_info_varmap(TCVarMap,
@@ -1862,8 +1853,8 @@
 simplify__find_excess_assigns_in_conj(Trace, TraceOptimized, VarSet,
 		ConjNonLocals, [Goal | Goals], RevGoals0, RevGoals, !Subn) :-
 	(
-		goal_is_excess_assign(Trace, TraceOptimized,
-			VarSet, ConjNonLocals, Goal, !Subn)
+        goal_is_excess_assign(Trace, TraceOptimized, VarSet, ConjNonLocals,
+            Goal, !Subn)
 	->
 		RevGoals1 = RevGoals0
 	;
@@ -1965,8 +1956,8 @@
 	simplify_info_get_module_info(!.Info, ModuleInfo0),
 	simplify_info_get_var_types(!.Info, VarTypes),
 	map__lookup(VarTypes, Var, Type),
-	instmap__bind_var_to_functor(Var, Type, ConsId,
-		InstMap0, InstMap1, ModuleInfo0, ModuleInfo1),
+    instmap__bind_var_to_functor(Var, Type, ConsId, InstMap0, InstMap1,
+        ModuleInfo0, ModuleInfo1),
 	simplify_info_set_module_info(ModuleInfo1, !Info),
 	simplify_info_set_instmap(InstMap1, !Info),
 	simplify__goal(Goal0, Goal, !Info),
@@ -1990,8 +1981,7 @@
 		goal_info_get_instmap_delta(GoalInfo, InstMapDelta0),
 		simplify_info_get_module_info(!.Info, ModuleInfo2),
 		instmap_delta_bind_var_to_functor(Var, Type, ConsId,
-			InstMap0, InstMapDelta0, InstMapDelta,
-			ModuleInfo2, ModuleInfo),
+            InstMap0, InstMapDelta0, InstMapDelta, ModuleInfo2, ModuleInfo),
 		simplify_info_set_module_info(ModuleInfo, !Info),
 
 		!:InstMaps = [InstMapDelta | !.InstMaps],
@@ -1999,8 +1989,8 @@
 	),
 
 	simplify_info_post_branch_update(Info0, !Info),
-	simplify__switch(Var, Cases0, RevCases, Cases, !InstMaps,
-		!CanFail, Info0, !Info).
+    simplify__switch(Var, Cases0, RevCases, Cases, !InstMaps, !CanFail,
+        Info0, !Info).
 
 	% Create a semidet unification at the start of a singleton case
 	% in a can_fail switch.
@@ -2038,8 +2028,7 @@
 	list__map(InstToUniMode, ArgInsts, UniModes),
 	UniMode = (Inst0 -> Inst0) - (Inst0 -> Inst0),
 	UnifyContext = unify_context(explicit, []),
-	Unification = deconstruct(Var, ConsId,
-		ArgVars, UniModes, can_fail, no),
+    Unification = deconstruct(Var, ConsId, ArgVars, UniModes, can_fail, no),
 	ExtraGoal = unify(Var, functor(ConsId, no, ArgVars),
 		UniMode, Unification, UnifyContext),
 	set__singleton_set(NonLocals, Var),
@@ -2080,8 +2069,7 @@
 			Goal0 \= disj([]) - _
 		->
 			goal_info_get_context(GoalInfo, Context),
-			simplify_info_add_msg(zero_soln_disjunct(Context),
-				!Info)
+            simplify_info_add_msg(zero_soln_disjunct(Context), !Info)
 		;
 			true
 		),
@@ -2104,8 +2092,7 @@
 		;
 			RevGoals1 = [Goal | RevGoals0],
 			goal_info_get_instmap_delta(GoalInfo, InstMapDelta),
-			!:PostBranchInstMaps =
-				[InstMapDelta | !.PostBranchInstMaps]
+            !:PostBranchInstMaps = [InstMapDelta | !.PostBranchInstMaps]
 		)
 	;
 		RevGoals1 = [Goal | RevGoals0],
@@ -2182,9 +2169,11 @@
 det_disj_to_ite([], _GoalInfo, _) :-
 	error("reached base case of det_disj_to_ite").
 det_disj_to_ite([Disjunct | Disjuncts], GoalInfo, Goal) :-
-	( Disjuncts = [] ->
+    (
+        Disjuncts = [],
 		Goal = Disjunct
 	;
+        Disjuncts = [_ | _],
 		Cond = Disjunct,
 		Cond = _CondGoal - CondGoalInfo,
 
@@ -2200,8 +2189,7 @@
 
 		goal_info_get_instmap_delta(GoalInfo, InstMapDelta0),
 		instmap_delta_restrict(InstMapDelta0, NonLocals, InstMapDelta),
-		goal_info_set_instmap_delta(NewGoalInfo0, InstMapDelta,
-			NewGoalInfo1),
+        goal_info_set_instmap_delta(NewGoalInfo0, InstMapDelta, NewGoalInfo1),
 
 		goal_info_get_determinism(CondGoalInfo, CondDetism),
 		goal_info_get_determinism(RestGoalInfo, RestDetism),
@@ -2259,13 +2247,16 @@
 		typeclass_info_varmap	:: typeclass_info_varmap
 	).
 
-simplify_info_init(DetInfo, Simplifications0, InstMap, VarSet, InstVarSet,
-		TVarMap, TCVarMap, Info) :-
+simplify_info_init(DetInfo, Simplifications, InstMap, ProcInfo, Info) :-
+    proc_info_varset(ProcInfo, VarSet),
+    proc_info_inst_varset(ProcInfo, InstVarSet),
+    proc_info_typeinfo_varmap(ProcInfo, TVarMap),
+    proc_info_typeclass_info_varmap(ProcInfo, TCVarMap),
 	set__init(Msgs),
-	set__list_to_set(Simplifications0, Simplifications),
-	Info = simplify_info(DetInfo, Msgs, Simplifications, common_info_init,
-		InstMap, VarSet, InstVarSet, no, no, no, 0, 0,
-		TVarMap, TCVarMap).
+    set__list_to_set(Simplifications, SimplificationsSet),
+    Info = simplify_info(DetInfo, Msgs, SimplificationsSet,
+        common_info_init, InstMap, VarSet, InstVarSet,
+        no, no, no, 0, 0, TVarMap, TCVarMap).
 
 	% Reinitialise the simplify_info before reprocessing a goal.
 :- pred simplify_info_reinit(set(simplification)::in, instmap::in,
@@ -2286,10 +2277,8 @@
 :- import_module parse_tree__prog_data.
 :- import_module set.
 
-:- pred simplify_info_init(det_info::in, list(simplification)::in, instmap::in,
-	prog_varset::in, inst_varset::in,
-	type_info_varmap::in, typeclass_info_varmap::in,
-	simplify_info::out) is det.
+:- pred simplify_info_init(det_info::in, list(simplification)::in,
+    instmap::in, proc_info::in, simplify_info::out) is det.
 
 :- pred simplify_info_get_det_info(simplify_info::in, det_info::out) is det.
 :- pred simplify_info_get_msgs(simplify_info::in, set(det_msg)::out) is det.
@@ -2459,6 +2448,9 @@
 simplify_do_once(Info) :-
 	simplify_info_get_simplifications(Info, Simplifications),
 	set__member(do_once, Simplifications).
+simplify_do_common(Info) :-
+    simplify_info_get_simplifications(Info, Simplifications),
+    set__member(common_struct, Simplifications).
 simplify_do_excess_assigns(Info) :-
 	simplify_info_get_simplifications(Info, Simplifications),
 	set__member(excess_assigns, Simplifications).
@@ -2468,9 +2460,6 @@
 simplify_do_const_prop(Info) :-
 	simplify_info_get_simplifications(Info, Simplifications),
 	set__member(constant_prop, Simplifications).
-simplify_do_common(Info) :-
-	simplify_info_get_simplifications(Info, Simplifications),
-	set__member(common_struct, Simplifications).
 simplify_do_more_common(Info) :-
 	simplify_info_get_simplifications(Info, Simplifications),
 	set__member(extra_common_struct, Simplifications).
@@ -2493,29 +2482,16 @@
 	% way since it is nearly always better to optimize them away.
 	% When doing deforestation, it may be better to remove
 	% as many common structures as possible.
+    %
 :- pred simplify_info_maybe_clear_structs(before_after::in, hlds_goal::in,
 	simplify_info::in, simplify_info::out) is det.
 
 simplify_info_maybe_clear_structs(BeforeAfter, Goal, !Info) :-
 	(
-		( cannot_flush(Goal)
-		; simplify_do_more_common(!.Info)
-		)
-	->
-		true
-	;
-		% First check to see if a call is common and can be replaced
-		% by a series of unifications.
 		simplify_do_common(!.Info),
-		(
-			BeforeAfter = after
-		;
-			BeforeAfter = before,
+        \+ simplify_do_more_common(!.Info),
 			Goal = GoalExpr - _,
-			GoalExpr \= call(_, _, _, _, _, _),
-			GoalExpr \= generic_call(_, _, _, _),
-			GoalExpr \= foreign_proc(_, _, _, _, _, _)
-		)
+        will_flush(GoalExpr, BeforeAfter) = yes
 	->
 		simplify_info_get_common_info(!.Info, CommonInfo0),
 		common_info_clear_structs(CommonInfo0, CommonInfo),
@@ -2524,6 +2500,84 @@
 		true
 	).
 
+	% Succeed if execution of the given goal cannot encounter a context
+	% that causes any variable to be flushed to its stack slot or to a
+	% register at the specified time.
+	%
+:- func will_flush(hlds_goal_expr, before_after) = bool.
+
+will_flush(unify(_, _, _, Unify, _), _) = WillFlush :-
+	( Unify = complicated_unify(_, _, _) ->
+		WillFlush = yes
+	;
+		WillFlush = no
+	).
+will_flush(call(_, _, _, BuiltinState, _, _), BeforeAfter) = WillFlush :-
+	( BuiltinState = inline_builtin ->
+		WillFlush = no
+	;
+        (
+            BeforeAfter = before,
+            WillFlush = no
+        ;
+            BeforeAfter = after,
+            WillFlush = yes
+        )
+	).
+will_flush(generic_call(GenericCall, _, _, _), BeforeAfter) = WillFlush :-
+	(
+        GenericCall = higher_order(_, _, _, _),
+		WillFlush0 = yes
+	;
+        GenericCall = class_method(_, _, _, _),
+		WillFlush0 = yes
+	;
+        GenericCall = unsafe_cast,
+		WillFlush0 = no
+	;
+        GenericCall = aditi_builtin(_, _),
+		WillFlush0 = yes
+	),
+    (
+        BeforeAfter = before,
+        WillFlush = no
+    ;
+        BeforeAfter = after,
+        WillFlush = WillFlush0
+    ).
+will_flush(foreign_proc(_, _, _, _, _, _), BeforeAfter) = WillFlush :-
+    (
+        BeforeAfter = before,
+        WillFlush = no
+    ;
+        BeforeAfter = after,
+        WillFlush = yes
+    ).
+will_flush(par_conj(_), _) = yes.
+will_flush(conj(_), _) = no.
+will_flush(switch(_, _, _), _) = no.
+will_flush(disj(_), BeforeAfter) = WillFlush :-
+    (
+        BeforeAfter = before,
+        WillFlush = yes
+    ;
+        BeforeAfter = after,
+        WillFlush = no
+    ).
+will_flush(if_then_else(_, _, _, _), BeforeAfter) = WillFlush :-
+    (
+        BeforeAfter = before,
+        WillFlush = yes
+    ;
+        BeforeAfter = after,
+        WillFlush = no
+    ).
+will_flush(not(_), _) = yes.
+will_flush(scope(_, _), _) = no.
+will_flush(shorthand(_), _) = _ :-
+    % These should have been expanded out by now.
+    error("will_flush: unexpected shorthand").
+
 	% Reset the instmap and seen calls for the next branch.
 :- pred simplify_info_post_branch_update(simplify_info::in, simplify_info::in,
 	simplify_info::out) is det.
cvs diff: I know nothing about x.m
--------------------------------------------------------------------------
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