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

Quan Phan quan.phan at cs.kuleuven.be
Wed Aug 15 10:39:01 AEST 2007


Hi,

Estimate hours taken: 15h.
Branch: main.

Implement the analysis 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.rbmm_goal_info_analysis.m:
	New file that contains the implementation of the analysis.

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 seperate 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 allocation 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 --------------
? .hlds_goal.m.swp
? .rbmm.points_to_analysis.m.swp
? diff.19.35
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	14 Aug 2007 23:41:09 -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.430
diff -u -r1.430 hlds_out.m
--- hlds_out.m	13 Aug 2007 03:01:40 -0000	1.430
+++ hlds_out.m	14 Aug 2007 23:41:10 -0000
@@ -1353,6 +1353,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	14 Aug 2007 23:41:11 -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.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	14 Aug 2007 23:41:11 -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	14 Aug 2007 23:41:11 -0000
@@ -25,6 +25,7 @@
 :- include_module points_to_analysis.
 :- include_module points_to_graph.
 :- include_module points_to_info.
+:- include_module rbmm_goal_info_analysis.
 :- 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.rbmm_goal_info_analysis.
 :- 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: rbmm.rbmm_goal_info_analysis.m
===================================================================
RCS file: rbmm.rbmm_goal_info_analysis.m
diff -N rbmm.rbmm_goal_info_analysis.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rbmm.rbmm_goal_info_analysis.m	14 Aug 2007 23:41:11 -0000
@@ -0,0 +1,488 @@
+%-----------------------------------------------------------------------------%
+% 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.rbmm_goal_info_analysis.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
+% support for region-based memory management.
+%
+%-----------------------------------------------------------------------------%
+
+:- module transform_hlds.rbmm.rbmm_goal_info_analysis.
+:- 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.
+
+%-----------------------------------------------------------------------------%
+%
+% rbmm_goal_info analysis.
+%
+
+    % We need to collect this pieces of information for the procedures which
+    % have been region-analyzed. Therefore we can use one of the resulting
+    % tables from previous phases for the PPId. The use of
+    % ActualRegionArgumentTable here is convenient because we also need the
+    % information about actual region arguments in this analysis.
+    %
+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_disjunction(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 that for nondet disjunction.
+        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),
+        compute_rbmm_info_switch(Cases, 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),
+    Else = hlds_goal(_, ElseInfo),
+    RbmmInfo = goal_info_get_rbmm(ElseInfo),
+    goal_info_set_maybe_rbmm(yes(RbmmInfo), !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 disjunction are those
+    % allocated into by any disjuncts AND EXIST ...
+    % The regions that are read from inside this disjunction are those that 
+    % are read from by any disjuncts AND EXIST ... 
+    %
+:- pred compute_rbmm_info_disjunction(list(hlds_goal)::in,
+    rbmm_goal_info::in, rbmm_goal_info::out) is det.
+
+compute_rbmm_info_disjunction([], !RbmmInfo).
+compute_rbmm_info_disjunction([Disj | Disjs], !RbmmInfo) :-
+    Disj = hlds_goal(_, DInfo),
+    DRbmmInfo = goal_info_get_rbmm(DInfo),
+    DRbmmInfo = rbmm_goal_info(_, _, _, DAllocatedInto, DUsed),
+    !.RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto0,
+        Used0),
+    set.difference(set.union(DAllocatedInto, AllocatedInto0), Created,
+        AllocatedInto),
+    set.difference(set.union(DUsed, Used0), Created, Used),
+    !:RbmmInfo = rbmm_goal_info(Created, Removed, Carried, AllocatedInto,
+        Used),
+    compute_rbmm_info_disjunction(Disjs, !RbmmInfo).
+
+    % The process here is similar to that for nondet disjunction.
+    %
+:- pred compute_rbmm_info_switch(list(case)::in, rbmm_goal_info::in,
+    rbmm_goal_info::out) is det.
+
+compute_rbmm_info_switch([], !SwitchRbmmInfo).
+compute_rbmm_info_switch([Case | Cases], !SwitchRbmmInfo) :-
+    Case = case(_, Goal),
+    Goal = hlds_goal(_, Info),
+    CaseRbmmInfo = goal_info_get_rbmm(Info),
+    CaseRbmmInfo = rbmm_goal_info(_, _, _, CaseAllocatedInto, CaseUsed),
+    !.SwitchRbmmInfo = rbmm_goal_info(Created, Removed, Carried,
+        AllocatedInto0, Used0),
+    set.difference(set.union(CaseAllocatedInto, AllocatedInto0), Created,
+        AllocatedInto),
+    set.difference(set.union(CaseUsed, Used0), Created, Used),
+    !:SwitchRbmmInfo = rbmm_goal_info(Created, Removed, Carried,
+        AllocatedInto, Used),
+    compute_rbmm_info_switch(Cases, !SwitchRbmmInfo).
+
+:- 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:"
+            ++ " encounter 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.rbmm_goal_info_analysis.m".
+
+%-----------------------------------------------------------------------------%
Index: rbmm.region_transformation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_transformation.m,v
retrieving revision 1.3
diff -u -r1.3 rbmm.region_transformation.m
--- rbmm.region_transformation.m	23 Jul 2007 05:06:15 -0000	1.3
+++ rbmm.region_transformation.m	14 Aug 2007 23:41:11 -0000
@@ -59,7 +59,7 @@
     %
 :- pred region_transform(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::in,
+    proc_pp_actual_region_args_table::in,
     renaming_table::in, renaming_table::in, region_instruction_table::in,
     renaming_annotation_table::in, renaming_annotation_table::in,
     name_to_prog_var_table::in, name_to_prog_var_table::out,
@@ -174,7 +174,7 @@
     %
 :- pred region_transform_pred(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::in,
+    proc_pp_actual_region_args_table::in,
     renaming_table::in, renaming_table::in, region_instruction_table::in,
     renaming_annotation_table::in, renaming_annotation_table::in,
     pred_id::in, name_to_prog_var_table::in, name_to_prog_var_table::out,
@@ -208,7 +208,7 @@
     %
 :- pred region_transform_proc(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::in,
+    proc_pp_actual_region_args_table::in,
     renaming_table::in, renaming_table::in, region_instruction_table::in,
     renaming_annotation_table::in, renaming_annotation_table::in,
     pred_id::in, proc_id::in, name_to_prog_var_table::in,
@@ -268,7 +268,7 @@
     %
 :- pred annotate_proc(module_info::in, pred_info::in, rpt_graph::in,
     region_set::in, region_set::in, region_set::in,
-    pp_pair_region_list_table::in, renaming_proc::in, renaming_proc::in,
+    pp_actual_region_args_table::in, renaming_proc::in, renaming_proc::in,
     region_instruction_proc::in, renaming_annotation_proc::in,
     renaming_annotation_proc::in, prog_varset::in, prog_varset::out,
     vartypes::in, vartypes::out, list(prog_var)::in, list(prog_var)::out,
@@ -348,7 +348,7 @@
     % caused by renaming and annotations needed for resurrection problem.
     %
 :- pred region_transform_goal(module_info::in, rpt_graph::in,
-    renaming_proc::in, renaming_proc::in, pp_pair_region_list_table::in,
+    renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
     region_instruction_proc::in, renaming_annotation_proc::in,
     renaming_annotation_proc::in, hlds_goal::in, hlds_goal::out,
     name_to_prog_var::in, name_to_prog_var::out,
@@ -415,7 +415,7 @@
     ).
 
 :- pred region_transform_goal_expr(module_info::in, rpt_graph::in,
-    renaming::in, renaming::in, pp_pair_region_list_table::in,
+    renaming::in, renaming::in, pp_actual_region_args_table::in,
     program_point::in, hlds_goal_expr::in, hlds_goal_expr::out,
     hlds_goal_info::in, hlds_goal_info::out, name_to_prog_var::in,
     name_to_prog_var::out, prog_varset::in, prog_varset::out,
@@ -433,10 +433,10 @@
     ( map.search(ActualRegionArgProc, ProgPoint, ActualNodes0) ->
         ActualNodes = ActualNodes0
     ;
-        ActualNodes = pair([],[])
+        ActualNodes = actual_region_args([], [], [])
     ),
-    ActualNodes = Ins - Outs,
-    AllNodes = Ins ++ Outs,
+    ActualNodes = actual_region_args(Constants, Ins, Outs),
+    AllNodes = Constants ++ Ins ++ Outs,
     list.map_foldl3(
         node_to_var_with_both_renamings(Graph, ResurRenaming, IteRenaming),
         AllNodes, ActualRegionArgs, !NameToVar, !VarSet, !VarTypes),
@@ -488,7 +488,7 @@
     % Because an atomic goal is turned into a conjunction, we need to
     % flatten its compounding conjunction if it is in one.
 :- pred region_transform_compound_goal(module_info::in, rpt_graph::in,
-    renaming_proc::in, renaming_proc::in, pp_pair_region_list_table::in,
+    renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
     region_instruction_proc::in, renaming_annotation_proc::in,
     renaming_annotation_proc::in, hlds_goal::in, hlds_goal::out,
     name_to_prog_var::in, name_to_prog_var::out,
@@ -584,11 +584,7 @@
         IsUnique, SubInfo),
     get_node_by_variable(Graph, Var, Node),
     NodeType = rptg_lookup_node_type(Graph, Node),
-    (
-        ( type_is_atomic(ModuleInfo, NodeType)
-        ; is_dummy_argument_type(ModuleInfo, NodeType)
-        )
-    ->
+    ( type_not_stored_in_region(NodeType, ModuleInfo) ->
         true
     ;
         Name = rptg_lookup_region_name(Graph, Node),
@@ -623,7 +619,7 @@
     % Finally, we try to flatten this new conjunction.
     %
 :- pred region_transform_case(module_info::in, rpt_graph::in,
-    renaming_proc::in, renaming_proc::in, pp_pair_region_list_table::in,
+    renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
     region_instruction_proc::in, renaming_annotation_proc::in,
     renaming_annotation_proc::in, hlds_goal::in, case::in, case::out,
     name_to_prog_var::in, name_to_prog_var::out,
Index: type_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.179
diff -u -r1.179 type_util.m
--- type_util.m	9 Aug 2007 05:28:26 -0000	1.179
+++ type_util.m	14 Aug 2007 23:41:12 -0000
@@ -233,6 +233,11 @@
     %
 :- func cons_id_adjusted_arity(module_info, mer_type, cons_id) = int.
 
+    % Check if (the terms of) the type is NOT allocated in a region in 
+    % region-based memory management.
+    %
+:- pred type_not_stored_in_region(mer_type::in, module_info::in) is semidet.
+
 %-----------------------------------------------------------------------------%
 
     % If possible, get the argument types for the cons_id. We need to pass in
@@ -955,6 +960,16 @@
 
 %-----------------------------------------------------------------------------%
 
+type_not_stored_in_region(Type, ModuleInfo) :-
+    ( type_is_atomic(ModuleInfo, Type)
+    ; is_dummy_argument_type(ModuleInfo, Type)
+    ; Type = type_info_type
+    ; Type = type_ctor_info_type
+    ; type_is_var(Type)
+    ).
+
+%-----------------------------------------------------------------------------%
+
 maybe_get_cons_id_arg_types(ModuleInfo, MaybeType, ConsId0, Arity,
         MaybeTypes) :-
     ( ConsId0 = cons(_SymName, _) ->
Index: user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.540
diff -u -r1.540 user_guide.texi
--- user_guide.texi	13 Aug 2007 03:01:55 -0000	1.540
+++ user_guide.texi	14 Aug 2007 23:42:53 -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