[m-rev.] For review: Filling in rbmm_goal_info field in goal_info

Quan Phan quan.phan at cs.kuleuven.be
Thu Sep 6 09:20:12 AEST 2007


Hi Julien,

I post everything again with the new diff.

Estimated hours taken: 15h.
Branch: main.

Implement a pass to fill in the rbmm_goal_info field in the goal_info
data structure. (Zoltan added this field several days ago.) This piece of
information will be used by the code generator to optimize the runtime support
needed for region-based memory management. It would be too much to describe
how the information will be used here. I am writing up the runtime support
needed for RBMM as the whole, which should include the explanation for this.

compiler/rbmm.add_rbmm_goal_infos.m:
	New file that contains the implementation of the pass.

compiler/hlds_goal.m:
	Add a function that initialize the rbmm_goal_info.

compiler/hlds_out.m:
	Add an option, 'e' to --dump-hlds-options to print out rbmm_goal_info.

compiler/rbmm.m:
	Include the new module and call the analysis.

compiler/rbmm.actual_region_arguments.m:
	Change the data structure that represents actual region arguments to
	have there separate lists for constant (carried), input (removed), and
	output (created) regions.

compiler/type_util.m:
	Add a predicate that check whether the terms of a type will be stored
	in regions or not. This predicate must be consistent with the process
	of generating allocations in unify_gen.m.

compiler/rbmm.interproc_region_lifetime.m:
	Change to use the new predicate in type_util.m.

compiler/rbmm.region_transformation.m:
	Change to conform to the change in actual_region_arguments.m.
	Change to use the new predicate in type_util.m

doc/user_guide.texi:
	Document the new option for --dump-hlds-options.
	Provide the missing description for the existing option 'R'.

Regards,
Quan.


-------------- next part --------------
cvs diff: Diffing .
Index: hlds_goal.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.180
diff -u -r1.180 hlds_goal.m
--- hlds_goal.m	7 Aug 2007 07:09:54 -0000	1.180
+++ hlds_goal.m	5 Sep 2007 18:46:00 -0000
@@ -882,6 +882,8 @@
                 used_regions            :: set(prog_var)
             ).
 
+:- func rbmm_info_init = rbmm_goal_info.
+
 :- type mode_constr_goal_info
     --->    mode_constr_goal_info(
                 % Inst_graph nodes that are reachable from variables
@@ -1684,6 +1686,9 @@
 
 ctgc_goal_info_init = ctgc_goal_info(set.init, set.init, no_reuse_info).
 
+rbmm_info_init = rbmm_goal_info(set.init, set.init, set.init, set.init,
+    set.init).
+
 goal_info_get_determinism(GoalInfo) = GoalInfo ^ gi_determinism.
 goal_info_get_instmap_delta(GoalInfo) = GoalInfo ^ gi_instmap_delta.
 goal_info_get_nonlocals(GoalInfo) = GoalInfo ^ gi_nonlocals.
Index: hlds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.432
diff -u -r1.432 hlds_out.m
--- hlds_out.m	20 Aug 2007 03:35:55 -0000	1.432
+++ hlds_out.m	5 Sep 2007 18:46:02 -0000
@@ -1354,6 +1354,37 @@
     ;
         true
     ),
