[m-rev.] diff: hlds_statistics.m

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


For post-commit review by anyone.

Zoltan.

Add a new option, --proc-size-statistics <filename>. When specified, the
compiler will append statistics about the sizes of procedures to the named
file.

compiler/hlds_statistics.m:
	New module that does this.

compiler/options.m:
doc/user_guide.texi:
	Document the new option.

compiler/mercury_compile_front_end.m:
	Invoke the code to gather and print statistics if the option is
	specified.

compiler/hlds_pred.m:
	Improve the style of some old code.


cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds.m,v
retrieving revision 1.226
diff -u -b -r1.226 hlds.m
--- compiler/hlds.m	14 Oct 2009 05:28:33 -0000	1.226
+++ compiler/hlds.m	3 Feb 2010 23:05:39 -0000
@@ -54,6 +54,7 @@
 :- include_module mark_static_terms.
 :- include_module mark_tail_calls.
 :- include_module passes_aux.
+:- include_module hlds_statistics.
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.255
diff -u -b -r1.255 hlds_pred.m
--- compiler/hlds_pred.m	4 Sep 2009 02:27:51 -0000	1.255
+++ compiler/hlds_pred.m	3 Feb 2010 23:05:39 -0000
@@ -1390,9 +1390,9 @@
         PredInfo ^ exist_quant_tvars, PredInfo ^ arg_types).
 
 pred_info_set_arg_types(TypeVarSet, ExistQVars, ArgTypes, !PredInfo) :-
-    !:PredInfo = !.PredInfo ^ decl_typevarset := TypeVarSet,
-    !:PredInfo = !.PredInfo ^ exist_quant_tvars := ExistQVars,
-    !:PredInfo = !.PredInfo ^ arg_types := ArgTypes.
+    !PredInfo ^ decl_typevarset := TypeVarSet,
+    !PredInfo ^ exist_quant_tvars := ExistQVars,
+    !PredInfo ^ arg_types := ArgTypes.
 
 pred_info_proc_info(PredInfo, ProcId, ProcInfo) :-
     ProcInfo = map.lookup(PredInfo ^ procedures, ProcId).
@@ -2521,11 +2521,11 @@
         RttiVarMaps, eval_normal, ProcSubInfo).
 
 proc_info_set_body(VarSet, VarTypes, HeadVars, Goal, RttiVarMaps, !ProcInfo) :-
-    !:ProcInfo = !.ProcInfo ^ prog_varset := VarSet,
-    !:ProcInfo = !.ProcInfo ^ var_types := VarTypes,
-    !:ProcInfo = !.ProcInfo ^ head_vars := HeadVars,
-    !:ProcInfo = !.ProcInfo ^ body := Goal,
-    !:ProcInfo = !.ProcInfo ^ proc_rtti_varmaps := RttiVarMaps.
+    !ProcInfo ^ prog_varset := VarSet,
+    !ProcInfo ^ var_types := VarTypes,
+    !ProcInfo ^ head_vars := HeadVars,
+    !ProcInfo ^ body := Goal,
+    !ProcInfo ^ proc_rtti_varmaps := RttiVarMaps.
 
 proc_info_get_context(PI, PI ^ proc_context).
 proc_info_get_varset(PI, PI ^ prog_varset).
@@ -2698,16 +2698,15 @@
     Termination2Info = ProcInfo ^ proc_sub_info ^ termination2.
 
 proc_info_set_termination2_info(Termination2Info, !ProcInfo) :-
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ termination2 :=
-        Termination2Info.
+    !ProcInfo ^ proc_sub_info ^ termination2 := Termination2Info.
 
 proc_info_get_structure_sharing(ProcInfo, MaybeSharing) :-
     MaybeSharing = ProcInfo ^ proc_sub_info ^ structure_sharing
         ^ maybe_sharing.
 
 proc_info_set_structure_sharing(Sharing, !ProcInfo) :-
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ structure_sharing
-        ^ maybe_sharing := yes(Sharing).
+    !ProcInfo ^ proc_sub_info ^ structure_sharing ^ maybe_sharing :=
+        yes(Sharing).
 
 proc_info_get_imported_structure_sharing(ProcInfo, HeadVars, Types, Sharing) :-
     MaybeImportedSharing = ProcInfo ^ proc_sub_info ^ structure_sharing
