[m-rev.] A diff of adding a new option for RBMM

Quan Phan quan.phan at cs.kuleuven.be
Sat Nov 28 02:50:09 AEDT 2009


Hi,

This diff has been reviewed by Zoltan.

Regards,
Quan.


compiler/options.m:
    Add a new option that allows us to distinguish between the rbmm2 and rbmm3
    versions of the system in the paper.

compiler/rbmm.add_rbmm_goal_infos.m:
    Use the new option to decide whether to apply the optimization
    that distinguishes rbmm3.

compiler/rbmm.points_to_graph.m:
    Add a utility predicate needed by the new code in
    rbmm.add_rbmm_goal_infos.m.

compiler/rbmm.region_arguments.m:
    A new module that replaces rbmm.actual_region_arguments.m. It computes
    the regions in one place, not in several.

compiler/rbmm.actual_region_arguments.m:
    Remove this replaced module.

compiler/rbmm.m:
    Replace the old module with the new one.

compiler/rbmm.points_to_analysis.m:
    Apply rule T6 from my thesis.

compiler/rbmm.points_to_info.m:
    Add meaningful names to some types.

compiler/rbmm.interproc_region_lifetime.m:
    Use the new type name.

compiler/rbmm.region_transformation.m:
    Use the new type name, and use the new data structure representing
    procedure arguments.

cvs diff: Diffing .
Index: options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.660
diff -u -r1.660 options.m
--- options.m	30 Oct 2009 03:33:17 -0000	1.660
+++ options.m	28 Nov 2009 01:52:05 -0000
@@ -372,6 +372,7 @@
     ;       extend_stacks_when_needed
     ;       stack_segments
     ;       use_regions
+    ;       use_alloc_regions
     ;       use_regions_debug
     ;       use_regions_profiling
     ;       source_to_source_debug
@@ -1247,6 +1248,7 @@
     extend_stacks_when_needed           -   bool(no),
     stack_segments                      -   bool(no),
     use_regions                         -   bool(no),
+    use_alloc_regions                   -   bool(yes),
     use_regions_debug                   -   bool(no),
     use_regions_profiling               -   bool(no),
     use_minimal_model_stack_copy        -   bool(no),
@@ -2112,6 +2114,7 @@
 long_option("extend-stacks-when-needed",    extend_stacks_when_needed).
 long_option("stack-segments",       stack_segments).
 long_option("use-regions",          use_regions).
+long_option("use-alloc-regions",    use_alloc_regions).
 long_option("use-regions-debug",    use_regions_debug).
 long_option("use-regions-profiling",use_regions_profiling).
 % Data representation options
@@ -4201,6 +4204,9 @@
         % should also document rbmmd rbmmp rbmmdp
         %"--use-regions\t\t(grade modifier: `.rbmm')",
         %"\tEnable support for region-based memory managment."
+        %"--use-alloc-regions",
+        %"\tCompute and use the exact set of regions",
+        %"\t that may be allocated into by a call."
     ]),
 
     io.write_string("\n    LLDS back-end compilation model options:\n"),
Index: rbmm.actual_region_arguments.m
===================================================================
RCS file: rbmm.actual_region_arguments.m
diff -N rbmm.actual_region_arguments.m
--- rbmm.actual_region_arguments.m	23 Dec 2008 01:37:40 -0000	1.4
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,268 +0,0 @@
-% -----------------------------------------------------------------------------%
-% vim: ft=mercury ts=4 sw=4 et
-%-----------------------------------------------------------------------------%
-% Copyright (C) 2007-2008 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.actual_region_arguments.m.
-% Main author: Quan Phan.
-%
-% We will pass regions as extra arguments in procedure calls. The extra formal
-% region arguments are already known from live region analysis.
-% This module derives the corresponding actual region arguments at call sites
-% in each procedure. This information will be used to extend the argument
-% lists of calls in the HLDS.
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- module transform_hlds.rbmm.actual_region_arguments.
-:- interface.
-
-:- import_module hlds.
-:- import_module hlds.hlds_module.
-:- import_module hlds.hlds_pred.
-:- import_module transform_hlds.rbmm.points_to_graph.
-:- import_module transform_hlds.rbmm.points_to_info.
-:- import_module transform_hlds.rbmm.region_liveness_info.
-:- import_module transform_hlds.smm_common.
-
-:- import_module list.
-:- import_module map.
-
-:- type proc_pp_actual_region_args_table
-    ==  map(
-                pred_proc_id,
-                pp_actual_region_args_table
-        ).
-
-:- type pp_actual_region_args_table
-    ==  map(
-                program_point,
-                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_actual_region_args_table::out) is det.
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- implementation.
-
-:- import_module check_hlds.
-:- import_module check_hlds.goal_path.
-:- import_module hlds.hlds_goal.
-:- import_module libs.
-:- import_module libs.compiler_util.
-
-:- import_module set.
-:- import_module string.
-:- import_module svmap.
-
-record_actual_region_arguments(ModuleInfo, RptaInfoTable, ConstantRTable,
-        DeadRTable, BornRTable, ActualRegionArgTable) :-
-    module_info_predids(PredIds, ModuleInfo, _),
-    list.foldl(record_actual_region_arguments_pred(ModuleInfo,
-        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
-        PredIds, map.init, ActualRegionArgTable).
-
-:- 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_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,
-        !ActualRegionArgTable) :-
-    module_info_pred_info(ModuleInfo, PredId, PredInfo),
-    ProcIds = pred_info_non_imported_procids(PredInfo),
-    list.foldl(record_actual_region_arguments_proc(ModuleInfo, PredId,
-        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable), ProcIds,
-        !ActualRegionArgTable).
-
-:- 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_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,
-        !ActualRegionArgTable) :-
-    PPId = proc(PredId, ProcId),
-    ( if    some_are_special_preds([PPId], ModuleInfo)
-      then  true
-      else
-            module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
-            fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
-            proc_info_get_goal(ProcInfo, Body),
-            record_actual_region_arguments_goal(ModuleInfo, PPId,
-                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Body,
-                map.init, ActualRegionArgProc),
-            svmap.set(PPId, ActualRegionArgProc, !ActualRegionArgTable)
-    ).
-
-:- 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_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, !ActualRegionArgProc) :-
-    Goal = hlds_goal(Expr, Info),
-    record_actual_region_arguments_expr(Expr, Info, ModuleInfo, PPId,
-        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
-        !ActualRegionArgProc).
-
-:- pred record_actual_region_arguments_expr(hlds_goal_expr::in,
-    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_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
-
-record_actual_region_arguments_expr(GoalExpr, GoalInfo, ModuleInfo, CallerPPId,
-        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
-        !ActualRegionArgProc) :-
-    (
-        GoalExpr = plain_call(PredId, ProcId, _, _, _, _),
-        CalleePPId = proc(PredId, ProcId),
-        ( some_are_special_preds([CalleePPId], ModuleInfo) ->
-            true
-        ;
-            CallSite = program_point_init(GoalInfo),
-            record_actual_region_arguments_call_site(CallerPPId, CallSite,
-                CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
-                BornRTable, !ActualRegionArgProc)
-        )
-    ;
-        GoalExpr = conj(_, Conjuncts),
-        list.foldl(
-            record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
-            Conjuncts, !ActualRegionArgProc)
-    ;
-        GoalExpr = disj(Disjuncts),
-        list.foldl(
-            record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
-            Disjuncts, !ActualRegionArgProc)
-    ;
-        GoalExpr = if_then_else(_, Cond, Then, Else),
-        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Cond,
-            !ActualRegionArgProc),
-        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Then,
-            !ActualRegionArgProc),
-        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Else,
-            !ActualRegionArgProc)
-    ;
-        GoalExpr = switch(_, _, Cases),
-        list.foldl(
-            record_actual_region_arguments_case(ModuleInfo, CallerPPId,
-                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
-            Cases, !ActualRegionArgProc)
-    ;
-        GoalExpr = generic_call(_, _, _, _),
-        sorry(this_file,
-            "record_actual_region_arguments_expr: generic_call NYI")
-    ;
-        GoalExpr = call_foreign_proc(_, _, _, _, _, _, _),
-        sorry(this_file,
-            "record_actual_region_arguments_expr: call_foreign_proc NYI")
-    ;
-        GoalExpr = negation(SubGoal),
-        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, SubGoal,
-            !ActualRegionArgProc)
-    ;
-        GoalExpr = unify(_, _, _, _, _)
-    ;
-        GoalExpr = scope(_, SubGoal),
-        % XXX We should special-case the handling of from_ground_term_construct
-        % scopes.
-        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
-            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, SubGoal,
-            !ActualRegionArgProc)
-    ;
-        GoalExpr = shorthand(_),
-        unexpected(this_file,
-            "record_actual_region_arguments_expr: shorthand")
-    ).
-
-:- 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_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) :-
-    Case = case(_, _, Goal),
-    record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
-        ConstantRTable, DeadRTable, BornRTable, Goal, !ActualRegionArgProc).
-
-:- pred record_actual_region_arguments_call_site(pred_proc_id::in,
-    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_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,
-        BornRTable, !ActualRegionArgProc) :-
-    map.lookup(ConstantRTable, CalleePPId, CalleeConstantR),
-    map.lookup(DeadRTable, CalleePPId, CalleeDeadR),
-    map.lookup(BornRTable, CalleePPId, CalleeBornR),
-
-    map.lookup(RptaInfoTable, CallerPPId, CallerRptaInfo),
-    CallerRptaInfo = rpta_info(_, CallerAlpha),
-    map.lookup(CallerAlpha, CallSite, AlphaAtCallSite),
-
-    % Actual constant region arguments.
-    set.to_sorted_list(CalleeConstantR, LCalleeConstantR),
-    list.foldl(find_actual_param(AlphaAtCallSite), LCalleeConstantR, [],
-        LActualConstantR0),
-    list.reverse(LActualConstantR0, LActualConstantR),
-
-    % Actual dead region arguments.
-    set.to_sorted_list(CalleeDeadR, LCalleeDeadR),
-    list.foldl(find_actual_param(AlphaAtCallSite), LCalleeDeadR, [],
-        LActualDeadR0),
-    list.reverse(LActualDeadR0, LActualDeadR),
-
-    % Actual born region arguments.
-    set.to_sorted_list(CalleeBornR, LCalleeBornR),
-    list.foldl(find_actual_param(AlphaAtCallSite), LCalleeBornR, [],
-        LActualBornR0),
-    list.reverse(LActualBornR0, LActualBornR),
-
-    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.
-
-find_actual_param(Alpha_PP, Formal, Actuals0, Actuals) :-
-    map.lookup(Alpha_PP, Formal, Actual),
-    Actuals = [Actual | Actuals0].
-
-%-----------------------------------------------------------------------------%
-
-:- func this_file = string.
-
-this_file = "rbmm.actual_region_arguments.m".
-
-%-----------------------------------------------------------------------------%
Index: rbmm.add_rbmm_goal_infos.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.add_rbmm_goal_infos.m,v
retrieving revision 1.8
diff -u -r1.8 rbmm.add_rbmm_goal_infos.m
--- rbmm.add_rbmm_goal_infos.m	2 Sep 2009 00:30:23 -0000	1.8
+++ rbmm.add_rbmm_goal_infos.m	28 Nov 2009 01:52:05 -0000
@@ -41,8 +41,8 @@
 
 :- 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_arguments.
 :- import_module transform_hlds.rbmm.region_resurrection_renaming.
 :- import_module transform_hlds.rbmm.region_transformation.
 