+    ( string.contains_char(Verbose, 'e') ->
+        MaybeRbmmInfo = goal_info_get_maybe_rbmm(GoalInfo),
+        (
+            MaybeRbmmInfo = yes(RbmmInfo),
+            RbmmInfo = rbmm_goal_info(Created, Removed, Carried, Alloc, Used),
+            write_indent(Indent, !IO),
+            io.write_string("% Created regions: ", !IO),
+            io.write_list(set.to_sorted_list(Created), ", ", io.write, !IO),
+            io.nl(!IO),
+            write_indent(Indent, !IO),
+            io.write_string("% Removed regions: ", !IO),
+            io.write_list(set.to_sorted_list(Removed), ", ", io.write, !IO),
+            io.nl(!IO),
+            write_indent(Indent, !IO),
+            io.write_string("% Carried regions: ", !IO),
+            io.write_list(set.to_sorted_list(Carried), ", ", io.write, !IO),
+            io.nl(!IO),
+            write_indent(Indent, !IO),
+            io.write_string("% Allocated into regions: ", !IO),
+            io.write_list(set.to_sorted_list(Alloc), ", ", io.write, !IO),
+            io.nl(!IO),
+            write_indent(Indent, !IO),
+            io.write_string("% Used regions: ", !IO),
+            io.write_list(set.to_sorted_list(Used), ", ", io.write, !IO),
+            io.nl(!IO)
+        ;
+            MaybeRbmmInfo = no
+        )
+    ;
+        true
+    ),
     ( string.contains_char(Verbose, 'z') ->
         Purity = goal_info_get_purity(GoalInfo),
         (
Index: rbmm.actual_region_arguments.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.actual_region_arguments.m,v
retrieving revision 1.3
diff -u -r1.3 rbmm.actual_region_arguments.m
--- rbmm.actual_region_arguments.m	23 Jul 2007 05:06:13 -0000	1.3
+++ rbmm.actual_region_arguments.m	5 Sep 2007 18:46:02 -0000
@@ -31,24 +31,28 @@
 
 :- import_module list.
 :- import_module map.
-:- import_module pair.
 
-:- type proc_pp_pair_region_list_table
+:- type proc_pp_actual_region_args_table
     ==  map(
                 pred_proc_id,
-                pp_pair_region_list_table
+                pp_actual_region_args_table
         ).
 
-:- type pp_pair_region_list_table
+:- type pp_actual_region_args_table
     ==  map(
                 program_point,
-                pair(list(rptg_node), list(rptg_node))
-                % The first element is inputs, the second is outputs.
+                actual_region_args
         ).
 
+:- type actual_region_args
+    --->    actual_region_args(
+                list(rptg_node),    % constant (carried) region arguments.
+                list(rptg_node),    % inputs (removed).
+                list(rptg_node)     % outputs (created).
+            ).
 :- pred record_actual_region_arguments(module_info::in, rpta_info_table::in,
     proc_region_set_table::in, proc_region_set_table::in,
-    proc_region_set_table::in, proc_pp_pair_region_list_table::out) is det.
+    proc_region_set_table::in, proc_pp_actual_region_args_table::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -75,8 +79,8 @@
 :- pred record_actual_region_arguments_pred(module_info::in,
     rpta_info_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in, pred_id::in,
-    proc_pp_pair_region_list_table::in, proc_pp_pair_region_list_table::out)
-    is det.
+    proc_pp_actual_region_args_table::in,
+    proc_pp_actual_region_args_table::out) is det.
 
 record_actual_region_arguments_pred(ModuleInfo, RptaInfoTable,
         ConstantRTable, DeadRTable, BornRTable, PredId,
@@ -90,8 +94,8 @@
 :- pred record_actual_region_arguments_proc(module_info::in, pred_id::in,
     rpta_info_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in, proc_id::in,
-    proc_pp_pair_region_list_table::in, proc_pp_pair_region_list_table::out)
-    is det.
+    proc_pp_actual_region_args_table::in,
+    proc_pp_actual_region_args_table::out) is det.
 
 record_actual_region_arguments_proc(ModuleInfo, PredId, RptaInfoTable,
         ConstantRTable, DeadRTable, BornRTable, ProcId,
@@ -112,7 +116,7 @@
 :- pred record_actual_region_arguments_goal(module_info::in,
     pred_proc_id::in, rpta_info_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in, hlds_goal::in,
-    pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
+    pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
 
 record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
         ConstantRTable, DeadRTable, BornRTable, Goal,
@@ -126,7 +130,7 @@
     hlds_goal_info::in, module_info::in, pred_proc_id::in,
     rpta_info_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in,
-    pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
+    pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
 
 record_actual_region_arguments_expr(conj(_, Conjs), _, ModuleInfo, PPId,
         RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
@@ -192,7 +196,7 @@
 :- pred record_actual_region_arguments_case(module_info::in,
     pred_proc_id::in, rpta_info_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in, case::in,
-    pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
+    pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
 
 record_actual_region_arguments_case(ModuleInfo, PPId, RptaInfoTable,
         ConstantRTable, DeadRTable, BornRTable, Case, !ActualRegionArgProc) :-
@@ -218,7 +222,7 @@
     program_point::in, pred_proc_id::in,
     rpta_info_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in,
-    pp_pair_region_list_table::in, pp_pair_region_list_table::out) is det.
+    pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
 
 record_actual_region_arguments_call_site(CallerPPId, CallSite,
         CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
@@ -249,10 +253,9 @@
         LActualBornR0),
     list.reverse(LActualBornR0, LActualBornR),
 
-    % Record in two groups: input region arguments composed of constants and
-    % deads, and output ones which are borns.
-    Ins = LActualConstantR ++ LActualDeadR,
-    svmap.det_insert(CallSite, Ins - LActualBornR, !ActualRegionArgProc).
+    svmap.det_insert(CallSite,
+        actual_region_args(LActualConstantR, LActualDeadR, LActualBornR),
+        !ActualRegionArgProc).
 
 :- pred find_actual_param(map(rptg_node, rptg_node)::in, rptg_node::in,
     list(rptg_node)::in, list(rptg_node)::out) is det.
Index: rbmm.add_rbmm_goal_infos.m
===================================================================
RCS file: rbmm.add_rbmm_goal_infos.m
diff -N rbmm.add_rbmm_goal_infos.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rbmm.add_rbmm_goal_infos.m	5 Sep 2007 18:46:03 -0000
@@ -0,0 +1,504 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2007 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 rbmm.add_rbmm_goal_infos.m.
+% Main author: Quan Phan.
+%
+% This module fills in rbmm_goal_info field in hlds_goal_extra_info data
+% structure. The details of this information can be read in hlds_goal.m.
+%
+% This information is used by the code generator to optimize the runtime
+% region support for backtracking in region-based memory management.
+%
+% To support programs with backtracking in region-based memory management we
+% have to deal with region resurrection (i.e., a region is dead during forward
+% execution but is still needed when the program backtracks) and we may also
+% want to do instant reclaiming when backtracking happens. In Mercury, the
+% support is needed for if-then-else, nondet disjunction and commit context.
+% This runtime support certainly incurs runtime overhead to programs therefore
+% we would like to pay for it only when we actually need it. For example, if
+% we know that the condition of an if-then-else does not allocate memory into
+% any existing regions, does not create any regions nor destroy any regions,
+% then we do not need to provide support for the if-then-else. This situation
+% is very often the case with if-then-elses therefore if we can exploit it we
+% will hopefully boost the performance of region-based memory management. The
+% rbmm_goal_info gives the code generator the information which is needed to
+% fulfill this optimization.
+%
+% XXX More information about the advanced runtime support for backtracking
+% should be documented or found somewhere but it is not available yet because
+% it is still in experimental state. We should fix this when it is more
+% stable.
+%-----------------------------------------------------------------------------%
+
+:- module transform_hlds.rbmm.add_rbmm_goal_infos.
+:- interface.
+
+:- import_module hlds.
+:- import_module hlds.hlds_module.
+:- import_module transform_hlds.rbmm.actual_region_arguments.
+:- import_module transform_hlds.rbmm.points_to_info.
+:- import_module transform_hlds.rbmm.region_resurrection_renaming.
+:- import_module transform_hlds.rbmm.region_transformation.
+
+:- pred collect_rbmm_goal_info(rpta_info_table::in,
+    proc_pp_actual_region_args_table::in, renaming_table::in,
+    renaming_table::in, name_to_prog_var_table::in,
+    module_info::in, module_info::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module check_hlds.
+:- import_module check_hlds.goal_path.
+:- import_module check_hlds.type_util.
+:- import_module hlds.hlds_goal.
+:- import_module hlds.hlds_pred.
+:- import_module libs.
+:- import_module libs.compiler_util.
+:- import_module mdbcomp.
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.
+:- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_type.
+:- import_module transform_hlds.rbmm.points_to_graph.
+:- import_module transform_hlds.smm_common.
+
+:- import_module string.
+:- import_module list.
+:- import_module map.
+:- import_module maybe.
+:- import_module set.
+
+%-----------------------------------------------------------------------------%
+%
+% Collect rbmm_goal_info.
+%
+
+    % It only makes sense to collect rbmm_goal_info for the procedures
+    % which have been region-analyzed. To find such procedures we can use one
+    % of the result tables of any previous region analyses.
+    % Note: The use of ActualRegionArgumentTable here is convenient because
+    % apart from the procedure id, we also need the information about actual
+    % region arguments in this pass.
+    %
+collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgumentTable,
+        ResurRenamingTable, IteRenamingTable, NameToRegionVarTable,
+        !ModuleInfo) :-
+    map.foldl(collect_rbmm_goal_info_proc(RptaInfoTable, ResurRenamingTable,
+        IteRenamingTable, NameToRegionVarTable), ActualRegionArgumentTable,
+        !ModuleInfo).
+
+:- pred collect_rbmm_goal_info_proc(rpta_info_table::in,
+    renaming_table::in, renaming_table::in, name_to_prog_var_table::in,
+    pred_proc_id::in, pp_actual_region_args_table::in,
+    module_info::in, module_info::out) is det.
+
+collect_rbmm_goal_info_proc(RptaInfoTable, ResurRenamingTable,
+        IteRenamingTable, NameToRegionVarTable, PPId, ActualRegionsArgsProc,
+        !ModuleInfo) :-
+    module_info_pred_proc_info(!.ModuleInfo, PPId, PredInfo, ProcInfo0),
+    proc_info_get_goal(ProcInfo0, Body0),
+    map.lookup(RptaInfoTable, PPId, RptaInfo),
+    RptaInfo = rpta_info(Graph, _),
+    ( map.search(ResurRenamingTable, PPId, ResurRenamingProc0) ->
+        ResurRenamingProc = ResurRenamingProc0
+    ;
+        ResurRenamingProc = map.init
+    ),
+    ( map.search(IteRenamingTable, PPId, IteRenamingProc0) ->
+        IteRenamingProc = IteRenamingProc0
+    ;
+        IteRenamingProc = map.init
+    ),
+    map.lookup(NameToRegionVarTable, PPId, NameToRegionVarProc),
+    collect_rbmm_goal_info_goal(!.ModuleInfo, ProcInfo0, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Body0, Body),
+    proc_info_set_goal(Body, ProcInfo0, ProcInfo),
+    module_info_set_pred_proc_info(PPId, PredInfo, ProcInfo, !ModuleInfo).
+
+:- pred collect_rbmm_goal_info_goal(module_info::in, proc_info::in,
+    rpt_graph::in, pp_actual_region_args_table::in, renaming_proc::in,
+    renaming_proc::in, name_to_prog_var::in,
+    hlds_goal::in, hlds_goal::out) is det.
+
+collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Goal) :-
+    !.Goal = hlds_goal(Expr0, Info0),
+    collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Expr0, Expr, Info0, Info),
+    !:Goal = hlds_goal(Expr, Info).
+
+:- pred collect_rbmm_goal_info_goal_expr(module_info::in, proc_info::in,
+    rpt_graph::in, pp_actual_region_args_table::in, renaming_proc::in,
+    renaming_proc::in, name_to_prog_var::in,
+    hlds_goal_expr::in, hlds_goal_expr::out,
+    hlds_goal_info::in, hlds_goal_info::out) is det.
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, _, Graph, _, ResurRenamingProc,
+        IteRenamingProc, NameToRegionVar, !Expr, !Info) :-
+    !.Expr = unify(_, _, _, Unification, _), 
+    ProgPoint = program_point_init(!.Info),
+    ( map.search(ResurRenamingProc, ProgPoint, ResurRenaming0) ->
+        ResurRenaming = ResurRenaming0
+    ;
+        ResurRenaming = map.init
+    ),
+    ( map.search(IteRenamingProc, ProgPoint, IteRenaming0) ->
+        IteRenaming = IteRenaming0
+    ;
+        IteRenaming = map.init
+    ),
+    collect_rbmm_goal_info_unification(Unification, ModuleInfo, Graph,
+        ResurRenaming, IteRenaming, NameToRegionVar, !Info).
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, _,
+        ActualRegionArgumentProc, _, _, _, !Expr, !Info) :-
+    !.Expr = plain_call(PredId, ProcId, Args, _, _, _),
+    CalleePPId = proc(PredId, ProcId),
+    (
+        is_create_region_call(!.Expr, ModuleInfo, CreatedRegion)
+    ->
+        RbmmGoalInfo = rbmm_goal_info(set.make_singleton_set(CreatedRegion),
+            set.init, set.init, set.init, set.init),
+        goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
+    ;
+        is_remove_region_call(!.Expr, ModuleInfo, RemovedRegion)
+    ->
+        RbmmGoalInfo = rbmm_goal_info(set.init,
+            set.make_singleton_set(RemovedRegion), set.init, set.init,
+            set.init),
+        goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
+    ;
+        some_are_special_preds([CalleePPId], ModuleInfo)
+    ->
+        goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
+    ;
+        CallSite = program_point_init(!.Info),
+        proc_info_get_vartypes(ProcInfo, VarTypes),
+        RegionArgs = list.filter(is_region_var(VarTypes), Args),
+        map.lookup(ActualRegionArgumentProc, CallSite, ActualRegionArgs),
+        ActualRegionArgs = actual_region_args(Constants, Inputs, _Outputs),
+        list.det_split_list(list.length(Constants), RegionArgs,
+            CarriedRegions, RemovedAndCreated),
+        list.det_split_list(list.length(Inputs), RemovedAndCreated,
+            RemovedRegions, CreatedRegions),
+        % XXX We safely approximate that RemovedRegions and CarriedRegions
+        % are allocated into and read from in this call.
+        AllocatedIntoAndReadFrom =
+            set.from_list(RemovedRegions ++ CarriedRegions),
+        RbmmGoalInfo = rbmm_goal_info(set.from_list(CreatedRegions),
+            set.from_list(RemovedRegions), set.from_list(CarriedRegions),
+            AllocatedIntoAndReadFrom, AllocatedIntoAndReadFrom),
+        goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
+     ).
+
+    % We do not handle generic calls and calls to foreign procs in RBMM yet,
+    % so if a program has any of them the RBMM compilation will fail before
+    % reaching here. We just call sorry now so that they are not
+    % forgotten when we deal with these explicitly in the future.
+    %
+collect_rbmm_goal_info_goal_expr(_, _, _, _, _, _, _, !Expr, !Info) :-
+    !.Expr = generic_call(_, _, _, _),
+    sorry(this_file,
+        "collect_rbmm_goal_info_goal_expr: generic call not handled"). 
+collect_rbmm_goal_info_goal_expr(_, _, _, _, _, _, _, !Expr, !Info) :-
+    !.Expr = call_foreign_proc(_, _, _, _, _, _, _),
+    sorry(this_file,
+        "collect_rbmm_goal_info_goal_expr: call to foreign proc not handled"). 
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Expr, !Info) :-
+    !.Expr = conj(ConjType, Conjs0),
+    list.map(collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc), Conjs0, Conjs), 
+    !:Expr = conj(ConjType, Conjs), 
+
+    % Calculate created, removed, allocated into, used regions.
+    compute_rbmm_info_conjunction(Conjs, rbmm_info_init, RbmmInfo0),
+
+    % Calculate carried regions.
+    % The carried regions are those that are NOT removed, NOT created by all
+    % the conjuncts.
+    RbmmInfo0 = rbmm_goal_info(Created, Removed, _, AllocatedInto, Used),
+    NonLocals = goal_info_get_nonlocals(!.Info),
+    proc_info_get_vartypes(ProcInfo, VarTypes),
+    NonLocalRegions = set.filter(is_region_var(VarTypes), NonLocals),
+    set.difference(NonLocalRegions, set.union(Created, Removed), Carried),
+    RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto, Used),
+    goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Expr, !Info) :-
+    !.Expr = disj(Disjs0),
+    list.map(collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc), Disjs0, Disjs), 
+    !:Expr = disj(Disjs),
+
+    (
+        Disjs = [],
+        goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
+    ;
+        % Well-modedness requires that each disjunct creates, removes and
+        % carries the same regions, which are also created, removed, carried
+        % by the disjunction. 
+        Disjs = [hlds_goal(_, DInfo) | _],
+        DRbmmInfo = goal_info_get_rbmm(DInfo),
+        DRbmmInfo = rbmm_goal_info(Created, Removed, Carried, _, _),
+        RbmmInfo0 = rbmm_goal_info(Created, Removed, Carried, set.init,
+            set.init), 
+
+        % Calculate allocated-into and used regions.
+        compute_rbmm_info_goals(Disjs, RbmmInfo0, RbmmInfo),
+        goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
+    ).
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Expr, !Info) :-
+    !.Expr = switch(A, B, Cases0), 
+    list.map(collect_rbmm_goal_info_case(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc), Cases0, Cases),
+    !:Expr = switch(A, B, Cases),
+    (
+        Cases = [],
+        unexpected(this_file, "collect_rbmm_goal_info_goal_expr: "
+            ++ "empty switch unexpected")
+    ;
+        % The process here is similar to the above code for disjunctions.
+        Cases = [Case | _],
+        Case = case(_, Goal),
+        Goal = hlds_goal(_, CaseInfo),
+        CaseRbmmInfo = goal_info_get_rbmm(CaseInfo),
+        CaseRbmmInfo = rbmm_goal_info(Created, Removed, Carried, _, _),
+        SwitchRbmmInfo0 = rbmm_goal_info(Created, Removed, Carried, set.init,
+            set.init),
+        list.foldl(
+            (pred(C::in, Gs0::in, Gs::out) is det :-
+                    C = case(_, G),
+                    Gs = [G | Gs0]
+            ), Cases, [], Goals),
+        compute_rbmm_info_goals(Goals, SwitchRbmmInfo0, SwitchRbmmInfo),
+        goal_info_set_maybe_rbmm(yes(SwitchRbmmInfo), !Info)
+    ).
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Expr, !Info) :-
+    !.Expr = negation(Goal0),
+    collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Goal0, Goal),
+    !:Expr = negation(Goal),
+    Goal = hlds_goal(_, Info),
+    RbmmInfo = goal_info_get_rbmm(Info),
+    goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Expr, !Info) :-
+    !.Expr = scope(Reason, Goal0), 
+    collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Goal0, Goal),
+    !:Expr = scope(Reason, Goal),
+    Goal = hlds_goal(_, Info),
+    RbmmInfo = goal_info_get_rbmm(Info),
+    goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info).
+
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Expr, !Info) :-
+    !.Expr = if_then_else(A, Cond0, Then0, Else0),
+    collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Cond0, Cond),
+    collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Then0, Then),
+    collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Else0, Else),
+    !:Expr = if_then_else(A, Cond, Then, Else),
+
+    % Well-modedness requires that the (cond, then) and the else parts create,
+    % remove and carry the same regions, which are also created, removed,
+    % carried by the if-then-else. 
+    Else = hlds_goal(_, ElseInfo),
+    ElseRbmmInfo = goal_info_get_rbmm(ElseInfo),
+    ElseRbmmInfo = rbmm_goal_info(Created, Removed, Carried, _, _),
+    IteRbmmInfo0 = rbmm_goal_info(Created, Removed, Carried, set.init,
+        set.init),
+    compute_rbmm_info_goals([Cond, Then, Else], IteRbmmInfo0, IteRbmmInfo),
+    goal_info_set_maybe_rbmm(yes(IteRbmmInfo), !Info).
+
+collect_rbmm_goal_info_goal_expr(_, _, _, _, _, _, _, !Expr, !Info) :-
+    !.Expr = shorthand(_), 
+    unexpected(this_file,
+        "collect_rbmm_goal_info_goal_expr: shorthand unexpected").
+
+    % The regions that are created inside this conjunction are all that are
+    % created inside each conjunct.
+    % The regions that are removed inside this conjunction are all that are
+    % removed inside each conjunct AND EXIST before the conjunction, i.e.,
+    % not being created in the condition.
+    % The regions that are allocated into inside this conjunction are those
+    % allocated into by any conjuncts AND EXIST ...
+    % The regions that are read from inside this conjunction are those that
+    % are read from by any conjuncts AND EXIST ...
+    %
+:- pred compute_rbmm_info_conjunction(list(hlds_goal)::in,
+    rbmm_goal_info::in, rbmm_goal_info::out) is det.
+
+compute_rbmm_info_conjunction([], !RbmmInfo).
+compute_rbmm_info_conjunction([Conj | Conjs], !RbmmInfo) :-
+    Conj = hlds_goal(_, CInfo),
+    CRbmmInfo = goal_info_get_rbmm(CInfo),
+    CRbmmInfo = rbmm_goal_info(CCreated, CRemoved, _, CAllocatedInto, CUsed),
+    !.RbmmInfo = rbmm_goal_info(Created0, Removed0, Carried, AllocatedInto0,
+        Used0),
+    set.union(CCreated, Created0, Created),
+    set.difference(set.union(CRemoved, Removed0), Created, Removed),
+    set.difference(set.union(CAllocatedInto, AllocatedInto0), Created,
+        AllocatedInto),
+    set.difference(set.union(CUsed, Used0), Created, Used),
+     
+    !:RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto,
+        Used),
+    compute_rbmm_info_conjunction(Conjs, !RbmmInfo). 
+
+    % The regions that are allocated into inside this list of goals are those
+    % allocated into by any goals AND EXIST ...
+    % The regions that are read from inside this list of goals are those that 
+    % are read from by any goals AND EXIST ... 
+    %
+    % This predicate are used to compute the above information for the goals
+    % in disjunction, cases, and if-then-else.
+    %
+:- pred compute_rbmm_info_goals(list(hlds_goal)::in,
+    rbmm_goal_info::in, rbmm_goal_info::out) is det.
+
+compute_rbmm_info_goals([], !RbmmInfo).
+compute_rbmm_info_goals([Goal | Goals], !RbmmInfo) :-
+    Goal = hlds_goal(_, Info),
+    GoalRbmmInfo = goal_info_get_rbmm(Info),
+    GoalRbmmInfo = rbmm_goal_info(_, _, _, GoalAllocatedInto, GoalUsed),
+    !.RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto0,
+        Used0),
+    set.difference(set.union(GoalAllocatedInto, AllocatedInto0), Created,
+        AllocatedInto),
+    set.difference(set.union(GoalUsed, Used0), Created, Used),
+    !:RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto,
+        Used),
+    compute_rbmm_info_goals(Goals, !RbmmInfo).
+
+:- pred collect_rbmm_goal_info_unification(unification::in, module_info::in,
+    rpt_graph::in, renaming::in, renaming::in, name_to_prog_var::in,
+    hlds_goal_info::in, hlds_goal_info::out) is det.
+
+collect_rbmm_goal_info_unification(Unification, ModuleInfo, Graph,
+        ResurRenaming, IteRenaming, RegionNameToVar, !Info) :-
+    (
+        Unification = construct(_, _, _, _, HowToConstruct, _, _),
+        (
+            HowToConstruct = construct_in_region(AllocatedIntoRegion),
+            RbmmInfo = rbmm_goal_info(set.init, set.init,
+                set.make_singleton_set(AllocatedIntoRegion),
+                set.make_singleton_set(AllocatedIntoRegion), set.init),
+            goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
+        ;
+            ( HowToConstruct = construct_statically(_)
+            ; HowToConstruct = construct_dynamically
+            ; HowToConstruct = reuse_cell(_)
+            ),
+            goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
+        )
+    ;
+        Unification = deconstruct(DeconsCellVar, _, _, _, _, _),
+        get_node_by_variable(Graph, DeconsCellVar, Node), 
+        NodeType = rptg_lookup_node_type(Graph, Node),
+        ( if    type_not_stored_in_region(NodeType, ModuleInfo)
+          then
+                goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
+          else
+                OriginalName = rptg_lookup_region_name(Graph, Node),
+                ( map.search(ResurRenaming, OriginalName, ResurName) ->
+                    Name = ResurName
+                ; map.search(IteRenaming, OriginalName, IteName) ->
+                    Name = IteName
+                ;
+                    Name = OriginalName
+                ),
+                map.lookup(RegionNameToVar, Name, RegionVar),
+                RbmmInfo = rbmm_goal_info(set.init, set.init,
+                    set.make_singleton_set(RegionVar),
+                    set.init, set.make_singleton_set(RegionVar)),
+                goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
+        )
+    ;
+        ( Unification = assign(_, _)
+        ; Unification = simple_test(_, _)
+        ),
+        goal_info_set_maybe_rbmm(yes(rbmm_goal_info(set.init, set.init,
+            set.init, set.init, set.init)), !Info)
+    ;
+        Unification = complicated_unify(_, _, _),
+        unexpected(this_file, "collect_rbmm_goal_info_unification:"
+            ++ " encountered complicated unification")
+    ).
+
+:- pred is_remove_region_call(hlds_goal_expr::in, module_info::in,
+    prog_var::out) is semidet.
+
+is_remove_region_call(plain_call(PredId, _ProcId, Args, _, _, _),
+        ModuleInfo, RemovedRegion) :-
+    module_info_pred_info(ModuleInfo, PredId, PredInfo),
+    pred_info_module(PredInfo) = mercury_region_builtin_module,
+    pred_info_name(PredInfo) = remove_region_pred_name,
+    Args = [RemovedRegion].
+
+:- pred is_create_region_call(hlds_goal_expr::in, module_info::in,
+    prog_var::out) is semidet.
+
+is_create_region_call(plain_call(PredId, _ProcId, Args, _, _, _),
+        ModuleInfo, CreatedRegion) :-
+    module_info_pred_info(ModuleInfo, PredId, PredInfo),
+    pred_info_module(PredInfo) = mercury_region_builtin_module,
+    pred_info_name(PredInfo) = create_region_pred_name,
+    Args = [CreatedRegion].
+
+:- pred collect_rbmm_goal_info_case(module_info::in, proc_info::in,
+    rpt_graph::in, pp_actual_region_args_table::in, renaming_proc::in,
+    renaming_proc::in, name_to_prog_var::in, case::in, case::out) is det.
+
+collect_rbmm_goal_info_case(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, !Case) :-
+    !.Case = case(Functor, Goal0),
+    collect_rbmm_goal_info_goal(ModuleInfo, ProcInfo, Graph,
+        ActualRegionsArgsProc, ResurRenamingProc, IteRenamingProc,
+        NameToRegionVarProc, Goal0, Goal),
+    !:Case = case(Functor, Goal).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "rbmm.add_rbmm_goal_infos.m".
+
+%-----------------------------------------------------------------------------%
Index: rbmm.interproc_region_lifetime.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.interproc_region_lifetime.m,v
retrieving revision 1.3
diff -u -r1.3 rbmm.interproc_region_lifetime.m
--- rbmm.interproc_region_lifetime.m	23 Jul 2007 05:06:13 -0000	1.3
+++ rbmm.interproc_region_lifetime.m	5 Sep 2007 18:46:03 -0000
@@ -69,6 +69,7 @@
 :- import_module parse_tree.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_type.
 :- import_module transform_hlds.dependency_graph.
 :- import_module transform_hlds.rbmm.points_to_graph.
 :- import_module transform_hlds.smm_common.