@@ -2719,19 +2718,18 @@
         !ProcInfo) :-
     ImportedSharing = imported_sharing(HeadVars, Types, Sharing),
     MaybeImportedSharing = yes(ImportedSharing),
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ structure_sharing
-        ^ maybe_imported_sharing := MaybeImportedSharing.
+    !ProcInfo ^ proc_sub_info ^ structure_sharing ^ maybe_imported_sharing :=
+        MaybeImportedSharing.
 
 proc_info_reset_imported_structure_sharing(!ProcInfo) :-
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ structure_sharing
-        ^ maybe_imported_sharing := no.
+    !ProcInfo ^ proc_sub_info ^ structure_sharing ^ maybe_imported_sharing :=
+        no.
 
 proc_info_get_structure_reuse(ProcInfo, MaybeReuse) :-
     MaybeReuse = ProcInfo ^ proc_sub_info ^ structure_reuse ^ maybe_reuse.
 
 proc_info_set_structure_reuse(Reuse, !ProcInfo) :-
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ structure_reuse
-        ^ maybe_reuse := yes(Reuse).
+    !ProcInfo ^ proc_sub_info ^ structure_reuse ^ maybe_reuse := yes(Reuse).
 
 proc_info_get_imported_structure_reuse(ProcInfo, HeadVars, Types, Reuse) :-
     MaybeImportedReuse = ProcInfo ^ proc_sub_info ^ structure_reuse
@@ -2743,12 +2741,11 @@
         !ProcInfo) :-
     ImportedReuse = imported_reuse(HeadVars, Types, Reuse),
     MaybeImportedReuse = yes(ImportedReuse),
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ structure_reuse
-        ^ maybe_imported_reuse := MaybeImportedReuse.
+    !ProcInfo ^ proc_sub_info ^ structure_reuse ^ maybe_imported_reuse :=
+        MaybeImportedReuse.
 
 proc_info_reset_imported_structure_reuse(!ProcInfo) :-
-    !:ProcInfo = !.ProcInfo ^ proc_sub_info ^ structure_reuse
-        ^ maybe_imported_reuse := no.
+    !ProcInfo ^ proc_sub_info ^ structure_reuse ^ maybe_imported_reuse := no.
 
 proc_info_ensure_unique_names(!ProcInfo) :-
     proc_info_get_vartypes(!.ProcInfo, VarTypes),