@@ -63,6 +63,8 @@
 :- import_module hlds.hlds_pred.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module libs.globals.
+:- import_module libs.options.
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.
@@ -72,11 +74,12 @@
 :- import_module transform_hlds.rbmm.points_to_graph.
 :- import_module transform_hlds.smm_common.
 
-:- import_module string.
+:- import_module bool.
 :- import_module list.
 :- import_module map.
 :- import_module maybe.
 :- import_module set.
+:- import_module string.
 
 %-----------------------------------------------------------------------------%
 %
@@ -163,7 +166,7 @@
     collect_rbmm_goal_info_unification(Unification, ModuleInfo, Graph,
         ResurRenaming, IteRenaming, NameToRegionVar, !Info).
 
-collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, _,
+collect_rbmm_goal_info_goal_expr(ModuleInfo, ProcInfo, Graph,
         ActualRegionArgumentProc, _, _, _, !Expr, !Info) :-
     !.Expr = plain_call(PredId, ProcId, Args, _, _, _),
     CalleePPId = proc(PredId, ProcId),
@@ -189,7 +192,7 @@
         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),
+        ActualRegionArgs = region_args(Constants, Inputs, _Outputs),
         list.det_split_list(list.length(Constants), RegionArgs,
             CarriedRegions, RemovedAndCreated),
         list.det_split_list(list.length(Inputs), RemovedAndCreated,
@@ -198,12 +201,55 @@
         % are allocated into and read from in this call.
         AllocatedIntoAndReadFrom =
             set.from_list(RemovedRegions ++ CarriedRegions),
+
+        module_info_get_globals(ModuleInfo, Globals),
+        globals.lookup_bool_option(Globals, use_alloc_regions,
+            UseAllocRegions),
+        (
+            UseAllocRegions = yes,
+            % Keep only the regions that are removed but also allocated into.
+            keep_allocated_regions(Inputs, RemovedRegions, Graph,
+                RemovedAndAllocRegions),
+            % Allocated regions are the above plus the carried ones.
+            % The carried here are those that are also allocated into.
+            AllocatedIntoRegions =
+                set.from_list(RemovedAndAllocRegions ++ CarriedRegions)
+        ;
+            UseAllocRegions = no,
+            AllocatedIntoRegions = AllocatedIntoAndReadFrom
+        ),
+
+        % The read-from set is not very important so we are not precise
+        % in estimating it.
         RbmmGoalInfo = rbmm_goal_info(set.from_list(CreatedRegions),
             set.from_list(RemovedRegions), set.from_list(CarriedRegions),
-            AllocatedIntoAndReadFrom, AllocatedIntoAndReadFrom),
+            AllocatedIntoRegions, AllocatedIntoAndReadFrom),
         goal_info_set_maybe_rbmm(yes(RbmmGoalInfo), !Info)
      ).
 