@@ -590,11 +591,7 @@
 
 retain_non_primitive_regions(ModuleInfo, Graph, Region, !RegionSet) :-
     NodeType = rptg_lookup_node_type(Graph, Region),
-    (
-        ( type_is_atomic(ModuleInfo, NodeType)
-        ; is_dummy_argument_type(ModuleInfo, NodeType)
-        )
-    ->
+    ( type_not_stored_in_region(NodeType, ModuleInfo) ->
         true
     ;
         svset.insert(Region, !RegionSet)
Index: rbmm.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
retrieving revision 1.6
diff -u -r1.6 rbmm.m
--- rbmm.m	20 Jul 2007 08:09:53 -0000	1.6
+++ rbmm.m	5 Sep 2007 18:46:03 -0000
@@ -25,6 +25,7 @@
 :- include_module points_to_analysis.
 :- include_module points_to_graph.
 :- include_module points_to_info.
+:- include_module add_rbmm_goal_infos.
 :- include_module region_instruction.
 :- include_module region_liveness_info.
 :- include_module region_resurrection_renaming.
@@ -51,6 +52,7 @@
 :- import_module transform_hlds.rbmm.live_region_analysis.
 :- import_module transform_hlds.rbmm.live_variable_analysis.
 :- import_module transform_hlds.rbmm.points_to_analysis.
+:- import_module transform_hlds.rbmm.add_rbmm_goal_infos.
 :- import_module transform_hlds.rbmm.region_instruction.
 :- import_module transform_hlds.rbmm.region_resurrection_renaming.
 :- import_module transform_hlds.rbmm.region_transformation.
@@ -115,8 +117,12 @@
     region_transform(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
         ActualRegionArgumentTable, ResurRenamingTable, IteRenamingTable,
         RegionInstructionTable, ResurRenamingAnnoTable,
-        IteRenamingAnnoTable, map.init, _NameToVarTable, !ModuleInfo).
+        IteRenamingAnnoTable, map.init, NameToVarTable, !ModuleInfo),
+    
+    collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgumentTable,
+        ResurRenamingTable, IteRenamingTable, NameToVarTable, !ModuleInfo).
 
 %-----------------------------------------------------------------------------%
 :- end_module transform_hlds.rbmm.
 %-----------------------------------------------------------------------------%
Index: user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.542
diff -u -r1.542 user_guide.texi
--- user_guide.texi	29 Aug 2007 01:27:05 -0000	1.542
+++ user_guide.texi	5 Sep 2007 18:46:08 -0000
@@ -6771,6 +6771,7 @@
 b - builtin flags on calls,
 c - contexts of goals and types,
 d - determinism of goals,
+e - created, removed, carried, allocated into, and used regions,
 f - follow_vars sets of goals,
 g - goal feature lists,
 i - variables whose instantiation changes,
@@ -6792,7 +6793,8 @@
 I - imported predicates,
 M - mode and inst information,
 P - path information,
-S - information about structure sharing
+R - live forward use, live backward use and reuse possibilities,
+S - information about structure sharing,
 T - type and typeclass information,
 U - unify and compare predicates,
 Z - information about globals structs representing call and answer tables.
cvs diff: Diffing notes


More information about the reviews mailing list