Index: compiler/hlds_statistics.m
===================================================================
RCS file: compiler/hlds_statistics.m
diff -N compiler/hlds_statistics.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/hlds_statistics.m	3 Feb 2010 23:05:39 -0000
@@ -0,0 +1,450 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2010 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: hlds_statistics.m.
+% Author: zs.
+%
+% Write out statistics about various aspects of the HLDS.
+%
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- module hlds.hlds_statistics.
+:- interface.
+
+:- import_module hlds.hlds_module.
+:- import_module io.
+
+    % Write out size statistics about each procedure in the module.
+    % The statistics state the size of the procedure's body (the number of
+    % subgoals of each possible kind) and the number of its variables.
+    %
+:- pred write_proc_stats_for_module(io.output_stream::in, string::in,
+    module_info::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds.hlds_goal.
+:- import_module hlds.hlds_pred.
+:- import_module hlds.hlds_error_util.
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.error_util.
+:- import_module parse_tree.prog_data.
+
+:- import_module int.
+:- import_module list.
+:- import_module map.
+:- import_module pair.
+:- import_module set_tree234.
+:- import_module string.
+:- import_module term.
+:- import_module varset.
+
+%-----------------------------------------------------------------------------%
+
+write_proc_stats_for_module(OutStream, Msg, ModuleInfo, !IO) :-
+    module_info_get_name(ModuleInfo, ModuleSymName),
+    ModuleName = sym_name_to_string(ModuleSymName),
+    io.format(OutStream, "MODULE %s\n", [s(ModuleName)], !IO),
+
+    module_info_preds(ModuleInfo, PredTable),
+    map.to_assoc_list(PredTable, Preds),
+    list.foldl(write_proc_stats_for_pred(OutStream, Msg, ModuleInfo),
+        Preds, !IO).
+
+:- pred write_proc_stats_for_pred(io.output_stream::in, string::in,
+    module_info::in, pair(pred_id, pred_info)::in, io::di, io::uo) is det.
+
+write_proc_stats_for_pred(OutStream, Msg, ModuleInfo, PredId - PredInfo, !IO) :-
+    (
+        ( pred_info_is_imported(PredInfo)
+        ; is_unify_or_compare_pred(PredInfo)
+        )
+    ->
+        true
+    ;
+        pred_info_get_procedures(PredInfo, ProcTable),
+        map.to_assoc_list(ProcTable, Procs),
+        list.foldl(
+            write_proc_stats_for_proc(OutStream, Msg, ModuleInfo, PredId),
+            Procs, !IO)
+    ).
+
+:- pred write_proc_stats_for_proc(io.output_stream::in, string::in,
+    module_info::in, pred_id::in, pair(proc_id, proc_info)::in,
+    io::di, io::uo) is det.
+
+write_proc_stats_for_proc(OutStream, Msg, ModuleInfo,
+        PredId, ProcId - ProcInfo, !IO) :-
+    NamePieces = describe_one_proc_name(ModuleInfo, should_not_module_qualify,
+        proc(PredId, ProcId)),
+    Name = error_pieces_to_string(NamePieces),
+
+    proc_info_get_goal(ProcInfo, Goal),
+    UsedVars0 = set_tree234.init,
+    Stats0 = init_proc_stats,
+    accumulate_proc_stats_in_goal(Goal, UsedVars0, UsedVars, Stats0, Stats),
+
+    proc_info_get_varset(ProcInfo, VarSet),
+    do_write_proc_stats(OutStream, Msg, Name, PredId, ProcId, Stats,
+        UsedVars, VarSet, !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- pred accumulate_proc_stats_in_goal(hlds_goal::in,
+    set_tree234(prog_var)::in, set_tree234(prog_var)::out,
+    proc_stats::in, proc_stats::out) is det.
+
+accumulate_proc_stats_in_goal(Goal, !UsedVars, !Stats) :-
+    Goal = hlds_goal(GoalExpr, _GoalInfo),
+    (
+        GoalExpr = unify(LHS, RHS, _, Uni, _),
+        (
+            Uni = construct(CellVar, _, ArgVars, _, _, _, _),
+            set_tree234.insert(CellVar, !UsedVars),
+            set_tree234.insert_list(ArgVars, !UsedVars),
+            !Stats ^ ps_unify_constructs := !.Stats ^ ps_unify_constructs + 1
+        ;
+            Uni = deconstruct(CellVar, _, ArgVars, _, _, _),
+            set_tree234.insert(CellVar, !UsedVars),
+            set_tree234.insert_list(ArgVars, !UsedVars),
+            !Stats ^ ps_unify_deconstructs :=
+                !.Stats ^ ps_unify_deconstructs + 1
+        ;
+            Uni = assign(ToVar, FromVar),
+            set_tree234.insert(ToVar, !UsedVars),
+            set_tree234.insert(FromVar, !UsedVars),
+            !Stats ^ ps_unify_assigns := !.Stats ^ ps_unify_assigns + 1
+        ;
+            Uni = simple_test(VarA, VarB),
+            set_tree234.insert(VarA, !UsedVars),
+            set_tree234.insert(VarB, !UsedVars),
+            !Stats ^ ps_unify_tests := !.Stats ^ ps_unify_tests + 1
+        ;
+            Uni = complicated_unify(_, _, _),
+            set_tree234.insert(LHS, !UsedVars),
+            (
+                RHS = rhs_var(RHSVar),
+                set_tree234.insert(RHSVar, !UsedVars),
+                !Stats ^ ps_unify_complicateds :=
+                    !.Stats ^ ps_unify_complicateds + 1
+            ;
+                RHS = rhs_functor(_, _, RHSVars),
+                set_tree234.insert_list(RHSVars, !UsedVars),
+                !Stats ^ ps_unify_complicateds :=
+                    !.Stats ^ ps_unify_complicateds + 1
+            ;
+                RHS = rhs_lambda_goal(_, _, _, _, NonLocals, QuantVars, _, _,
+                    LambdaGoal),
+                set_tree234.insert_list(NonLocals, !UsedVars),
+                set_tree234.insert_list(QuantVars, !UsedVars),
+                !Stats ^ ps_unify_complicateds :=
+                    !.Stats ^ ps_unify_complicateds + 1,
+                accumulate_proc_stats_in_goal(LambdaGoal, !UsedVars, !Stats)
+            )
+        )
+    ;
+        GoalExpr = plain_call(_, _, ArgVars, _, _, _),
+        set_tree234.insert_list(ArgVars, !UsedVars),
+        !Stats ^ ps_plain_calls := !.Stats ^ ps_plain_calls + 1
+    ;
+        GoalExpr = call_foreign_proc(_, _, _, Args, ExtraArgs, _, _),
+        ArgVars = list.map(foreign_arg_var, Args),
+        ExtraArgVars = list.map(foreign_arg_var, ExtraArgs),
+        set_tree234.insert_list(ArgVars, !UsedVars),
+        set_tree234.insert_list(ExtraArgVars, !UsedVars),
+        !Stats ^ ps_foreign_calls := !.Stats ^ ps_foreign_calls + 1
+    ;
+        GoalExpr = generic_call(CallKind, ArgVars, _, _),
+        set_tree234.insert_list(ArgVars, !UsedVars),
+        (
+            CallKind = higher_order(HOVar, _, _, _),
+            set_tree234.insert(HOVar, !UsedVars),
+            !Stats ^ ps_ho_calls := !.Stats ^ ps_ho_calls + 1
+        ;
+            CallKind = class_method(TCIVar, _, _, _),
+            set_tree234.insert(TCIVar, !UsedVars),
+            !Stats ^ ps_method_calls := !.Stats ^ ps_method_calls + 1
+        ;
+            CallKind = event_call(_),
+            !Stats ^ ps_event_calls := !.Stats ^ ps_event_calls + 1
+        ;
+            CallKind = cast(_),
+            !Stats ^ ps_casts := !.Stats ^ ps_casts + 1
+        )
+    ;
+        GoalExpr = conj(ConjType, Conjs),
+        (
+            ConjType = plain_conj,
+            !Stats ^ ps_plain_conjs := !.Stats ^ ps_plain_conjs + 1,
+            accumulate_proc_stats_in_plain_conj(Conjs, !UsedVars, !Stats)
+        ;
+            ConjType = parallel_conj,
+            !Stats ^ ps_parallel_conjs := !.Stats ^ ps_parallel_conjs + 1,
+            accumulate_proc_stats_in_parallel_conj(Conjs, !UsedVars, !Stats)
+        )
+    ;
+        GoalExpr = disj(Disjs),
+        !Stats ^ ps_disjs := !.Stats ^ ps_disjs + 1,
+        accumulate_proc_stats_in_disj(Disjs, !UsedVars, !Stats)
+    ;
+        GoalExpr = switch(SwitchVar, _, Cases),
+        set_tree234.insert(SwitchVar, !UsedVars),
+        !Stats ^ ps_switches := !.Stats ^ ps_switches + 1,
+        accumulate_proc_stats_in_switch(Cases, !UsedVars, !Stats)
+    ;
+        GoalExpr = if_then_else(_, CondGoal, ThenGoal, ElseGoal),
+        !Stats ^ ps_ites := !.Stats ^ ps_ites + 1,
+        accumulate_proc_stats_in_goal(CondGoal, !UsedVars, !Stats),
+        accumulate_proc_stats_in_goal(ThenGoal, !UsedVars, !Stats),
+        accumulate_proc_stats_in_goal(ElseGoal, !UsedVars, !Stats)
+    ;
+        GoalExpr = negation(SubGoal),
+        !Stats ^ ps_negations := !.Stats ^ ps_negations + 1,
+        accumulate_proc_stats_in_goal(SubGoal, !UsedVars, !Stats)
+    ;
+        GoalExpr = scope(_, SubGoal),
+        !Stats ^ ps_scopes := !.Stats ^ ps_scopes + 1,
+        accumulate_proc_stats_in_goal(SubGoal, !UsedVars, !Stats)
+    ;
+        GoalExpr = shorthand(ShortHand),
+        (
+            ShortHand = bi_implication(GoalA, GoalB),
+            !Stats ^ ps_bi_implications := !.Stats ^ ps_bi_implications + 1,
+            accumulate_proc_stats_in_goal(GoalA, !UsedVars, !Stats),
+            accumulate_proc_stats_in_goal(GoalB, !UsedVars, !Stats)
+        ;
+            ShortHand = atomic_goal(_, _, _, _, MainGoal, OrElseGoals, _),
+            !Stats ^ ps_atomic_goals := !.Stats ^ ps_atomic_goals + 1,
+            accumulate_proc_stats_in_goal(MainGoal, !UsedVars, !Stats),
+            list.foldl2(accumulate_proc_stats_in_goal, OrElseGoals,
+                !UsedVars, !Stats)
+        ;
+            ShortHand = try_goal(_, _, SubGoal),
+            !Stats ^ ps_try_goals := !.Stats ^ ps_try_goals + 1,
+            accumulate_proc_stats_in_goal(SubGoal, !UsedVars, !Stats)
+        )
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred accumulate_proc_stats_in_plain_conj(list(hlds_goal)::in,
+    set_tree234(prog_var)::in, set_tree234(prog_var)::out,
+    proc_stats::in, proc_stats::out) is det.
+
+accumulate_proc_stats_in_plain_conj([], !UsedVars, !Stats).
+accumulate_proc_stats_in_plain_conj([Goal | Goals], !UsedVars, !Stats) :-
+    !Stats ^ ps_plain_conjuncts := !.Stats ^ ps_plain_conjuncts + 1,
+    accumulate_proc_stats_in_goal(Goal, !UsedVars, !Stats),
+    accumulate_proc_stats_in_plain_conj(Goals, !UsedVars, !Stats).
+
+:- pred accumulate_proc_stats_in_parallel_conj(list(hlds_goal)::in,
+    set_tree234(prog_var)::in, set_tree234(prog_var)::out,
+    proc_stats::in, proc_stats::out) is det.
+
+accumulate_proc_stats_in_parallel_conj([], !UsedVars, !Stats).
+accumulate_proc_stats_in_parallel_conj([Goal | Goals], !UsedVars, !Stats) :-
+    !Stats ^ ps_parallel_conjuncts := !.Stats ^ ps_parallel_conjuncts + 1,
+    accumulate_proc_stats_in_goal(Goal, !UsedVars, !Stats),
+    accumulate_proc_stats_in_parallel_conj(Goals, !UsedVars, !Stats).
+
+:- pred accumulate_proc_stats_in_disj(list(hlds_goal)::in,
+    set_tree234(prog_var)::in, set_tree234(prog_var)::out,
+    proc_stats::in, proc_stats::out) is det.
+
+accumulate_proc_stats_in_disj([], !UsedVars, !Stats).
+accumulate_proc_stats_in_disj([Goal | Goals], !UsedVars, !Stats) :-
+    !Stats ^ ps_disjuncts := !.Stats ^ ps_disjuncts + 1,
+    accumulate_proc_stats_in_goal(Goal, !UsedVars, !Stats),
+    accumulate_proc_stats_in_disj(Goals, !UsedVars, !Stats).
+
+:- pred accumulate_proc_stats_in_switch(list(case)::in,
+    set_tree234(prog_var)::in, set_tree234(prog_var)::out,
+    proc_stats::in, proc_stats::out) is det.
+
+accumulate_proc_stats_in_switch([], !UsedVars, !Stats).
+accumulate_proc_stats_in_switch([Case | Cases], !UsedVars, !Stats) :-
+    !Stats ^ ps_switch_arms := !.Stats ^ ps_switch_arms + 1,
+    Case = case(_, _, Goal),
+    accumulate_proc_stats_in_goal(Goal, !UsedVars, !Stats),
+    accumulate_proc_stats_in_switch(Cases, !UsedVars, !Stats).
+
+%-----------------------------------------------------------------------------%
+
+:- type proc_stats
+    --->    proc_stats(
+                ps_unify_constructs     :: int,
+                ps_unify_deconstructs   :: int,
+                ps_unify_assigns        :: int,
+                ps_unify_tests          :: int,
+                ps_unify_complicateds   :: int,
+
+                ps_plain_calls          :: int,
+
+                ps_foreign_calls        :: int,
+
+                ps_ho_calls             :: int,
+                ps_method_calls         :: int,
+                ps_event_calls          :: int,
+                ps_casts                :: int,
+
+                ps_plain_conjs          :: int,
+                ps_plain_conjuncts      :: int,
+                ps_parallel_conjs       :: int,
+                ps_parallel_conjuncts   :: int,
+
+                ps_disjs                :: int,
+                ps_disjuncts            :: int,
+
+                ps_switches             :: int,
+                ps_switch_arms          :: int,
+
+                ps_ites                 :: int,
+
+                ps_negations            :: int,
+
+                ps_scopes               :: int,
+
+                ps_bi_implications      :: int,
+                ps_atomic_goals         :: int,
+                ps_try_goals            :: int
+            ).
+
+:- func init_proc_stats = proc_stats.
+
+init_proc_stats = Stats :-
+    Stats = proc_stats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
+
+:- pred write_proc_stat_components(io.output_stream::in, string::in,
+    string::in, pred_id::in, proc_id::in, proc_stats::in, io::di, io::uo)
+    is det.
+
+write_proc_stat_components(OutStream, Msg, Name, PredId, ProcId, Stats, !IO) :-
+    Stats = proc_stats(UnifyConstructs, UnifyDeconstructs,
+        UnifyAssigns, UnifyTests, UnifyComplicateds,
+        PlainCalls, ForeignCalls, HOCalls, MethodCalls, EventCalls, Casts,
+        PlainConjs, PlainConjuncts, ParallelConjs, ParallelConjuncts,
+        Disjs, Disjuncts, Switches, SwitchArms,
+        IfThenElses, Negations, Scopes, BiImplications, AtomicGoals, TryGoals),
+
+    Total =
+        UnifyConstructs + UnifyDeconstructs +
+        UnifyAssigns + UnifyTests + UnifyComplicateds +
+        PlainCalls + ForeignCalls +
+        HOCalls + MethodCalls + EventCalls + Casts +
+        PlainConjs + ParallelConjs +
+        Disjs + Switches +
+        IfThenElses + Negations + Scopes +
+        BiImplications + AtomicGoals + TryGoals,
+
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "unify_contructs", UnifyConstructs, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "unify_decontructs", UnifyDeconstructs, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "unify_assigns", UnifyAssigns, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "unify_tests", UnifyTests, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "unify_complicateds", UnifyComplicateds, !IO),
+
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "plain_calls", PlainCalls, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "foreign_calls", ForeignCalls, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "ho_calls", HOCalls, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "method_calls", MethodCalls, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "event_calls", EventCalls, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "casts", Casts, !IO),
+
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "plain_conjs", PlainConjs, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "plain_conjuncts", PlainConjuncts, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "parallel_conjs", ParallelConjs, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "parallel_conjuncts", ParallelConjuncts, !IO),
+
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "disjs", Disjs, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "disjunctions", Disjuncts, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "switches", Switches, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "switch_arms", SwitchArms, !IO),
+
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "if_then_elses", IfThenElses, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "negations", Negations, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "scopes", Scopes, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "bi_implications", BiImplications, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "atomic_goals", AtomicGoals, !IO),
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "try_goals", TryGoals, !IO),
+
+    output_proc_stat_component(OutStream, Msg, Name, PredId, ProcId,
+        "total_size", Total, !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- pred do_write_proc_stats(io.output_stream::in,
+    string::in, string::in, pred_id::in, proc_id::in,
+    proc_stats::in, set_tree234(prog_var)::in, prog_varset::in,
+    io::di, io::uo) is det.
+
+do_write_proc_stats(OutStream, Msg, Name, PredId, ProcId,
+        Stats, UsedVars, VarSet, !IO) :-
+    PredIdInt = pred_id_to_int(PredId),
+    ProcIdInt = proc_id_to_int(ProcId),
+    io.format(OutStream, "PROC %d %d %s\n",
+        [i(PredIdInt), i(ProcIdInt), s(Name)], !IO),
+
+    write_proc_stat_components(OutStream, Msg, Name, PredId, ProcId, Stats,
+        !IO),
+
+    varset.new_var(VarSet, Var, _UpdatedVarSet),
+    term.var_to_int(Var, VarInt),
+    NumUsedVars = set_tree234.count(UsedVars),
+    io.format(OutStream, "VARS %d %d\n", [i(VarInt), i(NumUsedVars)], !IO).
+
+:- pred output_proc_stat_component(io.output_stream::in,
+    string::in, string::in, pred_id::in, proc_id::in,
+    string::in, int::in, io::di, io::uo) is det.
+
+output_proc_stat_component(OutStream, _Msg, _Name, _PredId, _ProcId,
+        ComponentName, ComponentCount, !IO) :-
+    ( ComponentCount > 0 ->
+        io.format(OutStream, "GOAL %s: %d\n",
+            [s(ComponentName), i(ComponentCount)], !IO)
+    ;
+        true
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "hlds_statistics.m".
+
+%-----------------------------------------------------------------------------%
+:- end_module hlds.hlds_statistics.
+%-----------------------------------------------------------------------------%
Index: compiler/mercury_compile_front_end.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile_front_end.m,v
retrieving revision 1.2
diff -u -b -r1.2 mercury_compile_front_end.m
--- compiler/mercury_compile_front_end.m	16 Oct 2009 06:53:01 -0000	1.2
+++ compiler/mercury_compile_front_end.m	3 Feb 2010 23:05:39 -0000
@@ -86,6 +86,7 @@
 :- import_module check_hlds.unique_modes.
 :- import_module check_hlds.unused_imports.
 :- import_module hlds.hlds_error_util.
+:- import_module hlds.hlds_statistics.
 :- import_module libs.compiler_util.
 :- import_module libs.file_util.
 :- import_module libs.globals.
@@ -468,6 +469,9 @@
             !HLDS, !Specs, !IO),
         maybe_dump_hlds(!.HLDS, 65, "frontend_simplify", !DumpInfo, !IO),
 
+        maybe_proc_statistics(Verbose, Stats, "AfterFrontEnd", !HLDS,
+            !Specs, !IO),
+
         % Work out whether we encountered any errors.
         module_info_get_num_errors(!.HLDS, NumErrors),
         io.get_exit_status(ExitStatus, !IO),
@@ -866,8 +870,7 @@
             ->
                 list.cons(simp_constant_prop, !SimpList)
             ;
-                !:SimpList = list.delete_all(!.SimpList,
-                    simp_constant_prop)
+                !:SimpList = list.delete_all(!.SimpList, simp_constant_prop)
             ),
             list.cons(simp_do_once, !SimpList),
             list.cons(simp_elim_removable_scopes, !SimpList)