+    % The elements in the first and second lists are corresponding.
+    % Ones in the first list are the nodes in rpt graph therefore we can
+    % check their allocated property, ones in the second list are prog_vars
+    % (after renaming) that represent those in the first.
+    %
+:- pred keep_allocated_regions(list(rptg_node)::in, list(prog_var)::in,
+    rpt_graph::in, list(prog_var)::out) is det.
+
+keep_allocated_regions([], [], _, []).
+keep_allocated_regions([], [_ | _], _, []) :-
+    unexpected(this_file, "keep_allocated_regions: length mismatch").
+keep_allocated_regions([_ | _], [], _, []) :-
+    unexpected(this_file, "keep_allocated_regions: length mismatch").
+keep_allocated_regions([Input | Inputs], [RemovedRegion | RemovedRegions],
+        Graph, RemovedAndAllocRegions) :-
+    keep_allocated_regions(Inputs, RemovedRegions, Graph,
+        RemovedAndAllocRegions0), 
+    ( rptg_is_allocated_node(Graph, Input) ->
+        RemovedAndAllocRegions = [RemovedRegion | RemovedAndAllocRegions0]
+    ;
+        RemovedAndAllocRegions = RemovedAndAllocRegions0
+    ). 
+    
     % 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
@@ -440,6 +486,8 @@
           then
                 goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
           else
+                % We need to try to apply renaming here because the
+                % region name in the Graph may need to be changed.
                 OriginalName = rptg_lookup_region_name(Graph, Node),
                 ( map.search(ResurRenaming, OriginalName, ResurNameList) ->
                     Name = list.det_last(ResurNameList)
@@ -448,18 +496,29 @@
                 ;
                     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)),
+
+                % This region may only be read from in the procedure containing
+                % this deconstruction therefore there might be no entry for it
+                % in RegionNameToVar.
+                ( map.search(RegionNameToVar, Name, RegionVar) ->
+                    RbmmInfo = rbmm_goal_info(set.init, set.init,
+                        set.make_singleton_set(RegionVar),
+                        set.init, set.make_singleton_set(RegionVar))
+                ;
+                    RbmmInfo = rbmm_info_init
+                ),
                 goal_info_set_maybe_rbmm(yes(RbmmInfo), !Info)
         )
     ;
-        ( Unification = assign(_, _)
+        (
+          % XXX We do have assignments between two region variables. But
+          % we do not consider either of them created or removed because
+          % the region they are bound to is still there, i.e., it has been
+          % created and will not be removed.
+          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)
+        goal_info_set_maybe_rbmm(yes(rbmm_info_init), !Info)
     ;
         Unification = complicated_unify(_, _, _),
         unexpected(this_file, "collect_rbmm_goal_info_unification:"
Index: rbmm.interproc_region_lifetime.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.interproc_region_lifetime.m,v
retrieving revision 1.4
diff -u -r1.4 rbmm.interproc_region_lifetime.m
--- rbmm.interproc_region_lifetime.m	6 Sep 2007 12:45:24 -0000	1.4
+++ rbmm.interproc_region_lifetime.m	28 Nov 2009 01:52:05 -0000
@@ -144,7 +144,7 @@
 
 :- type rule_pred == (
         pred(pred_proc_id, region_set, region_set, proc_region_set_table,
-            map(rptg_node, rptg_node), region_set)
+            rpt_call_alpha_mapping, region_set)
     ).
 :- inst rule_pred == ( pred(in, in, in, in, in, out) is det ).
 
@@ -347,8 +347,8 @@
     % Rules for eliminating regions from deadR set.
     %
 :- pred dead_removal_rules(pred_proc_id::in, region_set::in, region_set::in,
-    proc_region_set_table::in, map(rptg_node, rptg_node)::in,
-    region_set::out) is det.
+    proc_region_set_table::in, rpt_call_alpha_mapping::in, region_set::out)
+    is det.
 
 dead_removal_rules(Q_Id, LRBefore, LRAfter, DeadRTable, AlphaAtPP, DeadR_q) :-
     % The current deadR of q.
@@ -364,7 +364,7 @@
     targets_with_more_than_one_source(AlphaAtPP, Targets),
     set.fold(dead_removal_rule_2(AlphaAtPP), Targets, DeadR_q1, DeadR_q).
 
