[m-rev.] for review: fix equivalence type performance problems
Simon Taylor
stayl at cs.mu.OZ.AU
Wed Dec 17 23:40:11 AEDT 2003
On 12-Dec-2003, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> On 12-Dec-2003, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> >
> > Fix excessive memory usage caused by the equiv_type_hlds pass.
> >
> > compiler/equiv_type_hlds.m:
> > compiler/equiv_type.m:
> > Maintain sharing in insts in the equiv_type_hlds pass.
> >
> > Avoid duplicating types and insts which do not contain
> > equivalence types to expand. (It should be possible
> > and may be worthwhile to implement a source to source
> > transformation to do this sort of thing automatically.
> > There are plenty of other instances of this in the
> > compiler and library).
> >
> > compiler/make_hlds.m:
> > Change required by the above.
>
> Those parts are fine.
>
> > compiler/mercury_compile.m:
> > Re-enable equiv_type_hlds.m.
> >
> > tests/hard_coded/Mmakefile:
> > Re-enable testing of equiv_type_hlds.m.
>
> I would like to see some performance figures for how much
> it costs to run this extra pass before we re-enable it.
With the extra change below, the equiv_type_hlds pass adds about
5% to compile time, much of that in equiv_type.replace_in_type.
I don't think we can do much better without changing the
representation of types in the compiler.
time mmc -C -I ../library -I ../browser -I ../analysis libs.options
With equiv_type_hlds: 27.1s (user time)
Without equiv_type_hlds: 26.1s
time mmc -C -I ../library -I ../browser -I ../analysis hlds.make_hlds
With equiv_type_hlds: 12.7s
Without equiv_type_hlds: 12.0s
Simon.
--- equiv_type_hlds.m 2003/12/15 11:31:25 1.2
+++ equiv_type_hlds.m 2003/12/15 12:12:58
@@ -318,12 +318,14 @@
proc_info_set_typeclass_info_varmap(TCVarMap, !ProcInfo),
proc_info_goal(!.ProcInfo, Goal0),
- replace_in_goal(EqvMap, Goal0, Goal,
+ replace_in_goal(EqvMap, Goal0, Goal, Changed,
replace_info(!.ModuleInfo, !.PredInfo,
!.ProcInfo, !.TVarSet, !.Cache, no),
replace_info(!:ModuleInfo, !:PredInfo,
!:ProcInfo, !:TVarSet, _XXX, Recompute)),
- proc_info_set_goal(Goal, !ProcInfo),
+ ( Changed = yes, proc_info_set_goal(Goal, !ProcInfo)
+ ; Changed = no
+ ),
( Recompute = yes ->
requantify_proc(!ProcInfo),
@@ -578,71 +580,122 @@
recompute :: bool
).
-:- pred replace_in_goal(eqv_map::in, hlds_goal::in, hlds_goal::out,
- replace_info::in, replace_info::out) is det.
-
-replace_in_goal(EqvMap, GoalExpr0 - GoalInfo0,
- GoalExpr - GoalInfo, !Info) :-
- replace_in_goal_expr(EqvMap, GoalExpr0, GoalExpr, !Info),
+:- pred replace_in_goal(eqv_map::in)
+ `with_type` replacer(hlds_goal, replace_info)
+ `with_inst` replacer.
+
+replace_in_goal(EqvMap, Goal0 @ (GoalExpr0 - GoalInfo0), Goal,
+ Changed, !Info) :-
+ replace_in_goal_expr(EqvMap, GoalExpr0, GoalExpr, Changed0, !Info),
goal_info_get_instmap_delta(GoalInfo0, InstMapDelta0),
TVarSet0 = !.Info ^ tvarset,
Cache0 = !.Info ^ inst_cache,
instmap_delta_map_foldl(
(pred(_::in, Inst0::in, Inst::out,
- {TVarSet1, Cache1}::in,
- {TVarSet2, Cache2}::out) is det :-
- replace_in_inst(EqvMap, Inst0, Inst, _,
+ {Changed1, TVarSet1, Cache1}::in,
+ {Changed1 `or` InstChanged,
+ TVarSet2, Cache2}::out) is det :-
+ replace_in_inst(EqvMap, Inst0, Inst, InstChanged,
TVarSet1, TVarSet2, Cache1, Cache2)
), InstMapDelta0, InstMapDelta,
- {TVarSet0, Cache0}, {TVarSet, Cache}),
- !:Info = (!.Info ^ tvarset := TVarSet)
- ^ inst_cache := Cache,
- goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo).
-
-:- pred replace_in_goal_expr(eqv_map::in,
- hlds_goal_expr::in, hlds_goal_expr::out,
- replace_info::in, replace_info::out) is det.
-
-replace_in_goal_expr(EqvMap, conj(Goals0), conj(Goals), !Info) :-
- list__map_foldl(replace_in_goal(EqvMap), Goals0, Goals, !Info).
-replace_in_goal_expr(EqvMap, par_conj(Goals0), par_conj(Goals), !Info) :-
- list__map_foldl(replace_in_goal(EqvMap), Goals0, Goals, !Info).
-replace_in_goal_expr(EqvMap, disj(Goals0), disj(Goals), !Info) :-
- list__map_foldl(replace_in_goal(EqvMap), Goals0, Goals, !Info).
-replace_in_goal_expr(EqvMap, switch(A, B, Cases0),
- switch(A, B, Cases), !Info) :-
- list__map_foldl(
- (pred(case(ConsId, Goal0)::in, case(ConsId, Goal)::out,
+ {Changed0, TVarSet0, Cache0}, {Changed, TVarSet, Cache}),
+ ( Changed = yes,
+ !:Info = (!.Info ^ tvarset := TVarSet)
+ ^ inst_cache := Cache,
+ goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo),
+ Goal = GoalExpr - GoalInfo
+ ; Changed = no,
+ Goal = Goal0
+ ).
+
+:- pred replace_in_goal_expr(eqv_map::in)
+ `with_type` replacer(hlds_goal_expr, replace_info)
+ `with_inst` replacer.
+
+replace_in_goal_expr(EqvMap, Goal0 @ conj(Goals0), Goal,
+ Changed, !Info) :-
+ replace_in_list(replace_in_goal(EqvMap), Goals0, Goals,
+ Changed, !Info),
+ ( Changed = yes, Goal = conj(Goals)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ par_conj(Goals0), Goal,
+ Changed, !Info) :-
+ replace_in_list(replace_in_goal(EqvMap), Goals0, Goals,
+ Changed, !Info),
+ ( Changed = yes, Goal = par_conj(Goals)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ disj(Goals0), Goal,
+ Changed, !Info) :-
+ replace_in_list(replace_in_goal(EqvMap), Goals0, Goals,
+ Changed, !Info),
+ ( Changed = yes, Goal = disj(Goals)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ switch(A, B, Cases0), Goal,
+ Changed, !Info) :-
+ replace_in_list(
+ (pred((Case0 @ case(ConsId, CaseGoal0))::in, Case::out,
+ CaseChanged::out,
!.Info::in, !:Info::out) is det :-
- replace_in_goal(EqvMap, Goal0, Goal, !Info)
- ), Cases0, Cases, !Info).
-replace_in_goal_expr(EqvMap, not(Goal0), not(Goal), !Info) :-
- replace_in_goal(EqvMap, Goal0, Goal, !Info).
-replace_in_goal_expr(EqvMap, some(A, B, Goal0), some(A, B, Goal), !Info) :-
- replace_in_goal(EqvMap, Goal0, Goal, !Info).
-replace_in_goal_expr(EqvMap, if_then_else(Vars, Cond0, Then0, Else0),
- if_then_else(Vars, Cond, Then, Else), !Info) :-
- replace_in_goal(EqvMap, Cond0, Cond, !Info),
- replace_in_goal(EqvMap, Then0, Then, !Info),
- replace_in_goal(EqvMap, Else0, Else, !Info).
-replace_in_goal_expr(_, call(_, _, _, _, _, _) @ Goal, Goal, !Info).
-replace_in_goal_expr(EqvMap, foreign_proc(_, _, _, _, _, _, _) @ Goal0, Goal,
- !Info) :-
+ replace_in_goal(EqvMap, CaseGoal0, CaseGoal,
+ CaseChanged, !Info),
+ ( CaseChanged = yes, Case = case(ConsId, CaseGoal)
+ ; CaseChanged = no, Case = Case0
+ )
+ ), Cases0, Cases, Changed, !Info),
+ ( Changed = yes, Goal = switch(A, B, Cases)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ not(NegGoal0), Goal, Changed, !Info) :-
+ replace_in_goal(EqvMap, NegGoal0, NegGoal, Changed, !Info),
+ ( Changed = yes, Goal = not(NegGoal)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ some(A, B, SomeGoal0), Goal,
+ Changed, !Info) :-
+ replace_in_goal(EqvMap, SomeGoal0, SomeGoal, Changed, !Info),
+ ( Changed = yes, Goal = some(A, B, SomeGoal)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ if_then_else(Vars, Cond0, Then0, Else0),
+ Goal, Changed, !Info) :-
+ replace_in_goal(EqvMap, Cond0, Cond, Changed1, !Info),
+ replace_in_goal(EqvMap, Then0, Then, Changed2, !Info),
+ replace_in_goal(EqvMap, Else0, Else, Changed3, !Info),
+ Changed = Changed1 `or` Changed2 `or` Changed3,
+ ( Changed = yes, Goal = if_then_else(Vars, Cond, Then, Else)
+ ; Changed = no, Goal = Goal0
+ ).
+replace_in_goal_expr(_, Goal @ call(_, _, _, _, _, _), Goal, no, !Info).
+replace_in_goal_expr(EqvMap, Goal0 @ foreign_proc(_, _, _, _, _, _, _), Goal,
+ Changed, !Info) :-
TVarSet0 = !.Info ^ tvarset,
replace_in_type_list(EqvMap, Goal0 ^ foreign_types, Types,
- _, TVarSet0, TVarSet, no, _),
- !:Info = !.Info ^ tvarset := TVarSet,
- Goal = Goal0 ^ foreign_types := Types.
-replace_in_goal_expr(EqvMap, generic_call(A, B, Modes0, D),
- generic_call(A, B, Modes, D), !Info) :-
+ Changed, TVarSet0, TVarSet, no, _),
+ ( Changed = yes,
+ !:Info = !.Info ^ tvarset := TVarSet,
+ Goal = Goal0 ^ foreign_types := Types
+ ; Changed = no,
+ Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ generic_call(A, B, Modes0, D), Goal,
+ Changed, !Info) :-
TVarSet0 = !.Info ^ tvarset,
Cache0 = !.Info ^ inst_cache,
- replace_in_modes(EqvMap, Modes0, Modes, _,
+ replace_in_modes(EqvMap, Modes0, Modes, Changed,
TVarSet0, TVarSet, Cache0, Cache),
- !:Info = (!.Info ^ tvarset := TVarSet)
- ^ inst_cache := Cache.
-replace_in_goal_expr(EqvMap, unify(Var, _, _, _, _) @ Goal0, Goal, !Info) :-
+ ( Changed = yes,
+ !:Info = (!.Info ^ tvarset := TVarSet)
+ ^ inst_cache := Cache,
+ Goal = generic_call(A, B, Modes, D)
+ ; Changed = no,
+ Goal = Goal0
+ ).
+replace_in_goal_expr(EqvMap, Goal0 @ unify(Var, _, _, _, _), Goal,
+ Changed, !Info) :-
module_info_types(!.Info ^ module_info, Types),
proc_info_vartypes(!.Info ^ proc_info, VarTypes),
map__lookup(VarTypes, Var, VarType),
@@ -663,6 +716,7 @@
type_to_ctor_and_args(VarType, _TypeInfoCtor,
[TypeInfoArgType])
->
+ Changed = yes,
pred_info_set_typevarset(!.Info ^ tvarset,
!.Info ^ pred_info, PredInfo0),
create_poly_info(!.Info ^ module_info,
@@ -701,57 +755,96 @@
hlds_data__get_type_defn_body(TypeDefn, Body),
Body = eqv_type(_)
->
+ Changed = yes,
Goal = conj([]),
!:Info = !.Info ^ recompute := yes
;
Goal0 ^ unify_mode = LMode0 - RMode0,
TVarSet0 = !.Info ^ tvarset,
Cache0 = !.Info ^ inst_cache,
- replace_in_mode(EqvMap, LMode0, LMode, _, TVarSet0, TVarSet1,
- Cache0, Cache1),
- replace_in_mode(EqvMap, RMode0, RMode, _, TVarSet1, TVarSet,
- Cache1, Cache),
+ replace_in_mode(EqvMap, LMode0, LMode, Changed1,
+ TVarSet0, TVarSet1, Cache0, Cache1),
+ replace_in_mode(EqvMap, RMode0, RMode, Changed2,
+ TVarSet1, TVarSet, Cache1, Cache),
!:Info = (!.Info ^ tvarset := TVarSet)
^ inst_cache := Cache,
replace_in_unification(EqvMap, Goal0 ^ unify_kind, Unification,
- !Info),
- Goal = (Goal0 ^ unify_mode := LMode - RMode)
- ^ unify_kind := Unification
+ Changed3, !Info),
+ Changed = Changed1 `or` Changed2 `or` Changed3,
+ ( Changed = yes,
+ Goal = (Goal0 ^ unify_mode := LMode - RMode)
+ ^ unify_kind := Unification
+ ; Changed = no,
+ Goal = Goal0
+ )
).
-replace_in_goal_expr(_, shorthand(_), _, !Info) :-
+replace_in_goal_expr(_, shorthand(_), _, _, !Info) :-
error("replace_in_goal_expr: shorthand").
-:- pred replace_in_unification(eqv_map::in, unification::in, unification::out,
- replace_info::in, replace_info::out) is det.
-
-replace_in_unification(_, assign(_, _) @ Uni, Uni, !Info).
-replace_in_unification(_, simple_test(_, _) @ Uni, Uni, !Info).
-replace_in_unification(EqvMap, complicated_unify(UniMode0, B, C),
- complicated_unify(UniMode, B, C), !Info) :-
- replace_in_uni_mode(EqvMap, UniMode0, UniMode, !Info).
+:- pred replace_in_unification(eqv_map::in)
+ `with_type` replacer(unification, replace_info)
+ `with_inst` replacer.
+
+replace_in_unification(_, assign(_, _) @ Uni, Uni, no, !Info).
+replace_in_unification(_, simple_test(_, _) @ Uni, Uni, no, !Info).
+replace_in_unification(EqvMap, Uni0 @ complicated_unify(UniMode0, B, C), Uni,
+ Changed, !Info) :-
+ replace_in_uni_mode(EqvMap, UniMode0, UniMode, Changed, !Info),
+ ( Changed = yes, Uni = complicated_unify(UniMode, B, C)
+ ; Changed = no, Uni = Uni0
+ ).
replace_in_unification(EqvMap, construct(_, _, _, _, _, _, _) @ Uni0, Uni,
- !Info) :-
- list__map_foldl(replace_in_uni_mode(EqvMap),
- Uni0 ^ construct_arg_modes, UniModes, !Info),
- Uni = Uni0 ^ construct_arg_modes := UniModes.
+ Changed, !Info) :-
+ replace_in_list(replace_in_uni_mode(EqvMap),
+ Uni0 ^ construct_arg_modes, UniModes, Changed, !Info),
+ ( Changed = yes, Uni = Uni0 ^ construct_arg_modes := UniModes
+ ; Changed = no, Uni = Uni0
+ ).
replace_in_unification(EqvMap, deconstruct(_, _, _, _, _, _) @ Uni0, Uni,
- !Info) :-
- list__map_foldl(replace_in_uni_mode(EqvMap),
- Uni0 ^ deconstruct_arg_modes, UniModes, !Info),
- Uni = Uni0 ^ deconstruct_arg_modes := UniModes.
+ Changed, !Info) :-
+ replace_in_list(replace_in_uni_mode(EqvMap),
+ Uni0 ^ deconstruct_arg_modes, UniModes, Changed, !Info),
+ ( Changed = yes, Uni = Uni0 ^ deconstruct_arg_modes := UniModes
+ ; Changed = no, Uni = Uni0
+ ).
-:- pred replace_in_uni_mode(eqv_map::in, uni_mode::in, uni_mode::out,
- replace_info::in, replace_info::out) is det.
+:- pred replace_in_uni_mode(eqv_map::in)
+ `with_type` replacer(uni_mode, replace_info)
+ `with_inst` replacer.
replace_in_uni_mode(EqvMap, ((InstA0 - InstB0) -> (InstC0 - InstD0)),
- ((InstA - InstB) -> (InstC - InstD)), !Info) :-
+ ((InstA - InstB) -> (InstC - InstD)), Changed, !Info) :-
some [!TVarSet, !Cache] (
!:TVarSet = !.Info ^ tvarset,
!:Cache = !.Info ^ inst_cache,
- replace_in_inst(EqvMap, InstA0, InstA, _, !TVarSet, !Cache),
- replace_in_inst(EqvMap, InstB0, InstB, _, !TVarSet, !Cache),
- replace_in_inst(EqvMap, InstC0, InstC, _, !TVarSet, !Cache),
- replace_in_inst(EqvMap, InstD0, InstD, _, !TVarSet, !Cache),
- !:Info = (!.Info ^ tvarset := !.TVarSet)
- ^ inst_cache := !.Cache
+ replace_in_inst(EqvMap, InstA0, InstA,
+ Changed1, !TVarSet, !Cache),
+ replace_in_inst(EqvMap, InstB0, InstB,
+ Changed2, !TVarSet, !Cache),
+ replace_in_inst(EqvMap, InstC0, InstC,
+ Changed3, !TVarSet, !Cache),
+ replace_in_inst(EqvMap, InstD0, InstD,
+ Changed4, !TVarSet, !Cache),
+ Changed = Changed1 `or` Changed2 `or` Changed3 `or` Changed4,
+ ( Changed = yes,
+ !:Info = (!.Info ^ tvarset := !.TVarSet)
+ ^ inst_cache := !.Cache
+ ; Changed = no
+ )
+ ).
+
+:- type replacer(T, Acc) == pred(T, T, bool, Acc, Acc).
+:- inst replacer == (pred(in, out, out, in, out) is det).
+
+:- pred replace_in_list(replacer(T, Acc)::in(replacer))
+ `with_type` replacer(list(T), Acc) `with_inst` replacer.
+
+replace_in_list(_, [], [], no, !Acc).
+replace_in_list(Repl, List0 @ [H0 | T0], List, Changed, !Acc) :-
+ replace_in_list(Repl, T0, T, Changed0, !Acc),
+ Repl(H0, H, Changed1, !Acc),
+ Changed = Changed0 `or` Changed1,
+ ( Changed = yes, List = [H | T]
+ ; Changed = no, List = List0
).
+
--------------------------------------------------------------------------
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