@@ -901,6 +904,37 @@
         SimpList = []
     ).
 
+:- pred maybe_proc_statistics(bool::in, bool::in, string::in,
+    module_info::in, module_info::out,
+    list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
+
+maybe_proc_statistics(Verbose, Stats, Msg, !HLDS, !Specs, !IO) :-
+    module_info_get_globals(!.HLDS, Globals),
+    maybe_write_out_errors(Verbose, Globals, !HLDS, !Specs, !IO),
+
+    globals.lookup_string_option(Globals, proc_size_statistics, StatsFileName),
+    ( StatsFileName = "" ->
+        % The user has not asked us to print these statistics.
+        true
+    ;
+        io.open_append(StatsFileName, StatsFileNameResult, !IO),
+        (
+            StatsFileNameResult = ok(StatsFileStream),
+            maybe_write_string(Verbose,
+                "% Generating proc statistics...\n", !IO),
+            write_proc_stats_for_module(StatsFileStream, Msg, !.HLDS, !IO),
+            maybe_write_string(Verbose, "% done.\n", !IO),
+            maybe_report_stats(Stats, !IO)
+        ;
+            StatsFileNameResult = error(StatsFileError),
+            io.error_message(StatsFileError, StatsFileErrorMsg),
+            maybe_write_string(Verbose,
+                "% Cannot write proc statistics: ", !IO),
+            maybe_write_string(Verbose, StatsFileErrorMsg, !IO),
+            maybe_write_string(Verbose, "\n", !IO)
+        )
+    ).
+
 %-----------------------------------------------------------------------------%
 
 :- func this_file = string.
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.666
diff -u -b -r1.666 options.m
--- compiler/options.m	28 Jan 2010 04:32:03 -0000	1.666
+++ compiler/options.m	3 Feb 2010 23:05:39 -0000
@@ -148,6 +148,7 @@
     ;       output_compile_error_lines
     ;       statistics
     ;       detailed_statistics
+    ;       proc_size_statistics
     ;       debug_types
     ;       debug_modes
     ;       debug_modes_statistics
@@ -1082,6 +1083,7 @@
     output_compile_error_lines          -   int(15),
     statistics                          -   bool(no),
     detailed_statistics                 -   bool(no),
+    proc_size_statistics                -   string(""),
     debug_types                         -   bool(no),
     debug_modes                         -   bool(no),
     debug_modes_statistics              -   bool(no),
@@ -1909,6 +1911,7 @@
 long_option("output-compile-error-lines",   output_compile_error_lines).
 long_option("statistics",               statistics).
 long_option("detailed-statistics",      detailed_statistics).
+long_option("proc-size-statistics",     proc_size_statistics).
 long_option("debug-types",              debug_types).
 long_option("debug-modes",              debug_modes).
 long_option("debug-modes-statistics",   debug_modes_statistics).
@@ -3442,6 +3445,9 @@
 %       "--detailed-statistics",
 %       "\tOutput more detailed messages about the compiler's",
 %       "\ttime/space usage.",
+        "--proc-size-statistics <filename>",
+        "\tAppend information about the size of each procedure in the module",
+        "\tin terms of goals and variables to the end of the named file.",
 % --debug-types works only if the compiler was compiled with
 % "--trace-flag type_checkpoint".
 %       "-T, --debug-types",
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.602
diff -u -b -r1.602 user_guide.texi
--- doc/user_guide.texi	28 Jan 2010 04:05:07 -0000	1.602
+++ doc/user_guide.texi	3 Feb 2010 23:05:39 -0000
@@ -6496,6 +6496,12 @@
 @findex --no-trad-passes
 @findex --trad-passes
 
+ at sp 1
+ at item --proc-size-statistics @var{filename}
+ at findex --proc-size-statistics
+Append information about the size of each procedure in the module
+in terms of goals and variables to the end of the named file.
+
 @c @sp 1
 @c @item -T
 @c @itemx --debug-types
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list