-:- pred dead_removal_rule_1(map(rptg_node, rptg_node)::in, rptg_node::in,
+:- pred dead_removal_rule_1(rpt_call_alpha_mapping::in, rptg_node::in,
     region_set::in, region_set::out) is det.
 
 dead_removal_rule_1(AlphaAtCallSite, Region, !DeadR_q) :-
@@ -375,7 +375,7 @@
     % Remove any r' that is in deadR(q).
     set.difference(!.DeadR_q, RPrimes, !:DeadR_q).
 
-:- pred dead_removal_rule_2(map(rptg_node, rptg_node)::in, rptg_node::in,
+:- pred dead_removal_rule_2(rpt_call_alpha_mapping::in, rptg_node::in,
     set(rptg_node)::in, set(rptg_node)::out) is det.
 
 dead_removal_rule_2(AlphaAtCallSite, Region, !DeadR_q) :-
@@ -386,7 +386,7 @@
     % rules for eliminating regions from bornR set.
     %
 :- pred born_removal_rules(pred_proc_id::in, region_set::in, region_set::in,
-    proc_region_set_table::in, map(rptg_node, rptg_node)::in,
+    proc_region_set_table::in, rpt_call_alpha_mapping::in,
     region_set::out) is det.
 
 born_removal_rules(Q_Id, LRBefore, _, BornRTable, AlphaAtCallSite, BornR_q) :-
@@ -403,7 +403,7 @@
     set.fold(born_removal_rule_2(AlphaAtCallSite), Targets,
         BornR_q1, BornR_q).
 
-:- pred born_removal_rule_1(map(rptg_node, rptg_node)::in, rptg_node::in,
+:- pred born_removal_rule_1(rpt_call_alpha_mapping::in, rptg_node::in,
     set(rptg_node)::in, set(rptg_node)::out) is det.
 
 born_removal_rule_1(AlphaAtCallSite, Region, !BornR_q) :-
@@ -414,7 +414,7 @@
     % alpha(r') = r, alpha(r'') = r, r', r'' in bornR(q) imply remove r',
     % r'' from bornR(q).
     %
-:- pred born_removal_rule_2(map(rptg_node, rptg_node)::in, rptg_node::in,
+:- pred born_removal_rule_2(rpt_call_alpha_mapping::in, rptg_node::in,
     set(rptg_node)::in, set(rptg_node)::out) is det.
 
 born_removal_rule_2(AlphaAtCallSite, Region, !BornR_q) :-
@@ -425,7 +425,7 @@
     % Find targets of alpha mapping that are mapped to by more than one
     % source.
     %
-:- pred targets_with_more_than_one_source(map(rptg_node, rptg_node)::in,
+:- pred targets_with_more_than_one_source(rpt_call_alpha_mapping::in,
     region_set::out) is det.
 
 targets_with_more_than_one_source(AlphaAtCallSite, Targets) :-
Index: rbmm.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
retrieving revision 1.9
diff -u -r1.9 rbmm.m
--- rbmm.m	23 Apr 2009 10:00:24 -0000	1.9
+++ rbmm.m	28 Nov 2009 01:52:05 -0000
@@ -16,7 +16,7 @@
 :- module transform_hlds.rbmm.
 :- interface.
 
-:- include_module actual_region_arguments.
+:- include_module add_rbmm_goal_infos.
 :- include_module condition_renaming.
 :- include_module execution_path.
 :- include_module interproc_region_lifetime.
@@ -25,7 +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_arguments.
 :- include_module region_instruction.
 :- include_module region_liveness_info.
 :- include_module region_resurrection_renaming.
@@ -45,7 +45,6 @@
 
 :- implementation.
 
-:- import_module transform_hlds.rbmm.actual_region_arguments.
 :- import_module transform_hlds.rbmm.condition_renaming.
 :- import_module transform_hlds.rbmm.execution_path.
 :- import_module transform_hlds.rbmm.interproc_region_lifetime.
@@ -53,6 +52,7 @@
 :- 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_arguments.
 :- import_module transform_hlds.rbmm.region_instruction.
 :- import_module transform_hlds.rbmm.region_resurrection_renaming.
 :- import_module transform_hlds.rbmm.region_transformation.
@@ -84,9 +84,9 @@
         BecomeLiveTable, BecomeDeadBeforeTable, BecomeDeadAfterTable,
         RegionInstructionTable),
 
-    record_actual_region_arguments(!.ModuleInfo, RptaInfoTable,
-        ConstantRTable, DeadRTable, BornRTable,
-        ActualRegionArgumentTable),
+    record_region_arguments(!.ModuleInfo, RptaInfoTable,
+        ConstantRTable, DeadRTable, BornRTable, FormalRegionArgTable,
+        ActualRegionArgTable),
 
     % The region analysis treats region variables as if they are
     % imperative-style updatable variables. They may also have scopes
@@ -119,12 +119,12 @@
         RptaInfoTable, IteRenamingTable0, IteRenamingTable,
         IteRenamingAnnoTable),
 
-    region_transform(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
-        ActualRegionArgumentTable, ResurRenamingTable, IteRenamingTable,
-        RegionInstructionTable, ResurRenamingAnnoTable,
+    region_transform(RptaInfoTable, FormalRegionArgTable,
+        ActualRegionArgTable, ResurRenamingTable,
+        IteRenamingTable, RegionInstructionTable, ResurRenamingAnnoTable,
         IteRenamingAnnoTable, map.init, NameToVarTable, !ModuleInfo),
     
-    collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgumentTable,
+    collect_rbmm_goal_info(RptaInfoTable, ActualRegionArgTable,
         ResurRenamingTable, IteRenamingTable, NameToVarTable, !ModuleInfo).
 
 %-----------------------------------------------------------------------------%
Index: rbmm.points_to_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.points_to_analysis.m,v
retrieving revision 1.12
diff -u -r1.12 rbmm.points_to_analysis.m
--- rbmm.points_to_analysis.m	19 Aug 2009 07:44:57 -0000	1.12
+++ rbmm.points_to_analysis.m	28 Nov 2009 01:52:05 -0000
@@ -772,7 +772,7 @@
     %
 :- pred alpha_mapping_at_call_site(list(prog_var)::in, list(prog_var)::in,
     rpt_graph::in, rpt_graph::in, rpt_graph::out,
-    map(rptg_node, rptg_node)::in, map(rptg_node, rptg_node)::out) is det.
+    rpt_call_alpha_mapping::in, rpt_call_alpha_mapping::out) is det.
 
 alpha_mapping_at_call_site([], [], _, !CallerGraph, !AlphaMap).
 alpha_mapping_at_call_site([], [_ | _], _, _, _, _, _) :-
@@ -781,30 +781,33 @@
 alpha_mapping_at_call_site([_ | _], [], _, _, _, _, _) :-
     unexpected(this_file,
         "alpha_mapping_at_call_site: actuals and formals do not match.").
-    % Xi's are formal arguments, Yi's are actual arguments at the call site
-    %
 alpha_mapping_at_call_site([Xi | Xs], [Yi | Ys], CalleeGraph,
         !CallerGraph, !AlphaMap) :-
+    % Xi's are formal arguments, Yi's are actual arguments at the call site.
     rptg_get_node_by_variable(CalleeGraph, Xi, N_Xi),
     rptg_get_node_by_variable(!.CallerGraph, Yi, N_Yi),
     ( map.search(!.AlphaMap, N_Xi, N_Y) ->
         % alpha(N_Xi) = N_Y, alpha(N_Xi) = N_Yi, N_Y != N_Yi.
         %
-        ( N_Y \= N_Yi ->
+        ( N_Y = N_Yi ->
+            true
+        ;
             % Apply rule P4.
             unify_operator(N_Y, N_Yi, !CallerGraph),
 
             % Apply rule P1 after some nodes are unified.
             rule_1(N_Y, !CallerGraph)
-        ;
-            true
         )
     ;
         svmap.set(N_Xi, N_Yi, !AlphaMap),
 
-        % N_Yi inherits N_Xi's is_allocated.
-        IsAlloc = rptg_lookup_node_is_allocated(CalleeGraph, N_Xi),
-        rptg_set_node_is_allocated(N_Yi, IsAlloc, !CallerGraph)
+        % If N_Xi's is_allocated then N_Yi is also allocated.
+        % Otherwise leave N_Yi alone.
+        ( rptg_is_allocated_node(CalleeGraph, N_Xi) ->
+            rptg_set_node_is_allocated(N_Yi, bool.yes, !CallerGraph)
+        ;
+           true
+        )
     ),
     alpha_mapping_at_call_site(Xs, Ys, CalleeGraph, !CallerGraph, !AlphaMap).
 
@@ -930,9 +933,12 @@
             svmap.set(CalleeM, CallerM, AlphaAtCallSite0, AlphaAtCallSite1),
             svmap.set(CallSite, AlphaAtCallSite1, !CallerAlphaMapping),
 
-            % CallerM inherits CalleeM's is_allocated.
-            IsAlloc = rptg_lookup_node_is_allocated(CalleeGraph, CalleeM),
-            rptg_set_node_is_allocated(CallerM, IsAlloc, !CallerGraph)
+            % If CalleeM's is_allocated then CallerM is also allocated. 
+            % Otherwise leave CallerM alone.
+            ( rptg_is_allocated_node(CalleeGraph, CalleeM) ->
+                rptg_set_node_is_allocated(CallerM, bool.yes, !CallerGraph)
+            ;   true
+            )
         )
       else
         true
Index: rbmm.points_to_graph.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.points_to_graph.m,v
retrieving revision 1.4
diff -u -r1.4 rbmm.points_to_graph.m
--- rbmm.points_to_graph.m	21 Apr 2009 14:05:55 -0000	1.4
+++ rbmm.points_to_graph.m	28 Nov 2009 01:52:05 -0000
@@ -179,6 +179,8 @@
 :- func rptg_lookup_node_vars(rpt_graph, rptg_node) = set(prog_var).
 :- func rptg_lookup_node_is_allocated(rpt_graph, rptg_node) = bool.
 
+:- pred rptg_is_allocated_node(rpt_graph::in, rptg_node::in) is semidet.
+
     % Return the list of edges (edge id's).
     %
 :- func rptg_lookup_list_outedges(rpt_graph, rptg_node) = list(rptg_edge).
@@ -589,6 +591,10 @@
     NodeContent = rptg_get_node_content(Graph, Node),
     IsAllocated = rptg_node_content_get_is_allocated(NodeContent).
 
+rptg_is_allocated_node(Graph, Region) :-
+    IsAlloc = rptg_lookup_node_is_allocated(Graph, Region),
+    IsAlloc = bool.yes.
+
 rptg_lookup_list_outedges(Graph, Node) = EdgeList :-
     OutEdgesOfNode = rptg_lookup_map_outedges(Graph, Node),
     map.keys(OutEdgesOfNode, EdgeList).
@@ -987,9 +993,6 @@
     Processed = [Node | Processed0],
 
     % Take out-edges of the Node and update the remembered list.
-    %OutEdges = rptg_get_outedges(Graph),
-    %map.lookup(OutEdges, Node, OutEdgesOfNode),
-    %map.keys(OutEdgesOfNode, EdgeList),
     EdgeList = rptg_lookup_list_outedges(Graph, Node),
     list.foldl(
         update_remembered_list(Selector, HLDS, TypeX, Graph, Processed),
Index: rbmm.points_to_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.points_to_info.m,v
retrieving revision 1.4
diff -u -r1.4 rbmm.points_to_info.m
--- rbmm.points_to_info.m	21 Apr 2009 14:05:55 -0000	1.4
+++ rbmm.points_to_info.m	28 Nov 2009 01:52:05 -0000
@@ -37,8 +37,6 @@
 :- pred rpta_info_table_set_rpta_info(pred_proc_id::in, rpta_info::in,
     rpta_info_table::in, rpta_info_table::out) is det.
 
-    % type rpta_info and operations
-    %
 :- type rpta_info
         ---> rpta_info(rpt_graph, rpt_alpha_mapping).
 
@@ -52,7 +50,16 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type rpt_alpha_mapping == map(program_point, map(rptg_node, rptg_node)).
+    % This type represents the alpha mapping of all call sites in a procedure.
+    % For documentation of alpha mappings, see Chapter 4 in Quan's thesis;
+    % basically, they map the nodes in the region points-to graph of the callee
+    % to the corresponding nodes in the caller.
+    %
+:- type rpt_alpha_mapping == map(program_point, rpt_call_alpha_mapping).
+
+    % This type represents the alpha mapping at one call site.
+    %
+:- type rpt_call_alpha_mapping == map(rptg_node, rptg_node).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -77,15 +84,13 @@
 %-----------------------------------------------------------------------------%
 
 rpta_info_table_init = map.init.
+
 rpta_info_table_search_rpta_info(PredProcId, Table) = RptaInfo :-
     Table ^ elem(PredProcId) = RptaInfo.
-rpta_info_table_set_rpta_info(PredProcId, RptaInfo, Table0, Table) :-
-    Table = Table0 ^ elem(PredProcId) := RptaInfo.
 
-    % The rpta_info will be for a specific procedure, so at the beginning
-    % the alpha mapping is empty and the rpt graph contains all the nodes
-    % corresponding to all the variables appear in the procedure.
-    %
+rpta_info_table_set_rpta_info(PredProcId, RptaInfo, !Table) :-
+    !Table ^ elem(PredProcId) := RptaInfo.
+
 rpta_info_init(ProcInfo) = RptaInfo :-
     proc_info_get_vartypes(ProcInfo, VarTypes),
     map.keys(VarTypes, Vars),
@@ -139,8 +144,8 @@
         AlphaMappingAtCallSiteA,AlphaMappingAtCallSiteB),
     rpt_alpha_mapping_equal_2(CallSiteAs, AlphaMappingA, AlphaMappingB).
 
-:- pred rpt_alpha_mapping_at_call_site_equal(map(rptg_node, rptg_node)::in,
-    map(rptg_node, rptg_node)::in) is semidet.
+:- pred rpt_alpha_mapping_at_call_site_equal(rpt_call_alpha_mapping::in,
+    rpt_call_alpha_mapping::in) is semidet.
 
 rpt_alpha_mapping_at_call_site_equal(AMAtCallSiteA, AMAtCallSiteB) :-
     map.count(AMAtCallSiteA, CA),
@@ -151,7 +156,7 @@
         AMAtCallSiteB).
 
 :- pred rpt_alpha_mapping_at_call_site_equal_2(list(rptg_node)::in,
-    map(rptg_node, rptg_node)::in, map(rptg_node, rptg_node)::in) is semidet.
+    rpt_call_alpha_mapping::in, rpt_call_alpha_mapping::in) is semidet.
 
 rpt_alpha_mapping_at_call_site_equal_2([], _, _).
 rpt_alpha_mapping_at_call_site_equal_2([N | Ns], AMAtCallSiteA,
Index: rbmm.region_arguments.m
===================================================================
RCS file: rbmm.region_arguments.m
diff -N rbmm.region_arguments.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ rbmm.region_arguments.m	28 Nov 2009 01:52:06 -0000
@@ -0,0 +1,334 @@
+% -----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2009 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.region_arguments.m.
+% Main author: qph.
+%
+% We will pass regions as extra arguments in procedure calls.
+% After the region liveness analysis we can decide on what region variables
+% need to be region arguments (for procedures and calls).
+% This module derives the formal region arguments for procedures and
+% the actual region arguments at call sites in each procedure.
+% This information will be used to extend the argument lists of procedures
+% and calls in the HLDS.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- module transform_hlds.rbmm.region_arguments.
+:- interface.
+
+:- import_module hlds.
+:- import_module hlds.hlds_module.
+:- import_module hlds.hlds_pred.
+:- import_module transform_hlds.rbmm.points_to_graph.
+:- import_module transform_hlds.rbmm.points_to_info.
+:- import_module transform_hlds.rbmm.region_liveness_info.
+:- import_module transform_hlds.smm_common.
+
+:- import_module list.
+:- import_module map.
+
+:- type proc_formal_region_args_table
+    ==  map(
+                pred_proc_id,
+                region_args
+        ).
+
+:- type proc_pp_actual_region_args_table
+    ==  map(
+                pred_proc_id,
+                pp_actual_region_args_table
+        ).
+
+:- type pp_actual_region_args_table
+    ==  map(
+                program_point,
+                region_args
+        ).
+
+:- type region_args
+    --->    region_args(
+                list(rptg_node),    % constant (carried) region arguments.
+                list(rptg_node),    % inputs (removed).
+                list(rptg_node)     % outputs (created).
+            ).
+
+:- pred record_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_formal_region_args_table::out,
+    proc_pp_actual_region_args_table::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module check_hlds.
+:- import_module check_hlds.goal_path.
+:- import_module hlds.hlds_goal.
+:- import_module libs.
+:- import_module libs.compiler_util.
+
+:- import_module set.
+:- import_module string.
+:- import_module svmap.
+
+record_region_arguments(ModuleInfo, RptaInfoTable, ConstantRTable,
+        DeadRTable, BornRTable, FormalRegionArgTable, ActualRegionArgTable) :-
+    module_info_predids(PredIds, ModuleInfo, _),
+    list.foldl2(record_actual_region_arguments_pred(ModuleInfo,
+        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+        PredIds, map.init, FormalRegionArgTable,
+        map.init, ActualRegionArgTable).
+
+:- 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_formal_region_args_table::in,
+    proc_formal_region_args_table::out,
+    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,
+        !FormalRegionArgTable, !ActualRegionArgTable) :-
+    module_info_pred_info(ModuleInfo, PredId, PredInfo),
+    ProcIds = pred_info_non_imported_procids(PredInfo),
+    list.foldl2(record_region_arguments_proc(ModuleInfo, PredId,
+        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable), ProcIds,
+        !FormalRegionArgTable, !ActualRegionArgTable).
+
+:- pred record_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_formal_region_args_table::in,
+    proc_formal_region_args_table::out,
+    proc_pp_actual_region_args_table::in,
+    proc_pp_actual_region_args_table::out) is det.
+
+record_region_arguments_proc(ModuleInfo, PredId, RptaInfoTable,
+        ConstantRTable, DeadRTable, BornRTable, ProcId,
+        !FormalRegionArgTable, !ActualRegionArgTable) :-
+    PPId = proc(PredId, ProcId),
+    ( if    some_are_special_preds([PPId], ModuleInfo)
+      then  true
+      else
+            record_formal_region_arguments_proc(PPId, RptaInfoTable,
+                ConstantRTable, DeadRTable, BornRTable, !FormalRegionArgTable),
+
+            module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
+            fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+            proc_info_get_goal(ProcInfo, Body),
+            record_actual_region_arguments_goal(ModuleInfo, PPId,
+                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Body,
+                !FormalRegionArgTable, map.init, ActualRegionArgProc),
+            svmap.set(PPId, ActualRegionArgProc, !ActualRegionArgTable)
+    ).
+
+:- pred record_formal_region_arguments_proc(pred_proc_id::in,
+    rpta_info_table::in, proc_region_set_table::in,
+    proc_region_set_table::in, proc_region_set_table::in,
+    proc_formal_region_args_table::in, proc_formal_region_args_table::out)
+    is det.
+
+record_formal_region_arguments_proc(PPId, RptaInfoTable,
+        ConstantRTable, DeadRTable, BornRTable, !FormalRegionArgTable) :-
+    ( map.search(!.FormalRegionArgTable, PPId, _) ->
+        true
+    ;
+        map.lookup(ConstantRTable, PPId, ConstantR),
+        map.lookup(DeadRTable, PPId, DeadR),
+        map.lookup(BornRTable, PPId, BornR),
+
+        map.lookup(RptaInfoTable, PPId, RptaInfo),
+        RptaInfo = rpta_info(Graph, _),
+
+        % Formal constant, allocated-into region arguments.
+        set.to_sorted_list(ConstantR, LConstantR),
+        list.filter(rptg_is_allocated_node(Graph),
+            LConstantR, LFormalConstantAllocR),
+
+        % Formal dead region arguments.
+        set.to_sorted_list(DeadR, FormalDeadR),
+
+        % Formal born region arguments.
+        set.to_sorted_list(BornR, FormalBornR),
+
+        svmap.det_insert(PPId,
+            region_args(LFormalConstantAllocR, FormalDeadR, FormalBornR),
+            !FormalRegionArgTable)
+    ).
+
+:- 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,
+    proc_formal_region_args_table::in, proc_formal_region_args_table::out,
+    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,
+        !FormalRegionArgTable, !ActualRegionArgProc) :-
+    Goal = hlds_goal(Expr, Info),
+    record_actual_region_arguments_expr(Expr, Info, ModuleInfo, PPId,
+        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+        !FormalRegionArgTable, !ActualRegionArgProc).
+
+:- pred record_actual_region_arguments_expr(hlds_goal_expr::in,
+    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,
+    proc_formal_region_args_table::in, proc_formal_region_args_table::out,
+    pp_actual_region_args_table::in, pp_actual_region_args_table::out) is det.
+
+record_actual_region_arguments_expr(GoalExpr, GoalInfo, ModuleInfo, CallerPPId,
+        RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+        !FormalRegionArgTable, !ActualRegionArgProc) :-
+    (
+        GoalExpr = plain_call(PredId, ProcId, _, _, _, _),
+        CalleePPId = proc(PredId, ProcId),
+        ( some_are_special_preds([CalleePPId], ModuleInfo) ->
+            true
+        ;
+            CallSite = program_point_init(GoalInfo),
+            record_actual_region_arguments_call_site(CallerPPId, CallSite,
+                CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
+                BornRTable, !FormalRegionArgTable, !ActualRegionArgProc)
+        )
+    ;
+        GoalExpr = conj(_, Conjuncts),
+        list.foldl2(
+            record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+            Conjuncts, !FormalRegionArgTable, !ActualRegionArgProc)
+    ;
+        GoalExpr = disj(Disjuncts),
+        list.foldl2(
+            record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+            Disjuncts, !FormalRegionArgTable, !ActualRegionArgProc)
+    ;
+        GoalExpr = if_then_else(_, Cond, Then, Else),
+        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Cond,
+            !FormalRegionArgTable, !ActualRegionArgProc),
+        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Then,
+            !FormalRegionArgTable, !ActualRegionArgProc),
+        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, Else,
+            !FormalRegionArgTable, !ActualRegionArgProc)
+    ;
+        GoalExpr = switch(_, _, Cases),
+        list.foldl2(
+            record_actual_region_arguments_case(ModuleInfo, CallerPPId,
+                RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+            Cases, !FormalRegionArgTable, !ActualRegionArgProc)
+    ;
+        GoalExpr = generic_call(_, _, _, _),
+        sorry(this_file,
+            "record_actual_region_arguments_expr: generic_call NYI")
+    ;
+        GoalExpr = call_foreign_proc(_, _, _, _, _, _, _),
+        sorry(this_file,
+            "record_actual_region_arguments_expr: call_foreign_proc NYI")
+    ;
+        GoalExpr = negation(SubGoal),
+        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, SubGoal,
+            !FormalRegionArgTable, !ActualRegionArgProc)
+    ;
+        GoalExpr = unify(_, _, _, _, _)
+    ;
+        GoalExpr = scope(_, SubGoal),
+        % XXX We should special-case the handling of from_ground_term_construct
+        % scopes.
+        record_actual_region_arguments_goal(ModuleInfo, CallerPPId,
+            RptaInfoTable, ConstantRTable, DeadRTable, BornRTable, SubGoal,
+            !FormalRegionArgTable, !ActualRegionArgProc)
+    ;
+        GoalExpr = shorthand(_),
+        unexpected(this_file,
+            "record_actual_region_arguments_expr: shorthand")
+    ).
+
+:- 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,
+    proc_formal_region_args_table::in, proc_formal_region_args_table::out,
+    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,
+        !FormalRegionArgTable, !ActualRegionArgProc) :-
+    Case = case(_, _, Goal),
+    record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+        ConstantRTable, DeadRTable, BornRTable, Goal, 
+        !FormalRegionArgTable, !ActualRegionArgProc).
+
+    % Region variables in deadR and in bornR are passed as arguments.
+    % Out of the region variables in constantR (constant in the sense that
+    % their bindings will not change during the call) we only pass ones that
+    % may be allocated into as arguments. The actual region arguments are
+    % computed according to these lines.
+    %
+:- pred record_actual_region_arguments_call_site(pred_proc_id::in,
+    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,
+    proc_formal_region_args_table::in, proc_formal_region_args_table::out,
+    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,
+        BornRTable, !FormalRegionArgTable, !ActualRegionArgProc) :-
+    ( map.search(!.FormalRegionArgTable, CalleePPId, FormalRegionArgCallee) ->
+        % If the formal region arguments of the called procedure have been
+        % computed, the corresponding actual ones can be straightforwardly
+        % derived using the call site's alpha mapping.
+        FormalRegionArgCallee =
+            region_args(FormalConstants, FormalDeads, FormalBorns),
+        map.lookup(RptaInfoTable, CallerPPId, CallerRptaInfo),
+        CallerRptaInfo = rpta_info(_CallerGraph, CallerAlpha),
+        map.lookup(CallerAlpha, CallSite, AlphaAtCallSite),
+        list.foldr(find_actual_param(AlphaAtCallSite), FormalConstants,
+            [], ActualConstants),
+        list.foldr(find_actual_param(AlphaAtCallSite), FormalDeads,
+            [], ActualDeads),
+        list.foldr(find_actual_param(AlphaAtCallSite), FormalBorns,
+            [], ActualBorns),
+        svmap.det_insert(CallSite,
+            region_args(ActualConstants, ActualDeads, ActualBorns),
+            !ActualRegionArgProc)
+    ;
+        % The formal region arguments of the called procedure haven't been
+        % recorded, so do it now.
+        record_formal_region_arguments_proc(CalleePPId, RptaInfoTable,
+            ConstantRTable, DeadRTable, BornRTable, !FormalRegionArgTable),
+
+        % We try again at this call site after the formal region arguments
+        % are recorded.
+        record_actual_region_arguments_call_site(CallerPPId, CallSite,
+            CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
+            BornRTable, !FormalRegionArgTable, !ActualRegionArgProc)
+    ).
+
+:- pred find_actual_param(rpt_call_alpha_mapping::in, rptg_node::in,
+    list(rptg_node)::in, list(rptg_node)::out) is det.
+
+find_actual_param(Alpha_PP, Formal, Actuals0, Actuals) :-
+    map.lookup(Alpha_PP, Formal, Actual),
+    Actuals = [Actual | Actuals0].
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "rbmm.region_arguments.m".
+
+%-----------------------------------------------------------------------------%
Index: rbmm.region_transformation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_transformation.m,v
retrieving revision 1.12
diff -u -r1.12 rbmm.region_transformation.m
--- rbmm.region_transformation.m	8 Sep 2009 02:43:38 -0000	1.12
+++ rbmm.region_transformation.m	28 Nov 2009 01:52:06 -0000
@@ -27,10 +27,9 @@
 :- import_module hlds.hlds_pred.
 :- import_module parse_tree.
 :- import_module parse_tree.prog_data.
