[m-rev.] For review: Fix some bugs related to RBMM

Quan Phan quan.phan at cs.kuleuven.be
Fri Apr 4 03:57:17 AEDT 2008


Hi,

This change is limited in RBMM implementation. Will anyone take a look
at it soon or can I commit first and will address comments, if any,
after that?

Zoltan, this includes the fix for the two bugs you detected and told me
in one of our emails before (tests/hard_coded/{cycles.m and cycles2.m}).

Thanks and regards,
Quan.
-------------- next part --------------
Estimated hours taken: 20
Branch: main

Fix some bugs in the implementation of RBMM.
1) Renaming of region variables:
There are cases where at a program point two resurrection renamings of a region
variable exist, one is to apply to the remove intruction and the other to the
create instruction annotated at that point. Before only one of them was kept,
now we keep both (1.1) and then apply them as said (1.2).

2) Fix some other bugs.
3) Improve namings and comments at various places.

Implement the saving of protected regions at disj frames ONLY for semidet
disjunctions. We need this information so as to be able to commit the regions'
removals when a nonlast disjunct of a semidet disjunction succeeds.

compiler/rbmm.region_resurrection_renaming.m:
	Implement 1.1).

	Use counter module instead of int to implement a counter.
	Fix a logic bug that to find resurrected, live regions before a join
	point, we also need to consider the regions live after the previous
	program point. Before we did not, which is a bug.

compiler/rbmm.region_transformation.m:
	Conform to 1) and implement (1.2).

	Ensure that when adding region paramaters to function call, the
	variant that the function output is at the end is respected. Before it
	is not, which is a bug.

compiler/rbmm.add_rbmm_goal_infos.m:
	To conform with 1).

compiler/rbmm.condition_renaming.m:
	To conform with 1).

	(*) Fix the bug that the reverse condition renaming for an if-then-else
	may be introduced in the condition of another if-then-else in the
	first's then part.

compiler/rbmm.region_instruction.m:
	Ensure that when both a remove and a create instructions are annotated
	to before a program point, the remove one will go first, then the
	create.
 
	Make them conform to the changes for 1).

compiler/rbmm.m:
	To conform with 1) and (*).
-------------- next part --------------
Index: compiler/rbmm.add_rbmm_goal_infos.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.add_rbmm_goal_infos.m,v
retrieving revision 1.3
diff -u -r1.3 rbmm.add_rbmm_goal_infos.m
--- compiler/rbmm.add_rbmm_goal_infos.m	27 Feb 2008 07:23:14 -0000	1.3
+++ compiler/rbmm.add_rbmm_goal_infos.m	3 Apr 2008 15:39:17 -0000
@@ -438,10 +438,10 @@
                 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
+                ( map.search(ResurRenaming, OriginalName, ResurNameList) ->
+                    Name = list.det_last(ResurNameList)
+                ; map.search(IteRenaming, OriginalName, IteNameList) ->
+                    Name = list.det_last(IteNameList)
                 ;
                     Name = OriginalName
                 ),
Index: compiler/rbmm.condition_renaming.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.condition_renaming.m,v
retrieving revision 1.8
diff -u -r1.8 rbmm.condition_renaming.m
--- compiler/rbmm.condition_renaming.m	27 Feb 2008 07:23:14 -0000	1.8
+++ compiler/rbmm.condition_renaming.m	3 Apr 2008 15:39:18 -0000
@@ -109,10 +109,20 @@
     % happens. For each Condition where renaming happens,
     % it finds the first program point in the corresponding Then and
     % introduces the reverse renaming annotation before that ponit.
-    %
+    % Note that that first program point must not be in the condition of
+    % an if-then-else. E.g., 
+    % if % a renaming exists here: R -> R_ite_1 
+    % then
+    %    if % not add reverse renaming annotation at this point.
+    %    then
+    %       % but at here: R := R_ite_1
+    %    else
+    %       $ and at here: R := R_ite_1
+    % else 
+    %    ...
 :- pred collect_ite_annotation(proc_goal_path_regions_table::in,
     execution_path_table::in, rpta_info_table::in, renaming_table::in,
-    renaming_annotation_table::out) is det.
+    renaming_table::out, renaming_annotation_table::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -387,13 +397,14 @@
 
 apply_region_renaming(Graph, Renaming, Node, !Regions) :-
     RegionName = rptg_lookup_region_name(Graph, Node),