-:- import_module transform_hlds.rbmm.actual_region_arguments.
 :- import_module transform_hlds.rbmm.points_to_info.
+:- import_module transform_hlds.rbmm.region_arguments.
 :- import_module transform_hlds.rbmm.region_instruction.
-:- import_module transform_hlds.rbmm.region_liveness_info.
 :- import_module transform_hlds.rbmm.region_resurrection_renaming.
 
 :- import_module map.
@@ -45,21 +44,24 @@
 :- type name_to_prog_var == map(string, prog_var).
 
     % The names of the predicates for creating and removing regions.
-    % The predicates are in mercury_region_builtin_module.
+    % The predicates are in region_builtin library module.
     %
 :- func create_region_pred_name = string.
 :- func remove_region_pred_name = string.
 
-    % XXX Besides changing the HLDS, this predicate also returns a mapping
-    % from a region name to a program variable which represents the
-    % region. We will only create a new program variable for a region
-    % name which is not yet in the map. Currently this map is only used
-    % in this transformation. If we do not need the map later on we should
-    % not return it.
+    % Besides changing the HLDS with region information, this predicate also
+    % returns a mapping from a region name to a program variable which
+    % represents the region. We will only create a new program variable for a
+    % region name which is not yet in the map. This information is needed when
+    % computing rbmm_goal_info. Note that because we only pass as argument to
+    % a procedure a region that will be allocated into, be removed, or be
+    % created in the procedure, some regions in the rpt graph of the procedure
+    % may not need to be presented by program variables. They are the regions
+    % that only be read from in the procedure. Therefore there are NO entries
+    % for them in the region_name-to-prog_var map.
     %