-    ( map.search(Renaming, RegionName, RenamedRegionName) ->
+    ( map.search(Renaming, RegionName, RenamedRegionNameList) ->
+        RenamedRegionName = list.det_last(RenamedRegionNameList),
         svset.insert(RenamedRegionName, !Regions)
     ;
         svset.insert(RegionName, !Regions)
     ).
 
-:- pred renaming_annotation_to_regions(region_instruction::in,
+:- pred renaming_annotation_to_regions(region_instr::in,
     set(string)::in, set(string)::out,
     set(string)::in, set(string)::out) is det.
 
@@ -914,9 +925,9 @@
 record_ite_renaming(ProgPoint, HowMany, _Graph, RegName, !IteRenamingProc) :-
     NewName = RegName ++ "_ite_" ++ string.int_to_string(HowMany),
     ( map.search(!.IteRenamingProc, ProgPoint, IteRenaming0) ->
-        svmap.set(RegName, NewName, IteRenaming0, IteRenaming)
+        svmap.set(RegName, [NewName], IteRenaming0, IteRenaming)
     ;
-        svmap.set(RegName, NewName, map.init, IteRenaming)
+        svmap.set(RegName, [NewName], map.init, IteRenaming)
     ),
     svmap.set(ProgPoint, IteRenaming, !IteRenamingProc).
 
@@ -1016,69 +1027,105 @@
 %
 
 collect_ite_annotation(IteRenamedRegionTable, ExecPathTable,
-        RptaInfoTable, IteRenamingTable, IteAnnotationTable) :-
-    map.foldl(
-        collect_ite_annotation_proc(ExecPathTable, RptaInfoTable,
-            IteRenamingTable),
-        IteRenamedRegionTable, map.init, IteAnnotationTable).
+        RptaInfoTable, !IteRenamingTable, IteAnnotationTable) :-
+    map.foldl2(
+        collect_ite_annotation_proc(ExecPathTable, RptaInfoTable),
+        IteRenamedRegionTable, !IteRenamingTable,
+        map.init, IteAnnotationTable).
 
 :- pred collect_ite_annotation_proc(execution_path_table::in,
-    rpta_info_table::in, renaming_table::in, pred_proc_id::in,
-    goal_path_regions_table::in,
+    rpta_info_table::in, pred_proc_id::in,
+    goal_path_regions_table::in, renaming_table::in, renaming_table::out, 
     renaming_annotation_table::in, renaming_annotation_table::out) is det.
 
-collect_ite_annotation_proc(ExecPathTable, RptaInfoTable, IteRenamingTable,
-        PPId, IteRenamedRegionProc, !IteAnnotationTable) :-
+collect_ite_annotation_proc(ExecPathTable, RptaInfoTable, PPId,
+        IteRenamedRegionProc, !IteRenamingTable, !IteAnnotationTable) :-
     map.lookup(ExecPathTable, PPId, ExecPaths),
     map.lookup(RptaInfoTable, PPId, RptaInfo),
-    map.lookup(IteRenamingTable, PPId, IteRenamingProc),
+    map.lookup(!.IteRenamingTable, PPId, IteRenamingProc0),
     RptaInfo = rpta_info(Graph, _),
-    map.foldl(
-        collect_ite_annotation_region_names(ExecPaths, Graph, IteRenamingProc),
-        IteRenamedRegionProc, map.init, IteAnnotationProc),
-    svmap.set(PPId, IteAnnotationProc, !IteAnnotationTable).
+    map.foldl2(
+        collect_ite_annotation_region_names(ExecPaths, Graph),
+        IteRenamedRegionProc, IteRenamingProc0, IteRenamingProc,
+        map.init, IteAnnotationProc),
+    svmap.set(PPId, IteAnnotationProc, !IteAnnotationTable),
+    svmap.set(PPId, IteRenamingProc, !IteRenamingTable).
 
 :- pred collect_ite_annotation_region_names(list(execution_path)::in,
-    rpt_graph::in, renaming_proc::in, goal_path::in, set(string)::in,
+    rpt_graph::in, goal_path::in, set(string)::in,
+    renaming_proc::in, renaming_proc::out, 
     renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
 
-collect_ite_annotation_region_names(ExecPaths, Graph, IteRenamingProc,
-        PathToCond, RenamedRegions, !IteAnnotationProc) :-
+collect_ite_annotation_region_names(ExecPaths, Graph, PathToCond,
+        RenamedRegions, !IteRenamingProc, !IteAnnotationProc) :-
     ( cord.split_last(PathToCond, InitialSteps, LastStep) ->
         expect(unify(LastStep, step_ite_cond), this_file,
             "collect_ite_annotation_region_names: not step_ite_cond"),
         PathToThen = cord.snoc(InitialSteps, step_ite_then),
         get_closest_condition_in_goal_path(PathToCond, _, 0, HowMany),
-        list.foldl(
-            collect_ite_annotation_exec_path(Graph, IteRenamingProc,
-                PathToThen, RenamedRegions, HowMany),
-            ExecPaths, !IteAnnotationProc)
+        list.foldl2(
+            collect_ite_annotation_exec_path(Graph, PathToThen,
+                RenamedRegions, HowMany),
+            ExecPaths, !IteRenamingProc, !IteAnnotationProc)
     ;
         unexpected(this_file,
             "collect_ite_annotation_region_set: empty path to condition.")
     ).
 
-:- pred collect_ite_annotation_exec_path(rpt_graph::in,
-    renaming_proc::in, goal_path::in,
+:- pred collect_ite_annotation_exec_path(rpt_graph::in, goal_path::in,
     set(string)::in, int::in, execution_path::in,
+    renaming_proc::in, renaming_proc::out, 
+    renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
+
+collect_ite_annotation_exec_path(_, _, _, _, [], !IteRenamingProc,
+        !IteAnnotationProc).
+collect_ite_annotation_exec_path(Graph, PathToThen, RenamedRegions,
+        HowMany, [ProgPoint - _ | ProgPoint_Goals],
+        !IteRenamingProc, !IteAnnotationProc) :-
+    % This is the first program point of this execution path.
+    % We never need to introduce reversed renaming at this point.
+    collect_ite_annotation_exec_path_2(Graph, PathToThen, RenamedRegions,
+        HowMany, ProgPoint, ProgPoint_Goals, !IteRenamingProc,
+        !IteAnnotationProc).
+
+    % Process from the 2nd program point onwards.
+:- pred collect_ite_annotation_exec_path_2(rpt_graph::in, goal_path::in,
+    set(string)::in, int::in, program_point::in, execution_path::in,
+    renaming_proc::in, renaming_proc::out, 
     renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
 
-collect_ite_annotation_exec_path(_, _, _, _, _, [], !IteAnnotationProc).
-collect_ite_annotation_exec_path(Graph, IteRenamingProc, PathToThen,
-        RenamedRegions, HowMany,
-        [ProgPoint - _ | ProgPoint_Goals], !IteAnnotationProc) :-
+collect_ite_annotation_exec_path_2(_, _, _, _, _, [], !IteRenamingProc,
+        !IteAnnotationProc).
+collect_ite_annotation_exec_path_2(Graph, PathToThen, RenamedRegions,
+        HowMany, PrevPoint, [ProgPoint - _ | ProgPoint_Goals],
+        !IteRenamingProc, !IteAnnotationProc) :-
     ProgPoint = pp(_, GoalPath),
     PathToThenSteps = cord.list(PathToThen),
     GoalPathSteps = cord.list(GoalPath),
-    ( list.append(_, PathToThenSteps, GoalPathSteps) ->
-        % This is the first goal in the corresponding then branch, we need
-        % to introduce reverse renaming at this point.
-        set.fold(
-            introduce_reverse_renaming(ProgPoint, IteRenamingProc, HowMany),
-            RenamedRegions, !IteAnnotationProc)
+    ( list.append(PathToThenSteps, FromThenSteps, GoalPathSteps) ->
+        ( list.member(step_ite_cond, FromThenSteps) ->
+            % We cannot introduce reverse renaming in the condition of
+            % an if-then-else. So we need to maintain the ite renaming
+            % from the previous point to this point.
+            ( map.search(!.IteRenamingProc, PrevPoint, PrevIteRenaming) ->
+                svmap.set(ProgPoint, PrevIteRenaming, !IteRenamingProc)
+            ;   true
+            ),
+            collect_ite_annotation_exec_path_2(Graph, PathToThen,
+                RenamedRegions, HowMany, ProgPoint, ProgPoint_Goals,
+                !IteRenamingProc, !IteAnnotationProc)
+        ;
+            % This is the first point in the corresponding then branch, which
+            % is not in the condition of another if-then-else, we need
+            % to introduce reverse renaming at this point.
+            set.fold(
+                introduce_reverse_renaming(ProgPoint, !.IteRenamingProc,
+                    HowMany),
+                RenamedRegions, !IteAnnotationProc)
+        )
     ;
-        collect_ite_annotation_exec_path(Graph, IteRenamingProc,
-            PathToThen, RenamedRegions, HowMany, ProgPoint_Goals,
+        collect_ite_annotation_exec_path_2(Graph, PathToThen, RenamedRegions,
+            HowMany, ProgPoint, ProgPoint_Goals, !IteRenamingProc,
             !IteAnnotationProc)
     ).
 
@@ -1096,8 +1143,14 @@
         !IteAnnotationProc) :-
     CurrentName = RegName ++ "_ite_" ++ string.int_to_string(HowMany),
     ( map.search(IteRenamingProc, ProgPoint, Renaming) ->
-        ( map.search(Renaming, RegName, RenameTo) ->
-            make_renaming_instruction(CurrentName, RenameTo, Annotation)
+        ( map.search(Renaming, RegName, RenameToList) ->
+            ( list.length(RenameToList) = 1 ->
+                RenameTo = list.det_last(RenameToList),
+                make_renaming_instruction(CurrentName, RenameTo, Annotation)
+            ;
+                unexpected(this_file,
+                    "introduce_reverse_renaming: more than one renaming exist.")
+            )
         ;
             make_renaming_instruction(CurrentName, RegName, Annotation)
         )
Index: compiler/rbmm.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
retrieving revision 1.7
diff -u -r1.7 rbmm.m
--- compiler/rbmm.m	6 Sep 2007 12:45:24 -0000	1.7
+++ compiler/rbmm.m	3 Apr 2008 15:39:18 -0000
@@ -102,17 +102,19 @@
     collect_region_resurrection_renaming(CreatedBeforeTable, LocalRTable,
         RptaInfoTable, ResurrectionPathTable, ResurrectionRenameTable),
     collect_renaming_and_annotation(ResurrectionRenameTable, JoinPointTable,
-        LRBeforeTable, BornRTable, RptaInfoTable, ResurrectionPathTable,
-        ExecPathTable, ResurRenamingAnnoTable, ResurRenamingTable),
+        LRBeforeTable, LRAfterTable, BornRTable, RptaInfoTable,
+        ResurrectionPathTable, ExecPathTable, ResurRenamingAnnoTable,
+        ResurRenamingTable),
     collect_non_local_and_in_cond_regions(!.ModuleInfo, RptaInfoTable,
         LRBeforeTable, LRAfterTable, ResurRenamingTable,
         ResurRenamingAnnoTable, LocalRegionsTable, InCondRegionsTable),
     collect_ite_renamed_regions(LocalRegionsTable, InCondRegionsTable,
         RenamedRegionsTable),
     collect_ite_renaming(!.ModuleInfo, RptaInfoTable, RenamedRegionsTable,
-        IteRenamingTable),
+        IteRenamingTable0),
     collect_ite_annotation(RenamedRegionsTable, ExecPathTable, 
-        RptaInfoTable, IteRenamingTable, IteRenamingAnnoTable),
+        RptaInfoTable, IteRenamingTable0, IteRenamingTable,
+        IteRenamingAnnoTable),
 
     region_transform(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
         ActualRegionArgumentTable, ResurRenamingTable, IteRenamingTable,
Index: compiler/rbmm.region_instruction.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_instruction.m,v
retrieving revision 1.4
diff -u -r1.4 rbmm.region_instruction.m
--- compiler/rbmm.region_instruction.m	23 Jul 2007 05:06:14 -0000	1.4
+++ compiler/rbmm.region_instruction.m	3 Apr 2008 15:39:18 -0000
@@ -28,25 +28,25 @@
 :- import_module map.
 :- import_module string.
 
-:- type region_instruction_table
-    ==      map(pred_proc_id, region_instruction_proc).
+:- type region_instr_table
+    ==      map(pred_proc_id, region_instr_proc).
 
-:- type region_instruction_proc
-    ==      map(program_point, instructions_before_after).
+:- type region_instr_proc
+    ==      map(program_point, instrs_before_after).
 
     % We introduce region instructions before and after a program point.
-:- type instructions_before_after
-    --->    instructions_before_after(
-                instructions_before    :: list(region_instruction),
+:- type instrs_before_after
+    --->    instrs_before_after(
+                instrs_before    :: list(region_instr),
                                         % Region instructions before a program
                                         % point.
 
-                instructions_after     :: list(region_instruction)
+                instrs_after     :: list(region_instr)
                                         % Region instructions after a program
                                         % point.
             ).
 
-:- type region_instruction
+:- type region_instr
     --->    create_region(
                 % Region name.
                 string
@@ -65,16 +65,16 @@
                 string
             ).
 
-:- type region_instruction_type
-    --->    create_region_instruction
-    ;       remove_region_instruction
-    ;       renaming_region_instruction.
+:- type region_instr_type
+    --->    create_region_instr
+    ;       remove_region_instr
+    ;       renaming_region_instr.
 
 :- pred introduce_region_instructions(module_info::in, rpta_info_table::in,
     execution_path_table::in, proc_pp_region_set_table::in,
     proc_pp_region_set_table::in, proc_pp_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in,
-    proc_region_set_table::in, region_instruction_table::out) is det.
+    proc_region_set_table::in, region_instr_table::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -113,7 +113,7 @@
     proc_pp_region_set_table::in, proc_pp_region_set_table::in,
     proc_pp_region_set_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in, pred_id::in,
-    region_instruction_table::in, region_instruction_table::out) is det.
+    region_instr_table::in, region_instr_table::out) is det.
 
 introduce_region_instructions_pred(ModuleInfo, RptaInfoTable, ExecPathTable,
         LRBeforeTable, LRAfterTable, VoidVarRegionTable, BornRTable,
@@ -130,7 +130,7 @@
     proc_pp_region_set_table::in, proc_pp_region_set_table::in,
     proc_pp_region_set_table::in, proc_region_set_table::in,
     proc_region_set_table::in, proc_region_set_table::in, proc_id::in,
-    region_instruction_table::in, region_instruction_table::out) is det.
+    region_instr_table::in, region_instr_table::out) is det.
 
 introduce_region_instructions_proc(ModuleInfo, PredId, RptaInfoTable,
         ExecPathTable, LRBeforeTable, LRAfterTable, VoidVarRegionTable,
@@ -164,7 +164,7 @@
     pp_region_set_table::in, pp_region_set_table::in,
     pp_region_set_table::in, proc_region_set_table::in,
     proc_region_set_table::in, module_info::in, proc_info::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 introduce_region_instructions_exec_paths([], _, _, _, _, _, _, _, _, _, _, _,
         !RegionInstructionProc).
@@ -184,7 +184,7 @@
     pp_region_set_table::in, pp_region_set_table::in,
     pp_region_set_table::in, proc_region_set_table::in,
     proc_region_set_table::in, module_info::in, proc_info::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 introduce_region_instructions_exec_path([], _, _, _, _, _, _, _, _, _, _, _,
         !RegionInstructionProc).
@@ -207,7 +207,7 @@
     set.intersect(Local_Born_Dead, DeadVoidVarRegions0, DeadVoidVarRegions),
     RptaInfo = rpta_info(CallerGraph, _),
     set.fold(
-        record_instruction_after_prog_point(remove_region_instruction,
+        record_instruction_after_prog_point(remove_region_instr,
             ProgPoint, CallerGraph),
         DeadVoidVarRegions, !RegionInstructionProc),
 
@@ -242,8 +242,9 @@
         set.difference(LRAfter, LRBeforeNext, ToBeRemovedBeforeNext),
         set.intersect(Local_Born_Dead, ToBeRemovedBeforeNext,
             ToBeRemovedBeforeNextAndAllowed),
-        set.fold(record_instruction_before_prog_point(remove_region_instruction,
-            NextProgPoint, CallerGraph), ToBeRemovedBeforeNextAndAllowed,
+        set.fold(record_instruction_before_prog_point(
+                remove_region_instr, NextProgPoint, CallerGraph),
+            ToBeRemovedBeforeNextAndAllowed,
             !RegionInstructionProc),
 
         introduce_region_instructions_exec_path(ProgPoint_Goals, RptaInfo,
@@ -270,7 +271,7 @@
     %
 :- pred transformation_rule_1(hlds_goal_expr::in, program_point::in,
     region_set::in, rpta_info::in, proc_region_set_table::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 transformation_rule_1(Expr, ProgPoint, ToBeCreatedAndAllowed, CallerRptaInfo,
         BornRTable, !RegionInstructionProc) :-
@@ -297,7 +298,7 @@
             % provided that they are in BornR or LocalR, i.e., p is allowed
             % to create them.
             set.fold(
-                record_instruction_before_prog_point(create_region_instruction,
+                record_instruction_before_prog_point(create_region_instr,
                     ProgPoint, CallerGraph),
                 ToBeCreatedAndAllowed, !RegionInstructionProc)
         )
@@ -314,7 +315,7 @@
 
 :- pred process_mapping_rule_1(program_point::in, region_set::in,
     region_set::in, rpt_graph::in, rptg_node::in, rptg_node::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 process_mapping_rule_1(ProgPoint, ToBeCreatedAndAllowed, CalleeBornR,
         CallerGraph, SourceRegion, TargetRegion, !RegionInstructionProc) :-
@@ -322,7 +323,7 @@
         set.contains(ToBeCreatedAndAllowed, TargetRegion),
         not set.contains(CalleeBornR, SourceRegion)
     ->
-        record_instruction_before_prog_point(create_region_instruction,
+        record_instruction_before_prog_point(create_region_instr,
             ProgPoint, CallerGraph, TargetRegion, !RegionInstructionProc)
     ;
         true
@@ -335,7 +336,7 @@
     %
 :- pred transformation_rule_2(hlds_goal_expr::in, program_point::in,
     region_set::in, rpta_info::in, module_info::in, proc_info::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 transformation_rule_2(Expr, ProgPoint, ToBeCreatedAndAllowed, RptaInfo,
         ModuleInfo, ProcInfo, !RegionInstructionProc) :-
@@ -349,9 +350,10 @@
 
         set.intersect(Reach_X, ToBeCreatedAndAllowed,
             ToBeCreatedAllowedAndReached),
-        set.fold(record_instruction_before_prog_point(create_region_instruction,
-            ProgPoint, Graph), ToBeCreatedAllowedAndReached,
-            !RegionInstructionProc)
+        set.fold(
+            record_instruction_before_prog_point(create_region_instr,
+                ProgPoint, Graph),
+            ToBeCreatedAllowedAndReached, !RegionInstructionProc)
     ;
         ( Expr = unify(_, _, _, deconstruct(_, _, _, _, _, _), _)
         ; Expr = unify(_, _, _, assign(_, _), _)
@@ -383,7 +385,7 @@
     %
 :- pred transformation_rule_3(hlds_goal_expr::in, program_point::in,
     region_set::in, rpta_info::in, proc_region_set_table::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 transformation_rule_3(Expr, ProgPoint, ToBeRemovedAndAllowed, CallerRptaInfo,
         DeadRTable, !RegionInstructionProc) :-
@@ -405,7 +407,7 @@
             % become dead provided that p is allowed to remove those
             % regions.
             set.fold(
-                record_instruction_after_prog_point(remove_region_instruction,
+                record_instruction_after_prog_point(remove_region_instr,
                     ProgPoint, CallerGraph),
                 ToBeRemovedAndAllowed, !RegionInstructionProc)
         )
@@ -422,7 +424,7 @@
 
 :- pred process_mapping_rule_3(program_point::in, region_set::in,
     region_set::in, rpt_graph::in, rptg_node::in, rptg_node::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 process_mapping_rule_3(ProgPoint, ToBeRemovedAndAllowed, CalleeDeadR,
         CallerGraph, SourceRegion, TargetRegion, !RegionInstructionProc) :-
@@ -430,7 +432,7 @@
         set.contains(ToBeRemovedAndAllowed, TargetRegion),
         not set.contains(CalleeDeadR, SourceRegion)
     ->
-        record_instruction_after_prog_point(remove_region_instruction,
+        record_instruction_after_prog_point(remove_region_instr,
             ProgPoint, CallerGraph, TargetRegion, !RegionInstructionProc)
     ;
         true
@@ -442,8 +444,8 @@
     % procedure is allowed to remove it.
     %
 :- pred transformation_rule_4(hlds_goal_expr::in, program_point::in,
-    region_set::in, rpta_info::in, region_instruction_proc::in,
-    region_instruction_proc::out) is det.
+    region_set::in, rpta_info::in, region_instr_proc::in,
+    region_instr_proc::out) is det.
 
 transformation_rule_4(Expr, ProgPoint, ToBeRemovedAndAllowed, RptaInfo,
         !RegionInstructionProc) :-
@@ -451,8 +453,10 @@
         Expr = unify(_, _, _, _, _)
     ->
         RptaInfo = rpta_info(Graph, _),
-        set.fold(record_instruction_after_prog_point(remove_region_instruction,
-            ProgPoint, Graph), ToBeRemovedAndAllowed, !RegionInstructionProc)
+        set.fold(
+            record_instruction_after_prog_point(remove_region_instr,
+                ProgPoint, Graph),
+            ToBeRemovedAndAllowed, !RegionInstructionProc)
     ;
         ( Expr = plain_call(_, _, _, _, _, _)
         ; Expr = conj(_, [])
@@ -469,20 +473,20 @@
     % We will record the annotations after the program point.
     %
 :- pred transformation_rule_4_2(program_point::in, region_set::in,
-    rpta_info::in, region_instruction_proc::in, region_instruction_proc::out)
+    rpta_info::in, region_instr_proc::in, region_instr_proc::out)
     is det.
 
 transformation_rule_4_2(ProgPoint, ToBeRemovedAndAllowed, RptaInfo,
         !RegionInstructionProc) :-
     RptaInfo = rpta_info(Graph, _),
     set.fold(
-        record_instruction_after_prog_point(remove_region_instruction,
+        record_instruction_after_prog_point(remove_region_instr,
             ProgPoint, Graph),
         ToBeRemovedAndAllowed, !RegionInstructionProc).
 
-:- pred record_instruction_after_prog_point(region_instruction_type::in,
+:- pred record_instruction_after_prog_point(region_instr_type::in,
     program_point::in, rpt_graph::in, rptg_node::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
 record_instruction_after_prog_point(RegionInstType, ProgPoint, Graph, Region,
         !RegionInstructionProc) :-
@@ -492,63 +496,74 @@
     % Attach the instruction to after the program point.
     (
         map.search(!.RegionInstructionProc, ProgPoint,
-            instructions_before_after(InstsBefore, InstsAfter))
+            instrs_before_after(InstsBefore, InstsAfter))
     ->
         ( list.member(RegionInstruction, InstsAfter) ->
             true
         ;
             svmap.set(ProgPoint,
-                instructions_before_after(InstsBefore,
+                instrs_before_after(InstsBefore,
                     [RegionInstruction | InstsAfter]),
                 !RegionInstructionProc)
         )
     ;
         svmap.set(ProgPoint,
-            instructions_before_after([], [RegionInstruction]),
+            instrs_before_after([], [RegionInstruction]),
             !RegionInstructionProc)
     ).
 
-:- pred record_instruction_before_prog_point(region_instruction_type::in,
+    % When adding region annotations to before a program point, we maintain
+    % that remove instructions are added to top, create instructions are
+    % appended at the end.
+    %
+:- pred record_instruction_before_prog_point(region_instr_type::in,
     program_point::in, rpt_graph::in, rptg_node::in,
-    region_instruction_proc::in, region_instruction_proc::out) is det.
+    region_instr_proc::in, region_instr_proc::out) is det.
 
-record_instruction_before_prog_point(RegionInstType, ProgPoint, Graph, Region,
+record_instruction_before_prog_point(RegionInstrType, ProgPoint, Graph, Region,
         !RegionInstructionProc) :-
     RegionName = rptg_lookup_region_name(Graph, Region),
-    make_create_or_remove_instruction(RegionInstType, RegionName,
+    make_create_or_remove_instruction(RegionInstrType, RegionName,
         RegionInstruction),
     % Attach the instruction to before the program point.
     (
         map.search(!.RegionInstructionProc, ProgPoint,
-            instructions_before_after(InstsBefore, InstsAfter))
+            instrs_before_after(InstrsBefore, InstrsAfter))
     ->
-        ( list.member(RegionInstruction, InstsBefore) ->
+        ( list.member(RegionInstruction, InstrsBefore) ->
             true
         ;
+            % It is only safe to add create intructions after remove
+            % instructions before a program point because we allow
+            % remove(R1), create(R1), p(..., R1, ...).
+            ( RegionInstrType = create_region_instr ->
+                NewInstrsBefore = InstrsBefore ++ [RegionInstruction]
+            ;
+                NewInstrsBefore = [RegionInstruction | InstrsBefore]
+            ),
             svmap.set(ProgPoint,
-                instructions_before_after([RegionInstruction | InstsBefore],
-                    InstsAfter),
+                instrs_before_after(NewInstrsBefore, InstrsAfter),
                 !RegionInstructionProc)
         )
     ;
         svmap.set(ProgPoint,
-            instructions_before_after([RegionInstruction], []),
+            instrs_before_after([RegionInstruction], []),
             !RegionInstructionProc)
     ).
 
-:- pred make_create_or_remove_instruction(region_instruction_type::in,
-    string::in, region_instruction::out) is det.
+:- pred make_create_or_remove_instruction(region_instr_type::in,
+    string::in, region_instr::out) is det.
 
-make_create_or_remove_instruction(RegionInstType, RegionName,
+make_create_or_remove_instruction(RegionInstrType, RegionName,
         RegionInstruction) :-
     (
-        RegionInstType = create_region_instruction,
+        RegionInstrType = create_region_instr,
         RegionInstruction = create_region(RegionName)
     ;
-        RegionInstType = remove_region_instruction,
+        RegionInstrType = remove_region_instr,
         RegionInstruction = remove_region(RegionName)
     ;
-        RegionInstType = renaming_region_instruction,
+        RegionInstrType = renaming_region_instr,
         unexpected(this_file, "make_create_or_remove_instruction: "
             ++ "unexpected region instruction type")
     ).
Index: compiler/rbmm.region_resurrection_renaming.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_resurrection_renaming.m,v
retrieving revision 1.5
diff -u -r1.5 rbmm.region_resurrection_renaming.m
--- compiler/rbmm.region_resurrection_renaming.m	23 Jul 2007 05:06:15 -0000	1.5
+++ compiler/rbmm.region_resurrection_renaming.m	3 Apr 2008 15:39:18 -0000
@@ -31,6 +31,7 @@
 
 :- import_module list.
 :- import_module map.
+:- import_module multi_map.
 :- import_module string.
 
 %-----------------------------------------------------------------------------%
@@ -41,13 +42,21 @@
 :- type renaming_proc ==
     map(program_point, renaming).
 
-:- type renaming == map(string, string).
+    % Most of the time, at a program point there is only one renaming for a
+    % region variable. But at some resurrection points, two renamings exists
+    % for the resurrecting region. This should happen only in the following
+    % case:
+    %       remove(R), % R -> R_Resur_1
+    %       create(R), % R -> R_Resur_2 
+    %   (i) goal    
+    % That's why multi_map is used.
+:- type renaming == multi_map(string, string).
 
 :- type renaming_annotation_table ==
     map(pred_proc_id, renaming_annotation_proc).
 
 :- type renaming_annotation_proc ==
-    map(program_point, list(region_instruction)).
+    map(program_point, list(region_instr)).
 
 :- type proc_resurrection_path_table ==
     map(pred_proc_id, exec_path_region_set_table).
@@ -73,21 +82,13 @@
     proc_region_set_table::in, proc_region_set_table::in,
     proc_pp_region_set_table::out, proc_resurrection_path_table::out) is det.
 
-    % This predicate only traverses procedures with the execution paths
-    % containing resurrection and computes *renaming* at the points
-    % where a resurrected region becomes live.
-    % The result here will also only contain procedures in which resurrection
-    % happens and for each procedure only execution paths in which
-    % resurrection happens.
-    %
-:- pred collect_region_resurrection_renaming(proc_pp_region_set_table::in,
-    proc_region_set_table::in, rpta_info_table::in,
-    proc_resurrection_path_table::in,
-    renaming_table::out) is det.
-
     % Collect join points in procedures.
-    % We need to find the join points in a procedure because we need to use
-    % a specific region name for each renaming at a join point.
+    % The purpose of finding join points in a procedure is because if a region
+    % is given different names in different execution paths leading to a join
+    % point, we need to unify those names at the join point.
+    % For this purpose, we will only collect join points in execution paths
+    % in which resurrection happens (i.e., the output table of by the above
+    % pass).
     %
     % A program point is a join point if it is in at least two execution
     % paths and its previous points in some two execution paths are different.
@@ -95,16 +96,36 @@
 :- pred collect_join_points(proc_resurrection_path_table::in,
     execution_path_table::in, join_point_region_name_table::out) is det.
 
-    % XXX Need to collect the execution paths in which a resurrection of a
-    % region does not happen but they contain a join point, where the
-    % region is renamed.
-    % At the creation point of the region in such an execution path, we also
-    % need to rename the region.
+    % This predicate find the execution paths in which we need to introduce
+    % resurrection renaming. These paths include
+    % 1) those in which resurrection happens (computed by
+    % compute_resurrection_paths),
+    % 2) and those in which resurrection does not happens but contain the join
+    % points that belong to those in 1). These can be seen as they share a
+    % program point with those in 1). We need to care about those paths
+    % because in such an execution path, we also need to rename a resurrected
+    % region (in the paths in 1)) so that at the join point it can be renamed
+    % again to the unified one. If we keep the original name we will have
+    % problem if the region is an output and therefore a renaming to the
+    % original name will be introduced after the last program point.
     %
 :- pred collect_paths_containing_join_points(execution_path_table::in,
     join_point_region_name_table::in, proc_resurrection_path_table::in,
     proc_resurrection_path_table::out) is det.
 
+    % This predicate only traverses the execution paths in which resurrection
+    % renaming is needed, i.e., those in the output table of the previous
+    % pass. It computes *renaming* at the points where a resurrected region
+    % becomes live.
+    % The result here will also only contain procedures in which resurrection
+    % happens and for each procedure only execution paths in which
+    % resurrection happens.
+    %
+:- pred collect_region_resurrection_renaming(proc_pp_region_set_table::in,
+    proc_region_set_table::in, rpta_info_table::in,
+    proc_resurrection_path_table::in,
+    renaming_table::out) is det.
+
     % This predicate collects *renaming* along the execution paths in
     % procedures where region resurrection happens. It also computes
     % the reversed renaming *annotations* to ensure the integrity use of
@@ -112,19 +133,20 @@
     %
 :- pred collect_renaming_and_annotation(renaming_table::in,
     join_point_region_name_table::in, proc_pp_region_set_table::in,
-    proc_region_set_table::in, rpta_info_table::in,
-    proc_resurrection_path_table::in, execution_path_table::in,
-    renaming_annotation_table::out, renaming_table::out) is det.
+    proc_pp_region_set_table::in, proc_region_set_table::in,
+    rpta_info_table::in, proc_resurrection_path_table::in,
+    execution_path_table::in, renaming_annotation_table::out,
+    renaming_table::out) is det.
 
     % Record the annotation for a procedure.
     %
-:- pred record_annotation(program_point::in, region_instruction::in,
+:- pred record_annotation(program_point::in, region_instr::in,
     renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
 
     % Make a region renaming instruction.
     %
 :- pred make_renaming_instruction(string::in, string::in,
-    region_instruction::out) is det.
+    region_instr::out) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -184,8 +206,8 @@
         LRAfterProc, set.union(BornRProc, LocalRProc)), ExecPaths,
         map.init, CreatedBeforeProc, map.init, PathContainsResurrectionProc),
     svmap.set(PPId, CreatedBeforeProc, !CreatedBeforeTable),
-    % We only want to include procedures in which resurrection happens
-    % in this map.
+    % We only want to include procedures in which resurrection happens in this
+    % map.
     ( map.count(PathContainsResurrectionProc) = 0 ->
         true
     ;
@@ -204,8 +226,7 @@
         LRAfterProc, Born_Local), ExecPath,
         set.init, _, !CreatedBeforeProc,
         set.init, ResurrectedRegionsInExecPath),
-    % We want to record only execution paths in which resurrections
-    % happen.
+    % We want to record only execution paths in which resurrections happen.
     ( set.empty(ResurrectedRegionsInExecPath) ->
         true
     ;
@@ -231,8 +252,8 @@
         CreatedBeforeProgPoint),
     svmap.set(ProgPoint, CreatedBeforeProgPoint, !CreatedBeforeProc),
 
-    % Resurrected regions become live at more than one program point
-    % in an execution path.
+    % Resurrected regions become live at more than one program point in an
+    % execution path.
     set.intersect(!.Candidates, CreatedBeforeProgPoint, ResurrectedRegions),
     set.union(ResurrectedRegions, !ResurrectedRegionsInExecPath),
 
@@ -269,31 +290,43 @@
             assoc_list.keys(ExecPath, P),
             Ps = [P | Ps0]),
         ExecPaths, [], Paths),
-    list.foldl3(collect_join_points_path(Paths), Paths,
+    list.foldl4(collect_join_points_path(Paths), Paths, map.init, _,
         counter.init(0), _, set.init, _JoinPoints, map.init, JoinPointProc),
     svmap.set(PPId, JoinPointProc, !JoinPointTable).
 
 :- pred collect_join_points_path(list(list(program_point))::in,
-    list(program_point)::in, counter::in, counter::out,
+    list(program_point)::in, 
+    map(program_point, string)::in, map(program_point, string)::out,
+    counter::in, counter::out,
     set(program_point)::in, set(program_point)::out,
     map(program_point, string)::in, map(program_point, string)::out) is det.
 
-collect_join_points_path(Paths, Path, !Counter, !JoinPoints,
+collect_join_points_path(Paths, Path, !JP2Name, !Counter, !JoinPoints,
         !JoinPointProc) :-
     list.delete_all(Paths, Path, TheOtherPaths),
     % We ignore the first program point in each path because
     % it cannot be a join point.
     ( Path = [PrevPoint, ProgPoint | ProgPoints] ->
-        ( is_join_point(ProgPoint, PrevPoint, TheOtherPaths) ->
-            counter.allocate(N, !Counter),
-            svmap.set(ProgPoint, "_jp_" ++ string.int_to_string(N),
-                !JoinPointProc),
-            svset.insert(ProgPoint, !JoinPoints)
-        ;
+        ( set.member(ProgPoint, !.JoinPoints) ->
             true
+        ;
+            ( is_join_point(ProgPoint, PrevPoint, TheOtherPaths) ->
+                % Try to lookup the postfix at this jp.
+                ( map.search(!.JP2Name, PrevPoint, JPName0) ->
+                    JPName = JPName0
+                ;
+                    counter.allocate(N, !Counter),
+                    JPName = "_jp_" ++ string.int_to_string(N),
+                    svmap.set(PrevPoint, JPName, !JP2Name)
+                ),
+                svmap.set(ProgPoint, JPName, !JoinPointProc),
+                svset.insert(ProgPoint, !JoinPoints)
+            ;
+                true
+            )
         ),
         collect_join_points_path(Paths, [ProgPoint | ProgPoints],
-            !Counter, !JoinPoints, !JoinPointProc)
+            !JP2Name, !Counter, !JoinPoints, !JoinPointProc)
     ;
         true
     ).
@@ -426,11 +459,11 @@
     list.foldl2(
         collect_region_resurrection_renaming_prog_point(Graph,
             CreatedBeforeProc, ResurrectedRegions),
-        ExecPath, 1, _, !ResurrectionRenameProc).
+        ExecPath, counter.init(0), _, !ResurrectionRenameProc).
 
 :- pred collect_region_resurrection_renaming_prog_point(rpt_graph::in,
     pp_region_set_table::in, region_set::in,
-    pair(program_point, hlds_goal)::in, int::in, int::out,
+    pair(program_point, hlds_goal)::in, counter::in, counter::out,
     renaming_proc::in, renaming_proc::out) is det.
 
 collect_region_resurrection_renaming_prog_point(Graph, CreatedBeforeProc,
@@ -443,11 +476,11 @@
     ( set.empty(ToBeRenamedRegions) ->
         true
     ;
+        counter.allocate(N, !RenamingCounter),
         set.fold(
-            record_renaming_prog_point(Graph, ProgPoint, !.RenamingCounter),
+            record_renaming_prog_point(Graph, ProgPoint, N),
             ToBeRenamedRegions, !ResurrectionRenameProc)
-    ),
-    !:RenamingCounter = !.RenamingCounter + 1.
+    ).
 
 :- pred record_renaming_prog_point(rpt_graph::in, program_point::in, int::in,
     rptg_node::in, renaming_proc::in, renaming_proc::out) is det.
@@ -459,9 +492,9 @@
         ++ string.int_to_string(RenamingCounter),
 
     ( map.search(!.ResurrectionRenameProc, ProgPoint, RenamingProgPoint0) ->
-        svmap.set(RegionName, Renamed, RenamingProgPoint0, RenamingProgPoint)
+        svmap.set(RegionName, [Renamed], RenamingProgPoint0, RenamingProgPoint)
     ;
-        svmap.det_insert(RegionName, Renamed, map.init, RenamingProgPoint)
+        svmap.det_insert(RegionName, [Renamed], map.init, RenamingProgPoint)
     ),
     svmap.set(ProgPoint, RenamingProgPoint, !ResurrectionRenameProc).
 
@@ -479,26 +512,29 @@
 % variable.
 
 collect_renaming_and_annotation(ResurrectionRenameTable, JoinPointTable,
-        LRBeforeTable, BornRTable, RptaInfoTable, ResurrectionPathTable,
-        ExecPathTable, AnnotationTable, RenamingTable) :-
+        LRBeforeTable, LRAfterTable, BornRTable, RptaInfoTable,
+        ResurrectionPathTable, ExecPathTable,
+        AnnotationTable, RenamingTable) :-
     map.foldl2(collect_renaming_and_annotation_proc(ExecPathTable,
-        JoinPointTable, LRBeforeTable, BornRTable, RptaInfoTable,
+        JoinPointTable, LRBeforeTable, LRAfterTable, BornRTable, RptaInfoTable,
         ResurrectionPathTable), ResurrectionRenameTable,
         map.init, AnnotationTable, map.init, RenamingTable).
 
 :- pred collect_renaming_and_annotation_proc(execution_path_table::in,
     join_point_region_name_table::in, proc_pp_region_set_table::in,
-    proc_region_set_table::in, rpta_info_table::in,
-    proc_resurrection_path_table::in, pred_proc_id::in,
+    proc_pp_region_set_table::in, proc_region_set_table::in,
+    rpta_info_table::in, proc_resurrection_path_table::in, pred_proc_id::in,
     renaming_proc::in,
     renaming_annotation_table::in, renaming_annotation_table::out,
     renaming_table::in, renaming_table::out) is det.
 
 collect_renaming_and_annotation_proc(ExecPathTable, JoinPointTable,
-        LRBeforeTable, BornRTable, RptaInfoTable, ResurrectionPathTable,
-        PPId, ResurrectionRenameProc, !AnnotationTable, !RenamingTable) :-
+        LRBeforeTable, LRAfterTable, BornRTable, RptaInfoTable,
+        ResurrectionPathTable, PPId, ResurrectionRenameProc,
+        !AnnotationTable, !RenamingTable) :-
     map.lookup(JoinPointTable, PPId, JoinPointProc),
     map.lookup(LRBeforeTable, PPId, LRBeforeProc),
+    map.lookup(LRAfterTable, PPId, LRAfterProc),
     map.lookup(BornRTable, PPId, BornR),
     map.lookup(RptaInfoTable, PPId, RptaInfo),
     RptaInfo = rpta_info(Graph, _),
@@ -514,8 +550,8 @@
         ResurrectedRegionsInPaths, set.init, ResurrectedRegionsProc),
     map.lookup(ExecPathTable, PPId, ExecPaths),
     list.foldl2(collect_renaming_and_annotation_exec_path(
-        ResurrectionRenameProc, JoinPointProc, LRBeforeProc, BornR,
-        Graph, ResurrectedRegionsProc), ExecPaths,
+        ResurrectionRenameProc, JoinPointProc, LRBeforeProc, LRAfterProc,
+        BornR, Graph, ResurrectedRegionsProc), ExecPaths,
         map.init, AnnotationProc, map.init, RenamingProc),
     svmap.set(PPId, AnnotationProc, !AnnotationTable),
     svmap.set(PPId, RenamingProc, !RenamingTable).
@@ -529,11 +565,12 @@
     %
 :- pred collect_renaming_and_annotation_exec_path(renaming_proc::in,
     map(program_point, string)::in, pp_region_set_table::in,
-    region_set::in, rpt_graph::in, region_set::in, execution_path::in,
+    pp_region_set_table::in, region_set::in, rpt_graph::in, region_set::in,
+    execution_path::in,
     renaming_annotation_proc::in, renaming_annotation_proc::out,
     renaming_proc::in, renaming_proc::out) is det.
 
-collect_renaming_and_annotation_exec_path(_, _, _, _, _, _, [],
+collect_renaming_and_annotation_exec_path(_, _, _, _, _, _, _, [],
         !AnnotationProc, !RenamingProc) :-
     unexpected(this_file, "collect_renaming_and_annotation_exec_path: "
         ++ "empty execution path encountered").
@@ -543,19 +580,22 @@
     % when it is a resurrection point.
     %
 collect_renaming_and_annotation_exec_path(ResurrectionRenameProc,
-        JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
-        [ProgPoint - _ | ProgPoint_Goals], !AnnotationProc, !RenamingProc) :-
+        JoinPointProc, LRBeforeProc, LRAfterProc, BornR, Graph,
+        ResurrectedRegions, [ProgPoint - _ | ProgPoint_Goals],
+        !AnnotationProc, !RenamingProc) :-
     ( map.search(ResurrectionRenameProc, ProgPoint, ResurRename) ->
         svmap.set(ProgPoint, ResurRename, !RenamingProc)
     ;
         svmap.set(ProgPoint, map.init, !RenamingProc)
     ),
     collect_renaming_and_annotation_exec_path_2(ResurrectionRenameProc,
-        JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
-        ProgPoint, ProgPoint_Goals, !AnnotationProc, !RenamingProc).
+        JoinPointProc, LRBeforeProc, LRAfterProc, BornR, Graph,
+        ResurrectedRegions, ProgPoint, ProgPoint_Goals, !AnnotationProc,
+        !RenamingProc).
 
 :- pred collect_renaming_and_annotation_exec_path_2(renaming_proc::in,
     map(program_point, string)::in, pp_region_set_table::in,
+    pp_region_set_table::in,
     region_set::in, rpt_graph::in, region_set::in, program_point::in,
     execution_path::in,
     renaming_annotation_proc::in, renaming_annotation_proc::out,
@@ -564,7 +604,7 @@
     % This means the first program point is also the last.
     % We do not need to do anything more.
     %
-collect_renaming_and_annotation_exec_path_2(_, _, _, _, _, _, _, [],
+collect_renaming_and_annotation_exec_path_2(_, _, _, _, _, _, _, _, [],
         !AnnotationProc, !RenamingProc).
 
     % This is a program point which is not the first.
@@ -587,16 +627,16 @@
     % parameters which resurrect.
     %
 collect_renaming_and_annotation_exec_path_2(ResurrectionRenameProc,
-        JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
-        PrevProgPoint, [ProgPoint - _ | ProgPoint_Goals],
+        JoinPointProc, LRBeforeProc, LRAfterProc, BornR, Graph,
+        ResurrectedRegions, PrevProgPoint, [ProgPoint - _ | ProgPoint_Goals],
         !AnnotationProc, !RenamingProc) :-
     map.lookup(!.RenamingProc, PrevProgPoint, PrevRenaming),
     ( map.search(ResurrectionRenameProc, ProgPoint, ResurRenaming) ->
         % This is a resurrection point of some region(s). We need to merge
         % the existing renaming at the previous point with the resurrection
-        % renaming here. When two renamings have the same key, i.e., the region
-        % resurrects, the resurrection renaming takes priority.
-        map.overlay(PrevRenaming, ResurRenaming, Renaming0),
+        % renaming here. When two renamings have the same key, i.e.,
+        % the related region resurrects, we will keep both renamings.
+        multi_map.merge(PrevRenaming, ResurRenaming, Renaming0),
         svmap.set(ProgPoint, Renaming0, !RenamingProc)
     ;
         % This is not a resurrection point (of any regions).
@@ -607,10 +647,14 @@
         % This is a join point.
         % Add annotations to the previous point.
         map.lookup(LRBeforeProc, ProgPoint, LRBeforeProgPoint),
-        set.intersect(ResurrectedRegions, LRBeforeProgPoint,
+        map.lookup(LRAfterProc, PrevProgPoint, LRAfterPrevProgPoint),
+        % Not yet dead in the sense that the region is still needed to be 
+        % removed.
+        set.union(LRBeforeProgPoint, LRAfterPrevProgPoint, NotYetDeadRegions),
+        set.intersect(ResurrectedRegions, NotYetDeadRegions,
             ResurrectedAndLiveRegions),
         set.fold2(
-            add_annotation_and_renaming(PrevProgPoint, Graph,
+            add_annotation_and_renaming_at_join_point(PrevProgPoint, Graph,
                 JoinPointName, PrevRenaming),
             ResurrectedAndLiveRegions, !AnnotationProc, map.init, Renaming),
         % We will just overwrite any existing renaming information
@@ -625,30 +669,32 @@
         % Add reversed renaming for regions in bornR.
         set.intersect(ResurrectedRegions, BornR, ResurrectedAndBornRegions),
         map.lookup(!.RenamingProc, ProgPoint, LastRenaming),
-        set.fold(add_annotation(ProgPoint, Graph, LastRenaming),
+        set.fold(add_annotation_at_last_prog_point(ProgPoint, Graph,
+                    LastRenaming),
             ResurrectedAndBornRegions, !AnnotationProc)
     ;
         ProgPoint_Goals = [_ | _],
         collect_renaming_and_annotation_exec_path_2(ResurrectionRenameProc,
-            JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
-            ProgPoint, ProgPoint_Goals, !AnnotationProc, !RenamingProc)
+            JoinPointProc, LRBeforeProc, LRAfterProc, BornR, Graph,
+            ResurrectedRegions, ProgPoint, ProgPoint_Goals, !AnnotationProc,
+            !RenamingProc)
     ).
 
     % This predicate adds renaming annotation after the previous program
     % point and records renaming from existing region name.
     %
-:- pred add_annotation_and_renaming(program_point::in,
+:- pred add_annotation_and_renaming_at_join_point(program_point::in,
     rpt_graph::in, string::in, renaming::in, rptg_node::in,
     renaming_annotation_proc::in, renaming_annotation_proc::out,
     renaming::in, renaming::out) is det.
 
-add_annotation_and_renaming(PrevProgPoint, Graph, JoinPointName,
+add_annotation_and_renaming_at_join_point(PrevProgPoint, Graph, JoinPointName,
         PrevRenaming, Region, !AnnotationProc, !Renaming) :-
     RegionName = rptg_lookup_region_name(Graph, Region),
     NewName = RegionName ++ JoinPointName,
 
-    % Add renaming.
-    svmap.det_insert(RegionName, NewName, !Renaming),
+    % Record renaming at the join point if it doesn't exist yet.
+    svmap.det_insert(RegionName, [NewName], !Renaming),
 
     % Add annotation to (after) the previous program point.
     % XXX Annotations are only added for resurrected regions that have been
@@ -657,7 +703,8 @@
     % It seems that we have to add annotations (reverse renaming) for ones that
     % have not been renamed as implemented below too. The only difference is
     % that the reverse renaming is between the new name and the original name.
-    ( map.search(PrevRenaming, RegionName, CurrentName) ->
+    ( map.search(PrevRenaming, RegionName, RenamedNames) ->
+        list.det_last(RenamedNames, CurrentName),
         make_renaming_instruction(CurrentName, NewName, Annotation),
         record_annotation(PrevProgPoint, Annotation, !AnnotationProc)
     ;
@@ -665,17 +712,19 @@
         record_annotation(PrevProgPoint, Annotation, !AnnotationProc)
     ).
 
-:- pred add_annotation(program_point::in, rpt_graph::in, renaming::in,
-    rptg_node::in, renaming_annotation_proc::in,
+:- pred add_annotation_at_last_prog_point(program_point::in, rpt_graph::in,
+    renaming::in, rptg_node::in, renaming_annotation_proc::in,
     renaming_annotation_proc::out) is det.
 
-add_annotation(ProgPoint, Graph, Renaming, Region, !AnnotationProc) :-
+add_annotation_at_last_prog_point(ProgPoint, Graph, Renaming, Region,
+        !AnnotationProc) :-
     RegionName = rptg_lookup_region_name(Graph, Region),
 
     % Add annotation to (after) the program point.
     % Annotations are only added for resurrected regions that have been
     % renamed in this execution path.
-    ( map.search(Renaming, RegionName, CurrentName) ->
+    ( map.search(Renaming, RegionName, CurrentNameList) ->
+        CurrentName = list.det_last(CurrentNameList),
         make_renaming_instruction(CurrentName, RegionName, Annotation),
         record_annotation(ProgPoint, Annotation, !AnnotationProc)
     ;
Index: compiler/rbmm.region_transformation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_transformation.m,v
retrieving revision 1.6
diff -u -r1.6 rbmm.region_transformation.m
--- compiler/rbmm.region_transformation.m	27 Feb 2008 07:23:14 -0000	1.6
+++ compiler/rbmm.region_transformation.m	3 Apr 2008 15:39:19 -0000
@@ -60,7 +60,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_actual_region_args_table::in,
-    renaming_table::in, renaming_table::in, region_instruction_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,
     module_info::in, module_info::out) is det.
@@ -175,7 +175,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_actual_region_args_table::in,
-    renaming_table::in, renaming_table::in, region_instruction_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.
@@ -209,7 +209,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_actual_region_args_table::in,
-    renaming_table::in, renaming_table::in, region_instruction_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.
@@ -269,7 +269,7 @@
 :- 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_instruction_proc::in, renaming_annotation_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,
@@ -349,7 +349,7 @@
     %
 :- pred region_transform_goal(module_info::in, rpt_graph::in,
     renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
-    region_instruction_proc::in, renaming_annotation_proc::in,
+    region_instr_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,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
@@ -380,10 +380,10 @@
         % Region instructions before and after this program point.
         (
             map.search(RegionInstructionProc, ProgPoint,
-                instructions_before_after(Before, After))
+                instrs_before_after(Before, After))
         ->
             % Region instructions before this program point.
-            list.foldl4(region_instruction_to_conj(ModuleInfo, Context,
+            list.foldl4(region_instruction_to_conj_before(ModuleInfo, Context,
                 ResurRenaming, IteRenaming), Before, !NameToVar,
                 !VarSet, !VarTypes, IteRenamingAssignments, Conjs1),
 
@@ -426,7 +426,7 @@
 
     % Annotate procedure calls with actual region arguments.
     %
-region_transform_goal_expr(_, Graph, ResurRenaming, IteRenaming,
+region_transform_goal_expr(ModuleInfo, Graph, ResurRenaming, IteRenaming,
         ActualRegionArgProc, ProgPoint, !GoalExpr, !GoalInfo,
         !NameToVar, !VarSet, !VarTypes) :-
     !.GoalExpr = plain_call(CalleePredId, CalleeProcId, Args0, Builtin,
@@ -443,7 +443,18 @@
     list.map_foldl3(
         node_to_var_with_both_renamings(Graph, ResurRenaming, IteRenaming),
         AllNodes, ActualRegionArgs, !NameToVar, !VarSet, !VarTypes),
-    Args = Args0 ++ ActualRegionArgs,
+    module_info_pred_info(ModuleInfo, CalleePredId, CalleePredInfo),
+    CalleePredOrFunc = pred_info_is_pred_or_func(CalleePredInfo),
+    (
+        CalleePredOrFunc = pf_predicate,
+        Args = Args0 ++ ActualRegionArgs
+    ;
+        CalleePredOrFunc = pf_function,
+        % The output of function is always at the last.
+        list.split_last_det(Args0, BeforeLast, Last),
+        Args = BeforeLast ++ ActualRegionArgs ++ [Last]
+    ),
+
     !:GoalExpr = plain_call(CalleePredId, CalleeProcId, Args, Builtin,
         Context, Name).
 
@@ -492,7 +503,7 @@
     % 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_actual_region_args_table::in,
-    region_instruction_proc::in, renaming_annotation_proc::in,
+    region_instr_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,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
@@ -623,7 +634,7 @@
     %
 :- pred region_transform_case(module_info::in, rpt_graph::in,
     renaming_proc::in, renaming_proc::in, pp_actual_region_args_table::in,
-    region_instruction_proc::in, renaming_annotation_proc::in,
+    region_instr_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,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
@@ -656,12 +667,12 @@
         % Region instructions before and after this program point.
         (
             map.search(RegionInstructionProc, ProgPoint,
-                instructions_before_after(Before, After))
+                instrs_before_after(Before, After))
         ->
             % Region instructions before this program point.
             list.foldl4(
-                region_instruction_to_conj(ModuleInfo, Context, ResurRenaming,
-                    IteRenaming),
+                region_instruction_to_conj_before(ModuleInfo, Context,
+                    ResurRenaming, IteRenaming),
                 Before, !NameToVar, !VarSet, !VarTypes,
                 IteRenamingAssignments, Conjs1),
 
@@ -674,8 +685,7 @@
             Conjs2 = IteRenamingAssignments
         ),
 
-        % Assignment unifications due to region resurrection
-        % renaming.
+        % Assignment unifications due to region resurrection renaming.
         assignments_from_resur_renaming_anno(ResurRenamingAnnoProc, ProgPoint,
             IteRenaming, !NameToVar, !VarSet, !VarTypes, Conjs2, Conjs),
 
@@ -784,7 +794,8 @@
     % Resurrection renaming will be applied first. If a renaming exists
     % for the name (i.e., the name will be changed to another name) then
     % ite renaming need not to be applied because actually it is not
-    % applicable anymore.
+    % applicable anymore. If more than one renaming exist, then we use
+    % the last one.
     %
 :- pred region_name_to_var_with_both_renamings(string::in, renaming::in,
     renaming::in, prog_var::out, name_to_prog_var::in, name_to_prog_var::out,
@@ -792,10 +803,30 @@
 
 region_name_to_var_with_both_renamings(Name0, ResurRenaming, IteRenaming,
         RegVar, !NameToVar, !VarSet, !VarTypes) :-
-    ( map.search(ResurRenaming, Name0, ResurName) ->
-        Name = ResurName
-    ; map.search(IteRenaming, Name0, IteName) ->
-        Name = IteName
+    ( map.search(ResurRenaming, Name0, ResurNameList) ->
+        list.det_last(ResurNameList, Name) 
+    ; map.search(IteRenaming, Name0, IteNameList) ->
+        list.det_last(IteNameList, Name) 
+    ;
+        Name = Name0
+    ),
+    region_name_to_var(Name, RegVar, !NameToVar, !VarSet, !VarTypes).
+
+    % This predicate is the same as the above except that if more than one
+    % renaming exist we will use the first one. This is for use *only* when
+    % renaming the region in a remove instruction added before a program
+    % point.
+    %
+:- pred region_name_to_var_with_both_renamings_before(string::in, renaming::in,
+    renaming::in, prog_var::out, name_to_prog_var::in, name_to_prog_var::out,
+    prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
+
+region_name_to_var_with_both_renamings_before(Name0, ResurRenaming,
+        IteRenaming, RegVar, !NameToVar, !VarSet, !VarTypes) :-
+    ( map.search(ResurRenaming, Name0, ResurNameList) ->
+        Name = list.det_index0(ResurNameList, 0)
+    ; map.search(IteRenaming, Name0, IteNameList) ->
+        Name = list.det_index0(IteNameList, 0)
     ;
         Name = Name0
     ),
@@ -810,8 +841,8 @@
 
 region_name_to_var_with_renaming(Name0, ResurRenaming, RegVar,
         !NameToVar, !VarSet, !VarTypes) :-
-    ( map.search(ResurRenaming, Name0, ResurName) ->
-        Name = ResurName
+    ( map.search(ResurRenaming, Name0, ResurNameList) ->
+        Name = list.det_last(ResurNameList)
     ;
         Name = Name0
     ),
@@ -820,11 +851,11 @@
     % The region name in a region instruction is subjected to renaming due
     % to if-then-else and region resurrection. This predicate turns such an
     % instruction into a call to a suitable region builtin.
-    % XXX Call to generate_simple_call here seems to overkill because we
+    % XXX Call to generate_simple_call here seems to be an overkill because we
     % will recompute nonlocals, instmap delta anyway.
     %
 :- pred region_instruction_to_conj(module_info::in, term.context::in,
-    renaming::in, renaming::in, region_instruction::in,
+    renaming::in, renaming::in, region_instr::in,
     name_to_prog_var::in, name_to_prog_var::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
     hlds_goals::in, hlds_goals::out) is det.
@@ -852,6 +883,40 @@
     ),
     Conjs = Conjs0 ++ [CallGoal].
 
+    % The same as the one right above except that to a region in a remove
+    % instruction we apply the first resurrection renaming.
+    %
+:- pred region_instruction_to_conj_before(module_info::in, term.context::in,
+    renaming::in, renaming::in, region_instr::in,
+    name_to_prog_var::in, name_to_prog_var::out,
+    prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
+    hlds_goals::in, hlds_goals::out) is det.
+
+region_instruction_to_conj_before(ModuleInfo, Context, ResurRenaming,
+        IteRenaming, RegionInstruction, !NameToVar, !VarSet, !VarTypes,
+        Conjs0, Conjs) :-
+    (
+        RegionInstruction = create_region(RegionName),
+        region_name_to_var_with_both_renamings(RegionName, ResurRenaming,
+            IteRenaming, RegionVar, !NameToVar, !VarSet, !VarTypes),
+        generate_simple_call(mercury_region_builtin_module,
+            create_region_pred_name, pf_predicate, only_mode, detism_det,
+            purity_impure, [RegionVar], [], [], ModuleInfo, Context, CallGoal)
+    ;
+        RegionInstruction = remove_region(RegionName),
+        region_name_to_var_with_both_renamings_before(RegionName,
+            ResurRenaming, IteRenaming, RegionVar, !NameToVar, !VarSet,
+            !VarTypes),
+        generate_simple_call(mercury_region_builtin_module,
+            remove_region_pred_name, pf_predicate, only_mode, detism_det,
+            purity_impure, [RegionVar], [], [], ModuleInfo, Context, CallGoal)
+    ;
+        RegionInstruction = rename_region(_, _),
+        unexpected(this_file, "region_instruction_to_conj: " ++
+            "encounter neither create or remove instruction")
+    ),
+    Conjs = Conjs0 ++ [CallGoal].
+
     % A resurrection renaming annotation is in the form Rx = Rx_resur_y,
     % where Rx is the original name of the region, the other is the one
     % the region is renamed to.
@@ -860,7 +925,7 @@
     % if-then-else, if such a renaming exists at the current program point.
     %
 :- pred resur_renaming_annotation_to_assignment(renaming::in,
-    region_instruction::in, name_to_prog_var::in, name_to_prog_var::out,
+    region_instr::in, name_to_prog_var::in, name_to_prog_var::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
     hlds_goals::in, hlds_goals::out) is det.
 
@@ -888,7 +953,7 @@
     % an assignment. No renaming needs to be applied to the
     % if-then-else renaming annotations.
     %
-:- pred ite_renaming_annotation_to_assignment(region_instruction::in,
+:- pred ite_renaming_annotation_to_assignment(region_instr::in,
     name_to_prog_var::in, name_to_prog_var::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
     hlds_goals::in, hlds_goals::out) is det.


More information about the reviews mailing list