-:- pred region_transform(rpta_info_table::in, proc_region_set_table::in,
-    proc_region_set_table::in, proc_region_set_table::in,
-    proc_pp_actual_region_args_table::in,
+:- pred region_transform(rpta_info_table::in,
+    proc_formal_region_args_table::in, proc_pp_actual_region_args_table::in,
     renaming_table::in, renaming_table::in, region_instr_table::in,
     renaming_annotation_table::in, renaming_annotation_table::in,
     name_to_prog_var_table::in, name_to_prog_var_table::out,
@@ -105,15 +107,13 @@
 create_region_pred_name = "create_region".
 remove_region_pred_name = "remove_region".
 
-region_transform(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+region_transform(RptaInfoTable, FormalRegionArgTable, ActualRegionArgTable,
+        ResurRenamingTable, IteRenamingTable, RegionInstructionTable,
+        ResurRenamingAnnoTable, IteRenamingAnnoTable, !NameToVarTable,
+        !ModuleInfo) :-
+    map.foldl2(annotate_pred, FormalRegionArgTable, [], PredIds, !ModuleInfo),
+    list.foldl2(region_transform_pred(RptaInfoTable, FormalRegionArgTable,
         ActualRegionArgTable, ResurRenamingTable, IteRenamingTable,
-        RegionInstructionTable, ResurRenamingAnnoTable, IteRenamingAnnoTable,
-        !NameToVarTable, !ModuleInfo) :-
-    map.foldl2(annotate_pred(DeadRTable, BornRTable), ConstantRTable, [],
-        PredIds, !ModuleInfo),
-    list.foldl2(region_transform_pred(RptaInfoTable,
-        ConstantRTable, DeadRTable, BornRTable, ActualRegionArgTable,
-        ResurRenamingTable, IteRenamingTable,
         RegionInstructionTable, ResurRenamingAnnoTable, IteRenamingAnnoTable),
         PredIds, !NameToVarTable, !ModuleInfo),
 
@@ -121,7 +121,6 @@
     % annotated with region information and recorded. This is necessary
     % because recompute_instmap_delta_proc and repuritycheck_proc need to
     % look up information about the (annotated) called procedures.
-
     list.foldl(update_instmap_delta_pred, PredIds, !ModuleInfo),
     list.foldl(recheck_purity_pred, PredIds, !ModuleInfo).
 
@@ -133,22 +132,20 @@
     % 2. Argument types: arg_types, updated with region type for region
     %    arguments.
     %
-:- pred annotate_pred(proc_region_set_table::in, proc_region_set_table::in,
-    pred_proc_id::in, region_set::in, list(pred_id)::in, list(pred_id)::out,
+:- pred annotate_pred(pred_proc_id::in, region_args::in,
+    list(pred_id)::in, list(pred_id)::out,
     module_info::in, module_info::out) is det.
 
-annotate_pred(DeadRTable, BornRTable, PPId, ConstantR, !Processed,
-        !ModuleInfo) :-
+annotate_pred(PPId, FormalRegionArgs, !Processed, !ModuleInfo) :-
     PPId = proc(PredId, _),
     ( list.member(PredId, !.Processed) ->
         true
     ;
         some [!PredInfo] (
             module_info_pred_info(!.ModuleInfo, PredId, !:PredInfo),
-            map.lookup(DeadRTable, PPId, DeadR),
-            map.lookup(BornRTable, PPId, BornR),
-            NumberOfRegArgs = set.count(DeadR) + set.count(BornR) +
-                set.count(ConstantR),
+            FormalRegionArgs = region_args(Constants, Deads, Borns),
+            NumberOfRegArgs = list.length(Constants) + list.length(Deads) +
+                list.length(Borns),
             Arity = pred_info_orig_arity(!.PredInfo),
             pred_info_set_orig_arity(Arity + NumberOfRegArgs, !PredInfo),
 
@@ -174,22 +171,22 @@
 
     % This predicate transforms the procedures of a predicate.
     %
-:- pred region_transform_pred(rpta_info_table::in, proc_region_set_table::in,
-    proc_region_set_table::in, proc_region_set_table::in,
+:- pred region_transform_pred(rpta_info_table::in,
+    proc_formal_region_args_table::in,
     proc_pp_actual_region_args_table::in,
     renaming_table::in, renaming_table::in, region_instr_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,
     module_info::in, module_info::out) is det.
 
-region_transform_pred(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+region_transform_pred(RptaInfoTable, FormalRegionArgTable,
         ActualRegionArgTable, ResurRenamingTable, IteRenamingTable,
         RegionInstructionTable, ResurRenamingAnnoTable, IteRenamingAnnoTable,
         PredId, !NameToVarTable, !ModuleInfo) :-
     module_info_pred_info(!.ModuleInfo, PredId, PredInfo),
     ProcIds = pred_info_non_imported_procids(PredInfo),
     list.foldl2(region_transform_proc(RptaInfoTable,
-        ConstantRTable, DeadRTable, BornRTable, ActualRegionArgTable,
+        FormalRegionArgTable, ActualRegionArgTable,
         ResurRenamingTable, IteRenamingTable,
         RegionInstructionTable, ResurRenamingAnnoTable, IteRenamingAnnoTable,
         PredId), ProcIds, !NameToVarTable, !ModuleInfo).
@@ -208,15 +205,14 @@
     % As said above, we will recompute instmap delta, recheck purity for
     % this annotated procedure after all the procedures have been transformed.
     %
-:- 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_actual_region_args_table::in,
+:- pred region_transform_proc(rpta_info_table::in,
+    proc_formal_region_args_table::in, proc_pp_actual_region_args_table::in,
     renaming_table::in, renaming_table::in, region_instr_table::in,
     renaming_annotation_table::in, renaming_annotation_table::in,
     pred_id::in, proc_id::in, name_to_prog_var_table::in,
     name_to_prog_var_table::out, module_info::in, module_info::out) is det.
 
-region_transform_proc(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+region_transform_proc(RptaInfoTable, FormalRegionArgTable,
         ActualRegionArgTable, ResurRenamingTable, IteRenamingTable,
         RegionInstructionTable, ResurRenamingAnnoTable, IteRenamingAnnoTable,
         PredId, ProcId, !NameToVarTable, !ModuleInfo) :-
@@ -229,9 +225,7 @@
     proc_info_get_argmodes(ProcInfo1, ActualArgModes0),
     proc_info_get_goal(ProcInfo1, Goal0),
     map.lookup(RptaInfoTable, PPId, rpta_info(Graph, _)),
-    map.lookup(ConstantRTable, PPId, ConstantR),
-    map.lookup(DeadRTable, PPId, DeadR),
-    map.lookup(BornRTable, PPId, BornR),
+    map.lookup(FormalRegionArgTable, PPId, FormalRegionArgProc),
     map.lookup(ActualRegionArgTable, PPId, ActualRegionArgProc),
     ( map.search(ResurRenamingTable, PPId, ResurRenamingProc0) ->
         ResurRenamingProc = ResurRenamingProc0,
@@ -249,7 +243,7 @@
     ),
     map.lookup(RegionInstructionTable, PPId, RegionInstructionProc),
     NameToVar0 = map.init,
-    annotate_proc(!.ModuleInfo, PredInfo0, Graph, ConstantR, DeadR, BornR,
+    annotate_proc(!.ModuleInfo, PredInfo0, Graph, FormalRegionArgProc,
         ActualRegionArgProc, ResurRenamingProc, IteRenamingProc,
         RegionInstructionProc, ResurRenamingAnnoProc, IteRenamingAnnoProc,
         VarSet0, _, VarTypes0, _, HeadVars0, _, ActualArgModes0, _,
@@ -269,16 +263,15 @@
     %    + new calls to region instructions
     %
 :- pred annotate_proc(module_info::in, pred_info::in, rpt_graph::in,
-    region_set::in, region_set::in, region_set::in,
-    pp_actual_region_args_table::in, renaming_proc::in, renaming_proc::in,
-    region_instr_proc::in, renaming_annotation_proc::in,
+    region_args::in, pp_actual_region_args_table::in, renaming_proc::in,
+    renaming_proc::in, region_instr_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,
     list(mer_mode)::in, list(mer_mode)::out, hlds_goal::in, hlds_goal::out,
     name_to_prog_var::in, name_to_prog_var::out, proc_info::in,
     proc_info::out) is det.
 
-annotate_proc(ModuleInfo, PredInfo, Graph, ConstantR, DeadR, BornR,
+annotate_proc(ModuleInfo, PredInfo, Graph, FormalRegionArgProc,
         ActualRegionArgProc, ResurRenamingProc, IteRenamingProc,
         RegionInstructionProc, ResurRenamingAnnoProc, IteRenamingAnnoProc,
         !VarSet, !VarTypes, !HeadVars, !ActualArgModes, !Goal,
@@ -302,18 +295,17 @@
     % Note that formal region arguments are not subjected to renaming.
     %
     % Along with the extra arguments we also add extra modes for them.
-    set.to_sorted_list(ConstantR, LConstantR),
-    set.to_sorted_list(DeadR, LDeadR),
-    set.to_sorted_list(BornR, LBornR),
-    FormalInputNodes = LConstantR ++ LDeadR,
-    FormalNodes = FormalInputNodes ++ LBornR,
+
+    FormalRegionArgProc = region_args(Constants, Deads, Borns),
+    FormalInputNodes = Constants ++ Deads,
+    FormalNodes = FormalInputNodes ++ Borns,
     list.map_foldl3(node_to_var(Graph), FormalNodes, FormalRegionArgs,
         !NameToVar, !VarSet, !VarTypes),
 
     InMode = in_mode,
     OutMode = out_mode,
     list.duplicate(list.length(FormalInputNodes), InMode, InModes),
-    list.duplicate(list.length(LBornR), OutMode, OutModes),
+    list.duplicate(list.length(Borns), OutMode, OutModes),
 
     % Notice that the output of a function needs to be the last argument.
     PredOrFunc = pred_info_is_pred_or_func(PredInfo),
@@ -438,9 +430,9 @@
     ( map.search(ActualRegionArgProc, ProgPoint, ActualNodes0) ->
         ActualNodes = ActualNodes0
     ;
-        ActualNodes = actual_region_args([], [], [])
+        ActualNodes = region_args([], [], [])
     ),
-    ActualNodes = actual_region_args(Constants, Ins, Outs),
+    ActualNodes = region_args(Constants, Ins, Outs),
     AllNodes = Constants ++ Ins ++ Outs,
     list.map_foldl3(
         node_to_var_with_both_renamings(Graph, ResurRenaming, IteRenaming),
cvs diff: Diffing notes

Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm
--------------------------------------------------------------------------
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